feed-the-machine 1.5.0 → 1.6.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 (224) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +170 -170
  3. package/bin/generate-manifest.mjs +463 -463
  4. package/bin/install.mjs +491 -491
  5. package/docs/HOOKS.md +243 -243
  6. package/docs/INBOX.md +233 -233
  7. package/ftm/SKILL.md +122 -122
  8. package/ftm-audit/SKILL.md +623 -541
  9. package/ftm-audit/references/protocols/PROJECT-PATTERNS.md +91 -91
  10. package/ftm-audit/references/protocols/RUNTIME-WIRING.md +66 -66
  11. package/ftm-audit/references/protocols/WIRING-CONTRACTS.md +135 -135
  12. package/ftm-audit/references/strategies/AUTO-FIX-STRATEGIES.md +69 -69
  13. package/ftm-audit/references/templates/REPORT-FORMAT.md +96 -96
  14. package/ftm-audit/scripts/run-knip.sh +23 -23
  15. package/ftm-audit.yml +2 -2
  16. package/ftm-brainstorm/SKILL.md +498 -498
  17. package/ftm-brainstorm/evals/evals.json +100 -100
  18. package/ftm-brainstorm/evals/promptfoo.yaml +109 -109
  19. package/ftm-brainstorm/references/agent-prompts.md +224 -224
  20. package/ftm-brainstorm/references/plan-template.md +121 -121
  21. package/ftm-brainstorm.yml +2 -2
  22. package/ftm-browse/SKILL.md +454 -454
  23. package/ftm-browse/daemon/browser-manager.ts +206 -206
  24. package/ftm-browse/daemon/bun.lock +30 -30
  25. package/ftm-browse/daemon/cli.ts +347 -347
  26. package/ftm-browse/daemon/commands.ts +410 -410
  27. package/ftm-browse/daemon/main.ts +357 -357
  28. package/ftm-browse/daemon/package.json +17 -17
  29. package/ftm-browse/daemon/server.ts +189 -189
  30. package/ftm-browse/daemon/snapshot.ts +519 -519
  31. package/ftm-browse/daemon/tsconfig.json +22 -22
  32. package/ftm-browse.yml +4 -4
  33. package/ftm-capture/SKILL.md +370 -370
  34. package/ftm-capture.yml +4 -4
  35. package/ftm-codex-gate/SKILL.md +361 -361
  36. package/ftm-codex-gate.yml +2 -2
  37. package/ftm-config/SKILL.md +345 -345
  38. package/ftm-config.default.yml +82 -80
  39. package/ftm-config.yml +2 -2
  40. package/ftm-council/SKILL.md +416 -416
  41. package/ftm-council/references/prompts/CLAUDE-INVESTIGATION.md +60 -60
  42. package/ftm-council/references/prompts/CODEX-INVESTIGATION.md +58 -58
  43. package/ftm-council/references/prompts/GEMINI-INVESTIGATION.md +58 -58
  44. package/ftm-council/references/prompts/REBUTTAL-TEMPLATE.md +57 -57
  45. package/ftm-council/references/protocols/PREREQUISITES.md +47 -47
  46. package/ftm-council/references/protocols/STEP-0-FRAMING.md +46 -46
  47. package/ftm-council.yml +2 -2
  48. package/ftm-dashboard/SKILL.md +163 -163
  49. package/ftm-dashboard.yml +4 -4
  50. package/ftm-debug/SKILL.md +1037 -1037
  51. package/ftm-debug/references/phases/PHASE-0-INTAKE.md +58 -58
  52. package/ftm-debug/references/phases/PHASE-1-TRIAGE.md +46 -46
  53. package/ftm-debug/references/phases/PHASE-2-WAR-ROOM-AGENTS.md +279 -279
  54. package/ftm-debug/references/phases/PHASE-3-TO-6-EXECUTION.md +436 -436
  55. package/ftm-debug/references/protocols/BLACKBOARD.md +86 -86
  56. package/ftm-debug/references/protocols/EDGE-CASES.md +103 -103
  57. package/ftm-debug.yml +2 -2
  58. package/ftm-diagram/SKILL.md +277 -277
  59. package/ftm-diagram.yml +2 -2
  60. package/ftm-executor/SKILL.md +777 -767
  61. package/ftm-executor/references/STYLE-TEMPLATE.md +73 -73
  62. package/ftm-executor/references/phases/PHASE-0-VERIFICATION.md +62 -62
  63. package/ftm-executor/references/phases/PHASE-2-AGENT-ASSEMBLY.md +34 -34
  64. package/ftm-executor/references/phases/PHASE-3-WORKTREES.md +38 -38
  65. package/ftm-executor/references/phases/PHASE-4-5-AUDIT.md +72 -72
  66. package/ftm-executor/references/phases/PHASE-4-DISPATCH.md +66 -66
  67. package/ftm-executor/references/phases/PHASE-5-5-CODEX-GATE.md +73 -73
  68. package/ftm-executor/references/protocols/DOCUMENTATION-BOOTSTRAP.md +36 -36
  69. package/ftm-executor/references/protocols/MODEL-PROFILE.md +59 -44
  70. package/ftm-executor/references/protocols/PROGRESS-TRACKING.md +66 -66
  71. package/ftm-executor/runtime/ftm-runtime.mjs +252 -252
  72. package/ftm-executor/runtime/package.json +8 -8
  73. package/ftm-executor.yml +2 -2
  74. package/ftm-git/SKILL.md +441 -441
  75. package/ftm-git/evals/evals.json +26 -26
  76. package/ftm-git/evals/promptfoo.yaml +75 -75
  77. package/ftm-git/hooks/post-commit-experience.sh +92 -92
  78. package/ftm-git/references/patterns/SECRET-PATTERNS.md +104 -104
  79. package/ftm-git/references/protocols/REMEDIATION.md +139 -139
  80. package/ftm-git/scripts/pre-commit-secrets.sh +110 -110
  81. package/ftm-git.yml +2 -2
  82. package/ftm-inbox/backend/adapters/_retry.py +64 -64
  83. package/ftm-inbox/backend/adapters/base.py +230 -230
  84. package/ftm-inbox/backend/adapters/freshservice.py +104 -104
  85. package/ftm-inbox/backend/adapters/gmail.py +125 -125
  86. package/ftm-inbox/backend/adapters/jira.py +136 -136
  87. package/ftm-inbox/backend/adapters/registry.py +192 -192
  88. package/ftm-inbox/backend/adapters/slack.py +110 -110
  89. package/ftm-inbox/backend/db/connection.py +54 -54
  90. package/ftm-inbox/backend/db/schema.py +78 -78
  91. package/ftm-inbox/backend/executor/__init__.py +7 -7
  92. package/ftm-inbox/backend/executor/engine.py +149 -149
  93. package/ftm-inbox/backend/executor/step_runner.py +98 -98
  94. package/ftm-inbox/backend/main.py +103 -103
  95. package/ftm-inbox/backend/models/__init__.py +1 -1
  96. package/ftm-inbox/backend/models/unified_task.py +36 -36
  97. package/ftm-inbox/backend/planner/__init__.py +6 -6
  98. package/ftm-inbox/backend/planner/generator.py +127 -127
  99. package/ftm-inbox/backend/planner/schema.py +34 -34
  100. package/ftm-inbox/backend/requirements.txt +5 -5
  101. package/ftm-inbox/backend/routes/execute.py +186 -186
  102. package/ftm-inbox/backend/routes/health.py +52 -52
  103. package/ftm-inbox/backend/routes/inbox.py +68 -68
  104. package/ftm-inbox/backend/routes/plan.py +271 -271
  105. package/ftm-inbox/bin/launchagent.mjs +91 -91
  106. package/ftm-inbox/bin/setup.mjs +188 -188
  107. package/ftm-inbox/bin/start.sh +10 -10
  108. package/ftm-inbox/bin/status.sh +17 -17
  109. package/ftm-inbox/bin/stop.sh +8 -8
  110. package/ftm-inbox/config.example.yml +55 -55
  111. package/ftm-inbox/package-lock.json +2898 -2898
  112. package/ftm-inbox/package.json +26 -26
  113. package/ftm-inbox/postcss.config.js +6 -6
  114. package/ftm-inbox/src/app.css +199 -199
  115. package/ftm-inbox/src/app.html +18 -18
  116. package/ftm-inbox/src/lib/api.ts +166 -166
  117. package/ftm-inbox/src/lib/components/ExecutionLog.svelte +81 -81
  118. package/ftm-inbox/src/lib/components/InboxFeed.svelte +143 -143
  119. package/ftm-inbox/src/lib/components/PlanStep.svelte +271 -271
  120. package/ftm-inbox/src/lib/components/PlanView.svelte +206 -206
  121. package/ftm-inbox/src/lib/components/StreamPanel.svelte +99 -99
  122. package/ftm-inbox/src/lib/components/TaskCard.svelte +190 -190
  123. package/ftm-inbox/src/lib/components/ui/EmptyState.svelte +63 -63
  124. package/ftm-inbox/src/lib/components/ui/KawaiiCard.svelte +86 -86
  125. package/ftm-inbox/src/lib/components/ui/PillButton.svelte +106 -106
  126. package/ftm-inbox/src/lib/components/ui/StatusBadge.svelte +67 -67
  127. package/ftm-inbox/src/lib/components/ui/StreamDrawer.svelte +149 -149
  128. package/ftm-inbox/src/lib/components/ui/ThemeToggle.svelte +80 -80
  129. package/ftm-inbox/src/lib/theme.ts +47 -47
  130. package/ftm-inbox/src/routes/+layout.svelte +76 -76
  131. package/ftm-inbox/src/routes/+page.svelte +401 -401
  132. package/ftm-inbox/svelte.config.js +12 -12
  133. package/ftm-inbox/tailwind.config.ts +63 -63
  134. package/ftm-inbox/tsconfig.json +13 -13
  135. package/ftm-inbox/vite.config.ts +6 -6
  136. package/ftm-intent/SKILL.md +241 -241
  137. package/ftm-intent.yml +2 -2
  138. package/ftm-manifest.json +3794 -3794
  139. package/ftm-map/SKILL.md +291 -291
  140. package/ftm-map/scripts/db.py +712 -712
  141. package/ftm-map/scripts/index.py +415 -415
  142. package/ftm-map/scripts/parser.py +224 -224
  143. package/ftm-map/scripts/queries/go-tags.scm +20 -20
  144. package/ftm-map/scripts/queries/javascript-tags.scm +35 -35
  145. package/ftm-map/scripts/queries/python-tags.scm +31 -31
  146. package/ftm-map/scripts/queries/ruby-tags.scm +19 -19
  147. package/ftm-map/scripts/queries/rust-tags.scm +37 -37
  148. package/ftm-map/scripts/queries/typescript-tags.scm +41 -41
  149. package/ftm-map/scripts/query.py +301 -301
  150. package/ftm-map/scripts/ranker.py +377 -377
  151. package/ftm-map/scripts/requirements.txt +5 -5
  152. package/ftm-map/scripts/setup-hooks.sh +27 -27
  153. package/ftm-map/scripts/setup.sh +56 -56
  154. package/ftm-map/scripts/test_db.py +364 -364
  155. package/ftm-map/scripts/test_parser.py +174 -174
  156. package/ftm-map/scripts/test_query.py +183 -183
  157. package/ftm-map/scripts/test_ranker.py +199 -199
  158. package/ftm-map/scripts/views.py +591 -591
  159. package/ftm-map.yml +2 -2
  160. package/ftm-mind/SKILL.md +1943 -1943
  161. package/ftm-mind/evals/promptfoo.yaml +142 -142
  162. package/ftm-mind/references/blackboard-schema.md +328 -328
  163. package/ftm-mind/references/complexity-guide.md +110 -110
  164. package/ftm-mind/references/event-registry.md +319 -319
  165. package/ftm-mind/references/mcp-inventory.md +296 -296
  166. package/ftm-mind/references/protocols/COMPLEXITY-SIZING.md +72 -72
  167. package/ftm-mind/references/protocols/MCP-HEURISTICS.md +32 -32
  168. package/ftm-mind/references/protocols/PLAN-APPROVAL.md +80 -80
  169. package/ftm-mind/references/reflexion-protocol.md +249 -249
  170. package/ftm-mind/references/routing/SCENARIOS.md +22 -22
  171. package/ftm-mind/references/routing-scenarios.md +35 -35
  172. package/ftm-mind.yml +2 -2
  173. package/ftm-pause/SKILL.md +395 -395
  174. package/ftm-pause/references/protocols/SKILL-RESTORE-PROTOCOLS.md +186 -186
  175. package/ftm-pause/references/protocols/VALIDATION.md +80 -80
  176. package/ftm-pause.yml +2 -2
  177. package/ftm-researcher/SKILL.md +275 -275
  178. package/ftm-researcher/evals/agent-diversity.yaml +17 -17
  179. package/ftm-researcher/evals/synthesis-quality.yaml +12 -12
  180. package/ftm-researcher/evals/trigger-accuracy.yaml +39 -39
  181. package/ftm-researcher/references/adaptive-search.md +116 -116
  182. package/ftm-researcher/references/agent-prompts.md +193 -193
  183. package/ftm-researcher/references/council-integration.md +193 -193
  184. package/ftm-researcher/references/output-format.md +203 -203
  185. package/ftm-researcher/references/synthesis-pipeline.md +165 -165
  186. package/ftm-researcher/scripts/score_credibility.py +234 -234
  187. package/ftm-researcher/scripts/validate_research.py +92 -92
  188. package/ftm-researcher.yml +2 -2
  189. package/ftm-resume/SKILL.md +518 -518
  190. package/ftm-resume/references/protocols/VALIDATION.md +172 -172
  191. package/ftm-resume.yml +2 -2
  192. package/ftm-retro/SKILL.md +380 -380
  193. package/ftm-retro/references/protocols/SCORING-RUBRICS.md +89 -89
  194. package/ftm-retro/references/templates/REPORT-FORMAT.md +109 -109
  195. package/ftm-retro.yml +2 -2
  196. package/ftm-routine/SKILL.md +170 -170
  197. package/ftm-routine.yml +4 -4
  198. package/ftm-state/blackboard/capabilities.json +5 -5
  199. package/ftm-state/blackboard/capabilities.schema.json +27 -27
  200. package/ftm-state/blackboard/context.json +23 -23
  201. package/ftm-state/blackboard/experiences/index.json +9 -9
  202. package/ftm-state/blackboard/patterns.json +6 -6
  203. package/ftm-state/schemas/context.schema.json +130 -130
  204. package/ftm-state/schemas/experience-index.schema.json +77 -77
  205. package/ftm-state/schemas/experience.schema.json +78 -78
  206. package/ftm-state/schemas/patterns.schema.json +44 -44
  207. package/ftm-upgrade/SKILL.md +194 -194
  208. package/ftm-upgrade/scripts/check-version.sh +76 -76
  209. package/ftm-upgrade/scripts/upgrade.sh +143 -143
  210. package/ftm-upgrade.yml +2 -2
  211. package/ftm-verify.yml +2 -2
  212. package/ftm.yml +2 -2
  213. package/hooks/ftm-blackboard-enforcer.sh +93 -93
  214. package/hooks/ftm-discovery-reminder.sh +90 -90
  215. package/hooks/ftm-drafts-gate.sh +61 -61
  216. package/hooks/ftm-event-logger.mjs +107 -107
  217. package/hooks/ftm-map-autodetect.sh +79 -79
  218. package/hooks/ftm-pending-sync-check.sh +22 -22
  219. package/hooks/ftm-plan-gate.sh +92 -92
  220. package/hooks/ftm-post-commit-trigger.sh +57 -57
  221. package/hooks/settings-template.json +81 -81
  222. package/install.sh +363 -363
  223. package/package.json +84 -84
  224. package/uninstall.sh +25 -25
@@ -1,143 +1,143 @@
1
- #!/usr/bin/env bash
2
- # upgrade.sh — Download and install latest feed-the-machine release
3
- # Usage: upgrade.sh [--version <tag>]
4
-
5
- set -uo pipefail
6
-
7
- REPO="kkudumu/ftm-brain"
8
- SKILLS_DIR="${HOME}/.claude/skills"
9
- VERSION_FILE="${SKILLS_DIR}/ftm-version.txt"
10
- DOWNLOAD_DIR="/tmp/ftm-upgrade"
11
- CACHE_FILE="${HOME}/.cache/ftm-brain/version-check"
12
-
13
- # ── Helpers ──────────────────────────────────────────────────────────────────
14
-
15
- log() { printf '[ftm-upgrade] %s\n' "$*"; }
16
- die() { printf '[ftm-upgrade] ERROR: %s\n' "$*" >&2; exit 1; }
17
-
18
- # ── Preflight checks ─────────────────────────────────────────────────────────
19
-
20
- if ! command -v gh >/dev/null 2>&1; then
21
- die "GitHub CLI (gh) is not installed. Install it with: brew install gh"
22
- fi
23
-
24
- if ! command -v tar >/dev/null 2>&1; then
25
- die "tar is required but not found."
26
- fi
27
-
28
- # ── Determine target version ─────────────────────────────────────────────────
29
-
30
- TARGET_VERSION=""
31
- while [ $# -gt 0 ]; do
32
- case "$1" in
33
- --version) TARGET_VERSION="$2"; shift 2 ;;
34
- *) die "Unknown argument: $1" ;;
35
- esac
36
- done
37
-
38
- if [ -z "${TARGET_VERSION}" ]; then
39
- log "Fetching latest release tag..."
40
- TARGET_VERSION=$(gh release list -R "${REPO}" --limit 1 2>&1 | awk 'NR==1{print $1}')
41
- if [ -z "${TARGET_VERSION}" ]; then
42
- die "Could not determine latest release. Check GitHub access and repository name."
43
- fi
44
- fi
45
-
46
- log "Target version: ${TARGET_VERSION}"
47
-
48
- # ── Read current version ─────────────────────────────────────────────────────
49
-
50
- if [ -f "${VERSION_FILE}" ]; then
51
- CURRENT_VERSION=$(tr -d '[:space:]' < "${VERSION_FILE}")
52
- else
53
- CURRENT_VERSION="(not installed)"
54
- fi
55
-
56
- log "Current version: ${CURRENT_VERSION}"
57
-
58
- if [ "${CURRENT_VERSION}" = "${TARGET_VERSION}" ]; then
59
- log "Already on the latest version (${TARGET_VERSION}). Nothing to do."
60
- exit 0
61
- fi
62
-
63
- # ── Download ──────────────────────────────────────────────────────────────────
64
-
65
- rm -rf "${DOWNLOAD_DIR}"
66
- mkdir -p "${DOWNLOAD_DIR}"
67
-
68
- log "Downloading release archive for ${TARGET_VERSION}..."
69
-
70
- gh release download "${TARGET_VERSION}" \
71
- -R "${REPO}" \
72
- --archive tar.gz \
73
- -D "${DOWNLOAD_DIR}" 2>&1 || die "Download failed. Check your internet connection and repository access."
74
-
75
- # Find the downloaded archive
76
- ARCHIVE=$(find "${DOWNLOAD_DIR}" -maxdepth 1 -name '*.tar.gz' | head -1)
77
- if [ -z "${ARCHIVE}" ]; then
78
- die "No archive found in ${DOWNLOAD_DIR} after download."
79
- fi
80
-
81
- log "Downloaded: ${ARCHIVE}"
82
-
83
- # ── Extract ───────────────────────────────────────────────────────────────────
84
-
85
- EXTRACT_DIR="${DOWNLOAD_DIR}/extracted"
86
- mkdir -p "${EXTRACT_DIR}"
87
-
88
- log "Extracting archive..."
89
- tar -xzf "${ARCHIVE}" -C "${EXTRACT_DIR}" 2>&1 || die "Extraction failed. Archive may be corrupt."
90
-
91
- # GitHub archives typically extract into a directory named <repo>-<tag>/
92
- REPO_DIR=$(find "${EXTRACT_DIR}" -maxdepth 1 -mindepth 1 -type d | head -1)
93
- if [ -z "${REPO_DIR}" ]; then
94
- die "Could not find extracted repository directory."
95
- fi
96
-
97
- log "Extracted to: ${REPO_DIR}"
98
-
99
- # ── Copy skill files ──────────────────────────────────────────────────────────
100
-
101
- # Look for a skills/ subdirectory in the archive; fall back to root
102
- SOURCE_SKILLS=""
103
- if [ -d "${REPO_DIR}/skills" ]; then
104
- SOURCE_SKILLS="${REPO_DIR}/skills"
105
- elif [ -d "${REPO_DIR}" ]; then
106
- # The repo root might itself contain SKILL.md files and .yml files
107
- SOURCE_SKILLS="${REPO_DIR}"
108
- fi
109
-
110
- if [ -z "${SOURCE_SKILLS}" ]; then
111
- die "No skills directory found in release archive."
112
- fi
113
-
114
- log "Copying skill files from ${SOURCE_SKILLS} to ${SKILLS_DIR}..."
115
-
116
- # Use rsync if available for cleaner copy, else cp
117
- if command -v rsync >/dev/null 2>&1; then
118
- rsync -av --exclude='.git' "${SOURCE_SKILLS}/" "${SKILLS_DIR}/" 2>&1
119
- else
120
- cp -R "${SOURCE_SKILLS}/." "${SKILLS_DIR}/" 2>&1
121
- fi
122
-
123
- # ── Update version file ───────────────────────────────────────────────────────
124
-
125
- printf '%s\n' "${TARGET_VERSION}" > "${VERSION_FILE}"
126
-
127
- # Invalidate version cache so next check-version.sh run is fresh
128
- rm -f "${CACHE_FILE}"
129
-
130
- # ── Summary ───────────────────────────────────────────────────────────────────
131
-
132
- log ""
133
- log "Upgrade complete."
134
- log " ${CURRENT_VERSION} → ${TARGET_VERSION}"
135
- log " Changelog: https://github.com/${REPO}/releases/tag/${TARGET_VERSION}"
136
- log ""
137
- log "Installed files updated in: ${SKILLS_DIR}"
138
-
139
- # ── Cleanup ───────────────────────────────────────────────────────────────────
140
-
141
- rm -rf "${DOWNLOAD_DIR}"
142
-
143
- exit 0
1
+ #!/usr/bin/env bash
2
+ # upgrade.sh — Download and install latest feed-the-machine release
3
+ # Usage: upgrade.sh [--version <tag>]
4
+
5
+ set -uo pipefail
6
+
7
+ REPO="kkudumu/ftm-brain"
8
+ SKILLS_DIR="${HOME}/.claude/skills"
9
+ VERSION_FILE="${SKILLS_DIR}/ftm-version.txt"
10
+ DOWNLOAD_DIR="/tmp/ftm-upgrade"
11
+ CACHE_FILE="${HOME}/.cache/ftm-brain/version-check"
12
+
13
+ # ── Helpers ──────────────────────────────────────────────────────────────────
14
+
15
+ log() { printf '[ftm-upgrade] %s\n' "$*"; }
16
+ die() { printf '[ftm-upgrade] ERROR: %s\n' "$*" >&2; exit 1; }
17
+
18
+ # ── Preflight checks ─────────────────────────────────────────────────────────
19
+
20
+ if ! command -v gh >/dev/null 2>&1; then
21
+ die "GitHub CLI (gh) is not installed. Install it with: brew install gh"
22
+ fi
23
+
24
+ if ! command -v tar >/dev/null 2>&1; then
25
+ die "tar is required but not found."
26
+ fi
27
+
28
+ # ── Determine target version ─────────────────────────────────────────────────
29
+
30
+ TARGET_VERSION=""
31
+ while [ $# -gt 0 ]; do
32
+ case "$1" in
33
+ --version) TARGET_VERSION="$2"; shift 2 ;;
34
+ *) die "Unknown argument: $1" ;;
35
+ esac
36
+ done
37
+
38
+ if [ -z "${TARGET_VERSION}" ]; then
39
+ log "Fetching latest release tag..."
40
+ TARGET_VERSION=$(gh release list -R "${REPO}" --limit 1 2>&1 | awk 'NR==1{print $1}')
41
+ if [ -z "${TARGET_VERSION}" ]; then
42
+ die "Could not determine latest release. Check GitHub access and repository name."
43
+ fi
44
+ fi
45
+
46
+ log "Target version: ${TARGET_VERSION}"
47
+
48
+ # ── Read current version ─────────────────────────────────────────────────────
49
+
50
+ if [ -f "${VERSION_FILE}" ]; then
51
+ CURRENT_VERSION=$(tr -d '[:space:]' < "${VERSION_FILE}")
52
+ else
53
+ CURRENT_VERSION="(not installed)"
54
+ fi
55
+
56
+ log "Current version: ${CURRENT_VERSION}"
57
+
58
+ if [ "${CURRENT_VERSION}" = "${TARGET_VERSION}" ]; then
59
+ log "Already on the latest version (${TARGET_VERSION}). Nothing to do."
60
+ exit 0
61
+ fi
62
+
63
+ # ── Download ──────────────────────────────────────────────────────────────────
64
+
65
+ rm -rf "${DOWNLOAD_DIR}"
66
+ mkdir -p "${DOWNLOAD_DIR}"
67
+
68
+ log "Downloading release archive for ${TARGET_VERSION}..."
69
+
70
+ gh release download "${TARGET_VERSION}" \
71
+ -R "${REPO}" \
72
+ --archive tar.gz \
73
+ -D "${DOWNLOAD_DIR}" 2>&1 || die "Download failed. Check your internet connection and repository access."
74
+
75
+ # Find the downloaded archive
76
+ ARCHIVE=$(find "${DOWNLOAD_DIR}" -maxdepth 1 -name '*.tar.gz' | head -1)
77
+ if [ -z "${ARCHIVE}" ]; then
78
+ die "No archive found in ${DOWNLOAD_DIR} after download."
79
+ fi
80
+
81
+ log "Downloaded: ${ARCHIVE}"
82
+
83
+ # ── Extract ───────────────────────────────────────────────────────────────────
84
+
85
+ EXTRACT_DIR="${DOWNLOAD_DIR}/extracted"
86
+ mkdir -p "${EXTRACT_DIR}"
87
+
88
+ log "Extracting archive..."
89
+ tar -xzf "${ARCHIVE}" -C "${EXTRACT_DIR}" 2>&1 || die "Extraction failed. Archive may be corrupt."
90
+
91
+ # GitHub archives typically extract into a directory named <repo>-<tag>/
92
+ REPO_DIR=$(find "${EXTRACT_DIR}" -maxdepth 1 -mindepth 1 -type d | head -1)
93
+ if [ -z "${REPO_DIR}" ]; then
94
+ die "Could not find extracted repository directory."
95
+ fi
96
+
97
+ log "Extracted to: ${REPO_DIR}"
98
+
99
+ # ── Copy skill files ──────────────────────────────────────────────────────────
100
+
101
+ # Look for a skills/ subdirectory in the archive; fall back to root
102
+ SOURCE_SKILLS=""
103
+ if [ -d "${REPO_DIR}/skills" ]; then
104
+ SOURCE_SKILLS="${REPO_DIR}/skills"
105
+ elif [ -d "${REPO_DIR}" ]; then
106
+ # The repo root might itself contain SKILL.md files and .yml files
107
+ SOURCE_SKILLS="${REPO_DIR}"
108
+ fi
109
+
110
+ if [ -z "${SOURCE_SKILLS}" ]; then
111
+ die "No skills directory found in release archive."
112
+ fi
113
+
114
+ log "Copying skill files from ${SOURCE_SKILLS} to ${SKILLS_DIR}..."
115
+
116
+ # Use rsync if available for cleaner copy, else cp
117
+ if command -v rsync >/dev/null 2>&1; then
118
+ rsync -av --exclude='.git' "${SOURCE_SKILLS}/" "${SKILLS_DIR}/" 2>&1
119
+ else
120
+ cp -R "${SOURCE_SKILLS}/." "${SKILLS_DIR}/" 2>&1
121
+ fi
122
+
123
+ # ── Update version file ───────────────────────────────────────────────────────
124
+
125
+ printf '%s\n' "${TARGET_VERSION}" > "${VERSION_FILE}"
126
+
127
+ # Invalidate version cache so next check-version.sh run is fresh
128
+ rm -f "${CACHE_FILE}"
129
+
130
+ # ── Summary ───────────────────────────────────────────────────────────────────
131
+
132
+ log ""
133
+ log "Upgrade complete."
134
+ log " ${CURRENT_VERSION} → ${TARGET_VERSION}"
135
+ log " Changelog: https://github.com/${REPO}/releases/tag/${TARGET_VERSION}"
136
+ log ""
137
+ log "Installed files updated in: ${SKILLS_DIR}"
138
+
139
+ # ── Cleanup ───────────────────────────────────────────────────────────────────
140
+
141
+ rm -rf "${DOWNLOAD_DIR}"
142
+
143
+ exit 0
package/ftm-upgrade.yml CHANGED
@@ -1,2 +1,2 @@
1
- name: ftm-upgrade
2
- description: Self-upgrade mechanism for ftm skills ecosystem. Checks GitHub Releases for new versions, caches results for 60min, shows changelog, and copies updated files. Use when user says "upgrade", "update skills", "new version", "check for updates", "ftm upgrade".
1
+ name: ftm-upgrade
2
+ description: Self-upgrade mechanism for ftm skills ecosystem. Checks GitHub Releases for new versions, caches results for 60min, shows changelog, and copies updated files. Use when user says "upgrade", "update skills", "new version", "check for updates", "ftm upgrade".
package/ftm-verify.yml CHANGED
@@ -1,2 +1,2 @@
1
- name: ftm-verify
2
- description: Comprehensive post-execution verification and auto-remediation engine using dual-model adversarial analysis. Replaces ftm-retro. After ftm-executor completes a plan, this skill runs two independent verification passes in parallel — Codex (OpenAI) and Gemini (Google) — each reading the entire codebase to check plan fulfillment, documentation fidelity, build health, test quality, and wiring integrity. Falls back to Claude subagents if either CLI is unavailable. Reconciles findings from both models, auto-remediates with parallel fix agents, and reports what was found, disagreed on, and fixed. Use when user says "verify", "is the plan done", "check everything", "verify plan", "ftm-verify", "did we miss anything", "is it complete", "validate the build", "check the plan", "verify execution", "post-execution check", or after any ftm-executor run completes. Also triggers on "retro", "retrospective", "how did that go", "execution review" since this skill supersedes ftm-retro. Even if the user just says "are we good?" after a plan execution — this is the skill.
1
+ name: ftm-verify
2
+ description: Comprehensive post-execution verification and auto-remediation engine using dual-model adversarial analysis. Replaces ftm-retro. After ftm-executor completes a plan, this skill runs two independent verification passes in parallel — Codex (OpenAI) and Gemini (Google) — each reading the entire codebase to check plan fulfillment, documentation fidelity, build health, test quality, and wiring integrity. Falls back to Claude subagents if either CLI is unavailable. Reconciles findings from both models, auto-remediates with parallel fix agents, and reports what was found, disagreed on, and fixed. Use when user says "verify", "is the plan done", "check everything", "verify plan", "ftm-verify", "did we miss anything", "is it complete", "validate the build", "check the plan", "verify execution", "post-execution check", or after any ftm-executor run completes. Also triggers on "retro", "retrospective", "how did that go", "execution review" since this skill supersedes ftm-retro. Even if the user just says "are we good?" after a plan execution — this is the skill.
package/ftm.yml CHANGED
@@ -1,2 +1,2 @@
1
- name: ftm
2
- description: Universal entry point for all ftm skills. Routes freeform text to the right ftm skill automatically. Use when user says "/ftm" followed by anything. ftm-mind is the default cognitive entry point for all unclassified input (OODA reasoning). Explicit prefixes route directly: brainstorm, execute, debug, audit, council, intent, diagram, codex-gate, pause, resume, browse, upgrade, retro, config, mind. Also use when user is unsure which ftm skill they need.
1
+ name: ftm
2
+ description: Universal entry point for all ftm skills. Routes freeform text to the right ftm skill automatically. Use when user says "/ftm" followed by anything. ftm-mind is the default cognitive entry point for all unclassified input (OODA reasoning). Explicit prefixes route directly: brainstorm, execute, debug, audit, council, intent, diagram, codex-gate, pause, resume, browse, upgrade, retro, config, mind. Also use when user is unsure which ftm skill they need.
@@ -1,93 +1,93 @@
1
- #!/usr/bin/env bash
2
- # ftm-blackboard-enforcer.sh
3
- # Stop hook that nudges Claude to record an experience if meaningful work
4
- # was done but no blackboard entry was written.
5
- #
6
- # Uses additionalContext (not "decision: block") so Claude can still act on
7
- # the reminder. A blocking stop creates a deadlock — Claude can't write files
8
- # after the user ends the conversation.
9
- #
10
- # "Meaningful work" = 3+ edits tracked by the edit counter,
11
- # or ftm skills were invoked (checked via context.json).
12
- #
13
- # Hook: Stop
14
-
15
- set -euo pipefail
16
-
17
- # shellcheck disable=SC2034
18
- INPUT=$(cat)
19
-
20
- STATE_DIR="$HOME/.claude/ftm-state"
21
- BB_DIR="$STATE_DIR/blackboard"
22
- EDIT_COUNTER="$STATE_DIR/.edit-count"
23
- CONTEXT_FILE="$BB_DIR/context.json"
24
- EXPERIENCES_DIR="$BB_DIR/experiences"
25
-
26
- # Check 1: Were there meaningful edits this session?
27
- # Edit counter contains just a number now (no session ID).
28
- # If the counter file is recent (< 4 hours) and >= 3, count as meaningful.
29
- HAD_EDITS=false
30
- if [[ -f "$EDIT_COUNTER" ]]; then
31
- COUNTER_AGE=$(( $(date +%s) - $(stat -c %Y "$EDIT_COUNTER" 2>/dev/null || stat -f %m "$EDIT_COUNTER" 2>/dev/null || echo "0") ))
32
- if [[ "$COUNTER_AGE" -lt 14400 ]]; then
33
- STORED_COUNT=$(cat "$EDIT_COUNTER" 2>/dev/null || echo "0")
34
- if [[ "$STORED_COUNT" -ge 3 ]]; then
35
- HAD_EDITS=true
36
- fi
37
- fi
38
- fi
39
-
40
- # Check 2: Were ftm skills invoked this session?
41
- HAD_SKILLS=false
42
- if [[ -f "$CONTEXT_FILE" ]]; then
43
- SKILLS_COUNT=$(jq -r '.session_metadata.skills_invoked | length' "$CONTEXT_FILE" 2>/dev/null || echo "0")
44
- if [[ "$SKILLS_COUNT" -gt 0 ]]; then
45
- HAD_SKILLS=true
46
- fi
47
- fi
48
-
49
- # If no meaningful work detected, allow stop quietly
50
- if [[ "$HAD_EDITS" == "false" && "$HAD_SKILLS" == "false" ]]; then
51
- # Clean up session markers
52
- rm -f "$EDIT_COUNTER" "$STATE_DIR/.plan-presented" 2>/dev/null
53
- exit 0
54
- fi
55
-
56
- # Check 3: Was an experience recorded today?
57
- TODAY=$(date +%Y-%m-%d)
58
- HAS_EXPERIENCE=false
59
-
60
- if [[ -d "$EXPERIENCES_DIR" ]]; then
61
- TODAY_EXPERIENCE=$(find "$EXPERIENCES_DIR" -name "${TODAY}*" -type f 2>/dev/null | head -1)
62
- if [[ -n "$TODAY_EXPERIENCE" ]]; then
63
- HAS_EXPERIENCE=true
64
- fi
65
- fi
66
-
67
- # Also check if context.json was updated today (recent_decisions not empty)
68
- if [[ -f "$CONTEXT_FILE" ]]; then
69
- DECISIONS_COUNT=$(jq -r '.recent_decisions | length' "$CONTEXT_FILE" 2>/dev/null || echo "0")
70
- LAST_UPDATED=$(jq -r '.session_metadata.last_updated // ""' "$CONTEXT_FILE" 2>/dev/null || echo "")
71
- if [[ "$DECISIONS_COUNT" -gt 0 && -n "$LAST_UPDATED" ]]; then
72
- if [[ "$LAST_UPDATED" == *"$TODAY"* ]]; then
73
- HAS_EXPERIENCE=true
74
- fi
75
- fi
76
- fi
77
-
78
- if [[ "$HAS_EXPERIENCE" == "true" ]]; then
79
- # Blackboard was written, clean up and allow stop
80
- rm -f "$EDIT_COUNTER" "$STATE_DIR/.plan-presented" 2>/dev/null
81
- exit 0
82
- fi
83
-
84
- # Work was done but no blackboard write — nudge (don't block)
85
- cat <<'JSON'
86
- {
87
- "stopReason": "[ftm-blackboard-enforcer] You did meaningful work this session but did not record an experience to the blackboard. Before finishing, please: (1) Update ~/.claude/ftm-state/blackboard/context.json with current_task status and recent_decisions. (2) Write an experience file to ~/.claude/ftm-state/blackboard/experiences/ with task_type, tags, outcome, and lessons. (3) Update ~/.claude/ftm-state/blackboard/experiences/index.json with the new entry. This is how ftm learns — skipping it means the next session starts from zero."
88
- }
89
- JSON
90
-
91
- # Clean up session markers regardless — don't let stale state carry over
92
- rm -f "$EDIT_COUNTER" "$STATE_DIR/.plan-presented" 2>/dev/null
93
- exit 0
1
+ #!/usr/bin/env bash
2
+ # ftm-blackboard-enforcer.sh
3
+ # Stop hook that nudges Claude to record an experience if meaningful work
4
+ # was done but no blackboard entry was written.
5
+ #
6
+ # Uses additionalContext (not "decision: block") so Claude can still act on
7
+ # the reminder. A blocking stop creates a deadlock — Claude can't write files
8
+ # after the user ends the conversation.
9
+ #
10
+ # "Meaningful work" = 3+ edits tracked by the edit counter,
11
+ # or ftm skills were invoked (checked via context.json).
12
+ #
13
+ # Hook: Stop
14
+
15
+ set -euo pipefail
16
+
17
+ # shellcheck disable=SC2034
18
+ INPUT=$(cat)
19
+
20
+ STATE_DIR="$HOME/.claude/ftm-state"
21
+ BB_DIR="$STATE_DIR/blackboard"
22
+ EDIT_COUNTER="$STATE_DIR/.edit-count"
23
+ CONTEXT_FILE="$BB_DIR/context.json"
24
+ EXPERIENCES_DIR="$BB_DIR/experiences"
25
+
26
+ # Check 1: Were there meaningful edits this session?
27
+ # Edit counter contains just a number now (no session ID).
28
+ # If the counter file is recent (< 4 hours) and >= 3, count as meaningful.
29
+ HAD_EDITS=false
30
+ if [[ -f "$EDIT_COUNTER" ]]; then
31
+ COUNTER_AGE=$(( $(date +%s) - $(stat -c %Y "$EDIT_COUNTER" 2>/dev/null || stat -f %m "$EDIT_COUNTER" 2>/dev/null || echo "0") ))
32
+ if [[ "$COUNTER_AGE" -lt 14400 ]]; then
33
+ STORED_COUNT=$(cat "$EDIT_COUNTER" 2>/dev/null || echo "0")
34
+ if [[ "$STORED_COUNT" -ge 3 ]]; then
35
+ HAD_EDITS=true
36
+ fi
37
+ fi
38
+ fi
39
+
40
+ # Check 2: Were ftm skills invoked this session?
41
+ HAD_SKILLS=false
42
+ if [[ -f "$CONTEXT_FILE" ]]; then
43
+ SKILLS_COUNT=$(jq -r '.session_metadata.skills_invoked | length' "$CONTEXT_FILE" 2>/dev/null || echo "0")
44
+ if [[ "$SKILLS_COUNT" -gt 0 ]]; then
45
+ HAD_SKILLS=true
46
+ fi
47
+ fi
48
+
49
+ # If no meaningful work detected, allow stop quietly
50
+ if [[ "$HAD_EDITS" == "false" && "$HAD_SKILLS" == "false" ]]; then
51
+ # Clean up session markers
52
+ rm -f "$EDIT_COUNTER" "$STATE_DIR/.plan-presented" 2>/dev/null
53
+ exit 0
54
+ fi
55
+
56
+ # Check 3: Was an experience recorded today?
57
+ TODAY=$(date +%Y-%m-%d)
58
+ HAS_EXPERIENCE=false
59
+
60
+ if [[ -d "$EXPERIENCES_DIR" ]]; then
61
+ TODAY_EXPERIENCE=$(find "$EXPERIENCES_DIR" -name "${TODAY}*" -type f 2>/dev/null | head -1)
62
+ if [[ -n "$TODAY_EXPERIENCE" ]]; then
63
+ HAS_EXPERIENCE=true
64
+ fi
65
+ fi
66
+
67
+ # Also check if context.json was updated today (recent_decisions not empty)
68
+ if [[ -f "$CONTEXT_FILE" ]]; then
69
+ DECISIONS_COUNT=$(jq -r '.recent_decisions | length' "$CONTEXT_FILE" 2>/dev/null || echo "0")
70
+ LAST_UPDATED=$(jq -r '.session_metadata.last_updated // ""' "$CONTEXT_FILE" 2>/dev/null || echo "")
71
+ if [[ "$DECISIONS_COUNT" -gt 0 && -n "$LAST_UPDATED" ]]; then
72
+ if [[ "$LAST_UPDATED" == *"$TODAY"* ]]; then
73
+ HAS_EXPERIENCE=true
74
+ fi
75
+ fi
76
+ fi
77
+
78
+ if [[ "$HAS_EXPERIENCE" == "true" ]]; then
79
+ # Blackboard was written, clean up and allow stop
80
+ rm -f "$EDIT_COUNTER" "$STATE_DIR/.plan-presented" 2>/dev/null
81
+ exit 0
82
+ fi
83
+
84
+ # Work was done but no blackboard write — nudge (don't block)
85
+ cat <<'JSON'
86
+ {
87
+ "stopReason": "[ftm-blackboard-enforcer] You did meaningful work this session but did not record an experience to the blackboard. Before finishing, please: (1) Update ~/.claude/ftm-state/blackboard/context.json with current_task status and recent_decisions. (2) Write an experience file to ~/.claude/ftm-state/blackboard/experiences/ with task_type, tags, outcome, and lessons. (3) Update ~/.claude/ftm-state/blackboard/experiences/index.json with the new entry. This is how ftm learns — skipping it means the next session starts from zero."
88
+ }
89
+ JSON
90
+
91
+ # Clean up session markers regardless — don't let stale state carry over
92
+ rm -f "$EDIT_COUNTER" "$STATE_DIR/.plan-presented" 2>/dev/null
93
+ exit 0