@plumpslabs/kuma 2.3.8 → 2.3.9

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 (31) hide show
  1. package/dist/{chunk-NAM7SCBT.js → chunk-3TX6Q37T.js} +26 -1
  2. package/dist/{chunk-RTGLQDMI.js → chunk-OJALFQ4H.js} +2 -2
  3. package/dist/{chunk-53J56QCQ.js → chunk-Q2444HWO.js} +1 -1
  4. package/dist/{chunk-SLRRDKQ2.js → chunk-R6B3VUSB.js} +2 -2
  5. package/dist/{chunk-PTEPJK6M.js → chunk-RI3DKY62.js} +1 -1
  6. package/dist/{chunk-FL2TLLMX.js → chunk-SPHI2BOO.js} +1 -1
  7. package/dist/{chunk-4OB3XMHT.js → chunk-ZKDYTYMS.js} +108 -2
  8. package/dist/{contextDigest-4PCK3DSM.js → contextDigest-5JXLH56Z.js} +3 -3
  9. package/dist/{domainRules-LDZPOIGZ.js → domainRules-ED6EOFVY.js} +2 -2
  10. package/dist/index.js +253 -65
  11. package/dist/kumaCheckpoint-XIQWRMGV.js +207 -0
  12. package/dist/kumaCodeScanner-LFJGPJNH.js +566 -0
  13. package/dist/kumaContractEngine-KX27T4N7.js +305 -0
  14. package/dist/{kumaDb-6D53ERFP.js → kumaDb-IC7UX7PU.js} +3 -1
  15. package/dist/{kumaDriftDetector-OESI5GTC.js → kumaDriftDetector-QBY6OJOO.js} +1 -1
  16. package/dist/{kumaGotchas-DU5H6N7X.js → kumaGotchas-5HODT5RI.js} +3 -3
  17. package/dist/{kumaGraph-AWP743TJ.js → kumaGraph-GUQM75WL.js} +8 -2
  18. package/dist/{kumaMemory-7TCUDVZX.js → kumaMemory-FMOWIODH.js} +2 -2
  19. package/dist/{kumaMiner-FFXSRHAO.js → kumaMiner-3RXEOCBP.js} +3 -3
  20. package/dist/{kumaPolicyEngine-S2PXN3C7.js → kumaPolicyEngine-ORBWL5PT.js} +2 -2
  21. package/dist/kumaProgressiveContext-CVSNPY3W.js +231 -0
  22. package/dist/{kumaSearch-QGB4QVXS.js → kumaSearch-B5WVYHHD.js} +1 -1
  23. package/dist/kumaTrajectory-T6DXGOG4.js +460 -0
  24. package/dist/{kumaVerifier-ARSGPZAM.js → kumaVerifier-KAYJHR5K.js} +2 -2
  25. package/dist/{kumaVisualize-TECABHUY.js → kumaVisualize-AFL7STLL.js} +1 -1
  26. package/dist/{safetyAudit-55IVCG5B.js → safetyAudit-32WSA4Z5.js} +2 -2
  27. package/dist/{safetyScore-GR5N55CU.js → safetyScore-WU27EOG4.js} +5 -5
  28. package/dist/{sessionMemory-CA34TCPF.js → sessionMemory-4UWA3E5J.js} +1 -1
  29. package/package.json +18 -13
  30. package/packages/ide/studio/dist/index.js +140 -0
  31. package/packages/ide/studio/public/index.html +500 -0
package/dist/index.js CHANGED
@@ -1,40 +1,40 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- ALL_CONFIG_TYPES,
4
- formatInitResults,
5
- runInit
6
- } from "./chunk-L5WU2HTN.js";
7
2
  import {
8
3
  auditStats,
9
4
  queryAudit,
10
5
  recordAudit
11
- } from "./chunk-PTEPJK6M.js";
6
+ } from "./chunk-RI3DKY62.js";
12
7
  import {
13
- analyzeImpact,
14
- autoHeal,
15
- detectStaleNodes,
16
- formatFlow,
17
- formatHealReport,
18
- formatImpact,
19
- getGraphStats,
20
- searchGraph,
21
- traceFlow
22
- } from "./chunk-4OB3XMHT.js";
8
+ ALL_CONFIG_TYPES,
9
+ formatInitResults,
10
+ runInit
11
+ } from "./chunk-L5WU2HTN.js";
23
12
  import {
24
13
  formatDecisionTemplate,
25
14
  getProactiveMemories,
26
15
  recordDecision,
27
16
  scoreMemoryRelevance
28
- } from "./chunk-RTGLQDMI.js";
17
+ } from "./chunk-OJALFQ4H.js";
29
18
  import {
30
19
  buildDriftMessages,
31
20
  getGitDiffStat,
32
21
  getSessionStats,
33
22
  getUnresolvedCount
34
- } from "./chunk-FL2TLLMX.js";
23
+ } from "./chunk-SPHI2BOO.js";
35
24
  import {
36
25
  sessionMemory
37
- } from "./chunk-SLRRDKQ2.js";
26
+ } from "./chunk-R6B3VUSB.js";
27
+ import {
28
+ analyzeImpact,
29
+ autoHeal,
30
+ detectStaleNodes,
31
+ formatFlow,
32
+ formatHealReport,
33
+ formatImpact,
34
+ getGraphStats,
35
+ searchGraph,
36
+ traceFlow
37
+ } from "./chunk-ZKDYTYMS.js";
38
38
  import {
39
39
  addContextNote,
40
40
  addSecurityFinding,
@@ -59,7 +59,7 @@ import {
59
59
  saveResearchCache,
60
60
  updateDecisionStatus,
61
61
  updateTodoStatus
62
- } from "./chunk-NAM7SCBT.js";
62
+ } from "./chunk-3TX6Q37T.js";
63
63
  import {
64
64
  getProjectRoot,
65
65
  validateFilePath
@@ -140,7 +140,12 @@ var CONTEXT_ALIASES = {
140
140
  "drift": "drift",
141
141
  "staleness": "drift",
142
142
  "code-drift": "drift",
143
- "freshness": "drift"
143
+ "freshness": "drift",
144
+ // Progressive context synonyms (Issue #25)
145
+ "progressive": "progressive",
146
+ "prog": "progressive",
147
+ "section": "progressive",
148
+ "sectional": "progressive"
144
149
  };
145
150
  async function handleContext(params) {
146
151
  const rawAction = params.action || "init";
@@ -171,8 +176,10 @@ async function handleContext(params) {
171
176
  return handleDigest(params);
172
177
  case "drift":
173
178
  return handleDrift(params);
179
+ case "progressive":
180
+ return handleProgressive(params);
174
181
  default:
175
- return `Unknown action "${action}". Use: init, research, impact, navigate, changes, rollback, researches, health, sync, visualize, digest, drift`;
182
+ return `Unknown action "${action}". Use: init, research, impact, navigate, changes, rollback, researches, health, sync, visualize, digest, drift, progressive`;
176
183
  }
177
184
  }
178
185
  async function handleInit(_params) {
@@ -233,8 +240,8 @@ async function handleInit(_params) {
233
240
  lines.push(` \u{1F4DD} Modified: ${summary.modifiedFiles?.length || 0} file(s)`);
234
241
  lines.push(` \u{1F6E0}\uFE0F Tool calls: ${summary.toolCallCount}`);
235
242
  try {
236
- const { computeSafetyScore, formatSafetyScore } = await import("./safetyScore-GR5N55CU.js");
237
- const { saveHealthSnapshot: saveHealthSnapshot2 } = await import("./kumaDb-6D53ERFP.js");
243
+ const { computeSafetyScore, formatSafetyScore } = await import("./safetyScore-WU27EOG4.js");
244
+ const { saveHealthSnapshot: saveHealthSnapshot2 } = await import("./kumaDb-IC7UX7PU.js");
238
245
  const score = await computeSafetyScore(_params.goal);
239
246
  const checksStr = JSON.stringify(score.checks);
240
247
  await saveHealthSnapshot2(score.score, score.risk, checksStr, score.summary);
@@ -296,7 +303,7 @@ async function handleResearch(params) {
296
303
  lines.push(" \u23F3 No content hash available \u2014 will research fresh");
297
304
  }
298
305
  lines.push("");
299
- lines.push("**Step 3/5: Graph Query**");
306
+ lines.push("**Step 3/5: Graph Query + Code Scan**");
300
307
  try {
301
308
  const graphResult = await searchGraph(scope, 15);
302
309
  const graphLines = graphResult.split("\n");
@@ -328,6 +335,14 @@ async function handleResearch(params) {
328
335
  } catch {
329
336
  lines.push(" \u26A0\uFE0F Graph query failed");
330
337
  }
338
+ try {
339
+ const { scanCodebase } = await import("./kumaCodeScanner-LFJGPJNH.js");
340
+ const scanResult = await scanCodebase({ scope, maxFiles: 100 });
341
+ if (scanResult.nodeCount > 0 || scanResult.edgeCount > 0) {
342
+ lines.push(` \u{1F52C} Auto-scanned ${scanResult.filesScanned} files \u2192 ${scanResult.nodeCount} nodes, ${scanResult.edgeCount} edges`);
343
+ }
344
+ } catch {
345
+ }
331
346
  lines.push("");
332
347
  lines.push("**Step 4/5: Impact Analysis**");
333
348
  try {
@@ -407,8 +422,8 @@ async function handleResearches(_params) {
407
422
  async function handleHealth(_params) {
408
423
  sessionMemory.recordToolCall("kuma_context_health", {});
409
424
  try {
410
- const { computeSafetyScore, formatSafetyScore } = await import("./safetyScore-GR5N55CU.js");
411
- const { saveHealthSnapshot: saveHealthSnapshot2 } = await import("./kumaDb-6D53ERFP.js");
425
+ const { computeSafetyScore, formatSafetyScore } = await import("./safetyScore-WU27EOG4.js");
426
+ const { saveHealthSnapshot: saveHealthSnapshot2 } = await import("./kumaDb-IC7UX7PU.js");
412
427
  const score = await computeSafetyScore();
413
428
  const checksStr = JSON.stringify(score.checks);
414
429
  await saveHealthSnapshot2(score.score, score.risk, checksStr, score.summary);
@@ -435,8 +450,8 @@ async function handleSync(params) {
435
450
  lines.push(` \u{1F6E0}\uFE0F Tool calls: ${summary.toolCallCount}`);
436
451
  lines.push("");
437
452
  try {
438
- const { computeSafetyScore, formatSafetyScore } = await import("./safetyScore-GR5N55CU.js");
439
- const { saveHealthSnapshot: saveHealthSnapshot2 } = await import("./kumaDb-6D53ERFP.js");
453
+ const { computeSafetyScore, formatSafetyScore } = await import("./safetyScore-WU27EOG4.js");
454
+ const { saveHealthSnapshot: saveHealthSnapshot2 } = await import("./kumaDb-IC7UX7PU.js");
440
455
  const score = await computeSafetyScore(params.goal);
441
456
  const checksStr = JSON.stringify(score.checks);
442
457
  await saveHealthSnapshot2(score.score, score.risk, checksStr, score.summary);
@@ -447,14 +462,14 @@ async function handleSync(params) {
447
462
  }
448
463
  lines.push("");
449
464
  try {
450
- const { getGraphStats: getGraphStats2 } = await import("./kumaGraph-AWP743TJ.js");
465
+ const { getGraphStats: getGraphStats2 } = await import("./kumaGraph-GUQM75WL.js");
451
466
  lines.push("**Knowledge Graph**");
452
467
  lines.push(await getGraphStats2());
453
468
  } catch {
454
469
  }
455
470
  lines.push("");
456
471
  try {
457
- const { getProactiveMemories: getProactiveMemories2 } = await import("./kumaMemory-7TCUDVZX.js");
472
+ const { getProactiveMemories: getProactiveMemories2 } = await import("./kumaMemory-FMOWIODH.js");
458
473
  const memories = getProactiveMemories2();
459
474
  if (memories) {
460
475
  lines.push("**Relevant Memories**");
@@ -468,7 +483,7 @@ async function handleSync(params) {
468
483
  }
469
484
  async function handleVisualize(params) {
470
485
  const scope = params.scope;
471
- const { generateVisualizeReport } = await import("./kumaVisualize-TECABHUY.js");
486
+ const { generateVisualizeReport } = await import("./kumaVisualize-AFL7STLL.js");
472
487
  return await generateVisualizeReport({
473
488
  scope,
474
489
  type: "flowchart",
@@ -478,11 +493,11 @@ async function handleVisualize(params) {
478
493
  async function handleDigest(_params) {
479
494
  sessionMemory.recordToolCall("kuma_context_digest", {});
480
495
  try {
481
- const { generateContextDigest } = await import("./contextDigest-4PCK3DSM.js");
496
+ const { generateContextDigest } = await import("./contextDigest-5JXLH56Z.js");
482
497
  return await generateContextDigest();
483
498
  } catch (err) {
484
499
  try {
485
- const { generateDigest } = await import("./domainRules-LDZPOIGZ.js");
500
+ const { generateDigest } = await import("./domainRules-ED6EOFVY.js");
486
501
  return generateDigest();
487
502
  } catch {
488
503
  return `Error generating digest: ${err}`;
@@ -492,7 +507,7 @@ async function handleDigest(_params) {
492
507
  async function handleDrift(_params) {
493
508
  sessionMemory.recordToolCall("kuma_context_drift", {});
494
509
  try {
495
- const { detectDrift, formatDriftReport, flagStaleRecords } = await import("./kumaDriftDetector-OESI5GTC.js");
510
+ const { detectDrift, formatDriftReport, flagStaleRecords } = await import("./kumaDriftDetector-QBY6OJOO.js");
496
511
  await flagStaleRecords();
497
512
  const records = await detectDrift();
498
513
  return formatDriftReport(records);
@@ -500,6 +515,42 @@ async function handleDrift(_params) {
500
515
  return `Error detecting drift: ${err}`;
501
516
  }
502
517
  }
518
+ async function handleProgressive(params) {
519
+ sessionMemory.recordToolCall("kuma_context_progressive", { scope: params.scope, section: params.section });
520
+ try {
521
+ const { getProgressiveContext, loadSection } = await import("./kumaProgressiveContext-CVSNPY3W.js");
522
+ if (params.section) {
523
+ const validSections = ["domain_rules", "architecture", "gotchas", "decisions", "graph", "changes", "health"];
524
+ if (!validSections.includes(params.section)) {
525
+ return `\u26A0\uFE0F Invalid section "${params.section}". Valid sections: ${validSections.join(", ")}`;
526
+ }
527
+ const content = await loadSection(params.section, params.scope);
528
+ return [
529
+ `\u{1F9E9} **Progressive Context** \u2014 Section: ${params.section}`,
530
+ `\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`,
531
+ "",
532
+ content
533
+ ].join("\n");
534
+ }
535
+ const result = await getProgressiveContext(params.scope);
536
+ const lines = [
537
+ "\u{1F9E9} **Progressive Context**",
538
+ `\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`,
539
+ "",
540
+ `\u{1F4CB} **Meta**: ${result.meta}`,
541
+ `\u{1F517} **Skill Boundary**: ${result.boundary.name} \u2014 ${result.boundary.description}`,
542
+ ""
543
+ ];
544
+ for (const section of result.sections) {
545
+ lines.push(section.content);
546
+ lines.push("");
547
+ }
548
+ lines.push("\u{1F4A1} Use kuma_context({ action: 'progressive', section: 'gotchas', scope: 'auth' }) to load specific context on demand.");
549
+ return lines.join("\n");
550
+ } catch (err) {
551
+ return `Error generating progressive context: ${err}`;
552
+ }
553
+ }
503
554
  function computeProjectHash(scope) {
504
555
  try {
505
556
  const root = getProjectRoot();
@@ -601,7 +652,25 @@ var MEMORY_ALIASES = {
601
652
  // Layers summary
602
653
  "layers": "layers",
603
654
  "3-layer": "layers",
604
- "memory-layers": "layers"
655
+ "memory-layers": "layers",
656
+ // Federated synonyms (Issue #27)
657
+ "federated": "federated",
658
+ "federated-graph": "federated",
659
+ "kuma-uri": "federated",
660
+ "remote-graph": "federated",
661
+ // Test generation synonyms (Issue #28)
662
+ "gen_test": "gen_test",
663
+ "gen-test": "gen_test",
664
+ "generate-test": "gen_test",
665
+ "gentest": "gen_test",
666
+ // Trajectory synonyms
667
+ "trajectory": "trajectory",
668
+ "trajectories": "trajectory",
669
+ "traj": "trajectory",
670
+ // Skills synonyms
671
+ "skills": "skills",
672
+ "distilled-skills": "skills",
673
+ "skill-list": "skills"
605
674
  };
606
675
  async function handleMemory(params) {
607
676
  const rawAction = params.action || "session";
@@ -639,6 +708,14 @@ async function handleMemory(params) {
639
708
  return handleGotchaAction(params);
640
709
  case "layers":
641
710
  return handleLayersSummary(params);
711
+ case "federated":
712
+ return handleFederated(params);
713
+ case "gen_test":
714
+ return handleGenTest(params);
715
+ case "trajectory":
716
+ return handleTrajectoryList(params);
717
+ case "skills":
718
+ return handleSkillsList(params);
642
719
  default:
643
720
  return `Unknown action "${action}".`;
644
721
  }
@@ -649,7 +726,7 @@ async function handleDecision(params) {
649
726
  case "template":
650
727
  return formatDecisionTemplate();
651
728
  case "suggest": {
652
- const { shouldRecordDecision } = await import("./kumaMemory-7TCUDVZX.js");
729
+ const { shouldRecordDecision } = await import("./kumaMemory-FMOWIODH.js");
653
730
  const check = shouldRecordDecision();
654
731
  return check.worth ? `\u{1F4A1} Decision suggested: "${check.title}"
655
732
  Use kuma_memory({ action: 'decision', title: '...', context: '...', rationale: '...', outcome: '...' }) to record.` : "\u2705 No decision needed at this time.";
@@ -727,11 +804,11 @@ async function handleSearch(params) {
727
804
  if (!query) return "\u26A0\uFE0F query or scope parameter required.";
728
805
  const limit = params.limit || 20;
729
806
  const memResults = sessionMemory.searchMemory(query, limit);
730
- const { searchGraph: searchGraph2 } = await import("./kumaGraph-AWP743TJ.js");
807
+ const { searchGraph: searchGraph2 } = await import("./kumaGraph-GUQM75WL.js");
731
808
  const graphResults = await searchGraph2(query, Math.min(limit, 10));
732
809
  let hybridResults = "";
733
810
  try {
734
- const { hybridSearch, formatHybridResults } = await import("./kumaSearch-QGB4QVXS.js");
811
+ const { hybridSearch, formatHybridResults } = await import("./kumaSearch-B5WVYHHD.js");
735
812
  const semanticResults = await hybridSearch(query, 8);
736
813
  if (semanticResults.length > 0) {
737
814
  hybridResults = "\n" + formatHybridResults(query, semanticResults);
@@ -815,7 +892,7 @@ async function handleDecisionLog(params) {
815
892
  }
816
893
  async function handleMine(params) {
817
894
  sessionMemory.recordToolCall("kuma_memory_mine", { scope: params.scope });
818
- const { mineHistoricalDecisions } = await import("./kumaMiner-FFXSRHAO.js");
895
+ const { mineHistoricalDecisions } = await import("./kumaMiner-3RXEOCBP.js");
819
896
  return await mineHistoricalDecisions({
820
897
  scope: params.scope,
821
898
  since: typeof params.since === "string" ? params.since : void 0,
@@ -824,7 +901,7 @@ async function handleMine(params) {
824
901
  });
825
902
  }
826
903
  async function handleLayerAction(layer, params) {
827
- const { readLayer, writeLayer } = await import("./domainRules-LDZPOIGZ.js");
904
+ const { readLayer, writeLayer } = await import("./domainRules-ED6EOFVY.js");
828
905
  if (params.content) {
829
906
  return writeLayer(layer, params.content);
830
907
  }
@@ -832,7 +909,7 @@ async function handleLayerAction(layer, params) {
832
909
  }
833
910
  async function handleGotchaAction(params) {
834
911
  if (params.content && params.scope) {
835
- const { addGotcha } = await import("./kumaGotchas-DU5H6N7X.js");
912
+ const { addGotcha } = await import("./kumaGotchas-5HODT5RI.js");
836
913
  return await addGotcha({
837
914
  filePath: params.scope,
838
915
  description: params.content,
@@ -840,15 +917,46 @@ async function handleGotchaAction(params) {
840
917
  workaround: params.description
841
918
  });
842
919
  }
843
- const { listGotchas, syncGotchasToDb } = await import("./kumaGotchas-DU5H6N7X.js");
920
+ const { listGotchas, syncGotchasToDb } = await import("./kumaGotchas-5HODT5RI.js");
844
921
  await syncGotchasToDb();
845
922
  return await listGotchas({
846
923
  filePath: params.scope,
847
924
  severity: params.status
848
925
  });
849
926
  }
927
+ async function handleFederated(params) {
928
+ sessionMemory.recordToolCall("kuma_memory_federated", { scope: params.scope, uri: params.uri });
929
+ if (params.uri) {
930
+ const { resolveFederatedNode } = await import("./kumaGraph-GUQM75WL.js");
931
+ return await resolveFederatedNode(params.uri);
932
+ }
933
+ const { listFederatedReferences } = await import("./kumaGraph-GUQM75WL.js");
934
+ return await listFederatedReferences();
935
+ }
936
+ async function handleGenTest(params) {
937
+ sessionMemory.recordToolCall("kuma_memory_gen_test", { target: params.target });
938
+ if (params.target) {
939
+ const id = parseInt(params.target, 10);
940
+ if (!isNaN(id)) {
941
+ const { generateTestFromTrajectoryId } = await import("./kumaTrajectory-T6DXGOG4.js");
942
+ return await generateTestFromTrajectoryId(id);
943
+ }
944
+ }
945
+ const { listGeneratedTests } = await import("./kumaTrajectory-T6DXGOG4.js");
946
+ return await listGeneratedTests();
947
+ }
948
+ async function handleTrajectoryList(params) {
949
+ sessionMemory.recordToolCall("kuma_memory_trajectory", {});
950
+ const { listTrajectories } = await import("./kumaTrajectory-T6DXGOG4.js");
951
+ return await listTrajectories(params.limit || 10);
952
+ }
953
+ async function handleSkillsList(_params) {
954
+ sessionMemory.recordToolCall("kuma_memory_skills", {});
955
+ const { listDistilledSkills } = await import("./kumaTrajectory-T6DXGOG4.js");
956
+ return await listDistilledSkills();
957
+ }
850
958
  async function handleLayersSummary(_params) {
851
- const { getLayersSummary } = await import("./domainRules-LDZPOIGZ.js");
959
+ const { getLayersSummary } = await import("./domainRules-ED6EOFVY.js");
852
960
  return getLayersSummary();
853
961
  }
854
962
 
@@ -1797,6 +1905,14 @@ async function handleSafety(params) {
1797
1905
  case "ast":
1798
1906
  case "validate":
1799
1907
  return handleAstValidation(params);
1908
+ case "checkpoint":
1909
+ return handleCheckpoint(params);
1910
+ case "rollback_label":
1911
+ return handleRollbackLabel(params);
1912
+ case "checkpoint_list":
1913
+ return handleCheckpointList(params);
1914
+ case "contract":
1915
+ return handleContract(params);
1800
1916
  default:
1801
1917
  return `Unknown action "${action}".`;
1802
1918
  }
@@ -1840,7 +1956,7 @@ async function handleLock(params) {
1840
1956
  }
1841
1957
  async function handleHealth2(_params) {
1842
1958
  try {
1843
- const { computeSafetyScore, formatSafetyScore } = await import("./safetyScore-GR5N55CU.js");
1959
+ const { computeSafetyScore, formatSafetyScore } = await import("./safetyScore-WU27EOG4.js");
1844
1960
  const score = await computeSafetyScore();
1845
1961
  await saveHealthSnapshot(score.score, score.risk, JSON.stringify(score.checks), score.summary);
1846
1962
  return formatSafetyScore(score);
@@ -1947,7 +2063,7 @@ async function handleClean(_params) {
1947
2063
  async function handlePolicy(params) {
1948
2064
  sessionMemory.recordToolCall("kuma_safety_policy", {});
1949
2065
  if (params.command) {
1950
- const { evaluateCommand, evaluateFilePath } = await import("./kumaPolicyEngine-S2PXN3C7.js");
2066
+ const { evaluateCommand, evaluateFilePath } = await import("./kumaPolicyEngine-ORBWL5PT.js");
1951
2067
  const commandVerdict = evaluateCommand(params.command);
1952
2068
  const lines = [];
1953
2069
  lines.push(`\u{1F4DC} **Policy Check**: ${commandVerdict.allowed ? "\u2705 Allowed" : "\u26D4 Blocked"}`);
@@ -1974,7 +2090,7 @@ async function handlePolicy(params) {
1974
2090
  }
1975
2091
  return lines.join("\n");
1976
2092
  }
1977
- const { formatPolicyStatus } = await import("./kumaPolicyEngine-S2PXN3C7.js");
2093
+ const { formatPolicyStatus } = await import("./kumaPolicyEngine-ORBWL5PT.js");
1978
2094
  return formatPolicyStatus();
1979
2095
  }
1980
2096
  async function handleAstValidation(params) {
@@ -1990,6 +2106,39 @@ async function handleAstValidation(params) {
1990
2106
  }
1991
2107
  return "\u26A0\uFE0F Provide a scope (file path) or command (code content) to validate.";
1992
2108
  }
2109
+ async function handleCheckpoint(params) {
2110
+ sessionMemory.recordToolCall("kuma_safety_checkpoint", { label: params.label });
2111
+ if (!params.label) return "\u26A0\uFE0F label parameter required. Example: kuma_safety({ action: 'checkpoint', label: 'pre-feature-x' })";
2112
+ const { createCheckpoint } = await import("./kumaCheckpoint-XIQWRMGV.js");
2113
+ return await createCheckpoint(params.label, params.description);
2114
+ }
2115
+ async function handleRollbackLabel(params) {
2116
+ sessionMemory.recordToolCall("kuma_safety_rollback_label", { label: params.label });
2117
+ if (!params.label) return "\u26A0\uFE0F label parameter required. Example: kuma_safety({ action: 'rollback_label', label: 'pre-feature-x' })";
2118
+ const { rollbackToCheckpoint } = await import("./kumaCheckpoint-XIQWRMGV.js");
2119
+ return await rollbackToCheckpoint(params.label);
2120
+ }
2121
+ async function handleCheckpointList(_params) {
2122
+ sessionMemory.recordToolCall("kuma_safety_checkpoint_list", {});
2123
+ const { listCheckpoints } = await import("./kumaCheckpoint-XIQWRMGV.js");
2124
+ return listCheckpoints();
2125
+ }
2126
+ async function handleContract(params) {
2127
+ sessionMemory.recordToolCall("kuma_safety_contract", {
2128
+ toolName: params.toolName || "edit",
2129
+ filePath: params.filePath,
2130
+ phase: params.phase || "pre"
2131
+ });
2132
+ const { runContractChecks, listContracts } = await import("./kumaContractEngine-KX27T4N7.js");
2133
+ if (!params.filePath && !params.toolName) {
2134
+ return listContracts();
2135
+ }
2136
+ return await runContractChecks(
2137
+ params.toolName || "edit",
2138
+ params.filePath,
2139
+ params.phase || "pre"
2140
+ );
2141
+ }
1993
2142
  var _lastVerifyCall = 0;
1994
2143
  var VERIFY_COOLDOWN_MS = 3e4;
1995
2144
  async function handleVerify(params) {
@@ -2000,7 +2149,7 @@ async function handleVerify(params) {
2000
2149
  }
2001
2150
  _lastVerifyCall = now;
2002
2151
  sessionMemory.recordToolCall("kuma_safety_verify", { scope: params.scope || params.filePath });
2003
- const { runAutoVerification } = await import("./kumaVerifier-ARSGPZAM.js");
2152
+ const { runAutoVerification } = await import("./kumaVerifier-KAYJHR5K.js");
2004
2153
  return await runAutoVerification({
2005
2154
  scope: params.scope || params.filePath,
2006
2155
  force: params.force,
@@ -2014,12 +2163,13 @@ function registerAllTools(server) {
2014
2163
  "kuma_context",
2015
2164
  "**Call FIRST every session.** Understand your project before making changes. Actions: init (load project brief), research (5-step pipeline: cache\u2192staleness\u2192graph\u2192impact\u2192decision), impact (analyze change effects), navigate (trace code flow), changes (view change log), health (project health score 0-100). RESEARCH IS REQUIRED before editing unfamiliar code.",
2016
2165
  {
2017
- action: z.enum(["init", "research", "impact", "navigate", "changes", "health", "rollback", "researches", "sync", "visualize", "digest", "drift"]).describe("Action: init=project brief, research=5-step research pipeline (REQUIRED before edits), impact=analyze change effects, navigate=trace code flow, changes=view change log, rollback=undo a change by ID, researches=list all cached research, sync=unified batch state, visualize=Mermaid knowledge graph diagram, digest=ultra-compact <500 token project briefing (Issue #18), drift=detect memory staleness & code drift (Issue #20), health=project health score"),
2018
- scope: z.string().optional().describe("Research scope for research action (e.g. 'auth', 'database', 'api')"),
2166
+ action: z.enum(["init", "research", "impact", "navigate", "changes", "health", "rollback", "researches", "sync", "visualize", "digest", "drift", "progressive"]).describe("Action: init=project brief, research=5-step research pipeline (REQUIRED before edits), impact=analyze change effects, navigate=trace code flow, changes=view change log, rollback=undo a change by ID, researches=list all cached research, sync=unified batch state, visualize=Mermaid knowledge graph diagram, digest=ultra-compact <500 token project briefing (Issue #18), drift=detect memory staleness & code drift (Issue #20), progressive=progressive context loading (Issue #25), health=project health score"),
2167
+ scope: z.string().optional().describe("Research scope for research/progressive action"),
2019
2168
  target: z.string().optional().describe("Target symbol/file for impact/navigate/changes"),
2020
2169
  goal: z.string().optional().describe("Current goal (for init/health)"),
2021
2170
  since: z.number().optional().describe("Unix timestamp filter for changes"),
2022
- compact: z.boolean().optional().default(false).describe("Compact output mode")
2171
+ compact: z.boolean().optional().default(false).describe("Compact output mode"),
2172
+ section: z.string().optional().describe("Context section for progressive action (domain_rules, architecture, gotchas, decisions, graph, changes, health)")
2023
2173
  },
2024
2174
  async (params) => {
2025
2175
  try {
@@ -2029,7 +2179,8 @@ function registerAllTools(server) {
2029
2179
  target: params.target,
2030
2180
  goal: params.goal,
2031
2181
  since: params.since,
2032
- compact: params.compact
2182
+ compact: params.compact,
2183
+ section: params.section
2033
2184
  });
2034
2185
  return { content: [{ type: "text", text }] };
2035
2186
  } catch (err) {
@@ -2041,8 +2192,8 @@ function registerAllTools(server) {
2041
2192
  "kuma_memory",
2042
2193
  "Record and retrieve project knowledge. Actions: decision (ADR-style record/template/suggest), mine (mine historical decisions from git log & code comments), research_save (save research), session (session summary), heal (graph repair), search (search all), changes (change log), todo (persistent todo CRUD), context (inject context notes), benchmark (capture/diff metrics), decision_log (living document with status tracking).",
2043
2194
  {
2044
- action: z.enum(["decision", "mine", "research_save", "session", "heal", "search", "changes", "todo", "context", "benchmark", "decision_log", "domain_rules", "arch_flow", "gotcha", "layers"]).describe("Memory action: decision=ADR, mine=mine git log & comments, research_save=save, session=summary, heal=repair, search=search, changes=log, todo=manage todos, context=inject notes, benchmark=capture/diff, decision_log=manage decisions, domain_rules=Layer 1 business rules (Issue #17), arch_flow=Layer 2 architecture flow (Issue #17), gotcha=Layer 3 known gotchas (Issue #17/#21), layers=all 3 layers summary"),
2045
- scope: z.string().optional().describe("Scope for research_save/search/todo/context/mine"),
2195
+ action: z.enum(["decision", "mine", "research_save", "session", "heal", "search", "changes", "todo", "context", "benchmark", "decision_log", "domain_rules", "arch_flow", "gotcha", "layers", "federated", "gen_test", "trajectory", "skills"]).describe("Memory action: decision=ADR, mine=mine git log & comments, research_save=save, session=summary, heal=repair, search=search, changes=log, todo=manage todos, context=inject notes, benchmark=capture/diff, decision_log=manage decisions, domain_rules=Layer 1 business rules (Issue #17), arch_flow=Layer 2 architecture flow (Issue #17), gotcha=Layer 3 known gotchas (Issue #17/#21), layers=all 3 layers summary, federated=resolve federated kuma:// URI (Issue #27), gen_test=generate test from trajectory (Issue #28), trajectory=list trajectories, skills=list distilled skills"),
2196
+ scope: z.string().optional().describe("Scope for research_save/search/todo/context/mine/federated"),
2046
2197
  query: z.string().optional().describe("Search query for search action"),
2047
2198
  content: z.string().optional().describe("Content/notes for research_save / context"),
2048
2199
  record: z.string().optional().describe("JSON record string for research_save"),
@@ -2058,7 +2209,7 @@ function registerAllTools(server) {
2058
2209
  healAction: z.enum(["check", "heal"]).optional().describe("Heal sub-action"),
2059
2210
  topic: z.string().optional().describe("Memory topic for session"),
2060
2211
  limit: z.number().min(1).max(100).optional().describe("Result limit"),
2061
- target: z.string().optional().describe("File path for changes / decision_log ID"),
2212
+ target: z.string().optional().describe("File path for changes / decision_log ID / trajectory ID"),
2062
2213
  since: z.number().optional().describe("Timestamp filter for changes"),
2063
2214
  compact: z.boolean().optional().default(false).describe("Compact output mode"),
2064
2215
  // Todo params
@@ -2072,7 +2223,9 @@ function registerAllTools(server) {
2072
2223
  // Benchmark params
2073
2224
  label: z.string().optional().describe("Benchmark label"),
2074
2225
  metrics: z.string().optional().describe("Benchmark metrics JSON"),
2075
- labelB: z.string().optional().describe("Second benchmark label for diff")
2226
+ labelB: z.string().optional().describe("Second benchmark label for diff"),
2227
+ // Federated params (#27)
2228
+ uri: z.string().optional().describe("Federated URI (kuma://project/node-id)")
2076
2229
  },
2077
2230
  async (params) => {
2078
2231
  try {
@@ -2093,7 +2246,8 @@ function registerAllTools(server) {
2093
2246
  topic: params.topic,
2094
2247
  limit: params.limit,
2095
2248
  target: params.target,
2096
- since: params.since
2249
+ since: params.since,
2250
+ uri: params.uri
2097
2251
  });
2098
2252
  return { content: [{ type: "text", text }] };
2099
2253
  } catch (err) {
@@ -2105,14 +2259,14 @@ function registerAllTools(server) {
2105
2259
  "kuma_safety",
2106
2260
  "Safety checks, policy enforcement, security scanning, integrated auto-verification, and project hygiene. Actions: guard (anti-pattern detection), verify (auto-run scoped tests), check (pre-exec safety), audit (query trail), lock (multi-agent), health (score), security (scan for leaks), gc (garbage collection), doctor (health check), portability (path check), gitignore (auto-config), override (bypass).",
2107
2261
  {
2108
- action: z.enum(["guard", "verify", "check", "audit", "lock", "health", "override", "security", "gc", "doctor", "portability", "gitignore", "clean", "policy", "ast", "validate"]).describe("Safety action: guard=anti-patterns, verify=auto-run scoped tests, check=pre-exec safety, audit=query trail, lock=multi-agent, health=score, security=scan leaks, gc=garbage collect, doctor=health check, portability=paths, gitignore=config, clean=purge scratch dir & drift, policy=Policy-as-Code engine (Issue #24), ast/validate=AST-based code validation (Issue #22), override=bypass"),
2262
+ action: z.enum(["guard", "verify", "check", "audit", "lock", "health", "override", "security", "gc", "doctor", "portability", "gitignore", "clean", "policy", "ast", "validate", "checkpoint", "rollback_label", "checkpoint_list", "contract"]).describe("Safety action: guard=anti-patterns, verify=auto-run scoped tests, check=pre-exec safety, audit=query trail, lock=multi-agent, health=score, security=scan leaks, gc=garbage collect, doctor=health check, portability=paths, gitignore=config, clean=purge scratch dir & drift, policy=Policy-as-Code engine (Issue #24), ast/validate=AST-based code validation (Issue #22), checkpoint=create atomic snapshot (Issue #29), rollback_label=restore from checkpoint (Issue #29), checkpoint_list=list checkpoints, contract=run contract checks (Issue #26), override=bypass"),
2109
2263
  // Verify params
2110
2264
  scope: z.string().optional().describe("Scope for verify or context (e.g. 'auth', file path)"),
2111
2265
  // Guard params
2112
2266
  guardGoal: z.string().optional().describe("Goal for guard check"),
2113
2267
  guardCheck: z.enum(["all", "anti-pattern", "loop", "drift", "context"]).optional().describe("Guard check type"),
2114
2268
  // Check params
2115
- filePath: z.string().optional().describe("File path for check/lock/security scan"),
2269
+ filePath: z.string().optional().describe("File path for check/lock/security scan/contract"),
2116
2270
  command: z.string().optional().describe("Command for check"),
2117
2271
  // Audit params
2118
2272
  toolName: z.string().optional().describe("Filter audit by tool name"),
@@ -2126,7 +2280,12 @@ function registerAllTools(server) {
2126
2280
  agentId: z.string().optional().describe("Agent ID for lock"),
2127
2281
  // Override params
2128
2282
  reason: z.string().optional().describe("Reason for safety override"),
2129
- compact: z.boolean().optional().default(false).describe("Compact output mode")
2283
+ compact: z.boolean().optional().default(false).describe("Compact output mode"),
2284
+ // Checkpoint params (#29)
2285
+ label: z.string().optional().describe("Checkpoint label for checkpoint/rollback_label actions"),
2286
+ description: z.string().optional().describe("Description for checkpoint"),
2287
+ // Contract params (#26)
2288
+ phase: z.enum(["pre", "post"]).optional().describe("Contract check phase")
2130
2289
  },
2131
2290
  async (params) => {
2132
2291
  try {
@@ -2145,7 +2304,10 @@ function registerAllTools(server) {
2145
2304
  lockAction: params.lockAction,
2146
2305
  lockFilePath: params.lockFilePath,
2147
2306
  agentId: params.agentId,
2148
- reason: params.reason
2307
+ reason: params.reason,
2308
+ label: params.label,
2309
+ description: params.description,
2310
+ phase: params.phase
2149
2311
  });
2150
2312
  return { content: [{ type: "text", text }] };
2151
2313
  } catch (err) {
@@ -2172,6 +2334,7 @@ Usage:
2172
2334
  npx @plumpslabs/kuma init --merge Append to existing files (default)
2173
2335
  npx @plumpslabs/kuma init --skip-existing Skip generation if file exists
2174
2336
  npx @plumpslabs/kuma init --claude --cursor Generate specific files
2337
+ npx @plumpslabs/kuma studio Start Kuma Studio web dashboard (knowledge graph visualizer)
2175
2338
  npx @plumpslabs/kuma init --help Show this help
2176
2339
 
2177
2340
  Available config files:
@@ -2199,7 +2362,7 @@ async function main() {
2199
2362
  console.error("");
2200
2363
  let killedCount = 0;
2201
2364
  try {
2202
- const { getRunningVerificationPid } = await import("./kumaVerifier-ARSGPZAM.js");
2365
+ const { getRunningVerificationPid } = await import("./kumaVerifier-KAYJHR5K.js");
2203
2366
  const pid = getRunningVerificationPid();
2204
2367
  if (pid) {
2205
2368
  try {
@@ -2291,6 +2454,31 @@ async function main() {
2291
2454
  console.error("");
2292
2455
  process.exit(0);
2293
2456
  }
2457
+ if (args[0] === "studio") {
2458
+ const { fileURLToPath } = await import("url");
2459
+ const { dirname, join } = await import("path");
2460
+ const { spawn } = await import("child_process");
2461
+ const { existsSync } = await import("fs");
2462
+ const distDir = dirname(fileURLToPath(import.meta.url));
2463
+ const studioPath = join(distDir, "..", "packages", "ide", "studio", "dist", "index.js");
2464
+ if (!existsSync(studioPath)) {
2465
+ console.error(`[${SERVER_NAME}] Kuma Studio not found at ${studioPath}`);
2466
+ console.error(`[${SERVER_NAME}] Make sure @plumpslabs/kuma is properly installed.`);
2467
+ console.error(`[${SERVER_NAME}] Or run manually: cd packages/ide/studio && pnpm start`);
2468
+ process.exit(1);
2469
+ }
2470
+ const studioArgs = args.slice(1);
2471
+ const child = spawn("node", [studioPath, ...studioArgs], {
2472
+ stdio: "inherit",
2473
+ cwd: process.cwd()
2474
+ });
2475
+ child.on("exit", (code) => process.exit(code ?? 1));
2476
+ child.on("error", (err) => {
2477
+ console.error(`[${SERVER_NAME}] Failed to start Kuma Studio: ${err.message}`);
2478
+ process.exit(1);
2479
+ });
2480
+ return;
2481
+ }
2294
2482
  if (args[0] === "--hook") {
2295
2483
  process.exit(0);
2296
2484
  }
@@ -2441,7 +2629,7 @@ async function main() {
2441
2629
  console.error(`[${SERVER_NAME}] \u2705 Restored session (${sessionInfo.toolCallCount} previous tool calls)`);
2442
2630
  }
2443
2631
  try {
2444
- const { buildFromSessionMemory } = await import("./kumaGraph-AWP743TJ.js");
2632
+ const { buildFromSessionMemory } = await import("./kumaGraph-GUQM75WL.js");
2445
2633
  const edgeCount = await buildFromSessionMemory();
2446
2634
  if (edgeCount > 0) {
2447
2635
  console.error(`[${SERVER_NAME}] \u2705 Graph auto-populated with ${edgeCount} entries from session memory`);
@@ -2461,7 +2649,7 @@ async function main() {
2461
2649
  console.error(`[${SERVER_NAME}] \u26A0\uFE0F Scratch directory setup: ${err}`);
2462
2650
  }
2463
2651
  try {
2464
- const { getDb: getDb2, saveDb } = await import("./kumaDb-6D53ERFP.js");
2652
+ const { getDb: getDb2, saveDb } = await import("./kumaDb-IC7UX7PU.js");
2465
2653
  const db = await getDb2();
2466
2654
  db.run(
2467
2655
  `INSERT INTO sessions (started_at, goal, tool_calls) VALUES (?, ?, ?)`,
@@ -2501,7 +2689,7 @@ fi
2501
2689
  console.error(`[${SERVER_NAME}] \u26A0\uFE0F Auto-capture hook setup: ${err}`);
2502
2690
  }
2503
2691
  try {
2504
- const { buildSearchVectors } = await import("./kumaSearch-QGB4QVXS.js");
2692
+ const { buildSearchVectors } = await import("./kumaSearch-B5WVYHHD.js");
2505
2693
  const vectors = await buildSearchVectors();
2506
2694
  if (vectors.length > 0) {
2507
2695
  console.error(`[${SERVER_NAME}] \u2705 Search vector cache pre-warmed (${vectors.length} documents)`);