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.
- package/LICENSE +21 -21
- package/README.md +170 -170
- package/bin/generate-manifest.mjs +463 -463
- package/bin/install.mjs +491 -491
- package/docs/HOOKS.md +243 -243
- package/docs/INBOX.md +233 -233
- package/ftm/SKILL.md +122 -122
- package/ftm-audit/SKILL.md +623 -541
- package/ftm-audit/references/protocols/PROJECT-PATTERNS.md +91 -91
- package/ftm-audit/references/protocols/RUNTIME-WIRING.md +66 -66
- package/ftm-audit/references/protocols/WIRING-CONTRACTS.md +135 -135
- package/ftm-audit/references/strategies/AUTO-FIX-STRATEGIES.md +69 -69
- package/ftm-audit/references/templates/REPORT-FORMAT.md +96 -96
- package/ftm-audit/scripts/run-knip.sh +23 -23
- package/ftm-audit.yml +2 -2
- package/ftm-brainstorm/SKILL.md +498 -498
- package/ftm-brainstorm/evals/evals.json +100 -100
- package/ftm-brainstorm/evals/promptfoo.yaml +109 -109
- package/ftm-brainstorm/references/agent-prompts.md +224 -224
- package/ftm-brainstorm/references/plan-template.md +121 -121
- package/ftm-brainstorm.yml +2 -2
- package/ftm-browse/SKILL.md +454 -454
- package/ftm-browse/daemon/browser-manager.ts +206 -206
- package/ftm-browse/daemon/bun.lock +30 -30
- package/ftm-browse/daemon/cli.ts +347 -347
- package/ftm-browse/daemon/commands.ts +410 -410
- package/ftm-browse/daemon/main.ts +357 -357
- package/ftm-browse/daemon/package.json +17 -17
- package/ftm-browse/daemon/server.ts +189 -189
- package/ftm-browse/daemon/snapshot.ts +519 -519
- package/ftm-browse/daemon/tsconfig.json +22 -22
- package/ftm-browse.yml +4 -4
- package/ftm-capture/SKILL.md +370 -370
- package/ftm-capture.yml +4 -4
- package/ftm-codex-gate/SKILL.md +361 -361
- package/ftm-codex-gate.yml +2 -2
- package/ftm-config/SKILL.md +345 -345
- package/ftm-config.default.yml +82 -80
- package/ftm-config.yml +2 -2
- package/ftm-council/SKILL.md +416 -416
- package/ftm-council/references/prompts/CLAUDE-INVESTIGATION.md +60 -60
- package/ftm-council/references/prompts/CODEX-INVESTIGATION.md +58 -58
- package/ftm-council/references/prompts/GEMINI-INVESTIGATION.md +58 -58
- package/ftm-council/references/prompts/REBUTTAL-TEMPLATE.md +57 -57
- package/ftm-council/references/protocols/PREREQUISITES.md +47 -47
- package/ftm-council/references/protocols/STEP-0-FRAMING.md +46 -46
- package/ftm-council.yml +2 -2
- package/ftm-dashboard/SKILL.md +163 -163
- package/ftm-dashboard.yml +4 -4
- package/ftm-debug/SKILL.md +1037 -1037
- package/ftm-debug/references/phases/PHASE-0-INTAKE.md +58 -58
- package/ftm-debug/references/phases/PHASE-1-TRIAGE.md +46 -46
- package/ftm-debug/references/phases/PHASE-2-WAR-ROOM-AGENTS.md +279 -279
- package/ftm-debug/references/phases/PHASE-3-TO-6-EXECUTION.md +436 -436
- package/ftm-debug/references/protocols/BLACKBOARD.md +86 -86
- package/ftm-debug/references/protocols/EDGE-CASES.md +103 -103
- package/ftm-debug.yml +2 -2
- package/ftm-diagram/SKILL.md +277 -277
- package/ftm-diagram.yml +2 -2
- package/ftm-executor/SKILL.md +777 -767
- package/ftm-executor/references/STYLE-TEMPLATE.md +73 -73
- package/ftm-executor/references/phases/PHASE-0-VERIFICATION.md +62 -62
- package/ftm-executor/references/phases/PHASE-2-AGENT-ASSEMBLY.md +34 -34
- package/ftm-executor/references/phases/PHASE-3-WORKTREES.md +38 -38
- package/ftm-executor/references/phases/PHASE-4-5-AUDIT.md +72 -72
- package/ftm-executor/references/phases/PHASE-4-DISPATCH.md +66 -66
- package/ftm-executor/references/phases/PHASE-5-5-CODEX-GATE.md +73 -73
- package/ftm-executor/references/protocols/DOCUMENTATION-BOOTSTRAP.md +36 -36
- package/ftm-executor/references/protocols/MODEL-PROFILE.md +59 -44
- package/ftm-executor/references/protocols/PROGRESS-TRACKING.md +66 -66
- package/ftm-executor/runtime/ftm-runtime.mjs +252 -252
- package/ftm-executor/runtime/package.json +8 -8
- package/ftm-executor.yml +2 -2
- package/ftm-git/SKILL.md +441 -441
- package/ftm-git/evals/evals.json +26 -26
- package/ftm-git/evals/promptfoo.yaml +75 -75
- package/ftm-git/hooks/post-commit-experience.sh +92 -92
- package/ftm-git/references/patterns/SECRET-PATTERNS.md +104 -104
- package/ftm-git/references/protocols/REMEDIATION.md +139 -139
- package/ftm-git/scripts/pre-commit-secrets.sh +110 -110
- package/ftm-git.yml +2 -2
- package/ftm-inbox/backend/adapters/_retry.py +64 -64
- package/ftm-inbox/backend/adapters/base.py +230 -230
- package/ftm-inbox/backend/adapters/freshservice.py +104 -104
- package/ftm-inbox/backend/adapters/gmail.py +125 -125
- package/ftm-inbox/backend/adapters/jira.py +136 -136
- package/ftm-inbox/backend/adapters/registry.py +192 -192
- package/ftm-inbox/backend/adapters/slack.py +110 -110
- package/ftm-inbox/backend/db/connection.py +54 -54
- package/ftm-inbox/backend/db/schema.py +78 -78
- package/ftm-inbox/backend/executor/__init__.py +7 -7
- package/ftm-inbox/backend/executor/engine.py +149 -149
- package/ftm-inbox/backend/executor/step_runner.py +98 -98
- package/ftm-inbox/backend/main.py +103 -103
- package/ftm-inbox/backend/models/__init__.py +1 -1
- package/ftm-inbox/backend/models/unified_task.py +36 -36
- package/ftm-inbox/backend/planner/__init__.py +6 -6
- package/ftm-inbox/backend/planner/generator.py +127 -127
- package/ftm-inbox/backend/planner/schema.py +34 -34
- package/ftm-inbox/backend/requirements.txt +5 -5
- package/ftm-inbox/backend/routes/execute.py +186 -186
- package/ftm-inbox/backend/routes/health.py +52 -52
- package/ftm-inbox/backend/routes/inbox.py +68 -68
- package/ftm-inbox/backend/routes/plan.py +271 -271
- package/ftm-inbox/bin/launchagent.mjs +91 -91
- package/ftm-inbox/bin/setup.mjs +188 -188
- package/ftm-inbox/bin/start.sh +10 -10
- package/ftm-inbox/bin/status.sh +17 -17
- package/ftm-inbox/bin/stop.sh +8 -8
- package/ftm-inbox/config.example.yml +55 -55
- package/ftm-inbox/package-lock.json +2898 -2898
- package/ftm-inbox/package.json +26 -26
- package/ftm-inbox/postcss.config.js +6 -6
- package/ftm-inbox/src/app.css +199 -199
- package/ftm-inbox/src/app.html +18 -18
- package/ftm-inbox/src/lib/api.ts +166 -166
- package/ftm-inbox/src/lib/components/ExecutionLog.svelte +81 -81
- package/ftm-inbox/src/lib/components/InboxFeed.svelte +143 -143
- package/ftm-inbox/src/lib/components/PlanStep.svelte +271 -271
- package/ftm-inbox/src/lib/components/PlanView.svelte +206 -206
- package/ftm-inbox/src/lib/components/StreamPanel.svelte +99 -99
- package/ftm-inbox/src/lib/components/TaskCard.svelte +190 -190
- package/ftm-inbox/src/lib/components/ui/EmptyState.svelte +63 -63
- package/ftm-inbox/src/lib/components/ui/KawaiiCard.svelte +86 -86
- package/ftm-inbox/src/lib/components/ui/PillButton.svelte +106 -106
- package/ftm-inbox/src/lib/components/ui/StatusBadge.svelte +67 -67
- package/ftm-inbox/src/lib/components/ui/StreamDrawer.svelte +149 -149
- package/ftm-inbox/src/lib/components/ui/ThemeToggle.svelte +80 -80
- package/ftm-inbox/src/lib/theme.ts +47 -47
- package/ftm-inbox/src/routes/+layout.svelte +76 -76
- package/ftm-inbox/src/routes/+page.svelte +401 -401
- package/ftm-inbox/svelte.config.js +12 -12
- package/ftm-inbox/tailwind.config.ts +63 -63
- package/ftm-inbox/tsconfig.json +13 -13
- package/ftm-inbox/vite.config.ts +6 -6
- package/ftm-intent/SKILL.md +241 -241
- package/ftm-intent.yml +2 -2
- package/ftm-manifest.json +3794 -3794
- package/ftm-map/SKILL.md +291 -291
- package/ftm-map/scripts/db.py +712 -712
- package/ftm-map/scripts/index.py +415 -415
- package/ftm-map/scripts/parser.py +224 -224
- package/ftm-map/scripts/queries/go-tags.scm +20 -20
- package/ftm-map/scripts/queries/javascript-tags.scm +35 -35
- package/ftm-map/scripts/queries/python-tags.scm +31 -31
- package/ftm-map/scripts/queries/ruby-tags.scm +19 -19
- package/ftm-map/scripts/queries/rust-tags.scm +37 -37
- package/ftm-map/scripts/queries/typescript-tags.scm +41 -41
- package/ftm-map/scripts/query.py +301 -301
- package/ftm-map/scripts/ranker.py +377 -377
- package/ftm-map/scripts/requirements.txt +5 -5
- package/ftm-map/scripts/setup-hooks.sh +27 -27
- package/ftm-map/scripts/setup.sh +56 -56
- package/ftm-map/scripts/test_db.py +364 -364
- package/ftm-map/scripts/test_parser.py +174 -174
- package/ftm-map/scripts/test_query.py +183 -183
- package/ftm-map/scripts/test_ranker.py +199 -199
- package/ftm-map/scripts/views.py +591 -591
- package/ftm-map.yml +2 -2
- package/ftm-mind/SKILL.md +1943 -1943
- package/ftm-mind/evals/promptfoo.yaml +142 -142
- package/ftm-mind/references/blackboard-schema.md +328 -328
- package/ftm-mind/references/complexity-guide.md +110 -110
- package/ftm-mind/references/event-registry.md +319 -319
- package/ftm-mind/references/mcp-inventory.md +296 -296
- package/ftm-mind/references/protocols/COMPLEXITY-SIZING.md +72 -72
- package/ftm-mind/references/protocols/MCP-HEURISTICS.md +32 -32
- package/ftm-mind/references/protocols/PLAN-APPROVAL.md +80 -80
- package/ftm-mind/references/reflexion-protocol.md +249 -249
- package/ftm-mind/references/routing/SCENARIOS.md +22 -22
- package/ftm-mind/references/routing-scenarios.md +35 -35
- package/ftm-mind.yml +2 -2
- package/ftm-pause/SKILL.md +395 -395
- package/ftm-pause/references/protocols/SKILL-RESTORE-PROTOCOLS.md +186 -186
- package/ftm-pause/references/protocols/VALIDATION.md +80 -80
- package/ftm-pause.yml +2 -2
- package/ftm-researcher/SKILL.md +275 -275
- package/ftm-researcher/evals/agent-diversity.yaml +17 -17
- package/ftm-researcher/evals/synthesis-quality.yaml +12 -12
- package/ftm-researcher/evals/trigger-accuracy.yaml +39 -39
- package/ftm-researcher/references/adaptive-search.md +116 -116
- package/ftm-researcher/references/agent-prompts.md +193 -193
- package/ftm-researcher/references/council-integration.md +193 -193
- package/ftm-researcher/references/output-format.md +203 -203
- package/ftm-researcher/references/synthesis-pipeline.md +165 -165
- package/ftm-researcher/scripts/score_credibility.py +234 -234
- package/ftm-researcher/scripts/validate_research.py +92 -92
- package/ftm-researcher.yml +2 -2
- package/ftm-resume/SKILL.md +518 -518
- package/ftm-resume/references/protocols/VALIDATION.md +172 -172
- package/ftm-resume.yml +2 -2
- package/ftm-retro/SKILL.md +380 -380
- package/ftm-retro/references/protocols/SCORING-RUBRICS.md +89 -89
- package/ftm-retro/references/templates/REPORT-FORMAT.md +109 -109
- package/ftm-retro.yml +2 -2
- package/ftm-routine/SKILL.md +170 -170
- package/ftm-routine.yml +4 -4
- package/ftm-state/blackboard/capabilities.json +5 -5
- package/ftm-state/blackboard/capabilities.schema.json +27 -27
- package/ftm-state/blackboard/context.json +23 -23
- package/ftm-state/blackboard/experiences/index.json +9 -9
- package/ftm-state/blackboard/patterns.json +6 -6
- package/ftm-state/schemas/context.schema.json +130 -130
- package/ftm-state/schemas/experience-index.schema.json +77 -77
- package/ftm-state/schemas/experience.schema.json +78 -78
- package/ftm-state/schemas/patterns.schema.json +44 -44
- package/ftm-upgrade/SKILL.md +194 -194
- package/ftm-upgrade/scripts/check-version.sh +76 -76
- package/ftm-upgrade/scripts/upgrade.sh +143 -143
- package/ftm-upgrade.yml +2 -2
- package/ftm-verify.yml +2 -2
- package/ftm.yml +2 -2
- package/hooks/ftm-blackboard-enforcer.sh +93 -93
- package/hooks/ftm-discovery-reminder.sh +90 -90
- package/hooks/ftm-drafts-gate.sh +61 -61
- package/hooks/ftm-event-logger.mjs +107 -107
- package/hooks/ftm-map-autodetect.sh +79 -79
- package/hooks/ftm-pending-sync-check.sh +22 -22
- package/hooks/ftm-plan-gate.sh +92 -92
- package/hooks/ftm-post-commit-trigger.sh +57 -57
- package/hooks/settings-template.json +81 -81
- package/install.sh +363 -363
- package/package.json +84 -84
- 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
|