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,142 @@
1
+ /**
2
+ * JFL Migration from ~/.jfl/ to XDG directories
3
+ *
4
+ * @purpose One-time migration of legacy ~/.jfl/ to XDG-compliant paths
5
+ */
6
+ import * as fs from 'fs';
7
+ import * as path from 'path';
8
+ import chalk from 'chalk';
9
+ import { JFL_PATHS, JFL_FILES, hasLegacyJflDir, ensureJflDirs } from './jfl-paths.js';
10
+ /**
11
+ * Migrate ~/.jfl/ to XDG directories
12
+ * Called automatically on first run if legacy dir exists
13
+ */
14
+ export async function migrateToXDG(options = {}) {
15
+ const result = {
16
+ success: true,
17
+ migrated: [],
18
+ errors: [],
19
+ };
20
+ if (!hasLegacyJflDir()) {
21
+ return result; // Nothing to migrate
22
+ }
23
+ if (!options.silent) {
24
+ console.log(chalk.cyan('\n📦 Migrating JFL to XDG directories...\n'));
25
+ }
26
+ try {
27
+ // Ensure new directories exist
28
+ ensureJflDirs();
29
+ // Migration map: legacy path → new path
30
+ const migrations = [
31
+ // Config files
32
+ {
33
+ from: path.join(JFL_PATHS.legacy, 'config.json'),
34
+ to: JFL_FILES.config,
35
+ type: 'config',
36
+ },
37
+ // Sessions (data)
38
+ {
39
+ from: path.join(JFL_PATHS.legacy, 'sessions.json'),
40
+ to: JFL_FILES.sessions,
41
+ type: 'data',
42
+ },
43
+ // Service manager (data)
44
+ {
45
+ from: path.join(JFL_PATHS.legacy, 'service-manager'),
46
+ to: JFL_FILES.servicesDir,
47
+ type: 'data',
48
+ },
49
+ // Update check cache
50
+ {
51
+ from: path.join(JFL_PATHS.legacy, '.jfl-last-update-check'),
52
+ to: JFL_FILES.updateCheck,
53
+ type: 'cache',
54
+ },
55
+ ];
56
+ // Execute migrations
57
+ for (const migration of migrations) {
58
+ try {
59
+ if (!fs.existsSync(migration.from)) {
60
+ continue; // Skip if source doesn't exist
61
+ }
62
+ const isDir = fs.statSync(migration.from).isDirectory();
63
+ if (isDir) {
64
+ // Copy directory recursively
65
+ copyDirRecursive(migration.from, migration.to);
66
+ }
67
+ else {
68
+ // Copy file
69
+ const destDir = path.dirname(migration.to);
70
+ if (!fs.existsSync(destDir)) {
71
+ fs.mkdirSync(destDir, { recursive: true });
72
+ }
73
+ fs.copyFileSync(migration.from, migration.to);
74
+ }
75
+ result.migrated.push(migration.to);
76
+ if (!options.silent) {
77
+ console.log(chalk.gray(` ✓ ${path.basename(migration.from)} → ${migration.type}`));
78
+ }
79
+ }
80
+ catch (err) {
81
+ result.errors.push({
82
+ file: migration.from,
83
+ error: err.message,
84
+ });
85
+ result.success = false;
86
+ }
87
+ }
88
+ // If migration successful, remove legacy directory
89
+ if (result.success && result.errors.length === 0) {
90
+ fs.rmSync(JFL_PATHS.legacy, { recursive: true, force: true });
91
+ if (!options.silent) {
92
+ console.log(chalk.green('\n✨ Migration complete!\n'));
93
+ console.log(chalk.gray(' Config: ~/.config/jfl/'));
94
+ console.log(chalk.gray(' Data: ~/.local/share/jfl/'));
95
+ console.log(chalk.gray(' Cache: ~/.cache/jfl/\n'));
96
+ }
97
+ }
98
+ }
99
+ catch (err) {
100
+ result.success = false;
101
+ result.errors.push({ file: 'migration', error: err.message });
102
+ }
103
+ return result;
104
+ }
105
+ /**
106
+ * Check if migration is needed and prompt user
107
+ * Called at CLI startup
108
+ */
109
+ export async function checkAndMigrate(options = {}) {
110
+ if (!hasLegacyJflDir()) {
111
+ return; // No migration needed
112
+ }
113
+ // Auto-migrate (user chose Option A)
114
+ const result = await migrateToXDG(options);
115
+ if (!result.success) {
116
+ console.error(chalk.red('\n⚠️ Migration had errors:'));
117
+ for (const error of result.errors) {
118
+ console.error(chalk.gray(` ${error.file}: ${error.error}`));
119
+ }
120
+ console.log(chalk.yellow('\nYou may need to migrate manually.\n'));
121
+ }
122
+ }
123
+ /**
124
+ * Recursively copy directory
125
+ */
126
+ function copyDirRecursive(src, dest) {
127
+ if (!fs.existsSync(dest)) {
128
+ fs.mkdirSync(dest, { recursive: true });
129
+ }
130
+ const entries = fs.readdirSync(src, { withFileTypes: true });
131
+ for (const entry of entries) {
132
+ const srcPath = path.join(src, entry.name);
133
+ const destPath = path.join(dest, entry.name);
134
+ if (entry.isDirectory()) {
135
+ copyDirRecursive(srcPath, destPath);
136
+ }
137
+ else {
138
+ fs.copyFileSync(srcPath, destPath);
139
+ }
140
+ }
141
+ }
142
+ //# sourceMappingURL=jfl-migration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jfl-migration.js","sourceRoot":"","sources":["../../src/utils/jfl-migration.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Centralized JFL directory path management
3
+ *
4
+ * @purpose Single source of truth for all JFL paths (global and project-local)
5
+ * @spec Implements XDG Base Directory Specification
6
+ */
7
+ /**
8
+ * XDG Base Directory paths for JFL
9
+ * Respects XDG environment variables, falls back to defaults
10
+ */
11
+ export declare const JFL_PATHS: {
12
+ readonly config: string;
13
+ readonly data: string;
14
+ readonly cache: string;
15
+ readonly legacy: string;
16
+ };
17
+ /**
18
+ * Specific file paths within JFL directories
19
+ */
20
+ export declare const JFL_FILES: {
21
+ readonly config: string;
22
+ readonly auth: string;
23
+ readonly sessions: string;
24
+ readonly servicesDir: string;
25
+ readonly servicesRegistry: string;
26
+ readonly servicesLogs: string;
27
+ readonly servicesPids: string;
28
+ readonly updateCheck: string;
29
+ };
30
+ /**
31
+ * Check if legacy ~/.jfl/ exists (needs migration)
32
+ */
33
+ export declare function hasLegacyJflDir(): boolean;
34
+ /**
35
+ * Get migration status
36
+ * Returns: 'none' | 'needed' | 'complete'
37
+ */
38
+ export declare function getMigrationStatus(): 'none' | 'needed' | 'complete';
39
+ /**
40
+ * Ensure JFL directories exist
41
+ * Creates XDG-compliant directory structure
42
+ */
43
+ export declare function ensureJflDirs(): void;
44
+ /**
45
+ * Get project-local .jfl directory
46
+ * @param projectRoot - Absolute path to project root
47
+ */
48
+ export declare function getProjectJflDir(projectRoot: string): string;
49
+ /**
50
+ * Get project-local .jfl file
51
+ * @param projectRoot - Absolute path to project root
52
+ * @param filename - File within .jfl/ directory
53
+ */
54
+ export declare function getProjectJflFile(projectRoot: string, filename: string): string;
55
+ //# sourceMappingURL=jfl-paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jfl-paths.d.ts","sourceRoot":"","sources":["../../src/utils/jfl-paths.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAoCH;;;GAGG;AACH,eAAO,MAAM,SAAS;;;;;CAYZ,CAAA;AAEV;;GAEG;AACH,eAAO,MAAM,SAAS;;;;;;;;;CAcZ,CAAA;AAEV;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,QAAQ,GAAG,UAAU,CAOnE;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAepC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE/E"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Centralized JFL directory path management
3
+ *
4
+ * @purpose Single source of truth for all JFL paths (global and project-local)
5
+ * @spec Implements XDG Base Directory Specification
6
+ */
7
+ import { homedir, platform } from 'os';
8
+ import { join } from 'path';
9
+ import * as fs from 'fs';
10
+ /**
11
+ * Get XDG config home directory (cross-platform)
12
+ */
13
+ function getConfigHome() {
14
+ if (platform() === 'win32') {
15
+ return process.env.APPDATA || join(homedir(), 'AppData', 'Roaming');
16
+ }
17
+ return process.env.XDG_CONFIG_HOME || join(homedir(), '.config');
18
+ }
19
+ /**
20
+ * Get XDG data home directory (cross-platform)
21
+ */
22
+ function getDataHome() {
23
+ if (platform() === 'win32') {
24
+ return process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local');
25
+ }
26
+ return process.env.XDG_DATA_HOME || join(homedir(), '.local', 'share');
27
+ }
28
+ /**
29
+ * Get XDG cache home directory (cross-platform)
30
+ */
31
+ function getCacheHome() {
32
+ if (platform() === 'win32') {
33
+ return join(process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local'), 'cache');
34
+ }
35
+ return process.env.XDG_CACHE_HOME || join(homedir(), '.cache');
36
+ }
37
+ /**
38
+ * XDG Base Directory paths for JFL
39
+ * Respects XDG environment variables, falls back to defaults
40
+ */
41
+ export const JFL_PATHS = {
42
+ // XDG Config Home: ~/.config/jfl/ (or %APPDATA%/jfl/ on Windows)
43
+ config: join(getConfigHome(), 'jfl'),
44
+ // XDG Data Home: ~/.local/share/jfl/ (or %LOCALAPPDATA%/jfl/ on Windows)
45
+ data: join(getDataHome(), 'jfl'),
46
+ // XDG Cache Home: ~/.cache/jfl/ (or %LOCALAPPDATA%/cache/jfl/ on Windows)
47
+ cache: join(getCacheHome(), 'jfl'),
48
+ // Legacy path (for migration detection)
49
+ legacy: join(homedir(), '.jfl'),
50
+ };
51
+ /**
52
+ * Specific file paths within JFL directories
53
+ */
54
+ export const JFL_FILES = {
55
+ // Config files
56
+ config: join(JFL_PATHS.config, 'config.json'),
57
+ auth: join(JFL_PATHS.config, 'auth.json'),
58
+ // Data files
59
+ sessions: join(JFL_PATHS.data, 'sessions.json'),
60
+ servicesDir: join(JFL_PATHS.data, 'services'),
61
+ servicesRegistry: join(JFL_PATHS.data, 'services', 'registry.json'),
62
+ servicesLogs: join(JFL_PATHS.data, 'services', 'logs'),
63
+ servicesPids: join(JFL_PATHS.data, 'services', 'pids'),
64
+ // Cache files
65
+ updateCheck: join(JFL_PATHS.cache, 'last-update-check'),
66
+ };
67
+ /**
68
+ * Check if legacy ~/.jfl/ exists (needs migration)
69
+ */
70
+ export function hasLegacyJflDir() {
71
+ return fs.existsSync(JFL_PATHS.legacy);
72
+ }
73
+ /**
74
+ * Get migration status
75
+ * Returns: 'none' | 'needed' | 'complete'
76
+ */
77
+ export function getMigrationStatus() {
78
+ const hasLegacy = hasLegacyJflDir();
79
+ const hasNew = fs.existsSync(JFL_PATHS.config);
80
+ if (!hasLegacy && !hasNew)
81
+ return 'none';
82
+ if (hasLegacy && !hasNew)
83
+ return 'needed';
84
+ return 'complete';
85
+ }
86
+ /**
87
+ * Ensure JFL directories exist
88
+ * Creates XDG-compliant directory structure
89
+ */
90
+ export function ensureJflDirs() {
91
+ const dirs = [
92
+ JFL_PATHS.config,
93
+ JFL_PATHS.data,
94
+ JFL_PATHS.cache,
95
+ JFL_FILES.servicesDir,
96
+ JFL_FILES.servicesLogs,
97
+ JFL_FILES.servicesPids,
98
+ ];
99
+ for (const dir of dirs) {
100
+ if (!fs.existsSync(dir)) {
101
+ fs.mkdirSync(dir, { recursive: true });
102
+ }
103
+ }
104
+ }
105
+ /**
106
+ * Get project-local .jfl directory
107
+ * @param projectRoot - Absolute path to project root
108
+ */
109
+ export function getProjectJflDir(projectRoot) {
110
+ return join(projectRoot, '.jfl');
111
+ }
112
+ /**
113
+ * Get project-local .jfl file
114
+ * @param projectRoot - Absolute path to project root
115
+ * @param filename - File within .jfl/ directory
116
+ */
117
+ export function getProjectJflFile(projectRoot, filename) {
118
+ return join(projectRoot, '.jfl', filename);
119
+ }
120
+ //# sourceMappingURL=jfl-paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jfl-paths.js","sourceRoot":"","sources":["../../src/utils/jfl-paths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Claude Code Settings Validator
3
+ *
4
+ * Validates and auto-fixes .claude/settings.json files to ensure compliance
5
+ * with Claude Code's schema requirements.
6
+ *
7
+ * @purpose Validate and repair Claude Code settings files
8
+ */
9
+ export interface ValidationError {
10
+ hook: string;
11
+ index: number;
12
+ error: string;
13
+ fix?: string;
14
+ }
15
+ export interface SettingsSchema {
16
+ hooks?: {
17
+ [hookName: string]: HookEntry[];
18
+ };
19
+ }
20
+ export interface HookEntry {
21
+ matcher: string;
22
+ hooks: HookCommand[];
23
+ }
24
+ export interface HookCommand {
25
+ type: string;
26
+ command: string;
27
+ args?: string[];
28
+ async?: boolean;
29
+ }
30
+ /**
31
+ * Validates a Claude Code settings object for schema compliance
32
+ *
33
+ * Checks for:
34
+ * 1. Missing `matcher` fields (Bug 1)
35
+ * 2. Invalid `:service` suffixes on hook names (Bug 2)
36
+ * 3. Flat object format instead of array (Bug 3)
37
+ * 4. Required hook command fields
38
+ * 5. Context-hub stop in Stop hook (should never stop shared service)
39
+ * 6. Exit 0 that masks hook failures (warning only)
40
+ *
41
+ * @param settings - The settings object to validate
42
+ * @returns Array of validation errors (empty if valid)
43
+ */
44
+ export declare function validateSettings(settings: any): ValidationError[];
45
+ /**
46
+ * Auto-fixes common settings schema violations
47
+ *
48
+ * Fixes:
49
+ * 1. Adds missing `matcher: ""` fields
50
+ * 2. Removes `:service` suffixes from hook names
51
+ * 3. Converts flat objects to proper array format
52
+ * 4. Removes context-hub stop from Stop hook
53
+ * 5. Preserves all existing valid configuration
54
+ *
55
+ * @param settings - The settings object to fix
56
+ * @returns Fixed settings object
57
+ */
58
+ export declare function fixSettings(settings: any): SettingsSchema;
59
+ /**
60
+ * Validates and returns a detailed report
61
+ *
62
+ * @param settings - The settings object to validate
63
+ * @returns Human-readable validation report
64
+ */
65
+ export declare function getValidationReport(settings: any): string;
66
+ /**
67
+ * Quick check if settings are valid
68
+ *
69
+ * @param settings - The settings object to check
70
+ * @returns true if valid, false otherwise
71
+ */
72
+ export declare function isValid(settings: any): boolean;
73
+ //# sourceMappingURL=settings-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-validator.d.ts","sourceRoot":"","sources":["../../src/utils/settings-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE;QACN,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,CAAC;KACjC,CAAC;CACH;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,GAAG,GAAG,eAAe,EAAE,CAuGjE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,GAAG,GAAG,cAAc,CA2DzD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,GAAG,GAAG,MAAM,CA6BzD;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAE9C"}
@@ -0,0 +1,222 @@
1
+ /**
2
+ * Claude Code Settings Validator
3
+ *
4
+ * Validates and auto-fixes .claude/settings.json files to ensure compliance
5
+ * with Claude Code's schema requirements.
6
+ *
7
+ * @purpose Validate and repair Claude Code settings files
8
+ */
9
+ /**
10
+ * Validates a Claude Code settings object for schema compliance
11
+ *
12
+ * Checks for:
13
+ * 1. Missing `matcher` fields (Bug 1)
14
+ * 2. Invalid `:service` suffixes on hook names (Bug 2)
15
+ * 3. Flat object format instead of array (Bug 3)
16
+ * 4. Required hook command fields
17
+ * 5. Context-hub stop in Stop hook (should never stop shared service)
18
+ * 6. Exit 0 that masks hook failures (warning only)
19
+ *
20
+ * @param settings - The settings object to validate
21
+ * @returns Array of validation errors (empty if valid)
22
+ */
23
+ export function validateSettings(settings) {
24
+ const errors = [];
25
+ if (!settings || typeof settings !== 'object') {
26
+ errors.push({
27
+ hook: 'root',
28
+ index: 0,
29
+ error: 'Settings must be an object',
30
+ });
31
+ return errors;
32
+ }
33
+ const hooks = settings.hooks;
34
+ if (!hooks || typeof hooks !== 'object') {
35
+ errors.push({
36
+ hook: 'root',
37
+ index: 0,
38
+ error: 'Settings must have a "hooks" object',
39
+ });
40
+ return errors;
41
+ }
42
+ // Validate each hook event
43
+ for (const [hookName, hookValue] of Object.entries(hooks)) {
44
+ // Bug 2: Check for :service suffix
45
+ if (hookName.includes(':')) {
46
+ errors.push({
47
+ hook: hookName,
48
+ index: 0,
49
+ error: `Hook name contains invalid ":service" suffix: "${hookName}"`,
50
+ fix: `Remove suffix, use "${hookName.split(':')[0]}" instead`,
51
+ });
52
+ }
53
+ // Bug 3: Check if value is array
54
+ if (!Array.isArray(hookValue)) {
55
+ errors.push({
56
+ hook: hookName,
57
+ index: 0,
58
+ error: `Hook value must be an array, got ${typeof hookValue}`,
59
+ fix: 'Wrap in array with {matcher, hooks} structure',
60
+ });
61
+ continue;
62
+ }
63
+ // Validate each entry in the hook array
64
+ hookValue.forEach((entry, index) => {
65
+ // Bug 1: Check for missing matcher
66
+ if (!('matcher' in entry)) {
67
+ errors.push({
68
+ hook: hookName,
69
+ index,
70
+ error: 'Hook entry missing required "matcher" field',
71
+ fix: 'Add "matcher": "" for lifecycle hooks, or pattern string for conditional hooks',
72
+ });
73
+ }
74
+ // Check for hooks array
75
+ if (!Array.isArray(entry.hooks)) {
76
+ errors.push({
77
+ hook: hookName,
78
+ index,
79
+ error: 'Hook entry missing required "hooks" array',
80
+ });
81
+ }
82
+ else {
83
+ // Validate individual hook commands
84
+ entry.hooks.forEach((cmd, cmdIndex) => {
85
+ if (!cmd.type) {
86
+ errors.push({
87
+ hook: hookName,
88
+ index,
89
+ error: `Hook command ${cmdIndex} missing "type" field`,
90
+ });
91
+ }
92
+ if (!cmd.command) {
93
+ errors.push({
94
+ hook: hookName,
95
+ index,
96
+ error: `Hook command ${cmdIndex} missing "command" field`,
97
+ });
98
+ }
99
+ // Check for context-hub stop in Stop hook (common bug)
100
+ if (hookName === 'Stop' && cmd.type === 'command' && cmd.command?.includes('jfl context-hub stop')) {
101
+ errors.push({
102
+ hook: hookName,
103
+ index,
104
+ error: 'Stop hook should NOT stop context-hub (shared service across sessions)',
105
+ fix: 'Remove "jfl context-hub stop" command from Stop hook',
106
+ });
107
+ }
108
+ // Warn about exit 0 that prevents blocking (not an error, just a warning)
109
+ if (cmd.type === 'command' && cmd.command?.includes('exit 0')) {
110
+ // This is a design limitation note, not an error
111
+ // We'll add this to validation report but won't block
112
+ }
113
+ });
114
+ }
115
+ });
116
+ }
117
+ return errors;
118
+ }
119
+ /**
120
+ * Auto-fixes common settings schema violations
121
+ *
122
+ * Fixes:
123
+ * 1. Adds missing `matcher: ""` fields
124
+ * 2. Removes `:service` suffixes from hook names
125
+ * 3. Converts flat objects to proper array format
126
+ * 4. Removes context-hub stop from Stop hook
127
+ * 5. Preserves all existing valid configuration
128
+ *
129
+ * @param settings - The settings object to fix
130
+ * @returns Fixed settings object
131
+ */
132
+ export function fixSettings(settings) {
133
+ if (!settings || typeof settings !== 'object') {
134
+ return { hooks: {} };
135
+ }
136
+ const fixed = {
137
+ hooks: {},
138
+ };
139
+ const hooks = settings.hooks || {};
140
+ for (const [hookName, hookValue] of Object.entries(hooks)) {
141
+ // Bug 2: Remove :service suffix
142
+ const cleanHookName = hookName.split(':')[0];
143
+ // Bug 3: Ensure array format
144
+ let hookArray;
145
+ if (!Array.isArray(hookValue)) {
146
+ // Convert flat object to array format
147
+ hookArray = [hookValue];
148
+ }
149
+ else {
150
+ hookArray = [...hookValue];
151
+ }
152
+ // Bug 1: Add missing matcher fields
153
+ // Bug 4: Remove context-hub stop from Stop hook
154
+ const fixedEntries = hookArray.map((entry) => {
155
+ if (!entry || typeof entry !== 'object') {
156
+ return entry;
157
+ }
158
+ const fixedEntry = { ...entry };
159
+ // Add matcher if missing
160
+ if (!('matcher' in fixedEntry)) {
161
+ // For lifecycle hooks (SessionStart, Stop, PreCompact), use empty string
162
+ // For tool/prompt hooks, preserve any existing pattern or default to empty
163
+ fixedEntry.matcher = '';
164
+ }
165
+ // Remove context-hub stop from Stop hook commands
166
+ if (cleanHookName === 'Stop' && Array.isArray(fixedEntry.hooks)) {
167
+ fixedEntry.hooks = fixedEntry.hooks.filter((cmd) => {
168
+ return !(cmd.type === 'command' && cmd.command?.includes('jfl context-hub stop'));
169
+ });
170
+ }
171
+ return fixedEntry;
172
+ });
173
+ if (!fixed.hooks) {
174
+ fixed.hooks = {};
175
+ }
176
+ fixed.hooks[cleanHookName] = fixedEntries;
177
+ }
178
+ // Preserve any other top-level settings
179
+ const result = { ...settings, hooks: fixed.hooks };
180
+ return result;
181
+ }
182
+ /**
183
+ * Validates and returns a detailed report
184
+ *
185
+ * @param settings - The settings object to validate
186
+ * @returns Human-readable validation report
187
+ */
188
+ export function getValidationReport(settings) {
189
+ const errors = validateSettings(settings);
190
+ if (errors.length === 0) {
191
+ return '✓ Settings are valid';
192
+ }
193
+ const lines = ['⚠️ Settings validation errors found:\n'];
194
+ const grouped = errors.reduce((acc, err) => {
195
+ if (!acc[err.hook]) {
196
+ acc[err.hook] = [];
197
+ }
198
+ acc[err.hook].push(err);
199
+ return acc;
200
+ }, {});
201
+ for (const [hook, hookErrors] of Object.entries(grouped)) {
202
+ lines.push(` ${hook}:`);
203
+ hookErrors.forEach(err => {
204
+ lines.push(` - ${err.error}`);
205
+ if (err.fix) {
206
+ lines.push(` Fix: ${err.fix}`);
207
+ }
208
+ });
209
+ lines.push('');
210
+ }
211
+ return lines.join('\n');
212
+ }
213
+ /**
214
+ * Quick check if settings are valid
215
+ *
216
+ * @param settings - The settings object to check
217
+ * @returns true if valid, false otherwise
218
+ */
219
+ export function isValid(settings) {
220
+ return validateSettings(settings).length === 0;
221
+ }
222
+ //# sourceMappingURL=settings-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-validator.js","sourceRoot":"","sources":["../../src/utils/settings-validator.ts"],"names":[],"mappings":"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"}