@mmnto/cli 0.1.0
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/dist/commands/briefing.d.ts +7 -0
- package/dist/commands/briefing.d.ts.map +1 -0
- package/dist/commands/briefing.js +134 -0
- package/dist/commands/briefing.js.map +1 -0
- package/dist/commands/handoff.d.ts +7 -0
- package/dist/commands/handoff.d.ts.map +1 -0
- package/dist/commands/handoff.js +119 -0
- package/dist/commands/handoff.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +227 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install-hooks.d.ts +4 -0
- package/dist/commands/install-hooks.d.ts.map +1 -0
- package/dist/commands/install-hooks.js +125 -0
- package/dist/commands/install-hooks.js.map +1 -0
- package/dist/commands/learn.d.ts +14 -0
- package/dist/commands/learn.d.ts.map +1 -0
- package/dist/commands/learn.js +323 -0
- package/dist/commands/learn.js.map +1 -0
- package/dist/commands/search.d.ts +5 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +31 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/shield.d.ts +8 -0
- package/dist/commands/shield.d.ts.map +1 -0
- package/dist/commands/shield.js +130 -0
- package/dist/commands/shield.js.map +1 -0
- package/dist/commands/spec.d.ts +7 -0
- package/dist/commands/spec.d.ts.map +1 -0
- package/dist/commands/spec.js +159 -0
- package/dist/commands/spec.js.map +1 -0
- package/dist/commands/stats.d.ts +2 -0
- package/dist/commands/stats.d.ts.map +1 -0
- package/dist/commands/stats.js +22 -0
- package/dist/commands/stats.js.map +1 -0
- package/dist/commands/sync.d.ts +4 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +16 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/triage.d.ts +7 -0
- package/dist/commands/triage.d.ts.map +1 -0
- package/dist/commands/triage.js +149 -0
- package/dist/commands/triage.js.map +1 -0
- package/dist/git.d.ts +12 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +127 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +178 -0
- package/dist/index.js.map +1 -0
- package/dist/utils.d.ts +48 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +224 -0
- package/dist/utils.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import { createEmbedder, LanceStore } from '@mmnto/totem';
|
|
3
|
+
import { extractChangedFiles, getDefaultBranch, getGitBranchDiff, getGitDiff } from '../git.js';
|
|
4
|
+
import { formatResults, loadConfig, loadEnv, resolveConfigPath, runOrchestrator, writeOutput, } from '../utils.js';
|
|
5
|
+
// ─── Constants ──────────────────────────────────────────
|
|
6
|
+
const TAG = 'Shield';
|
|
7
|
+
const MAX_DIFF_CHARS = 50_000;
|
|
8
|
+
const QUERY_DIFF_TRUNCATE = 2_000;
|
|
9
|
+
const MAX_SPEC_RESULTS = 3;
|
|
10
|
+
const MAX_SESSION_RESULTS = 5;
|
|
11
|
+
const MAX_CODE_RESULTS = 5;
|
|
12
|
+
// ─── System prompt ──────────────────────────────────────
|
|
13
|
+
const SYSTEM_PROMPT = `# Shield System Prompt — Pre-Flight Code Review
|
|
14
|
+
|
|
15
|
+
## Purpose
|
|
16
|
+
Perform a pre-flight code review on a git diff, using project-specific knowledge to catch traps and anti-patterns before a PR is opened.
|
|
17
|
+
|
|
18
|
+
## Role
|
|
19
|
+
You are a senior code reviewer analyzing a diff against the project's accumulated knowledge: past session lessons, architectural specs, and codebase conventions. Flag issues the developer might miss, especially ones that have caused problems before.
|
|
20
|
+
|
|
21
|
+
## Rules
|
|
22
|
+
- Focus on the DIFF — only comment on code that is actually changing
|
|
23
|
+
- Reference specific lines/hunks from the diff when flagging issues
|
|
24
|
+
- Cite Totem knowledge when it directly applies (e.g., "Session #142 found that...")
|
|
25
|
+
- Distinguish severity: CRITICAL (must fix), WARNING (should fix), INFO (consider)
|
|
26
|
+
- Be concise — this is a pre-flight check, not a full RFC
|
|
27
|
+
- If the diff looks clean and follows all known patterns, say so
|
|
28
|
+
|
|
29
|
+
## Output Format
|
|
30
|
+
Respond with ONLY the sections below. No preamble, no closing remarks.
|
|
31
|
+
|
|
32
|
+
### Summary
|
|
33
|
+
[1-2 sentences describing what this diff does at a high level]
|
|
34
|
+
|
|
35
|
+
### Critical Issues
|
|
36
|
+
[Issues that MUST be fixed before merging. If none, say "None found."]
|
|
37
|
+
|
|
38
|
+
### Warnings
|
|
39
|
+
[Issues that SHOULD be addressed. Include pattern violations, potential regressions, and lessons from past sessions. If none, say "None found."]
|
|
40
|
+
|
|
41
|
+
### Suggestions
|
|
42
|
+
[Optional improvements and style notes. If none, say "None."]
|
|
43
|
+
|
|
44
|
+
### Relevant History
|
|
45
|
+
[Specific past traps, lessons, or decisions from Totem knowledge that apply to this diff. If none, say "No relevant history found."]
|
|
46
|
+
`;
|
|
47
|
+
async function retrieveContext(query, store) {
|
|
48
|
+
const search = (typeFilter, maxResults) => store.search({ query, typeFilter, maxResults });
|
|
49
|
+
const [specs, sessions, code] = await Promise.all([
|
|
50
|
+
search('spec', MAX_SPEC_RESULTS),
|
|
51
|
+
search('session_log', MAX_SESSION_RESULTS),
|
|
52
|
+
search('code', MAX_CODE_RESULTS),
|
|
53
|
+
]);
|
|
54
|
+
return { specs, sessions, code };
|
|
55
|
+
}
|
|
56
|
+
function buildSearchQuery(changedFiles, diff) {
|
|
57
|
+
const fileNames = changedFiles.map((f) => path.basename(f)).join(' ');
|
|
58
|
+
const diffSnippet = diff.slice(0, QUERY_DIFF_TRUNCATE);
|
|
59
|
+
return `${fileNames} ${diffSnippet}`.trim();
|
|
60
|
+
}
|
|
61
|
+
// ─── Prompt assembly ────────────────────────────────────
|
|
62
|
+
function assemblePrompt(diff, changedFiles, context) {
|
|
63
|
+
const sections = [SYSTEM_PROMPT];
|
|
64
|
+
// Diff section
|
|
65
|
+
sections.push('=== DIFF ===');
|
|
66
|
+
sections.push(`Changed files: ${changedFiles.join(', ')}`);
|
|
67
|
+
sections.push('');
|
|
68
|
+
if (diff.length > MAX_DIFF_CHARS) {
|
|
69
|
+
sections.push(diff.slice(0, MAX_DIFF_CHARS));
|
|
70
|
+
sections.push(`\n... [diff truncated at ${MAX_DIFF_CHARS} chars] ...`);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
sections.push(diff);
|
|
74
|
+
}
|
|
75
|
+
// Totem knowledge
|
|
76
|
+
const specSection = formatResults(context.specs, 'RELATED SPECS & ADRs');
|
|
77
|
+
const sessionSection = formatResults(context.sessions, 'RELATED SESSION HISTORY & LESSONS');
|
|
78
|
+
const codeSection = formatResults(context.code, 'RELATED CODE PATTERNS');
|
|
79
|
+
if (specSection || sessionSection || codeSection) {
|
|
80
|
+
sections.push('\n=== TOTEM KNOWLEDGE ===');
|
|
81
|
+
if (specSection)
|
|
82
|
+
sections.push(specSection);
|
|
83
|
+
if (sessionSection)
|
|
84
|
+
sections.push(sessionSection);
|
|
85
|
+
if (codeSection)
|
|
86
|
+
sections.push(codeSection);
|
|
87
|
+
}
|
|
88
|
+
return sections.join('\n');
|
|
89
|
+
}
|
|
90
|
+
export async function shieldCommand(options) {
|
|
91
|
+
const cwd = process.cwd();
|
|
92
|
+
const configPath = resolveConfigPath(cwd);
|
|
93
|
+
loadEnv(cwd);
|
|
94
|
+
const config = await loadConfig(configPath);
|
|
95
|
+
// Get git diff — try uncommitted/staged first, fall back to branch diff vs main
|
|
96
|
+
const mode = options.staged ? 'staged' : 'all';
|
|
97
|
+
console.error(`[${TAG}] Getting ${mode === 'staged' ? 'staged' : 'uncommitted'} diff...`);
|
|
98
|
+
let diff = getGitDiff(mode, cwd);
|
|
99
|
+
if (!diff.trim()) {
|
|
100
|
+
const base = getDefaultBranch(cwd);
|
|
101
|
+
console.error(`[${TAG}] No uncommitted changes. Falling back to branch diff (${base}...HEAD)...`);
|
|
102
|
+
diff = getGitBranchDiff(cwd, base);
|
|
103
|
+
}
|
|
104
|
+
if (!diff.trim()) {
|
|
105
|
+
console.error(`[${TAG}] No changes detected. Nothing to review.`);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const changedFiles = extractChangedFiles(diff);
|
|
109
|
+
console.error(`[${TAG}] Changed files (${changedFiles.length}): ${changedFiles.join(', ')}`);
|
|
110
|
+
// Connect to LanceDB
|
|
111
|
+
const embedder = createEmbedder(config.embedding);
|
|
112
|
+
const store = new LanceStore(path.join(cwd, config.lanceDir), embedder);
|
|
113
|
+
await store.connect();
|
|
114
|
+
// Retrieve context from LanceDB
|
|
115
|
+
const query = buildSearchQuery(changedFiles, diff);
|
|
116
|
+
console.error(`[${TAG}] Querying Totem index...`);
|
|
117
|
+
const context = await retrieveContext(query, store);
|
|
118
|
+
const totalResults = context.specs.length + context.sessions.length + context.code.length;
|
|
119
|
+
console.error(`[${TAG}] Found: ${context.specs.length} specs, ${context.sessions.length} sessions, ${context.code.length} code chunks`);
|
|
120
|
+
// Assemble prompt
|
|
121
|
+
const prompt = assemblePrompt(diff, changedFiles, context);
|
|
122
|
+
console.error(`[${TAG}] Prompt: ${(prompt.length / 1024).toFixed(0)}KB`);
|
|
123
|
+
const content = runOrchestrator({ prompt, tag: TAG, options, config, cwd, totalResults });
|
|
124
|
+
if (content != null) {
|
|
125
|
+
writeOutput(content, options.out);
|
|
126
|
+
if (options.out)
|
|
127
|
+
console.error(`[${TAG}] Written to ${options.out}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=shield.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shield.js","sourceRoot":"","sources":["../../src/commands/shield.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../src/commands/spec.ts"],"names":[],"mappings":"AAwKA,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA2CpF"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { createEmbedder, LanceStore } from '@mmnto/totem';
|
|
5
|
+
import { formatResults, GH_TIMEOUT_MS, IS_WIN, loadConfig, loadEnv, resolveConfigPath, runOrchestrator, writeOutput, } from '../utils.js';
|
|
6
|
+
// ─── Constants ──────────────────────────────────────────
|
|
7
|
+
const TAG = 'Spec';
|
|
8
|
+
const QUERY_BODY_TRUNCATE = 500;
|
|
9
|
+
// ─── System prompt ──────────────────────────────────────
|
|
10
|
+
const SYSTEM_PROMPT = `# Spec System Prompt — Pre-Work Briefing
|
|
11
|
+
|
|
12
|
+
## Purpose
|
|
13
|
+
Produce a structured pre-work briefing for a GitHub issue before implementation begins.
|
|
14
|
+
|
|
15
|
+
## Role
|
|
16
|
+
You are a technical spec writer analyzing a GitHub issue and its related project context. Your job is to produce a focused briefing that identifies: relevant history, files to examine, implementation approach, traps, and test plan.
|
|
17
|
+
|
|
18
|
+
## Rules
|
|
19
|
+
- File paths must reference actual files from the context provided
|
|
20
|
+
- Cite related issues by number (#NNN) when relevant
|
|
21
|
+
- Identify edge cases the issue description doesn't mention
|
|
22
|
+
- Be concise — this is a briefing, not a full proposal
|
|
23
|
+
- When multiple approaches exist, list trade-offs with a clear recommendation
|
|
24
|
+
|
|
25
|
+
## Output Format
|
|
26
|
+
Respond with ONLY the sections below. No preamble, no closing remarks.
|
|
27
|
+
|
|
28
|
+
### Problem
|
|
29
|
+
[1-2 sentences restating the issue in concrete implementation terms. What exactly needs to change?]
|
|
30
|
+
|
|
31
|
+
### Historical Context
|
|
32
|
+
[Relevant sessions, PRs, decisions, related issues from the provided Totem knowledge. If nothing relevant, say "None found in provided context."]
|
|
33
|
+
|
|
34
|
+
### Files to Examine
|
|
35
|
+
[Ordered list of files the developer should read before starting. Most critical first. Format: \`path/to/file.ts\` — reason to examine]
|
|
36
|
+
|
|
37
|
+
### Approach
|
|
38
|
+
[Recommended implementation approach. Concrete steps, not abstract descriptions. If multiple valid approaches exist, list them as Option A / Option B with trade-offs and a clear recommendation.]
|
|
39
|
+
|
|
40
|
+
### Edge Cases & Traps
|
|
41
|
+
[Things the issue description doesn't mention but the developer should watch for. Include existing patterns that MUST be followed for consistency and potential regressions in related features.]
|
|
42
|
+
|
|
43
|
+
### Test Plan
|
|
44
|
+
[Specific test scenarios. Reference existing test file patterns when applicable.]
|
|
45
|
+
|
|
46
|
+
### Related Issues
|
|
47
|
+
[Issues that might be affected by or related to this work. Format: #NNN — title — relationship (blocks, unblocks, overlaps, conflicts). If none found, say "None identified."]
|
|
48
|
+
`;
|
|
49
|
+
// ─── GitHub helpers ─────────────────────────────────────
|
|
50
|
+
const GhIssueSchema = z.object({
|
|
51
|
+
number: z.number(),
|
|
52
|
+
title: z.string(),
|
|
53
|
+
body: z.string().nullable(),
|
|
54
|
+
labels: z.array(z.object({ name: z.string() })),
|
|
55
|
+
state: z.string(),
|
|
56
|
+
});
|
|
57
|
+
function fetchIssue(issueNumber, cwd) {
|
|
58
|
+
try {
|
|
59
|
+
const result = execFileSync('gh', ['issue', 'view', String(issueNumber), '--json', 'number,title,body,labels,state'], { cwd, encoding: 'utf-8', timeout: GH_TIMEOUT_MS, shell: IS_WIN });
|
|
60
|
+
return GhIssueSchema.parse(JSON.parse(result));
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
if (err instanceof z.ZodError) {
|
|
64
|
+
throw new Error(`[Totem Error] Failed to parse GitHub issue response: ${err.message}`);
|
|
65
|
+
}
|
|
66
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
67
|
+
if (msg.includes('ENOENT') || msg.includes('not found')) {
|
|
68
|
+
throw new Error(`[Totem Error] GitHub CLI (gh) is required for issue fetching. Install: https://cli.github.com`);
|
|
69
|
+
}
|
|
70
|
+
throw new Error(`[Totem Error] Failed to fetch issue #${issueNumber}: ${msg}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function retrieveContext(query, store) {
|
|
74
|
+
const search = (typeFilter, maxResults) => store.search({ query, typeFilter, maxResults });
|
|
75
|
+
const [specs, sessions, code] = await Promise.all([
|
|
76
|
+
search('spec', 5),
|
|
77
|
+
search('session_log', 5),
|
|
78
|
+
search('code', 3),
|
|
79
|
+
]);
|
|
80
|
+
return { specs, sessions, code };
|
|
81
|
+
}
|
|
82
|
+
function buildSearchQuery(issue) {
|
|
83
|
+
const labels = issue.labels.map((l) => l.name).join(' ');
|
|
84
|
+
const bodySnippet = (issue.body ?? '').slice(0, QUERY_BODY_TRUNCATE);
|
|
85
|
+
return `${issue.title} ${labels} ${bodySnippet}`.trim();
|
|
86
|
+
}
|
|
87
|
+
// ─── Prompt assembly ────────────────────────────────────
|
|
88
|
+
function assemblePrompt(issue, freeText, context) {
|
|
89
|
+
const sections = [SYSTEM_PROMPT];
|
|
90
|
+
// Target issue or free-text topic
|
|
91
|
+
if (issue) {
|
|
92
|
+
const issueLabels = issue.labels.map((l) => l.name).join(', ');
|
|
93
|
+
sections.push('=== TARGET ISSUE ===');
|
|
94
|
+
sections.push(`Issue #${issue.number}: ${issue.title}`);
|
|
95
|
+
sections.push(`Labels: ${issueLabels || '(none)'}`);
|
|
96
|
+
sections.push(`State: ${issue.state}`);
|
|
97
|
+
if (issue.body) {
|
|
98
|
+
sections.push('');
|
|
99
|
+
sections.push(issue.body);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else if (freeText) {
|
|
103
|
+
sections.push('=== TOPIC ===');
|
|
104
|
+
sections.push(freeText);
|
|
105
|
+
}
|
|
106
|
+
// Totem knowledge
|
|
107
|
+
const specSection = formatResults(context.specs, 'RELATED SPECS & ADRs');
|
|
108
|
+
const sessionSection = formatResults(context.sessions, 'RELATED SESSION HISTORY');
|
|
109
|
+
const codeSection = formatResults(context.code, 'RELATED CODE');
|
|
110
|
+
if (specSection || sessionSection || codeSection) {
|
|
111
|
+
sections.push('\n=== TOTEM KNOWLEDGE ===');
|
|
112
|
+
if (specSection)
|
|
113
|
+
sections.push(specSection);
|
|
114
|
+
if (sessionSection)
|
|
115
|
+
sections.push(sessionSection);
|
|
116
|
+
if (codeSection)
|
|
117
|
+
sections.push(codeSection);
|
|
118
|
+
}
|
|
119
|
+
return sections.join('\n');
|
|
120
|
+
}
|
|
121
|
+
export async function specCommand(input, options) {
|
|
122
|
+
const cwd = process.cwd();
|
|
123
|
+
const configPath = resolveConfigPath(cwd);
|
|
124
|
+
loadEnv(cwd);
|
|
125
|
+
const config = await loadConfig(configPath);
|
|
126
|
+
// Connect to LanceDB
|
|
127
|
+
const embedder = createEmbedder(config.embedding);
|
|
128
|
+
const store = new LanceStore(path.join(cwd, config.lanceDir), embedder);
|
|
129
|
+
await store.connect();
|
|
130
|
+
// Parse input: issue number or free-text
|
|
131
|
+
const issueNumber = /^\d+$/.test(input) ? parseInt(input, 10) : null;
|
|
132
|
+
let issue = null;
|
|
133
|
+
let query;
|
|
134
|
+
if (issueNumber) {
|
|
135
|
+
console.error(`[${TAG}] Fetching issue #${issueNumber}...`);
|
|
136
|
+
issue = fetchIssue(issueNumber, cwd);
|
|
137
|
+
console.error(`[${TAG}] Title: ${issue.title}`);
|
|
138
|
+
query = buildSearchQuery(issue);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
console.error(`[${TAG}] Topic: ${input}`);
|
|
142
|
+
query = input;
|
|
143
|
+
}
|
|
144
|
+
// Retrieve context from LanceDB
|
|
145
|
+
console.error(`[${TAG}] Querying Totem index...`);
|
|
146
|
+
const context = await retrieveContext(query, store);
|
|
147
|
+
const totalResults = context.specs.length + context.sessions.length + context.code.length;
|
|
148
|
+
console.error(`[${TAG}] Found: ${context.specs.length} specs, ${context.sessions.length} sessions, ${context.code.length} code chunks`);
|
|
149
|
+
// Assemble prompt
|
|
150
|
+
const prompt = assemblePrompt(issue, issueNumber ? null : input, context);
|
|
151
|
+
console.error(`[${TAG}] Prompt: ${(prompt.length / 1024).toFixed(0)}KB`);
|
|
152
|
+
const content = runOrchestrator({ prompt, tag: TAG, options, config, cwd, totalResults });
|
|
153
|
+
if (content != null) {
|
|
154
|
+
writeOutput(content, options.out);
|
|
155
|
+
if (options.out)
|
|
156
|
+
console.error(`[${TAG}] Written to ${options.out}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/commands/spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/commands/stats.ts"],"names":[],"mappings":"AAMA,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAsBlD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import { createEmbedder, LanceStore } from '@mmnto/totem';
|
|
3
|
+
import { loadConfig, loadEnv, resolveConfigPath } from '../utils.js';
|
|
4
|
+
export async function statsCommand() {
|
|
5
|
+
const cwd = process.cwd();
|
|
6
|
+
const configPath = resolveConfigPath(cwd);
|
|
7
|
+
loadEnv(cwd);
|
|
8
|
+
const config = await loadConfig(configPath);
|
|
9
|
+
const embedder = createEmbedder(config.embedding);
|
|
10
|
+
const store = new LanceStore(path.join(cwd, config.lanceDir), embedder);
|
|
11
|
+
await store.connect();
|
|
12
|
+
const { totalChunks, byType } = await store.stats();
|
|
13
|
+
console.log(`[Totem] Index statistics:`);
|
|
14
|
+
console.log(` Total chunks: ${totalChunks}`);
|
|
15
|
+
for (const [type, count] of Object.entries(byType)) {
|
|
16
|
+
console.log(` ${type}: ${count}`);
|
|
17
|
+
}
|
|
18
|
+
if (totalChunks === 0) {
|
|
19
|
+
console.log('\n No data indexed yet. Run `totem sync` first.');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/commands/stats.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1D,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErE,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,UAAU,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAE1C,OAAO,CAAC,GAAG,CAAC,CAAC;IAEb,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;IACxE,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;IAEtB,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;IAEpD,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,mBAAmB,WAAW,EAAE,CAAC,CAAC;IAC9C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;IAClE,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAIA,wBAAsB,WAAW,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB5E"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { runSync } from '@mmnto/totem';
|
|
2
|
+
import { loadConfig, loadEnv, resolveConfigPath } from '../utils.js';
|
|
3
|
+
export async function syncCommand(options) {
|
|
4
|
+
const cwd = process.cwd();
|
|
5
|
+
const configPath = resolveConfigPath(cwd);
|
|
6
|
+
loadEnv(cwd);
|
|
7
|
+
const config = await loadConfig(configPath);
|
|
8
|
+
const incremental = !options.full;
|
|
9
|
+
const result = await runSync(config, {
|
|
10
|
+
projectRoot: cwd,
|
|
11
|
+
incremental,
|
|
12
|
+
onProgress: (msg) => console.log(`[Totem] ${msg}`),
|
|
13
|
+
});
|
|
14
|
+
console.log(`[Totem] Done: ${result.chunksProcessed} chunks from ${result.filesProcessed} files`);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErE,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAA2B;IAC3D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,UAAU,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAE1C,OAAO,CAAC,GAAG,CAAC,CAAC;IAEb,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;IAElC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE;QACnC,WAAW,EAAE,GAAG;QAChB,WAAW;QACX,UAAU,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,EAAE,CAAC;KACnD,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,eAAe,gBAAgB,MAAM,CAAC,cAAc,QAAQ,CAAC,CAAC;AACpG,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triage.d.ts","sourceRoot":"","sources":["../../src/commands/triage.ts"],"names":[],"mappings":"AAkKA,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAwCzE"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { createEmbedder, LanceStore } from '@mmnto/totem';
|
|
5
|
+
import { formatResults, GH_TIMEOUT_MS, IS_WIN, loadConfig, loadEnv, resolveConfigPath, runOrchestrator, writeOutput, } from '../utils.js';
|
|
6
|
+
// ─── Constants ──────────────────────────────────────────
|
|
7
|
+
const TAG = 'Triage';
|
|
8
|
+
const MAX_SPEC_RESULTS = 5;
|
|
9
|
+
const MAX_SESSION_RESULTS = 5;
|
|
10
|
+
const QUERY_TITLES_TRUNCATE = 2_000;
|
|
11
|
+
const GH_ISSUE_LIMIT = 100;
|
|
12
|
+
// ─── System prompt ──────────────────────────────────────
|
|
13
|
+
const SYSTEM_PROMPT = `# Triage System Prompt — Active Work Roadmap
|
|
14
|
+
|
|
15
|
+
## Purpose
|
|
16
|
+
Produce a prioritized roadmap from the project's open GitHub issues, informed by recent work history from Totem knowledge.
|
|
17
|
+
|
|
18
|
+
## Role
|
|
19
|
+
You are a technical project manager analyzing a project's open issue backlog alongside its recent development history. Your job is to produce a clear, actionable prioritization that helps the developer decide what to work on next.
|
|
20
|
+
|
|
21
|
+
## Rules
|
|
22
|
+
- Reference issues by number (#NNN) and title
|
|
23
|
+
- Consider labels (bug, enhancement, priority, etc.) as strong signals
|
|
24
|
+
- Use recent session history and specs to understand project momentum — what was just finished, what's in progress
|
|
25
|
+
- Factor in issue age (updatedAt) — stale issues may need re-evaluation
|
|
26
|
+
- Be opinionated — give a clear recommendation, not a wishy-washy list
|
|
27
|
+
- Be concise — this is a decision-making tool, not a project plan
|
|
28
|
+
|
|
29
|
+
## Output Format
|
|
30
|
+
Respond with ONLY the sections below. No preamble, no closing remarks.
|
|
31
|
+
|
|
32
|
+
### Active Work Summary
|
|
33
|
+
[1-3 sentences about what was recently completed or is in progress, based on the Totem knowledge provided. If no relevant history, say "No recent session history available."]
|
|
34
|
+
|
|
35
|
+
### Prioritized Roadmap
|
|
36
|
+
[Ordered list of open issues, most important first. For each: #NNN — title — 1-sentence rationale for its priority position. Group by priority tier if helpful (e.g., "Do Next", "Up Next", "Backlog").]
|
|
37
|
+
|
|
38
|
+
### Next Issue
|
|
39
|
+
[Single recommended issue to work on next. Include: issue number, title, and 2-3 sentences explaining WHY this should be next — considering dependencies, momentum, and impact.]
|
|
40
|
+
|
|
41
|
+
### Blocked / Needs Input
|
|
42
|
+
[Issues that cannot progress without external input, decisions, or prerequisite work. If none, say "None identified."]
|
|
43
|
+
`;
|
|
44
|
+
// ─── GitHub helpers ─────────────────────────────────────
|
|
45
|
+
const GhIssueListItemSchema = z.object({
|
|
46
|
+
number: z.number(),
|
|
47
|
+
title: z.string(),
|
|
48
|
+
labels: z.array(z.object({ name: z.string() })),
|
|
49
|
+
updatedAt: z.string().datetime(),
|
|
50
|
+
});
|
|
51
|
+
function fetchOpenIssues(cwd) {
|
|
52
|
+
try {
|
|
53
|
+
const result = execFileSync('gh', [
|
|
54
|
+
'issue',
|
|
55
|
+
'list',
|
|
56
|
+
'--state',
|
|
57
|
+
'open',
|
|
58
|
+
'--json',
|
|
59
|
+
'number,title,labels,updatedAt',
|
|
60
|
+
'--limit',
|
|
61
|
+
String(GH_ISSUE_LIMIT),
|
|
62
|
+
], { cwd, encoding: 'utf-8', timeout: GH_TIMEOUT_MS, shell: IS_WIN });
|
|
63
|
+
return z.array(GhIssueListItemSchema).parse(JSON.parse(result));
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
if (err instanceof z.ZodError) {
|
|
67
|
+
throw new Error(`[Totem Error] Failed to parse GitHub issue list response: ${err.message}`);
|
|
68
|
+
}
|
|
69
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
70
|
+
if (msg.includes('ENOENT') || msg.includes('not found')) {
|
|
71
|
+
throw new Error(`[Totem Error] GitHub CLI (gh) is required for issue fetching. Install: https://cli.github.com`);
|
|
72
|
+
}
|
|
73
|
+
throw new Error(`[Totem Error] Failed to fetch open issues: ${msg}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function retrieveContext(query, store) {
|
|
77
|
+
const search = (typeFilter, maxResults) => store.search({ query, typeFilter, maxResults });
|
|
78
|
+
const [specs, sessions] = await Promise.all([
|
|
79
|
+
search('spec', MAX_SPEC_RESULTS),
|
|
80
|
+
search('session_log', MAX_SESSION_RESULTS),
|
|
81
|
+
]);
|
|
82
|
+
return { specs, sessions };
|
|
83
|
+
}
|
|
84
|
+
function buildSearchQuery(issues) {
|
|
85
|
+
const titles = issues.map((i) => i.title).join(' ');
|
|
86
|
+
const labels = [...new Set(issues.flatMap((i) => i.labels.map((l) => l.name)))].join(' ');
|
|
87
|
+
return `${titles} ${labels}`.slice(0, QUERY_TITLES_TRUNCATE).trim();
|
|
88
|
+
}
|
|
89
|
+
// ─── Prompt assembly ────────────────────────────────────
|
|
90
|
+
function formatIssueInventory(issues) {
|
|
91
|
+
const rows = issues.map((i) => {
|
|
92
|
+
const labels = i.labels.map((l) => l.name).join(', ') || '(none)';
|
|
93
|
+
const updated = i.updatedAt.slice(0, 10); // YYYY-MM-DD
|
|
94
|
+
return `| #${i.number} | ${i.title} | ${labels} | ${updated} |`;
|
|
95
|
+
});
|
|
96
|
+
return ['| Issue | Title | Labels | Updated |', '|---|---|---|---|', ...rows].join('\n');
|
|
97
|
+
}
|
|
98
|
+
function assemblePrompt(issues, context) {
|
|
99
|
+
const sections = [SYSTEM_PROMPT];
|
|
100
|
+
// Issue inventory
|
|
101
|
+
sections.push('=== OPEN ISSUES ===');
|
|
102
|
+
sections.push(`Total: ${issues.length} open issues\n`);
|
|
103
|
+
sections.push(formatIssueInventory(issues));
|
|
104
|
+
// Totem knowledge
|
|
105
|
+
const specSection = formatResults(context.specs, 'RECENT SPECS & ADRs');
|
|
106
|
+
const sessionSection = formatResults(context.sessions, 'RECENT SESSION HISTORY');
|
|
107
|
+
if (specSection || sessionSection) {
|
|
108
|
+
sections.push('\n=== TOTEM KNOWLEDGE ===');
|
|
109
|
+
if (specSection)
|
|
110
|
+
sections.push(specSection);
|
|
111
|
+
if (sessionSection)
|
|
112
|
+
sections.push(sessionSection);
|
|
113
|
+
}
|
|
114
|
+
return sections.join('\n');
|
|
115
|
+
}
|
|
116
|
+
export async function triageCommand(options) {
|
|
117
|
+
const cwd = process.cwd();
|
|
118
|
+
const configPath = resolveConfigPath(cwd);
|
|
119
|
+
loadEnv(cwd);
|
|
120
|
+
const config = await loadConfig(configPath);
|
|
121
|
+
// Fetch open issues
|
|
122
|
+
console.error(`[${TAG}] Fetching open issues...`);
|
|
123
|
+
const issues = fetchOpenIssues(cwd);
|
|
124
|
+
if (issues.length === 0) {
|
|
125
|
+
console.error(`[${TAG}] No open issues found. Nothing to triage.`);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
console.error(`[${TAG}] Found ${issues.length} open issues.`);
|
|
129
|
+
// Connect to LanceDB
|
|
130
|
+
const embedder = createEmbedder(config.embedding);
|
|
131
|
+
const store = new LanceStore(path.join(cwd, config.lanceDir), embedder);
|
|
132
|
+
await store.connect();
|
|
133
|
+
// Retrieve context from LanceDB
|
|
134
|
+
const query = buildSearchQuery(issues);
|
|
135
|
+
console.error(`[${TAG}] Querying Totem index...`);
|
|
136
|
+
const context = await retrieveContext(query, store);
|
|
137
|
+
const totalResults = context.specs.length + context.sessions.length;
|
|
138
|
+
console.error(`[${TAG}] Found: ${context.specs.length} specs, ${context.sessions.length} sessions`);
|
|
139
|
+
// Assemble prompt
|
|
140
|
+
const prompt = assemblePrompt(issues, context);
|
|
141
|
+
console.error(`[${TAG}] Prompt: ${(prompt.length / 1024).toFixed(0)}KB`);
|
|
142
|
+
const content = runOrchestrator({ prompt, tag: TAG, options, config, cwd, totalResults });
|
|
143
|
+
if (content != null) {
|
|
144
|
+
writeOutput(content, options.out);
|
|
145
|
+
if (options.out)
|
|
146
|
+
console.error(`[${TAG}] Written to ${options.out}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=triage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triage.js","sourceRoot":"","sources":["../../src/commands/triage.ts"],"names":[],"mappings":"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"}
|
package/dist/git.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function getGitBranch(cwd: string): string;
|
|
2
|
+
export declare function getGitStatus(cwd: string): string;
|
|
3
|
+
export declare function getGitDiff(mode: 'staged' | 'all', cwd: string): string;
|
|
4
|
+
export declare function getGitDiffStat(cwd: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Detect the default branch of the remote (e.g. main, master).
|
|
7
|
+
* Falls back to 'main' if detection fails.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getDefaultBranch(cwd: string): string;
|
|
10
|
+
export declare function getGitBranchDiff(cwd: string, base?: string): string;
|
|
11
|
+
export declare function extractChangedFiles(diff: string): string[];
|
|
12
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAmBA,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUhD;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUhD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,KAAK,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CActE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAWlD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA+BpD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAcnE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAS1D"}
|