@triedotdev/mcp 1.0.79 → 1.0.81

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 (54) hide show
  1. package/README.md +91 -20
  2. package/dist/{agent-smith-XGYNJUCJ.js → agent-smith-MCKGNWPL.js} +3 -3
  3. package/dist/{agent-smith-runner-QHYGVRNR.js → agent-smith-runner-GP5HLL7E.js} +3 -3
  4. package/dist/{chunk-LNLLZQWH.js → chunk-2BXLPYHR.js} +604 -138
  5. package/dist/chunk-2BXLPYHR.js.map +1 -0
  6. package/dist/{chunk-35FAFFHE.js → chunk-75J4HQTD.js} +2 -2
  7. package/dist/{chunk-RRDDAD5N.js → chunk-7OVM6KEY.js} +34 -7
  8. package/dist/chunk-7OVM6KEY.js.map +1 -0
  9. package/dist/chunk-B7CLAOEK.js +532 -0
  10. package/dist/chunk-B7CLAOEK.js.map +1 -0
  11. package/dist/{chunk-Z7N7KDK3.js → chunk-DCJKNE2L.js} +2 -1
  12. package/dist/{chunk-P6VLSYXN.js → chunk-EWIEXQES.js} +2 -2
  13. package/dist/{chunk-53URTRWH.js → chunk-FW435YKY.js} +300 -440
  14. package/dist/chunk-FW435YKY.js.map +1 -0
  15. package/dist/{chunk-UPKBO5EM.js → chunk-MVWRFARH.js} +137 -559
  16. package/dist/chunk-MVWRFARH.js.map +1 -0
  17. package/dist/{chunk-EWQF6INU.js → chunk-TBRU735C.js} +2 -2
  18. package/dist/{chunk-AIC4HOOQ.js → chunk-U5P3O5G5.js} +3 -3
  19. package/dist/{chunk-6QKDEGWR.js → chunk-WGECLUDQ.js} +4 -4
  20. package/dist/chunk-WGECLUDQ.js.map +1 -0
  21. package/dist/{chunk-3RKY55HZ.js → chunk-YKG4KIY7.js} +673 -83
  22. package/dist/chunk-YKG4KIY7.js.map +1 -0
  23. package/dist/cli/main.js +296 -64
  24. package/dist/cli/main.js.map +1 -1
  25. package/dist/cli/yolo-daemon.js +12 -11
  26. package/dist/cli/yolo-daemon.js.map +1 -1
  27. package/dist/{goal-manager-NI4LJ2SX.js → goal-manager-NHPEUWFY.js} +4 -4
  28. package/dist/guardian-agent-GWYDNLWC.js +21 -0
  29. package/dist/index.js +115 -50
  30. package/dist/index.js.map +1 -1
  31. package/dist/{issue-store-MULGOF6B.js → issue-store-RKJVOKSJ.js} +2 -2
  32. package/dist/ui/memory-viewer.html +4 -4
  33. package/dist/ui/pr-review.html +4 -4
  34. package/dist/ui/scan-dashboard.html +4 -4
  35. package/dist/ui/visual-qa.html +4 -4
  36. package/dist/workers/agent-worker.js +5 -5
  37. package/package.json +1 -1
  38. package/dist/chunk-3RKY55HZ.js.map +0 -1
  39. package/dist/chunk-53URTRWH.js.map +0 -1
  40. package/dist/chunk-6QKDEGWR.js.map +0 -1
  41. package/dist/chunk-LNLLZQWH.js.map +0 -1
  42. package/dist/chunk-RRDDAD5N.js.map +0 -1
  43. package/dist/chunk-UPKBO5EM.js.map +0 -1
  44. package/dist/guardian-agent-R5HX7UWJ.js +0 -17
  45. /package/dist/{agent-smith-XGYNJUCJ.js.map → agent-smith-MCKGNWPL.js.map} +0 -0
  46. /package/dist/{agent-smith-runner-QHYGVRNR.js.map → agent-smith-runner-GP5HLL7E.js.map} +0 -0
  47. /package/dist/{chunk-35FAFFHE.js.map → chunk-75J4HQTD.js.map} +0 -0
  48. /package/dist/{chunk-Z7N7KDK3.js.map → chunk-DCJKNE2L.js.map} +0 -0
  49. /package/dist/{chunk-P6VLSYXN.js.map → chunk-EWIEXQES.js.map} +0 -0
  50. /package/dist/{chunk-EWQF6INU.js.map → chunk-TBRU735C.js.map} +0 -0
  51. /package/dist/{chunk-AIC4HOOQ.js.map → chunk-U5P3O5G5.js.map} +0 -0
  52. /package/dist/{goal-manager-NI4LJ2SX.js.map → goal-manager-NHPEUWFY.js.map} +0 -0
  53. /package/dist/{guardian-agent-R5HX7UWJ.js.map → guardian-agent-GWYDNLWC.js.map} +0 -0
  54. /package/dist/{issue-store-MULGOF6B.js.map → issue-store-RKJVOKSJ.js.map} +0 -0
@@ -2,13 +2,28 @@ import {
2
2
  Executor,
3
3
  Triager,
4
4
  detectStack,
5
+ getDiff,
6
+ getRecentCommits,
5
7
  getStagedChanges,
6
8
  getUncommittedChanges,
7
- getWorkingTreeDiff
8
- } from "./chunk-LNLLZQWH.js";
9
+ getWorkingTreeDiff,
10
+ loadConfig
11
+ } from "./chunk-2BXLPYHR.js";
12
+ import {
13
+ ContextGraph
14
+ } from "./chunk-B7CLAOEK.js";
15
+ import {
16
+ scanForVulnerabilities
17
+ } from "./chunk-FCMAQSV7.js";
18
+ import {
19
+ scanForVibeCodeIssues
20
+ } from "./chunk-SH2JIQLB.js";
9
21
  import {
10
22
  Trie
11
23
  } from "./chunk-6NLHFIYA.js";
24
+ import {
25
+ storeIssues
26
+ } from "./chunk-WGECLUDQ.js";
12
27
  import {
13
28
  getWorkingDirectory
14
29
  } from "./chunk-CM7EHNQK.js";
@@ -452,390 +467,8 @@ async function getAutonomyConfig(projectPath) {
452
467
  return config;
453
468
  }
454
469
 
455
- // src/context/graph.ts
456
- import crypto from "crypto";
457
- import path2 from "path";
458
-
459
- // src/context/store.ts
460
- import Database from "better-sqlite3";
461
- import fs from "fs";
462
- import path from "path";
463
- var ContextStore = class {
464
- db;
465
- dbFilePath;
466
- constructor(projectPath, dbFilePath) {
467
- this.dbFilePath = dbFilePath ?? path.join(projectPath, ".trie", "context.db");
468
- this.ensureDirectory();
469
- this.db = new Database(this.dbFilePath);
470
- this.configure();
471
- this.prepareSchema();
472
- }
473
- get databasePath() {
474
- return this.dbFilePath;
475
- }
476
- addNode(node) {
477
- const stmt = this.db.prepare(
478
- `INSERT INTO nodes (id, type, data, created_at, updated_at)
479
- VALUES (@id, @type, @data, @created_at, @updated_at)`
480
- );
481
- stmt.run({
482
- id: node.id,
483
- type: node.type,
484
- data: JSON.stringify(node.data),
485
- created_at: node.created_at,
486
- updated_at: node.updated_at
487
- });
488
- return node;
489
- }
490
- upsertNode(node) {
491
- const stmt = this.db.prepare(
492
- `INSERT INTO nodes (id, type, data, created_at, updated_at)
493
- VALUES (@id, @type, @data, @created_at, @updated_at)
494
- ON CONFLICT(id) DO UPDATE SET
495
- type=excluded.type,
496
- data=excluded.data,
497
- updated_at=excluded.updated_at`
498
- );
499
- stmt.run({
500
- id: node.id,
501
- type: node.type,
502
- data: JSON.stringify(node.data),
503
- created_at: node.created_at,
504
- updated_at: node.updated_at
505
- });
506
- return node;
507
- }
508
- getNode(id) {
509
- const row = this.db.prepare("SELECT * FROM nodes WHERE id = ?").get(id);
510
- return row ? this.mapNodeRow(row) : null;
511
- }
512
- getNodeByType(type, id) {
513
- const row = this.db.prepare("SELECT * FROM nodes WHERE id = ? AND type = ?").get(id, type);
514
- return row ? this.mapNodeRow(row) : null;
515
- }
516
- updateNode(id, updates, updatedAt) {
517
- const existing = this.getNode(id);
518
- if (!existing) {
519
- return null;
520
- }
521
- const merged = {
522
- ...existing,
523
- data: { ...existing.data, ...updates },
524
- updated_at: updatedAt
525
- };
526
- this.db.prepare(
527
- `UPDATE nodes SET data = @data, updated_at = @updated_at
528
- WHERE id = @id`
529
- ).run({
530
- id,
531
- data: JSON.stringify(merged.data),
532
- updated_at: merged.updated_at
533
- });
534
- return merged;
535
- }
536
- deleteNode(id) {
537
- const deleteEdges = this.db.prepare("DELETE FROM edges WHERE from_id = ? OR to_id = ?");
538
- const deleteNodeStmt = this.db.prepare("DELETE FROM nodes WHERE id = ?");
539
- const transaction = this.db.transaction((nodeId) => {
540
- deleteEdges.run(nodeId, nodeId);
541
- deleteNodeStmt.run(nodeId);
542
- });
543
- transaction(id);
544
- }
545
- listNodes() {
546
- const rows = this.db.prepare("SELECT * FROM nodes").all();
547
- return rows.map((row) => this.mapNodeRow(row));
548
- }
549
- findNodesByType(type) {
550
- const rows = this.db.prepare("SELECT * FROM nodes WHERE type = ?").all(type);
551
- return rows.map((row) => this.mapNodeRow(row));
552
- }
553
- addEdge(edge) {
554
- const stmt = this.db.prepare(
555
- `INSERT INTO edges (id, from_id, to_id, type, weight, metadata, created_at)
556
- VALUES (@id, @from_id, @to_id, @type, @weight, @metadata, @created_at)`
557
- );
558
- stmt.run({
559
- id: edge.id,
560
- from_id: edge.from_id,
561
- to_id: edge.to_id,
562
- type: edge.type,
563
- weight: edge.weight,
564
- metadata: JSON.stringify(edge.metadata ?? {}),
565
- created_at: edge.created_at
566
- });
567
- return edge;
568
- }
569
- upsertEdge(edge) {
570
- const stmt = this.db.prepare(
571
- `INSERT INTO edges (id, from_id, to_id, type, weight, metadata, created_at)
572
- VALUES (@id, @from_id, @to_id, @type, @weight, @metadata, @created_at)
573
- ON CONFLICT(id) DO UPDATE SET
574
- from_id=excluded.from_id,
575
- to_id=excluded.to_id,
576
- type=excluded.type,
577
- weight=excluded.weight,
578
- metadata=excluded.metadata`
579
- );
580
- stmt.run({
581
- id: edge.id,
582
- from_id: edge.from_id,
583
- to_id: edge.to_id,
584
- type: edge.type,
585
- weight: edge.weight,
586
- metadata: JSON.stringify(edge.metadata ?? {}),
587
- created_at: edge.created_at
588
- });
589
- return edge;
590
- }
591
- getEdge(id) {
592
- const row = this.db.prepare("SELECT * FROM edges WHERE id = ?").get(id);
593
- return row ? this.mapEdgeRow(row) : null;
594
- }
595
- getEdges(nodeId, direction = "both") {
596
- let rows;
597
- if (direction === "in") {
598
- rows = this.db.prepare("SELECT * FROM edges WHERE to_id = ?").all(nodeId);
599
- } else if (direction === "out") {
600
- rows = this.db.prepare("SELECT * FROM edges WHERE from_id = ?").all(nodeId);
601
- } else {
602
- rows = this.db.prepare("SELECT * FROM edges WHERE from_id = ? OR to_id = ?").all(nodeId, nodeId);
603
- }
604
- return rows.map((row) => this.mapEdgeRow(row));
605
- }
606
- listEdges() {
607
- const rows = this.db.prepare("SELECT * FROM edges").all();
608
- return rows.map((row) => this.mapEdgeRow(row));
609
- }
610
- deleteEdge(id) {
611
- this.db.prepare("DELETE FROM edges WHERE id = ?").run(id);
612
- }
613
- close() {
614
- this.db.close();
615
- }
616
- ensureDirectory() {
617
- fs.mkdirSync(path.dirname(this.dbFilePath), { recursive: true });
618
- }
619
- configure() {
620
- this.db.pragma("journal_mode = WAL");
621
- this.db.pragma("busy_timeout = 5000");
622
- this.db.pragma("synchronous = NORMAL");
623
- }
624
- prepareSchema() {
625
- this.db.exec(`
626
- CREATE TABLE IF NOT EXISTS nodes (
627
- id TEXT PRIMARY KEY,
628
- type TEXT NOT NULL,
629
- data TEXT NOT NULL,
630
- created_at TEXT NOT NULL,
631
- updated_at TEXT NOT NULL
632
- );
633
-
634
- CREATE TABLE IF NOT EXISTS edges (
635
- id TEXT PRIMARY KEY,
636
- from_id TEXT NOT NULL,
637
- to_id TEXT NOT NULL,
638
- type TEXT NOT NULL,
639
- weight REAL NOT NULL DEFAULT 1,
640
- metadata TEXT DEFAULT '{}',
641
- created_at TEXT NOT NULL
642
- );
643
-
644
- CREATE INDEX IF NOT EXISTS idx_nodes_type ON nodes(type);
645
- CREATE INDEX IF NOT EXISTS idx_edges_from ON edges(from_id);
646
- CREATE INDEX IF NOT EXISTS idx_edges_to ON edges(to_id);
647
- CREATE INDEX IF NOT EXISTS idx_edges_type ON edges(type);
648
- `);
649
- }
650
- mapNodeRow(row) {
651
- return {
652
- id: row.id,
653
- type: row.type,
654
- data: JSON.parse(row.data),
655
- created_at: row.created_at,
656
- updated_at: row.updated_at
657
- };
658
- }
659
- mapEdgeRow(row) {
660
- return {
661
- id: row.id,
662
- from_id: row.from_id,
663
- to_id: row.to_id,
664
- type: row.type,
665
- weight: row.weight,
666
- created_at: row.created_at,
667
- metadata: row.metadata ? JSON.parse(row.metadata) : {}
668
- };
669
- }
670
- };
671
-
672
- // src/context/graph.ts
673
- var ContextGraph = class {
674
- store;
675
- projectPath;
676
- constructor(projectPath, dbPath, store) {
677
- this.projectPath = projectPath;
678
- this.store = store ?? new ContextStore(projectPath, dbPath);
679
- }
680
- get projectRoot() {
681
- return this.projectPath;
682
- }
683
- async addNode(type, data) {
684
- const now = (/* @__PURE__ */ new Date()).toISOString();
685
- const id = this.generateNodeId(type, data);
686
- const node = {
687
- id,
688
- type,
689
- data,
690
- created_at: now,
691
- updated_at: now
692
- };
693
- this.store.addNode(node);
694
- return node;
695
- }
696
- async getNode(type, id) {
697
- return this.store.getNodeByType(type, id);
698
- }
699
- async updateNode(type, id, updates) {
700
- const updated = this.store.updateNode(id, updates, (/* @__PURE__ */ new Date()).toISOString());
701
- if (updated && updated.type !== type) {
702
- throw new Error(`Type mismatch for node ${id}: expected ${type} but found ${updated.type}`);
703
- }
704
- }
705
- async deleteNode(_type, id) {
706
- this.store.deleteNode(id);
707
- }
708
- async addEdge(fromId, toId, type, metadata = {}, weight = 1) {
709
- const edge = {
710
- id: crypto.randomUUID(),
711
- from_id: fromId,
712
- to_id: toId,
713
- type,
714
- weight,
715
- metadata,
716
- created_at: (/* @__PURE__ */ new Date()).toISOString()
717
- };
718
- this.store.addEdge(edge);
719
- return edge;
720
- }
721
- async getEdges(nodeId, direction = "both") {
722
- return this.store.getEdges(nodeId, direction);
723
- }
724
- async getIncidentsForFile(filePath) {
725
- const fileNode = this.findFileNode(filePath);
726
- if (!fileNode) return [];
727
- const incidents = /* @__PURE__ */ new Map();
728
- const affectEdges = this.store.getEdges(fileNode.id, "in").filter((edge) => edge.type === "affects");
729
- for (const edge of affectEdges) {
730
- const changeId = edge.from_id;
731
- const leadEdges = this.store.getEdges(changeId, "out").filter((e) => e.type === "leadTo");
732
- const causedByEdges = this.store.getEdges(changeId, "in").filter((e) => e.type === "causedBy");
733
- for (const le of leadEdges) {
734
- const incident = this.store.getNodeByType("incident", le.to_id);
735
- if (incident) incidents.set(incident.id, incident);
736
- }
737
- for (const ce of causedByEdges) {
738
- const incident = this.store.getNodeByType("incident", ce.from_id);
739
- if (incident) incidents.set(incident.id, incident);
740
- }
741
- }
742
- return Array.from(incidents.values());
743
- }
744
- async getPatternsForFile(filePath) {
745
- const normalized = this.normalizePath(filePath);
746
- const nodes = this.store.findNodesByType("pattern");
747
- return nodes.filter(
748
- (node) => node.data.appliesTo.some((pattern) => normalized.includes(pattern) || filePath.includes(pattern))
749
- );
750
- }
751
- async getRecentChanges(limit) {
752
- const nodes = this.store.findNodesByType("change");
753
- return nodes.sort((a, b) => new Date(b.data.timestamp).getTime() - new Date(a.data.timestamp).getTime()).slice(0, limit);
754
- }
755
- async calculateFileRisk(filePath) {
756
- const fileNode = this.findFileNode(filePath);
757
- if (!fileNode) return "low";
758
- const incidentScore = Math.min(fileNode.data.incidentCount * 2, 6);
759
- const changeScore = Math.min(fileNode.data.changeCount, 4);
760
- const baseScore = this.riskLevelToScore(fileNode.data.riskLevel);
761
- const total = baseScore + incidentScore + changeScore;
762
- if (total >= 10) return "critical";
763
- if (total >= 7) return "high";
764
- if (total >= 4) return "medium";
765
- return "low";
766
- }
767
- async listNodes() {
768
- return this.store.listNodes();
769
- }
770
- async listEdges() {
771
- return this.store.listEdges();
772
- }
773
- async deleteEdge(id) {
774
- this.store.deleteEdge(id);
775
- }
776
- async getSnapshot() {
777
- return {
778
- nodes: this.store.listNodes(),
779
- edges: this.store.listEdges(),
780
- exported_at: (/* @__PURE__ */ new Date()).toISOString()
781
- };
782
- }
783
- async applySnapshot(snapshot) {
784
- for (const node of snapshot.nodes) {
785
- const existing = this.store.getNode(node.id);
786
- if (!existing || this.isNewer(node.updated_at, existing.updated_at)) {
787
- this.store.upsertNode(node);
788
- }
789
- }
790
- for (const edge of snapshot.edges) {
791
- const existing = this.store.getEdge(edge.id);
792
- if (!existing) {
793
- this.store.upsertEdge(edge);
794
- }
795
- }
796
- }
797
- generateNodeId(type, data) {
798
- if (type === "file") {
799
- const fileData = data;
800
- return this.normalizePath(fileData.path);
801
- }
802
- if (type === "change") {
803
- const changeData = data;
804
- if (changeData.commitHash) {
805
- return changeData.commitHash;
806
- }
807
- }
808
- return crypto.randomUUID();
809
- }
810
- findFileNode(filePath) {
811
- const normalized = this.normalizePath(filePath);
812
- const nodes = this.store.findNodesByType("file");
813
- return nodes.find(
814
- (node) => node.id === normalized || this.normalizePath(node.data.path) === normalized || node.data.path === filePath
815
- ) ?? null;
816
- }
817
- normalizePath(filePath) {
818
- return path2.resolve(this.projectPath, filePath);
819
- }
820
- riskLevelToScore(level) {
821
- switch (level) {
822
- case "critical":
823
- return 6;
824
- case "high":
825
- return 4;
826
- case "medium":
827
- return 2;
828
- default:
829
- return 0;
830
- }
831
- }
832
- isNewer(incoming, existing) {
833
- return new Date(incoming).getTime() >= new Date(existing).getTime();
834
- }
835
- };
836
-
837
470
  // src/agent/perceive.ts
838
- import path3 from "path";
471
+ import path from "path";
839
472
 
840
473
  // src/agent/diff-analyzer.ts
841
474
  var RISKY_PATTERNS = [/auth/i, /token/i, /password/i, /secret/i, /validate/i, /sanitize/i];
@@ -939,7 +572,7 @@ async function upsertWorkingChange(graph, files, projectPath) {
939
572
  return change.id;
940
573
  }
941
574
  async function ensureFileNode(graph, filePath, projectPath) {
942
- const normalized = path3.resolve(projectPath, filePath);
575
+ const normalized = path.resolve(projectPath, filePath);
943
576
  const existing = await graph.getNode("file", normalized);
944
577
  const now = (/* @__PURE__ */ new Date()).toISOString();
945
578
  if (existing) {
@@ -952,7 +585,7 @@ async function ensureFileNode(graph, filePath, projectPath) {
952
585
  }
953
586
  const data = {
954
587
  path: filePath,
955
- extension: path3.extname(filePath),
588
+ extension: path.extname(filePath),
956
589
  purpose: "",
957
590
  riskLevel: "medium",
958
591
  whyRisky: null,
@@ -965,7 +598,7 @@ async function ensureFileNode(graph, filePath, projectPath) {
965
598
  }
966
599
 
967
600
  // src/agent/risk-scorer.ts
968
- import path4 from "path";
601
+ import path2 from "path";
969
602
  var BASE_RISK = {
970
603
  low: 10,
971
604
  medium: 35,
@@ -986,7 +619,7 @@ function levelFromScore(score) {
986
619
  }
987
620
  async function scoreFile(graph, filePath, matchedPatterns = []) {
988
621
  const reasons = [];
989
- const normalized = path4.resolve(graph.projectRoot, filePath);
622
+ const normalized = path2.resolve(graph.projectRoot, filePath);
990
623
  const node = await graph.getNode("file", normalized);
991
624
  const incidents = await graph.getIncidentsForFile(filePath);
992
625
  let score = 10;
@@ -1454,29 +1087,29 @@ function formatFriendlyError(error) {
1454
1087
  }
1455
1088
 
1456
1089
  // src/context/sync.ts
1457
- import fs2 from "fs/promises";
1458
- import path5 from "path";
1090
+ import fs from "fs/promises";
1091
+ import path3 from "path";
1459
1092
  var DEFAULT_JSON_NAME = "context.json";
1460
1093
  async function exportToJson(graph, targetPath) {
1461
1094
  const snapshot = await graph.getSnapshot();
1462
1095
  const json = JSON.stringify(snapshot, null, 2);
1463
- const outputPath = targetPath ?? path5.join(graph.projectRoot, ".trie", DEFAULT_JSON_NAME);
1464
- await fs2.mkdir(path5.dirname(outputPath), { recursive: true });
1465
- await fs2.writeFile(outputPath, json, "utf8");
1096
+ const outputPath = targetPath ?? path3.join(graph.projectRoot, ".trie", DEFAULT_JSON_NAME);
1097
+ await fs.mkdir(path3.dirname(outputPath), { recursive: true });
1098
+ await fs.writeFile(outputPath, json, "utf8");
1466
1099
  return json;
1467
1100
  }
1468
1101
  async function importFromJson(graph, json, sourcePath) {
1469
- const payload = json.trim().length > 0 ? json : await fs2.readFile(sourcePath ?? path5.join(graph.projectRoot, ".trie", DEFAULT_JSON_NAME), "utf8");
1102
+ const payload = json.trim().length > 0 ? json : await fs.readFile(sourcePath ?? path3.join(graph.projectRoot, ".trie", DEFAULT_JSON_NAME), "utf8");
1470
1103
  const snapshot = JSON.parse(payload);
1471
1104
  await graph.applySnapshot(snapshot);
1472
1105
  }
1473
1106
 
1474
1107
  // src/context/incident-index.ts
1475
- import path7 from "path";
1108
+ import path5 from "path";
1476
1109
 
1477
1110
  // src/context/file-trie.ts
1478
- import fs3 from "fs";
1479
- import path6 from "path";
1111
+ import fs2 from "fs";
1112
+ import path4 from "path";
1480
1113
  import { performance } from "perf_hooks";
1481
1114
  function normalizePath(filePath) {
1482
1115
  const normalized = filePath.replace(/\\/g, "/");
@@ -1487,9 +1120,9 @@ var FilePathTrie = class {
1487
1120
  persistPath;
1488
1121
  constructor(persistPath) {
1489
1122
  if (persistPath) this.persistPath = persistPath;
1490
- if (persistPath && fs3.existsSync(persistPath)) {
1123
+ if (persistPath && fs2.existsSync(persistPath)) {
1491
1124
  try {
1492
- const raw = fs3.readFileSync(persistPath, "utf-8");
1125
+ const raw = fs2.readFileSync(persistPath, "utf-8");
1493
1126
  if (raw.trim().length > 0) {
1494
1127
  const json = JSON.parse(raw);
1495
1128
  this.trie = Trie.fromJSON(json);
@@ -1540,9 +1173,9 @@ var FilePathTrie = class {
1540
1173
  incidentCount: Array.isArray(r.value) ? r.value.length : 0
1541
1174
  })).sort((a, b) => b.incidentCount - a.incidentCount).slice(0, limit);
1542
1175
  }
1543
- timeLookup(path8) {
1176
+ timeLookup(path7) {
1544
1177
  const start = performance.now();
1545
- this.getIncidents(path8);
1178
+ this.getIncidents(path7);
1546
1179
  return performance.now() - start;
1547
1180
  }
1548
1181
  toJSON() {
@@ -1555,11 +1188,11 @@ var FilePathTrie = class {
1555
1188
  persist() {
1556
1189
  if (!this.persistPath) return;
1557
1190
  try {
1558
- const dir = path6.dirname(this.persistPath);
1559
- if (!fs3.existsSync(dir)) {
1560
- fs3.mkdirSync(dir, { recursive: true });
1191
+ const dir = path4.dirname(this.persistPath);
1192
+ if (!fs2.existsSync(dir)) {
1193
+ fs2.mkdirSync(dir, { recursive: true });
1561
1194
  }
1562
- fs3.writeFileSync(this.persistPath, JSON.stringify(this.trie.toJSON()), "utf-8");
1195
+ fs2.writeFileSync(this.persistPath, JSON.stringify(this.trie.toJSON()), "utf-8");
1563
1196
  } catch {
1564
1197
  }
1565
1198
  }
@@ -1574,7 +1207,7 @@ var IncidentIndex = class _IncidentIndex {
1574
1207
  this.graph = graph;
1575
1208
  this.projectRoot = projectRoot;
1576
1209
  this.trie = new FilePathTrie(
1577
- options?.persistPath ?? path7.join(projectRoot, ".trie", "incident-trie.json")
1210
+ options?.persistPath ?? path5.join(projectRoot, ".trie", "incident-trie.json")
1578
1211
  );
1579
1212
  }
1580
1213
  static async build(graph, projectRoot, options) {
@@ -1627,8 +1260,8 @@ var IncidentIndex = class _IncidentIndex {
1627
1260
  return Array.from(files);
1628
1261
  }
1629
1262
  normalizePath(filePath) {
1630
- const absolute = path7.isAbsolute(filePath) ? filePath : path7.join(this.projectRoot, filePath);
1631
- const relative = path7.relative(this.projectRoot, absolute);
1263
+ const absolute = path5.isAbsolute(filePath) ? filePath : path5.join(this.projectRoot, filePath);
1264
+ const relative = path5.relative(this.projectRoot, absolute);
1632
1265
  return relative.replace(/\\/g, "/");
1633
1266
  }
1634
1267
  };
@@ -1767,38 +1400,265 @@ var LearningSystem = class {
1767
1400
  }
1768
1401
  };
1769
1402
 
1770
- // src/tools/feedback.ts
1771
- var TrieFeedbackTool = class {
1772
- async execute(input) {
1773
- try {
1774
- const projectPath = input.directory || getWorkingDirectory(void 0, true);
1775
- const graph = new ContextGraph(projectPath);
1776
- const learning = new LearningSystem(graph, projectPath);
1777
- const decision = await graph.addNode("decision", {
1778
- context: input.target ?? "unspecified",
1779
- decision: input.helpful ? "helpful" : "not helpful",
1780
- reasoning: input.note ?? null,
1781
- outcome: input.helpful ? "good" : "bad",
1782
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1403
+ // src/guardian/learning-engine.ts
1404
+ import path6 from "path";
1405
+ var LearningEngine = class {
1406
+ projectPath;
1407
+ graph;
1408
+ learningSystem;
1409
+ constructor(projectPath, graph) {
1410
+ this.projectPath = projectPath;
1411
+ this.graph = graph || new ContextGraph(projectPath);
1412
+ this.learningSystem = new LearningSystem(this.graph, projectPath);
1413
+ }
1414
+ /**
1415
+ * Unified learning method: Scans history AND processes manual feedback
1416
+ */
1417
+ async learn(options = {}) {
1418
+ const results = [];
1419
+ if (!options.manualFeedback) {
1420
+ const implicitCount = await this.learnFromHistory(options.limit || 20);
1421
+ results.push({ learned: implicitCount, source: "git-history" });
1422
+ }
1423
+ if (options.manualFeedback) {
1424
+ await this.recordManualFeedback(
1425
+ options.manualFeedback.helpful,
1426
+ options.manualFeedback.files,
1427
+ options.manualFeedback.note
1428
+ );
1429
+ results.push({ learned: options.manualFeedback.files.length || 1, source: "manual-feedback" });
1430
+ }
1431
+ return results;
1432
+ }
1433
+ /**
1434
+ * Scan recent commits for implicit failure signals (reverts, fixes)
1435
+ */
1436
+ async learnFromHistory(limit = 20) {
1437
+ const commits = await getRecentCommits(this.projectPath, limit);
1438
+ const issuesToStore = [];
1439
+ for (const commit of commits) {
1440
+ const isRevert = commit.message.toLowerCase().includes("revert") || commit.message.startsWith('Revert "');
1441
+ const isFix = /fix(es|ed)?\s+#\d+/i.test(commit.message) || commit.message.toLowerCase().includes("bugfix");
1442
+ if (isRevert || isFix) {
1443
+ const type = isRevert ? "revert" : "fix";
1444
+ const diff = await getDiff(this.projectPath, commit.hash);
1445
+ const files = this.extractFilesFromDiff(diff);
1446
+ for (const file of files) {
1447
+ const learnedIssues = await this.extractIssuesFromDiff(diff, file, type, commit.message);
1448
+ issuesToStore.push(...learnedIssues);
1449
+ }
1450
+ }
1451
+ }
1452
+ if (issuesToStore.length > 0) {
1453
+ const result = await storeIssues(issuesToStore, path6.basename(this.projectPath), this.projectPath);
1454
+ return result.stored;
1455
+ }
1456
+ return 0;
1457
+ }
1458
+ /**
1459
+ * Record manual feedback (trie ok/bad) and adjust pattern confidence
1460
+ */
1461
+ async recordManualFeedback(helpful, files, note) {
1462
+ const decision = await this.graph.addNode("decision", {
1463
+ context: files.length > 0 ? files[0] : "unspecified",
1464
+ decision: helpful ? "helpful" : "not helpful",
1465
+ reasoning: note ?? null,
1466
+ outcome: helpful ? "good" : "bad",
1467
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1468
+ });
1469
+ if (files.length > 0) {
1470
+ for (const file of files) {
1471
+ const fileNode = await this.graph.getNode("file", file);
1472
+ if (fileNode) {
1473
+ await this.graph.addEdge(decision.id, fileNode.id, "affects");
1474
+ }
1475
+ }
1476
+ await this.learningSystem.onFeedback(helpful, files);
1477
+ }
1478
+ }
1479
+ extractFilesFromDiff(diff) {
1480
+ const files = /* @__PURE__ */ new Set();
1481
+ const lines = diff.split("\n");
1482
+ for (const line of lines) {
1483
+ if (line.startsWith("+++ b/")) {
1484
+ files.add(line.slice(6));
1485
+ }
1486
+ }
1487
+ return Array.from(files);
1488
+ }
1489
+ async extractIssuesFromDiff(diff, file, type, message) {
1490
+ const issues = [];
1491
+ const badLines = this.getBadLinesFromDiff(diff, file, type);
1492
+ const content = badLines.join("\n");
1493
+ if (!content) return [];
1494
+ const vulnerabilities = await scanForVulnerabilities(content, file);
1495
+ const vibeIssues = await scanForVibeCodeIssues(content, file);
1496
+ const allMatches = [...vulnerabilities, ...vibeIssues];
1497
+ for (const match of allMatches) {
1498
+ issues.push({
1499
+ id: `implicit-${type}-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
1500
+ severity: "serious",
1501
+ issue: `Implicit failure detected via ${type}: ${message}. Linked to pattern: ${match.category}`,
1502
+ fix: `Review the ${type} commit and avoid this pattern in ${file}.`,
1503
+ file,
1504
+ confidence: 0.7,
1505
+ autoFixable: false,
1506
+ agent: "implicit-learning",
1507
+ category: match.category
1783
1508
  });
1784
- if (input.files && input.files.length) {
1785
- for (const file of input.files) {
1786
- const fileNode = await graph.getNode("file", file);
1787
- if (fileNode) {
1788
- await graph.addEdge(decision.id, fileNode.id, "affects");
1509
+ }
1510
+ if (issues.length === 0) {
1511
+ issues.push({
1512
+ id: `implicit-${type}-${Date.now()}`,
1513
+ severity: "moderate",
1514
+ issue: `Historical ${type} detected: ${message}`,
1515
+ fix: `Review the changes in ${file} from this commit to avoid regression.`,
1516
+ file,
1517
+ confidence: 0.5,
1518
+ autoFixable: false,
1519
+ agent: "implicit-learning"
1520
+ });
1521
+ }
1522
+ return issues;
1523
+ }
1524
+ getBadLinesFromDiff(diff, file, type) {
1525
+ const badLines = [];
1526
+ const lines = diff.split("\n");
1527
+ let inTargetFile = false;
1528
+ for (const line of lines) {
1529
+ if (line.startsWith("+++ b/") || line.startsWith("--- a/")) {
1530
+ inTargetFile = line.includes(file);
1531
+ continue;
1532
+ }
1533
+ if (!inTargetFile) continue;
1534
+ if (type === "fix" && line.startsWith("-") && !line.startsWith("---")) {
1535
+ badLines.push(line.slice(1));
1536
+ } else if (type === "revert" && line.startsWith("+") && !line.startsWith("+++")) {
1537
+ badLines.push(line.slice(1));
1538
+ }
1539
+ }
1540
+ return badLines;
1541
+ }
1542
+ };
1543
+
1544
+ // src/ingest/linear-ingester.ts
1545
+ var LinearIngester = class {
1546
+ projectPath;
1547
+ graph;
1548
+ constructor(projectPath, graph) {
1549
+ this.projectPath = projectPath;
1550
+ this.graph = graph;
1551
+ }
1552
+ async syncTickets() {
1553
+ const apiKey = await this.getApiKey();
1554
+ if (!apiKey) {
1555
+ console.warn('Linear API key not found. Run "trie linear auth <key>" to enable ticket sync.');
1556
+ return;
1557
+ }
1558
+ const tickets = await this.fetchActiveTickets(apiKey);
1559
+ for (const ticket of tickets) {
1560
+ await this.ingestTicket(ticket);
1561
+ }
1562
+ }
1563
+ async getApiKey() {
1564
+ const config = await loadConfig();
1565
+ return config.apiKeys?.linear || process.env.LINEAR_API_KEY || null;
1566
+ }
1567
+ async fetchActiveTickets(apiKey) {
1568
+ const query = `
1569
+ query {
1570
+ issues(filter: { state: { type: { in: ["started", "unstarted"] } } }) {
1571
+ nodes {
1572
+ id
1573
+ identifier
1574
+ title
1575
+ description
1576
+ priority
1577
+ status {
1578
+ name
1579
+ }
1580
+ assignee {
1581
+ name
1582
+ }
1583
+ labels {
1584
+ nodes {
1585
+ name
1586
+ }
1587
+ }
1588
+ createdAt
1589
+ updatedAt
1789
1590
  }
1790
1591
  }
1791
- await learning.onFeedback(input.helpful, input.files);
1792
1592
  }
1793
- return {
1794
- content: [{
1795
- type: "text",
1796
- text: input.helpful ? "\u{1F44D} Thanks \u2014 I will prioritize more responses like this." : "\u{1F44E} Understood \u2014 I will adjust future guidance."
1797
- }]
1798
- };
1799
- } catch (error) {
1800
- const friendly = formatFriendlyError(error);
1801
- return { content: [{ type: "text", text: friendly.userMessage }] };
1593
+ `;
1594
+ const response = await fetch("https://api.linear.app/graphql", {
1595
+ method: "POST",
1596
+ headers: {
1597
+ "Content-Type": "application/json",
1598
+ "Authorization": apiKey
1599
+ },
1600
+ body: JSON.stringify({ query })
1601
+ });
1602
+ if (!response.ok) {
1603
+ throw new Error(`Linear API error: ${response.statusText}`);
1604
+ }
1605
+ const data = await response.json();
1606
+ return data.data.issues.nodes;
1607
+ }
1608
+ async ingestTicket(ticket) {
1609
+ const labels = ticket.labels.nodes.map((l) => l.name);
1610
+ const intentVibe = this.extractIntentVibes(ticket.title, ticket.description, labels);
1611
+ const linkedFiles = this.extractLinkedFiles(ticket.description);
1612
+ const data = {
1613
+ ticketId: ticket.identifier,
1614
+ title: ticket.title,
1615
+ description: ticket.description || "",
1616
+ priority: this.mapPriority(ticket.priority),
1617
+ labels,
1618
+ intentVibe,
1619
+ linkedFiles,
1620
+ status: ticket.status.name,
1621
+ assignee: ticket.assignee?.name || null,
1622
+ createdAt: ticket.createdAt,
1623
+ updatedAt: ticket.updatedAt
1624
+ };
1625
+ await this.graph.addNode("linear-ticket", data);
1626
+ for (const file of linkedFiles) {
1627
+ const fileNode = await this.graph.getNode("file", file);
1628
+ if (fileNode) {
1629
+ await this.graph.addEdge(`linear:${ticket.identifier}`, fileNode.id, "relatedTo");
1630
+ }
1631
+ }
1632
+ }
1633
+ extractIntentVibes(title, description, labels) {
1634
+ const vibes = /* @__PURE__ */ new Set();
1635
+ const text = (title + " " + (description || "") + " " + labels.join(" ")).toLowerCase();
1636
+ if (text.includes("performance") || text.includes("slow") || text.includes("optimize")) vibes.add("performance");
1637
+ if (text.includes("security") || text.includes("auth") || text.includes("vulnerability")) vibes.add("security");
1638
+ if (text.includes("refactor") || text.includes("cleanup") || text.includes("debt")) vibes.add("refactor");
1639
+ if (text.includes("feature") || text.includes("new")) vibes.add("feature");
1640
+ if (text.includes("bug") || text.includes("fix") || text.includes("broken")) vibes.add("bug");
1641
+ if (text.includes("breaking") || text.includes("major change")) vibes.add("breaking-change");
1642
+ return Array.from(vibes);
1643
+ }
1644
+ extractLinkedFiles(description) {
1645
+ if (!description) return [];
1646
+ const matches = description.match(/[\\w./_-]+\\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs)/gi);
1647
+ if (!matches) return [];
1648
+ return Array.from(new Set(matches.map((m) => m.replace(/^\.\/+/, ""))));
1649
+ }
1650
+ mapPriority(priority) {
1651
+ switch (priority) {
1652
+ case 1:
1653
+ return "urgent";
1654
+ case 2:
1655
+ return "high";
1656
+ case 3:
1657
+ return "medium";
1658
+ case 4:
1659
+ return "low";
1660
+ default:
1661
+ return "none";
1802
1662
  }
1803
1663
  }
1804
1664
  };
@@ -1809,7 +1669,6 @@ export {
1809
1669
  shouldAutoFix,
1810
1670
  shouldBlockPush,
1811
1671
  getAutonomyConfig,
1812
- ContextGraph,
1813
1672
  perceiveCurrentChanges,
1814
1673
  reasonAboutChangesHumanReadable,
1815
1674
  loadBootstrapContext,
@@ -1826,6 +1685,7 @@ export {
1826
1685
  exportToJson,
1827
1686
  importFromJson,
1828
1687
  IncidentIndex,
1829
- TrieFeedbackTool
1688
+ LearningEngine,
1689
+ LinearIngester
1830
1690
  };
1831
- //# sourceMappingURL=chunk-53URTRWH.js.map
1691
+ //# sourceMappingURL=chunk-FW435YKY.js.map