@triedotdev/mcp 1.0.149 → 1.0.154
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/LICENSE +21 -0
- package/README.md +150 -36
- package/dist/{autonomy-config-ZCOSTMPD.js → autonomy-config-RKLZW4XL.js} +4 -4
- package/dist/{chat-store-OJLJCJFI.js → chat-store-O3IJ5PMN.js} +4 -4
- package/dist/{chunk-IXO4G4D3.js → chunk-2LAJKFWU.js} +2 -2
- package/dist/{chunk-23RJT5WT.js → chunk-3CYMLM35.js} +2 -2
- package/dist/{chunk-QH77RQB3.js → chunk-4ZAFQEP6.js} +5 -6
- package/dist/chunk-4ZAFQEP6.js.map +1 -0
- package/dist/{chunk-SH7H3WRU.js → chunk-7F2R2ITA.js} +4 -4
- package/dist/{chunk-SH7H3WRU.js.map → chunk-7F2R2ITA.js.map} +1 -1
- package/dist/{chunk-FG467PDD.js → chunk-ALSCZ7WR.js} +2 -2
- package/dist/{chunk-YOJGSRZK.js → chunk-CBAMZERA.js} +2 -2
- package/dist/{chunk-53KUI7RQ.js → chunk-EMJ7RVWB.js} +38 -13
- package/dist/{chunk-53KUI7RQ.js.map → chunk-EMJ7RVWB.js.map} +1 -1
- package/dist/{chunk-NKHO34UZ.js → chunk-FTOF3FHT.js} +3 -3
- package/dist/{chunk-LD7ZEFNY.js → chunk-FXZAABXO.js} +2 -2
- package/dist/{chunk-ZUEAHFSY.js → chunk-HD5H7YSW.js} +313 -61
- package/dist/chunk-HD5H7YSW.js.map +1 -0
- package/dist/{chunk-APMV77PU.js → chunk-JKEEQAG2.js} +1 -1
- package/dist/chunk-JKEEQAG2.js.map +1 -0
- package/dist/{chunk-FH335WL5.js → chunk-JYWGYUKX.js} +2 -2
- package/dist/{chunk-TIMIKBY2.js → chunk-KLMJKM63.js} +2 -2
- package/dist/{chunk-4C67GV3O.js → chunk-KYKADM7P.js} +2 -2
- package/dist/{chunk-CU5VDH6F.js → chunk-L4FODDDB.js} +2 -2
- package/dist/{chunk-ILGMFND2.js → chunk-LFNH3CSN.js} +4 -4
- package/dist/{chunk-GAL7OIYU.js → chunk-LJISDV3A.js} +15 -15
- package/dist/{chunk-72KSLD7A.js → chunk-NVZZUUEU.js} +5 -5
- package/dist/{chunk-7OJ6JIPL.js → chunk-OVSYTWUU.js} +7 -150
- package/dist/chunk-OVSYTWUU.js.map +1 -0
- package/dist/{chunk-B2AHQ2IR.js → chunk-OWSGJUUR.js} +12 -12
- package/dist/{chunk-HYNDXZAU.js → chunk-QAM5X5HM.js} +1535 -90
- package/dist/chunk-QAM5X5HM.js.map +1 -0
- package/dist/{chunk-OTQEFXHU.js → chunk-T7UAH7GE.js} +2 -2
- package/dist/{chunk-FPEMP54L.js → chunk-UL337UDQ.js} +2 -2
- package/dist/{chunk-F4NJ4CBP.js → chunk-WO7CC5FH.js} +2 -2
- package/dist/{chunk-5KJ4UJOY.js → chunk-XD2HKZVB.js} +2 -2
- package/dist/{chunk-V7AY2EJO.js → chunk-YEQXKKZQ.js} +2 -2
- package/dist/{chunk-ZDDE442Q.js → chunk-Z2E7X4WI.js} +8 -8
- package/dist/{chunk-ZDDE442Q.js.map → chunk-Z2E7X4WI.js.map} +1 -1
- package/dist/cli/create-agent.js +9 -41
- package/dist/cli/create-agent.js.map +1 -1
- package/dist/cli/main.js +58 -96
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/yolo-daemon.js +65 -28
- package/dist/cli/yolo-daemon.js.map +1 -1
- package/dist/{client-INNE2GGZ.js → client-ZHOLZTRW.js} +4 -4
- package/dist/{codebase-index-FMIULFZQ.js → codebase-index-N37NDF2A.js} +4 -4
- package/dist/{fast-analyzer-CTT3MCPE.js → fast-analyzer-U6URGNQT.js} +6 -6
- package/dist/github-ingester-AR5A4RAC.js +11 -0
- package/dist/{goal-manager-IGUMDGCA.js → goal-manager-5QDITJKE.js} +8 -8
- package/dist/{goal-validator-DV6DRSGF.js → goal-validator-FU5QWDQT.js} +7 -7
- package/dist/graph-JO7GG65P.js +10 -0
- package/dist/{hypothesis-O72ZLVOW.js → hypothesis-JURDWVDC.js} +8 -8
- package/dist/incident-index-7CAXUNTL.js +11 -0
- package/dist/index.js +136 -1740
- package/dist/index.js.map +1 -1
- package/dist/{insight-store-Q62UGMTF.js → insight-store-AMEP5PPF.js} +4 -4
- package/dist/{issue-store-4FPABLC6.js → issue-store-RM3XLLKG.js} +5 -5
- package/dist/{ledger-43SIVE7X.js → ledger-PLE3C3X4.js} +14 -6
- package/dist/linear-ingester-NHFMKJBZ.js +11 -0
- package/dist/{output-manager-DZO5LGSG.js → output-manager-FX4V7ERT.js} +3 -3
- package/dist/{progress-PQVEM7BR.js → progress-PAYTY7BF.js} +2 -2
- package/dist/tiered-storage-3TUUR3L2.js +12 -0
- package/dist/trie-agent-QHPS4C5Z.js +27 -0
- package/dist/{vibe-code-signatures-ELEWJFGZ.js → vibe-code-signatures-J4GD4JOV.js} +3 -3
- package/dist/{vulnerability-signatures-EIJQX2TS.js → vulnerability-signatures-EIKOHFPK.js} +3 -3
- package/package.json +4 -6
- package/dist/chunk-7OJ6JIPL.js.map +0 -1
- package/dist/chunk-APMV77PU.js.map +0 -1
- package/dist/chunk-G76DYVGX.js +0 -136
- package/dist/chunk-G76DYVGX.js.map +0 -1
- package/dist/chunk-HYNDXZAU.js.map +0 -1
- package/dist/chunk-QH77RQB3.js.map +0 -1
- package/dist/chunk-ZUEAHFSY.js.map +0 -1
- package/dist/comprehension-46F7ZNKL.js +0 -821
- package/dist/comprehension-46F7ZNKL.js.map +0 -1
- package/dist/github-ingester-J2ZFYXVE.js +0 -11
- package/dist/graph-J4OGTYCO.js +0 -10
- package/dist/incident-index-BWW2UEY7.js +0 -11
- package/dist/linear-ingester-JRDQAIAA.js +0 -11
- package/dist/tiered-storage-VZL7KK64.js +0 -12
- package/dist/trie-agent-ET3DAP5Y.js +0 -27
- package/dist/workers/agent-worker.d.ts +0 -2
- package/dist/workers/agent-worker.js +0 -28
- package/dist/workers/agent-worker.js.map +0 -1
- /package/dist/{autonomy-config-ZCOSTMPD.js.map → autonomy-config-RKLZW4XL.js.map} +0 -0
- /package/dist/{chat-store-OJLJCJFI.js.map → chat-store-O3IJ5PMN.js.map} +0 -0
- /package/dist/{chunk-IXO4G4D3.js.map → chunk-2LAJKFWU.js.map} +0 -0
- /package/dist/{chunk-23RJT5WT.js.map → chunk-3CYMLM35.js.map} +0 -0
- /package/dist/{chunk-FG467PDD.js.map → chunk-ALSCZ7WR.js.map} +0 -0
- /package/dist/{chunk-YOJGSRZK.js.map → chunk-CBAMZERA.js.map} +0 -0
- /package/dist/{chunk-NKHO34UZ.js.map → chunk-FTOF3FHT.js.map} +0 -0
- /package/dist/{chunk-LD7ZEFNY.js.map → chunk-FXZAABXO.js.map} +0 -0
- /package/dist/{chunk-FH335WL5.js.map → chunk-JYWGYUKX.js.map} +0 -0
- /package/dist/{chunk-TIMIKBY2.js.map → chunk-KLMJKM63.js.map} +0 -0
- /package/dist/{chunk-4C67GV3O.js.map → chunk-KYKADM7P.js.map} +0 -0
- /package/dist/{chunk-CU5VDH6F.js.map → chunk-L4FODDDB.js.map} +0 -0
- /package/dist/{chunk-ILGMFND2.js.map → chunk-LFNH3CSN.js.map} +0 -0
- /package/dist/{chunk-GAL7OIYU.js.map → chunk-LJISDV3A.js.map} +0 -0
- /package/dist/{chunk-72KSLD7A.js.map → chunk-NVZZUUEU.js.map} +0 -0
- /package/dist/{chunk-B2AHQ2IR.js.map → chunk-OWSGJUUR.js.map} +0 -0
- /package/dist/{chunk-OTQEFXHU.js.map → chunk-T7UAH7GE.js.map} +0 -0
- /package/dist/{chunk-FPEMP54L.js.map → chunk-UL337UDQ.js.map} +0 -0
- /package/dist/{chunk-F4NJ4CBP.js.map → chunk-WO7CC5FH.js.map} +0 -0
- /package/dist/{chunk-5KJ4UJOY.js.map → chunk-XD2HKZVB.js.map} +0 -0
- /package/dist/{chunk-V7AY2EJO.js.map → chunk-YEQXKKZQ.js.map} +0 -0
- /package/dist/{client-INNE2GGZ.js.map → client-ZHOLZTRW.js.map} +0 -0
- /package/dist/{codebase-index-FMIULFZQ.js.map → codebase-index-N37NDF2A.js.map} +0 -0
- /package/dist/{fast-analyzer-CTT3MCPE.js.map → fast-analyzer-U6URGNQT.js.map} +0 -0
- /package/dist/{github-ingester-J2ZFYXVE.js.map → github-ingester-AR5A4RAC.js.map} +0 -0
- /package/dist/{goal-manager-IGUMDGCA.js.map → goal-manager-5QDITJKE.js.map} +0 -0
- /package/dist/{goal-validator-DV6DRSGF.js.map → goal-validator-FU5QWDQT.js.map} +0 -0
- /package/dist/{graph-J4OGTYCO.js.map → graph-JO7GG65P.js.map} +0 -0
- /package/dist/{hypothesis-O72ZLVOW.js.map → hypothesis-JURDWVDC.js.map} +0 -0
- /package/dist/{incident-index-BWW2UEY7.js.map → incident-index-7CAXUNTL.js.map} +0 -0
- /package/dist/{insight-store-Q62UGMTF.js.map → insight-store-AMEP5PPF.js.map} +0 -0
- /package/dist/{issue-store-4FPABLC6.js.map → issue-store-RM3XLLKG.js.map} +0 -0
- /package/dist/{ledger-43SIVE7X.js.map → ledger-PLE3C3X4.js.map} +0 -0
- /package/dist/{linear-ingester-JRDQAIAA.js.map → linear-ingester-NHFMKJBZ.js.map} +0 -0
- /package/dist/{output-manager-DZO5LGSG.js.map → output-manager-FX4V7ERT.js.map} +0 -0
- /package/dist/{progress-PQVEM7BR.js.map → progress-PAYTY7BF.js.map} +0 -0
- /package/dist/{tiered-storage-VZL7KK64.js.map → tiered-storage-3TUUR3L2.js.map} +0 -0
- /package/dist/{trie-agent-ET3DAP5Y.js.map → trie-agent-QHPS4C5Z.js.map} +0 -0
- /package/dist/{vibe-code-signatures-ELEWJFGZ.js.map → vibe-code-signatures-J4GD4JOV.js.map} +0 -0
- /package/dist/{vulnerability-signatures-EIJQX2TS.js.map → vulnerability-signatures-EIKOHFPK.js.map} +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Trie Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,48 +1,59 @@
|
|
|
1
|
-
# Trie: A trainable AI agent with cryptographic governance and portable context
|
|
1
|
+
# Trie: A trainable AI agent with a cryptographic governance ledger and portable context
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
**The ledger that keeps
|
|
4
|
+
**The ledger that keeps agents and humans aligned when shipping together.**
|
|
5
5
|
|
|
6
6
|
[](https://www.trie.dev) [](https://x.com/louiskishfy)
|
|
7
7
|
|
|
8
8
|
## What Trie Does
|
|
9
9
|
|
|
10
|
-
Trie is governance for teams where agents and humans ship together. Every decision, direction change, and tradeoff gets recorded in a
|
|
10
|
+
Trie is governance for teams where agents and humans ship together. Every decision, direction change, and tradeoff gets recorded in a governance ledger that every contributor—human or agent—reads from and writes to, across every tool in the stack.
|
|
11
11
|
|
|
12
12
|
- **Autonomous Operation**: Run `trie watch` and the agent monitors your codebase 24/7
|
|
13
13
|
- **Intelligent Extraction**: Automatically extracts decisions, facts, blockers from every change
|
|
14
|
-
- **
|
|
14
|
+
- **Governance ledger**: Tamper-evident chain with digital signatures—the shared memory that travels from Cursor/Claude Code → CLI → CI/CD
|
|
15
15
|
- **Predictive Intelligence**: `trie gotcha` queries the ledger to predict problems before they happen
|
|
16
16
|
- **Continuous Learning**: Feed it incidents with `trie tell`, teach it patterns with your history
|
|
17
17
|
|
|
18
18
|
The work stays coherent not because someone held it together, but because the ledger did. When any contributor flags a direction change, the ledger surfaces the relevant history instantly. When an agent acts, it does so with full context of what was decided before and why.
|
|
19
19
|
|
|
20
|
-
### The
|
|
20
|
+
### The Agent Coordination Problem
|
|
21
21
|
|
|
22
|
-
**The problem**: When
|
|
22
|
+
**The problem**: When agents and humans ship code together across Cursor, Claude Code, VS Code, and CI/CD, who's accountable for what? An agent makes a decision in one tool; a human modifies it in another; a second agent undoes both. Without a shared record, coordination becomes chaos.
|
|
23
23
|
|
|
24
|
-
**The solution**: Trie
|
|
24
|
+
**The solution**: Trie's governance ledger provides a shared source of truth that both agents and humans can trust. Every decision, every incident, every fix gets recorded with cryptographic signatures proving who (or what) made each change. When an agent queries the ledger, it gets the full context. When you review changes, you see the reasoning. When something breaks, the ledger shows you exactly what led there.
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
Think of it as **double-entry bookkeeping for code decisions**—not blockchain-level immutability, but tamper-evident accountability that works with Git and your existing workflow.
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
## Why It Matters for Agent Collaboration
|
|
29
29
|
|
|
30
|
-
When agents
|
|
30
|
+
When agents can ship production changes, you need governance that works for both humans and AI:
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
**Traditional tools fall short:**
|
|
33
|
+
- Linear tracks tasks, not decisions or reasoning
|
|
34
|
+
- GitHub shows changes, not why they were made
|
|
35
|
+
- Slack/Discord: context vanishes in chat history
|
|
36
|
+
- No tool tells you if an agent's change conflicts with yesterday's decision
|
|
33
37
|
|
|
34
|
-
|
|
38
|
+
**Trie's ledger provides:**
|
|
39
|
+
- **Tamper-evident history**: Ed25519 signatures detect if entries are modified
|
|
40
|
+
- **Automatic recording**: Agents and humans write to the same ledger
|
|
41
|
+
- **Cross-tool context**: Works in Cursor, CLI, CI/CD, MCP servers
|
|
42
|
+
- **Accountability**: See who (human or agent) made each decision and when
|
|
43
|
+
- **Pattern learning**: Every incident makes the system smarter
|
|
44
|
+
|
|
45
|
+
The ledger ensures nothing is lost. When an agent queries it, answers come with full provenance. When you review changes, you see the reasoning trail. When something breaks, the audit trail is already there.
|
|
35
46
|
|
|
36
47
|
### How the Agent Works
|
|
37
48
|
|
|
38
49
|
1. **`trie watch`** - Start the agent, it monitors your codebase autonomously
|
|
39
50
|
2. **Agent Extracts** - Every file change → extract decisions, facts, blockers
|
|
40
|
-
3. **Agent Stores** - Builds decision ledger with
|
|
51
|
+
3. **Agent Stores** - Builds decision ledger with signatures and metadata
|
|
41
52
|
4. **`trie gotcha`** - Agent queries ledger to predict problems in your current changes
|
|
42
53
|
5. **`trie tell`** - Feed agent incidents to improve its predictions
|
|
43
54
|
6. **Agent Learns** - Gets better at predicting what matters in YOUR codebase
|
|
44
55
|
|
|
45
|
-
Your decisions persist across tools. Your edge cases don't get forgotten. The ledger keeps agents and humans
|
|
56
|
+
Your decisions persist across tools. Your edge cases don't get forgotten. The ledger keeps agents and humans aligned—so you ship the right thing every time.
|
|
46
57
|
|
|
47
58
|
## Quick Start
|
|
48
59
|
|
|
@@ -91,13 +102,22 @@ Tools like Cursor Bugbot flag issues—but flagging doesn't help you avoid simil
|
|
|
91
102
|
|
|
92
103
|
## Key Features
|
|
93
104
|
|
|
105
|
+
### Built for Agent + Human Collaboration
|
|
106
|
+
|
|
107
|
+
- **Shared governance ledger** - Single source of truth that agents and humans both read from and write to
|
|
108
|
+
- **Digital signatures** - Ed25519 signatures prove who (human or agent) created each entry, automatic and zero-config
|
|
109
|
+
- **Accountability trail** - See exactly what decisions agents made and when, verify authenticity
|
|
110
|
+
- **Cross-tool context** - Works in Cursor, Claude Code, CLI, CI/CD—same ledger everywhere
|
|
111
|
+
- **Tamper detection** - Signatures and Git history make modifications visible
|
|
112
|
+
- **No coordination needed** - Agents and humans write concurrently; Git handles conflicts
|
|
113
|
+
|
|
94
114
|
### Governance That Scales
|
|
95
115
|
|
|
96
|
-
- **
|
|
97
|
-
- **
|
|
98
|
-
- **Decision memory** - Captures architectural choices, tradeoffs, and context across
|
|
99
|
-
- **Judgment artifacts** - Not just what shipped, but why, what was considered, and who decided
|
|
100
|
-
- **Git
|
|
116
|
+
- **Tamper-evident ledger** - Append-only chain with cryptographic signatures (not blockchain, think double-entry bookkeeping)
|
|
117
|
+
- **Correction pattern** - Entries never deleted, only marked as corrected with full audit trail
|
|
118
|
+
- **Decision memory** - Captures architectural choices, tradeoffs, and context across all tools
|
|
119
|
+
- **Judgment artifacts** - Not just what shipped, but why, what was considered, and who (or what) decided
|
|
120
|
+
- **Git integration** - Auto-commits ledger changes; distributed backup via Git history
|
|
101
121
|
|
|
102
122
|
### Intelligence That Compounds
|
|
103
123
|
|
|
@@ -109,7 +129,7 @@ Tools like Cursor Bugbot flag issues—but flagging doesn't help you avoid simil
|
|
|
109
129
|
|
|
110
130
|
### Integration Built for Speed
|
|
111
131
|
|
|
112
|
-
- **Multiple interfaces** - CLI, MCP tools for Claude/Cursor, visual dashboards
|
|
132
|
+
- **Multiple interfaces** - CLI, MCP tools for Claude/Cursor, visual dashboards
|
|
113
133
|
- **Git hooks** - Automatic checks before commits and pushes
|
|
114
134
|
- **Watch mode** - Real-time monitoring while you code
|
|
115
135
|
- **Fast performance** - Sub-500ms checks, won't slow down your workflow
|
|
@@ -161,7 +181,6 @@ your-project/
|
|
|
161
181
|
├── src/
|
|
162
182
|
└── .git/
|
|
163
183
|
```
|
|
164
|
-
Different machines
|
|
165
184
|
|
|
166
185
|
### Decision Memory Across Tools
|
|
167
186
|
|
|
@@ -296,27 +315,55 @@ Edge cases, tradeoffs, and system coherence—Trie handles governance by remembe
|
|
|
296
315
|
|
|
297
316
|
### Goals & Hypotheses
|
|
298
317
|
|
|
299
|
-
Set improvement goals and test theories:
|
|
318
|
+
Set improvement goals and test theories. **Goals are actively enforced in real-time** as you code:
|
|
300
319
|
|
|
301
320
|
```bash
|
|
302
|
-
# Set a goal
|
|
303
|
-
trie goal add "
|
|
321
|
+
# Set a goal - any custom rule you want enforced
|
|
322
|
+
trie goal add "No console.log statements in production"
|
|
323
|
+
trie goal add "All API endpoints must have rate limiting"
|
|
324
|
+
trie goal add "We never truncate text in UI components"
|
|
304
325
|
|
|
305
326
|
# Add a hypothesis
|
|
306
327
|
trie hypothesis add "Code reviews reduce bug rate"
|
|
307
328
|
|
|
308
|
-
#
|
|
329
|
+
# View progress
|
|
330
|
+
trie goal list
|
|
309
331
|
```
|
|
310
332
|
|
|
333
|
+
**How Goal Checking Works:**
|
|
334
|
+
|
|
335
|
+
When you run `trie watch`, the system actively monitors your code for goal violations using AI-powered analysis:
|
|
336
|
+
|
|
337
|
+
1. **Custom & Flexible** - Goals can be any quality rule you define (no emojis, no TODOs, security patterns, UI standards, etc.)
|
|
338
|
+
2. **RAG-Based** - Uses semantic understanding, not just keyword matching
|
|
339
|
+
3. **Real-Time** - Checks every file change against ALL active goals
|
|
340
|
+
4. **Smart Caching** - Avoids re-scanning unchanged files
|
|
341
|
+
5. **Cost-Aware** - Token budgets and cooldowns prevent runaway AI costs
|
|
342
|
+
6. **High Confidence** - Only reports violations with strong confidence scores
|
|
343
|
+
|
|
344
|
+
**Example Goal Violations Detected:**
|
|
345
|
+
- "No emojis in code" → Finds any Unicode emoji anywhere in files
|
|
346
|
+
- "All functions must have JSDoc" → Checks for missing documentation
|
|
347
|
+
- "No inline styles in React" → Detects style attributes in JSX
|
|
348
|
+
- "Every TODO must have a ticket reference" → Validates TODO format
|
|
349
|
+
|
|
350
|
+
Goals are tracked over time with metrics (violations caught, fixed, progress percentage).
|
|
351
|
+
|
|
311
352
|
### Watch Mode
|
|
312
353
|
|
|
313
|
-
Real-time monitoring with
|
|
354
|
+
Real-time monitoring with **proactive goal violation detection**:
|
|
314
355
|
|
|
315
356
|
```bash
|
|
316
357
|
trie watch
|
|
317
358
|
```
|
|
318
359
|
|
|
319
|
-
|
|
360
|
+
**Features:**
|
|
361
|
+
- **Interactive dashboard** with goals, memory, analysis activity panels
|
|
362
|
+
- **AI-powered goal checking** - automatically detects violations of your custom rules
|
|
363
|
+
- **Token-aware** - manages AI costs with budgets and cooldowns
|
|
364
|
+
- **Smart prioritization** - focuses on high-risk files first
|
|
365
|
+
- **Caching** - avoids duplicate scans of unchanged files
|
|
366
|
+
- **Real-time nudges** - immediate feedback when violations are detected
|
|
320
367
|
|
|
321
368
|
Running in Background: To keep trie watch running in the background, use screen or tmux:
|
|
322
369
|
|
|
@@ -796,8 +843,6 @@ trie ledger corrections --entries <entry-id1> <entry-id2>
|
|
|
796
843
|
- Learn from false positives to improve detection
|
|
797
844
|
- Track correction rates over time
|
|
798
845
|
|
|
799
|
-
See [docs/LEDGER_CORRECTIONS.md](./docs/LEDGER_CORRECTIONS.md) for detailed usage.
|
|
800
|
-
|
|
801
846
|
## CI/CD Integration
|
|
802
847
|
|
|
803
848
|
### GitHub Actions
|
|
@@ -826,16 +871,40 @@ Trie maintains two complementary memory systems that work together:
|
|
|
826
871
|
### 1. Governance Ledger (Primary Product)
|
|
827
872
|
|
|
828
873
|
**Location:** `.trie/memory/ledger.json`
|
|
829
|
-
**Purpose:**
|
|
830
|
-
**Architecture:** Append-only chain of blocks with
|
|
874
|
+
**Purpose:** Tamper-evident record of decisions, incidents, and fixes
|
|
875
|
+
**Architecture:** Append-only chain of blocks with Ed25519 signatures
|
|
831
876
|
|
|
832
|
-
This is the **core governance layer**
|
|
877
|
+
This is the **core governance layer** that:
|
|
833
878
|
- Powers `trie gotcha` predictions
|
|
834
|
-
- Provides
|
|
879
|
+
- Provides accountability for agent and human decisions
|
|
880
|
+
- Uses digital signatures to detect tampering
|
|
835
881
|
- Never deleted, only corrected (see [Ledger Corrections](./docs/LEDGER_CORRECTIONS.md))
|
|
836
|
-
-
|
|
882
|
+
- Auto-commits to Git for distributed backup
|
|
883
|
+
|
|
884
|
+
**How it works:**
|
|
885
|
+
- Every entry gets signed with Ed25519 (automatic, zero config)
|
|
886
|
+
- Signatures prove who created each entry and detect modifications
|
|
887
|
+
- Git integration provides distributed backup and history
|
|
888
|
+
- Think: **double-entry bookkeeping**, not blockchain
|
|
889
|
+
|
|
890
|
+
**Security model:**
|
|
891
|
+
- ✅ **Tamper-evident**: Signatures detect if entries are modified
|
|
892
|
+
- ✅ **Accountability**: See who (human or agent) made each decision
|
|
893
|
+
- ✅ **Git backup**: Distributed history via automatic commits
|
|
894
|
+
- ✅ **Verification**: `trie ledger verify` checks integrity
|
|
895
|
+
- ⚠️ **Not encrypted**: Ledger is plaintext (can add encryption if needed)
|
|
896
|
+
- ⚠️ **Not access-controlled**: Standard file permissions apply
|
|
897
|
+
- ⚠️ **Not deletion-proof**: Can still `rm .trie/` (but Git history remains)
|
|
898
|
+
|
|
899
|
+
**Real protection comes from:** Git history + Team workflow + PR reviews
|
|
900
|
+
|
|
901
|
+
Perfect for agent collaboration because:
|
|
902
|
+
- Agents can trust ledger contents (signatures verify authenticity)
|
|
903
|
+
- Humans can audit agent decisions (full provenance trail)
|
|
904
|
+
- Cross-tool context works (same ledger in Cursor, CLI, CI/CD)
|
|
905
|
+
- Conflicts are visible (Git shows competing changes)
|
|
837
906
|
|
|
838
|
-
|
|
907
|
+
Learn more: [Signatures & Git Integration](./docs/SIGNATURES_AND_GIT.md)
|
|
839
908
|
|
|
840
909
|
### 2. Issue Memory (Query Cache)
|
|
841
910
|
|
|
@@ -897,6 +966,51 @@ trie goal list
|
|
|
897
966
|
### Getting Help
|
|
898
967
|
- Issues: [Report bugs and request features](https://x.com/louiskishfy)
|
|
899
968
|
|
|
969
|
+
## Contributing
|
|
970
|
+
|
|
971
|
+
We welcome contributions from the community! Whether you're fixing bugs, adding features, improving documentation, or sharing feedback, your contributions help make Trie better for everyone.
|
|
972
|
+
|
|
973
|
+
### Quick Start for Contributors
|
|
974
|
+
|
|
975
|
+
1. **Fork and clone** the repository
|
|
976
|
+
2. **Install dependencies**: `npm install`
|
|
977
|
+
3. **Set up environment**: Copy `.env.example` to `.env.local` and add your API keys
|
|
978
|
+
4. **Build the project**: `npm run build`
|
|
979
|
+
5. **Run tests**: `npm test`
|
|
980
|
+
|
|
981
|
+
### Before Submitting
|
|
982
|
+
|
|
983
|
+
- Ensure all tests pass (`npm test`)
|
|
984
|
+
- Run type checking (`npm run typecheck`)
|
|
985
|
+
- Follow our code style (`npm run lint`)
|
|
986
|
+
- Update documentation for new features
|
|
987
|
+
- Never commit secrets or API keys
|
|
988
|
+
|
|
989
|
+
**Read our full [Contributing Guide](CONTRIBUTING.md) for detailed guidelines.**
|
|
990
|
+
|
|
991
|
+
### Ways to Contribute
|
|
992
|
+
|
|
993
|
+
- 🐛 **Report bugs** - Open an issue with reproduction steps
|
|
994
|
+
- 💡 **Suggest features** - Share ideas for improvements
|
|
995
|
+
- 📝 **Improve docs** - Fix typos, add examples, clarify instructions
|
|
996
|
+
- 🔧 **Submit PRs** - Fix bugs or implement features
|
|
997
|
+
- 🧪 **Add tests** - Improve test coverage
|
|
998
|
+
- 🔐 **Security** - Report vulnerabilities privately (see [SECURITY.md](SECURITY.md))
|
|
999
|
+
|
|
1000
|
+
### Code of Conduct
|
|
1001
|
+
|
|
1002
|
+
Be respectful, inclusive, and professional. We're building this together.
|
|
1003
|
+
|
|
1004
|
+
## Security
|
|
1005
|
+
|
|
1006
|
+
Please report security vulnerabilities privately. See [SECURITY.md](SECURITY.md) for details.
|
|
1007
|
+
|
|
1008
|
+
**Never commit:**
|
|
1009
|
+
- API keys or secrets
|
|
1010
|
+
- `.env.local` or `.env` files
|
|
1011
|
+
- Private signing keys (`.trie/keys/`)
|
|
1012
|
+
- Personal configuration
|
|
1013
|
+
|
|
900
1014
|
## License
|
|
901
1015
|
|
|
902
|
-
MIT License
|
|
1016
|
+
MIT License - See [LICENSE](LICENSE) for details.
|
|
@@ -10,9 +10,9 @@ import {
|
|
|
10
10
|
shouldAutoFix,
|
|
11
11
|
shouldBlockPush,
|
|
12
12
|
trackIssueOccurrence
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-XD2HKZVB.js";
|
|
14
|
+
import "./chunk-7F2R2ITA.js";
|
|
15
|
+
import "./chunk-JKEEQAG2.js";
|
|
16
16
|
import "./chunk-DGUM43GV.js";
|
|
17
17
|
export {
|
|
18
18
|
clearConfigCache,
|
|
@@ -27,4 +27,4 @@ export {
|
|
|
27
27
|
shouldBlockPush,
|
|
28
28
|
trackIssueOccurrence
|
|
29
29
|
};
|
|
30
|
-
//# sourceMappingURL=autonomy-config-
|
|
30
|
+
//# sourceMappingURL=autonomy-config-RKLZW4XL.js.map
|
|
@@ -2,14 +2,14 @@ import {
|
|
|
2
2
|
ChatStore,
|
|
3
3
|
clearChatStores,
|
|
4
4
|
getChatStore
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-3CYMLM35.js";
|
|
6
6
|
import "./chunk-43X6JBEM.js";
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-7F2R2ITA.js";
|
|
8
|
+
import "./chunk-JKEEQAG2.js";
|
|
9
9
|
import "./chunk-DGUM43GV.js";
|
|
10
10
|
export {
|
|
11
11
|
ChatStore,
|
|
12
12
|
clearChatStores,
|
|
13
13
|
getChatStore
|
|
14
14
|
};
|
|
15
|
-
//# sourceMappingURL=chat-store-
|
|
15
|
+
//# sourceMappingURL=chat-store-O3IJ5PMN.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-6NLHFIYA.js";
|
|
4
4
|
import {
|
|
5
5
|
isInteractiveMode
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-JKEEQAG2.js";
|
|
7
7
|
|
|
8
8
|
// src/trie/vibe-code-signatures.ts
|
|
9
9
|
var VIBE_CODE_PATTERNS = [
|
|
@@ -984,4 +984,4 @@ export {
|
|
|
984
984
|
scanForVibeCodeIssues,
|
|
985
985
|
getVibeCodeStats
|
|
986
986
|
};
|
|
987
|
-
//# sourceMappingURL=chunk-
|
|
987
|
+
//# sourceMappingURL=chunk-2LAJKFWU.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-7F2R2ITA.js";
|
|
7
7
|
|
|
8
8
|
// src/cli/dashboard/chat-store.ts
|
|
9
9
|
import { mkdir, readFile, unlink } from "fs/promises";
|
|
@@ -345,4 +345,4 @@ export {
|
|
|
345
345
|
getChatStore,
|
|
346
346
|
clearChatStores
|
|
347
347
|
};
|
|
348
|
-
//# sourceMappingURL=chunk-
|
|
348
|
+
//# sourceMappingURL=chunk-3CYMLM35.js.map
|
|
@@ -6,14 +6,14 @@ import {
|
|
|
6
6
|
} from "./chunk-EFWVF6TI.js";
|
|
7
7
|
import {
|
|
8
8
|
appendIssuesToLedger
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-HD5H7YSW.js";
|
|
10
10
|
import {
|
|
11
11
|
atomicWriteJSON
|
|
12
12
|
} from "./chunk-43X6JBEM.js";
|
|
13
13
|
import {
|
|
14
14
|
getTrieDirectory,
|
|
15
15
|
getWorkingDirectory
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-7F2R2ITA.js";
|
|
17
17
|
|
|
18
18
|
// src/memory/issue-store.ts
|
|
19
19
|
import { mkdir as mkdir2, readFile as readFile2, readdir } from "fs/promises";
|
|
@@ -432,8 +432,7 @@ async function storeIssues(issues, project, workDir) {
|
|
|
432
432
|
project,
|
|
433
433
|
resolved: false,
|
|
434
434
|
resolvedAt: void 0,
|
|
435
|
-
ledgerBlockHash:
|
|
436
|
-
// Will be set after ledger write
|
|
435
|
+
...issue.ledgerBlockHash && { ledgerBlockHash: issue.ledgerBlockHash }
|
|
437
436
|
};
|
|
438
437
|
stored.push(storedIssue);
|
|
439
438
|
}
|
|
@@ -675,7 +674,7 @@ async function getDailyLogs(workDir) {
|
|
|
675
674
|
async function getIssueLedgerEntry(issue, workDir) {
|
|
676
675
|
if (!issue.ledgerBlockHash) return null;
|
|
677
676
|
const projectDir = workDir || getWorkingDirectory(void 0, true);
|
|
678
|
-
const { getLedgerBlocks } = await import("./ledger-
|
|
677
|
+
const { getLedgerBlocks } = await import("./ledger-PLE3C3X4.js");
|
|
679
678
|
const blocks = await getLedgerBlocks(projectDir);
|
|
680
679
|
const block = blocks.find((b) => b.blockHash === issue.ledgerBlockHash);
|
|
681
680
|
if (!block) return null;
|
|
@@ -780,4 +779,4 @@ export {
|
|
|
780
779
|
getDailyLogs,
|
|
781
780
|
getIssueLedgerEntry
|
|
782
781
|
};
|
|
783
|
-
//# sourceMappingURL=chunk-
|
|
782
|
+
//# sourceMappingURL=chunk-4ZAFQEP6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/memory/issue-store.ts","../src/memory/bm25.ts","../src/memory/compactor.ts"],"sourcesContent":["/**\n * Issue Memory Store\n * \n * Working state cache complementary to the immutable ledger.\n * \n * Architecture:\n * - Ledger (.trie/memory/ledger.json) = immutable source of truth\n * - Issue Memory = mutable working state + BM25 search index\n * \n * Issue memory provides:\n * - Fast BM25 semantic search for pattern matching\n * - Mutable state tracking (resolved, open, fixed)\n * - Goal violation metrics and progress tracking\n * - Links back to ledger via ledgerBlockHash\n * \n * Phase 1 Hardening:\n * - SHA256 hashing for proper deduplication\n * - Atomic writes to prevent corruption\n * - Rotational backups for recovery\n * - Zod validation for data integrity\n */\n\nimport { mkdir, readFile, readdir } from 'fs/promises';\nimport { createHash } from 'crypto';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { getWorkingDirectory, getTrieDirectory } from '../utils/workspace.js';\nimport type { Issue } from '../types/index.js';\nimport { BM25Index } from './bm25.js';\nimport { compactOldIssues, saveCompactedSummary, getHistoricalInsights } from './compactor.js';\nimport { atomicWriteJSON } from '../utils/atomic-write.js';\nimport { BackupManager } from '../utils/backup-manager.js';\nimport { IssueIndexSchema, safeParseAndValidate } from './validation.js';\nimport { appendIssuesToLedger } from './ledger.js';\n\nexport interface StoredIssue {\n id: string;\n hash: string;\n severity: string;\n issue: string;\n fix: string;\n file: string;\n line: number | undefined;\n agent: string;\n category: string | undefined;\n timestamp: string;\n project: string;\n resolved: boolean | undefined;\n resolvedAt: string | undefined;\n ledgerBlockHash?: string; // Link to immutable ledger record\n}\n\nexport interface IssueSearchResult {\n issue: StoredIssue;\n score: number;\n matchType: 'bm25' | 'keyword' | 'fts5';\n}\n\nexport interface IssueMemoryStats {\n totalIssues: number;\n activeIssues: number; // Unresolved issues\n issuesByAgent: Record<string, number>;\n issuesBySeverity: Record<string, number>; // All issues (historical)\n activeIssuesBySeverity: Record<string, number>; // Only unresolved\n oldestIssue: string | undefined;\n newestIssue: string | undefined;\n resolvedCount: number;\n historicalIssues: number;\n improvementTrend: 'improving' | 'stable' | 'declining' | 'unknown';\n capacityInfo: {\n current: number;\n max: number;\n percentFull: number;\n isAtCap: boolean;\n };\n deduplicationStats: {\n duplicatesAvoided: number;\n uniquePatterns: number;\n };\n}\n\n/**\n * Store issues and link them to the ledger\n * \n * Flow:\n * 1. Append to ledger (immutable source of truth)\n * 2. Cache in issue memory with ledger reference\n * \n * Returns number of unique issues added (after deduplication)\n */\nexport async function storeIssues(\n issues: Issue[],\n project: string,\n workDir?: string\n): Promise<{ stored: number; duplicates: number }> {\n const projectDir = workDir || getWorkingDirectory(undefined, true);\n const memoryDir = join(getTrieDirectory(projectDir), 'memory');\n await mkdir(memoryDir, { recursive: true });\n \n const stored: StoredIssue[] = [];\n const now = new Date().toISOString();\n const seenHashes = new Set<string>();\n let duplicates = 0;\n \n for (const issue of issues) {\n const hash = hashIssue(issue);\n \n // Skip duplicates within the same scan\n if (seenHashes.has(hash)) {\n duplicates++;\n continue;\n }\n seenHashes.add(hash);\n \n const storedIssue: StoredIssue = {\n id: issue.id,\n hash,\n severity: issue.severity,\n issue: issue.issue,\n fix: issue.fix,\n file: issue.file,\n line: issue.line,\n agent: issue.agent,\n category: issue.category,\n timestamp: now,\n project,\n resolved: false,\n resolvedAt: undefined,\n ...(issue.ledgerBlockHash && { ledgerBlockHash: issue.ledgerBlockHash }),\n };\n stored.push(storedIssue);\n }\n\n // 1. Write to ledger (immutable source of truth)\n const ledgerBlock = await appendIssuesToLedger(stored, projectDir);\n \n // 2. Link issues to their ledger block\n if (ledgerBlock) {\n for (const issue of stored) {\n issue.ledgerBlockHash = ledgerBlock.blockHash;\n }\n }\n \n // 3. Cache in issue memory (working state + search index)\n const dedupedCount = await updateIssueIndex(stored, projectDir);\n \n return { stored: dedupedCount, duplicates: duplicates + (stored.length - dedupedCount) };\n}\n\n/**\n * Search issues using BM25 ranking (same algorithm as Elasticsearch)\n */\nexport async function searchIssues(\n query: string,\n options: {\n workDir?: string;\n limit?: number;\n project?: string;\n severity?: string[];\n agent?: string;\n includeResolved?: boolean;\n } = {}\n): Promise<IssueSearchResult[]> {\n const projectDir = options.workDir || getWorkingDirectory(undefined, true);\n const limit = options.limit || 10;\n const allIssues = await loadIssueIndex(projectDir);\n \n if (allIssues.length === 0) {\n return [];\n }\n\n // Filter issues first\n const filteredIssues = allIssues.filter(issue => {\n if (options.project && issue.project !== options.project) return false;\n if (options.severity && !options.severity.includes(issue.severity)) return false;\n if (options.agent && issue.agent !== options.agent) return false;\n if (!options.includeResolved && issue.resolved) return false;\n return true;\n });\n\n if (filteredIssues.length === 0) {\n return [];\n }\n\n // Build BM25 index\n const bm25 = new BM25Index();\n const issueMap = new Map<string, StoredIssue>();\n \n for (const issue of filteredIssues) {\n const searchText = `${issue.issue} ${issue.fix} ${issue.file} ${issue.agent} ${issue.category || ''} ${issue.severity}`;\n bm25.addDocument({\n id: issue.id,\n text: searchText,\n });\n issueMap.set(issue.id, issue);\n }\n\n // Search with BM25\n const bm25Results = bm25.search(query, limit);\n \n return bm25Results.map(result => ({\n issue: issueMap.get(result.id)!,\n score: result.score,\n matchType: 'bm25' as const,\n }));\n}\n\n/**\n * Find similar issues using BM25 similarity\n */\nexport async function findSimilarIssues(\n issue: Issue,\n options: {\n workDir?: string;\n limit?: number;\n excludeSameFile?: boolean;\n } = {}\n): Promise<IssueSearchResult[]> {\n // Use the issue description and fix as the query for similarity\n const query = `${issue.issue} ${issue.fix} ${issue.agent}`;\n const searchOptions: Parameters<typeof searchIssues>[1] = {\n limit: (options.limit || 5) + 5, // Get extra to account for filtering\n includeResolved: true,\n };\n if (options.workDir !== undefined) {\n searchOptions.workDir = options.workDir;\n }\n const results = await searchIssues(query, searchOptions);\n\n let filtered = results.filter(r => r.issue.id !== issue.id);\n \n if (options.excludeSameFile) {\n filtered = filtered.filter(r => r.issue.file !== issue.file);\n }\n \n return filtered.slice(0, options.limit || 5);\n}\n\n/**\n * Mark an issue as resolved\n */\nexport async function markIssueResolved(\n issueId: string,\n workDir?: string\n): Promise<boolean> {\n const projectDir = workDir || getWorkingDirectory(undefined, true);\n const index = await loadIssueIndex(projectDir);\n \n const issue = index.find(i => i.id === issueId);\n if (!issue) return false;\n \n issue.resolved = true;\n issue.resolvedAt = new Date().toISOString();\n \n await saveIssueIndex(index, projectDir);\n return true;\n}\n\n/**\n * Auto-resolve issues that were not found in the latest scan\n * \n * After a scan completes, this function compares new issues against stored issues.\n * Issues that were previously found in scanned files but are no longer detected\n * are automatically marked as resolved.\n * \n * @param newIssueHashes - Set of hashes from the current scan\n * @param scannedFiles - List of files that were scanned (to scope resolution)\n * @param workDir - Working directory\n * @returns Number of issues auto-resolved\n */\nexport async function autoResolveIssues(\n newIssueHashes: Set<string>,\n scannedFiles: string[],\n workDir?: string\n): Promise<{ resolved: number; stillActive: number }> {\n const projectDir = workDir || getWorkingDirectory(undefined, true);\n const index = await loadIssueIndex(projectDir);\n \n // Normalize scanned file paths for comparison\n const scannedFileSet = new Set(scannedFiles.map(f => f.replace(/\\\\/g, '/')));\n \n const now = new Date().toISOString();\n let resolvedCount = 0;\n let stillActiveCount = 0;\n \n for (const issue of index) {\n // Skip already resolved issues\n if (issue.resolved) continue;\n \n // Normalize the issue file path\n const normalizedFile = issue.file.replace(/\\\\/g, '/');\n \n // Only auto-resolve issues in files that were scanned\n // This prevents marking issues as resolved if we just did a partial scan\n if (!scannedFileSet.has(normalizedFile)) {\n stillActiveCount++;\n continue;\n }\n \n // If the issue's hash is NOT in the new scan results, it's been fixed\n if (!newIssueHashes.has(issue.hash)) {\n issue.resolved = true;\n issue.resolvedAt = now;\n resolvedCount++;\n } else {\n stillActiveCount++;\n }\n }\n \n // Only save if we resolved something\n if (resolvedCount > 0) {\n await saveIssueIndex(index, projectDir);\n }\n \n return { resolved: resolvedCount, stillActive: stillActiveCount };\n}\n\n/**\n * Resolve goal violation issues for a specific file and goal\n * Called when a goal violation is fixed\n */\nexport async function resolveGoalViolation(\n file: string,\n goalDescription: string,\n workDir?: string\n): Promise<number> {\n const projectDir = workDir || getWorkingDirectory(undefined, true);\n const index = await loadIssueIndex(projectDir);\n \n const now = new Date().toISOString();\n let resolvedCount = 0;\n \n for (const issue of index) {\n if (issue.resolved) continue;\n if (issue.agent !== 'goal-violation') continue;\n \n // Match file and goal description\n const normalizedFile = issue.file.replace(/\\\\/g, '/');\n const normalizedTarget = file.replace(/\\\\/g, '/');\n \n if (normalizedFile === normalizedTarget && \n issue.issue.includes(`Goal \"${goalDescription}\"`)) {\n issue.resolved = true;\n issue.resolvedAt = now;\n resolvedCount++;\n }\n }\n \n if (resolvedCount > 0) {\n await saveIssueIndex(index, projectDir);\n }\n \n return resolvedCount;\n}\n\n/**\n * Get hash for an issue (for external callers)\n */\nexport function getIssueHash(issue: Issue): string {\n return hashIssue(issue);\n}\n\n/**\n * Get memory statistics including historical insights\n */\nexport async function getMemoryStats(workDir?: string): Promise<IssueMemoryStats> {\n const projectDir = workDir || getWorkingDirectory(undefined, true);\n const index = await loadIssueIndex(projectDir);\n const historical = await getHistoricalInsights(projectDir);\n \n const MAX_ISSUES = 10000;\n const uniqueHashes = new Set(index.map(i => i.hash));\n \n const stats: IssueMemoryStats = {\n totalIssues: index.length,\n activeIssues: 0,\n issuesByAgent: {},\n issuesBySeverity: {},\n activeIssuesBySeverity: {},\n oldestIssue: undefined,\n newestIssue: undefined,\n resolvedCount: 0,\n historicalIssues: historical.totalHistoricalIssues,\n improvementTrend: historical.improvementTrend,\n capacityInfo: {\n current: index.length,\n max: MAX_ISSUES,\n percentFull: Math.round((index.length / MAX_ISSUES) * 100),\n isAtCap: index.length >= MAX_ISSUES,\n },\n deduplicationStats: {\n duplicatesAvoided: index.length - uniqueHashes.size,\n uniquePatterns: uniqueHashes.size,\n },\n };\n\n for (const issue of index) {\n stats.issuesByAgent[issue.agent] = (stats.issuesByAgent[issue.agent] || 0) + 1;\n stats.issuesBySeverity[issue.severity] = (stats.issuesBySeverity[issue.severity] || 0) + 1;\n \n if (issue.resolved) {\n stats.resolvedCount++;\n } else {\n stats.activeIssues++;\n stats.activeIssuesBySeverity[issue.severity] = (stats.activeIssuesBySeverity[issue.severity] || 0) + 1;\n }\n }\n\n if (index.length > 0) {\n const sorted = [...index].sort((a, b) => \n new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()\n );\n const oldest = sorted[0]?.timestamp;\n const newest = sorted[sorted.length - 1]?.timestamp;\n if (oldest !== undefined) {\n stats.oldestIssue = oldest;\n }\n if (newest !== undefined) {\n stats.newestIssue = newest;\n }\n }\n\n return stats;\n}\n\n/**\n * Get recent issues\n * @param options.includeResolved - If false (default), only returns unresolved issues\n */\nexport async function getRecentIssues(\n options: {\n workDir?: string;\n limit?: number;\n daysBack?: number;\n includeResolved?: boolean;\n } = {}\n): Promise<StoredIssue[]> {\n const projectDir = options.workDir || getWorkingDirectory(undefined, true);\n const index = await loadIssueIndex(projectDir);\n const limit = options.limit || 20;\n const daysBack = options.daysBack || 7;\n const includeResolved = options.includeResolved ?? false;\n \n const cutoff = new Date();\n cutoff.setDate(cutoff.getDate() - daysBack);\n \n return index\n .filter(i => {\n if (new Date(i.timestamp) < cutoff) return false;\n if (!includeResolved && i.resolved) return false;\n return true;\n })\n .sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())\n .slice(0, limit);\n}\n\n/**\n * Purge issues from memory\n * Offers different strategies for managing memory capacity\n */\nexport async function purgeIssues(\n strategy: 'smart' | 'resolved' | 'old' | 'all',\n options: {\n workDir?: string;\n daysOld?: number;\n } = {}\n): Promise<{ removed: number; remaining: number; strategy: string }> {\n const projectDir = options.workDir || getWorkingDirectory(undefined, true);\n const index = await loadIssueIndex(projectDir);\n const originalCount = index.length;\n \n let remaining: StoredIssue[] = [];\n \n switch (strategy) {\n case 'smart':\n // Keep: critical/high severity, recent (< 30 days), unresolved\n const thirtyDaysAgo = new Date();\n thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);\n \n remaining = index.filter(i => {\n const isRecent = new Date(i.timestamp) >= thirtyDaysAgo;\n const isImportant = ['critical', 'high'].includes(i.severity);\n const isUnresolved = !i.resolved;\n \n return isRecent || isImportant || isUnresolved;\n });\n break;\n \n case 'resolved':\n // Remove all resolved issues\n remaining = index.filter(i => !i.resolved);\n break;\n \n case 'old':\n // Remove issues older than specified days (default 90)\n const daysOld = options.daysOld || 90;\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - daysOld);\n \n remaining = index.filter(i => new Date(i.timestamp) >= cutoffDate);\n break;\n \n case 'all':\n // Clear all issues (keeps compacted summaries)\n remaining = [];\n break;\n }\n \n await saveIssueIndex(remaining, projectDir);\n \n return {\n removed: originalCount - remaining.length,\n remaining: remaining.length,\n strategy,\n };\n}\n\n/**\n * Get daily log files (legacy - deprecated)\n * \n * Note: Daily logs are redundant with the ledger.\n * The ledger provides the same information with better guarantees.\n * This function is kept for backward compatibility.\n */\nexport async function getDailyLogs(workDir?: string): Promise<string[]> {\n const projectDir = workDir || getWorkingDirectory(undefined, true);\n const memoryDir = join(getTrieDirectory(projectDir), 'memory');\n \n try {\n if (!existsSync(memoryDir)) return [];\n const files = await readdir(memoryDir);\n return files\n .filter(f => /^\\d{4}-\\d{2}-\\d{2}\\.md$/.test(f))\n .sort()\n .reverse();\n } catch {\n return [];\n }\n}\n\n// Private helpers\n\n/**\n * Get ledger entry for an issue\n * \n * Issue memory stores working state (resolved, etc.)\n * Ledger stores immutable history (what was detected, when)\n * \n * This helper links them together for full context.\n */\nexport async function getIssueLedgerEntry(\n issue: StoredIssue,\n workDir?: string\n): Promise<{ block: any; entry: any } | null> {\n if (!issue.ledgerBlockHash) return null;\n \n const projectDir = workDir || getWorkingDirectory(undefined, true);\n const { getLedgerBlocks } = await import('./ledger.js');\n const blocks = await getLedgerBlocks(projectDir);\n \n // Find the block this issue is linked to\n const block = blocks.find(b => b.blockHash === issue.ledgerBlockHash);\n if (!block) return null;\n \n // Find the specific entry in that block\n const entry = block.entries.find((e: any) => e.hash === issue.hash);\n if (!entry) return null;\n \n return { block, entry };\n}\n\n// Private helpers\n\n/**\n * Load issue index with validation and auto-recovery\n * \n * If the file is corrupted:\n * 1. Attempts to recover from the most recent valid backup\n * 2. Returns empty array if no valid backup exists\n */\nasync function loadIssueIndex(projectDir: string): Promise<StoredIssue[]> {\n const indexPath = join(getTrieDirectory(projectDir), 'memory', 'issues.json');\n \n try {\n if (existsSync(indexPath)) {\n const content = await readFile(indexPath, 'utf-8');\n const result = safeParseAndValidate(content, IssueIndexSchema);\n \n if (result.success) {\n return result.data as StoredIssue[];\n }\n \n // Validation failed - attempt recovery from backup\n console.error(` Issue index corrupted: ${result.error}`);\n const backupManager = new BackupManager(indexPath);\n \n if (await backupManager.recoverFromBackup()) {\n console.error(' ✅ Recovered from backup');\n const recovered = await readFile(indexPath, 'utf-8');\n const recoveredResult = safeParseAndValidate(recovered, IssueIndexSchema);\n if (recoveredResult.success) {\n return recoveredResult.data as StoredIssue[];\n }\n }\n \n console.error(' No valid backup found, starting fresh');\n }\n } catch {\n // Index doesn't exist or recovery failed\n }\n \n return [];\n}\n\nasync function updateIssueIndex(newIssues: StoredIssue[], projectDir: string): Promise<number> {\n const memoryDir = join(getTrieDirectory(projectDir), 'memory');\n await mkdir(memoryDir, { recursive: true });\n \n let existing = await loadIssueIndex(projectDir);\n \n // Intelligent deduplication: only add truly unique issues\n // Issues are unique if they have different hash (content + file + severity + agent)\n const hashSet = new Set(existing.map(i => i.hash));\n const toAdd = newIssues.filter(i => !hashSet.has(i.hash));\n const dedupedCount = toAdd.length;\n \n existing = [...existing, ...toAdd];\n \n // Intelligent compaction: summarize old issues instead of deleting\n if (existing.length > 500) {\n const { summary, remaining } = await compactOldIssues(existing, {\n keepDays: 30,\n minIssuesToCompact: 100,\n });\n \n if (summary) {\n await saveCompactedSummary(summary, projectDir);\n existing = remaining;\n }\n }\n \n // Hard cap: prune to 10,000 if still too large\n // Prioritize: 1) Recent issues, 2) High severity, 3) Unresolved\n if (existing.length > 10000) {\n existing = intelligentPrune(existing, 10000);\n }\n \n await saveIssueIndex(existing, projectDir);\n return dedupedCount;\n}\n\n/**\n * Intelligently prune issues to target count\n * Prioritizes: recent, high severity, unresolved\n */\nfunction intelligentPrune(issues: StoredIssue[], targetCount: number): StoredIssue[] {\n const severityWeight: Record<string, number> = {\n critical: 100,\n high: 50,\n moderate: 20,\n low: 10,\n info: 5,\n };\n \n const scored = issues.map(issue => {\n const ageInDays = (Date.now() - new Date(issue.timestamp).getTime()) / (1000 * 60 * 60 * 24);\n const recencyScore = Math.max(0, 100 - ageInDays * 2); // Newer = higher score\n const severityScore = severityWeight[issue.severity] || 10;\n const resolvedPenalty = issue.resolved ? -50 : 0;\n \n return {\n issue,\n score: recencyScore + severityScore + resolvedPenalty,\n };\n });\n \n return scored\n .sort((a, b) => b.score - a.score)\n .slice(0, targetCount)\n .map(s => s.issue);\n}\n\n/**\n * Save issue index with backup and atomic write\n * \n * 1. Creates a backup of the existing file\n * 2. Writes the new data atomically (temp file + rename)\n * 3. Maintains up to 5 rotational backups\n */\nasync function saveIssueIndex(issues: StoredIssue[], projectDir: string): Promise<void> {\n const memoryDir = join(getTrieDirectory(projectDir), 'memory');\n await mkdir(memoryDir, { recursive: true });\n \n const indexPath = join(memoryDir, 'issues.json');\n \n // Create backup before writing\n const backupManager = new BackupManager(indexPath);\n await backupManager.createBackup();\n \n // Atomic write\n await atomicWriteJSON(indexPath, issues);\n}\n\n/**\n * Hash an issue using SHA256 for proper deduplication\n * \n * Uses cryptographic hashing to eliminate collision risk.\n * The hash is truncated to 16 characters for storage efficiency\n * while still providing effectively zero collision probability.\n */\nfunction hashIssue(issue: Issue): string {\n const content = `${issue.issue}|${issue.file}|${issue.severity}|${issue.agent}`;\n return createHash('sha256').update(content).digest('hex').slice(0, 16);\n}\n\n","/**\n * BM25 Search Implementation\n * \n * BM25 (Best Match 25) is a ranking function used by search engines.\n * It's more sophisticated than TF-IDF and handles term frequency saturation.\n * \n * This is the same algorithm used by Elasticsearch.\n */\n\nexport interface BM25Document {\n id: string;\n text: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface BM25Result {\n id: string;\n score: number;\n metadata?: Record<string, unknown>;\n}\n\nexport class BM25Index {\n private documents: Map<string, BM25Document> = new Map();\n private termFrequencies: Map<string, Map<string, number>> = new Map();\n private documentFrequencies: Map<string, number> = new Map();\n private documentLengths: Map<string, number> = new Map();\n private avgDocLength: number = 0;\n private k1: number = 1.5;\n private b: number = 0.75;\n\n /**\n * Add a document to the index\n */\n addDocument(doc: BM25Document): void {\n const tokens = this.tokenize(doc.text);\n this.documents.set(doc.id, doc);\n this.documentLengths.set(doc.id, tokens.length);\n\n const termFreq = new Map<string, number>();\n const seenTerms = new Set<string>();\n\n for (const token of tokens) {\n termFreq.set(token, (termFreq.get(token) || 0) + 1);\n \n if (!seenTerms.has(token)) {\n seenTerms.add(token);\n this.documentFrequencies.set(token, (this.documentFrequencies.get(token) || 0) + 1);\n }\n }\n\n this.termFrequencies.set(doc.id, termFreq);\n this.updateAvgDocLength();\n }\n\n /**\n * Add multiple documents\n */\n addDocuments(docs: BM25Document[]): void {\n for (const doc of docs) {\n this.addDocument(doc);\n }\n }\n\n /**\n * Search the index\n */\n search(query: string, limit: number = 10): BM25Result[] {\n const queryTokens = this.tokenize(query);\n const scores: Map<string, number> = new Map();\n const N = this.documents.size;\n\n for (const [docId] of this.documents) {\n let score = 0;\n const docLength = this.documentLengths.get(docId) || 0;\n const termFreqs = this.termFrequencies.get(docId);\n\n if (!termFreqs) continue;\n\n for (const term of queryTokens) {\n const tf = termFreqs.get(term) || 0;\n if (tf === 0) continue;\n\n const df = this.documentFrequencies.get(term) || 0;\n const idf = Math.log((N - df + 0.5) / (df + 0.5) + 1);\n\n const numerator = tf * (this.k1 + 1);\n const denominator = tf + this.k1 * (1 - this.b + this.b * (docLength / this.avgDocLength));\n \n score += idf * (numerator / denominator);\n }\n\n if (score > 0) {\n scores.set(docId, score);\n }\n }\n\n return Array.from(scores.entries())\n .sort((a, b) => b[1] - a[1])\n .slice(0, limit)\n .map(([id, score]) => {\n const metadata = this.documents.get(id)?.metadata;\n const result: BM25Result = { id, score };\n if (metadata !== undefined) {\n result.metadata = metadata;\n }\n return result;\n });\n }\n\n /**\n * Get document count\n */\n get size(): number {\n return this.documents.size;\n }\n\n /**\n * Clear the index\n */\n clear(): void {\n this.documents.clear();\n this.termFrequencies.clear();\n this.documentFrequencies.clear();\n this.documentLengths.clear();\n this.avgDocLength = 0;\n }\n\n /**\n * Serialize the index to JSON\n */\n serialize(): string {\n return JSON.stringify({\n documents: Array.from(this.documents.entries()),\n termFrequencies: Array.from(this.termFrequencies.entries()).map(([k, v]) => [k, Array.from(v.entries())]),\n documentFrequencies: Array.from(this.documentFrequencies.entries()),\n documentLengths: Array.from(this.documentLengths.entries()),\n avgDocLength: this.avgDocLength,\n });\n }\n\n /**\n * Load from serialized JSON\n */\n static deserialize(json: string): BM25Index {\n const data = JSON.parse(json);\n const index = new BM25Index();\n \n index.documents = new Map(data.documents);\n index.termFrequencies = new Map(data.termFrequencies.map(([k, v]: [string, [string, number][]]) => [k, new Map(v)]));\n index.documentFrequencies = new Map(data.documentFrequencies);\n index.documentLengths = new Map(data.documentLengths);\n index.avgDocLength = data.avgDocLength;\n \n return index;\n }\n\n private tokenize(text: string): string[] {\n return text\n .toLowerCase()\n .replace(/[^\\w\\s]/g, ' ')\n .split(/\\s+/)\n .filter(token => token.length > 2 && !this.isStopWord(token));\n }\n\n private isStopWord(word: string): boolean {\n const stopWords = new Set([\n 'the', 'be', 'to', 'of', 'and', 'a', 'in', 'that', 'have', 'i',\n 'it', 'for', 'not', 'on', 'with', 'he', 'as', 'you', 'do', 'at',\n 'this', 'but', 'his', 'by', 'from', 'they', 'we', 'say', 'her', 'she',\n 'or', 'an', 'will', 'my', 'one', 'all', 'would', 'there', 'their', 'what',\n 'so', 'up', 'out', 'if', 'about', 'who', 'get', 'which', 'go', 'me',\n 'when', 'make', 'can', 'like', 'time', 'no', 'just', 'him', 'know', 'take',\n 'into', 'year', 'your', 'some', 'could', 'them', 'see', 'other', 'than', 'then',\n 'now', 'look', 'only', 'come', 'its', 'over', 'also', 'back', 'after', 'use',\n 'two', 'how', 'our', 'first', 'way', 'even', 'new', 'want', 'because', 'any',\n 'these', 'give', 'day', 'most', 'us', 'should', 'been', 'has', 'was', 'are',\n ]);\n return stopWords.has(word);\n }\n\n private updateAvgDocLength(): void {\n if (this.documentLengths.size === 0) {\n this.avgDocLength = 0;\n return;\n }\n const total = Array.from(this.documentLengths.values()).reduce((a, b) => a + b, 0);\n this.avgDocLength = total / this.documentLengths.size;\n }\n}\n","/**\n * Memory Compactor\n * \n * Intelligently compacts old issues into summaries instead of deleting them.\n * Preserves patterns and insights while reducing storage.\n * \n * Phase 1 Hardening:\n * - Atomic writes to prevent corruption\n * - Backup rotation for recovery\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 type { StoredIssue } from './issue-store.js';\nimport { atomicWriteJSON } from '../utils/atomic-write.js';\nimport { BackupManager } from '../utils/backup-manager.js';\nimport { CompactedSummariesIndexSchema, safeParseAndValidate } from './validation.js';\n\nexport interface CompactedSummary {\n period: string;\n startDate: string;\n endDate: string;\n totalIssues: number;\n resolvedCount: number;\n bySeverity: Record<string, number>;\n byAgent: Record<string, number>;\n topPatterns: PatternSummary[];\n hotFiles: { file: string; count: number }[];\n compactedAt: string;\n}\n\nexport interface PatternSummary {\n pattern: string;\n count: number;\n severity: string;\n agent: string;\n exampleFix: string;\n}\n\n/**\n * Compact old issues into summaries\n * Returns the compacted summary and the remaining (recent) issues\n */\nexport async function compactOldIssues(\n issues: StoredIssue[],\n options: {\n keepDays?: number;\n minIssuesToCompact?: number;\n } = {}\n): Promise<{ summary: CompactedSummary | null; remaining: StoredIssue[] }> {\n const keepDays = options.keepDays ?? 30;\n const minIssues = options.minIssuesToCompact ?? 100;\n \n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - keepDays);\n \n const oldIssues = issues.filter(i => new Date(i.timestamp) < cutoffDate);\n const recentIssues = issues.filter(i => new Date(i.timestamp) >= cutoffDate);\n \n // Only compact if we have enough old issues\n if (oldIssues.length < minIssues) {\n return { summary: null, remaining: issues };\n }\n \n // Build summary\n const summary = buildSummary(oldIssues);\n \n return { summary, remaining: recentIssues };\n}\n\n/**\n * Build a summary from a set of issues\n */\nfunction buildSummary(issues: StoredIssue[]): CompactedSummary {\n const sorted = issues.sort((a, b) => \n new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()\n );\n \n const bySeverity: Record<string, number> = {};\n const byAgent: Record<string, number> = {};\n const patternMap: Map<string, { count: number; issue: StoredIssue }> = new Map();\n const fileCount: Map<string, number> = new Map();\n \n for (const issue of issues) {\n // Count by severity\n bySeverity[issue.severity] = (bySeverity[issue.severity] || 0) + 1;\n \n // Count by agent\n byAgent[issue.agent] = (byAgent[issue.agent] || 0) + 1;\n \n // Track patterns (normalized issue text)\n const patternKey = normalizePattern(issue.issue);\n const existing = patternMap.get(patternKey);\n if (existing) {\n existing.count++;\n } else {\n patternMap.set(patternKey, { count: 1, issue });\n }\n \n // Count files\n const fileName = issue.file.split('/').pop() || issue.file;\n fileCount.set(fileName, (fileCount.get(fileName) || 0) + 1);\n }\n \n // Get top patterns\n const topPatterns = Array.from(patternMap.entries())\n .sort((a, b) => b[1].count - a[1].count)\n .slice(0, 10)\n .map(([pattern, data]) => ({\n pattern: pattern.slice(0, 100),\n count: data.count,\n severity: data.issue.severity,\n agent: data.issue.agent,\n exampleFix: data.issue.fix.slice(0, 200),\n }));\n \n // Get hot files\n const hotFiles = Array.from(fileCount.entries())\n .sort((a, b) => b[1] - a[1])\n .slice(0, 10)\n .map(([file, count]) => ({ file, count }));\n \n return {\n period: `${sorted[0]?.timestamp.split('T')[0]} to ${sorted[sorted.length - 1]?.timestamp.split('T')[0]}`,\n startDate: sorted[0]?.timestamp || '',\n endDate: sorted[sorted.length - 1]?.timestamp || '',\n totalIssues: issues.length,\n resolvedCount: issues.filter(i => i.resolved).length,\n bySeverity,\n byAgent,\n topPatterns,\n hotFiles,\n compactedAt: new Date().toISOString(),\n };\n}\n\n/**\n * Normalize issue text for pattern matching\n */\nfunction normalizePattern(text: string): string {\n return text\n .toLowerCase()\n .replace(/`[^`]+`/g, 'CODE')\n .replace(/\\b\\d+\\b/g, 'N')\n .replace(/[\"']/g, '')\n .replace(/\\s+/g, ' ')\n .trim()\n .slice(0, 150);\n}\n\n/**\n * Save compacted summary to disk with atomic write and backup\n */\nexport async function saveCompactedSummary(\n summary: CompactedSummary,\n projectDir: string\n): Promise<void> {\n const memoryDir = join(getTrieDirectory(projectDir), 'memory');\n await mkdir(memoryDir, { recursive: true });\n \n const summaryPath = join(memoryDir, 'compacted-summaries.json');\n \n let summaries: CompactedSummary[] = [];\n try {\n if (existsSync(summaryPath)) {\n const content = await readFile(summaryPath, 'utf-8');\n const result = safeParseAndValidate(content, CompactedSummariesIndexSchema);\n if (result.success) {\n summaries = result.data as CompactedSummary[];\n }\n }\n } catch {\n summaries = [];\n }\n \n summaries.push(summary);\n \n // Keep only last 12 summaries (1 year of monthly summaries)\n if (summaries.length > 12) {\n summaries = summaries.slice(-12);\n }\n \n // Create backup before writing\n const backupManager = new BackupManager(summaryPath);\n await backupManager.createBackup();\n \n // Atomic write\n await atomicWriteJSON(summaryPath, summaries);\n}\n\n/**\n * Load compacted summaries with validation and auto-recovery\n */\nexport async function loadCompactedSummaries(projectDir: string): Promise<CompactedSummary[]> {\n const summaryPath = join(getTrieDirectory(projectDir), 'memory', 'compacted-summaries.json');\n \n try {\n if (existsSync(summaryPath)) {\n const content = await readFile(summaryPath, 'utf-8');\n const result = safeParseAndValidate(content, CompactedSummariesIndexSchema);\n \n if (result.success) {\n return result.data as CompactedSummary[];\n }\n \n // Validation failed - attempt recovery\n const backupManager = new BackupManager(summaryPath);\n if (await backupManager.recoverFromBackup()) {\n const recovered = await readFile(summaryPath, 'utf-8');\n const recoveredResult = safeParseAndValidate(recovered, CompactedSummariesIndexSchema);\n if (recoveredResult.success) {\n return recoveredResult.data as CompactedSummary[];\n }\n }\n }\n } catch {\n // File doesn't exist or recovery failed\n }\n \n return [];\n}\n\n/**\n * Generate a markdown summary of compacted history\n */\nexport function formatCompactedSummary(summary: CompactedSummary): string {\n const lines: string[] = [\n `## Compacted Summary: ${summary.period}`,\n '',\n `**Total Issues:** ${summary.totalIssues} (${summary.resolvedCount} resolved)`,\n '',\n '### By Severity',\n ...Object.entries(summary.bySeverity).map(([s, c]) => `- ${s}: ${c}`),\n '',\n '### Top Patterns',\n ...summary.topPatterns.slice(0, 5).map(p => \n `- **${p.pattern.slice(0, 50)}...** (${p.count}x, ${p.severity})`\n ),\n '',\n '### Hot Files',\n ...summary.hotFiles.slice(0, 5).map(f => `- ${f.file}: ${f.count} issues`),\n ];\n \n return lines.join('\\n');\n}\n\n/**\n * Get insights from compacted history\n */\nexport async function getHistoricalInsights(projectDir: string): Promise<{\n totalHistoricalIssues: number;\n recurringPatterns: PatternSummary[];\n improvementTrend: 'improving' | 'stable' | 'declining' | 'unknown';\n}> {\n const summaries = await loadCompactedSummaries(projectDir);\n \n if (summaries.length === 0) {\n return {\n totalHistoricalIssues: 0,\n recurringPatterns: [],\n improvementTrend: 'unknown',\n };\n }\n \n const totalHistoricalIssues = summaries.reduce((sum, s) => sum + s.totalIssues, 0);\n \n // Find patterns that appear across multiple summaries\n const patternCounts: Map<string, PatternSummary & { appearances: number }> = new Map();\n \n for (const summary of summaries) {\n for (const pattern of summary.topPatterns) {\n const key = pattern.pattern;\n const existing = patternCounts.get(key);\n if (existing) {\n existing.count += pattern.count;\n existing.appearances++;\n } else {\n patternCounts.set(key, { ...pattern, appearances: 1 });\n }\n }\n }\n \n const recurringPatterns = Array.from(patternCounts.values())\n .filter(p => p.appearances >= 2)\n .sort((a, b) => b.count - a.count)\n .slice(0, 5);\n \n // Calculate improvement trend\n let improvementTrend: 'improving' | 'stable' | 'declining' | 'unknown' = 'unknown';\n \n if (summaries.length >= 2) {\n const recent = summaries.slice(-2);\n const olderCount = recent[0]?.totalIssues || 0;\n const newerCount = recent[1]?.totalIssues || 0;\n \n if (newerCount < olderCount * 0.8) {\n improvementTrend = 'improving';\n } else if (newerCount > olderCount * 1.2) {\n improvementTrend = 'declining';\n } else {\n improvementTrend = 'stable';\n }\n }\n \n return {\n totalHistoricalIssues,\n recurringPatterns,\n improvementTrend,\n };\n}\n"],"mappings":"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","names":["mkdir","readFile","existsSync","join","join","mkdir","existsSync","readFile"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isInteractiveMode
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-JKEEQAG2.js";
|
|
4
4
|
|
|
5
5
|
// src/utils/workspace.ts
|
|
6
6
|
import { execSync } from "child_process";
|
|
@@ -176,8 +176,8 @@ function getWorkingDirectory(explicitDir, silent = false) {
|
|
|
176
176
|
console.error(" Or set DEBUG_TRIE_WORKSPACE=1 to debug workspace detection");
|
|
177
177
|
console.error(` Current working directory: ${cwd}`);
|
|
178
178
|
console.error(" Examples:");
|
|
179
|
-
console.error(' Use
|
|
180
|
-
console.error(' Use
|
|
179
|
+
console.error(' Use trie_fix with directory: "/path/to/your/project"');
|
|
180
|
+
console.error(' Use trie watch with directory: "./your-project"');
|
|
181
181
|
}
|
|
182
182
|
return cwd;
|
|
183
183
|
}
|
|
@@ -186,4 +186,4 @@ export {
|
|
|
186
186
|
getTrieDirectory,
|
|
187
187
|
getWorkingDirectory
|
|
188
188
|
};
|
|
189
|
-
//# sourceMappingURL=chunk-
|
|
189
|
+
//# sourceMappingURL=chunk-7F2R2ITA.js.map
|