@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.
- package/README.md +91 -20
- package/dist/{agent-smith-XGYNJUCJ.js → agent-smith-MCKGNWPL.js} +3 -3
- package/dist/{agent-smith-runner-QHYGVRNR.js → agent-smith-runner-GP5HLL7E.js} +3 -3
- package/dist/{chunk-LNLLZQWH.js → chunk-2BXLPYHR.js} +604 -138
- package/dist/chunk-2BXLPYHR.js.map +1 -0
- package/dist/{chunk-35FAFFHE.js → chunk-75J4HQTD.js} +2 -2
- package/dist/{chunk-RRDDAD5N.js → chunk-7OVM6KEY.js} +34 -7
- package/dist/chunk-7OVM6KEY.js.map +1 -0
- package/dist/chunk-B7CLAOEK.js +532 -0
- package/dist/chunk-B7CLAOEK.js.map +1 -0
- package/dist/{chunk-Z7N7KDK3.js → chunk-DCJKNE2L.js} +2 -1
- package/dist/{chunk-P6VLSYXN.js → chunk-EWIEXQES.js} +2 -2
- package/dist/{chunk-53URTRWH.js → chunk-FW435YKY.js} +300 -440
- package/dist/chunk-FW435YKY.js.map +1 -0
- package/dist/{chunk-UPKBO5EM.js → chunk-MVWRFARH.js} +137 -559
- package/dist/chunk-MVWRFARH.js.map +1 -0
- package/dist/{chunk-EWQF6INU.js → chunk-TBRU735C.js} +2 -2
- package/dist/{chunk-AIC4HOOQ.js → chunk-U5P3O5G5.js} +3 -3
- package/dist/{chunk-6QKDEGWR.js → chunk-WGECLUDQ.js} +4 -4
- package/dist/chunk-WGECLUDQ.js.map +1 -0
- package/dist/{chunk-3RKY55HZ.js → chunk-YKG4KIY7.js} +673 -83
- package/dist/chunk-YKG4KIY7.js.map +1 -0
- package/dist/cli/main.js +296 -64
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/yolo-daemon.js +12 -11
- package/dist/cli/yolo-daemon.js.map +1 -1
- package/dist/{goal-manager-NI4LJ2SX.js → goal-manager-NHPEUWFY.js} +4 -4
- package/dist/guardian-agent-GWYDNLWC.js +21 -0
- package/dist/index.js +115 -50
- package/dist/index.js.map +1 -1
- package/dist/{issue-store-MULGOF6B.js → issue-store-RKJVOKSJ.js} +2 -2
- package/dist/ui/memory-viewer.html +4 -4
- package/dist/ui/pr-review.html +4 -4
- package/dist/ui/scan-dashboard.html +4 -4
- package/dist/ui/visual-qa.html +4 -4
- package/dist/workers/agent-worker.js +5 -5
- package/package.json +1 -1
- package/dist/chunk-3RKY55HZ.js.map +0 -1
- package/dist/chunk-53URTRWH.js.map +0 -1
- package/dist/chunk-6QKDEGWR.js.map +0 -1
- package/dist/chunk-LNLLZQWH.js.map +0 -1
- package/dist/chunk-RRDDAD5N.js.map +0 -1
- package/dist/chunk-UPKBO5EM.js.map +0 -1
- package/dist/guardian-agent-R5HX7UWJ.js +0 -17
- /package/dist/{agent-smith-XGYNJUCJ.js.map → agent-smith-MCKGNWPL.js.map} +0 -0
- /package/dist/{agent-smith-runner-QHYGVRNR.js.map → agent-smith-runner-GP5HLL7E.js.map} +0 -0
- /package/dist/{chunk-35FAFFHE.js.map → chunk-75J4HQTD.js.map} +0 -0
- /package/dist/{chunk-Z7N7KDK3.js.map → chunk-DCJKNE2L.js.map} +0 -0
- /package/dist/{chunk-P6VLSYXN.js.map → chunk-EWIEXQES.js.map} +0 -0
- /package/dist/{chunk-EWQF6INU.js.map → chunk-TBRU735C.js.map} +0 -0
- /package/dist/{chunk-AIC4HOOQ.js.map → chunk-U5P3O5G5.js.map} +0 -0
- /package/dist/{goal-manager-NI4LJ2SX.js.map → goal-manager-NHPEUWFY.js.map} +0 -0
- /package/dist/{guardian-agent-R5HX7UWJ.js.map → guardian-agent-GWYDNLWC.js.map} +0 -0
- /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
|
-
|
|
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
|
|
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 =
|
|
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:
|
|
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
|
|
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 =
|
|
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
|
|
1458
|
-
import
|
|
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 ??
|
|
1464
|
-
await
|
|
1465
|
-
await
|
|
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
|
|
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
|
|
1108
|
+
import path5 from "path";
|
|
1476
1109
|
|
|
1477
1110
|
// src/context/file-trie.ts
|
|
1478
|
-
import
|
|
1479
|
-
import
|
|
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 &&
|
|
1123
|
+
if (persistPath && fs2.existsSync(persistPath)) {
|
|
1491
1124
|
try {
|
|
1492
|
-
const raw =
|
|
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(
|
|
1176
|
+
timeLookup(path7) {
|
|
1544
1177
|
const start = performance.now();
|
|
1545
|
-
this.getIncidents(
|
|
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 =
|
|
1559
|
-
if (!
|
|
1560
|
-
|
|
1191
|
+
const dir = path4.dirname(this.persistPath);
|
|
1192
|
+
if (!fs2.existsSync(dir)) {
|
|
1193
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
1561
1194
|
}
|
|
1562
|
-
|
|
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 ??
|
|
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 =
|
|
1631
|
-
const relative =
|
|
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/
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
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
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
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
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
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
|
-
|
|
1688
|
+
LearningEngine,
|
|
1689
|
+
LinearIngester
|
|
1830
1690
|
};
|
|
1831
|
-
//# sourceMappingURL=chunk-
|
|
1691
|
+
//# sourceMappingURL=chunk-FW435YKY.js.map
|