peaks-cli 1.0.12 → 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/bin/peaks.js +0 -0
  2. package/dist/src/cli/commands/config-commands.js +1 -17
  3. package/dist/src/cli/commands/core-artifact-commands.js +48 -0
  4. package/dist/src/cli/commands/mcp-commands.d.ts +3 -0
  5. package/dist/src/cli/commands/mcp-commands.js +144 -0
  6. package/dist/src/cli/commands/openspec-commands.d.ts +3 -0
  7. package/dist/src/cli/commands/openspec-commands.js +169 -0
  8. package/dist/src/cli/commands/project-commands.d.ts +3 -0
  9. package/dist/src/cli/commands/project-commands.js +37 -0
  10. package/dist/src/cli/commands/request-commands.d.ts +3 -0
  11. package/dist/src/cli/commands/request-commands.js +140 -0
  12. package/dist/src/cli/commands/understand-commands.d.ts +3 -0
  13. package/dist/src/cli/commands/understand-commands.js +78 -0
  14. package/dist/src/cli/commands/workflow-commands.js +56 -94
  15. package/dist/src/cli/program.js +10 -0
  16. package/dist/src/services/artifacts/request-artifact-service.d.ts +58 -0
  17. package/dist/src/services/artifacts/request-artifact-service.js +432 -0
  18. package/dist/src/services/codegraph/codegraph-process-runner.d.ts +2 -0
  19. package/dist/src/services/codegraph/codegraph-process-runner.js +93 -0
  20. package/dist/src/services/codegraph/codegraph-service.js +13 -128
  21. package/dist/src/services/config/config-service.js +2 -22
  22. package/dist/src/services/dashboard/project-dashboard-service.d.ts +64 -0
  23. package/dist/src/services/dashboard/project-dashboard-service.js +112 -0
  24. package/dist/src/services/doctor/doctor-service.d.ts +7 -0
  25. package/dist/src/services/doctor/doctor-service.js +139 -0
  26. package/dist/src/services/mcp/mcp-apply-service.d.ts +31 -0
  27. package/dist/src/services/mcp/mcp-apply-service.js +112 -0
  28. package/dist/src/services/mcp/mcp-call-service.d.ts +17 -0
  29. package/dist/src/services/mcp/mcp-call-service.js +34 -0
  30. package/dist/src/services/mcp/mcp-client-service.d.ts +14 -0
  31. package/dist/src/services/mcp/mcp-client-service.js +49 -0
  32. package/dist/src/services/mcp/mcp-install-registry.d.ts +11 -0
  33. package/dist/src/services/mcp/mcp-install-registry.js +38 -0
  34. package/dist/src/services/mcp/mcp-plan-service.d.ts +29 -0
  35. package/dist/src/services/mcp/mcp-plan-service.js +109 -0
  36. package/dist/src/services/mcp/mcp-protocol.d.ts +24 -0
  37. package/dist/src/services/mcp/mcp-protocol.js +41 -0
  38. package/dist/src/services/mcp/mcp-scan-service.d.ts +8 -0
  39. package/dist/src/services/mcp/mcp-scan-service.js +214 -0
  40. package/dist/src/services/mcp/mcp-stdio-transport.d.ts +10 -0
  41. package/dist/src/services/mcp/mcp-stdio-transport.js +50 -0
  42. package/dist/src/services/mcp/mcp-types.d.ts +31 -0
  43. package/dist/src/services/mcp/mcp-types.js +1 -0
  44. package/dist/src/services/openspec/openspec-archive-service.d.ts +12 -0
  45. package/dist/src/services/openspec/openspec-archive-service.js +28 -0
  46. package/dist/src/services/openspec/openspec-bridge-service.d.ts +16 -0
  47. package/dist/src/services/openspec/openspec-bridge-service.js +76 -0
  48. package/dist/src/services/openspec/openspec-render-service.d.ts +38 -0
  49. package/dist/src/services/openspec/openspec-render-service.js +130 -0
  50. package/dist/src/services/openspec/openspec-scan-service.d.ts +6 -0
  51. package/dist/src/services/openspec/openspec-scan-service.js +123 -0
  52. package/dist/src/services/openspec/openspec-types.d.ts +39 -0
  53. package/dist/src/services/openspec/openspec-types.js +1 -0
  54. package/dist/src/services/openspec/openspec-validate-service.d.ts +27 -0
  55. package/dist/src/services/openspec/openspec-validate-service.js +77 -0
  56. package/dist/src/services/recommendations/capability-seed-items.js +2 -1
  57. package/dist/src/services/recommendations/capability-seed-mappings.js +1 -1
  58. package/dist/src/services/recommendations/capability-seed-sources.js +1 -1
  59. package/dist/src/services/shadcn/shadcn-service.d.ts +4 -0
  60. package/dist/src/services/shadcn/shadcn-service.js +15 -30
  61. package/dist/src/services/skills/skill-presence-service.d.ts +10 -0
  62. package/dist/src/services/skills/skill-presence-service.js +54 -0
  63. package/dist/src/services/skills/skill-runbook-service.d.ts +11 -0
  64. package/dist/src/services/skills/skill-runbook-service.js +60 -0
  65. package/dist/src/services/standards/project-standards-service.js +4 -9
  66. package/dist/src/services/understand/understand-scan-service.d.ts +28 -0
  67. package/dist/src/services/understand/understand-scan-service.js +157 -0
  68. package/dist/src/services/understand/understand-types.d.ts +24 -0
  69. package/dist/src/services/understand/understand-types.js +1 -0
  70. package/dist/src/services/workflow/workflow-autonomous-service.js +7 -13
  71. package/dist/src/shared/json-schema-mini.d.ts +10 -0
  72. package/dist/src/shared/json-schema-mini.js +113 -0
  73. package/dist/src/shared/paths.d.ts +1 -1
  74. package/dist/src/shared/paths.js +9 -1
  75. package/dist/src/shared/version.d.ts +1 -1
  76. package/dist/src/shared/version.js +1 -1
  77. package/package.json +2 -8
  78. package/schemas/doctor-report.schema.json +34 -0
  79. package/schemas/mcp-apply-result.schema.json +46 -0
  80. package/schemas/mcp-install-plan.schema.json +71 -0
  81. package/schemas/mcp-install-spec.schema.json +29 -0
  82. package/schemas/mcp-server.schema.json +29 -0
  83. package/schemas/openspec-change-summary.schema.json +68 -0
  84. package/schemas/openspec-render-request.schema.json +61 -0
  85. package/schemas/openspec-validation-result.schema.json +36 -0
  86. package/skills/peaks-prd/SKILL.md +61 -8
  87. package/skills/peaks-prd/references/artifact-per-request.md +78 -0
  88. package/skills/peaks-prd/references/workflow.md +7 -5
  89. package/skills/peaks-qa/SKILL.md +76 -8
  90. package/skills/peaks-qa/references/artifact-contracts.md +2 -2
  91. package/skills/peaks-qa/references/artifact-per-request.md +83 -0
  92. package/skills/peaks-qa/references/openspec-validation-gate.md +55 -0
  93. package/skills/peaks-qa/references/regression-gates.md +2 -2
  94. package/skills/peaks-rd/SKILL.md +98 -9
  95. package/skills/peaks-rd/references/artifact-contracts.md +2 -2
  96. package/skills/peaks-rd/references/artifact-per-request.md +90 -0
  97. package/skills/peaks-rd/references/openspec-mcp-cli.md +65 -0
  98. package/skills/peaks-rd/references/refactor-workflow.md +2 -2
  99. package/skills/peaks-sc/SKILL.md +46 -0
  100. package/skills/peaks-sc/references/openspec-commit-boundaries.md +33 -0
  101. package/skills/peaks-solo/SKILL.md +92 -9
  102. package/skills/peaks-solo/references/artifact-contracts.md +2 -2
  103. package/skills/peaks-solo/references/browser-workflow.md +114 -0
  104. package/skills/peaks-solo/references/external-skill-invocation.md +70 -0
  105. package/skills/peaks-solo/references/openspec-mcp-workflow.md +53 -0
  106. package/skills/peaks-solo/references/refactor-mode.md +2 -2
  107. package/skills/peaks-solo/references/workflow.md +1 -1
  108. package/skills/peaks-txt/SKILL.md +44 -0
  109. package/skills/peaks-ui/SKILL.md +59 -33
  110. package/skills/peaks-ui/references/artifact-per-request.md +71 -0
  111. package/skills/peaks-ui/references/workflow.md +8 -11
  112. package/scripts/strip-internal-exports.mjs +0 -33
@@ -0,0 +1,157 @@
1
+ import { stat } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { isDirectory, pathExists, readText } from '../../shared/fs.js';
4
+ import { getErrorMessage } from '../../shared/result.js';
5
+ function defaultArtifactDir(projectRoot) {
6
+ return join(projectRoot, '.understand-anything');
7
+ }
8
+ function countArrayField(record, key) {
9
+ const value = record[key];
10
+ return Array.isArray(value) ? value.length : 0;
11
+ }
12
+ async function readFlag(path) {
13
+ return { exists: await pathExists(path), path };
14
+ }
15
+ async function readGraph(graphPath) {
16
+ if (!(await pathExists(graphPath))) {
17
+ return { exists: false, path: graphPath };
18
+ }
19
+ const stats = await stat(graphPath);
20
+ const raw = await readText(graphPath);
21
+ try {
22
+ const parsed = JSON.parse(raw);
23
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
24
+ return {
25
+ exists: true,
26
+ path: graphPath,
27
+ sizeBytes: stats.size,
28
+ parseError: 'knowledge-graph.json must be a JSON object'
29
+ };
30
+ }
31
+ const record = parsed;
32
+ return {
33
+ exists: true,
34
+ path: graphPath,
35
+ sizeBytes: stats.size,
36
+ topLevelFields: Object.keys(record).sort(),
37
+ counts: {
38
+ nodes: countArrayField(record, 'nodes'),
39
+ edges: countArrayField(record, 'edges'),
40
+ layers: countArrayField(record, 'layers'),
41
+ tours: countArrayField(record, 'tours')
42
+ }
43
+ };
44
+ }
45
+ catch (error) {
46
+ return {
47
+ exists: true,
48
+ path: graphPath,
49
+ sizeBytes: stats.size,
50
+ parseError: getErrorMessage(error)
51
+ };
52
+ }
53
+ }
54
+ export async function scanUnderstandAnything(options) {
55
+ const artifactDir = options.artifactDir ?? defaultArtifactDir(options.projectRoot);
56
+ const exists = await isDirectory(artifactDir);
57
+ if (!exists) {
58
+ return {
59
+ exists: false,
60
+ artifactDir,
61
+ graph: { exists: false, path: join(artifactDir, 'knowledge-graph.json') },
62
+ intermediate: { exists: false, path: join(artifactDir, 'intermediate') },
63
+ diffOverlay: { exists: false, path: join(artifactDir, 'diff-overlay.json') }
64
+ };
65
+ }
66
+ const graph = await readGraph(join(artifactDir, 'knowledge-graph.json'));
67
+ const intermediate = await readFlag(join(artifactDir, 'intermediate'));
68
+ const diffOverlay = await readFlag(join(artifactDir, 'diff-overlay.json'));
69
+ return { exists: true, artifactDir, graph, intermediate, diffOverlay };
70
+ }
71
+ function pickStringId(value) {
72
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
73
+ return null;
74
+ }
75
+ const record = value;
76
+ for (const key of ['id', 'path', 'name', 'label']) {
77
+ const candidate = record[key];
78
+ if (typeof candidate === 'string' && candidate.length > 0) {
79
+ return candidate;
80
+ }
81
+ }
82
+ return null;
83
+ }
84
+ function pickStringField(record, key) {
85
+ const value = record[key];
86
+ return typeof value === 'string' && value.length > 0 ? value : null;
87
+ }
88
+ function pickNameArray(record, key) {
89
+ const value = record[key];
90
+ if (!Array.isArray(value)) {
91
+ return [];
92
+ }
93
+ return value
94
+ .map((entry) => {
95
+ if (typeof entry === 'string') {
96
+ return entry;
97
+ }
98
+ return pickStringId(entry);
99
+ })
100
+ .filter((entry) => entry !== null);
101
+ }
102
+ export async function summarizeKnowledgeGraph(options) {
103
+ const scanOptions = { projectRoot: options.projectRoot };
104
+ if (options.artifactDir !== undefined) {
105
+ scanOptions.artifactDir = options.artifactDir;
106
+ }
107
+ const scan = await scanUnderstandAnything(scanOptions);
108
+ const sampleSize = options.sampleSize ?? 5;
109
+ if (!scan.graph.exists) {
110
+ return {
111
+ exists: false,
112
+ path: scan.graph.path,
113
+ generatedAt: null,
114
+ topLevelFields: [],
115
+ counts: { nodes: 0, edges: 0, layers: 0, tours: 0 },
116
+ layerNames: [],
117
+ tourNames: [],
118
+ sampleNodes: []
119
+ };
120
+ }
121
+ if (scan.graph.parseError !== undefined) {
122
+ return {
123
+ exists: true,
124
+ path: scan.graph.path,
125
+ generatedAt: null,
126
+ topLevelFields: [],
127
+ counts: { nodes: 0, edges: 0, layers: 0, tours: 0 },
128
+ layerNames: [],
129
+ tourNames: [],
130
+ sampleNodes: [],
131
+ parseError: scan.graph.parseError
132
+ };
133
+ }
134
+ const raw = await readText(scan.graph.path);
135
+ const parsed = JSON.parse(raw);
136
+ const record = parsed;
137
+ const generatedAt = pickStringField(record, 'generatedAt');
138
+ const nodes = Array.isArray(record.nodes) ? record.nodes : [];
139
+ const sampleNodes = nodes.slice(0, sampleSize)
140
+ .map((entry) => pickStringId(entry))
141
+ .filter((entry) => entry !== null);
142
+ return {
143
+ exists: true,
144
+ path: scan.graph.path,
145
+ generatedAt,
146
+ topLevelFields: Object.keys(record).sort(),
147
+ counts: {
148
+ nodes: countArrayField(record, 'nodes'),
149
+ edges: countArrayField(record, 'edges'),
150
+ layers: countArrayField(record, 'layers'),
151
+ tours: countArrayField(record, 'tours')
152
+ },
153
+ layerNames: pickNameArray(record, 'layers'),
154
+ tourNames: pickNameArray(record, 'tours'),
155
+ sampleNodes
156
+ };
157
+ }
@@ -0,0 +1,24 @@
1
+ export type UnderstandGraphReport = {
2
+ exists: boolean;
3
+ path: string;
4
+ sizeBytes?: number;
5
+ topLevelFields?: string[];
6
+ counts?: {
7
+ nodes: number;
8
+ edges: number;
9
+ layers: number;
10
+ tours: number;
11
+ };
12
+ parseError?: string;
13
+ };
14
+ export type UnderstandFlagReport = {
15
+ exists: boolean;
16
+ path: string;
17
+ };
18
+ export type UnderstandScanReport = {
19
+ exists: boolean;
20
+ artifactDir: string;
21
+ graph: UnderstandGraphReport;
22
+ intermediate: UnderstandFlagReport;
23
+ diffOverlay: UnderstandFlagReport;
24
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -250,9 +250,6 @@ function readResumeArtifact(artifactWorkspacePath, artifact) {
250
250
  return null;
251
251
  }
252
252
  const pathSegments = artifact.replace(/\\/g, '/').split('/');
253
- if (pathSegments.length < 4 || pathSegments[0] !== '.peaks') {
254
- return null;
255
- }
256
253
  const sessionRootPath = resolve(artifactWorkspacePath, '.peaks', pathSegments[1]);
257
254
  const roleRootPath = resolve(sessionRootPath, pathSegments[2]);
258
255
  if (lstatSync(sessionRootPath).isSymbolicLink() || lstatSync(roleRootPath).isSymbolicLink()) {
@@ -261,16 +258,13 @@ function readResumeArtifact(artifactWorkspacePath, artifact) {
261
258
  let allowedRootRealPath;
262
259
  if (pathSegments[2] === 'rd') {
263
260
  const swarmRootPath = resolve(roleRootPath, 'swarm');
264
- if (pathSegments[3] !== 'swarm' || lstatSync(swarmRootPath).isSymbolicLink()) {
261
+ if (lstatSync(swarmRootPath).isSymbolicLink()) {
265
262
  return null;
266
263
  }
267
264
  allowedRootRealPath = realpathSync(swarmRootPath);
268
265
  }
269
- else if (pathSegments[2] === 'prd') {
270
- allowedRootRealPath = realpathSync(roleRootPath);
271
- }
272
266
  else {
273
- return null;
267
+ allowedRootRealPath = realpathSync(roleRootPath);
274
268
  }
275
269
  const artifactRealPath = realpathSync(artifactPath);
276
270
  if (!isInsidePath(allowedRootRealPath, artifactWorkspaceRealPath) || !isInsidePath(artifactRealPath, allowedRootRealPath)) {
@@ -354,12 +348,12 @@ function parseFrontMatter(content) {
354
348
  if (lines[0] !== '---') {
355
349
  return null;
356
350
  }
357
- const endIndex = lines.slice(1).findIndex((line) => line === '---');
358
- if (endIndex === -1) {
351
+ const closingDelimiterIndex = lines.slice(1).findIndex((line) => line === '---');
352
+ if (closingDelimiterIndex === -1) {
359
353
  return null;
360
354
  }
361
355
  const metadata = new Map();
362
- for (const line of lines.slice(1, endIndex + 1)) {
356
+ for (const line of lines.slice(1, closingDelimiterIndex + 1)) {
363
357
  const separatorIndex = line.indexOf(':');
364
358
  if (separatorIndex === -1) {
365
359
  return null;
@@ -370,8 +364,8 @@ function parseFrontMatter(content) {
370
364
  }
371
365
  function getMarkdownBody(content) {
372
366
  const lines = content.split(/\r?\n/);
373
- const endIndex = lines.slice(1).findIndex((line) => line === '---');
374
- return endIndex === -1 ? '' : lines.slice(endIndex + 2).join('\n');
367
+ const closingDelimiterIndex = lines.slice(1).findIndex((line) => line === '---');
368
+ return closingDelimiterIndex === -1 ? '' : lines.slice(closingDelimiterIndex + 2).join('\n');
375
369
  }
376
370
  function hasValidationReportBody(body) {
377
371
  return body.includes('Validation summary:')
@@ -0,0 +1,10 @@
1
+ export type JsonSchemaIssue = {
2
+ path: string;
3
+ message: string;
4
+ };
5
+ export type JsonSchemaResult = {
6
+ valid: boolean;
7
+ errors: JsonSchemaIssue[];
8
+ };
9
+ export type JsonSchemaNode = Record<string, unknown>;
10
+ export declare function validateAgainstSchema(value: unknown, schema: JsonSchemaNode): JsonSchemaResult;
@@ -0,0 +1,113 @@
1
+ function joinPath(parent, segment) {
2
+ if (parent === '/') {
3
+ return `/${segment}`;
4
+ }
5
+ return `${parent}/${segment}`;
6
+ }
7
+ function typeOf(value) {
8
+ if (value === null) {
9
+ return 'null';
10
+ }
11
+ if (Array.isArray(value)) {
12
+ return 'array';
13
+ }
14
+ if (Number.isInteger(value)) {
15
+ return 'integer';
16
+ }
17
+ return typeof value;
18
+ }
19
+ function matchesType(value, expected) {
20
+ if (expected === 'integer') {
21
+ return typeof value === 'number' && Number.isFinite(value) && Number.isInteger(value);
22
+ }
23
+ if (expected === 'number') {
24
+ return typeof value === 'number' && Number.isFinite(value);
25
+ }
26
+ if (expected === 'array') {
27
+ return Array.isArray(value);
28
+ }
29
+ if (expected === 'null') {
30
+ return value === null;
31
+ }
32
+ if (expected === 'object') {
33
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
34
+ }
35
+ return typeof value === expected;
36
+ }
37
+ function validateNode(value, schema, path, errors) {
38
+ if (Array.isArray(schema.oneOf)) {
39
+ const branches = schema.oneOf;
40
+ const branchErrors = [];
41
+ let matched = false;
42
+ for (const branch of branches) {
43
+ const sink = [];
44
+ validateNode(value, branch, path, sink);
45
+ if (sink.length === 0) {
46
+ matched = true;
47
+ break;
48
+ }
49
+ branchErrors.push(sink);
50
+ }
51
+ if (!matched) {
52
+ const detail = branchErrors.map((sink) => sink.map((issue) => issue.message).join(' / ')).join(' | ');
53
+ errors.push({ path, message: `does not match any oneOf branch (${detail})` });
54
+ }
55
+ return;
56
+ }
57
+ const expectedType = typeof schema.type === 'string' ? schema.type : null;
58
+ if (expectedType !== null && !matchesType(value, expectedType)) {
59
+ errors.push({ path, message: `expected type ${expectedType}, got ${typeOf(value)}` });
60
+ return;
61
+ }
62
+ if (typeof value === 'string') {
63
+ if (typeof schema.minLength === 'number' && value.length < schema.minLength) {
64
+ errors.push({ path, message: `string shorter than minLength ${schema.minLength}` });
65
+ }
66
+ if (typeof schema.pattern === 'string' && !new RegExp(schema.pattern).test(value)) {
67
+ errors.push({ path, message: `string does not match pattern ${schema.pattern}` });
68
+ }
69
+ if (Array.isArray(schema.enum) && !schema.enum.includes(value)) {
70
+ errors.push({ path, message: `value ${JSON.stringify(value)} is not in enum` });
71
+ }
72
+ return;
73
+ }
74
+ if (typeof value === 'number') {
75
+ if (typeof schema.minimum === 'number' && value < schema.minimum) {
76
+ errors.push({ path, message: `number below minimum ${schema.minimum}` });
77
+ }
78
+ return;
79
+ }
80
+ if (Array.isArray(value)) {
81
+ if (schema.items !== undefined) {
82
+ const itemSchema = schema.items;
83
+ value.forEach((entry, index) => {
84
+ validateNode(entry, itemSchema, joinPath(path, index), errors);
85
+ });
86
+ }
87
+ return;
88
+ }
89
+ if (value !== null && typeof value === 'object') {
90
+ const record = value;
91
+ if (Array.isArray(schema.required)) {
92
+ for (const key of schema.required) {
93
+ if (!Object.prototype.hasOwnProperty.call(record, key)) {
94
+ errors.push({ path, message: `missing required property: ${key}` });
95
+ }
96
+ }
97
+ }
98
+ const properties = schema.properties;
99
+ if (properties !== null && typeof properties === 'object' && !Array.isArray(properties)) {
100
+ const propertyMap = properties;
101
+ for (const [key, child] of Object.entries(propertyMap)) {
102
+ if (Object.prototype.hasOwnProperty.call(record, key)) {
103
+ validateNode(record[key], child, joinPath(path, key), errors);
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
109
+ export function validateAgainstSchema(value, schema) {
110
+ const errors = [];
111
+ validateNode(value, schema, '/', errors);
112
+ return { valid: errors.length === 0, errors };
113
+ }
@@ -3,4 +3,4 @@ export declare const skillsDir: string;
3
3
  export declare const schemasDir: string;
4
4
  export declare const templatesDir: string;
5
5
  export declare const requiredSkillNames: readonly ["peaks-solo", "peaks-prd", "peaks-ui", "peaks-rd", "peaks-qa", "peaks-sc", "peaks-txt"];
6
- export declare const requiredSchemaFiles: readonly ["artifact-manifest.schema.json", "context-capsule.schema.json", "approval-record.schema.json", "change-impact.schema.json", "refactor-slice-spec.schema.json", "artifact-retention-report.schema.json", "capability-source.schema.json", "capability-item.schema.json", "capability-availability.schema.json", "recommendation-plan.schema.json", "artifact-workspace.schema.json"];
6
+ export declare const requiredSchemaFiles: readonly ["artifact-manifest.schema.json", "context-capsule.schema.json", "approval-record.schema.json", "change-impact.schema.json", "refactor-slice-spec.schema.json", "artifact-retention-report.schema.json", "capability-source.schema.json", "capability-item.schema.json", "capability-availability.schema.json", "recommendation-plan.schema.json", "artifact-workspace.schema.json", "mcp-server.schema.json", "mcp-install-spec.schema.json", "mcp-install-plan.schema.json", "mcp-apply-result.schema.json", "openspec-change-summary.schema.json", "openspec-render-request.schema.json", "openspec-validation-result.schema.json", "doctor-report.schema.json"];
@@ -36,5 +36,13 @@ export const requiredSchemaFiles = [
36
36
  'capability-item.schema.json',
37
37
  'capability-availability.schema.json',
38
38
  'recommendation-plan.schema.json',
39
- 'artifact-workspace.schema.json'
39
+ 'artifact-workspace.schema.json',
40
+ 'mcp-server.schema.json',
41
+ 'mcp-install-spec.schema.json',
42
+ 'mcp-install-plan.schema.json',
43
+ 'mcp-apply-result.schema.json',
44
+ 'openspec-change-summary.schema.json',
45
+ 'openspec-render-request.schema.json',
46
+ 'openspec-validation-result.schema.json',
47
+ 'doctor-report.schema.json'
40
48
  ];
@@ -1 +1 @@
1
- export declare const CLI_VERSION = "1.0.12";
1
+ export declare const CLI_VERSION = "1.0.14";
@@ -1 +1 @@
1
- export const CLI_VERSION = "1.0.12";
1
+ export const CLI_VERSION = "1.0.14";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peaks-cli",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "description": "Peaks CLI and short skill family for Claude Code automation.",
5
5
  "author": "SquabbyZ",
6
6
  "license": "MIT",
@@ -21,7 +21,6 @@
21
21
  "scripts/sync-version.mjs",
22
22
  "scripts/install-skills.mjs",
23
23
  "scripts/watch.mjs",
24
- "scripts/strip-internal-exports.mjs",
25
24
  "skills/**",
26
25
  "!skills/**/test-prompts.json",
27
26
  "!skills/**/.DS_Store",
@@ -29,14 +28,13 @@
29
28
  "schemas/*.json"
30
29
  ],
31
30
  "scripts": {
32
- "build": "node ./scripts/sync-version.mjs && node ./scripts/clean-dist.mjs && tsc -p tsconfig.json && node ./scripts/strip-internal-exports.mjs",
31
+ "build": "node ./scripts/sync-version.mjs && node ./scripts/clean-dist.mjs && tsc -p tsconfig.json",
33
32
  "prepack": "npm run build",
34
33
  "postinstall": "node ./scripts/install-skills.mjs",
35
34
  "dev": "tsx src/cli/index.ts",
36
35
  "dev:watch": "node ./scripts/watch.mjs",
37
36
  "test": "vitest run",
38
37
  "test:coverage": "vitest run --coverage",
39
- "lint": "eslint eslint.config.js \"bin/**/*.js\" \"scripts/**/*.mjs\" \"src/**/*.ts\" \"tests/**/*.ts\" vitest.config.ts",
40
38
  "typecheck": "tsc -p tsconfig.json --noEmit"
41
39
  },
42
40
  "engines": {
@@ -48,14 +46,10 @@
48
46
  "shadcn": "4.7.0"
49
47
  },
50
48
  "devDependencies": {
51
- "@eslint/js": "^10.0.1",
52
49
  "@types/node": "^22.10.2",
53
50
  "@vitest/coverage-v8": "^2.1.8",
54
- "eslint": "^10.4.0",
55
- "globals": "^17.6.0",
56
51
  "tsx": "^4.19.2",
57
52
  "typescript": "^5.7.2",
58
- "typescript-eslint": "^8.59.4",
59
53
  "vitest": "^2.1.8"
60
54
  }
61
55
  }
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "Peaks Doctor Report",
4
+ "description": "The envelope emitted by `peaks doctor --json` (data field). Each check.id uses a `<prefix>:<target>` form so callers can route follow-up actions per category.",
5
+ "type": "object",
6
+ "required": ["checks", "summary"],
7
+ "properties": {
8
+ "checks": {
9
+ "type": "array",
10
+ "items": {
11
+ "type": "object",
12
+ "required": ["id", "ok", "message"],
13
+ "properties": {
14
+ "id": {
15
+ "type": "string",
16
+ "pattern": "^(skill|skill-name|skill-parse|skill-runbook|skill-apply-note|schema|config|doctor-self|capability):[A-Za-z0-9][A-Za-z0-9._-]*$",
17
+ "description": "Stable check id. Known prefixes: skill:<name> (required skill present), skill-name:<dir> (directory matches declared name), skill-parse:<dir> (skill metadata parsed), skill-runbook:<name> (Default runbook section exists), skill-apply-note:<name> (destructive --apply lines carry an authorization/--dry-run note), schema:<file> (schema file exists and is valid JSON), config:<scope> (optional config locations), doctor-self:<topic> (doctor validates its own output against this schema), capability:<name> (third-party capability is resolvable at the pinned version)."
18
+ },
19
+ "ok": { "type": "boolean" },
20
+ "message": { "type": "string", "minLength": 1 }
21
+ }
22
+ }
23
+ },
24
+ "summary": {
25
+ "type": "object",
26
+ "required": ["ok", "passed", "failed"],
27
+ "properties": {
28
+ "ok": { "type": "boolean" },
29
+ "passed": { "type": "integer", "minimum": 0 },
30
+ "failed": { "type": "integer", "minimum": 0 }
31
+ }
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "Peaks MCP Apply Result",
4
+ "type": "object",
5
+ "required": ["capabilityId", "action", "backup", "written", "envCheck"],
6
+ "properties": {
7
+ "capabilityId": { "type": "string", "minLength": 1 },
8
+ "action": {
9
+ "type": "string",
10
+ "enum": ["add", "update", "claimed", "noop"],
11
+ "description": "claimed is returned when an existing non-peaks-managed entry was overwritten with --claim."
12
+ },
13
+ "backup": {
14
+ "type": "object",
15
+ "required": ["path", "skipped"],
16
+ "properties": {
17
+ "path": {
18
+ "oneOf": [
19
+ { "type": "null" },
20
+ { "type": "string", "minLength": 1 }
21
+ ],
22
+ "description": "Absolute path to the backup settings.json copy. Null when no prior settings existed or skipped is true."
23
+ },
24
+ "skipped": {
25
+ "type": "boolean",
26
+ "description": "True when action was noop and no write occurred."
27
+ }
28
+ }
29
+ },
30
+ "written": {
31
+ "type": "object",
32
+ "required": ["settingsPath", "managedMarkerPath"],
33
+ "properties": {
34
+ "settingsPath": { "type": "string", "minLength": 1 },
35
+ "managedMarkerPath": { "type": "string", "minLength": 1 }
36
+ }
37
+ },
38
+ "envCheck": {
39
+ "type": "object",
40
+ "required": ["missing"],
41
+ "properties": {
42
+ "missing": { "type": "array", "items": { "type": "string" } }
43
+ }
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,71 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "Peaks MCP Install Plan",
4
+ "type": "object",
5
+ "required": ["capabilityId", "action", "spec", "current", "envCheck", "diff", "nextActions"],
6
+ "properties": {
7
+ "capabilityId": { "type": "string", "minLength": 1 },
8
+ "action": {
9
+ "type": "string",
10
+ "enum": ["add", "update", "noop", "conflict", "unknown-capability"]
11
+ },
12
+ "spec": {
13
+ "oneOf": [
14
+ { "type": "null" },
15
+ { "$ref": "mcp-install-spec.schema.json" }
16
+ ]
17
+ },
18
+ "current": {
19
+ "oneOf": [
20
+ { "type": "null" },
21
+ { "$ref": "mcp-server.schema.json" }
22
+ ]
23
+ },
24
+ "envCheck": {
25
+ "type": "object",
26
+ "required": ["missing"],
27
+ "properties": {
28
+ "missing": {
29
+ "type": "array",
30
+ "items": { "type": "string" },
31
+ "description": "Env var keys that are not set or are empty."
32
+ }
33
+ }
34
+ },
35
+ "diff": {
36
+ "oneOf": [
37
+ { "type": "null" },
38
+ {
39
+ "type": "object",
40
+ "properties": {
41
+ "command": {
42
+ "type": "object",
43
+ "required": ["before", "after"],
44
+ "properties": {
45
+ "before": { "type": "string" },
46
+ "after": { "type": "string" }
47
+ }
48
+ },
49
+ "args": {
50
+ "type": "object",
51
+ "required": ["before", "after"],
52
+ "properties": {
53
+ "before": { "type": "array", "items": { "type": "string" } },
54
+ "after": { "type": "array", "items": { "type": "string" } }
55
+ }
56
+ },
57
+ "envKeys": {
58
+ "type": "object",
59
+ "required": ["before", "after"],
60
+ "properties": {
61
+ "before": { "type": "array", "items": { "type": "string" } },
62
+ "after": { "type": "array", "items": { "type": "string" } }
63
+ }
64
+ }
65
+ }
66
+ }
67
+ ]
68
+ },
69
+ "nextActions": { "type": "array", "items": { "type": "string" } }
70
+ }
71
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "Peaks MCP Install Spec",
4
+ "type": "object",
5
+ "required": ["capabilityId", "name", "scope", "command", "args", "envKeys"],
6
+ "properties": {
7
+ "capabilityId": {
8
+ "type": "string",
9
+ "minLength": 1,
10
+ "description": "Capability id from the Peaks capability map (e.g. context7.docs-lookup)."
11
+ },
12
+ "name": {
13
+ "type": "string",
14
+ "minLength": 1,
15
+ "description": "Server key written into .claude/settings.json mcpServers."
16
+ },
17
+ "scope": {
18
+ "type": "string",
19
+ "enum": ["global", "project"]
20
+ },
21
+ "command": { "type": "string", "minLength": 1 },
22
+ "args": { "type": "array", "items": { "type": "string" } },
23
+ "envKeys": {
24
+ "type": "array",
25
+ "items": { "type": "string" },
26
+ "description": "Required env var names. Values are sourced from process.env at runtime and written as ${VAR} placeholders into settings.json."
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "Peaks MCP Server Config",
4
+ "type": "object",
5
+ "required": ["name", "command", "args", "envKeys", "source", "scope"],
6
+ "properties": {
7
+ "name": { "type": "string", "minLength": 1 },
8
+ "command": { "type": "string", "minLength": 1 },
9
+ "args": { "type": "array", "items": { "type": "string" } },
10
+ "envKeys": {
11
+ "type": "array",
12
+ "items": { "type": "string" },
13
+ "description": "Names of env vars referenced by the server config. Values are never stored here."
14
+ },
15
+ "source": {
16
+ "type": "string",
17
+ "enum": ["peaks", "cc-switch", "user", "plugin", "unknown"]
18
+ },
19
+ "scope": {
20
+ "type": "string",
21
+ "enum": ["global", "project", "plugin"]
22
+ },
23
+ "pluginName": {
24
+ "type": "string",
25
+ "minLength": 1,
26
+ "description": "Plugin id (e.g. playwright@claude-plugins-official) when source is plugin."
27
+ }
28
+ }
29
+ }