@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.
Files changed (110) hide show
  1. package/README.md +188 -43
  2. package/dist/{autonomy-config-QA6ATWLJ.js → autonomy-config-ZCOSTMPD.js} +3 -3
  3. package/dist/{chat-store-HFOOWZYN.js → chat-store-OJLJCJFI.js} +3 -3
  4. package/dist/{chunk-DFPVUMVE.js → chunk-23RJT5WT.js} +5 -4
  5. package/dist/chunk-23RJT5WT.js.map +1 -0
  6. package/dist/{chunk-QNKBXOIQ.js → chunk-3MUCUZ46.js} +3 -5
  7. package/dist/chunk-3MUCUZ46.js.map +1 -0
  8. package/dist/{chunk-WHIQAGB7.js → chunk-4C67GV3O.js} +2 -2
  9. package/dist/{chunk-AXYNWBME.js → chunk-4O2KRHK4.js} +1907 -414
  10. package/dist/chunk-4O2KRHK4.js.map +1 -0
  11. package/dist/{chunk-ZEXMMTIQ.js → chunk-5KJ4UJOY.js} +10 -5
  12. package/dist/chunk-5KJ4UJOY.js.map +1 -0
  13. package/dist/chunk-62POBLFC.js +1925 -0
  14. package/dist/chunk-62POBLFC.js.map +1 -0
  15. package/dist/{chunk-HUR67JXG.js → chunk-75ADWWUF.js} +38 -19
  16. package/dist/chunk-75ADWWUF.js.map +1 -0
  17. package/dist/{chunk-4JQ6W7LW.js → chunk-7OJ6JIPL.js} +40 -608
  18. package/dist/chunk-7OJ6JIPL.js.map +1 -0
  19. package/dist/{chunk-6VIMBFUZ.js → chunk-AF2APASP.js} +58 -20
  20. package/dist/chunk-AF2APASP.js.map +1 -0
  21. package/dist/{chunk-Z4DN527J.js → chunk-FG467PDD.js} +156 -39
  22. package/dist/chunk-FG467PDD.js.map +1 -0
  23. package/dist/{chunk-55CBWOEZ.js → chunk-FH335WL5.js} +10 -2
  24. package/dist/chunk-FH335WL5.js.map +1 -0
  25. package/dist/{chunk-O6OTJI3W.js → chunk-FPEMP54L.js} +22 -16
  26. package/dist/chunk-FPEMP54L.js.map +1 -0
  27. package/dist/{chunk-K6NTRSDF.js → chunk-GXF6JOCN.js} +24 -326
  28. package/dist/chunk-GXF6JOCN.js.map +1 -0
  29. package/dist/chunk-LD7ZEFNY.js +132 -0
  30. package/dist/chunk-LD7ZEFNY.js.map +1 -0
  31. package/dist/{chunk-6EP2VTHC.js → chunk-LT6VUZG2.js} +7 -4
  32. package/dist/chunk-LT6VUZG2.js.map +1 -0
  33. package/dist/chunk-NKHO34UZ.js +467 -0
  34. package/dist/chunk-NKHO34UZ.js.map +1 -0
  35. package/dist/{chunk-QM5VIDFN.js → chunk-OQ4A3RDY.js} +46 -30
  36. package/dist/chunk-OQ4A3RDY.js.map +1 -0
  37. package/dist/{chunk-45Y5TLQZ.js → chunk-SH7H3WRU.js} +3 -6
  38. package/dist/chunk-SH7H3WRU.js.map +1 -0
  39. package/dist/{chunk-G74XEI7K.js → chunk-UOSTOLU7.js} +21 -21
  40. package/dist/chunk-UOSTOLU7.js.map +1 -0
  41. package/dist/{chunk-DPZLABUC.js → chunk-XTTZAQWJ.js} +28 -22
  42. package/dist/chunk-XTTZAQWJ.js.map +1 -0
  43. package/dist/{chunk-A6PWS6ZV.js → chunk-YEIJW6X6.js} +15 -5
  44. package/dist/chunk-YEIJW6X6.js.map +1 -0
  45. package/dist/chunk-YOJGSRZK.js +216 -0
  46. package/dist/chunk-YOJGSRZK.js.map +1 -0
  47. package/dist/cli/create-agent.js +1 -1
  48. package/dist/cli/main.js +636 -99
  49. package/dist/cli/main.js.map +1 -1
  50. package/dist/cli/yolo-daemon.js +21 -19
  51. package/dist/cli/yolo-daemon.js.map +1 -1
  52. package/dist/{client-BZHI675W.js → client-INNE2GGZ.js} +3 -3
  53. package/dist/{codebase-index-CR6Q2HEI.js → codebase-index-5SEOESWM.js} +4 -4
  54. package/dist/fast-analyzer-AYLZB5TW.js +216 -0
  55. package/dist/fast-analyzer-AYLZB5TW.js.map +1 -0
  56. package/dist/github-ingester-J2ZFYXVE.js +11 -0
  57. package/dist/{goal-manager-62IL6WGY.js → goal-manager-ZBWKWEML.js} +6 -6
  58. package/dist/{goal-validator-HPPBSDXD.js → goal-validator-HNXXUCPW.js} +5 -5
  59. package/dist/{graph-PAUZ5EMP.js → graph-J4OGTYCO.js} +3 -3
  60. package/dist/{hypothesis-W37VG6DA.js → hypothesis-JCUMZKTG.js} +6 -6
  61. package/dist/{incident-index-ZCDSJ42L.js → incident-index-BWW2UEY7.js} +3 -3
  62. package/dist/index.js +1168 -137
  63. package/dist/index.js.map +1 -1
  64. package/dist/{insight-store-U3NYTOJE.js → insight-store-A5XXMFD6.js} +3 -5
  65. package/dist/{issue-store-EZMBHOVN.js → issue-store-LZWZIGM7.js} +3 -3
  66. package/dist/linear-ingester-JRDQAIAA.js +11 -0
  67. package/dist/{tiered-storage-QW2G7GSG.js → tiered-storage-VZL7KK64.js} +3 -3
  68. package/dist/tiered-storage-VZL7KK64.js.map +1 -0
  69. package/dist/trie-agent-M6PHM6UD.js +26 -0
  70. package/dist/trie-agent-M6PHM6UD.js.map +1 -0
  71. package/dist/ui/chat.html +260 -67
  72. package/dist/ui/goals.html +246 -3
  73. package/dist/ui/hypotheses.html +248 -5
  74. package/dist/ui/ledger.html +252 -9
  75. package/dist/ui/nudges.html +244 -1
  76. package/package.json +15 -8
  77. package/dist/chunk-45Y5TLQZ.js.map +0 -1
  78. package/dist/chunk-4JQ6W7LW.js.map +0 -1
  79. package/dist/chunk-55CBWOEZ.js.map +0 -1
  80. package/dist/chunk-6EP2VTHC.js.map +0 -1
  81. package/dist/chunk-6VIMBFUZ.js.map +0 -1
  82. package/dist/chunk-A6PWS6ZV.js.map +0 -1
  83. package/dist/chunk-AXYNWBME.js.map +0 -1
  84. package/dist/chunk-DFPVUMVE.js.map +0 -1
  85. package/dist/chunk-DPZLABUC.js.map +0 -1
  86. package/dist/chunk-G74XEI7K.js.map +0 -1
  87. package/dist/chunk-HUR67JXG.js.map +0 -1
  88. package/dist/chunk-K6NTRSDF.js.map +0 -1
  89. package/dist/chunk-O6OTJI3W.js.map +0 -1
  90. package/dist/chunk-QM5VIDFN.js.map +0 -1
  91. package/dist/chunk-QNKBXOIQ.js.map +0 -1
  92. package/dist/chunk-R3WZI6QZ.js +0 -883
  93. package/dist/chunk-R3WZI6QZ.js.map +0 -1
  94. package/dist/chunk-Z4DN527J.js.map +0 -1
  95. package/dist/chunk-ZEXMMTIQ.js.map +0 -1
  96. package/dist/guardian-agent-YKG5XURG.js +0 -30
  97. /package/dist/{autonomy-config-QA6ATWLJ.js.map → autonomy-config-ZCOSTMPD.js.map} +0 -0
  98. /package/dist/{chat-store-HFOOWZYN.js.map → chat-store-OJLJCJFI.js.map} +0 -0
  99. /package/dist/{chunk-WHIQAGB7.js.map → chunk-4C67GV3O.js.map} +0 -0
  100. /package/dist/{client-BZHI675W.js.map → client-INNE2GGZ.js.map} +0 -0
  101. /package/dist/{codebase-index-CR6Q2HEI.js.map → codebase-index-5SEOESWM.js.map} +0 -0
  102. /package/dist/{goal-manager-62IL6WGY.js.map → github-ingester-J2ZFYXVE.js.map} +0 -0
  103. /package/dist/{goal-validator-HPPBSDXD.js.map → goal-manager-ZBWKWEML.js.map} +0 -0
  104. /package/dist/{graph-PAUZ5EMP.js.map → goal-validator-HNXXUCPW.js.map} +0 -0
  105. /package/dist/{guardian-agent-YKG5XURG.js.map → graph-J4OGTYCO.js.map} +0 -0
  106. /package/dist/{hypothesis-W37VG6DA.js.map → hypothesis-JCUMZKTG.js.map} +0 -0
  107. /package/dist/{incident-index-ZCDSJ42L.js.map → incident-index-BWW2UEY7.js.map} +0 -0
  108. /package/dist/{insight-store-U3NYTOJE.js.map → insight-store-A5XXMFD6.js.map} +0 -0
  109. /package/dist/{issue-store-EZMBHOVN.js.map → issue-store-LZWZIGM7.js.map} +0 -0
  110. /package/dist/{tiered-storage-QW2G7GSG.js.map → linear-ingester-JRDQAIAA.js.map} +0 -0
package/README.md CHANGED
@@ -1,30 +1,36 @@
1
- # Trie: Trainable AI Agent for AI-Generated Codebases
1
+ # Trie: Governance for Teams That Ship with AI
2
2
 
3
- **Your autonomous agent that learns from every incident, extracts decisions from every change, and predicts problems before they happen.**
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
  [![Download Workspace](https://img.shields.io/badge/Download-Trie%20Workspace-blue)](https://www.trie.dev) [![Follow on X](https://img.shields.io/badge/Follow-@louiskishfy-1DA1F2?logo=x)](https://x.com/louiskishfy)
6
6
 
7
7
  ## What Trie Does
8
8
 
9
- Trie is an **autonomous, trainable AI agent** that maintains a decision ledger for your codebase:
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
- - **Ledger**: Builds institutional knowledge that travels from Cursor/Claude Code → CLI → CI/CD
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 agent learns from every incident, decision, and fix. When you ship, Trie remembers. When something breaks, Trie learns. Over time, your agent gets better at predicting what will go wrong before it does.
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 agentgets 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 your personal AI agent that maintains multiple codebases without losing context.**
27
+ **Trie is the governance layer for teams where agents and humans ship together.**
22
28
 
23
- Every bug you fix teaches the agent 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 by the agent.
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, **your agent remembers for you**. Instead of losing track of edge cases and tradeoffs as you switch between tools, **your agent maintains system coherence**.
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 is faster development with fewer production fires, because **your agent gets smarter every time something breaks** instead of starting from zero in every conversation.
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
- **Your thinking and planning keep up with code generation. Your decisions persist across tools. Your edge cases don't get forgotten. Your agent handles it all.**
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
- Building apps with AI tools like Cursor and Claude Code is incredibly fast - but maintaining them alone is a nightmare. You fix a bug and forget why it happened. The same issues keep coming back. Your codebase grows faster than your memory of it.
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 real challenge isn't generating codeit's maintaining it. Real software has countless edge cases. Every architectural decision involves tradeoffs. As you switch between Cursor, Claude Code, terminal, and CI/CD, context gets lost. You make a decision in one tool, forget it in another, and repeat the same mistakes.
81
+ The ledger is the answer. Trie keeps a tamper-evident record of decisions, incidents, and tradeoffs so everyonehuman 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
- You shipped an MVP. You've got traction. Maybe even paying customers. Now you're in the maintenance phase—where the hard work happens. Where you handle edge cases, make tradeoffs, and keep the system coherent as it grows. Where you need your thinking and planning to keep pace with rapid code generation.
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
- Trie remembers your decisions across tools, tracks the tradeoffs you've made, and maintains system coherence as your codebase evolves. It solves this by being your persistent memory. It keeps a ledger so it remembers what broke before, learns patterns across your projects, and warns you before you ship risky code. Tools like Cursor Bugbot are great, but just flagging issues isn't going to help you avoid similar patterns in the future. With Trie, you'll find quickly that you end up architecting apps and prompting better.
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
- - Context that travels - Your thinking and planning keep up with code generation across all your tools.
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 Guardian System
118
+ ### The Trie Agent
112
119
 
113
- Trie uses a "Guardian Agent" architecture:
120
+ Trie uses a proactive agent architecture:
114
121
 
115
122
  - Analyzes your code for potential issues based on your incident history.
116
- - Guardian decides what matters based on your history.
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 maintains a Context Graph that tracks decisions, tradeoffs, and architectural choices:
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 .trie/ folder
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, Trie remembers. Your thinking and planning keep up with code generation because every tool shares the same memory.
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
- **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.
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 **query** for what they need:
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
- **Why this matters**: Context management IS the product. Agents get the right information at the right moment, not everything dumped at once.
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
- **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.
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. Maintenance Phase
264
+ ### 4. Governance Phase
254
265
 
255
- This is where Trie shines. As your app grows and you handle edge cases:
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, you make a decision about error handling
259
- # Trie records it in the context graph
269
+ # Working in Cursor, an agent makes a decision about error handling
270
+ # Trie records it in the ledger
260
271
 
261
- # Switch to Claude Code later
262
- # Same context graph, same decisions remembered
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 the hard part that can't be automated by remembering what you decided, why you decided it, and what happened as a result.
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 guardian running while using other terminals. The interactive dashboard will be available when you reattach.
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 (NEW - Signal Extraction):**
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 guardian state. The Goals view will show a yellow warning box. To fix:
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-ZEXMMTIQ.js";
14
- import "./chunk-45Y5TLQZ.js";
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-QA6ATWLJ.js.map
30
+ //# sourceMappingURL=autonomy-config-ZCOSTMPD.js.map
@@ -2,9 +2,9 @@ import {
2
2
  ChatStore,
3
3
  clearChatStores,
4
4
  getChatStore
5
- } from "./chunk-DFPVUMVE.js";
5
+ } from "./chunk-23RJT5WT.js";
6
6
  import "./chunk-43X6JBEM.js";
7
- import "./chunk-45Y5TLQZ.js";
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-HFOOWZYN.js.map
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-45Y5TLQZ.js";
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-DFPVUMVE.js.map
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-45Y5TLQZ.js";
10
+ } from "./chunk-SH7H3WRU.js";
11
11
 
12
- // src/guardian/insight-store.ts
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-QNKBXOIQ.js.map
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-45Y5TLQZ.js";
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-WHIQAGB7.js.map
173
+ //# sourceMappingURL=chunk-4C67GV3O.js.map