feed-the-machine 1.7.9 → 1.7.11
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/bin/convert_claude_skills_to_codex.py +1 -1
- package/bin/playbook_engine/test_integration.py +2 -2
- package/ftm-manifest.json +2 -2
- package/ftm-mind/references/mcp-inventory.md +3 -3
- package/ftm-mind/references/orient-protocol.md +18 -0
- package/ftm-mind/references/protocols/MCP-HEURISTICS.md +1 -1
- package/ftm-upgrade/SKILL.md +5 -5
- package/ftm-upgrade/scripts/check-version.sh +1 -1
- package/ftm-upgrade/scripts/upgrade.sh +1 -1
- package/hooks/ftm-auto-log.sh +49 -0
- package/package.json +1 -1
|
@@ -277,7 +277,7 @@ def rewrite_commands(text: str, skill_names: list[str]) -> str:
|
|
|
277
277
|
|
|
278
278
|
def rewrite_paths(text: str) -> str:
|
|
279
279
|
replacements = [
|
|
280
|
-
("~/
|
|
280
|
+
("~/scratch/sso-plan.md", "$CODEX_HOME/skills/sso-buddy/sso-plan.md"),
|
|
281
281
|
(str(HOME / ".claude" / "skills") + "/", "$CODEX_HOME/skills/"),
|
|
282
282
|
(str(HOME / ".claude") + "/", "$CODEX_HOME/"),
|
|
283
283
|
("$HOME/.claude/skills/", "$CODEX_HOME/skills/"),
|
|
@@ -29,7 +29,7 @@ def env(tmp_path):
|
|
|
29
29
|
}
|
|
30
30
|
}))
|
|
31
31
|
(reg_dir / "jira.defaults.yml").write_text(yaml.dump({
|
|
32
|
-
"create_issue": {"assignee": "
|
|
32
|
+
"create_issue": {"assignee": "user@test.com", "board_id": 70},
|
|
33
33
|
}))
|
|
34
34
|
|
|
35
35
|
traces_dir = tmp_path / "traces"
|
|
@@ -48,7 +48,7 @@ def test_full_flow(env):
|
|
|
48
48
|
|
|
49
49
|
tracer.add_event(TraceEvent(type="user_instruction", content="Do SSO onboarding for Linear"))
|
|
50
50
|
tracer.add_event(TraceEvent(type="tool_call", tool="mcp__mcp-atlassian__jira_create_issue",
|
|
51
|
-
params={"project": "ITWORK2", "summary": "[SSO] Linear", "assignee": "
|
|
51
|
+
params={"project": "ITWORK2", "summary": "[SSO] Linear", "assignee": "user@test.com", "board_id": 70}))
|
|
52
52
|
tracer.add_event(TraceEvent(type="user_manual_action", content="Configured SAML in Okta",
|
|
53
53
|
inferred_step="Configure SAML in IdP", action_binding="playwright", auth_note="Okta admin"))
|
|
54
54
|
tracer.add_event(TraceEvent(type="tool_call", tool="mcp__slack__post_message",
|
package/ftm-manifest.json
CHANGED
|
@@ -3685,7 +3685,7 @@
|
|
|
3685
3685
|
"type": "tool",
|
|
3686
3686
|
"name": "gh",
|
|
3687
3687
|
"required": true,
|
|
3688
|
-
"description": "GitHub CLI for querying releases from kkudumu/
|
|
3688
|
+
"description": "GitHub CLI for querying releases from kkudumu/feed-the-machine"
|
|
3689
3689
|
},
|
|
3690
3690
|
{
|
|
3691
3691
|
"type": "reference",
|
|
@@ -3738,7 +3738,7 @@
|
|
|
3738
3738
|
"action": "report \"Cannot reach GitHub. Check internet connection.\""
|
|
3739
3739
|
},
|
|
3740
3740
|
{
|
|
3741
|
-
"condition": "kkudumu/
|
|
3741
|
+
"condition": "kkudumu/feed-the-machine repo not found",
|
|
3742
3742
|
"action": "report repo not found, suggest verifying access"
|
|
3743
3743
|
},
|
|
3744
3744
|
{
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
| Field | Detail |
|
|
112
112
|
|-------|--------|
|
|
113
113
|
| **Tools** | `chat`, `search`, `read_document` |
|
|
114
|
-
| **When to use** | Searching internal
|
|
114
|
+
| **When to use** | Searching internal company knowledge base, finding internal docs, policies, runbooks, past decisions |
|
|
115
115
|
| **When NOT to use** | External library docs (use context7); real-time web search (use WebSearch tool) |
|
|
116
116
|
| **Approval required** | Auto: all read-only |
|
|
117
117
|
|
|
@@ -161,13 +161,13 @@
|
|
|
161
161
|
| "email", "Gmail", "inbox", "draft", "reply to", "send to" | `gmail` | Communication |
|
|
162
162
|
| "calendar", "meeting", "schedule", "free time", "invite", "block time" | `google-calendar` | Calendar |
|
|
163
163
|
| "how do I use [library]", "API docs", "documentation for X framework" | `context7` | Ext. docs |
|
|
164
|
-
| "find in internal docs", "Glean", "search
|
|
164
|
+
| "find in internal docs", "Glean", "search company", "company policy" | `glean_default` | Internal knowledge |
|
|
165
165
|
| "screenshot", "test the UI", "click button", "E2E", "browser test" | `playwright` | Testing |
|
|
166
166
|
| "find someone's email", "contact info", "company profile", "person lookup" | `lusha` | CRM/people |
|
|
167
167
|
| "Swift docs", "SwiftUI", "UIKit", "Apple framework", "AppKit" | `apple-doc-mcp` | Apple dev |
|
|
168
168
|
| "think through this", "complex analysis", "multi-step reasoning", "trade-offs" | `sequential-thinking` | Reasoning |
|
|
169
169
|
| "debug browser", "network request", "Chrome DevTools", "performance profile" | `chrome-devtools` | Dev tools |
|
|
170
|
-
| "who is oncall", "search internal", "
|
|
170
|
+
| "who is oncall", "search internal", "company runbook" | `glean_default` | Internal ops |
|
|
171
171
|
| "IT admin", "org-wide Jira change", "admin Confluence" | `mcp-atlassian` | Admin ops |
|
|
172
172
|
| "highlight", "saved article", "Readwise", "reading list" | *(Readwise — not configured in current settings)* | — |
|
|
173
173
|
|
|
@@ -152,6 +152,24 @@ Every individual external mutation needs its own approval. "The user approved th
|
|
|
152
152
|
|
|
153
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
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
|
+
|
|
155
173
|
### What auto-proceeds (no approval needed)
|
|
156
174
|
|
|
157
175
|
- local code edits, documentation updates
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
Use the smallest relevant MCP set.
|
|
6
6
|
|
|
7
7
|
- Jira issue key or Atlassian URL → `mcp-atlassian-personal` (default; configured via `ops.mcp_account_rules.personal` in ftm-config.yml)
|
|
8
|
-
- "internal docs", "runbook", "
|
|
8
|
+
- "internal docs", "runbook", "company name", "Glean" → `glean_default`
|
|
9
9
|
- "how do I use X library" → `context7`
|
|
10
10
|
- "calendar", "meeting", "free time" → `google-calendar`
|
|
11
11
|
- "Slack", "channel", "thread", "notify" → `slack`
|
package/ftm-upgrade/SKILL.md
CHANGED
|
@@ -13,7 +13,7 @@ description: Self-upgrade mechanism for ftm skills ecosystem. Checks GitHub Rele
|
|
|
13
13
|
|
|
14
14
|
# ftm-upgrade
|
|
15
15
|
|
|
16
|
-
Self-upgrade mechanism for the ftm skills ecosystem. Fetches the latest release from `kkudumu/
|
|
16
|
+
Self-upgrade mechanism for the ftm skills ecosystem. Fetches the latest release from `kkudumu/feed-the-machine` on GitHub, compares it to the locally installed version, and copies updated skill files in place.
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
@@ -135,7 +135,7 @@ Map `CHECK_FAILED <reason>` codes to user-facing messages:
|
|
|
135
135
|
|---|---|
|
|
136
136
|
| `gh_not_installed` | GitHub CLI is not installed. Install it with: `brew install gh` (macOS) or see https://cli.github.com |
|
|
137
137
|
| `no_internet` | Cannot reach GitHub. Check your internet connection and try again. |
|
|
138
|
-
| `repo_not_found` | Repository `kkudumu/
|
|
138
|
+
| `repo_not_found` | Repository `kkudumu/feed-the-machine` not found. Verify you have access to the repository. |
|
|
139
139
|
| `no_releases_found` | No releases found in the repository yet. Check back later. |
|
|
140
140
|
| any other reason | Version check failed: `<reason>`. Try running manually: `bash ~/.claude/skills/ftm-upgrade/scripts/check-version.sh` |
|
|
141
141
|
|
|
@@ -150,11 +150,11 @@ Map `CHECK_FAILED <reason>` codes to user-facing messages:
|
|
|
150
150
|
|
|
151
151
|
**Cache location**: `~/.cache/ftm-skills/version-check`
|
|
152
152
|
**Version file**: `~/.claude/skills/ftm-version.txt`
|
|
153
|
-
**Repo**: `kkudumu/
|
|
153
|
+
**Repo**: `kkudumu/feed-the-machine`
|
|
154
154
|
|
|
155
155
|
## Requirements
|
|
156
156
|
|
|
157
|
-
- tool: `gh` | required | GitHub CLI for querying releases from kkudumu/
|
|
157
|
+
- tool: `gh` | required | GitHub CLI for querying releases from kkudumu/feed-the-machine
|
|
158
158
|
- reference: `~/.claude/skills/ftm-upgrade/scripts/check-version.sh` | required | version check and cache script
|
|
159
159
|
- reference: `~/.claude/skills/ftm-upgrade/scripts/upgrade.sh` | required | download and install latest release script
|
|
160
160
|
- reference: `~/.claude/skills/ftm-version.txt` | optional | locally installed version number
|
|
@@ -175,7 +175,7 @@ Map `CHECK_FAILED <reason>` codes to user-facing messages:
|
|
|
175
175
|
|
|
176
176
|
- condition: gh not installed | action: report "GitHub CLI not installed" with brew install gh instructions
|
|
177
177
|
- condition: no internet connection | action: report "Cannot reach GitHub. Check internet connection."
|
|
178
|
-
- condition: kkudumu/
|
|
178
|
+
- condition: kkudumu/feed-the-machine repo not found | action: report repo not found, suggest verifying access
|
|
179
179
|
- condition: no releases found | action: report "No releases found yet. Check back later."
|
|
180
180
|
- condition: upgrade.sh exits non-zero | action: report failure output, suggest running script manually
|
|
181
181
|
|
|
@@ -7,7 +7,7 @@ set -uo pipefail
|
|
|
7
7
|
CACHE_DIR="${HOME}/.cache/ftm-brain"
|
|
8
8
|
CACHE_FILE="${CACHE_DIR}/version-check"
|
|
9
9
|
VERSION_FILE="${HOME}/.claude/skills/ftm-version.txt"
|
|
10
|
-
REPO="kkudumu/
|
|
10
|
+
REPO="kkudumu/feed-the-machine"
|
|
11
11
|
|
|
12
12
|
# Ensure cache directory exists
|
|
13
13
|
mkdir -p "${CACHE_DIR}"
|
package/hooks/ftm-auto-log.sh
CHANGED
|
@@ -70,6 +70,55 @@ if echo "$USER_MESSAGE" | grep -qE "(I|i) .* (what|should|next|now)\?"; then
|
|
|
70
70
|
SHOULD_LOG=true
|
|
71
71
|
fi
|
|
72
72
|
|
|
73
|
+
# --- Tool activity check ---
|
|
74
|
+
# If mutating tool calls happened since the last auto-log check,
|
|
75
|
+
# inject a log reminder regardless of what the user's message says.
|
|
76
|
+
# This catches the case where Claude executes work (API calls, scripts, etc.)
|
|
77
|
+
# and the user's next message is just "what else?" or a new task.
|
|
78
|
+
LAST_AUTOLOG_TS="$FTM_STATE/.last-autolog-check"
|
|
79
|
+
EVENTS_LOG="$HOME/.claude/events.log"
|
|
80
|
+
|
|
81
|
+
if [ -f "$EVENTS_LOG" ]; then
|
|
82
|
+
LAST_CHECK=0
|
|
83
|
+
if [ -f "$LAST_AUTOLOG_TS" ]; then
|
|
84
|
+
LAST_CHECK=$(cat "$LAST_AUTOLOG_TS" 2>/dev/null || echo "0")
|
|
85
|
+
fi
|
|
86
|
+
NOW=$(date +%s)
|
|
87
|
+
|
|
88
|
+
# Count mutating tool calls since last check
|
|
89
|
+
MUTATING_CALLS=$(python3 -c "
|
|
90
|
+
import json, sys
|
|
91
|
+
count = 0
|
|
92
|
+
cutoff = $LAST_CHECK
|
|
93
|
+
mutating = {'Write', 'Edit', 'MultiEdit', 'Bash'}
|
|
94
|
+
mutating_prefixes = ('mcp__freshservice', 'mcp__mcp-atlassian', 'mcp__slack__slack_post', 'mcp__gmail__send')
|
|
95
|
+
try:
|
|
96
|
+
with open('$EVENTS_LOG') as f:
|
|
97
|
+
for line in f:
|
|
98
|
+
line = line.strip()
|
|
99
|
+
if not line: continue
|
|
100
|
+
try:
|
|
101
|
+
ev = json.loads(line)
|
|
102
|
+
ts = ev.get('timestamp', 0)
|
|
103
|
+
if isinstance(ts, str):
|
|
104
|
+
from datetime import datetime
|
|
105
|
+
ts = int(datetime.fromisoformat(ts.replace('Z', '+00:00')).timestamp())
|
|
106
|
+
if ts <= cutoff: continue
|
|
107
|
+
tool = ev.get('tool_name', '')
|
|
108
|
+
if tool in mutating or any(tool.startswith(p) for p in mutating_prefixes):
|
|
109
|
+
count += 1
|
|
110
|
+
except: pass
|
|
111
|
+
except: pass
|
|
112
|
+
print(count)
|
|
113
|
+
" 2>/dev/null)
|
|
114
|
+
|
|
115
|
+
echo "$NOW" > "$LAST_AUTOLOG_TS"
|
|
116
|
+
|
|
117
|
+
if [ "$MUTATING_CALLS" -gt 0 ] && [ "$SHOULD_LOG" != "true" ]; then
|
|
118
|
+
SHOULD_LOG=true
|
|
119
|
+
fi
|
|
120
|
+
fi
|
|
121
|
+
|
|
73
122
|
# If action detected, output logging reminder with exact instructions
|
|
74
123
|
TODAY=$(date +%Y-%m-%d)
|
|
75
124
|
DAILY_DIR="$HOME/.claude/ftm-ops/daily"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "feed-the-machine",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.11",
|
|
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",
|