feed-the-machine 1.7.8 → 1.7.10
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/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 +64 -18
- package/hooks/ftm-session-end.sh +37 -31
- 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
|
|
|
@@ -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
|
@@ -18,22 +18,9 @@
|
|
|
18
18
|
FTM_STATE="$HOME/.claude/ftm-state"
|
|
19
19
|
CONTEXT_JSON="$FTM_STATE/blackboard/context.json"
|
|
20
20
|
|
|
21
|
-
#
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
try:
|
|
25
|
-
with open('$CONTEXT_JSON') as f:
|
|
26
|
-
d = json.load(f)
|
|
27
|
-
task = d.get('current_task', {})
|
|
28
|
-
status = task.get('status', '')
|
|
29
|
-
print('1' if status not in ('', 'completed', 'none') else '0')
|
|
30
|
-
except Exception:
|
|
31
|
-
print('0')
|
|
32
|
-
" 2>/dev/null)
|
|
33
|
-
|
|
34
|
-
if [ "$FTM_ACTIVE" != "1" ]; then
|
|
35
|
-
exit 0 # Not in active ftm session, skip
|
|
36
|
-
fi
|
|
21
|
+
# NOTE: Session gate removed in v1.7.9. Daily logging should happen for ALL work,
|
|
22
|
+
# not just formal ftm sessions. Most productive work happens outside /ftm invocations
|
|
23
|
+
# and was going untracked because context.json status was "none" or "completed".
|
|
37
24
|
|
|
38
25
|
# Read payload from stdin (JSON) — extract prompt for action pattern matching
|
|
39
26
|
STDIN_DATA=$(cat)
|
|
@@ -83,10 +70,69 @@ if echo "$USER_MESSAGE" | grep -qE "(I|i) .* (what|should|next|now)\?"; then
|
|
|
83
70
|
SHOULD_LOG=true
|
|
84
71
|
fi
|
|
85
72
|
|
|
86
|
-
#
|
|
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
|
+
|
|
122
|
+
# If action detected, output logging reminder with exact instructions
|
|
123
|
+
TODAY=$(date +%Y-%m-%d)
|
|
124
|
+
DAILY_DIR="$HOME/.claude/ftm-ops/daily"
|
|
125
|
+
DAILY_FILE="$DAILY_DIR/$TODAY.md"
|
|
126
|
+
|
|
87
127
|
if [ "$SHOULD_LOG" = true ]; then
|
|
88
128
|
echo ""
|
|
89
|
-
echo "[Auto-log] Detected progress update.
|
|
129
|
+
echo "[Auto-log] Detected progress update. Append to daily log NOW:"
|
|
130
|
+
echo " File: $DAILY_FILE"
|
|
131
|
+
if [ ! -f "$DAILY_FILE" ]; then
|
|
132
|
+
echo " File doesn't exist yet — create it with header: # Daily Log — $TODAY"
|
|
133
|
+
fi
|
|
134
|
+
echo " Format: - HH:MM — [what was done] (ticket/PR/system if applicable)"
|
|
135
|
+
echo " Do this silently — don't announce it to the user."
|
|
90
136
|
echo ""
|
|
91
137
|
fi
|
|
92
138
|
|
package/hooks/ftm-session-end.sh
CHANGED
|
@@ -1,52 +1,58 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# ftm-session-end.sh
|
|
3
|
-
# Hook: Deactivate ftm session tracking when conversation ends
|
|
4
|
-
# Trigger:
|
|
3
|
+
# Hook: Deactivate ftm session tracking and ensure daily log exists when conversation ends
|
|
4
|
+
# Trigger: Stop
|
|
5
5
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
6
|
+
# Always runs — not gated on ftm session state. Every session that ends should:
|
|
7
|
+
# 1. Mark context.json as completed (if active)
|
|
8
|
+
# 2. Ensure today's daily log file exists (create if missing)
|
|
9
|
+
# 3. Remind Claude to append a session summary before exiting
|
|
9
10
|
|
|
10
11
|
FTM_STATE="$HOME/.claude/ftm-state"
|
|
11
12
|
CONTEXT_JSON="$FTM_STATE/blackboard/context.json"
|
|
13
|
+
TODAY=$(date +%Y-%m-%d)
|
|
14
|
+
DAILY_DIR="$HOME/.claude/ftm-ops/daily"
|
|
15
|
+
DAILY_FILE="$DAILY_DIR/$TODAY.md"
|
|
12
16
|
|
|
13
|
-
#
|
|
14
|
-
IS_ACTIVE=$(python3 -c "
|
|
15
|
-
import json, sys
|
|
16
|
-
try:
|
|
17
|
-
with open('$CONTEXT_JSON') as f:
|
|
18
|
-
d = json.load(f)
|
|
19
|
-
task = d.get('current_task', {})
|
|
20
|
-
status = task.get('status', '')
|
|
21
|
-
print('1' if status not in ('', 'completed', 'none') else '0')
|
|
22
|
-
except Exception:
|
|
23
|
-
print('0')
|
|
24
|
-
" 2>/dev/null)
|
|
25
|
-
|
|
26
|
-
if [ "$IS_ACTIVE" != "1" ]; then
|
|
27
|
-
exit 0
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
# Mark session as completed in context.json
|
|
17
|
+
# Mark session as completed in context.json (if it has an active task)
|
|
31
18
|
python3 -c "
|
|
32
|
-
import json, sys
|
|
19
|
+
import json, sys, os
|
|
33
20
|
from datetime import datetime
|
|
34
21
|
|
|
22
|
+
ctx_path = '$CONTEXT_JSON'
|
|
23
|
+
if not os.path.exists(ctx_path):
|
|
24
|
+
sys.exit(0)
|
|
25
|
+
|
|
35
26
|
try:
|
|
36
|
-
with open(
|
|
27
|
+
with open(ctx_path) as f:
|
|
37
28
|
d = json.load(f)
|
|
38
29
|
|
|
39
30
|
if 'current_task' in d and isinstance(d['current_task'], dict):
|
|
40
|
-
d['current_task']
|
|
31
|
+
status = d['current_task'].get('status', '')
|
|
32
|
+
if status not in ('', 'completed', 'none'):
|
|
33
|
+
d['current_task']['status'] = 'completed'
|
|
41
34
|
|
|
42
35
|
if 'session_metadata' in d and isinstance(d['session_metadata'], dict):
|
|
43
36
|
d['session_metadata']['last_updated'] = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
|
|
44
37
|
|
|
45
|
-
with open(
|
|
38
|
+
with open(ctx_path, 'w') as f:
|
|
46
39
|
json.dump(d, f, indent=2)
|
|
47
|
-
except Exception
|
|
48
|
-
|
|
49
|
-
sys.exit(1)
|
|
40
|
+
except Exception:
|
|
41
|
+
pass
|
|
50
42
|
" 2>/dev/null
|
|
51
43
|
|
|
52
|
-
|
|
44
|
+
# Ensure daily log directory and file exist
|
|
45
|
+
mkdir -p "$DAILY_DIR"
|
|
46
|
+
if [ ! -f "$DAILY_FILE" ]; then
|
|
47
|
+
echo "# Daily Log — $TODAY" > "$DAILY_FILE"
|
|
48
|
+
echo "" >> "$DAILY_FILE"
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# Remind Claude to write session summary to daily log
|
|
52
|
+
echo ""
|
|
53
|
+
echo "[Session ending] Before you finish, append a summary of this session to the daily log:"
|
|
54
|
+
echo " File: $DAILY_FILE"
|
|
55
|
+
echo " Format: ## Session — HH:MM"
|
|
56
|
+
echo " Then bullet points of what was accomplished, decisions made, and next steps."
|
|
57
|
+
echo " Do this silently — just write the file."
|
|
58
|
+
echo ""
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "feed-the-machine",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.10",
|
|
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",
|