jfl 0.1.0 → 0.2.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 (262) hide show
  1. package/README.md +443 -145
  2. package/clawdbot-plugin/clawdbot.plugin.json +20 -0
  3. package/clawdbot-plugin/index.js +555 -0
  4. package/clawdbot-plugin/index.ts +582 -0
  5. package/clawdbot-skill/SKILL.md +33 -336
  6. package/clawdbot-skill/index.ts +491 -321
  7. package/clawdbot-skill/skill.json +4 -13
  8. package/dist/commands/clawdbot.d.ts +11 -0
  9. package/dist/commands/clawdbot.d.ts.map +1 -0
  10. package/dist/commands/clawdbot.js +215 -0
  11. package/dist/commands/clawdbot.js.map +1 -0
  12. package/dist/commands/context-hub.d.ts +5 -0
  13. package/dist/commands/context-hub.d.ts.map +1 -1
  14. package/dist/commands/context-hub.js +394 -28
  15. package/dist/commands/context-hub.js.map +1 -1
  16. package/dist/commands/gtm-process-update.d.ts +10 -0
  17. package/dist/commands/gtm-process-update.d.ts.map +1 -0
  18. package/dist/commands/gtm-process-update.js +101 -0
  19. package/dist/commands/gtm-process-update.js.map +1 -0
  20. package/dist/commands/init.d.ts.map +1 -1
  21. package/dist/commands/init.js +278 -4
  22. package/dist/commands/init.js.map +1 -1
  23. package/dist/commands/login.d.ts.map +1 -1
  24. package/dist/commands/login.js +32 -33
  25. package/dist/commands/login.js.map +1 -1
  26. package/dist/commands/memory.d.ts +38 -0
  27. package/dist/commands/memory.d.ts.map +1 -0
  28. package/dist/commands/memory.js +229 -0
  29. package/dist/commands/memory.js.map +1 -0
  30. package/dist/commands/migrate-services.d.ts +8 -0
  31. package/dist/commands/migrate-services.d.ts.map +1 -0
  32. package/dist/commands/migrate-services.js +182 -0
  33. package/dist/commands/migrate-services.js.map +1 -0
  34. package/dist/commands/onboard.d.ts +24 -0
  35. package/dist/commands/onboard.d.ts.map +1 -0
  36. package/dist/commands/onboard.js +663 -0
  37. package/dist/commands/onboard.js.map +1 -0
  38. package/dist/commands/openclaw.d.ts +56 -0
  39. package/dist/commands/openclaw.d.ts.map +1 -0
  40. package/dist/commands/openclaw.js +700 -0
  41. package/dist/commands/openclaw.js.map +1 -0
  42. package/dist/commands/orchestrate.d.ts +14 -0
  43. package/dist/commands/orchestrate.d.ts.map +1 -0
  44. package/dist/commands/orchestrate.js +270 -0
  45. package/dist/commands/orchestrate.js.map +1 -0
  46. package/dist/commands/profile.d.ts +46 -0
  47. package/dist/commands/profile.d.ts.map +1 -0
  48. package/dist/commands/profile.js +498 -0
  49. package/dist/commands/profile.js.map +1 -0
  50. package/dist/commands/repair.d.ts.map +1 -1
  51. package/dist/commands/repair.js +37 -0
  52. package/dist/commands/repair.js.map +1 -1
  53. package/dist/commands/service-agent.d.ts +16 -0
  54. package/dist/commands/service-agent.d.ts.map +1 -0
  55. package/dist/commands/service-agent.js +375 -0
  56. package/dist/commands/service-agent.js.map +1 -0
  57. package/dist/commands/service-manager.d.ts +12 -0
  58. package/dist/commands/service-manager.d.ts.map +1 -0
  59. package/dist/commands/service-manager.js +967 -0
  60. package/dist/commands/service-manager.js.map +1 -0
  61. package/dist/commands/service-validate.d.ts +12 -0
  62. package/dist/commands/service-validate.d.ts.map +1 -0
  63. package/dist/commands/service-validate.js +611 -0
  64. package/dist/commands/service-validate.js.map +1 -0
  65. package/dist/commands/services-create.d.ts +15 -0
  66. package/dist/commands/services-create.d.ts.map +1 -0
  67. package/dist/commands/services-create.js +1452 -0
  68. package/dist/commands/services-create.js.map +1 -0
  69. package/dist/commands/services-scan.d.ts +13 -0
  70. package/dist/commands/services-scan.d.ts.map +1 -0
  71. package/dist/commands/services-scan.js +251 -0
  72. package/dist/commands/services-scan.js.map +1 -0
  73. package/dist/commands/services-sync-agents.d.ts +23 -0
  74. package/dist/commands/services-sync-agents.d.ts.map +1 -0
  75. package/dist/commands/services-sync-agents.js +207 -0
  76. package/dist/commands/services-sync-agents.js.map +1 -0
  77. package/dist/commands/services.d.ts +19 -0
  78. package/dist/commands/services.d.ts.map +1 -0
  79. package/dist/commands/services.js +742 -0
  80. package/dist/commands/services.js.map +1 -0
  81. package/dist/commands/session.d.ts +5 -1
  82. package/dist/commands/session.d.ts.map +1 -1
  83. package/dist/commands/session.js +68 -586
  84. package/dist/commands/session.js.map +1 -1
  85. package/dist/commands/status.d.ts.map +1 -1
  86. package/dist/commands/status.js +17 -0
  87. package/dist/commands/status.js.map +1 -1
  88. package/dist/commands/update.d.ts.map +1 -1
  89. package/dist/commands/update.js +75 -21
  90. package/dist/commands/update.js.map +1 -1
  91. package/dist/commands/validate-settings.d.ts +37 -0
  92. package/dist/commands/validate-settings.d.ts.map +1 -0
  93. package/dist/commands/validate-settings.js +197 -0
  94. package/dist/commands/validate-settings.js.map +1 -0
  95. package/dist/commands/voice.d.ts +0 -1
  96. package/dist/commands/voice.d.ts.map +1 -1
  97. package/dist/commands/voice.js +16 -15
  98. package/dist/commands/voice.js.map +1 -1
  99. package/dist/index.js +395 -141
  100. package/dist/index.js.map +1 -1
  101. package/dist/lib/agent-generator.d.ts +26 -0
  102. package/dist/lib/agent-generator.d.ts.map +1 -0
  103. package/dist/lib/agent-generator.js +331 -0
  104. package/dist/lib/agent-generator.js.map +1 -0
  105. package/dist/lib/memory-db.d.ts +102 -0
  106. package/dist/lib/memory-db.d.ts.map +1 -0
  107. package/dist/lib/memory-db.js +313 -0
  108. package/dist/lib/memory-db.js.map +1 -0
  109. package/dist/lib/memory-indexer.d.ts +47 -0
  110. package/dist/lib/memory-indexer.d.ts.map +1 -0
  111. package/dist/lib/memory-indexer.js +215 -0
  112. package/dist/lib/memory-indexer.js.map +1 -0
  113. package/dist/lib/memory-search.d.ts +41 -0
  114. package/dist/lib/memory-search.d.ts.map +1 -0
  115. package/dist/lib/memory-search.js +246 -0
  116. package/dist/lib/memory-search.js.map +1 -0
  117. package/dist/lib/openclaw-registry.d.ts +48 -0
  118. package/dist/lib/openclaw-registry.d.ts.map +1 -0
  119. package/dist/lib/openclaw-registry.js +181 -0
  120. package/dist/lib/openclaw-registry.js.map +1 -0
  121. package/dist/lib/openclaw-sdk.d.ts +107 -0
  122. package/dist/lib/openclaw-sdk.d.ts.map +1 -0
  123. package/dist/lib/openclaw-sdk.js +208 -0
  124. package/dist/lib/openclaw-sdk.js.map +1 -0
  125. package/dist/lib/peer-agent-generator.d.ts +44 -0
  126. package/dist/lib/peer-agent-generator.d.ts.map +1 -0
  127. package/dist/lib/peer-agent-generator.js +286 -0
  128. package/dist/lib/peer-agent-generator.js.map +1 -0
  129. package/dist/lib/service-dependencies.d.ts +44 -0
  130. package/dist/lib/service-dependencies.d.ts.map +1 -0
  131. package/dist/lib/service-dependencies.js +314 -0
  132. package/dist/lib/service-dependencies.js.map +1 -0
  133. package/dist/lib/service-detector.d.ts +61 -0
  134. package/dist/lib/service-detector.d.ts.map +1 -0
  135. package/dist/lib/service-detector.js +521 -0
  136. package/dist/lib/service-detector.js.map +1 -0
  137. package/dist/lib/service-gtm.d.ts +157 -0
  138. package/dist/lib/service-gtm.d.ts.map +1 -0
  139. package/dist/lib/service-gtm.js +786 -0
  140. package/dist/lib/service-gtm.js.map +1 -0
  141. package/dist/lib/service-mcp-base.d.ts +103 -0
  142. package/dist/lib/service-mcp-base.d.ts.map +1 -0
  143. package/dist/lib/service-mcp-base.js +263 -0
  144. package/dist/lib/service-mcp-base.js.map +1 -0
  145. package/dist/lib/service-utils.d.ts +103 -0
  146. package/dist/lib/service-utils.d.ts.map +1 -0
  147. package/dist/lib/service-utils.js +368 -0
  148. package/dist/lib/service-utils.js.map +1 -0
  149. package/dist/lib/skill-generator.d.ts +21 -0
  150. package/dist/lib/skill-generator.d.ts.map +1 -0
  151. package/dist/lib/skill-generator.js +253 -0
  152. package/dist/lib/skill-generator.js.map +1 -0
  153. package/dist/lib/stratus-client.d.ts +100 -0
  154. package/dist/lib/stratus-client.d.ts.map +1 -0
  155. package/dist/lib/stratus-client.js +255 -0
  156. package/dist/lib/stratus-client.js.map +1 -0
  157. package/dist/mcp/context-hub-mcp.js +135 -53
  158. package/dist/mcp/context-hub-mcp.js.map +1 -1
  159. package/dist/mcp/service-mcp-server.d.ts +12 -0
  160. package/dist/mcp/service-mcp-server.d.ts.map +1 -0
  161. package/dist/mcp/service-mcp-server.js +434 -0
  162. package/dist/mcp/service-mcp-server.js.map +1 -0
  163. package/dist/mcp/service-peer-mcp.d.ts +36 -0
  164. package/dist/mcp/service-peer-mcp.d.ts.map +1 -0
  165. package/dist/mcp/service-peer-mcp.js +220 -0
  166. package/dist/mcp/service-peer-mcp.js.map +1 -0
  167. package/dist/mcp/service-registry-mcp.d.ts +13 -0
  168. package/dist/mcp/service-registry-mcp.d.ts.map +1 -0
  169. package/dist/mcp/service-registry-mcp.js +330 -0
  170. package/dist/mcp/service-registry-mcp.js.map +1 -0
  171. package/dist/ui/banner.js +1 -1
  172. package/dist/ui/banner.js.map +1 -1
  173. package/dist/ui/context-hub-logs.d.ts +10 -0
  174. package/dist/ui/context-hub-logs.d.ts.map +1 -0
  175. package/dist/ui/context-hub-logs.js +175 -0
  176. package/dist/ui/context-hub-logs.js.map +1 -0
  177. package/dist/ui/service-dashboard.d.ts +11 -0
  178. package/dist/ui/service-dashboard.d.ts.map +1 -0
  179. package/dist/ui/service-dashboard.js +357 -0
  180. package/dist/ui/service-dashboard.js.map +1 -0
  181. package/dist/ui/services-manager.d.ts +11 -0
  182. package/dist/ui/services-manager.d.ts.map +1 -0
  183. package/dist/ui/services-manager.js +507 -0
  184. package/dist/ui/services-manager.js.map +1 -0
  185. package/dist/utils/auth-guard.d.ts.map +1 -1
  186. package/dist/utils/auth-guard.js +8 -9
  187. package/dist/utils/auth-guard.js.map +1 -1
  188. package/dist/utils/claude-md-generator.d.ts +10 -0
  189. package/dist/utils/claude-md-generator.d.ts.map +1 -0
  190. package/dist/utils/claude-md-generator.js +215 -0
  191. package/dist/utils/claude-md-generator.js.map +1 -0
  192. package/dist/utils/ensure-context-hub.d.ts +20 -0
  193. package/dist/utils/ensure-context-hub.d.ts.map +1 -0
  194. package/dist/utils/ensure-context-hub.js +65 -0
  195. package/dist/utils/ensure-context-hub.js.map +1 -0
  196. package/dist/utils/ensure-project.d.ts.map +1 -1
  197. package/dist/utils/ensure-project.js +3 -4
  198. package/dist/utils/ensure-project.js.map +1 -1
  199. package/dist/utils/jfl-config.d.ts +19 -0
  200. package/dist/utils/jfl-config.d.ts.map +1 -0
  201. package/dist/utils/jfl-config.js +112 -0
  202. package/dist/utils/jfl-config.js.map +1 -0
  203. package/dist/utils/jfl-migration.d.ts +29 -0
  204. package/dist/utils/jfl-migration.d.ts.map +1 -0
  205. package/dist/utils/jfl-migration.js +142 -0
  206. package/dist/utils/jfl-migration.js.map +1 -0
  207. package/dist/utils/jfl-paths.d.ts +55 -0
  208. package/dist/utils/jfl-paths.d.ts.map +1 -0
  209. package/dist/utils/jfl-paths.js +120 -0
  210. package/dist/utils/jfl-paths.js.map +1 -0
  211. package/dist/utils/settings-validator.d.ts +73 -0
  212. package/dist/utils/settings-validator.d.ts.map +1 -0
  213. package/dist/utils/settings-validator.js +222 -0
  214. package/dist/utils/settings-validator.js.map +1 -0
  215. package/package.json +19 -3
  216. package/scripts/commit-gtm.sh +56 -0
  217. package/scripts/commit-product.sh +68 -0
  218. package/scripts/context-query.sh +45 -0
  219. package/scripts/session/auto-commit.sh +297 -0
  220. package/scripts/session/jfl-doctor.sh +707 -0
  221. package/scripts/session/session-cleanup.sh +268 -0
  222. package/scripts/session/session-end.sh +198 -0
  223. package/scripts/session/session-init.sh +350 -0
  224. package/scripts/session/session-init.sh.backup +292 -0
  225. package/scripts/session/session-sync.sh +167 -0
  226. package/scripts/session/test-context-preservation.sh +160 -0
  227. package/scripts/session/test-critical-infrastructure.sh +293 -0
  228. package/scripts/session/test-experience-level.sh +336 -0
  229. package/scripts/session/test-session-cleanup.sh +268 -0
  230. package/scripts/session/test-session-sync.sh +320 -0
  231. package/scripts/voice-start.sh +36 -8
  232. package/scripts/where-am-i.sh +78 -0
  233. package/template/.claude/service-settings.json +32 -0
  234. package/template/.claude/settings.json +14 -1
  235. package/template/.claude/skills/end/SKILL.md +1780 -0
  236. package/template/.jfl/config.json +2 -1
  237. package/template/CLAUDE.md +1039 -134
  238. package/template/CLAUDE.md.bak +1187 -0
  239. package/template/scripts/commit-gtm.sh +56 -0
  240. package/template/scripts/commit-product.sh +68 -0
  241. package/template/scripts/migrate-to-branch-sessions.sh +201 -0
  242. package/template/scripts/session/auto-commit.sh +58 -6
  243. package/template/scripts/session/jfl-doctor.sh +137 -17
  244. package/template/scripts/session/session-cleanup.sh +268 -0
  245. package/template/scripts/session/session-end.sh +4 -0
  246. package/template/scripts/session/session-init.sh +253 -66
  247. package/template/scripts/session/test-critical-infrastructure.sh +293 -0
  248. package/template/scripts/session/test-experience-level.sh +336 -0
  249. package/template/scripts/session/test-session-cleanup.sh +268 -0
  250. package/template/scripts/session/test-session-sync.sh +320 -0
  251. package/template/scripts/where-am-i.sh +78 -0
  252. package/template/templates/service-agent/.claude/settings.json +32 -0
  253. package/template/templates/service-agent/CLAUDE.md +334 -0
  254. package/template/templates/service-agent/knowledge/ARCHITECTURE.md +115 -0
  255. package/template/templates/service-agent/knowledge/DEPLOYMENT.md +199 -0
  256. package/template/templates/service-agent/knowledge/RUNBOOK.md +412 -0
  257. package/template/templates/service-agent/knowledge/SERVICE_SPEC.md +77 -0
  258. package/dist/commands/session-mgmt.d.ts +0 -33
  259. package/dist/commands/session-mgmt.d.ts.map +0 -1
  260. package/dist/commands/session-mgmt.js +0 -404
  261. package/dist/commands/session-mgmt.js.map +0 -1
  262. package/template/scripts/session/auto-merge.sh +0 -325
@@ -0,0 +1,167 @@
1
+ #!/bin/bash
2
+ # session-sync.sh - Run at session start to ensure all repos are synced
3
+ # This prevents the "where did my files go" problem
4
+
5
+ set -e
6
+
7
+ RED='\033[0;31m'
8
+ GREEN='\033[0;32m'
9
+ YELLOW='\033[1;33m'
10
+ NC='\033[0m' # No Color
11
+
12
+ echo "========================================"
13
+ echo "JFL Session Sync"
14
+ echo "========================================"
15
+
16
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
17
+ GTM_ROOT="$(pwd)"
18
+
19
+ # Track failures
20
+ FAILURES=0
21
+
22
+ # Function to sync a repo
23
+ sync_repo() {
24
+ local repo_path="$1"
25
+ local repo_name="$2"
26
+
27
+ if [ ! -d "$repo_path" ]; then
28
+ echo -e "${RED}ERROR: $repo_name not found at $repo_path${NC}"
29
+ FAILURES=$((FAILURES + 1))
30
+ return 1
31
+ fi
32
+
33
+ echo ""
34
+ echo "--- Syncing $repo_name ---"
35
+ cd "$repo_path"
36
+
37
+ # Check if it's a git repo
38
+ if [ ! -d ".git" ]; then
39
+ echo -e "${YELLOW}WARNING: $repo_name is not a git repo${NC}"
40
+ return 0
41
+ fi
42
+
43
+ # Get current branch
44
+ CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "detached")
45
+
46
+ # Fetch latest
47
+ echo "Fetching from origin..."
48
+ git fetch origin 2>/dev/null || {
49
+ echo -e "${YELLOW}WARNING: Could not fetch $repo_name (no network?)${NC}"
50
+ return 0
51
+ }
52
+
53
+ # Check if behind
54
+ if [ "$CURRENT_BRANCH" != "detached" ] && [ "$CURRENT_BRANCH" != "" ]; then
55
+ LOCAL=$(git rev-parse HEAD)
56
+ REMOTE=$(git rev-parse "origin/$CURRENT_BRANCH" 2>/dev/null || echo "")
57
+
58
+ if [ -n "$REMOTE" ] && [ "$LOCAL" != "$REMOTE" ]; then
59
+ BEHIND=$(git rev-list --count HEAD.."origin/$CURRENT_BRANCH" 2>/dev/null || echo "0")
60
+ AHEAD=$(git rev-list --count "origin/$CURRENT_BRANCH"..HEAD 2>/dev/null || echo "0")
61
+
62
+ if [ "$BEHIND" -gt 0 ]; then
63
+ echo -e "${YELLOW}$repo_name is $BEHIND commits behind origin/$CURRENT_BRANCH${NC}"
64
+
65
+ # Check for uncommitted changes
66
+ if [ -n "$(git status --porcelain)" ]; then
67
+ echo -e "${RED}ERROR: $repo_name has uncommitted changes AND is behind${NC}"
68
+ echo "Please commit or stash changes, then pull"
69
+ FAILURES=$((FAILURES + 1))
70
+ else
71
+ echo "Pulling latest..."
72
+ git pull origin "$CURRENT_BRANCH" || {
73
+ echo -e "${RED}ERROR: Failed to pull $repo_name${NC}"
74
+ FAILURES=$((FAILURES + 1))
75
+ }
76
+ fi
77
+ fi
78
+
79
+ if [ "$AHEAD" -gt 0 ]; then
80
+ echo -e "${YELLOW}$repo_name is $AHEAD commits ahead (unpushed)${NC}"
81
+ fi
82
+ else
83
+ echo -e "${GREEN}$repo_name is up to date${NC}"
84
+ fi
85
+ else
86
+ echo -e "${YELLOW}$repo_name is in detached HEAD state${NC}"
87
+ # Try to checkout main and pull
88
+ echo "Attempting to checkout main and pull..."
89
+ git checkout main 2>/dev/null && git pull origin main 2>/dev/null || {
90
+ echo -e "${YELLOW}Could not auto-fix detached HEAD${NC}"
91
+ }
92
+ fi
93
+
94
+ # Show current state
95
+ echo "Current: $(git log --oneline -1)"
96
+ }
97
+
98
+ # Sync main GTM repo
99
+ sync_repo "$GTM_ROOT" "jfl-gtm"
100
+
101
+ # Check for product - submodule or symlink
102
+ PRODUCT_PATH="$GTM_ROOT/product"
103
+ if [ -d "$PRODUCT_PATH" ] && [ -f "$PRODUCT_PATH/.git" ]; then
104
+ # It's a submodule (submodules have .git as a FILE, not directory)
105
+ echo ""
106
+ echo "--- Updating product submodule ---"
107
+ cd "$GTM_ROOT"
108
+
109
+ # First, init if needed
110
+ git submodule init product 2>/dev/null || true
111
+
112
+ # Update to latest from remote
113
+ git submodule update --remote product || {
114
+ echo -e "${YELLOW}WARNING: Could not update product submodule${NC}"
115
+ }
116
+
117
+ # Show what commit we're on
118
+ cd "$PRODUCT_PATH"
119
+ echo -e "${GREEN}product submodule at: $(git log --oneline -1)${NC}"
120
+ cd "$GTM_ROOT"
121
+
122
+ elif [ -L "$PRODUCT_PATH" ]; then
123
+ # It's a symlink - resolve and sync the target (legacy support)
124
+ echo -e "${YELLOW}WARNING: product/ is a symlink, not a submodule${NC}"
125
+ echo "Consider converting to submodule for better reliability"
126
+
127
+ TARGET=$(readlink "$PRODUCT_PATH")
128
+ if [[ "$TARGET" == ../* ]]; then
129
+ RESOLVED_TARGET="$GTM_ROOT/$TARGET"
130
+ else
131
+ RESOLVED_TARGET="$TARGET"
132
+ fi
133
+ RESOLVED_TARGET=$(cd "$RESOLVED_TARGET" 2>/dev/null && pwd)
134
+
135
+ if [ -n "$RESOLVED_TARGET" ]; then
136
+ sync_repo "$RESOLVED_TARGET" "jfl-platform (product symlink target)"
137
+ else
138
+ echo -e "${RED}ERROR: Could not resolve product symlink target${NC}"
139
+ FAILURES=$((FAILURES + 1))
140
+ fi
141
+ elif [ ! -e "$PRODUCT_PATH" ]; then
142
+ # Product doesn't exist - try to init submodule
143
+ echo ""
144
+ echo "--- Initializing product submodule ---"
145
+ cd "$GTM_ROOT"
146
+ git submodule init product 2>/dev/null && git submodule update product || {
147
+ echo -e "${YELLOW}WARNING: Could not initialize product submodule${NC}"
148
+ }
149
+ fi
150
+
151
+ # Sync other submodules
152
+ echo ""
153
+ echo "--- Syncing submodules ---"
154
+ cd "$GTM_ROOT"
155
+ git submodule update --init --recursive 2>/dev/null || true
156
+
157
+ # Final status
158
+ echo ""
159
+ echo "========================================"
160
+ if [ $FAILURES -gt 0 ]; then
161
+ echo -e "${RED}Session sync completed with $FAILURES errors${NC}"
162
+ echo "Please fix the above issues before continuing"
163
+ exit 1
164
+ else
165
+ echo -e "${GREEN}Session sync completed successfully${NC}"
166
+ fi
167
+ echo "========================================"
@@ -0,0 +1,160 @@
1
+ #!/bin/bash
2
+ # test-context-preservation.sh - Verify that context files exist and are in sync
3
+ # Run this to catch "missing files" issues before they become problems
4
+
5
+ set -e
6
+
7
+ RED='\033[0;31m'
8
+ GREEN='\033[0;32m'
9
+ YELLOW='\033[1;33m'
10
+ NC='\033[0m'
11
+
12
+ echo "========================================"
13
+ echo "Context Preservation Test"
14
+ echo "========================================"
15
+
16
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
17
+ GTM_ROOT="$(pwd)"
18
+
19
+ FAILURES=0
20
+ WARNINGS=0
21
+
22
+ # Test 1: Critical GTM knowledge files exist
23
+ echo ""
24
+ echo "Test 1: Critical knowledge files"
25
+ CRITICAL_FILES=(
26
+ "knowledge/VISION.md"
27
+ "knowledge/NARRATIVE.md"
28
+ "knowledge/ROADMAP.md"
29
+ "knowledge/BRAND_DECISIONS.md"
30
+ "knowledge/DESIGN_SYSTEM.md"
31
+ "knowledge/NAMING.md"
32
+ "knowledge/PRODUCT_SPEC_V2.md"
33
+ )
34
+
35
+ for file in "${CRITICAL_FILES[@]}"; do
36
+ if [ -f "$GTM_ROOT/$file" ]; then
37
+ SIZE=$(wc -c < "$GTM_ROOT/$file")
38
+ if [ "$SIZE" -lt 100 ]; then
39
+ echo -e "${YELLOW} WARNING: $file exists but is very small ($SIZE bytes)${NC}"
40
+ WARNINGS=$((WARNINGS + 1))
41
+ else
42
+ echo -e "${GREEN} ✓ $file ($SIZE bytes)${NC}"
43
+ fi
44
+ else
45
+ echo -e "${RED} ✗ $file MISSING${NC}"
46
+ FAILURES=$((FAILURES + 1))
47
+ fi
48
+ done
49
+
50
+ # Test 2: Product platform specs exist
51
+ echo ""
52
+ echo "Test 2: Product platform specs"
53
+ PRODUCT_PATH="$GTM_ROOT/product"
54
+ if [ -L "$PRODUCT_PATH" ]; then
55
+ PRODUCT_PATH=$(cd "$PRODUCT_PATH" 2>/dev/null && pwd)
56
+ fi
57
+
58
+ PLATFORM_FILES=(
59
+ "PLATFORM_SPEC.md"
60
+ "TEMPLATE_SPEC.md"
61
+ "CONTEXT_GRAPH_SPEC.md"
62
+ )
63
+
64
+ for file in "${PLATFORM_FILES[@]}"; do
65
+ if [ -f "$PRODUCT_PATH/$file" ]; then
66
+ SIZE=$(wc -c < "$PRODUCT_PATH/$file")
67
+ echo -e "${GREEN} ✓ product/$file ($SIZE bytes)${NC}"
68
+ else
69
+ echo -e "${RED} ✗ product/$file MISSING${NC}"
70
+ FAILURES=$((FAILURES + 1))
71
+ fi
72
+ done
73
+
74
+ # Test 3: Git repos are in sync with remotes
75
+ echo ""
76
+ echo "Test 3: Git sync status"
77
+
78
+ check_git_sync() {
79
+ local repo_path="$1"
80
+ local repo_name="$2"
81
+
82
+ cd "$repo_path" 2>/dev/null || return 1
83
+
84
+ git fetch origin 2>/dev/null || {
85
+ echo -e "${YELLOW} WARNING: Could not fetch $repo_name${NC}"
86
+ WARNINGS=$((WARNINGS + 1))
87
+ return 0
88
+ }
89
+
90
+ BRANCH=$(git branch --show-current 2>/dev/null || echo "")
91
+ if [ -z "$BRANCH" ]; then
92
+ echo -e "${YELLOW} WARNING: $repo_name is in detached HEAD${NC}"
93
+ WARNINGS=$((WARNINGS + 1))
94
+ return 0
95
+ fi
96
+
97
+ LOCAL=$(git rev-parse HEAD)
98
+ REMOTE=$(git rev-parse "origin/$BRANCH" 2>/dev/null || echo "")
99
+
100
+ if [ -z "$REMOTE" ]; then
101
+ echo -e "${YELLOW} WARNING: $repo_name has no remote tracking${NC}"
102
+ WARNINGS=$((WARNINGS + 1))
103
+ return 0
104
+ fi
105
+
106
+ BEHIND=$(git rev-list --count HEAD.."origin/$BRANCH" 2>/dev/null || echo "0")
107
+
108
+ if [ "$BEHIND" -gt 0 ]; then
109
+ echo -e "${RED} ✗ $repo_name is $BEHIND commits BEHIND origin${NC}"
110
+ FAILURES=$((FAILURES + 1))
111
+ else
112
+ echo -e "${GREEN} ✓ $repo_name is in sync${NC}"
113
+ fi
114
+ }
115
+
116
+ check_git_sync "$GTM_ROOT" "jfl-gtm"
117
+
118
+ # Check product target
119
+ PRODUCT_LINK="$GTM_ROOT/product"
120
+ if [ -L "$PRODUCT_LINK" ]; then
121
+ TARGET=$(readlink "$PRODUCT_LINK")
122
+ if [[ "$TARGET" == ../* ]]; then
123
+ RESOLVED="$GTM_ROOT/$TARGET"
124
+ else
125
+ RESOLVED="$TARGET"
126
+ fi
127
+ RESOLVED=$(cd "$RESOLVED" 2>/dev/null && pwd)
128
+ if [ -n "$RESOLVED" ]; then
129
+ check_git_sync "$RESOLVED" "jfl-platform"
130
+ fi
131
+ fi
132
+
133
+ # Test 4: No uncommitted critical changes
134
+ echo ""
135
+ echo "Test 4: Uncommitted changes check"
136
+ cd "$GTM_ROOT"
137
+ UNCOMMITTED=$(git status --porcelain knowledge/ 2>/dev/null | wc -l)
138
+ if [ "$UNCOMMITTED" -gt 0 ]; then
139
+ echo -e "${YELLOW} WARNING: $UNCOMMITTED uncommitted changes in knowledge/${NC}"
140
+ git status --porcelain knowledge/ | head -5
141
+ WARNINGS=$((WARNINGS + 1))
142
+ else
143
+ echo -e "${GREEN} ✓ No uncommitted knowledge changes${NC}"
144
+ fi
145
+
146
+ # Summary
147
+ echo ""
148
+ echo "========================================"
149
+ if [ $FAILURES -gt 0 ]; then
150
+ echo -e "${RED}FAILED: $FAILURES critical issues found${NC}"
151
+ echo "Run: ./scripts/session-sync.sh to fix sync issues"
152
+ exit 1
153
+ elif [ $WARNINGS -gt 0 ]; then
154
+ echo -e "${YELLOW}PASSED with $WARNINGS warnings${NC}"
155
+ exit 0
156
+ else
157
+ echo -e "${GREEN}PASSED: All context preservation checks passed${NC}"
158
+ exit 0
159
+ fi
160
+ echo "========================================"
@@ -0,0 +1,293 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Critical Infrastructure Tests - Work Loss Prevention
4
+ #
5
+ # Tests the three pillars that prevent work loss:
6
+ # 1. Signal handling (Ctrl+C, crashes)
7
+ # 2. Unmerged branch detection
8
+ # 3. Crash reconciliation
9
+ #
10
+ # @purpose Rigorous testing of work-loss-prevention infrastructure
11
+
12
+ set -e
13
+
14
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
+ REPO_DIR="$(git rev-parse --path-format=absolute --git-common-dir)"
16
+ REPO_DIR="${REPO_DIR%/.git}"
17
+ WORKTREES_DIR="$REPO_DIR/worktrees"
18
+
19
+ # Colors
20
+ RED='\033[0;31m'
21
+ GREEN='\033[0;32m'
22
+ YELLOW='\033[1;33m'
23
+ BLUE='\033[0;34m'
24
+ NC='\033[0m'
25
+
26
+ TESTS_PASSED=0
27
+ TESTS_FAILED=0
28
+
29
+ # Test helper functions
30
+ pass() {
31
+ echo -e "${GREEN}✓${NC} $1"
32
+ TESTS_PASSED=$((TESTS_PASSED + 1))
33
+ }
34
+
35
+ fail() {
36
+ echo -e "${RED}✗${NC} $1"
37
+ TESTS_FAILED=$((TESTS_FAILED + 1))
38
+ }
39
+
40
+ section() {
41
+ echo ""
42
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
43
+ echo -e "${BLUE}$1${NC}"
44
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
45
+ }
46
+
47
+ cleanup_test_branches() {
48
+ # Clean up any test branches from previous runs
49
+ git branch -D test-merged-branch 2>/dev/null || true
50
+ git branch -D test-unmerged-branch 2>/dev/null || true
51
+ }
52
+
53
+ # ==============================================================================
54
+ # Test 1: Signal Handling in Auto-Commit
55
+ # ==============================================================================
56
+
57
+ test_signal_handling() {
58
+ section "Test 1: Signal Handling (auto-commit graceful shutdown)"
59
+
60
+ # Check for signal trap in auto-commit.sh
61
+ if grep -q "trap graceful_shutdown" "$SCRIPT_DIR/auto-commit.sh"; then
62
+ pass "Signal trap registered for graceful shutdown"
63
+ else
64
+ fail "No signal trap found in auto-commit.sh"
65
+ fi
66
+
67
+ # Check for graceful_shutdown function
68
+ if grep -q "graceful_shutdown()" "$SCRIPT_DIR/auto-commit.sh"; then
69
+ pass "graceful_shutdown() function exists"
70
+ else
71
+ fail "graceful_shutdown() function missing"
72
+ fi
73
+
74
+ # Check that stop_daemon sends SIGTERM (not hard kill)
75
+ if grep -A10 "stop_daemon()" "$SCRIPT_DIR/auto-commit.sh" | grep -q "kill -TERM"; then
76
+ pass "stop_daemon() sends SIGTERM for graceful shutdown"
77
+ else
78
+ fail "stop_daemon() uses hard kill instead of graceful shutdown"
79
+ fi
80
+
81
+ # Anti-test: Verify old behavior is removed
82
+ if grep -A10 "stop_daemon()" "$SCRIPT_DIR/auto-commit.sh" | grep -q "kill \"\$pid\" 2>/dev/null$"; then
83
+ fail "Old hard-kill behavior still present"
84
+ else
85
+ pass "Old hard-kill behavior removed"
86
+ fi
87
+ }
88
+
89
+ # ==============================================================================
90
+ # Test 2: Doctor Script - Unmerged Branch Detection
91
+ # ==============================================================================
92
+
93
+ test_unmerged_detection() {
94
+ section "Test 2: Unmerged Branch Detection"
95
+
96
+ cd "$REPO_DIR"
97
+
98
+ # Create test branches
99
+ cleanup_test_branches
100
+
101
+ # Create merged branch (0 commits ahead)
102
+ git branch test-merged-branch HEAD 2>/dev/null || true
103
+
104
+ # Create unmerged branch (1 commit ahead)
105
+ git checkout -b test-unmerged-branch 2>/dev/null || git checkout test-unmerged-branch
106
+ echo "test change" >> .jfl/test-file.txt
107
+ git add .jfl/test-file.txt
108
+ git commit -m "test: unmerged commit" >/dev/null 2>&1 || true
109
+ git checkout main 2>/dev/null
110
+
111
+ # Run doctor and capture output
112
+ output=$("$SCRIPT_DIR/jfl-doctor.sh" --verbose 2>&1 || true)
113
+
114
+ # Test: Check code has MERGED label (may not appear in output if no merged orphans exist)
115
+ if grep -q "✓ MERGED (safe to delete):" "$SCRIPT_DIR/jfl-doctor.sh"; then
116
+ pass "Merged branches labeled as safe in code"
117
+ else
118
+ fail "Merged branches not properly labeled in code"
119
+ fi
120
+
121
+ # Test: UNMERGED branch shows up as do NOT delete
122
+ if echo "$output" | grep -q "⚠️ UNMERGED (do NOT delete):"; then
123
+ pass "Unmerged branches labeled as dangerous"
124
+ else
125
+ fail "Unmerged branches not properly labeled"
126
+ fi
127
+
128
+ # Test: Check code formats commit counts correctly
129
+ if grep -q "commits NOT in main" "$SCRIPT_DIR/jfl-doctor.sh"; then
130
+ pass "Unmerged commit count format present in code"
131
+ else
132
+ fail "Unmerged commit count format missing"
133
+ fi
134
+
135
+ # Anti-test: Verify unmerged branches are NEVER deleted in --fix mode
136
+ before_count=$(git branch --list 'test-*' | wc -l | tr -d ' ')
137
+ "$SCRIPT_DIR/jfl-doctor.sh" --fix >/dev/null 2>&1 || true
138
+ after_count=$(git branch --list 'test-*' | wc -l | tr -d ' ')
139
+
140
+ if git rev-parse test-unmerged-branch >/dev/null 2>&1; then
141
+ pass "Unmerged branch NOT deleted by --fix mode"
142
+ else
143
+ fail "DANGER: --fix mode deleted unmerged branch!"
144
+ fi
145
+
146
+ # Cleanup
147
+ cleanup_test_branches
148
+ rm -f .jfl/test-file.txt
149
+ }
150
+
151
+ # ==============================================================================
152
+ # Test 3: Crash Reconciliation
153
+ # ==============================================================================
154
+
155
+ test_crash_reconciliation() {
156
+ section "Test 3: Crash Reconciliation (uncommitted work detection)"
157
+
158
+ # Check that session-init scans for uncommitted work
159
+ if grep -q "Check for uncommitted work in stale sessions" "$SCRIPT_DIR/session-init.sh"; then
160
+ pass "Crash reconciliation code present in session-init"
161
+ else
162
+ fail "No crash reconciliation in session-init"
163
+ fi
164
+
165
+ # Check for the prompt
166
+ if grep -q "This work needs to be saved before continuing" "$SCRIPT_DIR/session-init.sh"; then
167
+ pass "User prompt for uncommitted work exists"
168
+ else
169
+ fail "No prompt for uncommitted work"
170
+ fi
171
+
172
+ # Check for auto-commit option
173
+ if grep -q "Auto-commit all and continue" "$SCRIPT_DIR/session-init.sh"; then
174
+ pass "Auto-commit option available"
175
+ else
176
+ fail "No auto-commit option in crash recovery"
177
+ fi
178
+
179
+ # Anti-test: Verify it doesn't just skip uncommitted work
180
+ if grep -q "git status --porcelain" "$SCRIPT_DIR/session-init.sh"; then
181
+ pass "Checks for uncommitted changes properly"
182
+ else
183
+ fail "Doesn't check for uncommitted changes"
184
+ fi
185
+ }
186
+
187
+ # ==============================================================================
188
+ # Test 4: REPO_DIR Resolution (worktree-aware)
189
+ # ==============================================================================
190
+
191
+ test_repo_dir_resolution() {
192
+ section "Test 4: REPO_DIR Resolution (works from worktrees)"
193
+
194
+ # Check that doctor uses git to find main repo
195
+ if grep -q "git rev-parse --path-format=absolute --git-common-dir" "$SCRIPT_DIR/jfl-doctor.sh"; then
196
+ pass "Doctor script uses git to find main repo"
197
+ else
198
+ fail "Doctor script doesn't resolve repo correctly"
199
+ fi
200
+
201
+ # Test from main repo
202
+ cd "$REPO_DIR"
203
+ detected_repo=$("$SCRIPT_DIR/jfl-doctor.sh" 2>&1 | grep -c "jfl doctor" || echo "0")
204
+ if [[ "$detected_repo" -gt 0 ]]; then
205
+ pass "Doctor runs from main repo"
206
+ else
207
+ fail "Doctor fails from main repo"
208
+ fi
209
+
210
+ # Test from worktree (if any exist)
211
+ if [[ -d "$WORKTREES_DIR" ]]; then
212
+ first_worktree=$(ls "$WORKTREES_DIR" | head -1)
213
+ if [[ -n "$first_worktree" ]]; then
214
+ cd "$WORKTREES_DIR/$first_worktree"
215
+ detected_repo=$("$SCRIPT_DIR/jfl-doctor.sh" 2>&1 | grep -c "jfl doctor" || echo "0")
216
+ if [[ "$detected_repo" -gt 0 ]]; then
217
+ pass "Doctor runs from worktree"
218
+ else
219
+ fail "Doctor fails from worktree"
220
+ fi
221
+ fi
222
+ fi
223
+
224
+ cd "$REPO_DIR"
225
+ }
226
+
227
+ # ==============================================================================
228
+ # Test 5: Session Sync (pulls main into worktree)
229
+ # ==============================================================================
230
+
231
+ test_session_sync() {
232
+ section "Test 5: Session Sync (main branch updates)"
233
+
234
+ # Check if session-sync exists
235
+ if [[ -f "$SCRIPT_DIR/session-sync.sh" ]]; then
236
+ pass "session-sync.sh exists"
237
+
238
+ # Check if it pulls main
239
+ if grep -q "git pull\|git fetch" "$SCRIPT_DIR/session-sync.sh"; then
240
+ pass "session-sync pulls from remote"
241
+ else
242
+ fail "session-sync doesn't pull from remote"
243
+ fi
244
+ else
245
+ fail "session-sync.sh missing"
246
+ fi
247
+
248
+ # Check if session-init calls session-sync
249
+ if [[ -f "$SCRIPT_DIR/session-init.sh" ]]; then
250
+ if grep -q "session-sync" "$SCRIPT_DIR/session-init.sh"; then
251
+ pass "session-init calls session-sync"
252
+ else
253
+ fail "session-init doesn't call session-sync"
254
+ fi
255
+ fi
256
+ }
257
+
258
+ # ==============================================================================
259
+ # Run All Tests
260
+ # ==============================================================================
261
+
262
+ main() {
263
+ echo ""
264
+ echo "╔══════════════════════════════════════════════════════════╗"
265
+ echo "║ JFL Critical Infrastructure Tests ║"
266
+ echo "║ Work Loss Prevention ║"
267
+ echo "╚══════════════════════════════════════════════════════════╝"
268
+
269
+ test_signal_handling
270
+ test_unmerged_detection
271
+ test_crash_reconciliation
272
+ test_repo_dir_resolution
273
+ test_session_sync
274
+
275
+ # Summary
276
+ echo ""
277
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
278
+ echo -e "${BLUE}Test Results${NC}"
279
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
280
+ echo -e "${GREEN}Passed:${NC} $TESTS_PASSED"
281
+ if [[ $TESTS_FAILED -gt 0 ]]; then
282
+ echo -e "${RED}Failed:${NC} $TESTS_FAILED"
283
+ echo ""
284
+ echo -e "${RED}CRITICAL INFRASTRUCTURE HAS ISSUES${NC}"
285
+ exit 1
286
+ else
287
+ echo ""
288
+ echo -e "${GREEN}✓ All critical infrastructure tests passed${NC}"
289
+ exit 0
290
+ fi
291
+ }
292
+
293
+ main "$@"