@triedotdev/mcp 1.0.102 → 1.0.103
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/dist/{chunk-OVRG5RP3.js → chunk-33WL3D7A.js} +3 -5
- package/dist/{chunk-OVRG5RP3.js.map → chunk-33WL3D7A.js.map} +1 -1
- package/dist/{chunk-JDHR5BDR.js → chunk-6JPPYG7F.js} +928 -258
- package/dist/chunk-6JPPYG7F.js.map +1 -0
- package/dist/{chunk-M4JCQO5G.js → chunk-CKYU5JOD.js} +579 -114
- package/dist/chunk-CKYU5JOD.js.map +1 -0
- package/dist/{chunk-B3MNN3XB.js → chunk-HFKOGW7H.js} +6 -8
- package/dist/{chunk-B3MNN3XB.js.map → chunk-HFKOGW7H.js.map} +1 -1
- package/dist/chunk-HIKONDDO.js +26 -0
- package/dist/chunk-HIKONDDO.js.map +1 -0
- package/dist/chunk-M4YMTHGG.js +2822 -0
- package/dist/chunk-M4YMTHGG.js.map +1 -0
- package/dist/{chunk-NIASHOAB.js → chunk-SPQJC7RA.js} +5 -5
- package/dist/cli/main.js +16 -18
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/yolo-daemon.js +17 -64
- package/dist/cli/yolo-daemon.js.map +1 -1
- package/dist/{goal-manager-LAOT4QQX.js → goal-manager-AP4LTE6U.js} +3 -4
- package/dist/{guardian-agent-M352CBE5.js → guardian-agent-WB6LWRLM.js} +7 -8
- package/dist/index.js +41 -119
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
- package/dist/chunk-AE2XLMZC.js +0 -6152
- package/dist/chunk-AE2XLMZC.js.map +0 -1
- package/dist/chunk-CCI6LKXZ.js +0 -526
- package/dist/chunk-CCI6LKXZ.js.map +0 -1
- package/dist/chunk-JDHR5BDR.js.map +0 -1
- package/dist/chunk-M4JCQO5G.js.map +0 -1
- package/dist/chunk-R3I2GCZC.js +0 -682
- package/dist/chunk-R3I2GCZC.js.map +0 -1
- package/dist/issue-store-W2X33X2X.js +0 -28
- package/dist/issue-store-W2X33X2X.js.map +0 -1
- /package/dist/{chunk-NIASHOAB.js.map → chunk-SPQJC7RA.js.map} +0 -0
- /package/dist/{goal-manager-LAOT4QQX.js.map → goal-manager-AP4LTE6U.js.map} +0 -0
- /package/dist/{guardian-agent-M352CBE5.js.map → guardian-agent-WB6LWRLM.js.map} +0 -0
package/dist/chunk-CCI6LKXZ.js
DELETED
|
@@ -1,526 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getTrieDirectory,
|
|
3
|
-
getWorkingDirectory
|
|
4
|
-
} from "./chunk-R4AAPFXC.js";
|
|
5
|
-
|
|
6
|
-
// src/utils/project-info.ts
|
|
7
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
8
|
-
import { existsSync } from "fs";
|
|
9
|
-
import { join } from "path";
|
|
10
|
-
var PROJECT_MD_PATH = "PROJECT.md";
|
|
11
|
-
function getProjectTemplate() {
|
|
12
|
-
return `# Project Information
|
|
13
|
-
|
|
14
|
-
> This file stores important project context for AI assistants.
|
|
15
|
-
> Edit freely - this file is yours, not auto-generated.
|
|
16
|
-
> Available via MCP resource: \`trie://project\`
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## Project Overview
|
|
21
|
-
|
|
22
|
-
<!-- Describe your project's purpose and goals -->
|
|
23
|
-
|
|
24
|
-
[Add project description here]
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## Technology Stack
|
|
29
|
-
|
|
30
|
-
<!-- List frameworks, languages, databases, cloud services, etc. -->
|
|
31
|
-
|
|
32
|
-
- **Language:**
|
|
33
|
-
- **Framework:**
|
|
34
|
-
- **Database:**
|
|
35
|
-
- **Hosting:**
|
|
36
|
-
|
|
37
|
-
---
|
|
38
|
-
|
|
39
|
-
## Architecture
|
|
40
|
-
|
|
41
|
-
<!-- Key patterns, architectural decisions, and system design -->
|
|
42
|
-
|
|
43
|
-
[Describe your architecture here]
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## Coding Conventions
|
|
48
|
-
|
|
49
|
-
<!-- Style guidelines, naming conventions, patterns to follow -->
|
|
50
|
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## Environment
|
|
58
|
-
|
|
59
|
-
<!-- URLs, API endpoints, deployment info -->
|
|
60
|
-
|
|
61
|
-
| Environment | URL | Notes |
|
|
62
|
-
|-------------|-----|-------|
|
|
63
|
-
| Development | | |
|
|
64
|
-
| Staging | | |
|
|
65
|
-
| Production | | |
|
|
66
|
-
|
|
67
|
-
---
|
|
68
|
-
|
|
69
|
-
## Team
|
|
70
|
-
|
|
71
|
-
<!-- Ownership, contacts, responsibilities -->
|
|
72
|
-
|
|
73
|
-
- **Owner:**
|
|
74
|
-
- **Team:**
|
|
75
|
-
|
|
76
|
-
---
|
|
77
|
-
|
|
78
|
-
## Compliance
|
|
79
|
-
|
|
80
|
-
<!-- HIPAA, SOC2, GDPR, PCI-DSS requirements if applicable -->
|
|
81
|
-
|
|
82
|
-
- [ ] GDPR
|
|
83
|
-
- [ ] SOC2
|
|
84
|
-
- [ ] HIPAA
|
|
85
|
-
- [ ] PCI-DSS
|
|
86
|
-
|
|
87
|
-
---
|
|
88
|
-
|
|
89
|
-
## AI Instructions
|
|
90
|
-
|
|
91
|
-
<!-- Special instructions for AI assistants working on this project -->
|
|
92
|
-
|
|
93
|
-
When working on this project, AI assistants should:
|
|
94
|
-
|
|
95
|
-
1.
|
|
96
|
-
2.
|
|
97
|
-
3.
|
|
98
|
-
|
|
99
|
-
---
|
|
100
|
-
|
|
101
|
-
*This file is read by Trie agents and exposed via \`trie://project\` MCP resource.*
|
|
102
|
-
*Edit this file to provide context to Claude Code, Cursor, GitHub Actions, and other AI tools.*
|
|
103
|
-
`;
|
|
104
|
-
}
|
|
105
|
-
function projectInfoExists(workDir) {
|
|
106
|
-
const dir = workDir || getWorkingDirectory(void 0, true);
|
|
107
|
-
const projectPath = join(getTrieDirectory(dir), PROJECT_MD_PATH);
|
|
108
|
-
return existsSync(projectPath);
|
|
109
|
-
}
|
|
110
|
-
async function loadProjectInfo(workDir) {
|
|
111
|
-
const dir = workDir || getWorkingDirectory(void 0, true);
|
|
112
|
-
const projectPath = join(getTrieDirectory(dir), PROJECT_MD_PATH);
|
|
113
|
-
try {
|
|
114
|
-
if (!existsSync(projectPath)) {
|
|
115
|
-
return null;
|
|
116
|
-
}
|
|
117
|
-
return await readFile(projectPath, "utf-8");
|
|
118
|
-
} catch {
|
|
119
|
-
return null;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
async function saveProjectInfo(content, workDir) {
|
|
123
|
-
const dir = workDir || getWorkingDirectory(void 0, true);
|
|
124
|
-
const trieDir = getTrieDirectory(dir);
|
|
125
|
-
const projectPath = join(trieDir, PROJECT_MD_PATH);
|
|
126
|
-
await mkdir(trieDir, { recursive: true });
|
|
127
|
-
await writeFile(projectPath, content, "utf-8");
|
|
128
|
-
}
|
|
129
|
-
async function initProjectInfo(workDir) {
|
|
130
|
-
const dir = workDir || getWorkingDirectory(void 0, true);
|
|
131
|
-
const projectPath = join(getTrieDirectory(dir), PROJECT_MD_PATH);
|
|
132
|
-
if (existsSync(projectPath)) {
|
|
133
|
-
return { created: false, path: projectPath };
|
|
134
|
-
}
|
|
135
|
-
await saveProjectInfo(getProjectTemplate(), dir);
|
|
136
|
-
return { created: true, path: projectPath };
|
|
137
|
-
}
|
|
138
|
-
async function getProjectSection(sectionName, workDir) {
|
|
139
|
-
const content = await loadProjectInfo(workDir);
|
|
140
|
-
if (!content) return null;
|
|
141
|
-
const sectionRegex = new RegExp(
|
|
142
|
-
`## ${escapeRegex(sectionName)}\\s*\\n([\\s\\S]*?)(?=\\n## |\\n---\\s*$|$)`,
|
|
143
|
-
"i"
|
|
144
|
-
);
|
|
145
|
-
const match = content.match(sectionRegex);
|
|
146
|
-
if (match?.[1]) {
|
|
147
|
-
return match[1].trim();
|
|
148
|
-
}
|
|
149
|
-
return null;
|
|
150
|
-
}
|
|
151
|
-
async function updateProjectSection(sectionName, newContent, workDir) {
|
|
152
|
-
let content = await loadProjectInfo(workDir);
|
|
153
|
-
if (!content) {
|
|
154
|
-
await initProjectInfo(workDir);
|
|
155
|
-
content = await loadProjectInfo(workDir);
|
|
156
|
-
if (!content) return false;
|
|
157
|
-
}
|
|
158
|
-
const sectionRegex = new RegExp(
|
|
159
|
-
`(## ${escapeRegex(sectionName)}\\s*\\n)([\\s\\S]*?)((?=\\n## )|(?=\\n---\\s*$)|$)`,
|
|
160
|
-
"i"
|
|
161
|
-
);
|
|
162
|
-
if (content.match(sectionRegex)) {
|
|
163
|
-
const updatedContent = content.replace(sectionRegex, `$1
|
|
164
|
-
${newContent}
|
|
165
|
-
|
|
166
|
-
$3`);
|
|
167
|
-
await saveProjectInfo(updatedContent, workDir);
|
|
168
|
-
return true;
|
|
169
|
-
}
|
|
170
|
-
return false;
|
|
171
|
-
}
|
|
172
|
-
async function appendToSection(sectionName, contentToAdd, workDir) {
|
|
173
|
-
const currentContent = await getProjectSection(sectionName, workDir);
|
|
174
|
-
if (currentContent === null) return false;
|
|
175
|
-
const newContent = currentContent + "\n" + contentToAdd;
|
|
176
|
-
return updateProjectSection(sectionName, newContent, workDir);
|
|
177
|
-
}
|
|
178
|
-
async function getProjectSections(workDir) {
|
|
179
|
-
const content = await loadProjectInfo(workDir);
|
|
180
|
-
if (!content) return [];
|
|
181
|
-
const sectionRegex = /^## (.+)$/gm;
|
|
182
|
-
const sections = [];
|
|
183
|
-
let match;
|
|
184
|
-
while ((match = sectionRegex.exec(content)) !== null) {
|
|
185
|
-
if (match[1]) {
|
|
186
|
-
sections.push(match[1].trim());
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
return sections;
|
|
190
|
-
}
|
|
191
|
-
async function getProjectInfoStructured(workDir) {
|
|
192
|
-
const dir = workDir || getWorkingDirectory(void 0, true);
|
|
193
|
-
const projectPath = join(getTrieDirectory(dir), PROJECT_MD_PATH);
|
|
194
|
-
const content = await loadProjectInfo(dir);
|
|
195
|
-
if (!content) {
|
|
196
|
-
return {
|
|
197
|
-
exists: false,
|
|
198
|
-
path: projectPath,
|
|
199
|
-
sections: {},
|
|
200
|
-
raw: null
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
const sectionNames = await getProjectSections(dir);
|
|
204
|
-
const sections = {};
|
|
205
|
-
for (const name of sectionNames) {
|
|
206
|
-
const sectionContent = await getProjectSection(name, dir);
|
|
207
|
-
if (sectionContent) {
|
|
208
|
-
sections[name] = sectionContent;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
return {
|
|
212
|
-
exists: true,
|
|
213
|
-
path: projectPath,
|
|
214
|
-
sections,
|
|
215
|
-
raw: content
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
function escapeRegex(str) {
|
|
219
|
-
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// src/utils/context-state.ts
|
|
223
|
-
import { readFile as readFile2, mkdir as mkdir2 } from "fs/promises";
|
|
224
|
-
import { existsSync as existsSync2 } from "fs";
|
|
225
|
-
import { join as join2, basename } from "path";
|
|
226
|
-
var STATE_JSON_PATH = "state.json";
|
|
227
|
-
async function loadContextState() {
|
|
228
|
-
const workDir = getWorkingDirectory(void 0, true);
|
|
229
|
-
const statePath = join2(getTrieDirectory(workDir), STATE_JSON_PATH);
|
|
230
|
-
const defaults = getDefaultState();
|
|
231
|
-
try {
|
|
232
|
-
if (existsSync2(statePath)) {
|
|
233
|
-
const content = await readFile2(statePath, "utf-8");
|
|
234
|
-
const loaded = JSON.parse(content);
|
|
235
|
-
return {
|
|
236
|
-
...defaults,
|
|
237
|
-
...loaded,
|
|
238
|
-
skills: loaded.skills || defaults.skills
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
} catch {
|
|
242
|
-
}
|
|
243
|
-
return defaults;
|
|
244
|
-
}
|
|
245
|
-
function getDefaultState() {
|
|
246
|
-
return {
|
|
247
|
-
lastScan: null,
|
|
248
|
-
healthScore: 0,
|
|
249
|
-
activePriorities: [
|
|
250
|
-
"Initial setup required - run first scan with `trie scan`",
|
|
251
|
-
"Configure agents in `.trie/config.json`",
|
|
252
|
-
"Set up CI/CD integration"
|
|
253
|
-
],
|
|
254
|
-
contextSignals: {},
|
|
255
|
-
agentStatus: {},
|
|
256
|
-
scanHistory: [],
|
|
257
|
-
customAgents: [],
|
|
258
|
-
skills: {},
|
|
259
|
-
environment: detectEnvironment()
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
function detectEnvironment() {
|
|
263
|
-
if (process.env.GITHUB_ACTIONS) return "github-actions";
|
|
264
|
-
if (process.env.GITLAB_CI) return "gitlab-ci";
|
|
265
|
-
if (process.env.CI) return "ci";
|
|
266
|
-
const parent = process.env._ || "";
|
|
267
|
-
if (parent.includes("cursor")) return "cursor";
|
|
268
|
-
if (parent.includes("claude")) return "claude-code";
|
|
269
|
-
return "cli";
|
|
270
|
-
}
|
|
271
|
-
async function getContextForAI() {
|
|
272
|
-
const state = await loadContextState();
|
|
273
|
-
const workDir = getWorkingDirectory(void 0, true);
|
|
274
|
-
const lines = [];
|
|
275
|
-
if (projectInfoExists(workDir)) {
|
|
276
|
-
const projectInfo = await loadProjectInfo(workDir);
|
|
277
|
-
if (projectInfo) {
|
|
278
|
-
lines.push(projectInfo);
|
|
279
|
-
lines.push("");
|
|
280
|
-
lines.push("---");
|
|
281
|
-
lines.push("");
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
lines.push(
|
|
285
|
-
"## Trie Scan Context",
|
|
286
|
-
"",
|
|
287
|
-
`**Health Score:** ${state.healthScore}%`,
|
|
288
|
-
`**Last Scan:** ${state.lastScan ? new Date(state.lastScan.timestamp).toLocaleString() : "Never"}`,
|
|
289
|
-
"",
|
|
290
|
-
"**Active Priorities:**",
|
|
291
|
-
...state.activePriorities.map((p) => `- ${p}`),
|
|
292
|
-
""
|
|
293
|
-
);
|
|
294
|
-
if (state.lastScan) {
|
|
295
|
-
lines.push(
|
|
296
|
-
"**Recent Issues:**",
|
|
297
|
-
`- Critical: ${state.lastScan.issues.critical}`,
|
|
298
|
-
`- Serious: ${state.lastScan.issues.serious}`,
|
|
299
|
-
`- Moderate: ${state.lastScan.issues.moderate}`,
|
|
300
|
-
`- Low: ${state.lastScan.issues.low}`,
|
|
301
|
-
""
|
|
302
|
-
);
|
|
303
|
-
if (state.lastScan.hotFiles.length > 0) {
|
|
304
|
-
lines.push(
|
|
305
|
-
"**Hot Files (most issues):**",
|
|
306
|
-
...state.lastScan.hotFiles.slice(0, 5).map((f) => `- ${f.file}: ${f.issueCount} issues`),
|
|
307
|
-
""
|
|
308
|
-
);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
return lines.join("\n");
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// src/utils/trie-init.ts
|
|
315
|
-
import { existsSync as existsSync3 } from "fs";
|
|
316
|
-
import { join as join3 } from "path";
|
|
317
|
-
var INIT_MARKERS = [
|
|
318
|
-
"PROJECT.md",
|
|
319
|
-
"RULES.md",
|
|
320
|
-
"TEAM.md",
|
|
321
|
-
"BOOTSTRAP.md",
|
|
322
|
-
"AGENTS.md",
|
|
323
|
-
"config.json"
|
|
324
|
-
];
|
|
325
|
-
function isTrieInitialized(workDir) {
|
|
326
|
-
const dir = workDir || getWorkingDirectory(void 0, true);
|
|
327
|
-
const trieDir = getTrieDirectory(dir);
|
|
328
|
-
return INIT_MARKERS.some((marker) => existsSync3(join3(trieDir, marker)));
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// src/skills/audit-logger.ts
|
|
332
|
-
function formatAuditLog(_entry) {
|
|
333
|
-
return "Audit logging has been integrated into the decision ledger";
|
|
334
|
-
}
|
|
335
|
-
function getAuditStatistics() {
|
|
336
|
-
return {
|
|
337
|
-
totalScans: 0,
|
|
338
|
-
totalIssues: 0,
|
|
339
|
-
criticalCount: 0,
|
|
340
|
-
seriousCount: 0,
|
|
341
|
-
moderateCount: 0,
|
|
342
|
-
lowCount: 0,
|
|
343
|
-
totalExecutions: 0,
|
|
344
|
-
successfulExecutions: 0,
|
|
345
|
-
failedExecutions: 0,
|
|
346
|
-
uniqueSkills: 0,
|
|
347
|
-
totalCommands: 0,
|
|
348
|
-
blockedCommands: 0,
|
|
349
|
-
totalNetworkCalls: 0,
|
|
350
|
-
blockedNetworkCalls: 0
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
function createAuditEntry(skillName, skillSource, triggeredBy, targetPath) {
|
|
354
|
-
return {
|
|
355
|
-
skillName,
|
|
356
|
-
skillSource,
|
|
357
|
-
triggeredBy,
|
|
358
|
-
targetPath,
|
|
359
|
-
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
360
|
-
commands: []
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
|
-
function completeAuditEntry(entry, success, error) {
|
|
364
|
-
const result = {
|
|
365
|
-
...entry,
|
|
366
|
-
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
367
|
-
success
|
|
368
|
-
};
|
|
369
|
-
if (error !== void 0) {
|
|
370
|
-
result.error = error;
|
|
371
|
-
}
|
|
372
|
-
return result;
|
|
373
|
-
}
|
|
374
|
-
async function logSkillExecution(_execution) {
|
|
375
|
-
}
|
|
376
|
-
async function getRecentAuditLogs(_limit = 10) {
|
|
377
|
-
return [];
|
|
378
|
-
}
|
|
379
|
-
async function getSkillAuditLogs(_skillName) {
|
|
380
|
-
return [];
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// src/utils/command-runner.ts
|
|
384
|
-
import { exec, execFile, execSync } from "child_process";
|
|
385
|
-
import { promisify } from "util";
|
|
386
|
-
var execAsync = promisify(exec);
|
|
387
|
-
var execFileAsync = promisify(execFile);
|
|
388
|
-
function redact(text) {
|
|
389
|
-
return text.replace(/\b(AWS|ANTHROPIC|OPENAI|GITHUB)_[A-Z0-9_]*\s*=\s*([^\s"'`]+)/gi, "$1_<REDACTED>=<REDACTED>").replace(/\bBearer\s+[A-Za-z0-9\-._~+/]+=*\b/g, "Bearer <REDACTED>").replace(/\bghp_[A-Za-z0-9]{20,}\b/g, "ghp_<REDACTED>").replace(/\b(?:xox[baprs]-)[A-Za-z0-9-]{10,}\b/g, "<REDACTED_SLACK_TOKEN>").replace(/\bAKIA[0-9A-Z]{16}\b/g, "AKIA<REDACTED>");
|
|
390
|
-
}
|
|
391
|
-
function clampOutput(text, maxChars) {
|
|
392
|
-
if (text.length <= maxChars) return text;
|
|
393
|
-
return text.slice(0, maxChars) + `
|
|
394
|
-
\u2026(truncated ${text.length - maxChars} chars)`;
|
|
395
|
-
}
|
|
396
|
-
function buildCommandRecord(command) {
|
|
397
|
-
return {
|
|
398
|
-
command,
|
|
399
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
400
|
-
};
|
|
401
|
-
}
|
|
402
|
-
async function finalizeAndWrite(entry, cmd, outcome, options) {
|
|
403
|
-
const duration = Date.now() - outcome.startedAt;
|
|
404
|
-
cmd.duration = duration;
|
|
405
|
-
if (outcome.exitCode !== void 0) {
|
|
406
|
-
cmd.exitCode = outcome.exitCode;
|
|
407
|
-
}
|
|
408
|
-
const captureOutput = options?.captureOutput ?? false;
|
|
409
|
-
const redactOutput = options?.redactOutput ?? true;
|
|
410
|
-
const maxOutputChars = options?.maxOutputChars ?? 2e3;
|
|
411
|
-
if (captureOutput) {
|
|
412
|
-
const out = outcome.stdout ?? "";
|
|
413
|
-
const err = outcome.stderr ?? "";
|
|
414
|
-
cmd.stdout = redactOutput ? redact(clampOutput(out, maxOutputChars)) : clampOutput(out, maxOutputChars);
|
|
415
|
-
cmd.stderr = redactOutput ? redact(clampOutput(err, maxOutputChars)) : clampOutput(err, maxOutputChars);
|
|
416
|
-
}
|
|
417
|
-
const completed = completeAuditEntry(entry, outcome.success, outcome.error);
|
|
418
|
-
await logSkillExecution(completed);
|
|
419
|
-
}
|
|
420
|
-
async function runShellCommand(command, audit, options) {
|
|
421
|
-
const startedAt = Date.now();
|
|
422
|
-
const entry = createAuditEntry(audit.actor, audit.source ?? "trie", audit.triggeredBy, audit.targetPath);
|
|
423
|
-
const cmd = buildCommandRecord(command);
|
|
424
|
-
entry.commands?.push(cmd);
|
|
425
|
-
try {
|
|
426
|
-
const { stdout, stderr } = await execAsync(command, {
|
|
427
|
-
cwd: options?.cwd,
|
|
428
|
-
timeout: options?.timeoutMs,
|
|
429
|
-
maxBuffer: options?.maxBuffer
|
|
430
|
-
});
|
|
431
|
-
await finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout, stderr, startedAt }, options);
|
|
432
|
-
return { stdout: stdout ?? "", stderr: stderr ?? "", exitCode: 0 };
|
|
433
|
-
} catch (e) {
|
|
434
|
-
const err = e;
|
|
435
|
-
const stdout = typeof err.stdout === "string" ? err.stdout : "";
|
|
436
|
-
const stderr = typeof err.stderr === "string" ? err.stderr : "";
|
|
437
|
-
const exitCode = typeof err.code === "number" ? err.code : 1;
|
|
438
|
-
await finalizeAndWrite(
|
|
439
|
-
entry,
|
|
440
|
-
cmd,
|
|
441
|
-
{ success: false, exitCode, stdout, stderr, error: err.message, startedAt },
|
|
442
|
-
// Capture output for failures by default (so audits are useful)
|
|
443
|
-
{ ...options, captureOutput: options?.captureOutput ?? true }
|
|
444
|
-
);
|
|
445
|
-
return { stdout, stderr, exitCode };
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
function runShellCommandSync(command, audit, options) {
|
|
449
|
-
const startedAt = Date.now();
|
|
450
|
-
const entry = createAuditEntry(audit.actor, audit.source ?? "trie", audit.triggeredBy, audit.targetPath);
|
|
451
|
-
const cmd = buildCommandRecord(command);
|
|
452
|
-
entry.commands?.push(cmd);
|
|
453
|
-
try {
|
|
454
|
-
const stdout = execSync(command, {
|
|
455
|
-
cwd: options?.cwd,
|
|
456
|
-
timeout: options?.timeoutMs,
|
|
457
|
-
maxBuffer: options?.maxBuffer,
|
|
458
|
-
encoding: "utf-8",
|
|
459
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
460
|
-
});
|
|
461
|
-
void finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout, stderr: "", startedAt }, options);
|
|
462
|
-
return { stdout: stdout ?? "", exitCode: 0 };
|
|
463
|
-
} catch (e) {
|
|
464
|
-
const err = e;
|
|
465
|
-
const stdout = typeof err.stdout === "string" ? err.stdout : "";
|
|
466
|
-
const stderr = typeof err.stderr === "string" ? err.stderr : "";
|
|
467
|
-
const exitCode = typeof err.status === "number" ? err.status : 1;
|
|
468
|
-
void finalizeAndWrite(
|
|
469
|
-
entry,
|
|
470
|
-
cmd,
|
|
471
|
-
{ success: false, exitCode, stdout, stderr, error: err.message, startedAt },
|
|
472
|
-
{ ...options, captureOutput: options?.captureOutput ?? true }
|
|
473
|
-
);
|
|
474
|
-
return { stdout, exitCode };
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
async function runExecFile(file, args, audit, options) {
|
|
478
|
-
const startedAt = Date.now();
|
|
479
|
-
const command = [file, ...args].join(" ");
|
|
480
|
-
const entry = createAuditEntry(audit.actor, audit.source ?? "trie", audit.triggeredBy, audit.targetPath);
|
|
481
|
-
const cmd = buildCommandRecord(command);
|
|
482
|
-
entry.commands?.push(cmd);
|
|
483
|
-
try {
|
|
484
|
-
const { stdout, stderr } = await execFileAsync(file, args, {
|
|
485
|
-
cwd: options?.cwd,
|
|
486
|
-
timeout: options?.timeoutMs,
|
|
487
|
-
maxBuffer: options?.maxBuffer
|
|
488
|
-
});
|
|
489
|
-
await finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout: String(stdout ?? ""), stderr: String(stderr ?? ""), startedAt }, options);
|
|
490
|
-
return { stdout: String(stdout ?? ""), stderr: String(stderr ?? ""), exitCode: 0 };
|
|
491
|
-
} catch (e) {
|
|
492
|
-
const err = e;
|
|
493
|
-
const stdout = typeof err.stdout === "string" ? err.stdout : "";
|
|
494
|
-
const stderr = typeof err.stderr === "string" ? err.stderr : "";
|
|
495
|
-
const exitCode = typeof err.code === "number" ? err.code : 1;
|
|
496
|
-
await finalizeAndWrite(
|
|
497
|
-
entry,
|
|
498
|
-
cmd,
|
|
499
|
-
{ success: false, exitCode, stdout, stderr, error: err.message, startedAt },
|
|
500
|
-
{ ...options, captureOutput: options?.captureOutput ?? true }
|
|
501
|
-
);
|
|
502
|
-
return { stdout, stderr, exitCode };
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
export {
|
|
507
|
-
formatAuditLog,
|
|
508
|
-
getAuditStatistics,
|
|
509
|
-
getRecentAuditLogs,
|
|
510
|
-
getSkillAuditLogs,
|
|
511
|
-
runShellCommand,
|
|
512
|
-
runShellCommandSync,
|
|
513
|
-
runExecFile,
|
|
514
|
-
projectInfoExists,
|
|
515
|
-
loadProjectInfo,
|
|
516
|
-
initProjectInfo,
|
|
517
|
-
getProjectSection,
|
|
518
|
-
updateProjectSection,
|
|
519
|
-
appendToSection,
|
|
520
|
-
getProjectSections,
|
|
521
|
-
getProjectInfoStructured,
|
|
522
|
-
loadContextState,
|
|
523
|
-
getContextForAI,
|
|
524
|
-
isTrieInitialized
|
|
525
|
-
};
|
|
526
|
-
//# sourceMappingURL=chunk-CCI6LKXZ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/project-info.ts","../src/utils/context-state.ts","../src/utils/trie-init.ts","../src/skills/audit-logger.ts","../src/utils/command-runner.ts"],"sourcesContent":["/**\n * Project Info Manager\n * \n * Manages the .trie/PROJECT.md file that stores user-defined project context.\n * Unlike AGENTS.md (auto-generated), PROJECT.md is fully user-controlled.\n */\n\nimport { readFile, writeFile, mkdir } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { getWorkingDirectory, getTrieDirectory } from './workspace.js';\n\nconst PROJECT_MD_PATH = 'PROJECT.md';\n\n/**\n * Default PROJECT.md template\n */\nexport function getProjectTemplate(): string {\n return `# Project Information\n\n> This file stores important project context for AI assistants.\n> Edit freely - this file is yours, not auto-generated.\n> Available via MCP resource: \\`trie://project\\`\n\n---\n\n## Project Overview\n\n<!-- Describe your project's purpose and goals -->\n\n[Add project description here]\n\n---\n\n## Technology Stack\n\n<!-- List frameworks, languages, databases, cloud services, etc. -->\n\n- **Language:** \n- **Framework:** \n- **Database:** \n- **Hosting:** \n\n---\n\n## Architecture\n\n<!-- Key patterns, architectural decisions, and system design -->\n\n[Describe your architecture here]\n\n---\n\n## Coding Conventions\n\n<!-- Style guidelines, naming conventions, patterns to follow -->\n\n- \n- \n- \n\n---\n\n## Environment\n\n<!-- URLs, API endpoints, deployment info -->\n\n| Environment | URL | Notes |\n|-------------|-----|-------|\n| Development | | |\n| Staging | | |\n| Production | | |\n\n---\n\n## Team\n\n<!-- Ownership, contacts, responsibilities -->\n\n- **Owner:** \n- **Team:** \n\n---\n\n## Compliance\n\n<!-- HIPAA, SOC2, GDPR, PCI-DSS requirements if applicable -->\n\n- [ ] GDPR\n- [ ] SOC2\n- [ ] HIPAA\n- [ ] PCI-DSS\n\n---\n\n## AI Instructions\n\n<!-- Special instructions for AI assistants working on this project -->\n\nWhen working on this project, AI assistants should:\n\n1. \n2. \n3. \n\n---\n\n*This file is read by Trie agents and exposed via \\`trie://project\\` MCP resource.*\n*Edit this file to provide context to Claude Code, Cursor, GitHub Actions, and other AI tools.*\n`;\n}\n\n/**\n * Check if PROJECT.md exists\n */\nexport function projectInfoExists(workDir?: string): boolean {\n const dir = workDir || getWorkingDirectory(undefined, true);\n const projectPath = join(getTrieDirectory(dir), PROJECT_MD_PATH);\n return existsSync(projectPath);\n}\n\n/**\n * Load PROJECT.md content\n */\nexport async function loadProjectInfo(workDir?: string): Promise<string | null> {\n const dir = workDir || getWorkingDirectory(undefined, true);\n const projectPath = join(getTrieDirectory(dir), PROJECT_MD_PATH);\n \n try {\n if (!existsSync(projectPath)) {\n return null;\n }\n return await readFile(projectPath, 'utf-8');\n } catch {\n return null;\n }\n}\n\n/**\n * Save PROJECT.md content\n */\nexport async function saveProjectInfo(content: string, workDir?: string): Promise<void> {\n const dir = workDir || getWorkingDirectory(undefined, true);\n const trieDir = getTrieDirectory(dir);\n const projectPath = join(trieDir, PROJECT_MD_PATH);\n \n // Ensure .trie directory exists\n await mkdir(trieDir, { recursive: true });\n \n await writeFile(projectPath, content, 'utf-8');\n}\n\n/**\n * Initialize PROJECT.md with template\n */\nexport async function initProjectInfo(workDir?: string): Promise<{ created: boolean; path: string }> {\n const dir = workDir || getWorkingDirectory(undefined, true);\n const projectPath = join(getTrieDirectory(dir), PROJECT_MD_PATH);\n \n if (existsSync(projectPath)) {\n return { created: false, path: projectPath };\n }\n \n await saveProjectInfo(getProjectTemplate(), dir);\n return { created: true, path: projectPath };\n}\n\n/**\n * Get a specific section from PROJECT.md\n */\nexport async function getProjectSection(sectionName: string, workDir?: string): Promise<string | null> {\n const content = await loadProjectInfo(workDir);\n if (!content) return null;\n \n // Find section by header\n const sectionRegex = new RegExp(\n `## ${escapeRegex(sectionName)}\\\\s*\\\\n([\\\\s\\\\S]*?)(?=\\\\n## |\\\\n---\\\\s*$|$)`,\n 'i'\n );\n \n const match = content.match(sectionRegex);\n if (match?.[1]) {\n return match[1].trim();\n }\n \n return null;\n}\n\n/**\n * Update a specific section in PROJECT.md\n */\nexport async function updateProjectSection(\n sectionName: string, \n newContent: string, \n workDir?: string\n): Promise<boolean> {\n let content = await loadProjectInfo(workDir);\n \n if (!content) {\n // Initialize with template first\n await initProjectInfo(workDir);\n content = await loadProjectInfo(workDir);\n if (!content) return false;\n }\n \n // Find and replace section content\n const sectionRegex = new RegExp(\n `(## ${escapeRegex(sectionName)}\\\\s*\\\\n)([\\\\s\\\\S]*?)((?=\\\\n## )|(?=\\\\n---\\\\s*$)|$)`,\n 'i'\n );\n \n if (content.match(sectionRegex)) {\n const updatedContent = content.replace(sectionRegex, `$1\\n${newContent}\\n\\n$3`);\n await saveProjectInfo(updatedContent, workDir);\n return true;\n }\n \n return false;\n}\n\n/**\n * Append content to a section\n */\nexport async function appendToSection(\n sectionName: string,\n contentToAdd: string,\n workDir?: string\n): Promise<boolean> {\n const currentContent = await getProjectSection(sectionName, workDir);\n if (currentContent === null) return false;\n \n const newContent = currentContent + '\\n' + contentToAdd;\n return updateProjectSection(sectionName, newContent, workDir);\n}\n\n/**\n * Get all section names from PROJECT.md\n */\nexport async function getProjectSections(workDir?: string): Promise<string[]> {\n const content = await loadProjectInfo(workDir);\n if (!content) return [];\n \n const sectionRegex = /^## (.+)$/gm;\n const sections: string[] = [];\n let match;\n \n while ((match = sectionRegex.exec(content)) !== null) {\n if (match[1]) {\n sections.push(match[1].trim());\n }\n }\n \n return sections;\n}\n\n/**\n * Get project info as structured data (for JSON responses)\n */\nexport async function getProjectInfoStructured(workDir?: string): Promise<{\n exists: boolean;\n path: string;\n sections: Record<string, string>;\n raw: string | null;\n}> {\n const dir = workDir || getWorkingDirectory(undefined, true);\n const projectPath = join(getTrieDirectory(dir), PROJECT_MD_PATH);\n const content = await loadProjectInfo(dir);\n \n if (!content) {\n return {\n exists: false,\n path: projectPath,\n sections: {},\n raw: null,\n };\n }\n \n const sectionNames = await getProjectSections(dir);\n const sections: Record<string, string> = {};\n \n for (const name of sectionNames) {\n const sectionContent = await getProjectSection(name, dir);\n if (sectionContent) {\n sections[name] = sectionContent;\n }\n }\n \n return {\n exists: true,\n path: projectPath,\n sections,\n raw: content,\n };\n}\n\n/**\n * Escape special regex characters\n */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","/**\n * Context State Manager\n * \n * Manages the .trie/AGENTS.md file that provides context to AI coding assistants.\n * Updates automatically when agents run to keep context current.\n * Also integrates with issue memory and cross-project tracking.\n * \n * Phase 1 Hardening:\n * - Atomic writes to prevent corruption\n */\n\nimport { readFile, mkdir } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join, basename } from 'path';\nimport { getWorkingDirectory, getTrieDirectory } from './workspace.js';\nimport type { AgentResult } from '../types/index.js';\nimport type { SkillRecord } from '../types/external-skill.js';\nimport { loadProjectInfo, projectInfoExists } from './project-info.js';\nimport { storeIssues, autoResolveIssues, getIssueHash } from '../memory/issue-store.js';\nimport { recordToGlobalMemory, updateGlobalMemoryMd } from '../memory/global-memory.js';\nimport { atomicWriteJSON, atomicWriteFile } from './atomic-write.js';\n\nexport interface ScanSummary {\n timestamp: string;\n agents: string[];\n filesScanned: number;\n issues: {\n critical: number;\n serious: number;\n moderate: number;\n low: number;\n total: number;\n };\n duration: number;\n hotFiles: Array<{ file: string; issueCount: number }>;\n}\n\nexport interface ContextState {\n lastScan: ScanSummary | null;\n healthScore: number;\n activePriorities: string[];\n contextSignals: Record<string, boolean>;\n agentStatus: Record<string, {\n lastRun: string | null;\n issuesFound: number;\n skillsApplied?: string[];\n }>;\n scanHistory: ScanSummary[];\n customAgents: string[];\n skills: Record<string, SkillRecord>;\n environment?: string;\n}\n\nconst AGENTS_MD_PATH = 'AGENTS.md';\nconst STATE_JSON_PATH = 'state.json';\n\n/**\n * Load current context state\n */\nexport async function loadContextState(): Promise<ContextState> {\n const workDir = getWorkingDirectory(undefined, true);\n const statePath = join(getTrieDirectory(workDir), STATE_JSON_PATH);\n const defaults = getDefaultState();\n \n try {\n if (existsSync(statePath)) {\n const content = await readFile(statePath, 'utf-8');\n const loaded = JSON.parse(content);\n // Merge with defaults to ensure new fields exist\n return {\n ...defaults,\n ...loaded,\n skills: loaded.skills || defaults.skills,\n };\n }\n } catch {\n // Return default state\n }\n \n return defaults;\n}\n\n/**\n * Save context state using atomic write\n */\nexport async function saveContextState(state: ContextState): Promise<void> {\n const workDir = getWorkingDirectory(undefined, true);\n const trieDir = getTrieDirectory(workDir);\n const statePath = join(trieDir, STATE_JSON_PATH);\n \n // Ensure directory exists\n await mkdir(trieDir, { recursive: true });\n \n // Use atomic write to prevent corruption\n await atomicWriteJSON(statePath, state);\n}\n\n/**\n * Update context state after a scan\n */\nexport async function updateContextAfterScan(\n results: AgentResult[],\n filesScanned: number,\n contextSignals: Record<string, boolean>,\n duration: number,\n scannedFiles?: string[]\n): Promise<void> {\n const state = await loadContextState();\n const workDir = getWorkingDirectory(undefined, true);\n const now = new Date().toISOString();\n \n // Calculate issue counts\n const allIssues = results.flatMap(r => r.issues);\n const issueCounts = {\n critical: allIssues.filter(i => i.severity === 'critical').length,\n serious: allIssues.filter(i => i.severity === 'serious').length,\n moderate: allIssues.filter(i => i.severity === 'moderate').length,\n low: allIssues.filter(i => i.severity === 'low').length,\n total: allIssues.length,\n };\n \n // Find hot files\n const fileIssueMap = new Map<string, number>();\n for (const issue of allIssues) {\n const count = fileIssueMap.get(issue.file) || 0;\n fileIssueMap.set(issue.file, count + 1);\n }\n const hotFiles = Array.from(fileIssueMap.entries())\n .sort((a, b) => b[1] - a[1])\n .slice(0, 10)\n .map(([file, issueCount]) => ({ file, issueCount }));\n \n // Create scan summary\n const scanSummary: ScanSummary = {\n timestamp: now,\n agents: results.map(r => r.agent),\n filesScanned,\n issues: issueCounts,\n duration,\n hotFiles,\n };\n \n // Update agent status\n for (const result of results) {\n state.agentStatus[result.agent] = {\n lastRun: now,\n issuesFound: result.issues.length,\n };\n }\n \n // Calculate health score (0-100)\n // Penalize critical issues heavily, serious issues moderately\n const criticalPenalty = issueCounts.critical * 25;\n const seriousPenalty = issueCounts.serious * 10;\n const moderatePenalty = issueCounts.moderate * 3;\n const lowPenalty = issueCounts.low * 1;\n const totalPenalty = Math.min(100, criticalPenalty + seriousPenalty + moderatePenalty + lowPenalty);\n state.healthScore = Math.max(0, 100 - totalPenalty);\n \n // Update priorities based on issues\n state.activePriorities = generatePriorities(issueCounts, contextSignals);\n \n // Update context signals\n state.contextSignals = { ...state.contextSignals, ...contextSignals };\n \n // Update scan history (keep last 20)\n state.scanHistory = [scanSummary, ...state.scanHistory.slice(0, 19)];\n state.lastScan = scanSummary;\n \n // Save state\n await saveContextState(state);\n \n // Update AGENTS.md\n await updateAgentsMd(state);\n \n // Store issues to memory\n const projectName = basename(workDir);\n if (allIssues.length > 0) {\n try {\n await storeIssues(allIssues, projectName, workDir);\n await recordToGlobalMemory(allIssues, projectName, workDir, state.healthScore);\n await updateGlobalMemoryMd();\n } catch {\n // Memory storage is non-critical, don't fail the scan\n }\n }\n \n // Auto-resolve issues that are no longer detected in scanned files\n if (scannedFiles && scannedFiles.length > 0) {\n try {\n // Build set of hashes from current scan\n const currentHashes = new Set(allIssues.map(issue => getIssueHash(issue)));\n const { resolved } = await autoResolveIssues(currentHashes, scannedFiles, workDir);\n if (resolved > 0) {\n // Log auto-resolution in non-interactive mode\n const { isInteractiveMode } = await import('./progress.js');\n if (!isInteractiveMode()) {\n console.error(` ✓ Auto-resolved ${resolved} issue${resolved > 1 ? 's' : ''} no longer detected`);\n }\n }\n } catch {\n // Auto-resolution is non-critical\n }\n }\n}\n\n/**\n * Update the AGENTS.md file with current state\n */\nasync function updateAgentsMd(state: ContextState): Promise<void> {\n const workDir = getWorkingDirectory(undefined, true);\n const mdPath = join(getTrieDirectory(workDir), AGENTS_MD_PATH);\n \n let content: string;\n try {\n content = await readFile(mdPath, 'utf-8');\n } catch {\n // Use template if file doesn't exist\n content = getAgentsMdTemplate();\n }\n \n // Update sections\n content = updateSection(content, 'Project State', generateProjectStateTable(state));\n content = updateSection(content, 'Active Priorities', generatePrioritiesList(state));\n content = updateSection(content, 'Agent Status', generateAgentStatusTable(state));\n content = updateSection(content, 'Recent Scan History', generateScanHistoryTable(state));\n content = updateSection(content, 'Context Signals Detected', generateContextSignals(state));\n content = updateSection(content, 'Risk Assessment', generateRiskAssessment(state));\n content = updateSection(content, 'Hot Files', generateHotFilesSection(state));\n \n // Update last updated timestamp\n content = content.replace(\n /Last updated:.*$/m,\n `Last updated: ${new Date().toISOString()}`\n );\n \n // Use atomic write to prevent corruption\n await atomicWriteFile(mdPath, content);\n}\n\n/**\n * Update a specific section in the markdown\n */\nfunction updateSection(content: string, sectionName: string, newContent: string): string {\n // Look for the section header and replace content until the next section\n const sectionRegex = new RegExp(\n `(### ${sectionName}[\\\\s\\\\S]*?)(?=###|---|\\n## |$)`,\n 'g'\n );\n \n const replacement = `### ${sectionName}\\n${newContent}\\n\\n`;\n \n if (content.match(sectionRegex)) {\n return content.replace(sectionRegex, replacement);\n }\n \n // Section doesn't exist, don't add it\n return content;\n}\n\n/**\n * Generate the project state table\n */\nfunction generateProjectStateTable(state: ContextState): string {\n const lastScan = state.lastScan;\n const lastScanDate = lastScan ? new Date(lastScan.timestamp).toLocaleString() : 'Never';\n const criticalCount = lastScan?.issues.critical ?? 0;\n const totalTasks = lastScan?.issues.total ?? 0;\n \n return `| Metric | Value | Updated |\n|--------|-------|---------|\n| Last Scan | ${lastScanDate} | ${lastScan ? 'Auto' : '-'} |\n| Critical Issues | ${criticalCount} | ${lastScan ? 'Auto' : '-'} |\n| Open Tasks | ${totalTasks} | ${lastScan ? 'Auto' : '-'} |\n| Health Score | ${state.healthScore}% | ${lastScan ? 'Auto' : '-'} |`;\n}\n\n/**\n * Generate priorities list\n */\nfunction generatePrioritiesList(state: ContextState): string {\n if (state.activePriorities.length === 0) {\n return '_No active priorities. Run a scan to identify issues._';\n }\n \n return state.activePriorities\n .map((p, i) => `${i + 1}. ${p}`)\n .join('\\n');\n}\n\n/**\n * Generate priorities based on scan results\n */\nfunction generatePriorities(\n issues: { critical: number; serious: number; moderate: number; low: number },\n contextSignals: Record<string, boolean>\n): string[] {\n const priorities: string[] = [];\n \n if (issues.critical > 0) {\n priorities.push(`Fix ${issues.critical} critical security issue${issues.critical > 1 ? 's' : ''} immediately`);\n }\n \n if (issues.serious > 0) {\n priorities.push(`Address ${issues.serious} serious issue${issues.serious > 1 ? 's' : ''} before deployment`);\n }\n \n if (contextSignals.touchesAuth && issues.critical === 0) {\n priorities.push('Auth code reviewed - continue monitoring');\n }\n \n if (contextSignals.touchesPayments) {\n priorities.push('💳 Payment code detected - ensure PCI compliance');\n }\n \n if (issues.moderate > 5) {\n priorities.push(`Schedule time to address ${issues.moderate} moderate issues`);\n }\n \n if (priorities.length === 0) {\n priorities.push('No critical issues - focus on feature development');\n }\n \n return priorities.slice(0, 5);\n}\n\n/**\n * Generate agent status table\n */\nfunction generateAgentStatusTable(state: ContextState): string {\n const builtInAgents = [\n 'security', 'legal', 'accessibility', 'bugs',\n 'design', 'architecture', 'performance', 'devops', 'soc2',\n 'e2e', 'typecheck', 'visual-qa', 'data-flow'\n ];\n \n let table = `| Agent | Status | Last Run | Issues Found |\n|-------|--------|----------|--------------|`;\n \n for (const agent of builtInAgents) {\n const status = state.agentStatus[agent];\n const lastRun = status?.lastRun \n ? new Date(status.lastRun).toLocaleDateString()\n : 'Never';\n const issues = status?.issuesFound ?? '-';\n const statusEmoji = status ? '✅' : '⏸️';\n \n table += `\\n| ${agent} | ${statusEmoji} Ready | ${lastRun} | ${issues} |`;\n }\n \n return table;\n}\n\n/**\n * Generate scan history table\n */\nfunction generateScanHistoryTable(state: ContextState): string {\n if (state.scanHistory.length === 0) {\n return `| Date | Agents | Files | Issues | Duration |\n|------|--------|-------|--------|----------|\n| - | - | - | - | - |`;\n }\n \n let table = `| Date | Agents | Files | Issues | Duration |\n|------|--------|-------|--------|----------|`;\n \n for (const scan of state.scanHistory.slice(0, 10)) {\n const date = new Date(scan.timestamp).toLocaleDateString();\n const agents = scan.agents.slice(0, 3).join(', ') + (scan.agents.length > 3 ? '...' : '');\n const duration = `${(scan.duration / 1000).toFixed(1)}s`;\n \n table += `\\n| ${date} | ${agents} | ${scan.filesScanned} | ${scan.issues.total} | ${duration} |`;\n }\n \n return table;\n}\n\n/**\n * Generate context signals section\n */\nfunction generateContextSignals(state: ContextState): string {\n const signals = [\n 'touchesAuth',\n 'touchesPayments', \n 'touchesUserData',\n 'touchesAPI',\n 'touchesDatabase',\n 'touchesCrypto'\n ];\n \n return signals\n .map(s => {\n const value = state.contextSignals[s];\n const emoji = value === true ? '✅' : value === false ? '❌' : '❓';\n return `- \\`${s}\\`: ${emoji} ${value === undefined ? 'Unknown' : value ? 'Yes' : 'No'}`;\n })\n .join('\\n');\n}\n\n/**\n * Generate risk assessment section\n */\nfunction generateRiskAssessment(state: ContextState): string {\n const score = state.healthScore;\n let riskLevel: string;\n let confidence: number;\n \n if (state.lastScan === null) {\n return `- Overall Risk: Unknown\n- Confidence: 0%`;\n }\n \n if (score >= 90) {\n riskLevel = '🟢 Low';\n confidence = 95;\n } else if (score >= 70) {\n riskLevel = '🟡 Medium';\n confidence = 85;\n } else if (score >= 50) {\n riskLevel = '🟠 High';\n confidence = 80;\n } else {\n riskLevel = '🔴 Critical';\n confidence = 90;\n }\n \n return `- Overall Risk: ${riskLevel}\n- Health Score: ${score}%\n- Confidence: ${confidence}%`;\n}\n\n/**\n * Generate hot files section\n */\nfunction generateHotFilesSection(state: ContextState): string {\n if (!state.lastScan || state.lastScan.hotFiles.length === 0) {\n return '_Run a scan to identify hot files._';\n }\n \n return state.lastScan.hotFiles\n .map(f => `- \\`${f.file}\\` - ${f.issueCount} issue${f.issueCount > 1 ? 's' : ''}`)\n .join('\\n');\n}\n\n/**\n * Get default state\n */\nfunction getDefaultState(): ContextState {\n return {\n lastScan: null,\n healthScore: 0,\n activePriorities: [\n 'Initial setup required - run first scan with `trie scan`',\n 'Configure agents in `.trie/config.json`',\n 'Set up CI/CD integration'\n ],\n contextSignals: {},\n agentStatus: {},\n scanHistory: [],\n customAgents: [],\n skills: {},\n environment: detectEnvironment(),\n };\n}\n\n/**\n * Detect the current execution environment\n */\nexport function detectEnvironment(): string {\n if (process.env.GITHUB_ACTIONS) return 'github-actions';\n if (process.env.GITLAB_CI) return 'gitlab-ci';\n if (process.env.CI) return 'ci';\n const parent = process.env._ || '';\n if (parent.includes('cursor')) return 'cursor';\n if (parent.includes('claude')) return 'claude-code';\n return 'cli';\n}\n\n/**\n * Record skill installation in context state\n */\nexport async function recordSkillInstalled(params: {\n name: string;\n source: string;\n}): Promise<void> {\n const state = await loadContextState();\n state.skills[params.name] = {\n source: params.source,\n installedAt: new Date().toISOString(),\n timesApplied: 0,\n appliedBy: [],\n };\n await saveContextState(state);\n}\n\n/**\n * Record skill usage by an agent\n */\nexport async function recordSkillUsage(params: {\n skillNames: string[];\n agentName: string;\n}): Promise<void> {\n const state = await loadContextState();\n const now = new Date().toISOString();\n \n for (const skillName of params.skillNames) {\n const skillRecord = state.skills[skillName];\n if (skillRecord) {\n skillRecord.timesApplied++;\n skillRecord.lastApplied = now;\n if (!skillRecord.appliedBy.includes(params.agentName)) {\n skillRecord.appliedBy.push(params.agentName);\n }\n }\n }\n \n const agentStatus = state.agentStatus[params.agentName];\n if (agentStatus) {\n agentStatus.skillsApplied = params.skillNames;\n }\n \n await saveContextState(state);\n}\n\n/**\n * Get the AGENTS.md template\n */\nfunction getAgentsMdTemplate(): string {\n return `# Trie Agent Context\n\n> **Auto-generated file** - Updated automatically when agents run.\n> Last updated: Never (initial state)\n\nThis file provides prioritized context for all AI coding assistants working with this codebase.\nAgents should read this file first and update it after completing scans.\n\n---\n\n## Quick Context (Read First)\n\n### Project State\n| Metric | Value | Updated |\n|--------|-------|---------|\n| Last Scan | Never | - |\n| Critical Issues | 0 | - |\n| Open Tasks | 0 | - |\n| Health Score | Unknown | - |\n\n### Active Priorities\n1. Initial setup required - run first scan with \\`trie scan\\`\n2. Configure agents in \\`.trie/config.json\\`\n3. Set up CI/CD integration\n\n### Hot Files\n_Run a scan to identify hot files._\n\n---\n\n## Agent Status\n\n### Agent Status\n| Agent | Status | Last Run | Issues Found |\n|-------|--------|----------|--------------|\n| security | Ready | Never | - |\n| bugs | Ready | Never | - |\n\n### Recent Scan History\n| Date | Agents | Files | Issues | Duration |\n|------|--------|-------|--------|----------|\n| - | - | - | - | - |\n\n---\n\n## Context Analysis\n\n### Context Signals Detected\n- \\`touchesAuth\\`: Unknown\n- \\`touchesPayments\\`: Unknown\n- \\`touchesUserData\\`: Unknown\n- \\`touchesAPI\\`: Unknown\n- \\`touchesDatabase\\`: Unknown\n- \\`touchesCrypto\\`: Unknown\n\n### Risk Assessment\n- Overall Risk: Unknown\n- Confidence: 0%\n\n---\n\n*This file is maintained by Trie agents. Manual edits will be preserved in non-auto sections.*\n`;\n}\n\n/**\n * Add custom skill to context state\n */\nexport async function addCustomAgentToContext(agentName: string): Promise<void> {\n const state = await loadContextState();\n \n if (!state.customAgents.includes(agentName)) {\n state.customAgents.push(agentName);\n await saveContextState(state);\n }\n}\n\n/**\n * Get context state for AI assistants (formatted summary)\n */\nexport async function getContextForAI(): Promise<string> {\n const state = await loadContextState();\n const workDir = getWorkingDirectory(undefined, true);\n \n const lines: string[] = [];\n \n // Include PROJECT.md content first (user-defined context takes priority)\n if (projectInfoExists(workDir)) {\n const projectInfo = await loadProjectInfo(workDir);\n if (projectInfo) {\n lines.push(projectInfo);\n lines.push('');\n lines.push('---');\n lines.push('');\n }\n }\n \n // Add Trie scan context\n lines.push(\n '## Trie Scan Context',\n '',\n `**Health Score:** ${state.healthScore}%`,\n `**Last Scan:** ${state.lastScan ? new Date(state.lastScan.timestamp).toLocaleString() : 'Never'}`,\n '',\n '**Active Priorities:**',\n ...state.activePriorities.map(p => `- ${p}`),\n ''\n );\n \n if (state.lastScan) {\n lines.push(\n '**Recent Issues:**',\n `- Critical: ${state.lastScan.issues.critical}`,\n `- Serious: ${state.lastScan.issues.serious}`,\n `- Moderate: ${state.lastScan.issues.moderate}`,\n `- Low: ${state.lastScan.issues.low}`,\n ''\n );\n \n if (state.lastScan.hotFiles.length > 0) {\n lines.push(\n '**Hot Files (most issues):**',\n ...state.lastScan.hotFiles.slice(0, 5).map(f => `- ${f.file}: ${f.issueCount} issues`),\n ''\n );\n }\n }\n \n return lines.join('\\n');\n}\n","import { existsSync } from 'fs';\nimport { join } from 'path';\nimport { getWorkingDirectory, getTrieDirectory } from './workspace.js';\n\nconst INIT_MARKERS = [\n 'PROJECT.md',\n 'RULES.md',\n 'TEAM.md',\n 'BOOTSTRAP.md',\n 'AGENTS.md',\n 'config.json',\n];\n\nexport function isTrieInitialized(workDir?: string): boolean {\n const dir = workDir || getWorkingDirectory(undefined, true);\n const trieDir = getTrieDirectory(dir);\n return INIT_MARKERS.some((marker) => existsSync(join(trieDir, marker)));\n}\n","/**\n * Audit logger stub\n * Audit functionality has been integrated into decision ledger\n */\n\nexport interface AuditStatistics {\n totalScans: number;\n totalIssues: number;\n criticalCount: number;\n seriousCount: number;\n moderateCount: number;\n lowCount: number;\n totalExecutions: number;\n successfulExecutions: number;\n failedExecutions: number;\n uniqueSkills: number;\n totalCommands: number;\n blockedCommands: number;\n totalNetworkCalls: number;\n blockedNetworkCalls: number;\n}\n\nexport interface AuditEntry {\n id: string;\n timestamp: string;\n command: string;\n status: string;\n commands?: ExecutedCommand[];\n}\n\nexport interface ExecutedCommand {\n command: string;\n timestamp: string;\n exitCode?: number;\n duration?: number;\n stdout?: string;\n stderr?: string;\n}\n\nexport interface SkillExecution {\n skillName: string;\n skillSource: string;\n triggeredBy: 'scan' | 'mcp' | 'cli' | 'watch' | 'manual';\n targetPath: string;\n startedAt: string;\n completedAt?: string;\n success?: boolean;\n error?: string;\n commands?: ExecutedCommand[];\n}\n\nexport function formatAuditLog(_entry: AuditEntry): string {\n return 'Audit logging has been integrated into the decision ledger';\n}\n\nexport function getAuditStatistics(): AuditStatistics {\n return {\n totalScans: 0,\n totalIssues: 0,\n criticalCount: 0,\n seriousCount: 0,\n moderateCount: 0,\n lowCount: 0,\n totalExecutions: 0,\n successfulExecutions: 0,\n failedExecutions: 0,\n uniqueSkills: 0,\n totalCommands: 0,\n blockedCommands: 0,\n totalNetworkCalls: 0,\n blockedNetworkCalls: 0,\n };\n}\n\nexport function createAuditEntry(\n skillName: string, \n skillSource: string, \n triggeredBy: SkillExecution['triggeredBy'], \n targetPath: string\n): SkillExecution {\n return {\n skillName,\n skillSource,\n triggeredBy,\n targetPath,\n startedAt: new Date().toISOString(),\n commands: [],\n };\n}\n\nexport function completeAuditEntry(\n entry: SkillExecution, \n success: boolean, \n error?: string\n): SkillExecution {\n const result: SkillExecution = {\n ...entry,\n completedAt: new Date().toISOString(),\n success,\n };\n if (error !== undefined) {\n result.error = error;\n }\n return result;\n}\n\nexport async function logSkillExecution(_execution: SkillExecution): Promise<void> {\n // Stub - no-op\n}\n\nexport async function getRecentAuditLogs(_limit: number = 10): Promise<AuditEntry[]> {\n return [];\n}\n\nexport async function getSkillAuditLogs(_skillName: string): Promise<AuditEntry[]> {\n return [];\n}\n","/**\n * Command Runner (with audit logging)\n *\n * Goal: Whenever Trie runs a shell command, record:\n * - command string\n * - exit code\n * - duration\n * - optional (redacted) stdout/stderr\n */\nimport { exec, execFile, execSync, type ExecException } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nimport {\n createAuditEntry,\n completeAuditEntry,\n logSkillExecution,\n type ExecutedCommand,\n type SkillExecution,\n} from '../skills/audit-logger.js';\n\nconst execAsync = promisify(exec);\nconst execFileAsync = promisify(execFile);\n\nexport type { ExecutedCommand, SkillExecution };\nexport type AuditTriggeredBy = SkillExecution['triggeredBy'];\n\nexport interface CommandAuditContext {\n /** Shown as `skillName` in audit logs; use something like `tool:pr-review` */\n actor: string;\n /** Where this came from in the product flow */\n triggeredBy: AuditTriggeredBy;\n /** Usually the working directory / repo path */\n targetPath: string;\n /** Optional string for `skillSource` */\n source?: string;\n}\n\nexport interface RunCommandOptions {\n cwd?: string;\n timeoutMs?: number;\n maxBuffer?: number;\n\n /** Capture stdout/stderr in the audit log */\n captureOutput?: boolean;\n /** Redact obvious secrets from captured output */\n redactOutput?: boolean;\n /** Max chars to keep per output stream */\n maxOutputChars?: number;\n}\n\nfunction redact(text: string): string {\n // Keep this conservative to avoid false redaction and avoid expensive processing.\n return text\n // Common key=value secrets\n .replace(/\\b(AWS|ANTHROPIC|OPENAI|GITHUB)_[A-Z0-9_]*\\s*=\\s*([^\\s\"'`]+)/gi, '$1_<REDACTED>=<REDACTED>')\n // Bearer tokens\n .replace(/\\bBearer\\s+[A-Za-z0-9\\-._~+/]+=*\\b/g, 'Bearer <REDACTED>')\n // GitHub tokens / generic tokens\n .replace(/\\bghp_[A-Za-z0-9]{20,}\\b/g, 'ghp_<REDACTED>')\n .replace(/\\b(?:xox[baprs]-)[A-Za-z0-9-]{10,}\\b/g, '<REDACTED_SLACK_TOKEN>')\n // AWS access key id (best-effort)\n .replace(/\\bAKIA[0-9A-Z]{16}\\b/g, 'AKIA<REDACTED>');\n}\n\nfunction clampOutput(text: string, maxChars: number): string {\n if (text.length <= maxChars) return text;\n return text.slice(0, maxChars) + `\\n…(truncated ${text.length - maxChars} chars)`;\n}\n\nfunction buildCommandRecord(command: string): ExecutedCommand {\n return {\n command,\n timestamp: new Date().toISOString(),\n };\n}\n\nasync function finalizeAndWrite(\n entry: SkillExecution,\n cmd: ExecutedCommand,\n outcome: { success: boolean; exitCode?: number; stdout?: string; stderr?: string; error?: string; startedAt: number },\n options?: Pick<RunCommandOptions, 'captureOutput' | 'redactOutput' | 'maxOutputChars'>\n): Promise<void> {\n const duration = Date.now() - outcome.startedAt;\n cmd.duration = duration;\n if (outcome.exitCode !== undefined) {\n cmd.exitCode = outcome.exitCode;\n }\n\n const captureOutput = options?.captureOutput ?? false;\n const redactOutput = options?.redactOutput ?? true;\n const maxOutputChars = options?.maxOutputChars ?? 2000;\n\n if (captureOutput) {\n const out = outcome.stdout ?? '';\n const err = outcome.stderr ?? '';\n cmd.stdout = redactOutput ? redact(clampOutput(out, maxOutputChars)) : clampOutput(out, maxOutputChars);\n cmd.stderr = redactOutput ? redact(clampOutput(err, maxOutputChars)) : clampOutput(err, maxOutputChars);\n }\n\n const completed = completeAuditEntry(entry, outcome.success, outcome.error);\n await logSkillExecution(completed);\n}\n\nexport async function runShellCommand(\n command: string,\n audit: CommandAuditContext,\n options?: RunCommandOptions\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const startedAt = Date.now();\n const entry = createAuditEntry(audit.actor, audit.source ?? 'trie', audit.triggeredBy, audit.targetPath);\n const cmd = buildCommandRecord(command);\n entry.commands?.push(cmd);\n\n try {\n const { stdout, stderr } = await execAsync(command, {\n cwd: options?.cwd,\n timeout: options?.timeoutMs,\n maxBuffer: options?.maxBuffer,\n });\n\n await finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout, stderr, startedAt }, options);\n return { stdout: stdout ?? '', stderr: stderr ?? '', exitCode: 0 };\n } catch (e) {\n const err = e as ExecException & { stdout?: unknown; stderr?: unknown; code?: unknown };\n const stdout = typeof err.stdout === 'string' ? err.stdout : '';\n const stderr = typeof err.stderr === 'string' ? err.stderr : '';\n const exitCode = typeof err.code === 'number' ? err.code : 1;\n\n await finalizeAndWrite(\n entry,\n cmd,\n { success: false, exitCode, stdout, stderr, error: err.message, startedAt },\n // Capture output for failures by default (so audits are useful)\n { ...options, captureOutput: options?.captureOutput ?? true }\n );\n\n return { stdout, stderr, exitCode };\n }\n}\n\nexport function runShellCommandSync(\n command: string,\n audit: CommandAuditContext,\n options?: Omit<RunCommandOptions, 'timeoutMs'> & { timeoutMs?: number }\n): { stdout: string; exitCode: number } {\n const startedAt = Date.now();\n const entry = createAuditEntry(audit.actor, audit.source ?? 'trie', audit.triggeredBy, audit.targetPath);\n const cmd = buildCommandRecord(command);\n entry.commands?.push(cmd);\n\n try {\n const stdout = execSync(command, {\n cwd: options?.cwd,\n timeout: options?.timeoutMs,\n maxBuffer: options?.maxBuffer,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n // Fire-and-forget write; sync APIs can’t await.\n void finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout, stderr: '', startedAt }, options);\n return { stdout: stdout ?? '', exitCode: 0 };\n } catch (e) {\n const err = e as ExecException & { stdout?: unknown; stderr?: unknown; status?: unknown };\n const stdout = typeof err.stdout === 'string' ? err.stdout : '';\n const stderr = typeof err.stderr === 'string' ? err.stderr : '';\n const exitCode = typeof err.status === 'number' ? err.status : 1;\n\n void finalizeAndWrite(\n entry,\n cmd,\n { success: false, exitCode, stdout, stderr, error: err.message, startedAt },\n { ...options, captureOutput: options?.captureOutput ?? true }\n );\n\n return { stdout, exitCode };\n }\n}\n\nexport async function runExecFile(\n file: string,\n args: string[],\n audit: CommandAuditContext,\n options?: Omit<RunCommandOptions, 'timeoutMs'> & { timeoutMs?: number }\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const startedAt = Date.now();\n const command = [file, ...args].join(' ');\n const entry = createAuditEntry(audit.actor, audit.source ?? 'trie', audit.triggeredBy, audit.targetPath);\n const cmd = buildCommandRecord(command);\n entry.commands?.push(cmd);\n\n try {\n const { stdout, stderr } = await execFileAsync(file, args, {\n cwd: options?.cwd,\n timeout: options?.timeoutMs,\n maxBuffer: options?.maxBuffer,\n });\n\n await finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout: String(stdout ?? ''), stderr: String(stderr ?? ''), startedAt }, options);\n return { stdout: String(stdout ?? ''), stderr: String(stderr ?? ''), exitCode: 0 };\n } catch (e) {\n const err = e as ExecException & { stdout?: unknown; stderr?: unknown; code?: unknown };\n const stdout = typeof err.stdout === 'string' ? err.stdout : '';\n const stderr = typeof err.stderr === 'string' ? err.stderr : '';\n const exitCode = typeof err.code === 'number' ? err.code : 1;\n\n await finalizeAndWrite(\n entry,\n cmd,\n { success: false, exitCode, stdout, stderr, error: err.message, startedAt },\n { ...options, captureOutput: options?.captureOutput ?? true }\n );\n return { stdout, stderr, exitCode };\n }\n}\n\n"],"mappings":"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","names":["readFile","mkdir","existsSync","join","join","existsSync","readFile","existsSync","join","existsSync","join"]}
|