peaks-cli 1.0.28 → 1.1.1
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/bin/peaks.js +0 -0
- package/dist/src/cli/commands/core-artifact-commands.js +4 -4
- package/dist/src/cli/commands/project-commands.js +23 -101
- package/dist/src/cli/commands/statusline-commands.d.ts +3 -0
- package/dist/src/cli/commands/statusline-commands.js +111 -0
- package/dist/src/cli/program.js +2 -0
- package/dist/src/services/doctor/doctor-service.d.ts +1 -0
- package/dist/src/services/doctor/doctor-service.js +40 -0
- package/dist/src/services/memory/project-context-service.d.ts +0 -38
- package/dist/src/services/memory/project-context-service.js +2 -304
- package/dist/src/services/memory/project-memory-service.d.ts +17 -1
- package/dist/src/services/memory/project-memory-service.js +72 -4
- package/dist/src/services/skills/skill-statusline-renderer.d.ts +6 -0
- package/dist/src/services/skills/skill-statusline-renderer.js +55 -0
- package/dist/src/services/skills/skill-statusline-service.d.ts +22 -0
- package/dist/src/services/skills/skill-statusline-service.js +94 -0
- package/dist/src/services/skills/statusline-settings-service.d.ts +32 -0
- package/dist/src/services/skills/statusline-settings-service.js +144 -0
- package/dist/src/shared/version.d.ts +1 -1
- package/dist/src/shared/version.js +1 -1
- package/package.json +1 -1
- package/schemas/doctor-report.schema.json +2 -2
- package/skills/peaks-prd/SKILL.md +10 -3
- package/skills/peaks-qa/SKILL.md +10 -3
- package/skills/peaks-rd/SKILL.md +10 -3
- package/skills/peaks-sc/SKILL.md +11 -4
- package/skills/peaks-solo/SKILL.md +16 -9
- package/skills/peaks-txt/SKILL.md +12 -5
- package/skills/peaks-ui/SKILL.md +10 -3
package/bin/peaks.js
CHANGED
|
File without changes
|
|
@@ -227,11 +227,11 @@ export function registerCoreAndArtifactCommands(program, io) {
|
|
|
227
227
|
const memory = program.command('memory').description('Manage project-local Peaks memory');
|
|
228
228
|
addJsonOption(memory
|
|
229
229
|
.command('extract')
|
|
230
|
-
.description('Extract stable project memory from skill artifacts into project .
|
|
230
|
+
.description('Extract stable project memory from skill artifacts into project .peaks/memory')
|
|
231
231
|
.requiredOption('--project <path>', 'target project root')
|
|
232
232
|
.requiredOption('--artifact <path...>', 'skill artifact paths inside the project')
|
|
233
233
|
.option('--dry-run', 'preview writes without changing files', true)
|
|
234
|
-
.option('--apply', 'write extracted memories into project .
|
|
234
|
+
.option('--apply', 'write extracted memories into project .peaks/memory')).action((options) => {
|
|
235
235
|
try {
|
|
236
236
|
const result = executeProjectMemoryExtract({ projectRoot: options.project, artifactPaths: options.artifact, apply: options.apply === true });
|
|
237
237
|
printResult(io, ok('memory.extract', summarizeProjectMemoryExtractResult(result)), options.json);
|
|
@@ -243,11 +243,11 @@ export function registerCoreAndArtifactCommands(program, io) {
|
|
|
243
243
|
});
|
|
244
244
|
addJsonOption(memory
|
|
245
245
|
.command('sync')
|
|
246
|
-
.description('Back up project .
|
|
246
|
+
.description('Back up project .peaks/memory into the artifact workspace')
|
|
247
247
|
.requiredOption('--project <path>', 'target project root')
|
|
248
248
|
.requiredOption('--workspace <path>', 'artifact workspace path')
|
|
249
249
|
.option('--dry-run', 'preview copies without changing files', true)
|
|
250
|
-
.option('--apply', 'copy project .
|
|
250
|
+
.option('--apply', 'copy project .peaks/memory into artifact workspace backup')).action((options) => {
|
|
251
251
|
try {
|
|
252
252
|
const result = executeProjectMemoryBackup({ projectRoot: options.project, artifactWorkspacePath: options.workspace, apply: options.apply === true });
|
|
253
253
|
printResult(io, ok('memory.sync', summarizeProjectMemoryBackupResult(result)), options.json);
|
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
import { loadProjectDashboard } from '../../services/dashboard/project-dashboard-service.js';
|
|
2
|
-
import { generateProjectContext,
|
|
2
|
+
import { generateProjectContext, readProjectContext } from '../../services/memory/project-context-service.js';
|
|
3
|
+
import { readProjectMemories } from '../../services/memory/project-memory-service.js';
|
|
3
4
|
import { fail, ok } from '../../shared/result.js';
|
|
4
5
|
import { addJsonOption, getErrorMessage, printResult } from '../cli-helpers.js';
|
|
5
|
-
function defined(obj) {
|
|
6
|
-
const result = {};
|
|
7
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
8
|
-
if (v !== undefined)
|
|
9
|
-
result[k] = v;
|
|
10
|
-
}
|
|
11
|
-
return result;
|
|
12
|
-
}
|
|
13
6
|
export function registerProjectCommands(program, io) {
|
|
14
7
|
const project = program.command('project').description('Aggregate Peaks state for a target project (read-only)');
|
|
15
8
|
addJsonOption(project
|
|
@@ -75,104 +68,33 @@ export function registerProjectCommands(program, io) {
|
|
|
75
68
|
process.exitCode = 1;
|
|
76
69
|
}
|
|
77
70
|
});
|
|
78
|
-
// ---
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
.
|
|
82
|
-
.description('Read the full ontology JSON for LLM consumption')
|
|
83
|
-
.requiredOption('--project <path>', 'target project root')).action((options) => {
|
|
84
|
-
try {
|
|
85
|
-
const onto = loadOntology(options.project);
|
|
86
|
-
if (onto === null) {
|
|
87
|
-
// Auto-generate if missing
|
|
88
|
-
const result = generateProjectContext(options.project);
|
|
89
|
-
printResult(io, ok('project.ontology', result.ontology), options.json);
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
printResult(io, ok('project.ontology', onto), options.json);
|
|
93
|
-
}
|
|
94
|
-
catch (error) {
|
|
95
|
-
printResult(io, fail('project.ontology', 'ONTOLOGY_FAILED', getErrorMessage(error), { projectRoot: options.project }, ['Check the project path']), options.json);
|
|
96
|
-
process.exitCode = 1;
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
addJsonOption(ontology
|
|
100
|
-
.command('module')
|
|
101
|
-
.description('Record or query a project module')
|
|
102
|
-
.requiredOption('--project <path>', 'target project root')
|
|
103
|
-
.option('--id <id>', 'module id (kebab-case)')
|
|
104
|
-
.option('--path <path>', 'file path for the module')
|
|
105
|
-
.option('--risk <level>', 'risk level: low, medium, high')
|
|
106
|
-
.option('--summary <text>', 'brief module description')
|
|
107
|
-
.option('--session <id>', 'session id')
|
|
108
|
-
.option('--put', 'write/update the module entry')).action((options) => {
|
|
109
|
-
try {
|
|
110
|
-
if (options.put) {
|
|
111
|
-
if (!options.id || !options.path || !options.session) {
|
|
112
|
-
printResult(io, fail('project.ontology.module', 'MISSING_FIELDS', '--id, --path, --session required with --put', {}, ['Provide all required fields']), options.json);
|
|
113
|
-
process.exitCode = 1;
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
const risk = (options.risk === 'low' || options.risk === 'medium' || options.risk === 'high') ? options.risk : undefined;
|
|
117
|
-
const result = upsertModule(options.project, defined({
|
|
118
|
-
id: options.id,
|
|
119
|
-
path: options.path,
|
|
120
|
-
session: options.session,
|
|
121
|
-
risk,
|
|
122
|
-
summary: options.summary
|
|
123
|
-
}));
|
|
124
|
-
printResult(io, ok('project.ontology.module', { modules: result.modules }), options.json);
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
const onto = loadOntology(options.project) ?? generateProjectContext(options.project).ontology;
|
|
128
|
-
if (options.id) {
|
|
129
|
-
const mod = onto.modules.find((m) => m.id === options.id);
|
|
130
|
-
printResult(io, ok('project.ontology.module', mod ?? { notFound: true, id: options.id }), options.json);
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
printResult(io, ok('project.ontology.module', { modules: onto.modules }), options.json);
|
|
134
|
-
}
|
|
135
|
-
catch (error) {
|
|
136
|
-
printResult(io, fail('project.ontology.module', 'ONTOLOGY_MODULE_FAILED', getErrorMessage(error), {}, []), options.json);
|
|
137
|
-
process.exitCode = 1;
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
addJsonOption(ontology
|
|
141
|
-
.command('decision')
|
|
142
|
-
.description('Record or query architectural decisions')
|
|
71
|
+
// --- Structured project memory (durable, LLM-authored, stored under .peaks/memory) ---
|
|
72
|
+
addJsonOption(project
|
|
73
|
+
.command('memories')
|
|
74
|
+
.description('Read durable project memories (decisions, conventions, modules, rules) from .peaks/memory for LLM consumption')
|
|
143
75
|
.requiredOption('--project <path>', 'target project root')
|
|
144
|
-
.option('--
|
|
145
|
-
.option('--what <text>', 'what was decided')
|
|
146
|
-
.option('--why <text>', 'rationale behind the decision')
|
|
147
|
-
.option('--scope <modules>', 'comma-separated module ids')
|
|
148
|
-
.option('--session <id>', 'session id')
|
|
149
|
-
.option('--date <date>', 'decision date')
|
|
150
|
-
.option('--put', 'write/update the decision')).action((options) => {
|
|
76
|
+
.option('--kind <kind>', 'filter by kind: project, rule, decision, reference, feedback, convention, module')).action((options) => {
|
|
151
77
|
try {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
session: options.session, date: options.date
|
|
162
|
-
}));
|
|
163
|
-
printResult(io, ok('project.ontology.decision', { decisions: result.decisions }), options.json);
|
|
78
|
+
const result = readProjectMemories(options.project);
|
|
79
|
+
if (options.kind) {
|
|
80
|
+
const memories = result.memories.filter((memory) => memory.kind === options.kind);
|
|
81
|
+
printResult(io, ok('project.memories', {
|
|
82
|
+
memoryDir: result.memoryDir,
|
|
83
|
+
kind: options.kind,
|
|
84
|
+
total: memories.length,
|
|
85
|
+
memories
|
|
86
|
+
}), options.json);
|
|
164
87
|
return;
|
|
165
88
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
printResult(io, ok('project.ontology.decision', { decisions: onto.decisions }), options.json);
|
|
89
|
+
printResult(io, ok('project.memories', {
|
|
90
|
+
memoryDir: result.memoryDir,
|
|
91
|
+
total: result.total,
|
|
92
|
+
byKind: result.byKind,
|
|
93
|
+
memories: result.memories
|
|
94
|
+
}), options.json);
|
|
173
95
|
}
|
|
174
96
|
catch (error) {
|
|
175
|
-
printResult(io, fail('project.
|
|
97
|
+
printResult(io, fail('project.memories', 'PROJECT_MEMORIES_FAILED', getErrorMessage(error), { projectRoot: options.project }, ['Check the project path and .peaks/memory directory']), options.json);
|
|
176
98
|
process.exitCode = 1;
|
|
177
99
|
}
|
|
178
100
|
});
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { fail, ok } from '../../shared/result.js';
|
|
2
|
+
import { addJsonOption, printResult, getErrorMessage } from '../cli-helpers.js';
|
|
3
|
+
import { findProjectRoot } from '../../services/config/config-safety.js';
|
|
4
|
+
import { buildStatusLineModel, parseStatusLineStdin } from '../../services/skills/skill-statusline-service.js';
|
|
5
|
+
import { renderStatusLine } from '../../services/skills/skill-statusline-renderer.js';
|
|
6
|
+
import { applyStatusLineInstall, planStatusLineInstall, removeStatusLineInstall } from '../../services/skills/statusline-settings-service.js';
|
|
7
|
+
const STDIN_READ_TIMEOUT_MS = 250;
|
|
8
|
+
/** Read piped stdin if present; resolve quickly with '' when attached to a TTY. */
|
|
9
|
+
function readStdin() {
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
if (process.stdin.isTTY) {
|
|
12
|
+
resolve('');
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
let data = '';
|
|
16
|
+
let settled = false;
|
|
17
|
+
const finish = () => {
|
|
18
|
+
if (settled)
|
|
19
|
+
return;
|
|
20
|
+
settled = true;
|
|
21
|
+
resolve(data);
|
|
22
|
+
};
|
|
23
|
+
const timer = setTimeout(finish, STDIN_READ_TIMEOUT_MS);
|
|
24
|
+
timer.unref?.();
|
|
25
|
+
process.stdin.setEncoding('utf8');
|
|
26
|
+
process.stdin.on('data', (chunk) => {
|
|
27
|
+
data += chunk;
|
|
28
|
+
});
|
|
29
|
+
process.stdin.on('end', () => {
|
|
30
|
+
clearTimeout(timer);
|
|
31
|
+
finish();
|
|
32
|
+
});
|
|
33
|
+
process.stdin.on('error', () => {
|
|
34
|
+
clearTimeout(timer);
|
|
35
|
+
finish();
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function resolveScope(options) {
|
|
40
|
+
return options.global ? 'global' : 'project';
|
|
41
|
+
}
|
|
42
|
+
export function registerStatusLineCommands(program, io) {
|
|
43
|
+
const statusline = program
|
|
44
|
+
.command('statusline')
|
|
45
|
+
.description('Render the Peaks skill status line for Claude Code (reads session JSON on stdin)')
|
|
46
|
+
.option('--project <path>', 'project root path (auto-detected from cwd when omitted)')
|
|
47
|
+
.action(async (options) => {
|
|
48
|
+
const raw = await readStdin();
|
|
49
|
+
const stdin = parseStatusLineStdin(raw);
|
|
50
|
+
// When a project override is passed (or no stdin), seed cwd so detection works.
|
|
51
|
+
const seeded = options.project
|
|
52
|
+
? { ...(stdin ?? {}), workspace: { current_dir: options.project } }
|
|
53
|
+
: stdin;
|
|
54
|
+
const model = buildStatusLineModel(seeded, Date.now());
|
|
55
|
+
io.stdout(renderStatusLine(model));
|
|
56
|
+
});
|
|
57
|
+
addJsonOption(statusline
|
|
58
|
+
.command('install')
|
|
59
|
+
.description('Install the Peaks status line into .claude/settings.json (project scope by default)')
|
|
60
|
+
.option('--global', 'install into the user-level ~/.claude/settings.json instead of the project')
|
|
61
|
+
.option('--project <path>', 'project root path (auto-detected from cwd when omitted)')
|
|
62
|
+
.option('--force', 'overwrite an existing non-Peaks statusLine entry')
|
|
63
|
+
.option('--dry-run', 'show what would change without writing')).action((options) => {
|
|
64
|
+
const scope = resolveScope(options);
|
|
65
|
+
const projectRoot = scope === 'project'
|
|
66
|
+
? (options.project ?? findProjectRoot(process.cwd()) ?? process.cwd())
|
|
67
|
+
: undefined;
|
|
68
|
+
try {
|
|
69
|
+
if (options.dryRun) {
|
|
70
|
+
const plan = planStatusLineInstall(scope, projectRoot);
|
|
71
|
+
const warnings = plan.conflict
|
|
72
|
+
? [`An existing statusLine command is set: ${plan.conflictCommand}. Rerun with --force to overwrite.`]
|
|
73
|
+
: [];
|
|
74
|
+
printResult(io, ok('statusline.install', { ...plan, applied: false, dryRun: true }, warnings), options.json);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const result = applyStatusLineInstall(scope, projectRoot, options.force ? { force: true } : {});
|
|
78
|
+
const warnings = result.conflict && !result.applied
|
|
79
|
+
? [`An existing statusLine command is set: ${result.conflictCommand}. Rerun with --force to overwrite.`]
|
|
80
|
+
: [];
|
|
81
|
+
const nextActions = result.applied
|
|
82
|
+
? ['Restart Claude Code (or reload the window) so the status line takes effect']
|
|
83
|
+
: [];
|
|
84
|
+
printResult(io, ok('statusline.install', { ...result, dryRun: false }, warnings, nextActions), options.json);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
const message = getErrorMessage(error);
|
|
88
|
+
printResult(io, fail('statusline.install', 'STATUSLINE_INSTALL_FAILED', message, { scope, applied: false }, [message]), options.json);
|
|
89
|
+
process.exitCode = 1;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
addJsonOption(statusline
|
|
93
|
+
.command('uninstall')
|
|
94
|
+
.description('Remove the Peaks status line from .claude/settings.json')
|
|
95
|
+
.option('--global', 'remove from the user-level ~/.claude/settings.json instead of the project')
|
|
96
|
+
.option('--project <path>', 'project root path (auto-detected from cwd when omitted)')).action((options) => {
|
|
97
|
+
const scope = resolveScope(options);
|
|
98
|
+
const projectRoot = scope === 'project'
|
|
99
|
+
? (options.project ?? findProjectRoot(process.cwd()) ?? process.cwd())
|
|
100
|
+
: undefined;
|
|
101
|
+
try {
|
|
102
|
+
const result = removeStatusLineInstall(scope, projectRoot);
|
|
103
|
+
printResult(io, ok('statusline.uninstall', result), options.json);
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
const message = getErrorMessage(error);
|
|
107
|
+
printResult(io, fail('statusline.uninstall', 'STATUSLINE_UNINSTALL_FAILED', message, { scope, removed: false }, [message]), options.json);
|
|
108
|
+
process.exitCode = 1;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
package/dist/src/cli/program.js
CHANGED
|
@@ -10,6 +10,7 @@ import { registerProjectCommands } from './commands/project-commands.js';
|
|
|
10
10
|
import { registerRequestCommands } from './commands/request-commands.js';
|
|
11
11
|
import { registerScanCommands } from './commands/scan-commands.js';
|
|
12
12
|
import { registerShadcnCommands } from './commands/shadcn-commands.js';
|
|
13
|
+
import { registerStatusLineCommands } from './commands/statusline-commands.js';
|
|
13
14
|
import { registerUnderstandCommands } from './commands/understand-commands.js';
|
|
14
15
|
import { registerWorkspaceCommands } from './commands/workspace-commands.js';
|
|
15
16
|
export { printResult } from './cli-helpers.js';
|
|
@@ -40,6 +41,7 @@ export function createProgram(io = { stdout: (text) => console.log(text), stderr
|
|
|
40
41
|
registerRequestCommands(program, io);
|
|
41
42
|
registerScanCommands(program, io);
|
|
42
43
|
registerShadcnCommands(program, io);
|
|
44
|
+
registerStatusLineCommands(program, io);
|
|
43
45
|
registerUnderstandCommands(program, io);
|
|
44
46
|
registerWorkspaceCommands(program, io);
|
|
45
47
|
return program;
|
|
@@ -24,5 +24,6 @@ export type DoctorOptions = {
|
|
|
24
24
|
codegraphProbe?: () => CodegraphCapabilityProbe;
|
|
25
25
|
skillPresenceProbe?: () => SkillPresence | null;
|
|
26
26
|
skillPresenceFreshnessThresholdMs?: number;
|
|
27
|
+
statusLineInstalledProbe?: () => boolean;
|
|
27
28
|
};
|
|
28
29
|
export declare function runDoctor(options?: DoctorOptions): Promise<DoctorReport>;
|
|
@@ -8,6 +8,8 @@ import { requiredSchemaFiles, requiredSkillNames, schemasDir } from '../../share
|
|
|
8
8
|
import { getErrorMessage } from '../../shared/result.js';
|
|
9
9
|
import { loadSkillRegistry } from '../skills/skill-registry.js';
|
|
10
10
|
import { getSkillPresence } from '../skills/skill-presence-service.js';
|
|
11
|
+
import { planStatusLineInstall } from '../skills/statusline-settings-service.js';
|
|
12
|
+
import { findProjectRoot } from '../config/config-safety.js';
|
|
11
13
|
const CODEGRAPH_EXPECTED_VERSION = '0.7.10';
|
|
12
14
|
const SKILL_PRESENCE_FRESHNESS_THRESHOLD_MS = 24 * 60 * 60 * 1000;
|
|
13
15
|
function defaultCodegraphProbe() {
|
|
@@ -22,6 +24,17 @@ function defaultCodegraphProbe() {
|
|
|
22
24
|
binaryExists: existsSync(binaryPath)
|
|
23
25
|
};
|
|
24
26
|
}
|
|
27
|
+
function defaultStatusLineInstalledProbe() {
|
|
28
|
+
const projectRoot = findProjectRoot(process.cwd());
|
|
29
|
+
if (projectRoot === null)
|
|
30
|
+
return false;
|
|
31
|
+
try {
|
|
32
|
+
return planStatusLineInstall('project', projectRoot).alreadyInstalled;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
25
38
|
const DESTRUCTIVE_APPLY_PATTERNS = [
|
|
26
39
|
/peaks\s+memory\s+sync[^\n]*--apply/,
|
|
27
40
|
/peaks\s+memory\s+extract[^\n]*--apply/,
|
|
@@ -190,6 +203,33 @@ export async function runDoctor(options = {}) {
|
|
|
190
203
|
}
|
|
191
204
|
}
|
|
192
205
|
}
|
|
206
|
+
// Discoverability nudge: when a skill is actively orchestrating but the
|
|
207
|
+
// out-of-band statusLine isn't installed, the user has no terminal-level
|
|
208
|
+
// signal that Peaks is in control. Suggest installing it (non-failing).
|
|
209
|
+
const statusLineProbe = options.statusLineInstalledProbe ?? defaultStatusLineInstalledProbe;
|
|
210
|
+
let statusLineInstalled = false;
|
|
211
|
+
try {
|
|
212
|
+
statusLineInstalled = statusLineProbe();
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
statusLineInstalled = false;
|
|
216
|
+
}
|
|
217
|
+
if (presence !== null && !statusLineInstalled) {
|
|
218
|
+
checks.push({
|
|
219
|
+
id: 'statusline:install',
|
|
220
|
+
ok: true,
|
|
221
|
+
message: 'A Peaks skill is active but the statusLine is not installed; run `peaks statusline install` so the active skill shows in the terminal status bar'
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
checks.push({
|
|
226
|
+
id: 'statusline:install',
|
|
227
|
+
ok: true,
|
|
228
|
+
message: statusLineInstalled
|
|
229
|
+
? 'Peaks statusLine is installed'
|
|
230
|
+
: 'Peaks statusLine not installed (no active skill; install optional)'
|
|
231
|
+
});
|
|
232
|
+
}
|
|
193
233
|
const probe = options.codegraphProbe ?? defaultCodegraphProbe;
|
|
194
234
|
try {
|
|
195
235
|
const result = probe();
|
|
@@ -2,48 +2,10 @@ export type ProjectContextSection = {
|
|
|
2
2
|
heading: string;
|
|
3
3
|
body: string;
|
|
4
4
|
};
|
|
5
|
-
export type Module = {
|
|
6
|
-
id: string;
|
|
7
|
-
path: string;
|
|
8
|
-
risk?: 'low' | 'medium' | 'high';
|
|
9
|
-
sessions: string[];
|
|
10
|
-
summary?: string;
|
|
11
|
-
};
|
|
12
|
-
export type Decision = {
|
|
13
|
-
id: string;
|
|
14
|
-
what: string;
|
|
15
|
-
why?: string;
|
|
16
|
-
scope: string[];
|
|
17
|
-
session: string;
|
|
18
|
-
date: string;
|
|
19
|
-
};
|
|
20
|
-
export type Convention = {
|
|
21
|
-
id: string;
|
|
22
|
-
rule: string;
|
|
23
|
-
category: 'code-style' | 'architecture' | 'naming' | 'tooling' | 'other';
|
|
24
|
-
source: string;
|
|
25
|
-
date: string;
|
|
26
|
-
};
|
|
27
|
-
export type Ontology = {
|
|
28
|
-
version: 1;
|
|
29
|
-
updated: string;
|
|
30
|
-
project: string;
|
|
31
|
-
modules: Module[];
|
|
32
|
-
decisions: Decision[];
|
|
33
|
-
conventions: Convention[];
|
|
34
|
-
};
|
|
35
|
-
export declare function loadOntology(projectRoot: string): Ontology | null;
|
|
36
|
-
export declare function saveOntology(projectRoot: string, onto: Ontology): void;
|
|
37
|
-
export declare function upsertModule(projectRoot: string, mod: Omit<Module, 'sessions'> & {
|
|
38
|
-
session: string;
|
|
39
|
-
}): Ontology;
|
|
40
|
-
export declare function upsertDecision(projectRoot: string, dec: Decision): Ontology;
|
|
41
|
-
export declare function upsertConvention(projectRoot: string, conv: Convention): Ontology;
|
|
42
5
|
export declare function generateProjectContext(projectRoot: string): {
|
|
43
6
|
path: string;
|
|
44
7
|
content: string;
|
|
45
8
|
sessionCount: number;
|
|
46
|
-
ontology: Ontology;
|
|
47
9
|
};
|
|
48
10
|
export declare function readProjectContext(projectRoot: string): string | null;
|
|
49
11
|
export declare function getProjectContextPath(projectRoot: string): string;
|