@principal-ai/principal-studio-cli 0.37.0 → 0.38.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/README.md +1 -1
- package/dist/commands/subsystem-model.d.ts.map +1 -1
- package/dist/commands/subsystem-model.js +110 -3
- package/dist/index.cjs +320 -91
- package/dist/index.cjs.map +4 -4
- package/dist/lib/subsystem-model-store.d.ts +23 -11
- package/dist/lib/subsystem-model-store.d.ts.map +1 -1
- package/dist/lib/subsystem-model-store.js +99 -53
- package/package.json +3 -3
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Lets the CLI create/list models without Studio's HTTP bridge running.
|
|
6
6
|
* Structural validation mirrors the Studio POST gate (construct / mechanism /
|
|
7
|
-
*
|
|
7
|
+
* walkthroughs / detail provenance). File/symbol verification is Studio-only
|
|
8
8
|
* for now and may be empty on CLI-created records until opened/updated there.
|
|
9
9
|
*/
|
|
10
10
|
export declare const SUBSYSTEM_EDGE_MECHANISMS: readonly ["imports", "imports_from", "re_exports", "defines", "calls", "extends", "inherits", "implements", "mixes_in", "uses", "method", "references", "contains", "feeds", "produces", "writes", "reads", "watches", "registers-into"];
|
|
11
|
-
export declare const SUBSYSTEM_COMPONENT_CONSTRUCTS: readonly ["class", "function", "method", "interface", "type_alias", "enum", "store", "external"];
|
|
12
|
-
export declare const
|
|
11
|
+
export declare const SUBSYSTEM_COMPONENT_CONSTRUCTS: readonly ["class", "function", "method", "interface", "type_alias", "enum", "store", "external", "custom_entity"];
|
|
12
|
+
export declare const SUBSYSTEM_DECLARATION_PROVENANCES: readonly ["verified", "authored"];
|
|
13
13
|
export interface SubsystemModelIndexEntry {
|
|
14
14
|
id: string;
|
|
15
15
|
title: string;
|
|
@@ -25,14 +25,19 @@ export interface SubsystemModelIndexEntry {
|
|
|
25
25
|
owner: string;
|
|
26
26
|
name: string;
|
|
27
27
|
};
|
|
28
|
+
/** Host-only gist link mirrored from the record. */
|
|
29
|
+
gist?: {
|
|
30
|
+
id: string;
|
|
31
|
+
fileName?: string;
|
|
32
|
+
};
|
|
28
33
|
}
|
|
29
34
|
export interface StoredSubsystemModel {
|
|
30
35
|
id: string;
|
|
31
36
|
title: string;
|
|
32
37
|
description?: string;
|
|
33
38
|
components: unknown[];
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
relations: unknown[];
|
|
40
|
+
walkthroughs?: unknown[];
|
|
36
41
|
createdAt: string;
|
|
37
42
|
updatedAt: string;
|
|
38
43
|
lastOpenedAt?: string;
|
|
@@ -43,14 +48,19 @@ export interface StoredSubsystemModel {
|
|
|
43
48
|
};
|
|
44
49
|
repoRoot?: string;
|
|
45
50
|
repoRoots?: Record<string, string>;
|
|
51
|
+
/** Host-only GitHub gist link (not portable). */
|
|
52
|
+
gist?: {
|
|
53
|
+
id: string;
|
|
54
|
+
fileName?: string;
|
|
55
|
+
};
|
|
46
56
|
verification?: unknown;
|
|
47
57
|
}
|
|
48
58
|
export interface CreateSubsystemModelInput {
|
|
49
59
|
title: string;
|
|
50
60
|
description?: string;
|
|
51
61
|
components: unknown[];
|
|
52
|
-
|
|
53
|
-
|
|
62
|
+
relations: unknown[];
|
|
63
|
+
walkthroughs?: unknown[];
|
|
54
64
|
source?: string;
|
|
55
65
|
repo?: {
|
|
56
66
|
owner: string;
|
|
@@ -60,15 +70,17 @@ export interface CreateSubsystemModelInput {
|
|
|
60
70
|
repoRoots?: Record<string, string>;
|
|
61
71
|
}
|
|
62
72
|
export declare function subsystemModelFilePath(id: string): string;
|
|
63
|
-
export declare function
|
|
64
|
-
export declare function
|
|
73
|
+
export declare function findRelationTypeProblems(relations: unknown): string[];
|
|
74
|
+
export declare function findWalkthroughProblems(walkthroughs: unknown): string[];
|
|
65
75
|
export declare function findComponentConstructProblems(components: unknown): string[];
|
|
66
|
-
export declare function
|
|
67
|
-
export declare function
|
|
76
|
+
export declare function findDeclarationProvenanceProblems(components: unknown): string[];
|
|
77
|
+
export declare function normalizeDeclarationProvenance(components: unknown): void;
|
|
68
78
|
export declare function isRepoRoots(value: unknown): value is Record<string, string>;
|
|
69
79
|
/** Structural problems that would make Studio reject a POST (empty = valid). */
|
|
70
80
|
export declare function findCreateProblems(body: Record<string, unknown>): string[];
|
|
71
81
|
export declare function listSubsystemModels(): Promise<SubsystemModelIndexEntry[]>;
|
|
72
82
|
export declare function getSubsystemModel(id: string): Promise<StoredSubsystemModel | null>;
|
|
73
83
|
export declare function createSubsystemModel(doc: CreateSubsystemModelInput): Promise<StoredSubsystemModel>;
|
|
84
|
+
/** Patch an existing record (e.g. stamp a host gist ref after share). */
|
|
85
|
+
export declare function updateSubsystemModel(id: string, patch: Partial<Pick<StoredSubsystemModel, 'title' | 'description' | 'components' | 'relations' | 'walkthroughs' | 'source' | 'repo' | 'repoRoot' | 'repoRoots' | 'gist'>>): Promise<StoredSubsystemModel | null>;
|
|
74
86
|
//# sourceMappingURL=subsystem-model-store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subsystem-model-store.d.ts","sourceRoot":"","sources":["../../src/lib/subsystem-model-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"subsystem-model-store.d.ts","sourceRoot":"","sources":["../../src/lib/subsystem-model-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Lets the CLI create/list models without Studio's HTTP bridge running.
|
|
6
6
|
* Structural validation mirrors the Studio POST gate (construct / mechanism /
|
|
7
|
-
*
|
|
7
|
+
* walkthroughs / detail provenance). File/symbol verification is Studio-only
|
|
8
8
|
* for now and may be empty on CLI-created records until opened/updated there.
|
|
9
9
|
*/
|
|
10
10
|
import { promises as fs } from 'node:fs';
|
|
11
11
|
import { homedir } from 'node:os';
|
|
12
12
|
import { join } from 'node:path';
|
|
13
|
+
import { deriveGraphEdges } from '@principal-ai/subsystems-core';
|
|
13
14
|
const ROOT = join(homedir(), '.principal', 'subsystem-models');
|
|
14
15
|
const INDEX_PATH = join(ROOT, '_index.json');
|
|
15
16
|
export const SUBSYSTEM_EDGE_MECHANISMS = [
|
|
@@ -42,8 +43,9 @@ export const SUBSYSTEM_COMPONENT_CONSTRUCTS = [
|
|
|
42
43
|
'enum',
|
|
43
44
|
'store',
|
|
44
45
|
'external',
|
|
46
|
+
'custom_entity',
|
|
45
47
|
];
|
|
46
|
-
export const
|
|
48
|
+
export const SUBSYSTEM_DECLARATION_PROVENANCES = ['verified', 'authored'];
|
|
47
49
|
function graphId() {
|
|
48
50
|
const ts = Date.now();
|
|
49
51
|
const rand = Math.random().toString(36).slice(2, 11);
|
|
@@ -58,53 +60,72 @@ export function subsystemModelFilePath(id) {
|
|
|
58
60
|
async function ensureDir() {
|
|
59
61
|
await fs.mkdir(ROOT, { recursive: true });
|
|
60
62
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
const SUBSYSTEM_RELATION_TYPES = [
|
|
64
|
+
'imports', 'imports_from', 're_exports', 'defines', 'extends', 'inherits',
|
|
65
|
+
'implements', 'mixes_in', 'method', 'references', 'contains',
|
|
66
|
+
];
|
|
67
|
+
const SUBSYSTEM_WALKTHROUGH_MECHANISMS = [
|
|
68
|
+
'calls', 'uses', 'feeds', 'produces', 'writes', 'reads', 'watches', 'registers-into',
|
|
69
|
+
];
|
|
70
|
+
export function findRelationTypeProblems(relations) {
|
|
71
|
+
if (!Array.isArray(relations))
|
|
72
|
+
return ['relations must be an array'];
|
|
64
73
|
const problems = [];
|
|
65
|
-
for (const
|
|
66
|
-
const
|
|
67
|
-
if (typeof
|
|
68
|
-
|
|
69
|
-
|
|
74
|
+
for (const rel of relations) {
|
|
75
|
+
const r = rel;
|
|
76
|
+
if (typeof r?.id !== 'string' || !r.id.trim()) {
|
|
77
|
+
problems.push(`relation ${JSON.stringify(r?.id ?? '<no id>')}: id is required`);
|
|
78
|
+
}
|
|
79
|
+
if (typeof r?.from !== 'string' || !r.from.trim()) {
|
|
80
|
+
problems.push(`relation ${JSON.stringify(r?.id ?? '<no id>')}: from is required`);
|
|
81
|
+
}
|
|
82
|
+
if (typeof r?.to !== 'string' || !r.to.trim()) {
|
|
83
|
+
problems.push(`relation ${JSON.stringify(r?.id ?? '<no id>')}: to is required`);
|
|
84
|
+
}
|
|
85
|
+
if (typeof r?.relationType !== 'string' ||
|
|
86
|
+
!SUBSYSTEM_RELATION_TYPES.includes(r.relationType)) {
|
|
87
|
+
problems.push(`relation ${JSON.stringify(r?.id ?? '<no id>')}: unknown relationType ${JSON.stringify(r?.relationType)}`);
|
|
70
88
|
}
|
|
71
|
-
problems.push(`edge ${JSON.stringify(e?.id ?? '<no id>')}: unknown mechanism ${JSON.stringify(e?.mechanism)} — allowed: ${SUBSYSTEM_EDGE_MECHANISMS.join(', ')}`);
|
|
72
89
|
}
|
|
73
90
|
return problems;
|
|
74
91
|
}
|
|
75
|
-
export function
|
|
76
|
-
if (
|
|
92
|
+
export function findWalkthroughProblems(walkthroughs) {
|
|
93
|
+
if (walkthroughs === undefined)
|
|
77
94
|
return [];
|
|
78
|
-
if (!Array.isArray(
|
|
79
|
-
return ['
|
|
80
|
-
const edgeIds = new Set((Array.isArray(edges) ? edges : [])
|
|
81
|
-
.map((e) => e?.id)
|
|
82
|
-
.filter((id) => typeof id === 'string'));
|
|
95
|
+
if (!Array.isArray(walkthroughs))
|
|
96
|
+
return ['walkthroughs must be an array'];
|
|
83
97
|
const problems = [];
|
|
84
|
-
for (const
|
|
85
|
-
const
|
|
86
|
-
const label = JSON.stringify(
|
|
87
|
-
if (typeof
|
|
88
|
-
problems.push(`
|
|
98
|
+
for (const wt of walkthroughs) {
|
|
99
|
+
const w = wt;
|
|
100
|
+
const label = JSON.stringify(w?.id ?? '<no id>');
|
|
101
|
+
if (typeof w?.id !== 'string' || !w.id.trim()) {
|
|
102
|
+
problems.push(`walkthrough ${label}: id is required`);
|
|
89
103
|
continue;
|
|
90
104
|
}
|
|
91
|
-
if (typeof
|
|
92
|
-
problems.push(`
|
|
105
|
+
if (typeof w?.title !== 'string' || !w.title.trim()) {
|
|
106
|
+
problems.push(`walkthrough ${label}: title is required`);
|
|
93
107
|
}
|
|
94
|
-
if (!Array.isArray(
|
|
95
|
-
problems.push(`
|
|
108
|
+
if (!Array.isArray(w.steps)) {
|
|
109
|
+
problems.push(`walkthrough ${label}: steps array is required`);
|
|
96
110
|
continue;
|
|
97
111
|
}
|
|
98
|
-
|
|
112
|
+
w.steps.forEach((step, i) => {
|
|
99
113
|
const s = step;
|
|
100
|
-
if (typeof s?.
|
|
101
|
-
problems.push(`
|
|
114
|
+
if (typeof s?.from !== 'string' || !s.from.trim()) {
|
|
115
|
+
problems.push(`walkthrough ${label}: step ${i} from is required`);
|
|
116
|
+
}
|
|
117
|
+
if (typeof s?.to !== 'string' || !s.to.trim()) {
|
|
118
|
+
problems.push(`walkthrough ${label}: step ${i} to is required`);
|
|
119
|
+
}
|
|
120
|
+
if (typeof s?.mechanism !== 'string' ||
|
|
121
|
+
!SUBSYSTEM_WALKTHROUGH_MECHANISMS.includes(s.mechanism)) {
|
|
122
|
+
problems.push(`walkthrough ${label}: step ${i} unknown mechanism ${JSON.stringify(s?.mechanism)}`);
|
|
102
123
|
}
|
|
103
124
|
if (typeof s?.file !== 'string' || !s.file.trim()) {
|
|
104
|
-
problems.push(`
|
|
125
|
+
problems.push(`walkthrough ${label}: step ${i} file is required`);
|
|
105
126
|
}
|
|
106
127
|
else if (typeof s?.line !== 'number' || !Number.isInteger(s.line) || s.line < 1) {
|
|
107
|
-
problems.push(`
|
|
128
|
+
problems.push(`walkthrough ${label}: step ${i} line must be a positive 1-based integer`);
|
|
108
129
|
}
|
|
109
130
|
});
|
|
110
131
|
}
|
|
@@ -124,50 +145,55 @@ export function findComponentConstructProblems(components) {
|
|
|
124
145
|
}
|
|
125
146
|
return problems;
|
|
126
147
|
}
|
|
127
|
-
export function
|
|
148
|
+
export function findDeclarationProvenanceProblems(components) {
|
|
128
149
|
if (!Array.isArray(components))
|
|
129
150
|
return [];
|
|
130
151
|
const problems = [];
|
|
131
152
|
for (const component of components) {
|
|
132
153
|
const c = component;
|
|
133
|
-
if (!c || typeof c !== 'object'
|
|
154
|
+
if (!c || typeof c !== 'object')
|
|
155
|
+
continue;
|
|
156
|
+
if (!c['declaration'])
|
|
134
157
|
continue;
|
|
135
|
-
const p = c['
|
|
158
|
+
const p = c['declarationProvenance'];
|
|
136
159
|
if (p === undefined)
|
|
137
160
|
continue;
|
|
138
|
-
if (typeof p === 'string' &&
|
|
161
|
+
if (typeof p === 'string' &&
|
|
162
|
+
SUBSYSTEM_DECLARATION_PROVENANCES.includes(p)) {
|
|
139
163
|
continue;
|
|
140
164
|
}
|
|
141
|
-
problems.push(`component ${JSON.stringify(String(c['id'] ?? '<no id>'))}: invalid
|
|
165
|
+
problems.push(`component ${JSON.stringify(String(c['id'] ?? '<no id>'))}: invalid declarationProvenance ${JSON.stringify(p)} — allowed: ${SUBSYSTEM_DECLARATION_PROVENANCES.join(', ')}. Hand-authored declarations must be "authored"; "verified" is reserved for tool-extracted data.`);
|
|
142
166
|
}
|
|
143
167
|
return problems;
|
|
144
168
|
}
|
|
145
|
-
export function
|
|
169
|
+
export function normalizeDeclarationProvenance(components) {
|
|
146
170
|
if (!Array.isArray(components))
|
|
147
171
|
return;
|
|
148
172
|
for (const component of components) {
|
|
149
173
|
const c = component;
|
|
150
174
|
if (!c || typeof c !== 'object')
|
|
151
175
|
continue;
|
|
152
|
-
const
|
|
153
|
-
if (!
|
|
154
|
-
delete c['
|
|
176
|
+
const declaration = c['declaration'];
|
|
177
|
+
if (!declaration || typeof declaration !== 'object') {
|
|
178
|
+
delete c['declarationProvenance'];
|
|
155
179
|
continue;
|
|
156
180
|
}
|
|
157
|
-
const p = c['
|
|
181
|
+
const p = c['declarationProvenance'];
|
|
158
182
|
if (p !== 'verified' && p !== 'authored')
|
|
159
|
-
c['
|
|
160
|
-
const kind =
|
|
183
|
+
c['declarationProvenance'] = 'authored';
|
|
184
|
+
const kind = declaration['kind'];
|
|
161
185
|
const arrays = {
|
|
162
186
|
function: ['parameters', 'callers', 'callees'],
|
|
163
187
|
method: ['parameters'],
|
|
164
188
|
class: ['methods', 'properties', 'extends', 'implements', 'instantiations', 'references'],
|
|
165
189
|
type: ['properties', 'usedBy', 'implementors'],
|
|
166
190
|
module: ['imports', 'exports', 'symbols'],
|
|
191
|
+
custom_entity: ['attributes'],
|
|
192
|
+
store: ['properties'],
|
|
167
193
|
};
|
|
168
194
|
for (const key of arrays[String(kind)] ?? []) {
|
|
169
|
-
if (!Array.isArray(
|
|
170
|
-
|
|
195
|
+
if (!Array.isArray(declaration[key]))
|
|
196
|
+
declaration[key] = [];
|
|
171
197
|
}
|
|
172
198
|
}
|
|
173
199
|
}
|
|
@@ -185,16 +211,16 @@ export function findCreateProblems(body) {
|
|
|
185
211
|
if (!Array.isArray(body['components'])) {
|
|
186
212
|
problems.push('components array is required');
|
|
187
213
|
}
|
|
188
|
-
if (!Array.isArray(body['
|
|
189
|
-
problems.push('
|
|
214
|
+
if (!Array.isArray(body['relations'])) {
|
|
215
|
+
problems.push('relations array is required');
|
|
190
216
|
}
|
|
191
217
|
if (problems.length > 0)
|
|
192
218
|
return problems;
|
|
193
219
|
return [
|
|
194
220
|
...findComponentConstructProblems(body['components']),
|
|
195
|
-
...
|
|
196
|
-
...
|
|
197
|
-
...
|
|
221
|
+
...findDeclarationProvenanceProblems(body['components']),
|
|
222
|
+
...findRelationTypeProblems(body['relations']),
|
|
223
|
+
...findWalkthroughProblems(body['walkthroughs']),
|
|
198
224
|
];
|
|
199
225
|
}
|
|
200
226
|
function indexEntryFor(record) {
|
|
@@ -203,13 +229,17 @@ function indexEntryFor(record) {
|
|
|
203
229
|
title: record.title,
|
|
204
230
|
description: record.description,
|
|
205
231
|
componentCount: record.components.length,
|
|
206
|
-
edgeCount:
|
|
232
|
+
edgeCount: deriveGraphEdges({
|
|
233
|
+
relations: record.relations,
|
|
234
|
+
walkthroughs: record.walkthroughs,
|
|
235
|
+
}).length,
|
|
207
236
|
createdAt: record.createdAt,
|
|
208
237
|
updatedAt: record.updatedAt,
|
|
209
238
|
lastOpenedAt: record.lastOpenedAt,
|
|
210
239
|
fileName: `${record.id}.json`,
|
|
211
240
|
source: record.source,
|
|
212
241
|
repo: record.repo,
|
|
242
|
+
gist: record.gist,
|
|
213
243
|
};
|
|
214
244
|
}
|
|
215
245
|
async function readIndex() {
|
|
@@ -278,7 +308,7 @@ export async function getSubsystemModel(id) {
|
|
|
278
308
|
}
|
|
279
309
|
export async function createSubsystemModel(doc) {
|
|
280
310
|
await ensureDir();
|
|
281
|
-
|
|
311
|
+
normalizeDeclarationProvenance(doc.components);
|
|
282
312
|
const now = new Date().toISOString();
|
|
283
313
|
const record = {
|
|
284
314
|
...doc,
|
|
@@ -290,3 +320,19 @@ export async function createSubsystemModel(doc) {
|
|
|
290
320
|
await upsertIndexEntry(indexEntryFor(record));
|
|
291
321
|
return record;
|
|
292
322
|
}
|
|
323
|
+
/** Patch an existing record (e.g. stamp a host gist ref after share). */
|
|
324
|
+
export async function updateSubsystemModel(id, patch) {
|
|
325
|
+
const existing = await getSubsystemModel(id);
|
|
326
|
+
if (!existing)
|
|
327
|
+
return null;
|
|
328
|
+
if (patch.components !== undefined)
|
|
329
|
+
normalizeDeclarationProvenance(patch.components);
|
|
330
|
+
const updated = {
|
|
331
|
+
...existing,
|
|
332
|
+
...patch,
|
|
333
|
+
updatedAt: new Date().toISOString(),
|
|
334
|
+
};
|
|
335
|
+
await fs.writeFile(graphPath(id), JSON.stringify(updated, null, 2), 'utf8');
|
|
336
|
+
await upsertIndexEntry(indexEntryFor(updated));
|
|
337
|
+
return updated;
|
|
338
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@principal-ai/principal-studio-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"description": "Principal AI CLI — subsystem models, Subsystems Studio, trails, and agent sessions",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"@principal-ai/alexandria-core-library": "^0.4.0",
|
|
36
36
|
"@principal-ai/codebase-composition": "^0.2.57",
|
|
37
37
|
"@principal-ai/file-city-builder": "^0.5.0",
|
|
38
|
-
"@principal-ai/subsystems-core": "^0.30.0",
|
|
39
38
|
"@principal-ai/repository-abstraction": "^0.5.7",
|
|
39
|
+
"@principal-ai/subsystems-core": "0.32.0",
|
|
40
40
|
"better-sqlite3": "^13.0.0",
|
|
41
41
|
"chalk": "5.6.2",
|
|
42
42
|
"commander": "14.0.2",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"js-yaml": "4.1.1"
|
|
46
46
|
},
|
|
47
47
|
"optionalDependencies": {
|
|
48
|
-
"@principal-ai/subsystems-studio": "^0.6.
|
|
48
|
+
"@principal-ai/subsystems-studio": "^0.6.9"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/better-sqlite3": "^7.6.13",
|