jfl 0.9.1 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/context-hub.d.ts.map +1 -1
- package/dist/commands/context-hub.js +141 -3
- package/dist/commands/context-hub.js.map +1 -1
- package/dist/commands/ide.d.ts.map +1 -1
- package/dist/commands/ide.js +22 -0
- package/dist/commands/ide.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +6 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/linear.d.ts.map +1 -1
- package/dist/commands/linear.js +24 -0
- package/dist/commands/linear.js.map +1 -1
- package/dist/commands/peter.d.ts.map +1 -1
- package/dist/commands/peter.js +11 -15
- package/dist/commands/peter.js.map +1 -1
- package/dist/commands/pi.d.ts +3 -0
- package/dist/commands/pi.d.ts.map +1 -1
- package/dist/commands/pi.js +19 -0
- package/dist/commands/pi.js.map +1 -1
- package/dist/commands/pivot.d.ts.map +1 -1
- package/dist/commands/pivot.js +22 -25
- package/dist/commands/pivot.js.map +1 -1
- package/dist/commands/repair.d.ts.map +1 -1
- package/dist/commands/repair.js +26 -0
- package/dist/commands/repair.js.map +1 -1
- package/dist/commands/session.d.ts.map +1 -1
- package/dist/commands/session.js +39 -0
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +60 -0
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +3 -1
- package/dist/commands/update.js.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/advanced-setup.js +7 -7
- package/dist/lib/advanced-setup.js.map +1 -1
- package/dist/lib/agent-session.d.ts.map +1 -1
- package/dist/lib/agent-session.js +6 -3
- package/dist/lib/agent-session.js.map +1 -1
- package/dist/lib/discovery-agent.js +1 -1
- package/dist/lib/discovery-agent.js.map +1 -1
- package/dist/lib/gtm-generator.js +7 -0
- package/dist/lib/gtm-generator.js.map +1 -1
- package/dist/lib/linear-webhook.d.ts +50 -0
- package/dist/lib/linear-webhook.d.ts.map +1 -0
- package/dist/lib/linear-webhook.js +92 -0
- package/dist/lib/linear-webhook.js.map +1 -0
- package/dist/lib/memory-db.d.ts +8 -0
- package/dist/lib/memory-db.d.ts.map +1 -1
- package/dist/lib/memory-db.js +24 -0
- package/dist/lib/memory-db.js.map +1 -1
- package/dist/lib/memory-indexer.d.ts +8 -0
- package/dist/lib/memory-indexer.d.ts.map +1 -1
- package/dist/lib/memory-indexer.js +30 -1
- package/dist/lib/memory-indexer.js.map +1 -1
- package/dist/lib/memory-search.d.ts.map +1 -1
- package/dist/lib/memory-search.js +2 -7
- package/dist/lib/memory-search.js.map +1 -1
- package/dist/lib/onboarding.js +1 -1
- package/dist/lib/onboarding.js.map +1 -1
- package/dist/lib/rl-manager.d.ts +1 -1
- package/dist/lib/rl-manager.d.ts.map +1 -1
- package/dist/lib/rl-manager.js +3 -3
- package/dist/lib/rl-manager.js.map +1 -1
- package/dist/lib/service-detector.js +2 -2
- package/dist/lib/service-detector.js.map +1 -1
- package/dist/lib/telemetry/physical-world-collector.js +1 -1
- package/dist/lib/telemetry/physical-world-collector.js.map +1 -1
- package/dist/lib/tool-schemas.d.ts +35 -0
- package/dist/lib/tool-schemas.d.ts.map +1 -0
- package/dist/lib/tool-schemas.js +246 -0
- package/dist/lib/tool-schemas.js.map +1 -0
- package/dist/lib/workspace/data-pipeline.d.ts.map +1 -1
- package/dist/lib/workspace/data-pipeline.js +29 -20
- package/dist/lib/workspace/data-pipeline.js.map +1 -1
- package/dist/lib/workspace/engine.d.ts +1 -0
- package/dist/lib/workspace/engine.d.ts.map +1 -1
- package/dist/lib/workspace/engine.js +10 -0
- package/dist/lib/workspace/engine.js.map +1 -1
- package/dist/mcp/context-hub-mcp.js +7 -1
- package/dist/mcp/context-hub-mcp.js.map +1 -1
- package/dist/types/telemetry.d.ts +1 -0
- package/dist/types/telemetry.d.ts.map +1 -1
- package/dist/utils/git.d.ts +1 -1
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +9 -6
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/provenance.d.ts +65 -0
- package/dist/utils/provenance.d.ts.map +1 -0
- package/dist/utils/provenance.js +213 -0
- package/dist/utils/provenance.js.map +1 -0
- package/package.json +1 -1
- package/packages/pi/assets/boot.mp3 +0 -0
- package/packages/pi/extensions/autoresearch.ts +3 -2
- package/packages/pi/extensions/context.ts +38 -114
- package/packages/pi/extensions/eval.ts +2 -1
- package/packages/pi/extensions/header.ts +171 -0
- package/packages/pi/extensions/hub-tools.ts +31 -11
- package/packages/pi/extensions/hud-tool.ts +231 -70
- package/packages/pi/extensions/index.ts +65 -64
- package/packages/pi/extensions/jfl-resolve.ts +98 -0
- package/packages/pi/extensions/journal.ts +91 -6
- package/packages/pi/extensions/map-bridge.ts +31 -0
- package/packages/pi/extensions/memory-tool.ts +3 -3
- package/packages/pi/extensions/onboarding-v2.ts +263 -410
- package/packages/pi/extensions/onboarding-v3.ts +32 -21
- package/packages/pi/extensions/peter-parker.ts +2 -1
- package/packages/pi/extensions/policy-head-tool.ts +3 -2
- package/packages/pi/extensions/portfolio-bridge.ts +3 -4
- package/packages/pi/extensions/service-skills.ts +6 -1
- package/packages/pi/extensions/session.ts +97 -15
- package/packages/pi/extensions/startup-briefing.ts +313 -0
- package/packages/pi/extensions/stratus-bridge.ts +2 -1
- package/packages/pi/extensions/subway-mesh.ts +893 -0
- package/packages/pi/extensions/synopsis-tool.ts +6 -1
- package/packages/pi/extensions/training-buffer-tool.ts +3 -2
- package/packages/pi/extensions/types.ts +3 -0
- package/packages/pi/package.json +4 -1
- package/packages/pi/skills/viz/SKILL.md +204 -0
- package/scripts/pp-branch-pr.sh +24 -6
- package/scripts/pp-branch-pr.sh.bak +115 -0
- package/template/.pi/settings.json +5 -0
- package/template/CLAUDE.md +82 -1738
- package/template/CLAUDE.md.bak +0 -1187
|
@@ -12,7 +12,7 @@ import { existsSync, readFileSync, appendFileSync, mkdirSync } from "fs"
|
|
|
12
12
|
import { join } from "path"
|
|
13
13
|
import { execSync } from "child_process"
|
|
14
14
|
import type { PiContext, PiTheme, JflConfig, AgentEndEvent, ToolExecutionEvent } from "./types.js"
|
|
15
|
-
import { getCurrentBranch } from "./session.js"
|
|
15
|
+
import { getCurrentBranch, getSessionBranch } from "./session.js"
|
|
16
16
|
import { emitCustomEvent } from "./map-bridge.js"
|
|
17
17
|
|
|
18
18
|
let projectRoot = ""
|
|
@@ -33,7 +33,9 @@ interface JournalEntry {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
function getJournalPath(root: string): string {
|
|
36
|
-
|
|
36
|
+
// Prefer the session branch tracked by session.ts — git HEAD may differ
|
|
37
|
+
// if checkout failed due to dirty working tree
|
|
38
|
+
const branch = getSessionBranch() || getCurrentBranch(root)
|
|
37
39
|
return join(root, ".jfl", "journal", `${branch}.jsonl`)
|
|
38
40
|
}
|
|
39
41
|
|
|
@@ -57,7 +59,7 @@ function readRecentEntries(root: string, count = 5): JournalEntry[] {
|
|
|
57
59
|
}
|
|
58
60
|
}
|
|
59
61
|
|
|
60
|
-
function hasJournalEntryForSession(root: string, sessionBranch: string): boolean {
|
|
62
|
+
export function hasJournalEntryForSession(root: string, sessionBranch: string): boolean {
|
|
61
63
|
const journalPath = join(root, ".jfl", "journal", `${sessionBranch}.jsonl`)
|
|
62
64
|
if (!existsSync(journalPath)) return false
|
|
63
65
|
const content = readFileSync(journalPath, "utf-8").trim()
|
|
@@ -117,7 +119,7 @@ export async function setupJournal(ctx: PiContext, _config: JflConfig): Promise<
|
|
|
117
119
|
const entry: JournalEntry = {
|
|
118
120
|
v: 1,
|
|
119
121
|
ts: new Date().toISOString(),
|
|
120
|
-
session: getCurrentBranch(projectRoot),
|
|
122
|
+
session: getSessionBranch() || getCurrentBranch(projectRoot),
|
|
121
123
|
type,
|
|
122
124
|
status: "complete",
|
|
123
125
|
title: title.trim(),
|
|
@@ -134,7 +136,7 @@ export async function setupJournal(ctx: PiContext, _config: JflConfig): Promise<
|
|
|
134
136
|
}
|
|
135
137
|
|
|
136
138
|
// Fallback: raw JSON input for non-interactive mode
|
|
137
|
-
const branch = getCurrentBranch(projectRoot)
|
|
139
|
+
const branch = getSessionBranch() || getCurrentBranch(projectRoot)
|
|
138
140
|
const template = JSON.stringify({
|
|
139
141
|
v: 1,
|
|
140
142
|
ts: new Date().toISOString(),
|
|
@@ -172,6 +174,21 @@ export async function onToolExecutionEnd(
|
|
|
172
174
|
event: ToolExecutionEvent
|
|
173
175
|
): Promise<void> {
|
|
174
176
|
const toolName = event.toolName ?? event.tool ?? ""
|
|
177
|
+
|
|
178
|
+
// TaskUpdate completed → journal nudge (parity with CC PostToolUse hook)
|
|
179
|
+
if (toolName === "TaskUpdate") {
|
|
180
|
+
const input = event.input ?? event.args ?? {}
|
|
181
|
+
const inputStr = typeof input === "string" ? input : JSON.stringify(input)
|
|
182
|
+
if (/"status"\s*:\s*"completed"/.test(inputStr)) {
|
|
183
|
+
const branch = getCurrentBranch(projectRoot)
|
|
184
|
+
ctx.ui.notify(
|
|
185
|
+
`Task completed — write journal entry\nFile: .jfl/journal/${branch}.jsonl`,
|
|
186
|
+
{ level: "info" }
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
return
|
|
190
|
+
}
|
|
191
|
+
|
|
175
192
|
if (toolName.toLowerCase() !== "bash") return
|
|
176
193
|
|
|
177
194
|
const result = String(event.result ?? "")
|
|
@@ -202,10 +219,78 @@ export async function onJournalAgentEnd(
|
|
|
202
219
|
// Removed: "Journal entry recommended" nudge (noisy)
|
|
203
220
|
}
|
|
204
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Check @purpose header on Write/Edit to code files.
|
|
224
|
+
* Equivalent to Claude Code's PostToolUse(Write|Edit) hook.
|
|
225
|
+
*/
|
|
226
|
+
export function checkPurposeHeader(
|
|
227
|
+
ctx: PiContext,
|
|
228
|
+
event: ToolExecutionEvent
|
|
229
|
+
): void {
|
|
230
|
+
const toolName = (event.toolName ?? event.tool ?? "").toLowerCase()
|
|
231
|
+
if (toolName !== "write" && toolName !== "edit") return
|
|
232
|
+
|
|
233
|
+
// Extract file path from tool input
|
|
234
|
+
const input = event.input ?? event.args ?? {}
|
|
235
|
+
const filePath = typeof input === "string"
|
|
236
|
+
? input
|
|
237
|
+
: (input as any).path ?? (input as any).file_path ?? ""
|
|
238
|
+
|
|
239
|
+
if (!filePath) return
|
|
240
|
+
if (!/\.(ts|tsx|js|jsx)$/.test(filePath)) return
|
|
241
|
+
|
|
242
|
+
const fullPath = filePath.startsWith("/") ? filePath : join(projectRoot, filePath)
|
|
243
|
+
if (!existsSync(fullPath)) return
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
const head = readFileSync(fullPath, "utf-8").slice(0, 800)
|
|
247
|
+
if (!head.includes("@purpose")) {
|
|
248
|
+
ctx.ui.notify(
|
|
249
|
+
`⚠️ Missing @purpose header in ${filePath}\n Add: /** @purpose One-line description */`,
|
|
250
|
+
{ level: "warn" }
|
|
251
|
+
)
|
|
252
|
+
}
|
|
253
|
+
} catch {}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Auto-commit changes before context compaction.
|
|
258
|
+
* Equivalent to Claude Code's PreCompact hook that runs:
|
|
259
|
+
* git add knowledge/ previews/ content/ suggestions/ .jfl/ && git commit
|
|
260
|
+
*/
|
|
261
|
+
function autoCommitBeforeCompact(ctx: PiContext): void {
|
|
262
|
+
const trackedDirs = ["knowledge", "previews", "content", "suggestions", ".jfl", "CLAUDE.md"]
|
|
263
|
+
const addPaths = trackedDirs
|
|
264
|
+
.filter((d) => existsSync(join(projectRoot, d)))
|
|
265
|
+
.join(" ")
|
|
266
|
+
|
|
267
|
+
if (!addPaths) return
|
|
268
|
+
|
|
269
|
+
try {
|
|
270
|
+
const status = execSync(`git status --porcelain -- ${addPaths}`, {
|
|
271
|
+
cwd: projectRoot,
|
|
272
|
+
encoding: "utf-8",
|
|
273
|
+
}).trim()
|
|
274
|
+
|
|
275
|
+
if (!status) return // nothing to commit
|
|
276
|
+
|
|
277
|
+
execSync(`git add ${addPaths} && git commit -m "auto-commit: pre-compact save"`, {
|
|
278
|
+
cwd: projectRoot,
|
|
279
|
+
stdio: "pipe",
|
|
280
|
+
})
|
|
281
|
+
ctx.log("Pre-compact auto-commit saved changes", "debug")
|
|
282
|
+
} catch {
|
|
283
|
+
// Not critical — auto-commit daemon is the primary safety net
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
205
287
|
export async function checkJournalBeforeCompact(
|
|
206
288
|
ctx: PiContext
|
|
207
289
|
): Promise<{ cancel: true } | void> {
|
|
208
|
-
|
|
290
|
+
// Auto-commit changes before compaction (safety net)
|
|
291
|
+
autoCommitBeforeCompact(ctx)
|
|
292
|
+
|
|
293
|
+
const branch = getSessionBranch() || getCurrentBranch(projectRoot)
|
|
209
294
|
if (!hasJournalEntryForSession(projectRoot, branch)) {
|
|
210
295
|
if (ctx.ui.hasUI) {
|
|
211
296
|
const ok = await ctx.ui.confirm(
|
|
@@ -143,6 +143,37 @@ export async function setupMapBridge(ctx: PiContext, config: JflConfig): Promise
|
|
|
143
143
|
if (port) hubUrl = `http://localhost:${port}`
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
// Verify the hub is actually reachable on this port.
|
|
147
|
+
// If not, try discovering the real port from the running process.
|
|
148
|
+
try {
|
|
149
|
+
const healthResp = await fetch(`${hubUrl}/health`, { signal: AbortSignal.timeout(3000) })
|
|
150
|
+
if (!healthResp.ok) throw new Error("unhealthy")
|
|
151
|
+
} catch {
|
|
152
|
+
ctx.log(`Hub unreachable at ${hubUrl}, attempting port discovery...`, "warn")
|
|
153
|
+
// Try to find the actual port from the running hub process
|
|
154
|
+
try {
|
|
155
|
+
const { execSync } = await import("child_process")
|
|
156
|
+
const psOut = execSync(
|
|
157
|
+
`ps aux | grep "context-hub serve.*--project-root ${root.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}" | grep -v grep`,
|
|
158
|
+
{ encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"] }
|
|
159
|
+
).trim()
|
|
160
|
+
const portMatch = psOut.match(/--port\s+(\d+)/)
|
|
161
|
+
if (portMatch) {
|
|
162
|
+
const discoveredPort = portMatch[1]
|
|
163
|
+
const testResp = await fetch(`http://localhost:${discoveredPort}/health`, { signal: AbortSignal.timeout(3000) })
|
|
164
|
+
if (testResp.ok) {
|
|
165
|
+
hubUrl = `http://localhost:${discoveredPort}`
|
|
166
|
+
// Fix the stale port file
|
|
167
|
+
const { writeFileSync } = await import("fs")
|
|
168
|
+
writeFileSync(join(root, ".jfl", "context-hub.port"), discoveredPort)
|
|
169
|
+
ctx.log(`Hub discovered on port ${discoveredPort} — fixed stale port file`, "warn")
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
} catch {
|
|
173
|
+
ctx.log("Hub port discovery failed — hub tools will be unavailable", "warn")
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
146
177
|
ctx.on("hook:session-start", (data) => postToHub({ type: "hook:session-start", source: "pi-session", data, ts: new Date().toISOString() }))
|
|
147
178
|
ctx.on("hook:session-end", (data) => postToHub({ type: "hook:session-end", source: "pi-session", data, ts: new Date().toISOString() }))
|
|
148
179
|
|
|
@@ -110,9 +110,9 @@ export function setupMemoryTool(ctx: PiContext): void {
|
|
|
110
110
|
})
|
|
111
111
|
|
|
112
112
|
if (!resp.ok) return "Failed to add memory — hub returned error."
|
|
113
|
-
const data = await resp.json() as { ok?: boolean; id?: string }
|
|
114
|
-
return data.ok
|
|
115
|
-
? `Memory added: "${title}" (${type ?? "note"})`
|
|
113
|
+
const data = await resp.json() as { ok?: boolean; id?: string | number }
|
|
114
|
+
return (data.ok || data.id)
|
|
115
|
+
? `Memory added: "${title}" (${type ?? "note"})${data.id ? ` [id: ${data.id}]` : ""}`
|
|
116
116
|
: "Memory add returned unexpected response."
|
|
117
117
|
} catch {
|
|
118
118
|
return "Memory add unavailable — Context Hub may not be running."
|