@triedotdev/mcp 1.0.137 → 1.0.139
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 +188 -43
- package/dist/{autonomy-config-QA6ATWLJ.js → autonomy-config-ZCOSTMPD.js} +3 -3
- package/dist/{chat-store-HFOOWZYN.js → chat-store-OJLJCJFI.js} +3 -3
- package/dist/{chunk-DFPVUMVE.js → chunk-23RJT5WT.js} +5 -4
- package/dist/chunk-23RJT5WT.js.map +1 -0
- package/dist/{chunk-QNKBXOIQ.js → chunk-3MUCUZ46.js} +3 -5
- package/dist/chunk-3MUCUZ46.js.map +1 -0
- package/dist/{chunk-WHIQAGB7.js → chunk-4C67GV3O.js} +2 -2
- package/dist/{chunk-AXYNWBME.js → chunk-4O2KRHK4.js} +1907 -414
- package/dist/chunk-4O2KRHK4.js.map +1 -0
- package/dist/{chunk-ZEXMMTIQ.js → chunk-5KJ4UJOY.js} +10 -5
- package/dist/chunk-5KJ4UJOY.js.map +1 -0
- package/dist/chunk-62POBLFC.js +1925 -0
- package/dist/chunk-62POBLFC.js.map +1 -0
- package/dist/{chunk-HUR67JXG.js → chunk-75ADWWUF.js} +38 -19
- package/dist/chunk-75ADWWUF.js.map +1 -0
- package/dist/{chunk-4JQ6W7LW.js → chunk-7OJ6JIPL.js} +40 -608
- package/dist/chunk-7OJ6JIPL.js.map +1 -0
- package/dist/{chunk-6VIMBFUZ.js → chunk-AF2APASP.js} +58 -20
- package/dist/chunk-AF2APASP.js.map +1 -0
- package/dist/{chunk-Z4DN527J.js → chunk-FG467PDD.js} +156 -39
- package/dist/chunk-FG467PDD.js.map +1 -0
- package/dist/{chunk-55CBWOEZ.js → chunk-FH335WL5.js} +10 -2
- package/dist/chunk-FH335WL5.js.map +1 -0
- package/dist/{chunk-O6OTJI3W.js → chunk-FPEMP54L.js} +22 -16
- package/dist/chunk-FPEMP54L.js.map +1 -0
- package/dist/{chunk-K6NTRSDF.js → chunk-GXF6JOCN.js} +24 -326
- package/dist/chunk-GXF6JOCN.js.map +1 -0
- package/dist/chunk-LD7ZEFNY.js +132 -0
- package/dist/chunk-LD7ZEFNY.js.map +1 -0
- package/dist/{chunk-6EP2VTHC.js → chunk-LT6VUZG2.js} +7 -4
- package/dist/chunk-LT6VUZG2.js.map +1 -0
- package/dist/chunk-NKHO34UZ.js +467 -0
- package/dist/chunk-NKHO34UZ.js.map +1 -0
- package/dist/{chunk-QM5VIDFN.js → chunk-OQ4A3RDY.js} +46 -30
- package/dist/chunk-OQ4A3RDY.js.map +1 -0
- package/dist/{chunk-45Y5TLQZ.js → chunk-SH7H3WRU.js} +3 -6
- package/dist/chunk-SH7H3WRU.js.map +1 -0
- package/dist/{chunk-G74XEI7K.js → chunk-UOSTOLU7.js} +21 -21
- package/dist/chunk-UOSTOLU7.js.map +1 -0
- package/dist/{chunk-DPZLABUC.js → chunk-XTTZAQWJ.js} +28 -22
- package/dist/chunk-XTTZAQWJ.js.map +1 -0
- package/dist/{chunk-A6PWS6ZV.js → chunk-YEIJW6X6.js} +15 -5
- package/dist/chunk-YEIJW6X6.js.map +1 -0
- package/dist/chunk-YOJGSRZK.js +216 -0
- package/dist/chunk-YOJGSRZK.js.map +1 -0
- package/dist/cli/create-agent.js +1 -1
- package/dist/cli/main.js +636 -99
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/yolo-daemon.js +21 -19
- package/dist/cli/yolo-daemon.js.map +1 -1
- package/dist/{client-BZHI675W.js → client-INNE2GGZ.js} +3 -3
- package/dist/{codebase-index-CR6Q2HEI.js → codebase-index-5SEOESWM.js} +4 -4
- package/dist/fast-analyzer-AYLZB5TW.js +216 -0
- package/dist/fast-analyzer-AYLZB5TW.js.map +1 -0
- package/dist/github-ingester-J2ZFYXVE.js +11 -0
- package/dist/{goal-manager-62IL6WGY.js → goal-manager-ZBWKWEML.js} +6 -6
- package/dist/{goal-validator-HPPBSDXD.js → goal-validator-HNXXUCPW.js} +5 -5
- package/dist/{graph-PAUZ5EMP.js → graph-J4OGTYCO.js} +3 -3
- package/dist/{hypothesis-W37VG6DA.js → hypothesis-JCUMZKTG.js} +6 -6
- package/dist/{incident-index-ZCDSJ42L.js → incident-index-BWW2UEY7.js} +3 -3
- package/dist/index.js +1168 -137
- package/dist/index.js.map +1 -1
- package/dist/{insight-store-U3NYTOJE.js → insight-store-A5XXMFD6.js} +3 -5
- package/dist/{issue-store-EZMBHOVN.js → issue-store-LZWZIGM7.js} +3 -3
- package/dist/linear-ingester-JRDQAIAA.js +11 -0
- package/dist/{tiered-storage-QW2G7GSG.js → tiered-storage-VZL7KK64.js} +3 -3
- package/dist/tiered-storage-VZL7KK64.js.map +1 -0
- package/dist/trie-agent-M6PHM6UD.js +26 -0
- package/dist/trie-agent-M6PHM6UD.js.map +1 -0
- package/dist/ui/chat.html +260 -67
- package/dist/ui/goals.html +246 -3
- package/dist/ui/hypotheses.html +248 -5
- package/dist/ui/ledger.html +252 -9
- package/dist/ui/nudges.html +244 -1
- package/package.json +15 -8
- package/dist/chunk-45Y5TLQZ.js.map +0 -1
- package/dist/chunk-4JQ6W7LW.js.map +0 -1
- package/dist/chunk-55CBWOEZ.js.map +0 -1
- package/dist/chunk-6EP2VTHC.js.map +0 -1
- package/dist/chunk-6VIMBFUZ.js.map +0 -1
- package/dist/chunk-A6PWS6ZV.js.map +0 -1
- package/dist/chunk-AXYNWBME.js.map +0 -1
- package/dist/chunk-DFPVUMVE.js.map +0 -1
- package/dist/chunk-DPZLABUC.js.map +0 -1
- package/dist/chunk-G74XEI7K.js.map +0 -1
- package/dist/chunk-HUR67JXG.js.map +0 -1
- package/dist/chunk-K6NTRSDF.js.map +0 -1
- package/dist/chunk-O6OTJI3W.js.map +0 -1
- package/dist/chunk-QM5VIDFN.js.map +0 -1
- package/dist/chunk-QNKBXOIQ.js.map +0 -1
- package/dist/chunk-R3WZI6QZ.js +0 -883
- package/dist/chunk-R3WZI6QZ.js.map +0 -1
- package/dist/chunk-Z4DN527J.js.map +0 -1
- package/dist/chunk-ZEXMMTIQ.js.map +0 -1
- package/dist/guardian-agent-YKG5XURG.js +0 -30
- /package/dist/{autonomy-config-QA6ATWLJ.js.map → autonomy-config-ZCOSTMPD.js.map} +0 -0
- /package/dist/{chat-store-HFOOWZYN.js.map → chat-store-OJLJCJFI.js.map} +0 -0
- /package/dist/{chunk-WHIQAGB7.js.map → chunk-4C67GV3O.js.map} +0 -0
- /package/dist/{client-BZHI675W.js.map → client-INNE2GGZ.js.map} +0 -0
- /package/dist/{codebase-index-CR6Q2HEI.js.map → codebase-index-5SEOESWM.js.map} +0 -0
- /package/dist/{goal-manager-62IL6WGY.js.map → github-ingester-J2ZFYXVE.js.map} +0 -0
- /package/dist/{goal-validator-HPPBSDXD.js.map → goal-manager-ZBWKWEML.js.map} +0 -0
- /package/dist/{graph-PAUZ5EMP.js.map → goal-validator-HNXXUCPW.js.map} +0 -0
- /package/dist/{guardian-agent-YKG5XURG.js.map → graph-J4OGTYCO.js.map} +0 -0
- /package/dist/{hypothesis-W37VG6DA.js.map → hypothesis-JCUMZKTG.js.map} +0 -0
- /package/dist/{incident-index-ZCDSJ42L.js.map → incident-index-BWW2UEY7.js.map} +0 -0
- /package/dist/{insight-store-U3NYTOJE.js.map → insight-store-A5XXMFD6.js.map} +0 -0
- /package/dist/{issue-store-EZMBHOVN.js.map → issue-store-LZWZIGM7.js.map} +0 -0
- /package/dist/{tiered-storage-QW2G7GSG.js.map → linear-ingester-JRDQAIAA.js.map} +0 -0
package/README.md
CHANGED
|
@@ -1,30 +1,36 @@
|
|
|
1
|
-
# Trie:
|
|
1
|
+
# Trie: Governance for Teams That Ship with AI
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**The ledger that keeps your work compliant when agents and humans ship together—so you ship the right thing every time.**
|
|
4
4
|
|
|
5
5
|
[](https://www.trie.dev) [](https://x.com/louiskishfy)
|
|
6
6
|
|
|
7
7
|
## What Trie Does
|
|
8
8
|
|
|
9
|
-
Trie
|
|
9
|
+
Trie maintains a **decision ledger** that governs work across agents and humans:
|
|
10
10
|
|
|
11
11
|
- **Autonomous Operation**: Run `trie watch` and the agent monitors your codebase 24/7
|
|
12
12
|
- **Intelligent Extraction**: Automatically extracts decisions, facts, blockers from every change
|
|
13
|
-
- **
|
|
13
|
+
- **Cryptographic governance ledger**: Stores decisions, incidents, and fixes in a tamper-evident chain—the shared memory that travels from Cursor/Claude Code → CLI → CI/CD, solving the context-across-tools problem
|
|
14
14
|
- **Predictive Intelligence**: `trie gotcha` queries the ledger to predict problems before they happen
|
|
15
15
|
- **Continuous Learning**: Feed it incidents with `trie tell`, teach it patterns with your history
|
|
16
16
|
|
|
17
|
-
The
|
|
17
|
+
The ledger learns from every incident, decision, and fix. When you ship, Trie remembers. When something breaks, Trie learns. Over time, everyone on the team—human and agent—gets better at predicting what will go wrong before it does.
|
|
18
|
+
|
|
19
|
+
### The Context-Across-Tools Problem (and How the Ledger Solves It)
|
|
20
|
+
|
|
21
|
+
**The problem**: When work happens across Cursor, Claude Code, VS Code, the terminal, and CI/CD, context fragments. An agent makes a decision in one tool; a human forgets it in another. Each environment has its own memory—or none at all. You burn tokens re-explaining the same constraints, or worse, ship code that violates decisions made elsewhere.
|
|
22
|
+
|
|
23
|
+
**The solution**: Trie stores important information in a **cryptographic governance ledger**—a tamper-evident, append-only chain of blocks. Every decision, incident, fix, and tradeoff gets written to the ledger. Because the ledger lives in your `.trie/` folder and syncs across your team, **every tool reads from the same source of truth**. Cursor, Claude, the CLI, and CI/CD all query the same blocks. No more context loss. No more conflicting memories. The ledger is the shared brain that keeps agents and humans aligned across every tool you use.
|
|
18
24
|
|
|
19
25
|
## Goal
|
|
20
26
|
|
|
21
|
-
**Trie is
|
|
27
|
+
**Trie is the governance layer for teams where agents and humans ship together.**
|
|
22
28
|
|
|
23
|
-
Every bug you fix teaches the
|
|
29
|
+
Every bug you fix teaches the ledger a pattern that protects all your projects. Every incident you report becomes institutional knowledge that travels with your code. Every decision you make—and the tradeoffs you considered—gets extracted and stored automatically. The ledger keeps work compliant so you ship the right thing every time.
|
|
24
30
|
|
|
25
|
-
Instead of burning tokens on the same questions across different repos or forgetting why you architected something a certain way six months ago,
|
|
31
|
+
Instead of burning tokens on the same questions across different repos or forgetting why you architected something a certain way six months ago, the ledger remembers for everyone. Instead of agents and humans stepping on each other's decisions, the ledger maintains system coherence.
|
|
26
32
|
|
|
27
|
-
The result
|
|
33
|
+
The result: faster development with fewer production fires, because the ledger gets smarter every time something breaks—and every agent and human on the team benefits.
|
|
28
34
|
|
|
29
35
|
### How the Agent Works
|
|
30
36
|
|
|
@@ -35,7 +41,7 @@ The result is faster development with fewer production fires, because **your age
|
|
|
35
41
|
5. **`trie tell`** - Feed agent incidents to improve its predictions
|
|
36
42
|
6. **Agent Learns** - Gets better at predicting what matters in YOUR codebase
|
|
37
43
|
|
|
38
|
-
|
|
44
|
+
Your decisions persist across tools. Your edge cases don't get forgotten. The ledger keeps agents and humans compliant—so you ship the right thing every time.
|
|
39
45
|
|
|
40
46
|
## Quick Start
|
|
41
47
|
|
|
@@ -70,13 +76,13 @@ trie bad # Prediction was wrong
|
|
|
70
76
|
|
|
71
77
|
## Why Trie Exists
|
|
72
78
|
|
|
73
|
-
|
|
79
|
+
The real challenge isn't generating code—it's governance. When some of your teammates are agents and you're working with multiple humans, context fragments. An agent makes a decision in Cursor, a human forgets it in Claude Code, another agent ships something that breaks what you fixed last week. You're not just maintaining a codebase—you're coordinating a mixed team where work happens across tools, models, and people.
|
|
74
80
|
|
|
75
|
-
The
|
|
81
|
+
The ledger is the answer. Trie keeps a tamper-evident record of decisions, incidents, and tradeoffs so everyone—human and agent—stays compliant with what you've already learned. Ship the right thing every time. That's the competitive advantage. Software margins are compressing; pure application software is becoming a fundamentally different, worse category. The teams that can coordinate agents and humans, that can scale contributors without losing coherence, will win.
|
|
76
82
|
|
|
77
|
-
|
|
83
|
+
Cursor is building toward self-driving codebases—agents that merge PRs, manage rollouts, and monitor production. We're moving from a world where developers use agents to create diffs to one where agents ship tested features end-to-end. The closer we march toward self-driving systems and AGI, the more important governance becomes. That shift requires tooling that coordinates work across many agents and models that learn from past runs. Trie is optimized for coordination and collaboration with both humans and agents. It keeps your work compliant, scales your contributors (human and AI), and turns your decision history into durable institutional knowledge.
|
|
78
84
|
|
|
79
|
-
|
|
85
|
+
Tools like Cursor Bugbot flag issues—but flagging doesn't help you avoid similar patterns in the future. Trie remembers what broke, learns across projects, and warns before you ship risky code. You end up architecting better and prompting better because the ledger enforces coherence.
|
|
80
86
|
|
|
81
87
|
## Key Features
|
|
82
88
|
|
|
@@ -86,7 +92,8 @@ Trie remembers your decisions across tools, tracks the tradeoffs you've made, an
|
|
|
86
92
|
- Cross-project learning - Patterns discovered in one project help prevent bugs in others.
|
|
87
93
|
- Incident tracking - Build a searchable history of what went wrong and why.
|
|
88
94
|
- Decision memory - Remembers architectural choices and tradeoffs across Cursor, Claude, VS Code, CLI, and CI/CD.
|
|
89
|
-
-
|
|
95
|
+
- Cryptographic governance ledger - Chain-of-blocks, append-only, tamper-evident; solves the context-across-tools problem; every tool reads from the same source of truth.
|
|
96
|
+
- Governance that travels - The ledger keeps agents and humans compliant across all your tools.
|
|
90
97
|
|
|
91
98
|
### Intelligent Analysis
|
|
92
99
|
|
|
@@ -108,12 +115,12 @@ Trie remembers your decisions across tools, tracks the tradeoffs you've made, an
|
|
|
108
115
|
|
|
109
116
|
## How It Works
|
|
110
117
|
|
|
111
|
-
### The
|
|
118
|
+
### The Trie Agent
|
|
112
119
|
|
|
113
|
-
Trie uses a
|
|
120
|
+
Trie uses a proactive agent architecture:
|
|
114
121
|
|
|
115
122
|
- Analyzes your code for potential issues based on your incident history.
|
|
116
|
-
-
|
|
123
|
+
- The agent decides what matters based on your history.
|
|
117
124
|
- Memory Tree stores incident patterns using a trie data structure for fast lookups.
|
|
118
125
|
- Learning Loop improves predictions based on your feedback.
|
|
119
126
|
|
|
@@ -126,10 +133,14 @@ your-project/
|
|
|
126
133
|
│ ├── warm/ # Queryable decisions DB
|
|
127
134
|
│ │ └── decisions.db # SQLite database
|
|
128
135
|
│ ├── cold/ # Archived history
|
|
129
|
-
│ ├── memory/ # Incident history
|
|
136
|
+
│ ├── memory/ # Incident history + ledger.json (cryptographic ledger)
|
|
130
137
|
│ ├── patterns/ # Learned patterns
|
|
131
138
|
│ ├── context.json # Project knowledge graph
|
|
132
139
|
│ └── config.json # Settings
|
|
140
|
+
├── .trie-shared/ # Shared ledger for team sync (optional)
|
|
141
|
+
│ ├── active/ # Recent blocks
|
|
142
|
+
│ ├── archived/ # Compressed old blocks
|
|
143
|
+
│ └── ledger-manifest.json
|
|
133
144
|
├── src/
|
|
134
145
|
└── .git/
|
|
135
146
|
```
|
|
@@ -143,18 +154,18 @@ Different machines
|
|
|
143
154
|
|
|
144
155
|
### Decision Memory Across Tools
|
|
145
156
|
|
|
146
|
-
Trie
|
|
157
|
+
Trie solves the context-across-tools problem with a **cryptographic governance ledger**: an append-only, tamper-evident chain of blocks that stores decisions, incidents, fixes, and tradeoffs. Every tool—Cursor, Claude, VS Code, CLI, CI/CD—reads from the same ledger in `.trie/`, so there is no context fragmentation.
|
|
147
158
|
|
|
148
|
-
Decision nodes store why you made certain choices and what tradeoffs were considered
|
|
149
|
-
Cross-tool access - Cursor, Claude, VS Code, CLI, and CI/CD all read from the same
|
|
150
|
-
Context trail - Knows which environment ran which analysis and when
|
|
151
|
-
Relationship tracking - Files ↔ Changes ↔ Incidents ↔ Fixes ↔ Decisions
|
|
159
|
+
- **Decision nodes** store why you made certain choices and what tradeoffs were considered
|
|
160
|
+
- **Cross-tool access** - Cursor, Claude, VS Code, CLI, and CI/CD all read from the same `.trie/` folder
|
|
161
|
+
- **Context trail** - Knows which environment ran which analysis and when
|
|
162
|
+
- **Relationship tracking** - Files ↔ Changes ↔ Incidents ↔ Fixes ↔ Decisions
|
|
152
163
|
|
|
153
|
-
When you switch from Cursor to Claude Code to terminal
|
|
164
|
+
When you switch from Cursor to Claude Code to terminal—or when different agents and humans work in parallel—Trie remembers. Every tool shares the same ledger, so governance stays consistent.
|
|
154
165
|
|
|
155
166
|
### Signal Extraction: Context Without Pollution
|
|
156
167
|
|
|
157
|
-
|
|
168
|
+
The Problem: Agents drown in raw data. Dumping 10,000 lines of logs, 500 Slack messages, and 200 commits into context is expensive and ineffective.
|
|
158
169
|
|
|
159
170
|
**Trie's Solution**: Extract signal, not noise.
|
|
160
171
|
|
|
@@ -181,7 +192,7 @@ When you switch from Cursor to Claude Code to terminal, Trie remembers. Your thi
|
|
|
181
192
|
|
|
182
193
|
#### MCP Query Tools
|
|
183
194
|
|
|
184
|
-
Agents don't get dumps—they
|
|
195
|
+
Agents don't get dumps—they query for what they need:
|
|
185
196
|
|
|
186
197
|
```typescript
|
|
187
198
|
// Agent queries decision ledger
|
|
@@ -196,7 +207,7 @@ trie_get_decisions({
|
|
|
196
207
|
// 2. "EU customers need VAT validation" (2 months ago)
|
|
197
208
|
```
|
|
198
209
|
|
|
199
|
-
|
|
210
|
+
Why this matters: context management IS the product. Agents get the right information at the right moment, not everything dumped at once.
|
|
200
211
|
|
|
201
212
|
## Core Workflow
|
|
202
213
|
|
|
@@ -214,7 +225,7 @@ trie status # Check overall project health
|
|
|
214
225
|
# Trie's Context Graph remembers why you made choices and what happened
|
|
215
226
|
```
|
|
216
227
|
|
|
217
|
-
|
|
228
|
+
Pro tip: The moment something goes sideways, check Trie again. Don't keep pushing—re-plan with historical context. Trie shows you what broke before, what decisions were made, and what edge cases caused issues. Use that knowledge to inform your plan, then let your AI tools implement it.
|
|
218
229
|
|
|
219
230
|
### 1. Teaching Phase
|
|
220
231
|
|
|
@@ -250,16 +261,16 @@ trie bad
|
|
|
250
261
|
# Also updates: decision patterns, edge case recognition, tradeoff understanding
|
|
251
262
|
```
|
|
252
263
|
|
|
253
|
-
### 4.
|
|
264
|
+
### 4. Governance Phase
|
|
254
265
|
|
|
255
|
-
This is where Trie shines. As your
|
|
266
|
+
This is where Trie shines. As your team grows—more humans, more agents, more tools:
|
|
256
267
|
|
|
257
268
|
```bash
|
|
258
|
-
# Working in Cursor,
|
|
259
|
-
# Trie records it in the
|
|
269
|
+
# Working in Cursor, an agent makes a decision about error handling
|
|
270
|
+
# Trie records it in the ledger
|
|
260
271
|
|
|
261
|
-
#
|
|
262
|
-
# Same
|
|
272
|
+
# A teammate switches to Claude Code later
|
|
273
|
+
# Same ledger, same decisions, same compliance
|
|
263
274
|
|
|
264
275
|
# Push from terminal
|
|
265
276
|
# Git hooks check against your full history of decisions and incidents
|
|
@@ -268,7 +279,7 @@ This is where Trie shines. As your app grows and you handle edge cases:
|
|
|
268
279
|
# Same checks, same memory, same coherence
|
|
269
280
|
```
|
|
270
281
|
|
|
271
|
-
Edge cases, tradeoffs, and system coherence—Trie handles
|
|
282
|
+
Edge cases, tradeoffs, and system coherence—Trie handles governance by remembering what was decided, why it was decided, and what happened as a result. When agents and humans ship together, the ledger keeps everyone compliant.
|
|
272
283
|
|
|
273
284
|
## Advanced Features
|
|
274
285
|
|
|
@@ -312,7 +323,7 @@ trie watch
|
|
|
312
323
|
# Reattach with: tmux attach -t trie-watch
|
|
313
324
|
```
|
|
314
325
|
|
|
315
|
-
This allows you to keep the
|
|
326
|
+
This allows you to keep the agent running while using other terminals. The interactive dashboard will be available when you reattach.
|
|
316
327
|
|
|
317
328
|
### JIT Defect Prediction ("Gotchas")
|
|
318
329
|
|
|
@@ -332,6 +343,116 @@ trie gotcha
|
|
|
332
343
|
|
|
333
344
|
Trie will warn you if your current task correlates with historical regressions or high-risk signatures.
|
|
334
345
|
|
|
346
|
+
### Integrations: Linear, GitHub & Cursor Cloud Agent
|
|
347
|
+
|
|
348
|
+
**Linear** — Sync active tickets for JIT defect prediction:
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
trie linear auth <your-api-key>
|
|
352
|
+
trie linear sync
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Or via MCP: `trie_linear_sync` — syncs tickets into the context graph for gotcha predictions.
|
|
356
|
+
|
|
357
|
+
**GitHub** — Sync open PRs and issues into the context graph:
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
# Via MCP (Cursor/Claude)
|
|
361
|
+
trie_github_sync
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Links PRs to changed files and to Linear tickets mentioned in PR descriptions. Requires `GITHUB_TOKEN` (repo scope for private repos, public_repo for public).
|
|
365
|
+
|
|
366
|
+
**Cursor Cloud Agent** — Dispatch high-risk issues to Cursor's cloud for verified, test-passing fixes:
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
# Via MCP
|
|
370
|
+
trie_cloud_fix action:configure apiKey:"key-..."
|
|
371
|
+
trie_cloud_fix action:dispatch issueIds:["issue-1", "issue-2"]
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
The cloud agent runs in an isolated VM, applies the fix, runs tests, captures screenshots, and opens a PR. Requires `CURSOR_API_KEY`. Use `trie_fix action:route` first to see which issues qualify.
|
|
375
|
+
|
|
376
|
+
### Fix Triage System
|
|
377
|
+
|
|
378
|
+
Trie routes each issue to one of three fix strategies based on a scoring system:
|
|
379
|
+
|
|
380
|
+
| Strategy | When | Action |
|
|
381
|
+
|----------|------|--------|
|
|
382
|
+
| **inline-auto** | Trivial, auto-fixable (score < 0) | Apply fix automatically |
|
|
383
|
+
| **local-ai** | Moderate risk (score 0–3) | `trie_fix` — local AI applies fix |
|
|
384
|
+
| **cloud-agent** | High risk (score ≥ 4) | `trie_cloud_fix` — Cursor cloud agent |
|
|
385
|
+
|
|
386
|
+
Scoring signals: Issue shape (effort, severity, CWE, OWASP), code context (tests, auth/crypto/payments), occurrence history (how often seen), pipeline context (linked PR/ticket), and user config.
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
# See routing plan before applying
|
|
390
|
+
trie_fix action:route
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Pipeline View
|
|
394
|
+
|
|
395
|
+
Get a consolidated view of your work across Linear, GitHub, and Trie:
|
|
396
|
+
|
|
397
|
+
```bash
|
|
398
|
+
# Via MCP
|
|
399
|
+
trie_pipeline # Full status: tickets, PRs, issues, coverage gaps
|
|
400
|
+
trie_pipeline action:coverage # Only Trie issues with no ticket/PR
|
|
401
|
+
trie_pipeline action:create_tickets issueIds:["id1","id2"] # Open Linear tickets for uncovered issues
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Cryptographic Governance Ledger
|
|
405
|
+
|
|
406
|
+
Trie uses a **chain-of-blocks ledger** for tamper-evident incident history and team sync. The ledger transforms from isolated per-developer chains into a collaborative, distributed cryptographic ledger that scales to teams while maintaining integrity.
|
|
407
|
+
|
|
408
|
+
**Architecture:**
|
|
409
|
+
- **Chained blocks** — Each block links to the previous via hash; genesis block starts the chain
|
|
410
|
+
- **Merkle roots** — Block contents hashed for integrity verification
|
|
411
|
+
- **Author attribution** — Each block records who added it; git commit correlation for developer attribution
|
|
412
|
+
- **Version 2 format** — Syncable blocks with backwards compatibility for v1 ledgers
|
|
413
|
+
|
|
414
|
+
**Shared storage** (`.trie-shared/`):
|
|
415
|
+
|
|
416
|
+
```
|
|
417
|
+
.trie-shared/
|
|
418
|
+
├── ledger-manifest.json # Global chain metadata + index
|
|
419
|
+
├── active/ # Hot storage (recent blocks)
|
|
420
|
+
│ ├── 2024-01-20.json
|
|
421
|
+
│ └── 2024-01-21.json
|
|
422
|
+
└── archived/ # Cold storage (compressed)
|
|
423
|
+
├── 2024-01.tar.gz # Monthly archives
|
|
424
|
+
└── 2023-12.tar.gz
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
**Compression & scalability:**
|
|
428
|
+
- Automatic archiving after 30 days
|
|
429
|
+
- gzip compression with configurable levels (90%+ space savings)
|
|
430
|
+
- Hot/cold storage tiers; lazy loading of archived content
|
|
431
|
+
|
|
432
|
+
**Conflict resolution:** Divergent chains merge with timestamp or longest-chain strategy; entry deduplication across developer chains.
|
|
433
|
+
|
|
434
|
+
**Git integration:** Auto-sync via `trie sync hooks --install` — pre-push and post-merge hooks keep local and shared ledgers in sync. Commit correlation and developer attribution from git history.
|
|
435
|
+
|
|
436
|
+
**Backwards compatibility:** Automatic migration of v1 ledgers; legacy detection and zero-data-loss upgrade.
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
# Sync commands
|
|
440
|
+
trie sync init # Initialize shared storage
|
|
441
|
+
trie sync pull # Pull shared updates (auto-migrates legacy)
|
|
442
|
+
trie sync push # Push local changes
|
|
443
|
+
trie sync status # Show sync state, conflicts
|
|
444
|
+
trie sync migrate # Manually migrate legacy v1 ledger
|
|
445
|
+
trie sync hooks --install # Install pre-push/post-merge auto-sync hooks
|
|
446
|
+
|
|
447
|
+
# Ledger commands
|
|
448
|
+
trie ledger verify # Validate chain integrity
|
|
449
|
+
trie ledger history # Show chain with author attribution
|
|
450
|
+
trie ledger stats # Block counts, entries, severity breakdown
|
|
451
|
+
trie ledger diff # Compare local vs shared
|
|
452
|
+
trie ledger compress # Manually archive old blocks
|
|
453
|
+
trie ledger storage # Detailed storage usage stats
|
|
454
|
+
```
|
|
455
|
+
|
|
335
456
|
### Integration with AI Coding Tools
|
|
336
457
|
|
|
337
458
|
Trie provides MCP (Model Context Protocol) tools for seamless integration with Claude, Cursor, and other AI assistants:
|
|
@@ -340,9 +461,16 @@ Trie provides MCP (Model Context Protocol) tools for seamless integration with C
|
|
|
340
461
|
trie_tell - Report incidents and extract structured signals
|
|
341
462
|
trie_check - Quick risk assessment
|
|
342
463
|
trie_memory - Search incident history
|
|
343
|
-
trie_fix - Apply suggested fixes
|
|
464
|
+
trie_fix - Apply suggested fixes (use action:route to see triage plan)
|
|
465
|
+
trie_cloud_fix - Dispatch to Cursor cloud agent for verified fixes
|
|
466
|
+
|
|
467
|
+
**Integration Tools:**
|
|
468
|
+
trie_linear_sync - Sync active Linear tickets
|
|
469
|
+
trie_github_sync - Sync open PRs and issues from GitHub
|
|
470
|
+
trie_github_branches - Fetch branches with latest commit info (which branch has latest updates)
|
|
471
|
+
trie_pipeline - Consolidated view of tickets, PRs, issues, coverage gaps
|
|
344
472
|
|
|
345
|
-
**Query Tools (
|
|
473
|
+
**Query Tools (Signal Extraction):**
|
|
346
474
|
trie_get_decisions - Query decisions with filters (tags, time, file)
|
|
347
475
|
trie_get_blockers - Get active blockers only
|
|
348
476
|
trie_get_related_decisions - Find related context
|
|
@@ -433,7 +561,9 @@ For Claude (MCP): Add to your MCP settings:
|
|
|
433
561
|
"args": ["mcp"],
|
|
434
562
|
"env": {
|
|
435
563
|
"ANTHROPIC_API_KEY": "your-api-key-here",
|
|
436
|
-
"LINEAR_API_KEY": "your-key"
|
|
564
|
+
"LINEAR_API_KEY": "your-key",
|
|
565
|
+
"GITHUB_TOKEN": "your-github-token",
|
|
566
|
+
"CURSOR_API_KEY": "your-cursor-key"
|
|
437
567
|
}
|
|
438
568
|
}
|
|
439
569
|
}
|
|
@@ -474,6 +604,23 @@ trie goal list # View progress
|
|
|
474
604
|
trie linear sync # Sync Linear tickets for intent context
|
|
475
605
|
```
|
|
476
606
|
|
|
607
|
+
### Ledger & Sync
|
|
608
|
+
|
|
609
|
+
```bash
|
|
610
|
+
trie ledger verify # Verify chain integrity
|
|
611
|
+
trie ledger history # Show blocks with author attribution
|
|
612
|
+
trie ledger stats # Block counts, entries, severity
|
|
613
|
+
trie ledger diff # Compare local vs shared ledger
|
|
614
|
+
trie ledger compress # Archive old blocks
|
|
615
|
+
trie ledger storage # Storage usage stats
|
|
616
|
+
trie sync init # Initialize shared ledger
|
|
617
|
+
trie sync pull # Pull from shared storage
|
|
618
|
+
trie sync push # Push local blocks to shared
|
|
619
|
+
trie sync status # Show sync state and conflicts
|
|
620
|
+
trie sync migrate # Migrate legacy v1 ledger
|
|
621
|
+
trie sync hooks --install # Install auto-sync git hooks
|
|
622
|
+
```
|
|
623
|
+
|
|
477
624
|
### Feedback & Training
|
|
478
625
|
|
|
479
626
|
```bash
|
|
@@ -635,7 +782,7 @@ What happens at the 10,000 issue cap: Trie will deduplicate new repeats, compact
|
|
|
635
782
|
|
|
636
783
|
**Hooks not working**: Reinstall with `trie init`. Make sure you have write permissions to .git/hooks/.
|
|
637
784
|
|
|
638
|
-
**Goals showing but not detecting violations**: This happens when goals appear in the UI but aren't active in
|
|
785
|
+
**Goals showing but not detecting violations**: This happens when goals appear in the UI but aren't active in project state. The Goals view will show a yellow warning box. To fix:
|
|
639
786
|
```bash
|
|
640
787
|
# Quick fix - activate a specific goal
|
|
641
788
|
node fix-goals.js "NO EMOJIS"
|
|
@@ -644,8 +791,6 @@ node fix-goals.js "NO EMOJIS"
|
|
|
644
791
|
trie goal add "NO EMOJIS"
|
|
645
792
|
trie goal list
|
|
646
793
|
```
|
|
647
|
-
See [Goal Detection Fix](./docs/GOAL_DETECTION_FIX.md) for details.
|
|
648
|
-
|
|
649
794
|
### Getting Help
|
|
650
795
|
- Issues: [Report bugs and request features](https://x.com/louiskishfy)
|
|
651
796
|
|
|
@@ -10,8 +10,8 @@ import {
|
|
|
10
10
|
shouldAutoFix,
|
|
11
11
|
shouldBlockPush,
|
|
12
12
|
trackIssueOccurrence
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-5KJ4UJOY.js";
|
|
14
|
+
import "./chunk-SH7H3WRU.js";
|
|
15
15
|
import "./chunk-APMV77PU.js";
|
|
16
16
|
import "./chunk-DGUM43GV.js";
|
|
17
17
|
export {
|
|
@@ -27,4 +27,4 @@ export {
|
|
|
27
27
|
shouldBlockPush,
|
|
28
28
|
trackIssueOccurrence
|
|
29
29
|
};
|
|
30
|
-
//# sourceMappingURL=autonomy-config-
|
|
30
|
+
//# sourceMappingURL=autonomy-config-ZCOSTMPD.js.map
|
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
ChatStore,
|
|
3
3
|
clearChatStores,
|
|
4
4
|
getChatStore
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-23RJT5WT.js";
|
|
6
6
|
import "./chunk-43X6JBEM.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-SH7H3WRU.js";
|
|
8
8
|
import "./chunk-APMV77PU.js";
|
|
9
9
|
import "./chunk-DGUM43GV.js";
|
|
10
10
|
export {
|
|
@@ -12,4 +12,4 @@ export {
|
|
|
12
12
|
clearChatStores,
|
|
13
13
|
getChatStore
|
|
14
14
|
};
|
|
15
|
-
//# sourceMappingURL=chat-store-
|
|
15
|
+
//# sourceMappingURL=chat-store-OJLJCJFI.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-43X6JBEM.js";
|
|
4
4
|
import {
|
|
5
5
|
getTrieDirectory
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-SH7H3WRU.js";
|
|
7
7
|
|
|
8
8
|
// src/cli/dashboard/chat-store.ts
|
|
9
9
|
import { mkdir, readFile, unlink } from "fs/promises";
|
|
@@ -20,11 +20,12 @@ var ChatMessageSchema = z.object({
|
|
|
20
20
|
input: z.record(z.any())
|
|
21
21
|
})).optional(),
|
|
22
22
|
pendingFix: z.object({
|
|
23
|
-
id: z.string(),
|
|
23
|
+
id: z.string().optional(),
|
|
24
24
|
file: z.string(),
|
|
25
25
|
goal: z.string(),
|
|
26
26
|
violation: z.string(),
|
|
27
|
-
suggestedFix: z.string().optional()
|
|
27
|
+
suggestedFix: z.string().optional(),
|
|
28
|
+
directory: z.string().optional()
|
|
28
29
|
}).optional()
|
|
29
30
|
});
|
|
30
31
|
var ChatSessionSchema = z.object({
|
|
@@ -344,4 +345,4 @@ export {
|
|
|
344
345
|
getChatStore,
|
|
345
346
|
clearChatStores
|
|
346
347
|
};
|
|
347
|
-
//# sourceMappingURL=chunk-
|
|
348
|
+
//# sourceMappingURL=chunk-23RJT5WT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/dashboard/chat-store.ts"],"sourcesContent":["/**\n * Chat Store - Persistent storage for chat history\n * \n * Features:\n * - Save and load chat sessions\n * - List all chat sessions\n * - Archive management (rename, delete, export)\n * - Atomic writes with backup rotation\n * - Zod validation for data integrity\n * \n * Persists to: .trie/memory/chats/\n */\n\nimport { mkdir, readFile, unlink } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { getTrieDirectory } from '../../utils/workspace.js';\nimport { z } from 'zod';\nimport { atomicWriteJSON } from '../../utils/atomic-write.js';\nimport type { ChatMessage } from './types.js';\n\n// ============================================================================\n// Schemas\n// ============================================================================\n\nconst ChatMessageSchema = z.object({\n role: z.enum(['user', 'assistant']),\n content: z.string(),\n timestamp: z.number(),\n toolCalls: z.array(z.object({\n id: z.string(),\n name: z.string(),\n input: z.record(z.any()),\n })).optional(),\n pendingFix: z.object({\n id: z.string().optional(),\n file: z.string(),\n goal: z.string(),\n violation: z.string(),\n suggestedFix: z.string().optional(),\n directory: z.string().optional(),\n }).optional(),\n});\n\nconst ChatSessionSchema = z.object({\n id: z.string(),\n title: z.string(),\n messages: z.array(ChatMessageSchema),\n createdAt: z.number(),\n updatedAt: z.number(),\n archived: z.boolean(),\n});\n\nexport type ChatSession = z.infer<typeof ChatSessionSchema>;\n\nconst ChatStoreIndexSchema = z.object({\n version: z.literal(1),\n sessions: z.array(z.object({\n id: z.string(),\n title: z.string(),\n createdAt: z.number(),\n updatedAt: z.number(),\n archived: z.boolean(),\n messageCount: z.number(),\n })),\n lastUpdated: z.string(),\n});\n\ntype ChatStoreIndex = z.infer<typeof ChatStoreIndexSchema>;\n\n// ============================================================================\n// ChatStore Class\n// ============================================================================\n\nexport class ChatStore {\n private projectPath: string;\n private index: ChatStoreIndex | null = null;\n \n constructor(projectPath: string) {\n this.projectPath = projectPath;\n }\n \n /**\n * Get the chats directory path\n */\n private getChatsDir(): string {\n return join(getTrieDirectory(this.projectPath), 'memory', 'chats');\n }\n \n /**\n * Get the index file path\n */\n private getIndexPath(): string {\n return join(this.getChatsDir(), 'index.json');\n }\n \n /**\n * Get the path for a specific session file\n */\n private getSessionPath(sessionId: string): string {\n return join(this.getChatsDir(), `${sessionId}.json`);\n }\n \n /**\n * Load the index file\n */\n private async loadIndex(): Promise<ChatStoreIndex> {\n if (this.index) {\n return this.index;\n }\n \n const indexPath = this.getIndexPath();\n \n if (existsSync(indexPath)) {\n try {\n const content = await readFile(indexPath, 'utf-8');\n const parsed = JSON.parse(content);\n const result = ChatStoreIndexSchema.safeParse(parsed);\n \n if (result.success) {\n this.index = result.data;\n return this.index;\n }\n } catch (error) {\n console.error('Failed to load chat index:', error);\n }\n }\n \n // Create empty index\n this.index = {\n version: 1,\n sessions: [],\n lastUpdated: new Date().toISOString(),\n };\n \n return this.index;\n }\n \n /**\n * Save the index file\n */\n private async saveIndex(): Promise<void> {\n if (!this.index) return;\n \n const indexPath = this.getIndexPath();\n const chatsDir = this.getChatsDir();\n \n // Ensure directory exists\n await mkdir(chatsDir, { recursive: true });\n \n // Update timestamp\n this.index.lastUpdated = new Date().toISOString();\n \n // Atomic write\n await atomicWriteJSON(indexPath, this.index);\n }\n \n /**\n * Generate a unique session ID\n */\n private generateSessionId(): string {\n return `chat-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n }\n \n /**\n * Generate a default title from the first user message\n */\n private generateTitle(messages: ChatMessage[]): string {\n const firstUser = messages.find(m => m.role === 'user');\n if (firstUser) {\n const text = firstUser.content.trim();\n const maxLen = 50;\n if (text.length > maxLen) {\n return text.slice(0, maxLen) + '...';\n }\n return text;\n }\n return 'New Chat';\n }\n \n /**\n * Save a chat session\n */\n async saveSession(messages: ChatMessage[], sessionId?: string, title?: string): Promise<string> {\n await this.loadIndex();\n \n const id = sessionId || this.generateSessionId();\n const now = Date.now();\n \n // Load existing session if updating\n let createdAt = now;\n if (sessionId) {\n const existing = this.index!.sessions.find(s => s.id === sessionId);\n if (existing) {\n createdAt = existing.createdAt;\n }\n }\n \n const session: ChatSession = {\n id,\n title: title || this.generateTitle(messages),\n messages,\n createdAt,\n updatedAt: now,\n archived: false,\n };\n \n // Validate\n const result = ChatSessionSchema.safeParse(session);\n if (!result.success) {\n throw new Error(`Invalid chat session: ${result.error.message}`);\n }\n \n // Save session file\n const sessionPath = this.getSessionPath(id);\n await mkdir(this.getChatsDir(), { recursive: true });\n await atomicWriteJSON(sessionPath, session);\n \n // Update index\n const existingIndex = this.index!.sessions.findIndex(s => s.id === id);\n const indexEntry = {\n id,\n title: session.title,\n createdAt: session.createdAt,\n updatedAt: session.updatedAt,\n archived: session.archived,\n messageCount: messages.length,\n };\n \n if (existingIndex >= 0) {\n this.index!.sessions[existingIndex] = indexEntry;\n } else {\n this.index!.sessions.unshift(indexEntry);\n }\n \n await this.saveIndex();\n \n return id;\n }\n \n /**\n * Load a chat session\n */\n async loadSession(sessionId: string): Promise<ChatSession | null> {\n const sessionPath = this.getSessionPath(sessionId);\n \n if (!existsSync(sessionPath)) {\n return null;\n }\n \n try {\n const content = await readFile(sessionPath, 'utf-8');\n const parsed = JSON.parse(content);\n const result = ChatSessionSchema.safeParse(parsed);\n \n if (result.success) {\n return result.data;\n }\n \n console.error('Invalid chat session:', result.error.message);\n return null;\n } catch (error) {\n console.error('Failed to load chat session:', error);\n return null;\n }\n }\n \n /**\n * List all chat sessions\n */\n async listSessions(includeArchived: boolean = false): Promise<ChatStoreIndex['sessions']> {\n await this.loadIndex();\n \n let sessions = this.index!.sessions;\n \n if (!includeArchived) {\n sessions = sessions.filter(s => !s.archived);\n }\n \n // Sort by most recent first\n return sessions.sort((a, b) => b.updatedAt - a.updatedAt);\n }\n \n /**\n * Delete a chat session\n */\n async deleteSession(sessionId: string): Promise<boolean> {\n await this.loadIndex();\n \n const sessionPath = this.getSessionPath(sessionId);\n \n if (!existsSync(sessionPath)) {\n return false;\n }\n \n try {\n await unlink(sessionPath);\n \n // Remove from index\n this.index!.sessions = this.index!.sessions.filter(s => s.id !== sessionId);\n await this.saveIndex();\n \n return true;\n } catch (error) {\n console.error('Failed to delete chat session:', error);\n return false;\n }\n }\n \n /**\n * Rename a chat session\n */\n async renameSession(sessionId: string, newTitle: string): Promise<boolean> {\n await this.loadIndex();\n \n const session = await this.loadSession(sessionId);\n if (!session) {\n return false;\n }\n \n session.title = newTitle;\n session.updatedAt = Date.now();\n \n // Save updated session\n const sessionPath = this.getSessionPath(sessionId);\n await atomicWriteJSON(sessionPath, session);\n \n // Update index\n const indexEntry = this.index!.sessions.find(s => s.id === sessionId);\n if (indexEntry) {\n indexEntry.title = newTitle;\n indexEntry.updatedAt = session.updatedAt;\n await this.saveIndex();\n }\n \n return true;\n }\n \n /**\n * Archive a chat session\n */\n async archiveSession(sessionId: string): Promise<boolean> {\n await this.loadIndex();\n \n const session = await this.loadSession(sessionId);\n if (!session) {\n return false;\n }\n \n session.archived = true;\n session.updatedAt = Date.now();\n \n // Save updated session\n const sessionPath = this.getSessionPath(sessionId);\n await atomicWriteJSON(sessionPath, session);\n \n // Update index\n const indexEntry = this.index!.sessions.find(s => s.id === sessionId);\n if (indexEntry) {\n indexEntry.archived = true;\n indexEntry.updatedAt = session.updatedAt;\n await this.saveIndex();\n }\n \n return true;\n }\n \n /**\n * Unarchive a chat session\n */\n async unarchiveSession(sessionId: string): Promise<boolean> {\n await this.loadIndex();\n \n const session = await this.loadSession(sessionId);\n if (!session) {\n return false;\n }\n \n session.archived = false;\n session.updatedAt = Date.now();\n \n // Save updated session\n const sessionPath = this.getSessionPath(sessionId);\n await atomicWriteJSON(sessionPath, session);\n \n // Update index\n const indexEntry = this.index!.sessions.find(s => s.id === sessionId);\n if (indexEntry) {\n indexEntry.archived = false;\n indexEntry.updatedAt = session.updatedAt;\n await this.saveIndex();\n }\n \n return true;\n }\n \n /**\n * Export a chat session as JSON\n */\n async exportSession(sessionId: string): Promise<string | null> {\n const session = await this.loadSession(sessionId);\n if (!session) {\n return null;\n }\n \n return JSON.stringify(session, null, 2);\n }\n \n /**\n * Get statistics about chat sessions\n */\n async getStats(): Promise<{\n total: number;\n active: number;\n archived: number;\n totalMessages: number;\n }> {\n await this.loadIndex();\n \n const total = this.index!.sessions.length;\n const archived = this.index!.sessions.filter(s => s.archived).length;\n const active = total - archived;\n const totalMessages = this.index!.sessions.reduce((sum, s) => sum + s.messageCount, 0);\n \n return { total, active, archived, totalMessages };\n }\n \n /**\n * Prune old sessions (older than N days)\n */\n async pruneOldSessions(daysToKeep: number = 90): Promise<number> {\n await this.loadIndex();\n \n const cutoff = Date.now() - (daysToKeep * 24 * 60 * 60 * 1000);\n const toDelete = this.index!.sessions.filter(s => s.updatedAt < cutoff);\n \n for (const session of toDelete) {\n await this.deleteSession(session.id);\n }\n \n return toDelete.length;\n }\n}\n\n// ============================================================================\n// Singleton Management\n// ============================================================================\n\nconst chatStores: Map<string, ChatStore> = new Map();\n\n/**\n * Get the ChatStore for a project (singleton per project)\n */\nexport function getChatStore(projectPath: string): ChatStore {\n let store = chatStores.get(projectPath);\n if (!store) {\n store = new ChatStore(projectPath);\n chatStores.set(projectPath, store);\n }\n return store;\n}\n\n/**\n * Clear all ChatStore instances (for testing)\n */\nexport function clearChatStores(): void {\n chatStores.clear();\n}\n"],"mappings":"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","names":[]}
|
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
} from "./chunk-43X6JBEM.js";
|
|
8
8
|
import {
|
|
9
9
|
getTrieDirectory
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-SH7H3WRU.js";
|
|
11
11
|
|
|
12
|
-
// src/
|
|
12
|
+
// src/agent/insight-store.ts
|
|
13
13
|
import { mkdir, readFile } from "fs/promises";
|
|
14
14
|
import { existsSync } from "fs";
|
|
15
15
|
import { join } from "path";
|
|
@@ -51,7 +51,6 @@ var InsightSchema = z.object({
|
|
|
51
51
|
category: z.enum(["security", "quality", "performance", "pattern", "progress", "general"]),
|
|
52
52
|
details: InsightDetailsSchema.optional()
|
|
53
53
|
});
|
|
54
|
-
var GuardianInsightSchema = InsightSchema;
|
|
55
54
|
var InsightStoreDataSchema = z.object({
|
|
56
55
|
version: z.literal(1),
|
|
57
56
|
insights: z.array(InsightSchema),
|
|
@@ -433,10 +432,9 @@ function clearInsightStores() {
|
|
|
433
432
|
export {
|
|
434
433
|
InsightDetailsSchema,
|
|
435
434
|
InsightSchema,
|
|
436
|
-
GuardianInsightSchema,
|
|
437
435
|
InsightStoreDataSchema,
|
|
438
436
|
InsightStore,
|
|
439
437
|
getInsightStore,
|
|
440
438
|
clearInsightStores
|
|
441
439
|
};
|
|
442
|
-
//# sourceMappingURL=chunk-
|
|
440
|
+
//# sourceMappingURL=chunk-3MUCUZ46.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/agent/insight-store.ts"],"sourcesContent":["/**\n * Insight Store - Persistent storage for insights\n * \n * Persists to: .trie/memory/insights.json\n * \n * Features:\n * - Insight persistence across restarts\n * - Cooldown state persistence (prevents duplicate insights)\n * - Dismissed insight tracking\n * - Atomic writes with backup rotation\n * - Zod validation for data integrity\n */\n\nimport { mkdir, readFile } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { getTrieDirectory } from '../utils/workspace.js';\nimport { z } from 'zod';\nimport { atomicWriteJSON } from '../utils/atomic-write.js';\nimport { BackupManager } from '../utils/backup-manager.js';\nimport { safeParseAndValidate } from '../memory/validation.js';\n\n// ============================================================================\n// Schemas\n// ============================================================================\n\n/**\n * Schema for insight details\n */\nexport const InsightDetailsSchema = z.object({\n affectedFiles: z.array(z.string()).optional(),\n issueBreakdown: z.record(z.string(), z.number()).optional(),\n examples: z.array(z.string()).optional(),\n trend: z.enum(['improving', 'stable', 'worsening']).optional(),\n comparison: z.string().optional(),\n resolvedCount: z.number().optional(),\n resolvedIssues: z.array(z.object({\n file: z.string(),\n line: z.number().optional(),\n issue: z.string(),\n agent: z.string(),\n resolvedAt: z.string().optional(),\n })).optional(),\n summary: z.string().optional(),\n // Hypothesis-related fields\n hypothesis: z.string().optional(),\n testCriteria: z.string().optional(),\n confidence: z.number().optional(),\n // Pattern-related fields\n patternsCount: z.number().optional(),\n topPattern: z.string().optional(),\n});\n\n/**\n * Schema for an insight\n */\nexport const InsightSchema = z.object({\n id: z.string(),\n type: z.enum(['observation', 'warning', 'suggestion', 'celebration', 'question']),\n message: z.string(),\n context: z.string().optional(),\n suggestedAction: z.string().optional(),\n actionCommand: z.string().optional(),\n relatedIssues: z.array(z.string()),\n priority: z.number().min(1).max(10),\n timestamp: z.number(),\n dismissed: z.boolean(),\n category: z.enum(['security', 'quality', 'performance', 'pattern', 'progress', 'general']),\n details: InsightDetailsSchema.optional(),\n});\n\nexport type Insight = z.infer<typeof InsightSchema>;\n\n/**\n * Schema for the entire insight store file\n */\nexport const InsightStoreDataSchema = z.object({\n version: z.literal(1),\n insights: z.array(InsightSchema),\n cooldowns: z.record(z.string(), z.number()), // insightKey -> timestamp\n dismissedIds: z.array(z.string()), // Track dismissed insight IDs permanently\n lastUpdated: z.string(),\n});\n\nexport type InsightStoreData = z.infer<typeof InsightStoreDataSchema>;\n\n// ============================================================================\n// InsightStore Class\n// ============================================================================\n\n/**\n * Persistent store for insights\n * \n * Usage:\n * ```typescript\n * const store = new InsightStore(projectPath);\n * await store.load();\n * \n * await store.addInsight(insight);\n * const active = store.getActiveInsights();\n * await store.dismissInsight(insightId);\n * ```\n */\nexport class InsightStore {\n private projectPath: string;\n private data: InsightStoreData;\n private loaded: boolean = false;\n private dirty: boolean = false;\n \n // Default cooldown periods (in ms)\n static readonly COOLDOWNS: Record<string, number> = {\n 'pre-push-warning': 60000, // 1 min between pre-push warnings\n 'security-warning': 30000, // 30s between security warnings\n 'new-issues': 30000, // 30s between new issue observations\n 'celebration': 60000, // 1 min between celebrations\n 'pattern-suggestion': 120000, // 2 min between pattern suggestions\n 'accessibility-visual-qa': 300000, // 5 min between visual QA suggestions\n 'goal-suggestion': 300000, // 5 min between goal suggestions\n 'risk-prediction': 180000, // 3 min between risk predictions\n 'hypothesis-update': 600000, // 10 min between hypothesis updates\n 'auto-escalation': 300000, // 5 min between auto-escalations\n };\n \n constructor(projectPath: string) {\n this.projectPath = projectPath;\n this.data = this.createEmptyData();\n }\n \n /**\n * Get the storage file path\n */\n private getStorePath(): string {\n return join(getTrieDirectory(this.projectPath), 'memory', 'insights.json');\n }\n \n /**\n * Create empty data structure\n */\n private createEmptyData(): InsightStoreData {\n return {\n version: 1,\n insights: [],\n cooldowns: {},\n dismissedIds: [],\n lastUpdated: new Date().toISOString(),\n };\n }\n \n /**\n * Load insights from disk\n * \n * If the file is corrupted, attempts recovery from backup.\n * Returns empty data if no valid file/backup exists.\n */\n async load(): Promise<InsightStoreData> {\n if (this.loaded) {\n return this.data;\n }\n \n const storePath = this.getStorePath();\n \n try {\n if (existsSync(storePath)) {\n const content = await readFile(storePath, 'utf-8');\n const result = safeParseAndValidate(content, InsightStoreDataSchema);\n \n if (result.success) {\n this.data = result.data;\n this.loaded = true;\n // Deduplicate any existing duplicate insights\n this.deduplicateInsights();\n return this.data;\n }\n \n // Validation failed - attempt recovery from backup\n console.error(` Insight store corrupted: ${result.error}`);\n const backupManager = new BackupManager(storePath);\n \n if (await backupManager.recoverFromBackup()) {\n console.error(' Recovered from backup');\n const recovered = await readFile(storePath, 'utf-8');\n const recoveredResult = safeParseAndValidate(recovered, InsightStoreDataSchema);\n if (recoveredResult.success) {\n this.data = recoveredResult.data;\n this.loaded = true;\n // Deduplicate any existing duplicate insights\n this.deduplicateInsights();\n return this.data;\n }\n }\n \n console.error(' No valid backup found, starting fresh');\n }\n } catch (error) {\n // File doesn't exist or recovery failed - start fresh\n console.error(` Could not load insight store: ${error}`);\n }\n \n this.data = this.createEmptyData();\n this.loaded = true;\n return this.data;\n }\n \n /**\n * Deduplicate existing insights on load\n * Keeps the most recent instance of each unique insight\n */\n private deduplicateInsights(): void {\n const seen = new Map<string, number>(); // contentKey -> index of first occurrence\n const toRemove: number[] = [];\n \n // Process from newest to oldest (insights are sorted by recency)\n for (let i = 0; i < this.data.insights.length; i++) {\n const insight = this.data.insights[i];\n if (!insight) continue;\n \n const contentKey = this.getContentKey(insight);\n \n if (seen.has(contentKey)) {\n // This is a duplicate - mark for removal\n toRemove.push(i);\n } else {\n seen.set(contentKey, i);\n }\n }\n \n // Remove duplicates (reverse order to preserve indices)\n if (toRemove.length > 0) {\n for (let i = toRemove.length - 1; i >= 0; i--) {\n const idx = toRemove[i];\n if (idx !== undefined) {\n this.data.insights.splice(idx, 1);\n }\n }\n this.dirty = true;\n }\n }\n \n /**\n * Save insights to disk\n * \n * Creates backup before writing, uses atomic write.\n */\n async save(): Promise<void> {\n if (!this.dirty && this.loaded) {\n return; // No changes to save\n }\n \n const storePath = this.getStorePath();\n const memoryDir = join(getTrieDirectory(this.projectPath), 'memory');\n \n // Ensure directory exists\n await mkdir(memoryDir, { recursive: true });\n \n // Create backup before writing\n const backupManager = new BackupManager(storePath);\n await backupManager.createBackup();\n \n // Update timestamp\n this.data.lastUpdated = new Date().toISOString();\n \n // Atomic write\n await atomicWriteJSON(storePath, this.data);\n \n this.dirty = false;\n }\n \n /**\n * Generate a content-based key for deduplication\n * Insights with the same content key are considered duplicates\n */\n private getContentKey(insight: Insight): string {\n // Normalize the message by removing specific numbers/counts that might vary slightly\n // e.g., \"Found 30 security issues\" and \"Found 31 security issues\" are the same insight\n const normalizedMessage = insight.message\n .replace(/\\d+/g, 'N') // Replace all numbers with N\n .toLowerCase()\n .trim();\n \n return `${insight.type}:${insight.category}:${normalizedMessage}`;\n }\n \n /**\n * Add an insight to the store\n * \n * Checks for duplicates using both insight ID and content similarity.\n * If a similar insight already exists (same type, category, and normalized message),\n * updates its timestamp instead of creating a duplicate.\n * Respects cooldowns to prevent insight spam.\n */\n async addInsight(insight: Insight): Promise<boolean> {\n await this.load();\n \n // Check if already exists by ID\n if (this.data.insights.some(i => i.id === insight.id)) {\n return false;\n }\n \n // Check if ID was previously dismissed (don't re-add)\n if (this.data.dismissedIds.includes(insight.id)) {\n return false;\n }\n \n // Check for content-based duplicates (same type, category, similar message)\n const contentKey = this.getContentKey(insight);\n const existingIndex = this.data.insights.findIndex(i => \n !i.dismissed && this.getContentKey(i) === contentKey\n );\n \n if (existingIndex >= 0) {\n // Update existing insight instead of adding duplicate\n const existing = this.data.insights[existingIndex];\n if (existing) {\n // Update with new data but keep the original ID\n existing.timestamp = insight.timestamp;\n existing.message = insight.message; // Update with current counts\n existing.details = insight.details; // Update details\n existing.relatedIssues = insight.relatedIssues;\n existing.suggestedAction = insight.suggestedAction;\n \n // Move to front of list\n this.data.insights.splice(existingIndex, 1);\n this.data.insights.unshift(existing);\n \n this.dirty = true;\n await this.save();\n }\n return false; // Return false to indicate no new insight was created\n }\n \n // Add to front of list\n this.data.insights.unshift(insight);\n \n // Keep only last 100 insights\n if (this.data.insights.length > 100) {\n this.data.insights = this.data.insights.slice(0, 100);\n }\n \n this.dirty = true;\n await this.save();\n \n return true;\n }\n \n /**\n * Check if a cooldown has expired for an insight type\n */\n canCreateInsight(insightKey: string): boolean {\n const lastTime = this.data.cooldowns[insightKey];\n const cooldown = InsightStore.COOLDOWNS[insightKey] || 30000;\n \n if (!lastTime) return true;\n return Date.now() - lastTime > cooldown;\n }\n \n /**\n * Mark that an insight type was created (set cooldown)\n */\n async markInsightCreated(insightKey: string): Promise<void> {\n await this.load();\n this.data.cooldowns[insightKey] = Date.now();\n this.dirty = true;\n await this.save();\n }\n \n /**\n * Get active (non-dismissed) insights\n * \n * Returns insights sorted by priority (highest first),\n * limited to the specified count.\n */\n getActiveInsights(limit: number = 5): Insight[] {\n return this.data.insights\n .filter(i => !i.dismissed)\n .sort((a, b) => b.priority - a.priority)\n .slice(0, limit);\n }\n \n /**\n * Get all insights (including dismissed)\n */\n getAllInsights(): Insight[] {\n return [...this.data.insights];\n }\n \n /**\n * Dismiss an insight by ID\n */\n async dismissInsight(insightId: string): Promise<boolean> {\n await this.load();\n \n const insight = this.data.insights.find(i => i.id === insightId);\n if (!insight) {\n return false;\n }\n \n insight.dismissed = true;\n \n // Track permanently dismissed IDs\n if (!this.data.dismissedIds.includes(insightId)) {\n this.data.dismissedIds.push(insightId);\n \n // Keep only last 500 dismissed IDs\n if (this.data.dismissedIds.length > 500) {\n this.data.dismissedIds = this.data.dismissedIds.slice(-500);\n }\n }\n \n this.dirty = true;\n await this.save();\n \n return true;\n }\n \n /**\n * Remove an insight entirely\n */\n async removeInsight(insightId: string): Promise<boolean> {\n await this.load();\n \n const index = this.data.insights.findIndex(i => i.id === insightId);\n if (index === -1) {\n return false;\n }\n \n this.data.insights.splice(index, 1);\n this.dirty = true;\n await this.save();\n \n return true;\n }\n \n /**\n * Clear all cooldowns\n */\n async clearCooldowns(): Promise<void> {\n await this.load();\n this.data.cooldowns = {};\n this.dirty = true;\n await this.save();\n }\n \n /**\n * Get insight by ID\n */\n getInsight(insightId: string): Insight | undefined {\n return this.data.insights.find(i => i.id === insightId);\n }\n \n /**\n * Update an existing insight\n */\n async updateInsight(insightId: string, updates: Partial<Insight>): Promise<boolean> {\n await this.load();\n \n const insight = this.data.insights.find(i => i.id === insightId);\n if (!insight) {\n return false;\n }\n \n Object.assign(insight, updates);\n this.dirty = true;\n await this.save();\n \n return true;\n }\n \n /**\n * Get insights by category\n */\n getInsightsByCategory(category: Insight['category']): Insight[] {\n return this.data.insights.filter(i => i.category === category && !i.dismissed);\n }\n \n /**\n * Get insights by type\n */\n getInsightsByType(type: Insight['type']): Insight[] {\n return this.data.insights.filter(i => i.type === type && !i.dismissed);\n }\n \n /**\n * Get insights from the last N hours\n */\n getRecentInsights(hours: number = 24): Insight[] {\n const cutoff = Date.now() - (hours * 60 * 60 * 1000);\n return this.data.insights.filter(i => i.timestamp >= cutoff);\n }\n \n /**\n * Get statistics about insights\n */\n getStats(): {\n total: number;\n active: number;\n dismissed: number;\n byCategory: Record<string, number>;\n byType: Record<string, number>;\n } {\n const stats = {\n total: this.data.insights.length,\n active: 0,\n dismissed: 0,\n byCategory: {} as Record<string, number>,\n byType: {} as Record<string, number>,\n };\n \n for (const insight of this.data.insights) {\n if (insight.dismissed) {\n stats.dismissed++;\n } else {\n stats.active++;\n }\n \n stats.byCategory[insight.category] = (stats.byCategory[insight.category] || 0) + 1;\n stats.byType[insight.type] = (stats.byType[insight.type] || 0) + 1;\n }\n \n return stats;\n }\n \n /**\n * Prune old insights (older than N days)\n */\n async pruneOldInsights(daysToKeep: number = 30): Promise<number> {\n await this.load();\n \n const cutoff = Date.now() - (daysToKeep * 24 * 60 * 60 * 1000);\n const originalCount = this.data.insights.length;\n \n this.data.insights = this.data.insights.filter(i => i.timestamp >= cutoff);\n \n const pruned = originalCount - this.data.insights.length;\n if (pruned > 0) {\n this.dirty = true;\n await this.save();\n }\n \n return pruned;\n }\n \n /**\n * Check if the store has been loaded\n */\n isLoaded(): boolean {\n return this.loaded;\n }\n \n /**\n * Force reload from disk\n */\n async reload(): Promise<InsightStoreData> {\n this.loaded = false;\n this.dirty = false;\n return this.load();\n }\n}\n\n// ============================================================================\n// Singleton Management\n// ============================================================================\n\nconst insightStores: Map<string, InsightStore> = new Map();\n\n/**\n * Get the InsightStore for a project (singleton per project)\n */\nexport function getInsightStore(projectPath: string): InsightStore {\n let store = insightStores.get(projectPath);\n if (!store) {\n store = new InsightStore(projectPath);\n insightStores.set(projectPath, store);\n }\n return store;\n}\n\n/**\n * Clear all InsightStore instances (for testing)\n */\nexport function clearInsightStores(): void {\n insightStores.clear();\n}\n"],"mappings":"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","names":[]}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-6NLHFIYA.js";
|
|
4
4
|
import {
|
|
5
5
|
getTrieDirectory
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-SH7H3WRU.js";
|
|
7
7
|
|
|
8
8
|
// src/context/incident-index.ts
|
|
9
9
|
import path2 from "path";
|
|
@@ -170,4 +170,4 @@ var IncidentIndex = class _IncidentIndex {
|
|
|
170
170
|
export {
|
|
171
171
|
IncidentIndex
|
|
172
172
|
};
|
|
173
|
-
//# sourceMappingURL=chunk-
|
|
173
|
+
//# sourceMappingURL=chunk-4C67GV3O.js.map
|