jfl 0.9.6 → 0.9.8

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 (212) hide show
  1. package/dist/commands/agents.js +1 -1
  2. package/dist/commands/agents.js.map +1 -1
  3. package/dist/commands/context-hub.d.ts.map +1 -1
  4. package/dist/commands/context-hub.js +77 -18
  5. package/dist/commands/context-hub.js.map +1 -1
  6. package/dist/commands/deploy.js +1 -1
  7. package/dist/commands/deploy.js.map +1 -1
  8. package/dist/commands/feedback.js +1 -1
  9. package/dist/commands/feedback.js.map +1 -1
  10. package/dist/commands/hud.js +1 -1
  11. package/dist/commands/hud.js.map +1 -1
  12. package/dist/commands/init-from-service.js +1 -1
  13. package/dist/commands/init-from-service.js.map +1 -1
  14. package/dist/commands/init.js +1 -1
  15. package/dist/commands/init.js.map +1 -1
  16. package/dist/commands/kanban.js +6 -6
  17. package/dist/commands/kanban.js.map +1 -1
  18. package/dist/commands/login.d.ts +2 -13
  19. package/dist/commands/login.d.ts.map +1 -1
  20. package/dist/commands/login.js +6 -44
  21. package/dist/commands/login.js.map +1 -1
  22. package/dist/commands/organize.d.ts +16 -0
  23. package/dist/commands/organize.d.ts.map +1 -0
  24. package/dist/commands/organize.js +334 -0
  25. package/dist/commands/organize.js.map +1 -0
  26. package/dist/commands/peter.d.ts.map +1 -1
  27. package/dist/commands/peter.js +273 -0
  28. package/dist/commands/peter.js.map +1 -1
  29. package/dist/commands/pi.d.ts.map +1 -1
  30. package/dist/commands/pi.js +11 -5
  31. package/dist/commands/pi.js.map +1 -1
  32. package/dist/commands/repair.js +1 -1
  33. package/dist/commands/repair.js.map +1 -1
  34. package/dist/commands/setup.d.ts.map +1 -1
  35. package/dist/commands/setup.js +113 -45
  36. package/dist/commands/setup.js.map +1 -1
  37. package/dist/commands/status.d.ts.map +1 -1
  38. package/dist/commands/status.js +4 -4
  39. package/dist/commands/status.js.map +1 -1
  40. package/dist/commands/update.d.ts.map +1 -1
  41. package/dist/commands/update.js +66 -0
  42. package/dist/commands/update.js.map +1 -1
  43. package/dist/index.d.ts +0 -6
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +60 -19
  46. package/dist/index.js.map +1 -1
  47. package/dist/lib/agent-config.d.ts.map +1 -1
  48. package/dist/lib/agent-config.js +24 -2
  49. package/dist/lib/agent-config.js.map +1 -1
  50. package/dist/lib/hub-health.d.ts.map +1 -1
  51. package/dist/lib/hub-health.js +14 -2
  52. package/dist/lib/hub-health.js.map +1 -1
  53. package/dist/lib/resource-optimizer-middleware.d.ts.map +1 -1
  54. package/dist/lib/resource-optimizer-middleware.js +8 -2
  55. package/dist/lib/resource-optimizer-middleware.js.map +1 -1
  56. package/dist/lib/telemetry.d.ts.map +1 -1
  57. package/dist/lib/telemetry.js +13 -12
  58. package/dist/lib/telemetry.js.map +1 -1
  59. package/dist/utils/auth-status.d.ts +21 -0
  60. package/dist/utils/auth-status.d.ts.map +1 -0
  61. package/dist/utils/auth-status.js +53 -0
  62. package/dist/utils/auth-status.js.map +1 -0
  63. package/package.json +3 -2
  64. package/packages/pi/dist/agent-grid.d.ts +24 -0
  65. package/packages/pi/dist/agent-grid.d.ts.map +1 -0
  66. package/packages/pi/dist/agent-grid.js +162 -0
  67. package/packages/pi/dist/agent-grid.js.map +1 -0
  68. package/packages/pi/dist/agent-names.d.ts +43 -0
  69. package/packages/pi/dist/agent-names.d.ts.map +1 -0
  70. package/packages/pi/dist/agent-names.js +156 -0
  71. package/packages/pi/dist/agent-names.js.map +1 -0
  72. package/packages/pi/dist/autoresearch.d.ts +15 -0
  73. package/packages/pi/dist/autoresearch.d.ts.map +1 -0
  74. package/packages/pi/dist/autoresearch.js +372 -0
  75. package/packages/pi/dist/autoresearch.js.map +1 -0
  76. package/packages/pi/dist/bookmarks.d.ts +15 -0
  77. package/packages/pi/dist/bookmarks.d.ts.map +1 -0
  78. package/packages/pi/dist/bookmarks.js +77 -0
  79. package/packages/pi/dist/bookmarks.js.map +1 -0
  80. package/packages/pi/dist/context.d.ts +17 -0
  81. package/packages/pi/dist/context.d.ts.map +1 -0
  82. package/packages/pi/dist/context.js +152 -0
  83. package/packages/pi/dist/context.js.map +1 -0
  84. package/packages/pi/dist/crm-tool.d.ts +12 -0
  85. package/packages/pi/dist/crm-tool.d.ts.map +1 -0
  86. package/packages/pi/dist/crm-tool.js +58 -0
  87. package/packages/pi/dist/crm-tool.js.map +1 -0
  88. package/packages/pi/dist/eval-tool.d.ts +11 -0
  89. package/packages/pi/dist/eval-tool.d.ts.map +1 -0
  90. package/packages/pi/dist/eval-tool.js +188 -0
  91. package/packages/pi/dist/eval-tool.js.map +1 -0
  92. package/packages/pi/dist/eval.d.ts +12 -0
  93. package/packages/pi/dist/eval.d.ts.map +1 -0
  94. package/packages/pi/dist/eval.js +43 -0
  95. package/packages/pi/dist/eval.js.map +1 -0
  96. package/packages/pi/dist/footer.d.ts +20 -0
  97. package/packages/pi/dist/footer.d.ts.map +1 -0
  98. package/packages/pi/dist/footer.js +222 -0
  99. package/packages/pi/dist/footer.js.map +1 -0
  100. package/packages/pi/dist/header.d.ts +17 -0
  101. package/packages/pi/dist/header.d.ts.map +1 -0
  102. package/packages/pi/dist/header.js +156 -0
  103. package/packages/pi/dist/header.js.map +1 -0
  104. package/packages/pi/dist/hub-resolver.d.ts +11 -0
  105. package/packages/pi/dist/hub-resolver.d.ts.map +1 -0
  106. package/packages/pi/dist/hub-resolver.js +58 -0
  107. package/packages/pi/dist/hub-resolver.js.map +1 -0
  108. package/packages/pi/dist/hub-tools.d.ts +14 -0
  109. package/packages/pi/dist/hub-tools.d.ts.map +1 -0
  110. package/packages/pi/dist/hub-tools.js +266 -0
  111. package/packages/pi/dist/hub-tools.js.map +1 -0
  112. package/packages/pi/dist/hud-tool.d.ts +17 -0
  113. package/packages/pi/dist/hud-tool.d.ts.map +1 -0
  114. package/packages/pi/dist/hud-tool.js +297 -0
  115. package/packages/pi/dist/hud-tool.js.map +1 -0
  116. package/packages/pi/dist/index.d.ts +12 -0
  117. package/packages/pi/dist/index.d.ts.map +1 -0
  118. package/packages/pi/dist/index.js +436 -0
  119. package/packages/pi/dist/index.js.map +1 -0
  120. package/packages/pi/dist/jfl-resolve.d.ts +29 -0
  121. package/packages/pi/dist/jfl-resolve.d.ts.map +1 -0
  122. package/packages/pi/dist/jfl-resolve.js +89 -0
  123. package/packages/pi/dist/jfl-resolve.js.map +1 -0
  124. package/packages/pi/dist/journal.d.ts +23 -0
  125. package/packages/pi/dist/journal.d.ts.map +1 -0
  126. package/packages/pi/dist/journal.js +250 -0
  127. package/packages/pi/dist/journal.js.map +1 -0
  128. package/packages/pi/dist/map-bridge.d.ts +20 -0
  129. package/packages/pi/dist/map-bridge.d.ts.map +1 -0
  130. package/packages/pi/dist/map-bridge.js +181 -0
  131. package/packages/pi/dist/map-bridge.js.map +1 -0
  132. package/packages/pi/dist/memory-tool.d.ts +11 -0
  133. package/packages/pi/dist/memory-tool.d.ts.map +1 -0
  134. package/packages/pi/dist/memory-tool.js +148 -0
  135. package/packages/pi/dist/memory-tool.js.map +1 -0
  136. package/packages/pi/dist/notifications.d.ts +15 -0
  137. package/packages/pi/dist/notifications.d.ts.map +1 -0
  138. package/packages/pi/dist/notifications.js +65 -0
  139. package/packages/pi/dist/notifications.js.map +1 -0
  140. package/packages/pi/dist/onboarding-v1.d.ts +15 -0
  141. package/packages/pi/dist/onboarding-v1.d.ts.map +1 -0
  142. package/packages/pi/dist/onboarding-v1.js +417 -0
  143. package/packages/pi/dist/onboarding-v1.js.map +1 -0
  144. package/packages/pi/dist/onboarding-v2.d.ts +18 -0
  145. package/packages/pi/dist/onboarding-v2.d.ts.map +1 -0
  146. package/packages/pi/dist/onboarding-v2.js +402 -0
  147. package/packages/pi/dist/onboarding-v2.js.map +1 -0
  148. package/packages/pi/dist/onboarding-v3.d.ts +13 -0
  149. package/packages/pi/dist/onboarding-v3.d.ts.map +1 -0
  150. package/packages/pi/dist/onboarding-v3.js +581 -0
  151. package/packages/pi/dist/onboarding-v3.js.map +1 -0
  152. package/packages/pi/dist/peter-parker.d.ts +12 -0
  153. package/packages/pi/dist/peter-parker.d.ts.map +1 -0
  154. package/packages/pi/dist/peter-parker.js +162 -0
  155. package/packages/pi/dist/peter-parker.js.map +1 -0
  156. package/packages/pi/dist/pivot-tool.d.ts +11 -0
  157. package/packages/pi/dist/pivot-tool.d.ts.map +1 -0
  158. package/packages/pi/dist/pivot-tool.js +56 -0
  159. package/packages/pi/dist/pivot-tool.js.map +1 -0
  160. package/packages/pi/dist/policy-head-tool.d.ts +15 -0
  161. package/packages/pi/dist/policy-head-tool.d.ts.map +1 -0
  162. package/packages/pi/dist/policy-head-tool.js +220 -0
  163. package/packages/pi/dist/policy-head-tool.js.map +1 -0
  164. package/packages/pi/dist/portfolio-bridge.d.ts +12 -0
  165. package/packages/pi/dist/portfolio-bridge.d.ts.map +1 -0
  166. package/packages/pi/dist/portfolio-bridge.js +81 -0
  167. package/packages/pi/dist/portfolio-bridge.js.map +1 -0
  168. package/packages/pi/dist/service-skills.d.ts +15 -0
  169. package/packages/pi/dist/service-skills.d.ts.map +1 -0
  170. package/packages/pi/dist/service-skills.js +198 -0
  171. package/packages/pi/dist/service-skills.js.map +1 -0
  172. package/packages/pi/dist/session.d.ts +24 -0
  173. package/packages/pi/dist/session.d.ts.map +1 -0
  174. package/packages/pi/dist/session.js +394 -0
  175. package/packages/pi/dist/session.js.map +1 -0
  176. package/packages/pi/dist/shortcuts.d.ts +11 -0
  177. package/packages/pi/dist/shortcuts.d.ts.map +1 -0
  178. package/packages/pi/dist/shortcuts.js +231 -0
  179. package/packages/pi/dist/shortcuts.js.map +1 -0
  180. package/packages/pi/dist/startup-briefing.d.ts +13 -0
  181. package/packages/pi/dist/startup-briefing.d.ts.map +1 -0
  182. package/packages/pi/dist/startup-briefing.js +271 -0
  183. package/packages/pi/dist/startup-briefing.js.map +1 -0
  184. package/packages/pi/dist/stratus-bridge.d.ts +14 -0
  185. package/packages/pi/dist/stratus-bridge.d.ts.map +1 -0
  186. package/packages/pi/dist/stratus-bridge.js +104 -0
  187. package/packages/pi/dist/stratus-bridge.js.map +1 -0
  188. package/packages/pi/dist/subway-mesh.d.ts +88 -0
  189. package/packages/pi/dist/subway-mesh.d.ts.map +1 -0
  190. package/packages/pi/dist/subway-mesh.js +813 -0
  191. package/packages/pi/dist/subway-mesh.js.map +1 -0
  192. package/packages/pi/dist/synopsis-tool.d.ts +12 -0
  193. package/packages/pi/dist/synopsis-tool.d.ts.map +1 -0
  194. package/packages/pi/dist/synopsis-tool.js +84 -0
  195. package/packages/pi/dist/synopsis-tool.js.map +1 -0
  196. package/packages/pi/dist/tool-renderers.d.ts +55 -0
  197. package/packages/pi/dist/tool-renderers.d.ts.map +1 -0
  198. package/packages/pi/dist/tool-renderers.js +349 -0
  199. package/packages/pi/dist/tool-renderers.js.map +1 -0
  200. package/packages/pi/dist/training-buffer-tool.d.ts +16 -0
  201. package/packages/pi/dist/training-buffer-tool.d.ts.map +1 -0
  202. package/packages/pi/dist/training-buffer-tool.js +319 -0
  203. package/packages/pi/dist/training-buffer-tool.js.map +1 -0
  204. package/packages/pi/dist/types.d.ts +195 -0
  205. package/packages/pi/dist/types.d.ts.map +1 -0
  206. package/packages/pi/dist/types.js +11 -0
  207. package/packages/pi/dist/types.js.map +1 -0
  208. package/packages/pi/extensions/session.ts +115 -8
  209. package/packages/pi/extensions/training-buffer-tool.ts +15 -8
  210. package/packages/pi/extensions/types.ts +1 -0
  211. package/packages/pi/package.json +2 -3
  212. package/scripts/postinstall.js +52 -4
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { execSync, spawn } from "child_process"
13
- import { existsSync, readFileSync } from "fs"
13
+ import { existsSync, readFileSync, writeFileSync } from "fs"
14
14
  import { join } from "path"
15
15
  import type { PiContext, JflConfig } from "./types.js"
16
16
  import { hubUrl, authToken } from "./map-bridge.js"
@@ -18,6 +18,104 @@ import { hubUrl, authToken } from "./map-bridge.js"
18
18
  let autoCommitProcess: ReturnType<typeof spawn> | null = null
19
19
  let sessionBranch = ""
20
20
 
21
+ /**
22
+ * Create a session branch locally without the Hub.
23
+ * Parity with scripts/session/session-init.sh:
24
+ * 1. Commit or stash dirty state
25
+ * 2. If on a stale session branch, try to switch to working branch
26
+ * 3. Create new session branch from clean base
27
+ * 4. Pop stash if needed
28
+ */
29
+ function createSessionBranchLocally(root: string, ctx: { log: (msg: string, level?: "debug" | "info" | "warn" | "error") => void; ui: { notify: (msg: string, opts?: any) => void } }): string {
30
+ // Generate session branch name
31
+ const user = (() => {
32
+ try {
33
+ return execSync("git config user.name", { cwd: root, stdio: ["pipe", "pipe", "pipe"] })
34
+ .toString().trim().replace(/\s+/g, "-").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 30) || "user"
35
+ } catch { return "user" }
36
+ })()
37
+ const now = new Date()
38
+ const dateStr = now.toISOString().slice(0, 10).replace(/-/g, "")
39
+ const timeStr = now.toISOString().slice(11, 16).replace(":", "")
40
+ const randomId = Math.random().toString(16).slice(2, 8)
41
+ const branchName = `session-${user}-${dateStr}-${timeStr}-${randomId}`
42
+
43
+ // Get working branch from config
44
+ let workingBranch = "main"
45
+ const configPath = join(root, ".jfl", "config.json")
46
+ if (existsSync(configPath)) {
47
+ try {
48
+ const cfg = JSON.parse(readFileSync(configPath, "utf-8"))
49
+ if (cfg.working_branch) workingBranch = cfg.working_branch
50
+ } catch {}
51
+ }
52
+
53
+ // Step 1: Commit or stash dirty state so checkout doesn't fail
54
+ let stashed = false
55
+ try {
56
+ const status = execSync("git status --porcelain", { cwd: root, timeout: 5000, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim()
57
+ if (status) {
58
+ try {
59
+ execSync("git add -A && git commit -m 'auto: session-init save before branch switch' --no-verify", { cwd: root, timeout: 10000, stdio: ["pipe", "pipe", "pipe"] })
60
+ } catch {
61
+ // Commit failed — stash instead
62
+ try {
63
+ execSync("git stash push -m 'jfl-session-init-stash' --include-untracked", { cwd: root, timeout: 10000, stdio: ["pipe", "pipe", "pipe"] })
64
+ stashed = true
65
+ } catch {}
66
+ }
67
+ }
68
+ } catch {}
69
+
70
+ // Step 2: If on a stale session branch, try to switch to working branch
71
+ const currentBranch = getCurrentBranch(root)
72
+ if (currentBranch.startsWith("session-")) {
73
+ try {
74
+ execSync(`git checkout "${workingBranch}"`, { cwd: root, timeout: 10000, stdio: ["pipe", "pipe", "pipe"] })
75
+ ctx.log(`Switched from stale session branch ${currentBranch} → ${workingBranch}`, "info")
76
+ } catch {
77
+ ctx.log(`Could not switch from ${currentBranch} — branching from it`, "warn")
78
+ }
79
+ }
80
+
81
+ // Step 3: Create new session branch
82
+ let finalBranch = branchName
83
+ try {
84
+ execSync(`git checkout -b "${branchName}"`, { cwd: root, stdio: ["pipe", "pipe", "pipe"] })
85
+ ctx.ui.notify(`Session branch: ${branchName}`, { level: "info" })
86
+ } catch {
87
+ // Branch name collision — retry with longer ID
88
+ const fallbackId = Math.random().toString(16).slice(2, 14)
89
+ const fallbackBranch = `session-${user}-${dateStr}-${timeStr}-${fallbackId}`
90
+ try {
91
+ execSync(`git checkout -b "${fallbackBranch}"`, { cwd: root, stdio: ["pipe", "pipe", "pipe"] })
92
+ finalBranch = fallbackBranch
93
+ } catch {
94
+ // Give up — use current branch
95
+ finalBranch = getCurrentBranch(root)
96
+ ctx.log(`Could not create session branch — using ${finalBranch}`, "warn")
97
+ ctx.ui.notify(`Branch creation failed — using ${finalBranch}`, { level: "warn" })
98
+ }
99
+ }
100
+
101
+ // Step 4: Pop stash if we stashed
102
+ if (stashed) {
103
+ try {
104
+ execSync("git stash pop", { cwd: root, timeout: 10000, stdio: ["pipe", "pipe", "pipe"] })
105
+ } catch {
106
+ ctx.log("Could not pop stash — run 'git stash pop' manually", "warn")
107
+ }
108
+ }
109
+
110
+ // Save session info
111
+ try {
112
+ const jflDir = join(root, ".jfl")
113
+ writeFileSync(join(jflDir, "current-session-branch.txt"), finalBranch)
114
+ } catch {}
115
+
116
+ return finalBranch
117
+ }
118
+
21
119
  function findScript(root: string, scriptName: string): string | null {
22
120
  const candidates = [
23
121
  join(root, "scripts", "session", scriptName),
@@ -46,26 +144,35 @@ export async function setupSession(ctx: PiContext, _config: JflConfig): Promise<
46
144
 
47
145
  if (resp.ok) {
48
146
  const data = await resp.json() as { branch?: string; syncOk?: boolean; warnings?: string[]; doctor?: { errors: number; warnings: number } }
49
- sessionBranch = data.branch ?? ctx.session.branch
50
147
  if (data.warnings?.length) {
51
148
  for (const w of data.warnings) ctx.log(w, "warn")
52
149
  }
53
150
  if (data.doctor?.errors) {
54
151
  ctx.ui.notify(`Doctor: ${data.doctor.errors} errors`, { level: "warn" })
55
152
  }
56
- ctx.log(`Session init via Hub: branch=${sessionBranch}, sync=${data.syncOk}`, "debug")
153
+
154
+ // Hub may return 200 OK but fail to create a branch (dirty state, etc).
155
+ // If branch is missing or is the working branch (main), fall back to local creation.
156
+ const hubBranch = data.branch ?? ""
157
+ if (hubBranch.startsWith("session-")) {
158
+ sessionBranch = hubBranch
159
+ ctx.log(`Session init via Hub: branch=${sessionBranch}, sync=${data.syncOk}`, "debug")
160
+ } else {
161
+ ctx.log(`Hub returned non-session branch "${hubBranch}" — creating locally`, "warn")
162
+ sessionBranch = createSessionBranchLocally(root, ctx)
163
+ }
57
164
  } else {
58
165
  const errText = await resp.text().catch(() => "unknown")
59
166
  ctx.log(`Hub session init failed (${resp.status}): ${errText}`, "warn")
60
- ctx.ui.notify("Session init failed — working on current branch", { level: "warn" })
61
- sessionBranch = ctx.session.branch
167
+ sessionBranch = createSessionBranchLocally(root, ctx)
62
168
  }
63
169
  } catch (err) {
64
- // Hub not available — fall back to local branch detection
170
+ // Hub not available — create session branch locally (parity with session-init.sh)
65
171
  const msg = err instanceof Error ? err.message : String(err)
66
172
  ctx.log(`Hub unavailable for session init: ${msg}`, "warn")
67
- ctx.ui.notify(`Hub unreachable (${hubUrl}) no session branch created`, { level: "warn" })
68
- sessionBranch = ctx.session.branch
173
+ ctx.ui.notify(`Hub unreachable — creating session branch locally`, { level: "warn" })
174
+
175
+ sessionBranch = createSessionBranchLocally(root, ctx)
69
176
  }
70
177
 
71
178
  // Start auto-commit daemon — must be local (detached process)
@@ -317,18 +317,23 @@ export async function onTrainingAgentEnd(
317
317
  event: AgentEndEvent
318
318
  ): Promise<void> {
319
319
  const turnCount = event.messages?.length ?? event.turnCount ?? 0
320
- if (turnCount < 2) return
320
+ // Only log tuples when actual work happened (files changed).
321
+ // Previously this logged every session as "improved" with a fake +0.01 delta,
322
+ // polluting the training buffer with 187+ garbage noops.
323
+ const filesChanged = event.filesChanged || []
324
+ if (turnCount < 2 || filesChanged.length === 0) return
321
325
 
322
326
  const tb = await getTrainingBuffer()
323
327
  if (!tb) return
324
328
 
325
329
  const existing: any[] = tb.read()
326
- const recentDeltas = existing.slice(-10).map((e: any) => e.reward.composite_delta)
327
- const currentScore = existing.length > 0
328
- ? existing[existing.length - 1].state.composite_score + existing[existing.length - 1].reward.composite_delta
330
+ // Safe access reward or composite_delta may be missing on older entries
331
+ const recentDeltas = existing.slice(-10).map((e: any) => e.reward?.composite_delta ?? 0)
332
+ const lastEntry = existing.length > 0 ? existing[existing.length - 1] : null
333
+ const currentScore = lastEntry
334
+ ? (lastEntry.state?.composite_score ?? 0) + (lastEntry.reward?.composite_delta ?? 0)
329
335
  : 0
330
336
 
331
- const filesChanged = event.filesChanged || []
332
337
  const exitReason = event.exitReason as string | undefined
333
338
  const isSuccess = exitReason !== "error" && exitReason !== "timeout"
334
339
 
@@ -353,11 +358,13 @@ export async function onTrainingAgentEnd(
353
358
  branch: ctx.session.branch,
354
359
  },
355
360
  reward: {
356
- composite_delta: isSuccess ? 0.01 : -0.005,
361
+ // Don't fabricate deltas — use 0 to indicate "no eval ran".
362
+ // Real deltas come from the RL agent loop (peter daily), not session logging.
363
+ composite_delta: 0,
357
364
  dimension_deltas: {},
358
365
  tests_added: 0,
359
- quality_score: isSuccess ? 0.7 : 0.3,
360
- improved: isSuccess,
366
+ quality_score: isSuccess ? 0.5 : 0.3,
367
+ improved: false, // Only the RL eval loop can determine improvement
361
368
  },
362
369
  metadata: {
363
370
  branch: ctx.session.branch,
@@ -162,6 +162,7 @@ export interface JflConfig {
162
162
  disable_shortcuts?: boolean
163
163
  disable_notifications?: boolean
164
164
  disable_onboarding?: boolean
165
+ disable_briefing?: boolean
165
166
  onboarding_variant?: "v1" | "v2" | "v3"
166
167
  auto_start?: boolean
167
168
  }
@@ -37,9 +37,8 @@
37
37
  "typescript": "^5.3.3"
38
38
  },
39
39
  "pi": {
40
-
41
- "entry": "dist/index.js",
42
- "extensions": ["dist/index.js"],
40
+ "entry": "extensions/index.ts",
41
+ "extensions": ["extensions/index.ts"],
43
42
  "skills": "skills",
44
43
  "themes": "themes/jfl.theme.json",
45
44
  "teams": "teams"
@@ -13,6 +13,13 @@ import { execSync, spawnSync } from "child_process";
13
13
  import { platform } from "os";
14
14
 
15
15
  const TOOLS = [
16
+ {
17
+ name: "pi",
18
+ package: "@mariozechner/pi-coding-agent",
19
+ description: "Pi coding agent runtime",
20
+ requiresBun: false,
21
+ minVersion: "0.57.0",
22
+ },
16
23
  {
17
24
  name: "ralph-tui",
18
25
  package: "ralph-tui",
@@ -50,6 +57,36 @@ function installWithBun(pkg) {
50
57
  }
51
58
  }
52
59
 
60
+ function installWithNpm(pkg) {
61
+ try {
62
+ console.log(` Installing ${pkg}...`);
63
+ execSync(`npm install -g ${pkg}`, { stdio: "inherit" });
64
+ return true;
65
+ } catch (error) {
66
+ console.error(` Failed to install ${pkg}: ${error.message}`);
67
+ return false;
68
+ }
69
+ }
70
+
71
+ function getInstalledVersion(cmd) {
72
+ try {
73
+ return execSync(`${cmd} --version`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
74
+ } catch {
75
+ return null;
76
+ }
77
+ }
78
+
79
+ function isVersionSufficient(installed, minimum) {
80
+ if (!installed || !minimum) return true;
81
+ const iParts = installed.split(".").map(Number);
82
+ const mParts = minimum.split(".").map(Number);
83
+ for (let i = 0; i < 3; i++) {
84
+ if ((iParts[i] || 0) > (mParts[i] || 0)) return true;
85
+ if ((iParts[i] || 0) < (mParts[i] || 0)) return false;
86
+ }
87
+ return true; // equal
88
+ }
89
+
53
90
  function main() {
54
91
  console.log("\n🚀 JFL CLI - Setting up bundled tools...\n");
55
92
 
@@ -81,15 +118,23 @@ function main() {
81
118
 
82
119
  // Check if already installed
83
120
  if (hasCommand(tool.name)) {
84
- console.log(`✅ ${tool.name} already installed`);
85
- continue;
121
+ const version = getInstalledVersion(tool.name);
122
+ if (tool.minVersion && version && !isVersionSufficient(version, tool.minVersion)) {
123
+ console.log(`⬆️ ${tool.name} v${version} → updating (min: ${tool.minVersion})`);
124
+ } else {
125
+ console.log(`✅ ${tool.name} already installed${version ? ` (v${version})` : ""}`);
126
+ continue;
127
+ }
86
128
  }
87
129
 
88
130
  console.log(`📦 Installing ${tool.name} - ${tool.description}`);
89
- const success = installWithBun(tool.package);
131
+ const success = tool.requiresBun
132
+ ? installWithBun(tool.package)
133
+ : installWithNpm(tool.package);
90
134
 
91
135
  if (success) {
92
- console.log(`✅ ${tool.name} installed successfully\n`);
136
+ const version = getInstalledVersion(tool.name);
137
+ console.log(`✅ ${tool.name} installed${version ? ` (v${version})` : ""}\n`);
93
138
  } else {
94
139
  console.log(`⚠️ ${tool.name} installation failed (optional)\n`);
95
140
  }
@@ -98,6 +143,9 @@ function main() {
98
143
  console.log("🎉 JFL CLI setup complete!\n");
99
144
  console.log("Available tools:");
100
145
  console.log(" jfl - Main CLI");
146
+ if (hasCommand("pi")) {
147
+ console.log(" pi - Coding agent runtime");
148
+ }
101
149
  if (hasCommand("ralph-tui")) {
102
150
  console.log(" ralph-tui - AI agent loop orchestrator");
103
151
  }