@a-company/paradigm 3.43.0 → 3.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/{chunk-YW5OCVKB.js → chunk-FKJUBQU3.js} +14 -1
  2. package/dist/chunk-KVDYJLTC.js +121 -0
  3. package/dist/{symphony-ROEKK7VD.js → chunk-S2HO5MLR.js} +53 -431
  4. package/dist/{chunk-RGFANZ4Q.js → chunk-ZDHLG5VP.js} +14 -1
  5. package/dist/{chunk-CZEIK3Y2.js → chunk-ZMQA6SCO.js} +1 -1
  6. package/dist/{chunk-7WEKMZ46.js → chunk-ZSYVKSY6.js} +1 -1
  7. package/dist/{commands-LEPFD7S5.js → commands-5N4ILTPH.js} +13 -0
  8. package/dist/{dist-RVKYUCRU.js → dist-CM3MVWWW.js} +1 -1
  9. package/dist/{dist-Y7I3CFY5.js → dist-POMVY6WP.js} +2 -2
  10. package/dist/{habits-O37HTUKE.js → habits-RG5SVKXP.js} +2 -2
  11. package/dist/index.js +69 -48
  12. package/dist/mcp.js +89 -9
  13. package/dist/peers-RFQCWVLV.js +82 -0
  14. package/dist/{platform-server-KK4OCRTV.js → platform-server-H7Y6Q7O4.js} +10 -1
  15. package/dist/{reindex-NZQRGKPN.js → reindex-WIJMCJ4A.js} +1 -1
  16. package/dist/{sentinel-BKYTBT7M.js → sentinel-UOIGJWHH.js} +1 -1
  17. package/dist/{sentinel-bridge-IZTXYS5M.js → sentinel-bridge-APDXYAZS.js} +1 -1
  18. package/dist/sentinel-mcp.js +13 -0
  19. package/dist/sentinel.js +6 -6
  20. package/dist/{serve-3V2WXLGM.js → serve-KKEHE44G.js} +1 -1
  21. package/dist/{server-OFEJ2HJP.js → server-JV6UFGWZ.js} +1 -1
  22. package/dist/symphony-6K3HD7AW.js +791 -0
  23. package/dist/symphony-YCHBYN3E.js +326 -0
  24. package/dist/symphony-peers-APOGJPF4.js +120 -0
  25. package/dist/symphony-peers-HSY3RI3S.js +34 -0
  26. package/dist/symphony-relay-GTAJRCVF.js +683 -0
  27. package/dist/{triage-POXJ2TIX.js → triage-IZ4MDYNB.js} +2 -2
  28. package/dist/university-content/courses/para-501.json +84 -0
  29. package/package.json +1 -1
  30. package/platform-ui/dist/assets/{GitSection-DvyJBF_-.js → GitSection-BD3Ze06e.js} +1 -1
  31. package/platform-ui/dist/assets/{GraphSection-BiQrXqfs.js → GraphSection-SglITfSs.js} +1 -1
  32. package/platform-ui/dist/assets/{LoreSection-BaH1FaRb.js → LoreSection-bR5Km4Fd.js} +1 -1
  33. package/platform-ui/dist/assets/{SentinelSection-DemAznjI.js → SentinelSection-QSpAZArG.js} +1 -1
  34. package/platform-ui/dist/assets/SymphonySection-CobYJgvg.js +1 -0
  35. package/platform-ui/dist/assets/SymphonySection-zY0C5tFl.css +1 -0
  36. package/platform-ui/dist/assets/{index-DDKhCt-w.js → index-DbxeSMkV.js} +11 -11
  37. package/platform-ui/dist/index.html +1 -1
@@ -4405,7 +4405,7 @@ function assertStep(step, event) {
4405
4405
  async function validateAgainstSentinel(persona, options = {}) {
4406
4406
  const steps = [];
4407
4407
  try {
4408
- const { SentinelStorage } = await import("./dist-RVKYUCRU.js");
4408
+ const { SentinelStorage } = await import("./dist-CM3MVWWW.js");
4409
4409
  const storage = new SentinelStorage();
4410
4410
  const events = storage.queryEvents?.({
4411
4411
  schemaId: "paradigm-personas",
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  SentinelStorage
4
- } from "./chunk-YW5OCVKB.js";
4
+ } from "./chunk-FKJUBQU3.js";
5
5
 
6
6
  // ../sentinel/dist/chunk-VQ3SIN7S.js
7
7
  import { v4 as uuidv4 } from "uuid";
@@ -599,6 +599,19 @@ var SentinelStorage = class {
599
599
  );
600
600
  this.save();
601
601
  }
602
+ resolveIncident(id, options) {
603
+ this.updateIncident(id, {
604
+ status: "resolved",
605
+ resolvedAt: (/* @__PURE__ */ new Date()).toISOString()
606
+ });
607
+ if (options?.notes) {
608
+ this.addIncidentNote(id, {
609
+ author: "system",
610
+ content: options.notes,
611
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
612
+ });
613
+ }
614
+ }
602
615
  addIncidentNote(incidentId, note) {
603
616
  this.initializeSync();
604
617
  const incident = this.getIncident(incidentId);
@@ -28,7 +28,7 @@ import {
28
28
  loadServerConfig,
29
29
  loadUniversalPatterns,
30
30
  writeConfig
31
- } from "./chunk-RGFANZ4Q.js";
31
+ } from "./chunk-ZDHLG5VP.js";
32
32
  export {
33
33
  ContextEnricher,
34
34
  DEFAULT_AUTH_CONFIG,
@@ -19,7 +19,7 @@ import {
19
19
  loadAllSeedPatterns,
20
20
  loadParadigmPatterns,
21
21
  loadUniversalPatterns
22
- } from "./chunk-7WEKMZ46.js";
22
+ } from "./chunk-ZSYVKSY6.js";
23
23
  import {
24
24
  DEFAULT_AUTH_CONFIG,
25
25
  DEFAULT_RATE_LIMIT_CONFIG,
@@ -30,7 +30,7 @@ import {
30
30
  loadConfig,
31
31
  loadServerConfig,
32
32
  writeConfig
33
- } from "./chunk-YW5OCVKB.js";
33
+ } from "./chunk-FKJUBQU3.js";
34
34
  import "./chunk-ZXMDA7VB.js";
35
35
  export {
36
36
  ContextEnricher,
@@ -934,7 +934,7 @@ async function habitsStatusCommand(options) {
934
934
  const enabled = getEnabledHabits(habits);
935
935
  let practiceData = null;
936
936
  try {
937
- const { SentinelStorage } = await import("./dist-Y7I3CFY5.js");
937
+ const { SentinelStorage } = await import("./dist-POMVY6WP.js");
938
938
  const sentinelDir = path3.join(rootDir, ".paradigm", "sentinel");
939
939
  if (fs2.existsSync(sentinelDir)) {
940
940
  const storage = new SentinelStorage(sentinelDir);
@@ -1302,7 +1302,7 @@ async function habitsCheckCommand(options) {
1302
1302
  try {
1303
1303
  const sentinelDir = path3.join(rootDir, ".paradigm", "sentinel");
1304
1304
  if (fs2.existsSync(sentinelDir)) {
1305
- const { SentinelStorage } = await import("./dist-Y7I3CFY5.js");
1305
+ const { SentinelStorage } = await import("./dist-POMVY6WP.js");
1306
1306
  const storage = new SentinelStorage(sentinelDir);
1307
1307
  for (const e of evaluation.evaluations) {
1308
1308
  storage.recordPracticeEvent({
package/dist/index.js CHANGED
@@ -588,76 +588,76 @@ hooksCmd.action(async () => {
588
588
  });
589
589
  var triageCmd = program.command("triage").description("Semantic error triage - incident management and pattern matching");
590
590
  triageCmd.command("list").alias("ls").description("List recent incidents with matched patterns").option("-l, --limit <number>", "Maximum incidents to show", "10").option("-s, --status <status>", "Filter by status: open, investigating, resolved, wont-fix, all").option("--symbol <symbol>", "Filter by symbol (e.g., @checkout, ^auth)").option("-e, --env <environment>", "Filter by environment").option("--search <text>", "Search in error messages").option("--from <date>", "Filter from date (ISO format)").option("--to <date>", "Filter to date (ISO format)").option("--json", "Output as JSON").action(async (options) => {
591
- const { triageListCommand } = await import("./triage-POXJ2TIX.js");
591
+ const { triageListCommand } = await import("./triage-IZ4MDYNB.js");
592
592
  await triageListCommand(options);
593
593
  });
594
594
  triageCmd.command("show <id>").description("Show full incident details").option("--timeline", "Include flow timeline").option("--json", "Output as JSON").action(async (id, options) => {
595
- const { triageShowCommand } = await import("./triage-POXJ2TIX.js");
595
+ const { triageShowCommand } = await import("./triage-IZ4MDYNB.js");
596
596
  await triageShowCommand(id, options);
597
597
  });
598
598
  triageCmd.command("resolve <id>").description("Mark incident as resolved").option("-p, --pattern <patternId>", "Pattern that led to resolution").option("-c, --commit <hash>", "Git commit hash of fix").option("--pr <url>", "Pull request URL").option("-n, --notes <text>", "Resolution notes").option("--wont-fix", "Mark as will not fix").action(async (id, options) => {
599
- const { triageResolveCommand } = await import("./triage-POXJ2TIX.js");
599
+ const { triageResolveCommand } = await import("./triage-IZ4MDYNB.js");
600
600
  await triageResolveCommand(id, options);
601
601
  });
602
602
  triageCmd.command("note <id> <note>").description("Add a note to an incident").action(async (id, note) => {
603
- const { triageNoteCommand } = await import("./triage-POXJ2TIX.js");
603
+ const { triageNoteCommand } = await import("./triage-IZ4MDYNB.js");
604
604
  await triageNoteCommand(id, note);
605
605
  });
606
606
  triageCmd.command("link <id1> <id2>").description("Link two related incidents").action(async (id1, id2) => {
607
- const { triageLinkCommand } = await import("./triage-POXJ2TIX.js");
607
+ const { triageLinkCommand } = await import("./triage-IZ4MDYNB.js");
608
608
  await triageLinkCommand(id1, id2);
609
609
  });
610
610
  var triagePatternsCmd = triageCmd.command("patterns").description("Manage failure patterns");
611
611
  triagePatternsCmd.command("list").alias("ls").description("List all patterns").option("--source <source>", "Filter by source: manual, suggested, imported, community").option("--min-confidence <score>", "Minimum confidence score").option("--json", "Output as JSON").action(async (options) => {
612
- const { triagePatternsListCommand } = await import("./triage-POXJ2TIX.js");
612
+ const { triagePatternsListCommand } = await import("./triage-IZ4MDYNB.js");
613
613
  await triagePatternsListCommand(options);
614
614
  });
615
615
  triagePatternsCmd.command("show <id>").description("Show pattern details").option("--json", "Output as JSON").action(async (id, options) => {
616
- const { triagePatternsShowCommand } = await import("./triage-POXJ2TIX.js");
616
+ const { triagePatternsShowCommand } = await import("./triage-IZ4MDYNB.js");
617
617
  await triagePatternsShowCommand(id, options);
618
618
  });
619
619
  triagePatternsCmd.command("add").description("Create a new pattern").requiredOption("--id <id>", "Pattern ID (kebab-case)").requiredOption("--name <name>", "Human-readable name").option("--description <text>", "Pattern description").option("--symbols <pairs>", 'Symbol criteria (e.g., "feature:@checkout,gate:^auth")').option("--error-contains <keywords>", "Error keywords (comma-separated)").option("--missing-signals <signals>", "Expected missing signals (comma-separated)").option("--strategy <strategy>", "Resolution strategy: retry, fallback, fix-data, fix-code, ignore, escalate", "fix-code").option("--priority <priority>", "Priority: low, medium, high, critical", "medium").option("--code-hint <text>", "Code hint for resolution").option("--tags <tags>", "Tags (comma-separated)").option("--from-incident <id>", "Generate suggestion from incident").action(async (options) => {
620
- const { triagePatternsAddCommand } = await import("./triage-POXJ2TIX.js");
620
+ const { triagePatternsAddCommand } = await import("./triage-IZ4MDYNB.js");
621
621
  await triagePatternsAddCommand(options);
622
622
  });
623
623
  triagePatternsCmd.command("delete <id>").alias("rm").description("Delete a pattern").action(async (id) => {
624
- const { triagePatternsDeleteCommand } = await import("./triage-POXJ2TIX.js");
624
+ const { triagePatternsDeleteCommand } = await import("./triage-IZ4MDYNB.js");
625
625
  await triagePatternsDeleteCommand(id);
626
626
  });
627
627
  triagePatternsCmd.command("test <id>").description("Test pattern against historical incidents").option("-l, --limit <number>", "Max incidents to test against", "100").option("--json", "Output as JSON").action(async (id, options) => {
628
- const { triagePatternsTestCommand } = await import("./triage-POXJ2TIX.js");
628
+ const { triagePatternsTestCommand } = await import("./triage-IZ4MDYNB.js");
629
629
  await triagePatternsTestCommand(id, options);
630
630
  });
631
631
  triagePatternsCmd.command("seed").description("Load built-in seed patterns").action(async () => {
632
- const { triagePatternsSeedCommand } = await import("./triage-POXJ2TIX.js");
632
+ const { triagePatternsSeedCommand } = await import("./triage-IZ4MDYNB.js");
633
633
  await triagePatternsSeedCommand();
634
634
  });
635
635
  triagePatternsCmd.action(async () => {
636
- const { triagePatternsListCommand } = await import("./triage-POXJ2TIX.js");
636
+ const { triagePatternsListCommand } = await import("./triage-IZ4MDYNB.js");
637
637
  await triagePatternsListCommand({});
638
638
  });
639
639
  triageCmd.command("export <type>").description("Export patterns or full backup (type: patterns, backup)").option("-o, --output <path>", "Output file path").option("--include-private", "Include private patterns").action(async (type, options) => {
640
- const { triageExportCommand } = await import("./triage-POXJ2TIX.js");
640
+ const { triageExportCommand } = await import("./triage-IZ4MDYNB.js");
641
641
  await triageExportCommand(type, options);
642
642
  });
643
643
  triageCmd.command("import <file>").description("Import patterns from JSON file").option("--overwrite", "Overwrite existing patterns").action(async (file, options) => {
644
- const { triageImportCommand } = await import("./triage-POXJ2TIX.js");
644
+ const { triageImportCommand } = await import("./triage-IZ4MDYNB.js");
645
645
  await triageImportCommand(file, options);
646
646
  });
647
647
  triageCmd.command("restore <file>").description("Restore from full backup").action(async (file) => {
648
- const { triageRestoreCommand } = await import("./triage-POXJ2TIX.js");
648
+ const { triageRestoreCommand } = await import("./triage-IZ4MDYNB.js");
649
649
  await triageRestoreCommand(file);
650
650
  });
651
651
  triageCmd.command("stats").description("Show statistics dashboard").option("-p, --period <period>", "Time period: 1d, 7d, 30d, 90d", "7d").option("--symbol <symbol>", "Show health for specific symbol").option("--json", "Output as JSON").action(async (options) => {
652
- const { triageStatsCommand } = await import("./triage-POXJ2TIX.js");
652
+ const { triageStatsCommand } = await import("./triage-IZ4MDYNB.js");
653
653
  await triageStatsCommand(options);
654
654
  });
655
655
  triageCmd.command("record").description("Manually record an incident").requiredOption("--error <message>", "Error message").requiredOption("-e, --env <environment>", "Environment").option("--feature <symbol>", "Feature symbol (@...)").option("--component <symbol>", "Component symbol (#...)").option("--flow <symbol>", "Flow symbol ($...)").option("--gate <symbol>", "Gate symbol (^...)").option("--signal <symbol>", "Signal symbol (!...)").option("--state <symbol>", "State symbol (%...)").option("--integration <symbol>", "Integration symbol (&...)").option("--service <name>", "Service name").option("--version <version>", "App version").option("--stack <trace>", "Stack trace").option("--json", "Output as JSON").action(async (options) => {
656
- const { triageRecordCommand } = await import("./triage-POXJ2TIX.js");
656
+ const { triageRecordCommand } = await import("./triage-IZ4MDYNB.js");
657
657
  await triageRecordCommand(options);
658
658
  });
659
659
  triageCmd.option("-l, --limit <number>", "Maximum incidents to show", "10").option("-s, --status <status>", "Filter by status").option("--json", "Output as JSON").action(async (options) => {
660
- const { triageListCommand } = await import("./triage-POXJ2TIX.js");
660
+ const { triageListCommand } = await import("./triage-IZ4MDYNB.js");
661
661
  await triageListCommand(options);
662
662
  });
663
663
  var loreCmd = program.command("lore").description("Project lore - timeline of everything that happened to this project");
@@ -710,7 +710,7 @@ loreCmd.option("-p, --port <port>", "Port to run on", "3840").option("--no-open"
710
710
  await loreServeCommand(void 0, options);
711
711
  });
712
712
  program.command("serve").description("Launch Paradigm Platform \u2014 unified development management UI").option("-p, --port <port>", "Port to run on", "3850").option("--no-open", "Don't open browser automatically").option("--sections <list>", "Comma-separated sections to enable (e.g., lore,graph,git)").action(async (options) => {
713
- const { serveCommand } = await import("./serve-3V2WXLGM.js");
713
+ const { serveCommand } = await import("./serve-KKEHE44G.js");
714
714
  await serveCommand(options);
715
715
  });
716
716
  var graphCmd = program.command("graph").description("Interactive symbol relationship graph").argument("[path]", "Project directory", void 0).option("-p, --port <port>", "Port to run on", "3841").option("--no-open", "Don't open browser automatically").action(async (path2, options) => {
@@ -723,48 +723,48 @@ graphCmd.command("generate").description("Generate a named graph file in .paradi
723
723
  });
724
724
  var habitsCmd = program.command("habits").description("Behavioral habits - practice tracking and compliance");
725
725
  habitsCmd.command("list").alias("ls").description("List all configured habits").option("--trigger <trigger>", "Filter by trigger: preflight, postflight, on-stop, on-commit").option("--category <category>", "Filter by category: discovery, verification, testing, documentation, collaboration, security").option("--json", "Output as JSON").action(async (options) => {
726
- const { habitsListCommand } = await import("./habits-O37HTUKE.js");
726
+ const { habitsListCommand } = await import("./habits-RG5SVKXP.js");
727
727
  await habitsListCommand(options);
728
728
  });
729
729
  habitsCmd.command("status").description("Show practice profile with compliance rates").option("-p, --period <period>", "Time period: 7d, 30d, 90d, all", "30d").option("--json", "Output as JSON").action(async (options) => {
730
- const { habitsStatusCommand } = await import("./habits-O37HTUKE.js");
730
+ const { habitsStatusCommand } = await import("./habits-RG5SVKXP.js");
731
731
  await habitsStatusCommand(options);
732
732
  });
733
733
  habitsCmd.command("init").description("Initialize habits.yaml with seed habits").option("-f, --force", "Overwrite existing file").action(async (options) => {
734
- const { habitsInitCommand } = await import("./habits-O37HTUKE.js");
734
+ const { habitsInitCommand } = await import("./habits-RG5SVKXP.js");
735
735
  await habitsInitCommand(options);
736
736
  });
737
737
  habitsCmd.command("check").description("Evaluate habit compliance for a trigger point").requiredOption("-t, --trigger <trigger>", "Trigger: preflight, postflight, on-stop, on-commit").option("--record", "Record practice events to Sentinel").option("--json", "Output as JSON").option("--files <files>", "Comma-separated files modified (default: git diff)").option("--symbols <symbols>", "Comma-separated symbols touched").action(async (options) => {
738
- const { habitsCheckCommand } = await import("./habits-O37HTUKE.js");
738
+ const { habitsCheckCommand } = await import("./habits-RG5SVKXP.js");
739
739
  await habitsCheckCommand(options);
740
740
  });
741
741
  habitsCmd.command("add").description("Add a custom habit").requiredOption("--id <id>", "Habit ID (kebab-case)").requiredOption("--name <name>", "Human-readable name").requiredOption("--description <desc>", "What this habit enforces").requiredOption("--category <category>", "Category: discovery, verification, testing, documentation, collaboration, security").requiredOption("--trigger <trigger>", "Trigger: preflight, postflight, on-stop, on-commit").option("--severity <severity>", "Severity: advisory, warn, block", "advisory").option("--tools <tools>", "Comma-separated tools to check (for tool-called check type)").option("--check-type <type>", "Check type: tool-called, file-exists, file-modified, lore-recorded, symbols-registered, gates-declared, tests-exist, git-clean", "tool-called").option("--patterns <patterns>", "Comma-separated patterns (for file-exists, file-modified, tests-exist check types)").action(async (options) => {
742
- const { habitsAddCommand } = await import("./habits-O37HTUKE.js");
742
+ const { habitsAddCommand } = await import("./habits-RG5SVKXP.js");
743
743
  await habitsAddCommand({ ...options, checkType: options.checkType });
744
744
  });
745
745
  habitsCmd.command("edit <id>").description("Edit a habit (seed habits: only severity/enabled; custom: all fields)").option("--name <name>", "New name").option("--description <desc>", "New description").option("--category <category>", "New category").option("--trigger <trigger>", "New trigger").option("--severity <severity>", "New severity: advisory, warn, block").option("--enabled <bool>", "Enable or disable: true, false").option("--check-type <type>", "New check type").option("--patterns <patterns>", "Comma-separated patterns").option("--tools <tools>", "Comma-separated tools").action(async (id, options) => {
746
- const { habitsEditCommand } = await import("./habits-O37HTUKE.js");
746
+ const { habitsEditCommand } = await import("./habits-RG5SVKXP.js");
747
747
  await habitsEditCommand(id, { ...options, checkType: options.checkType });
748
748
  });
749
749
  habitsCmd.command("remove <id>").description("Remove a custom habit (seed habits cannot be removed, only disabled)").option("-y, --yes", "Skip confirmation").action(async (id, options) => {
750
- const { habitsRemoveCommand } = await import("./habits-O37HTUKE.js");
750
+ const { habitsRemoveCommand } = await import("./habits-RG5SVKXP.js");
751
751
  await habitsRemoveCommand(id, options);
752
752
  });
753
753
  habitsCmd.command("enable <id>").description("Enable a habit").action(async (id) => {
754
- const { habitsToggleCommand } = await import("./habits-O37HTUKE.js");
754
+ const { habitsToggleCommand } = await import("./habits-RG5SVKXP.js");
755
755
  await habitsToggleCommand(id, "enable");
756
756
  });
757
757
  habitsCmd.command("disable <id>").description("Disable a habit").action(async (id) => {
758
- const { habitsToggleCommand } = await import("./habits-O37HTUKE.js");
758
+ const { habitsToggleCommand } = await import("./habits-RG5SVKXP.js");
759
759
  await habitsToggleCommand(id, "disable");
760
760
  });
761
761
  habitsCmd.action(async () => {
762
- const { habitsListCommand } = await import("./habits-O37HTUKE.js");
762
+ const { habitsListCommand } = await import("./habits-RG5SVKXP.js");
763
763
  await habitsListCommand({});
764
764
  });
765
765
  var sentinelCmd = program.command("sentinel").description("Sentinel \u2014 semantic error monitoring");
766
766
  sentinelCmd.command("defend [path]", { isDefault: true }).description("Launch the Sentinel UI - unified codebase intelligence visualizer").option("-p, --port <port>", "Port to run on", "3838").option("--no-open", "Don't open browser automatically").action(async (path2, options) => {
767
- const { sentinelCommand } = await import("./sentinel-BKYTBT7M.js");
767
+ const { sentinelCommand } = await import("./sentinel-UOIGJWHH.js");
768
768
  await sentinelCommand(path2, options);
769
769
  });
770
770
  program.command("conductor").description("Launch Paradigm Conductor \u2014 multimodal mission control for Claude Code sessions").option("--build", "Force rebuild the native binary").option("-v, --verbose", "Show build output").action(async (options) => {
@@ -835,71 +835,92 @@ pipelineCmd.action(async () => {
835
835
  });
836
836
  var symphonyCmd = program.command("symphony").description("Symphony \u2014 agent-to-agent messaging for multi-session collaboration");
837
837
  symphonyCmd.command("join").description("Join this session to the Symphony network").option("--remote <ip>", "Connect to remote Symphony server").action(async (options) => {
838
- const { symphonyJoinCommand } = await import("./symphony-ROEKK7VD.js");
838
+ const { symphonyJoinCommand } = await import("./symphony-6K3HD7AW.js");
839
839
  await symphonyJoinCommand(options);
840
840
  });
841
841
  symphonyCmd.command("leave").description("Remove this session from the Symphony network").action(async () => {
842
- const { symphonyLeaveCommand } = await import("./symphony-ROEKK7VD.js");
842
+ const { symphonyLeaveCommand } = await import("./symphony-6K3HD7AW.js");
843
843
  await symphonyLeaveCommand();
844
844
  });
845
845
  symphonyCmd.command("whoami").description("Show this agent's identity and linked peers").action(async () => {
846
- const { symphonyWhoamiCommand } = await import("./symphony-ROEKK7VD.js");
846
+ const { symphonyWhoamiCommand } = await import("./symphony-6K3HD7AW.js");
847
847
  await symphonyWhoamiCommand();
848
848
  });
849
849
  symphonyCmd.command("list").alias("ls").description("List all joined agents").option("--json", "Output as JSON").action(async (options) => {
850
- const { symphonyListCommand } = await import("./symphony-ROEKK7VD.js");
850
+ const { symphonyListCommand } = await import("./symphony-6K3HD7AW.js");
851
851
  await symphonyListCommand(options);
852
852
  });
853
853
  symphonyCmd.command("send <message>").description("Send a note to agents").option("--to <agent>", "Send to specific agent (omit for broadcast)").option("--thread <id>", "Reply to existing thread").action(async (message, options) => {
854
- const { symphonySendCommand } = await import("./symphony-ROEKK7VD.js");
854
+ const { symphonySendCommand } = await import("./symphony-6K3HD7AW.js");
855
855
  await symphonySendCommand(message, options);
856
856
  });
857
857
  symphonyCmd.command("read").description("Show unread notes").action(async () => {
858
- const { symphonyReadCommand } = await import("./symphony-ROEKK7VD.js");
858
+ const { symphonyReadCommand } = await import("./symphony-6K3HD7AW.js");
859
859
  await symphonyReadCommand();
860
860
  });
861
861
  symphonyCmd.command("inbox").description("Show unread notes (alias for read)").action(async () => {
862
- const { symphonyReadCommand } = await import("./symphony-ROEKK7VD.js");
862
+ const { symphonyReadCommand } = await import("./symphony-6K3HD7AW.js");
863
863
  await symphonyReadCommand();
864
864
  });
865
865
  symphonyCmd.command("threads").description("List all threads").option("--json", "Output as JSON").action(async (options) => {
866
- const { symphonyThreadsCommand } = await import("./symphony-ROEKK7VD.js");
866
+ const { symphonyThreadsCommand } = await import("./symphony-6K3HD7AW.js");
867
867
  await symphonyThreadsCommand(options);
868
868
  });
869
869
  symphonyCmd.command("thread <id>").description("Show full thread conversation").action(async (id) => {
870
- const { symphonyThreadCommand } = await import("./symphony-ROEKK7VD.js");
870
+ const { symphonyThreadCommand } = await import("./symphony-6K3HD7AW.js");
871
871
  await symphonyThreadCommand(id);
872
872
  });
873
873
  symphonyCmd.command("resolve <id>").description("Mark a thread as resolved").option("--decision <text>", "Decision text to record").action(async (id, options) => {
874
- const { symphonyResolveCommand } = await import("./symphony-ROEKK7VD.js");
874
+ const { symphonyResolveCommand } = await import("./symphony-6K3HD7AW.js");
875
875
  await symphonyResolveCommand(id, options);
876
876
  });
877
877
  symphonyCmd.command("status").description("Show Symphony network status").option("--json", "Output as JSON").action(async (options) => {
878
- const { symphonyStatusCommand } = await import("./symphony-ROEKK7VD.js");
878
+ const { symphonyStatusCommand } = await import("./symphony-6K3HD7AW.js");
879
879
  await symphonyStatusCommand(options);
880
880
  });
881
- symphonyCmd.command("serve").description("Start TCP server for remote Symphony linking").option("--port <port>", "Port to listen on", "3939").action(async (options) => {
882
- const { symphonyServeCommand } = await import("./symphony-ROEKK7VD.js");
881
+ symphonyCmd.command("serve").description("Start Symphony relay server for cross-machine networking").option("--port <port>", "Port to listen on", "3939").option("--public", "Show connection string for internet access").action(async (options) => {
882
+ const { symphonyServeCommand } = await import("./symphony-6K3HD7AW.js");
883
883
  await symphonyServeCommand(options);
884
884
  });
885
+ var peersCmd = symphonyCmd.command("peers").description("Manage trusted remote peers");
886
+ peersCmd.command("list", { isDefault: true }).description("List trusted peers and their agents").option("--json", "Output as JSON").action(async (options) => {
887
+ const { symphonyPeersCommand } = await import("./peers-RFQCWVLV.js");
888
+ await symphonyPeersCommand(options);
889
+ });
890
+ peersCmd.command("revoke <id>").description("Revoke trust for a peer (disconnects immediately)").action(async (id) => {
891
+ const { symphonyPeersRevokeCommand } = await import("./peers-RFQCWVLV.js");
892
+ await symphonyPeersRevokeCommand(id);
893
+ });
894
+ peersCmd.command("forget").description("Clear all peer trust records").option("--force", "Skip confirmation").action(async (options) => {
895
+ const { symphonyPeersForgetCommand } = await import("./peers-RFQCWVLV.js");
896
+ await symphonyPeersForgetCommand(options);
897
+ });
898
+ peersCmd.action(async () => {
899
+ const { symphonyPeersCommand } = await import("./peers-RFQCWVLV.js");
900
+ await symphonyPeersCommand({});
901
+ });
885
902
  symphonyCmd.command("request <file>").description("Request a file from another agent").option("--from <agent>", "Agent to request from").option("--reason <text>", "Why this file is needed").action(async (file, options) => {
886
- const { symphonyRequestCommand } = await import("./symphony-ROEKK7VD.js");
903
+ const { symphonyRequestCommand } = await import("./symphony-6K3HD7AW.js");
887
904
  await symphonyRequestCommand(file, options);
888
905
  });
889
906
  symphonyCmd.command("requests").description("List pending file requests").action(async () => {
890
- const { symphonyRequestsCommand } = await import("./symphony-ROEKK7VD.js");
907
+ const { symphonyRequestsCommand } = await import("./symphony-6K3HD7AW.js");
891
908
  await symphonyRequestsCommand();
892
909
  });
893
910
  symphonyCmd.command("approve <id>").description("Approve a file request").option("--redact", "Strip sensitive lines before sending").action(async (id, options) => {
894
- const { symphonyApproveCommand } = await import("./symphony-ROEKK7VD.js");
911
+ const { symphonyApproveCommand } = await import("./symphony-6K3HD7AW.js");
895
912
  await symphonyApproveCommand(id, options);
896
913
  });
897
914
  symphonyCmd.command("deny <id>").description("Deny a file request").option("--reason <text>", "Reason for denial").action(async (id, options) => {
898
- const { symphonyDenyCommand } = await import("./symphony-ROEKK7VD.js");
915
+ const { symphonyDenyCommand } = await import("./symphony-6K3HD7AW.js");
899
916
  await symphonyDenyCommand(id, options);
900
917
  });
918
+ symphonyCmd.command("watch").description("Watch inbox in real-time \u2014 zero AI tokens, pure file monitoring").option("--interval <ms>", "Poll interval in milliseconds (default: 2000)").option("--thread <id>", "Only show messages from this thread").option("--quiet", "Minimal output \u2014 messages only, no header").action(async (options) => {
919
+ const { symphonyWatchCommand } = await import("./symphony-6K3HD7AW.js");
920
+ await symphonyWatchCommand(options);
921
+ });
901
922
  symphonyCmd.action(async () => {
902
- const { symphonyStatusCommand } = await import("./symphony-ROEKK7VD.js");
923
+ const { symphonyStatusCommand } = await import("./symphony-6K3HD7AW.js");
903
924
  await symphonyStatusCommand({});
904
925
  });
905
926
  program.parse();
package/dist/mcp.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  StatsCalculator,
15
15
  TimelineBuilder,
16
16
  loadAllSeedPatterns
17
- } from "./chunk-RGFANZ4Q.js";
17
+ } from "./chunk-ZDHLG5VP.js";
18
18
  import {
19
19
  addStep,
20
20
  addToolBreadcrumb,
@@ -90,7 +90,7 @@ import {
90
90
  validateProtocol,
91
91
  validatePurposeFile,
92
92
  validateUniversityContent
93
- } from "./chunk-CZEIK3Y2.js";
93
+ } from "./chunk-ZMQA6SCO.js";
94
94
  import {
95
95
  addLoreAssessment,
96
96
  deleteLoreEntry,
@@ -12098,7 +12098,7 @@ var PERSONA_SCHEMA = {
12098
12098
  var sentinelSchemaRegistered = false;
12099
12099
  async function emitPersonaEvents(result) {
12100
12100
  try {
12101
- const { SentinelStorage: SentinelStorage2 } = await import("./dist-RVKYUCRU.js");
12101
+ const { SentinelStorage: SentinelStorage2 } = await import("./dist-CM3MVWWW.js");
12102
12102
  const storage2 = new SentinelStorage2();
12103
12103
  if (!sentinelSchemaRegistered) {
12104
12104
  try {
@@ -14557,12 +14557,15 @@ function getMyIdentity(projectDir2) {
14557
14557
  return null;
14558
14558
  }
14559
14559
  }
14560
- function markAgentPollTime(agentId) {
14560
+ function markAgentPollTime(agentId, statusBlurb) {
14561
14561
  const identityPath = path28.join(getAgentDir(agentId), "identity.json");
14562
14562
  if (!fs26.existsSync(identityPath)) return;
14563
14563
  try {
14564
14564
  const identity = JSON.parse(fs26.readFileSync(identityPath, "utf-8"));
14565
14565
  identity.lastPoll = (/* @__PURE__ */ new Date()).toISOString();
14566
+ if (statusBlurb !== void 0) {
14567
+ identity.statusBlurb = statusBlurb || void 0;
14568
+ }
14566
14569
  fs26.writeFileSync(identityPath, JSON.stringify(identity, null, 2), "utf-8");
14567
14570
  } catch {
14568
14571
  }
@@ -14581,6 +14584,35 @@ function outboxPath(agentId) {
14581
14584
  function ackPath(agentId) {
14582
14585
  return path28.join(getAgentDir(agentId), "ack.json");
14583
14586
  }
14587
+ function peekInbox(agentId) {
14588
+ const filePath = inboxPath(agentId);
14589
+ if (!fs26.existsSync(filePath)) return { hasNew: false, inboxSize: 0 };
14590
+ const stat = fs26.statSync(filePath);
14591
+ const inboxSize = stat.size;
14592
+ const ack = readAck(agentId);
14593
+ if (!ack) {
14594
+ return { hasNew: inboxSize > 0, inboxSize };
14595
+ }
14596
+ const ackSizePath = path28.join(getAgentDir(agentId), "ack-size.json");
14597
+ if (fs26.existsSync(ackSizePath)) {
14598
+ try {
14599
+ const ackSize = JSON.parse(fs26.readFileSync(ackSizePath, "utf-8"));
14600
+ return { hasNew: inboxSize > (ackSize.size || 0), inboxSize };
14601
+ } catch {
14602
+ }
14603
+ }
14604
+ return { hasNew: inboxSize > 0, inboxSize };
14605
+ }
14606
+ function recordAckSize(agentId) {
14607
+ const filePath = inboxPath(agentId);
14608
+ const ackSizePath = path28.join(getAgentDir(agentId), "ack-size.json");
14609
+ try {
14610
+ const size = fs26.existsSync(filePath) ? fs26.statSync(filePath).size : 0;
14611
+ ensureAgentDir(agentId);
14612
+ fs26.writeFileSync(ackSizePath, JSON.stringify({ size }), "utf-8");
14613
+ } catch {
14614
+ }
14615
+ }
14584
14616
  function appendToInbox(agentId, message) {
14585
14617
  ensureAgentDir(agentId);
14586
14618
  appendJsonlLine(inboxPath(agentId), message);
@@ -14939,12 +14971,34 @@ function isProcessAlive2(pid) {
14939
14971
  // ../paradigm-mcp/src/tools/symphony.ts
14940
14972
  function getSymphonyToolsList() {
14941
14973
  return [
14974
+ {
14975
+ name: "paradigm_symphony_peek",
14976
+ description: "Ultra-cheap inbox check \u2014 file stat only, no parsing. Returns { hasNew: true/false }. Use with /loop 10s for near-free monitoring. When hasNew is true, call paradigm_symphony_poll to read messages. ~15 tokens.",
14977
+ inputSchema: {
14978
+ type: "object",
14979
+ properties: {
14980
+ status: {
14981
+ type: "string",
14982
+ description: "Short status blurb (same as poll). Updates heartbeat."
14983
+ }
14984
+ }
14985
+ },
14986
+ annotations: {
14987
+ readOnlyHint: true,
14988
+ destructiveHint: false
14989
+ }
14990
+ },
14942
14991
  {
14943
14992
  name: "paradigm_symphony_poll",
14944
- description: "Poll inbox for new notes. Call via /loop for continuous agent messaging. Returns unread notes formatted as markdown with thread context and suggested actions. Updates heartbeat. ~200 tokens.",
14993
+ description: "Read inbox notes and process them. Call when paradigm_symphony_peek returns hasNew: true, or directly via /loop for continuous messaging. Returns unread notes formatted as markdown with thread context and suggested actions. Updates heartbeat and optional status blurb. ~200 tokens.",
14945
14994
  inputSchema: {
14946
14995
  type: "object",
14947
- properties: {}
14996
+ properties: {
14997
+ status: {
14998
+ type: "string",
14999
+ description: 'Short status blurb describing what you are currently working on (e.g., "Implementing auth middleware \u2014 3 files modified"). Visible to humans and other agents in the Network view.'
15000
+ }
15001
+ }
14948
15002
  },
14949
15003
  annotations: {
14950
15004
  readOnlyHint: false,
@@ -15113,14 +15167,26 @@ async function handleSymphonyTool(name, args, ctx) {
15113
15167
  identity = registerAgent(ctx.rootDir);
15114
15168
  }
15115
15169
  switch (name) {
15170
+ case "paradigm_symphony_peek": {
15171
+ const peekStatus = args.status;
15172
+ markAgentPollTime(identity.id, peekStatus);
15173
+ const { hasNew } = peekInbox(identity.id);
15174
+ const pendingRequests = hasNew ? listFileRequests("pending").length : 0;
15175
+ return {
15176
+ handled: true,
15177
+ text: JSON.stringify(hasNew ? { hasNew: true, pendingFileRequests: pendingRequests, action: "call paradigm_symphony_poll to read" } : { hasNew: false })
15178
+ };
15179
+ }
15116
15180
  case "paradigm_symphony_poll": {
15117
15181
  cleanStaleAgents();
15118
15182
  expireOldRequests();
15119
- markAgentPollTime(identity.id);
15183
+ const statusBlurb = args.status;
15184
+ markAgentPollTime(identity.id, statusBlurb);
15120
15185
  const messages = readInbox(identity.id);
15121
15186
  if (messages.length > 0) {
15122
15187
  const lastId = messages[messages.length - 1].id;
15123
15188
  acknowledgeMessages(identity.id, lastId);
15189
+ recordAckSize(identity.id);
15124
15190
  }
15125
15191
  garbageCollect(identity.id);
15126
15192
  const pendingRequests = listFileRequests("pending");
@@ -15227,6 +15293,18 @@ async function handleSymphonyTool(name, args, ctx) {
15227
15293
  const threads = listThreads("active");
15228
15294
  const unread = readInbox(identity.id);
15229
15295
  const pendingRequests = listFileRequests("pending");
15296
+ let peers = [];
15297
+ try {
15298
+ const { loadPeers } = await import("./symphony-peers-APOGJPF4.js");
15299
+ const allPeers = loadPeers();
15300
+ peers = allPeers.filter((p) => !p.revoked).map((p) => ({
15301
+ id: p.id,
15302
+ address: p.address,
15303
+ agents: p.agents?.length ?? 0,
15304
+ lastSeen: p.lastSeen
15305
+ }));
15306
+ } catch {
15307
+ }
15230
15308
  return {
15231
15309
  handled: true,
15232
15310
  text: JSON.stringify({
@@ -15241,8 +15319,10 @@ async function handleSymphonyTool(name, args, ctx) {
15241
15319
  project: a.project,
15242
15320
  role: a.role,
15243
15321
  status: isAgentAsleep(a) ? "asleep" : "awake",
15244
- lastPoll: a.lastPoll
15322
+ lastPoll: a.lastPoll,
15323
+ statusBlurb: a.statusBlurb
15245
15324
  })),
15325
+ peers,
15246
15326
  activeThreads: threads.map((t) => ({
15247
15327
  id: t.id,
15248
15328
  topic: t.topic,
@@ -17440,7 +17520,7 @@ Update command:
17440
17520
  trackToolCall(noWsText.length, name);
17441
17521
  return { content: [{ type: "text", text: noWsText }] };
17442
17522
  }
17443
- const { rebuildStaticFiles: rebuildStaticFiles2 } = await import("./reindex-NZQRGKPN.js");
17523
+ const { rebuildStaticFiles: rebuildStaticFiles2 } = await import("./reindex-WIJMCJ4A.js");
17444
17524
  const memberResults = [];
17445
17525
  for (const member of ctx.workspace.config.members) {
17446
17526
  const memberAbsPath = path31.resolve(path31.dirname(ctx.workspace.workspacePath), member.path);
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ forgetAllPeers,
4
+ loadPeers,
5
+ revokePeer
6
+ } from "./chunk-KVDYJLTC.js";
7
+ import "./chunk-ZXMDA7VB.js";
8
+
9
+ // src/commands/symphony/peers.ts
10
+ import chalk from "chalk";
11
+ async function symphonyPeersCommand(options) {
12
+ const peers = loadPeers();
13
+ if (options.json) {
14
+ console.log(JSON.stringify(peers, null, 2));
15
+ return;
16
+ }
17
+ if (peers.length === 0) {
18
+ console.log(chalk.yellow('No trusted peers. Run "paradigm symphony serve" to accept connections.'));
19
+ return;
20
+ }
21
+ console.log(chalk.cyan(`
22
+ Trusted Peers (${peers.length})
23
+ `));
24
+ console.log(chalk.gray(` ${"PEER ID".padEnd(20)} ${"ADDRESS".padEnd(22)} ${"STATUS".padEnd(10)} ${"AGENTS".padEnd(8)} LAST SEEN`));
25
+ console.log(chalk.gray(` ${"\u2500".repeat(20)} ${"\u2500".repeat(22)} ${"\u2500".repeat(10)} ${"\u2500".repeat(8)} ${"\u2500".repeat(20)}`));
26
+ for (const peer of peers) {
27
+ const status = peer.revoked ? chalk.red("revoked") : chalk.green("trusted");
28
+ const agentCount = (peer.agents || []).length.toString();
29
+ const lastSeen = peer.lastSeen ? formatRelativeTime(peer.lastSeen) : chalk.gray("never");
30
+ console.log(` ${chalk.white(peer.id.padEnd(20))} ${peer.address.padEnd(22)} ${status.padEnd(10)} ${agentCount.padEnd(8)} ${lastSeen}`);
31
+ if (peer.agents && peer.agents.length > 0) {
32
+ for (const agent of peer.agents) {
33
+ const agentStatus = agent.status === "awake" ? chalk.green("awake") : chalk.yellow("asleep");
34
+ console.log(chalk.gray(` \u2514 ${agent.id} [${agentStatus}]`));
35
+ }
36
+ }
37
+ }
38
+ console.log();
39
+ }
40
+ async function symphonyPeersRevokeCommand(peerId) {
41
+ const success = revokePeer(peerId);
42
+ if (success) {
43
+ console.log(chalk.green(`\u2713 Revoked peer ${chalk.bold(peerId)}`));
44
+ console.log(chalk.gray(" Peer will be disconnected and cannot reconnect until re-paired."));
45
+ } else {
46
+ console.log(chalk.red(`Peer "${peerId}" not found.`));
47
+ const peers = loadPeers();
48
+ if (peers.length > 0) {
49
+ console.log(chalk.gray("\n Available peers:"));
50
+ for (const p of peers) {
51
+ console.log(chalk.gray(` ${p.id} (${p.address})`));
52
+ }
53
+ }
54
+ }
55
+ }
56
+ async function symphonyPeersForgetCommand(options) {
57
+ const peers = loadPeers();
58
+ if (peers.length === 0) {
59
+ console.log(chalk.yellow("No peers to forget."));
60
+ return;
61
+ }
62
+ if (!options.force) {
63
+ console.log(chalk.yellow(`This will remove all ${peers.length} trusted peer(s). Use --force to confirm.`));
64
+ return;
65
+ }
66
+ const count = forgetAllPeers();
67
+ console.log(chalk.green(`\u2713 Forgot ${count} peer${count !== 1 ? "s" : ""}`));
68
+ console.log(chalk.gray(" All peer trust records deleted. Re-pairing required for remote connections."));
69
+ }
70
+ function formatRelativeTime(isoDate) {
71
+ const diff = Date.now() - new Date(isoDate).getTime();
72
+ const seconds = Math.floor(diff / 1e3);
73
+ if (seconds < 60) return "just now";
74
+ if (seconds < 3600) return `${Math.floor(seconds / 60)}m ago`;
75
+ if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ago`;
76
+ return `${Math.floor(seconds / 86400)}d ago`;
77
+ }
78
+ export {
79
+ symphonyPeersCommand,
80
+ symphonyPeersForgetCommand,
81
+ symphonyPeersRevokeCommand
82
+ };