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.
Files changed (126) hide show
  1. package/dist/commands/context-hub.d.ts.map +1 -1
  2. package/dist/commands/context-hub.js +141 -3
  3. package/dist/commands/context-hub.js.map +1 -1
  4. package/dist/commands/ide.d.ts.map +1 -1
  5. package/dist/commands/ide.js +22 -0
  6. package/dist/commands/ide.js.map +1 -1
  7. package/dist/commands/init.d.ts.map +1 -1
  8. package/dist/commands/init.js +6 -0
  9. package/dist/commands/init.js.map +1 -1
  10. package/dist/commands/linear.d.ts.map +1 -1
  11. package/dist/commands/linear.js +24 -0
  12. package/dist/commands/linear.js.map +1 -1
  13. package/dist/commands/peter.d.ts.map +1 -1
  14. package/dist/commands/peter.js +11 -15
  15. package/dist/commands/peter.js.map +1 -1
  16. package/dist/commands/pi.d.ts +3 -0
  17. package/dist/commands/pi.d.ts.map +1 -1
  18. package/dist/commands/pi.js +19 -0
  19. package/dist/commands/pi.js.map +1 -1
  20. package/dist/commands/pivot.d.ts.map +1 -1
  21. package/dist/commands/pivot.js +22 -25
  22. package/dist/commands/pivot.js.map +1 -1
  23. package/dist/commands/repair.d.ts.map +1 -1
  24. package/dist/commands/repair.js +26 -0
  25. package/dist/commands/repair.js.map +1 -1
  26. package/dist/commands/session.d.ts.map +1 -1
  27. package/dist/commands/session.js +39 -0
  28. package/dist/commands/session.js.map +1 -1
  29. package/dist/commands/start.d.ts.map +1 -1
  30. package/dist/commands/start.js +60 -0
  31. package/dist/commands/start.js.map +1 -1
  32. package/dist/commands/update.d.ts.map +1 -1
  33. package/dist/commands/update.js +3 -1
  34. package/dist/commands/update.js.map +1 -1
  35. package/dist/index.js +3 -0
  36. package/dist/index.js.map +1 -1
  37. package/dist/lib/advanced-setup.js +7 -7
  38. package/dist/lib/advanced-setup.js.map +1 -1
  39. package/dist/lib/agent-session.d.ts.map +1 -1
  40. package/dist/lib/agent-session.js +6 -3
  41. package/dist/lib/agent-session.js.map +1 -1
  42. package/dist/lib/discovery-agent.js +1 -1
  43. package/dist/lib/discovery-agent.js.map +1 -1
  44. package/dist/lib/gtm-generator.js +7 -0
  45. package/dist/lib/gtm-generator.js.map +1 -1
  46. package/dist/lib/linear-webhook.d.ts +50 -0
  47. package/dist/lib/linear-webhook.d.ts.map +1 -0
  48. package/dist/lib/linear-webhook.js +92 -0
  49. package/dist/lib/linear-webhook.js.map +1 -0
  50. package/dist/lib/memory-db.d.ts +8 -0
  51. package/dist/lib/memory-db.d.ts.map +1 -1
  52. package/dist/lib/memory-db.js +24 -0
  53. package/dist/lib/memory-db.js.map +1 -1
  54. package/dist/lib/memory-indexer.d.ts +8 -0
  55. package/dist/lib/memory-indexer.d.ts.map +1 -1
  56. package/dist/lib/memory-indexer.js +30 -1
  57. package/dist/lib/memory-indexer.js.map +1 -1
  58. package/dist/lib/memory-search.d.ts.map +1 -1
  59. package/dist/lib/memory-search.js +2 -7
  60. package/dist/lib/memory-search.js.map +1 -1
  61. package/dist/lib/onboarding.js +1 -1
  62. package/dist/lib/onboarding.js.map +1 -1
  63. package/dist/lib/rl-manager.d.ts +1 -1
  64. package/dist/lib/rl-manager.d.ts.map +1 -1
  65. package/dist/lib/rl-manager.js +3 -3
  66. package/dist/lib/rl-manager.js.map +1 -1
  67. package/dist/lib/service-detector.js +2 -2
  68. package/dist/lib/service-detector.js.map +1 -1
  69. package/dist/lib/telemetry/physical-world-collector.js +1 -1
  70. package/dist/lib/telemetry/physical-world-collector.js.map +1 -1
  71. package/dist/lib/tool-schemas.d.ts +35 -0
  72. package/dist/lib/tool-schemas.d.ts.map +1 -0
  73. package/dist/lib/tool-schemas.js +246 -0
  74. package/dist/lib/tool-schemas.js.map +1 -0
  75. package/dist/lib/workspace/data-pipeline.d.ts.map +1 -1
  76. package/dist/lib/workspace/data-pipeline.js +29 -20
  77. package/dist/lib/workspace/data-pipeline.js.map +1 -1
  78. package/dist/lib/workspace/engine.d.ts +1 -0
  79. package/dist/lib/workspace/engine.d.ts.map +1 -1
  80. package/dist/lib/workspace/engine.js +10 -0
  81. package/dist/lib/workspace/engine.js.map +1 -1
  82. package/dist/mcp/context-hub-mcp.js +7 -1
  83. package/dist/mcp/context-hub-mcp.js.map +1 -1
  84. package/dist/types/telemetry.d.ts +1 -0
  85. package/dist/types/telemetry.d.ts.map +1 -1
  86. package/dist/utils/git.d.ts +1 -1
  87. package/dist/utils/git.d.ts.map +1 -1
  88. package/dist/utils/git.js +9 -6
  89. package/dist/utils/git.js.map +1 -1
  90. package/dist/utils/provenance.d.ts +65 -0
  91. package/dist/utils/provenance.d.ts.map +1 -0
  92. package/dist/utils/provenance.js +213 -0
  93. package/dist/utils/provenance.js.map +1 -0
  94. package/package.json +1 -1
  95. package/packages/pi/assets/boot.mp3 +0 -0
  96. package/packages/pi/extensions/autoresearch.ts +3 -2
  97. package/packages/pi/extensions/context.ts +38 -114
  98. package/packages/pi/extensions/eval.ts +2 -1
  99. package/packages/pi/extensions/header.ts +171 -0
  100. package/packages/pi/extensions/hub-tools.ts +31 -11
  101. package/packages/pi/extensions/hud-tool.ts +231 -70
  102. package/packages/pi/extensions/index.ts +65 -64
  103. package/packages/pi/extensions/jfl-resolve.ts +98 -0
  104. package/packages/pi/extensions/journal.ts +91 -6
  105. package/packages/pi/extensions/map-bridge.ts +31 -0
  106. package/packages/pi/extensions/memory-tool.ts +3 -3
  107. package/packages/pi/extensions/onboarding-v2.ts +263 -410
  108. package/packages/pi/extensions/onboarding-v3.ts +32 -21
  109. package/packages/pi/extensions/peter-parker.ts +2 -1
  110. package/packages/pi/extensions/policy-head-tool.ts +3 -2
  111. package/packages/pi/extensions/portfolio-bridge.ts +3 -4
  112. package/packages/pi/extensions/service-skills.ts +6 -1
  113. package/packages/pi/extensions/session.ts +97 -15
  114. package/packages/pi/extensions/startup-briefing.ts +313 -0
  115. package/packages/pi/extensions/stratus-bridge.ts +2 -1
  116. package/packages/pi/extensions/subway-mesh.ts +893 -0
  117. package/packages/pi/extensions/synopsis-tool.ts +6 -1
  118. package/packages/pi/extensions/training-buffer-tool.ts +3 -2
  119. package/packages/pi/extensions/types.ts +3 -0
  120. package/packages/pi/package.json +4 -1
  121. package/packages/pi/skills/viz/SKILL.md +204 -0
  122. package/scripts/pp-branch-pr.sh +24 -6
  123. package/scripts/pp-branch-pr.sh.bak +115 -0
  124. package/template/.pi/settings.json +5 -0
  125. package/template/CLAUDE.md +82 -1738
  126. package/template/CLAUDE.md.bak +0 -1187
@@ -1 +1 @@
1
- {"version":3,"file":"context-hub.d.ts","sourceRoot":"","sources":["../../src/commands/context-hub.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAolFH,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAiBjF;AAkMD,wBAAsB,qBAAqB,CAAC,IAAI,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAiHxF;AAMD,wBAAsB,iBAAiB,CACrC,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,iBA8lBzF"}
1
+ {"version":3,"file":"context-hub.d.ts","sourceRoot":"","sources":["../../src/commands/context-hub.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAwuFH,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAiBjF;AAkMD,wBAAsB,qBAAqB,CAAC,IAAI,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAiHxF;AAMD,wBAAsB,iBAAiB,CACrC,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,iBA8lBzF"}
@@ -16,7 +16,7 @@ import { homedir } from "os";
16
16
  import { fileURLToPath } from "url";
17
17
  import { initializeDatabase, getMemoryStats, insertMemory } from "../lib/memory-db.js";
18
18
  import { searchMemories } from "../lib/memory-search.js";
19
- import { indexJournalEntries, startPeriodicIndexing } from "../lib/memory-indexer.js";
19
+ import { indexJournalEntries, startPeriodicIndexing, backfillEmbeddings } from "../lib/memory-indexer.js";
20
20
  import { getProjectPort } from "../utils/context-hub-port.js";
21
21
  import { getConfigValue, setConfig } from "../utils/jfl-config.js";
22
22
  import Conf from "conf";
@@ -318,6 +318,74 @@ function readCodeContext(projectRoot, limit = 30) {
318
318
  }
319
319
  return items;
320
320
  }
321
+ /**
322
+ * Read GTM content artifacts — drafts, specs, content, scripts.
323
+ * Used instead of code indexing for GTM-type projects.
324
+ */
325
+ function readGtmContent(projectRoot, limit = 40) {
326
+ const items = [];
327
+ const gtmDirs = [
328
+ { dir: "content", type: "content" },
329
+ { dir: "drafts", type: "draft" },
330
+ { dir: "specs", type: "spec" },
331
+ { dir: "scripts", type: "script" },
332
+ ];
333
+ const mdExtensions = [".md", ".txt"];
334
+ const scriptExtensions = [".sh", ".py", ".mjs", ".js"];
335
+ for (const { dir, type } of gtmDirs) {
336
+ const fullDir = path.join(projectRoot, dir);
337
+ if (!fs.existsSync(fullDir))
338
+ continue;
339
+ function scanDir(d, depth = 0) {
340
+ if (depth > 3 || items.length >= limit)
341
+ return;
342
+ try {
343
+ const entries = fs.readdirSync(d, { withFileTypes: true });
344
+ for (const entry of entries) {
345
+ if (items.length >= limit)
346
+ break;
347
+ if (entry.name.startsWith(".") || entry.name === "node_modules")
348
+ continue;
349
+ const fullPath = path.join(d, entry.name);
350
+ if (entry.isDirectory()) {
351
+ scanDir(fullPath, depth + 1);
352
+ }
353
+ else {
354
+ const isMarkdown = mdExtensions.some(ext => entry.name.endsWith(ext));
355
+ const isScript = type === "script" && scriptExtensions.some(ext => entry.name.endsWith(ext));
356
+ if (isMarkdown || isScript) {
357
+ try {
358
+ const raw = fs.readFileSync(fullPath, "utf-8");
359
+ // Extract first heading + first paragraph as summary
360
+ const lines = raw.split("\n").filter(l => l.trim());
361
+ const heading = lines.find(l => l.startsWith("#"))?.replace(/^#+\s*/, "") || entry.name;
362
+ const bodyLines = lines.filter(l => !l.startsWith("#") && !l.startsWith("---"));
363
+ const summary = bodyLines.slice(0, 5).join(" ").slice(0, 500);
364
+ if (summary.length > 20) {
365
+ items.push({
366
+ source: "content",
367
+ type,
368
+ title: heading,
369
+ content: summary,
370
+ path: fullPath
371
+ });
372
+ }
373
+ }
374
+ catch {
375
+ // Skip unreadable files
376
+ }
377
+ }
378
+ }
379
+ }
380
+ }
381
+ catch {
382
+ // Skip unreadable directories
383
+ }
384
+ }
385
+ scanDir(fullDir);
386
+ }
387
+ return items;
388
+ }
321
389
  // ============================================================================
322
390
  // Search & Scoring (TF-IDF style)
323
391
  // ============================================================================
@@ -401,11 +469,24 @@ function semanticSearch(items, query) {
401
469
  // ============================================================================
402
470
  // Orchestrator
403
471
  // ============================================================================
472
+ function getProjectType(projectRoot) {
473
+ const configPath = path.join(projectRoot, ".jfl", "config.json");
474
+ if (fs.existsSync(configPath)) {
475
+ try {
476
+ const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
477
+ return config.type || "standalone";
478
+ }
479
+ catch { }
480
+ }
481
+ return "standalone";
482
+ }
404
483
  function getUnifiedContext(projectRoot, query, taskType) {
405
484
  const journalItems = readJournalEntries(projectRoot);
406
485
  const knowledgeItems = readKnowledgeDocs(projectRoot);
486
+ const projectType = getProjectType(projectRoot);
407
487
  const codeItems = readCodeContext(projectRoot);
408
- let items = [...journalItems, ...knowledgeItems, ...codeItems];
488
+ const contentItems = projectType === "gtm" ? readGtmContent(projectRoot) : [];
489
+ let items = [...journalItems, ...knowledgeItems, ...codeItems, ...contentItems];
409
490
  // Apply semantic search if query provided
410
491
  if (query) {
411
492
  items = semanticSearch(items, query);
@@ -416,6 +497,7 @@ function getUnifiedContext(projectRoot, query, taskType) {
416
497
  journal: journalItems.length > 0,
417
498
  knowledge: knowledgeItems.length > 0,
418
499
  code: codeItems.length > 0,
500
+ content: contentItems.length > 0,
419
501
  memory: fs.existsSync(path.join(projectRoot, ".jfl", "memory.db")),
420
502
  },
421
503
  query,
@@ -476,8 +558,11 @@ async function fetchChildContext(child, endpoint, body) {
476
558
  async function getPortfolioContext(projectRoot, query, taskType, maxItems) {
477
559
  const local = getUnifiedContext(projectRoot, query, taskType);
478
560
  const children = getChildHubs(projectRoot);
479
- if (children.length === 0)
561
+ if (children.length === 0) {
562
+ if (maxItems)
563
+ local.items = local.items.slice(0, maxItems);
480
564
  return local;
565
+ }
481
566
  const endpoint = query ? "/api/context/search" : "/api/context";
482
567
  const body = { maxItems: maxItems || 20 };
483
568
  if (query)
@@ -707,6 +792,7 @@ function createServer(projectRoot, port, eventBus, flowEngine) {
707
792
  journal_count: context.items.filter(i => i.source === 'journal').length,
708
793
  knowledge_count: context.items.filter(i => i.source === 'knowledge').length,
709
794
  code_count: context.items.filter(i => i.source === 'code').length,
795
+ content_count: context.items.filter(i => i.source === 'content').length,
710
796
  query_length: query ? query.length : 0,
711
797
  });
712
798
  res.writeHead(200, { "Content-Type": "application/json" });
@@ -962,6 +1048,28 @@ function createServer(projectRoot, port, eventBus, flowEngine) {
962
1048
  });
963
1049
  return;
964
1050
  }
1051
+ // POST /api/memory/index — trigger journal→memory indexing + embedding backfill
1052
+ if (url.pathname === "/api/memory/index" && req.method === "POST") {
1053
+ let body = "";
1054
+ req.on("data", (chunk) => body += chunk);
1055
+ req.on("end", async () => {
1056
+ try {
1057
+ const { force, backfill } = JSON.parse(body || "{}");
1058
+ const stats = await indexJournalEntries(force ?? false);
1059
+ let embeddingStats = { updated: 0, errors: 0 };
1060
+ if (backfill !== false) {
1061
+ embeddingStats = await backfillEmbeddings();
1062
+ }
1063
+ res.writeHead(200, { "Content-Type": "application/json" });
1064
+ res.end(JSON.stringify({ ok: true, ...stats, embeddings_backfilled: embeddingStats.updated, embedding_errors: embeddingStats.errors }));
1065
+ }
1066
+ catch (err) {
1067
+ res.writeHead(500, { "Content-Type": "application/json" });
1068
+ res.end(JSON.stringify({ error: err.message }));
1069
+ }
1070
+ });
1071
+ return;
1072
+ }
965
1073
  // Eval trajectory
966
1074
  if (url.pathname === "/api/eval/trajectory" && req.method === "GET") {
967
1075
  try {
@@ -2274,6 +2382,36 @@ function createServer(projectRoot, port, eventBus, flowEngine) {
2274
2382
  }
2275
2383
  return;
2276
2384
  }
2385
+ // POST /api/webhooks/linear — handle Linear webhook events
2386
+ if (url.pathname === "/api/webhooks/linear" && req.method === "POST") {
2387
+ let body = "";
2388
+ req.on("data", (chunk) => { body += chunk; });
2389
+ req.on("end", async () => {
2390
+ try {
2391
+ const payload = JSON.parse(body || "{}");
2392
+ const { handleLinearWebhook } = await import("../lib/linear-webhook.js");
2393
+ const result = handleLinearWebhook(payload, projectRoot);
2394
+ if (result.handled && eventBus) {
2395
+ eventBus.emit({
2396
+ type: "linear:document-sync",
2397
+ source: "linear-webhook",
2398
+ data: {
2399
+ action: payload.action,
2400
+ documentTitle: payload.data?.title,
2401
+ journalFile: result.journalFile,
2402
+ },
2403
+ });
2404
+ }
2405
+ res.writeHead(200, { "Content-Type": "application/json" });
2406
+ res.end(JSON.stringify(result));
2407
+ }
2408
+ catch (err) {
2409
+ res.writeHead(400, { "Content-Type": "application/json" });
2410
+ res.end(JSON.stringify({ error: err.message }));
2411
+ }
2412
+ });
2413
+ return;
2414
+ }
2277
2415
  // 404
2278
2416
  res.writeHead(404, { "Content-Type": "application/json" });
2279
2417
  res.end(JSON.stringify({ error: "Not found" }));