@principal-ai/subsystems-core 0.34.2 → 0.36.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/types/subsystem-model.d.ts +19 -5
- package/dist/types/subsystem-model.d.ts.map +1 -1
- package/dist/types/subsystem-model.js.map +1 -1
- package/dist/validation.d.ts +1 -1
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +24 -12
- package/dist/validation.js.map +1 -1
- package/package.json +2 -2
- package/schemas/subsystem-model.schema.json +16 -10
- package/src/types/subsystem-model.ts +19 -5
- package/src/validation.test.ts +25 -8
- package/src/validation.ts +24 -12
|
@@ -202,7 +202,14 @@ export interface SubsystemCustomEntityDeclaration {
|
|
|
202
202
|
export type SubsystemConstructDeclaration = SubsystemClassDeclaration | SubsystemFunctionDeclaration | SubsystemMethodDeclaration | SubsystemTypeDeclaration | SubsystemExternalDeclaration | SubsystemStoreDeclaration | SubsystemCustomEntityDeclaration;
|
|
203
203
|
/** A component node — the named unit, construct-tagged. */
|
|
204
204
|
export interface SubsystemComponent {
|
|
205
|
-
|
|
205
|
+
/**
|
|
206
|
+
* Model-local stable alias. Referenced by relation / walkthrough `from` /
|
|
207
|
+
* `to`; unique per model. Edges point at the alias, not the location — a
|
|
208
|
+
* file move or symbol rename leaves edges intact. Code identity lives on
|
|
209
|
+
* `purl` + `file` + `symbol` and is what composed (multi-model) views
|
|
210
|
+
* join on, not this field.
|
|
211
|
+
*/
|
|
212
|
+
alias: string;
|
|
206
213
|
/** Display label. Prefer aligning with `symbol` when present. */
|
|
207
214
|
name: string;
|
|
208
215
|
construct: SubsystemConstruct;
|
|
@@ -262,9 +269,9 @@ export interface SubsystemComponent {
|
|
|
262
269
|
/** A topology relation between components (structural / module / type). */
|
|
263
270
|
export interface SubsystemRelation {
|
|
264
271
|
id: string;
|
|
265
|
-
/** Source component
|
|
272
|
+
/** Source component alias. */
|
|
266
273
|
from: string;
|
|
267
|
-
/** Target component
|
|
274
|
+
/** Target component alias (or external label). */
|
|
268
275
|
to: string;
|
|
269
276
|
relationType: SubsystemRelationType;
|
|
270
277
|
/** Concrete file/symbol evidence (often purls). */
|
|
@@ -282,15 +289,22 @@ export interface SubsystemComponentEdge {
|
|
|
282
289
|
refs?: string[];
|
|
283
290
|
}
|
|
284
291
|
export interface SubsystemWalkthroughStep {
|
|
285
|
-
/** Source component
|
|
292
|
+
/** Source component alias. */
|
|
286
293
|
from: string;
|
|
287
|
-
/** Target component
|
|
294
|
+
/** Target component alias. */
|
|
288
295
|
to: string;
|
|
289
296
|
/** Runtime seam label (Set B). */
|
|
290
297
|
mechanism: SubsystemWalkthroughMechanism;
|
|
291
298
|
file: string;
|
|
292
299
|
/** 1-based line within `file`. */
|
|
293
300
|
line: number;
|
|
301
|
+
/**
|
|
302
|
+
* File-anchored purl of the seam site (e.g.
|
|
303
|
+
* `pkg:github/owner/name#path/to/file.ts`), mirroring component `purl`.
|
|
304
|
+
* Required: readers resolve the checkout from this instead of guessing
|
|
305
|
+
* the repo from the step's endpoint components.
|
|
306
|
+
*/
|
|
307
|
+
purl: string;
|
|
294
308
|
/** Frame name for this hop (function/method/symbol). Optional. */
|
|
295
309
|
symbol?: string;
|
|
296
310
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subsystem-model.d.ts","sourceRoot":"","sources":["../../src/types/subsystem-model.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"subsystem-model.d.ts","sourceRoot":"","sources":["../../src/types/subsystem-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subsystem-model.js","sourceRoot":"","sources":["../../src/types/subsystem-model.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;
|
|
1
|
+
{"version":3,"file":"subsystem-model.js","sourceRoot":"","sources":["../../src/types/subsystem-model.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AA6ZH;;;;GAIG;AACH,SAAgB,wBAAwB,CAAC,KAAc;IACrD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,CAAC,GAAG,KAIT,CAAC;IACF,OAAO,CACL,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ;QAC3B,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;QAC3B,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAC3B,CAAC;AACJ,CAAC;AAZD,4DAYC;AAED;;;;GAIG;AACH,SAAgB,kBAAkB,CAChC,GAA2B;IAE3B,MAAM,GAAG,GAA2B;QAClC,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,SAAS,EAAE,GAAG,CAAC,SAAS;KACzB,CAAC;IACF,IAAI,GAAG,CAAC,OAAO;QAAE,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;IAC3C,IAAI,GAAG,CAAC,WAAW;QAAE,GAAG,CAAC,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC;IACvD,IAAI,GAAG,CAAC,YAAY;QAAE,GAAG,CAAC,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC;IAC1D,OAAO,GAAG,CAAC;AACb,CAAC;AAZD,gDAYC;AAED,6EAA6E;AAC7E,SAAgB,kBAAkB,CAChC,IAAY,EACZ,EAAU,EACV,SAAiC;IAEjC,OAAO,GAAG,IAAI,KAAK,SAAS,MAAM,EAAE,EAAE,CAAC;AACzC,CAAC;AAND,gDAMC;AAED;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,GAGhC;IACC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkC,CAAC;IACvD,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,SAAS,IAAI,EAAE,EAAE;QACnC,MAAM,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,kBAAkB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;QACpE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YACjB,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE;gBACX,EAAE;gBACF,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,SAAS,EAAE,CAAC,CAAC,YAAY;gBACzB,IAAI,EAAE,CAAC,CAAC,IAAI;aACb,CAAC,CAAC;SACJ;KACF;IACD,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,YAAY,IAAI,EAAE,EAAE;QACtC,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,KAAK,EAAE;YAC1B,MAAM,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YAClE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;gBACjB,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE;oBACX,EAAE;oBACF,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,EAAE,EAAE,IAAI,CAAC,EAAE;oBACX,SAAS,EAAE,IAAI,CAAC,SAAS;iBAC1B,CAAC,CAAC;aACJ;SACF;KACF;IACD,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AAC5B,CAAC;AA/BD,4CA+BC"}
|
package/dist/validation.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Cross-field validation for a subsystem model document.
|
|
3
3
|
*
|
|
4
4
|
* These are the rules the JSON Schema (`schemas/subsystem-model.schema.json`)
|
|
5
|
-
* cannot express — anything that spans fields or arrays:
|
|
5
|
+
* cannot express — anything that spans fields or arrays: alias uniqueness,
|
|
6
6
|
* referential integrity between relations/walkthroughs and components, and the
|
|
7
7
|
* `module` implies `file` invariant. Structural checks (types, `required`,
|
|
8
8
|
* enums, ranges, closed objects) belong to the schema and are enforced per
|
package/dist/validation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,sBAAsB,EAGvB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,0BAA0B;IACzC,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD;;;GAGG;AACH,wBAAgB,gCAAgC,CAC9C,GAAG,EAAE,sBAAsB,GAC1B,0BAA0B,EAAE,
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,sBAAsB,EAGvB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,0BAA0B;IACzC,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD;;;GAGG;AACH,wBAAgB,gCAAgC,CAC9C,GAAG,EAAE,sBAAsB,GAC1B,0BAA0B,EAAE,CA2E9B"}
|
package/dist/validation.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Cross-field validation for a subsystem model document.
|
|
4
4
|
*
|
|
5
5
|
* These are the rules the JSON Schema (`schemas/subsystem-model.schema.json`)
|
|
6
|
-
* cannot express — anything that spans fields or arrays:
|
|
6
|
+
* cannot express — anything that spans fields or arrays: alias uniqueness,
|
|
7
7
|
* referential integrity between relations/walkthroughs and components, and the
|
|
8
8
|
* `module` implies `file` invariant. Structural checks (types, `required`,
|
|
9
9
|
* enums, ranges, closed objects) belong to the schema and are enforced per
|
|
@@ -25,18 +25,18 @@ function validateSubsystemModelCrossField(doc) {
|
|
|
25
25
|
const components = doc.components ?? [];
|
|
26
26
|
const relations = doc.relations ?? [];
|
|
27
27
|
const walkthroughs = doc.walkthroughs ?? [];
|
|
28
|
-
// Component
|
|
29
|
-
// relations and walkthrough steps.
|
|
28
|
+
// Component aliases must be unique, and the set is the referential target
|
|
29
|
+
// for relations and walkthrough steps.
|
|
30
30
|
const ids = new Set();
|
|
31
31
|
components.forEach((c, i) => {
|
|
32
|
-
if (ids.has(c.
|
|
32
|
+
if (ids.has(c.alias)) {
|
|
33
33
|
problems.push({
|
|
34
|
-
path: `/components/${i}/
|
|
35
|
-
message: `component ${JSON.stringify(c.
|
|
34
|
+
path: `/components/${i}/alias`,
|
|
35
|
+
message: `component ${JSON.stringify(c.alias)}: duplicate alias`,
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
38
|
else {
|
|
39
|
-
ids.add(c.
|
|
39
|
+
ids.add(c.alias);
|
|
40
40
|
}
|
|
41
41
|
// A grounded component that claims a `module` needs a `file` to ground the
|
|
42
42
|
// frame. Externals / proposed carry no file by design.
|
|
@@ -45,7 +45,7 @@ function validateSubsystemModelCrossField(doc) {
|
|
|
45
45
|
if (module && !file && !isUngrounded(c)) {
|
|
46
46
|
problems.push({
|
|
47
47
|
path: `/components/${i}/module`,
|
|
48
|
-
message: `component ${JSON.stringify(c.
|
|
48
|
+
message: `component ${JSON.stringify(c.alias)}: module ${JSON.stringify(module)} is set but file is empty — a module frame needs a file to ground it (mark the component proposed if it is not placed yet).`,
|
|
49
49
|
});
|
|
50
50
|
}
|
|
51
51
|
});
|
|
@@ -53,13 +53,13 @@ function validateSubsystemModelCrossField(doc) {
|
|
|
53
53
|
if (!ids.has(r.from)) {
|
|
54
54
|
problems.push({
|
|
55
55
|
path: `/relations/${i}/from`,
|
|
56
|
-
message: `relation ${JSON.stringify(r.id)}: from ${JSON.stringify(r.from)} does not match any component
|
|
56
|
+
message: `relation ${JSON.stringify(r.id)}: from ${JSON.stringify(r.from)} does not match any component alias`,
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
59
|
if (!ids.has(r.to)) {
|
|
60
60
|
problems.push({
|
|
61
61
|
path: `/relations/${i}/to`,
|
|
62
|
-
message: `relation ${JSON.stringify(r.id)}: to ${JSON.stringify(r.to)} does not match any component
|
|
62
|
+
message: `relation ${JSON.stringify(r.id)}: to ${JSON.stringify(r.to)} does not match any component alias`,
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
});
|
|
@@ -68,15 +68,27 @@ function validateSubsystemModelCrossField(doc) {
|
|
|
68
68
|
if (!ids.has(step.from)) {
|
|
69
69
|
problems.push({
|
|
70
70
|
path: `/walkthroughs/${wi}/steps/${si}/from`,
|
|
71
|
-
message: `walkthrough ${JSON.stringify(w.id)}: step ${si} from ${JSON.stringify(step.from)} does not match any component
|
|
71
|
+
message: `walkthrough ${JSON.stringify(w.id)}: step ${si} from ${JSON.stringify(step.from)} does not match any component alias`,
|
|
72
72
|
});
|
|
73
73
|
}
|
|
74
74
|
if (!ids.has(step.to)) {
|
|
75
75
|
problems.push({
|
|
76
76
|
path: `/walkthroughs/${wi}/steps/${si}/to`,
|
|
77
|
-
message: `walkthrough ${JSON.stringify(w.id)}: step ${si} to ${JSON.stringify(step.to)} does not match any component
|
|
77
|
+
message: `walkthrough ${JSON.stringify(w.id)}: step ${si} to ${JSON.stringify(step.to)} does not match any component alias`,
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
|
+
// A file-anchored step purl names its own site: the fragment must be
|
|
81
|
+
// the step file. Repo-only purls still resolve, so only the anchored
|
|
82
|
+
// form is checked.
|
|
83
|
+
if (typeof step.purl === 'string' && step.purl.includes('#')) {
|
|
84
|
+
const fragment = step.purl.split('#').slice(1).join('#');
|
|
85
|
+
if (fragment !== step.file) {
|
|
86
|
+
problems.push({
|
|
87
|
+
path: `/walkthroughs/${wi}/steps/${si}/purl`,
|
|
88
|
+
message: `walkthrough ${JSON.stringify(w.id)}: step ${si} purl fragment ${JSON.stringify(fragment)} does not match step file ${JSON.stringify(step.file)}`,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
80
92
|
});
|
|
81
93
|
});
|
|
82
94
|
return problems;
|
package/dist/validation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;AAcH,SAAS,YAAY,CAAC,CAAqB;IACzC,OAAO,CAAC,CAAC,SAAS,KAAK,UAAU,IAAI,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,SAAgB,gCAAgC,CAC9C,GAA2B;IAE3B,MAAM,QAAQ,GAAiC,EAAE,CAAC;IAClD,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC;IACxC,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC;IACtC,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC;IAE5C,0EAA0E;IAC1E,
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@principal-ai/subsystems-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.0",
|
|
4
4
|
"description": "Subsystem model types and agent-session tooling for Principal AI",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -65,4 +65,4 @@
|
|
|
65
65
|
"access": "public",
|
|
66
66
|
"registry": "https://registry.npmjs.org/"
|
|
67
67
|
}
|
|
68
|
-
}
|
|
68
|
+
}
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"relations": {
|
|
35
35
|
"type": "array",
|
|
36
|
-
"description": "Topology relations (structural / module / type). `from` / `to` reference component `
|
|
36
|
+
"description": "Topology relations (structural / module / type). `from` / `to` reference component `alias`es. Runtime seams belong on walkthrough steps, not here.",
|
|
37
37
|
"items": {
|
|
38
38
|
"$ref": "#/$defs/relation"
|
|
39
39
|
}
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
"component": {
|
|
123
123
|
"type": "object",
|
|
124
124
|
"required": [
|
|
125
|
-
"
|
|
125
|
+
"alias",
|
|
126
126
|
"name",
|
|
127
127
|
"construct",
|
|
128
128
|
"file",
|
|
@@ -130,10 +130,10 @@
|
|
|
130
130
|
],
|
|
131
131
|
"additionalProperties": false,
|
|
132
132
|
"properties": {
|
|
133
|
-
"
|
|
133
|
+
"alias": {
|
|
134
134
|
"type": "string",
|
|
135
135
|
"minLength": 1,
|
|
136
|
-
"description": "
|
|
136
|
+
"description": "Model-local stable alias, unique per model. Referenced by relation / walkthrough `from` / `to`; edges point at the alias, not the location, so a file move or symbol rename leaves edges intact. Code identity (for composed multi-model views) lives on `purl` + `file` + `symbol`, not here."
|
|
137
137
|
},
|
|
138
138
|
"name": {
|
|
139
139
|
"type": "string",
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
},
|
|
146
146
|
"file": {
|
|
147
147
|
"type": "string",
|
|
148
|
-
"description": "Repo-root-relative path of the source location this component lives in.
|
|
148
|
+
"description": "Repo-root-relative path of the source location this component lives in. Resolved against the checkout of the repo named by this component's `purl` (via the Alexandria registry). Empty string allowed for pure externals."
|
|
149
149
|
},
|
|
150
150
|
"purl": {
|
|
151
151
|
"type": "string",
|
|
@@ -230,12 +230,12 @@
|
|
|
230
230
|
"from": {
|
|
231
231
|
"type": "string",
|
|
232
232
|
"minLength": 1,
|
|
233
|
-
"description": "Source component `
|
|
233
|
+
"description": "Source component `alias`."
|
|
234
234
|
},
|
|
235
235
|
"to": {
|
|
236
236
|
"type": "string",
|
|
237
237
|
"minLength": 1,
|
|
238
|
-
"description": "Target component `
|
|
238
|
+
"description": "Target component `alias` (or external target label)."
|
|
239
239
|
},
|
|
240
240
|
"relationType": {
|
|
241
241
|
"$ref": "#/$defs/relationType"
|
|
@@ -257,19 +257,20 @@
|
|
|
257
257
|
"to",
|
|
258
258
|
"mechanism",
|
|
259
259
|
"file",
|
|
260
|
-
"line"
|
|
260
|
+
"line",
|
|
261
|
+
"purl"
|
|
261
262
|
],
|
|
262
263
|
"additionalProperties": false,
|
|
263
264
|
"properties": {
|
|
264
265
|
"from": {
|
|
265
266
|
"type": "string",
|
|
266
267
|
"minLength": 1,
|
|
267
|
-
"description": "Source component `
|
|
268
|
+
"description": "Source component `alias`."
|
|
268
269
|
},
|
|
269
270
|
"to": {
|
|
270
271
|
"type": "string",
|
|
271
272
|
"minLength": 1,
|
|
272
|
-
"description": "Target component `
|
|
273
|
+
"description": "Target component `alias`."
|
|
273
274
|
},
|
|
274
275
|
"mechanism": {
|
|
275
276
|
"$ref": "#/$defs/mechanism"
|
|
@@ -284,6 +285,11 @@
|
|
|
284
285
|
"minimum": 1,
|
|
285
286
|
"description": "1-based line of the site within `file`."
|
|
286
287
|
},
|
|
288
|
+
"purl": {
|
|
289
|
+
"type": "string",
|
|
290
|
+
"minLength": 1,
|
|
291
|
+
"description": "File-anchored purl of the seam site (e.g. `pkg:github/owner/name#path/to/file.ts`), mirroring component `purl`. Required: readers resolve the checkout from this instead of guessing the repo from the step's endpoint components."
|
|
292
|
+
},
|
|
287
293
|
"symbol": {
|
|
288
294
|
"type": "string",
|
|
289
295
|
"minLength": 1,
|
|
@@ -272,7 +272,14 @@ export type SubsystemConstructDeclaration =
|
|
|
272
272
|
|
|
273
273
|
/** A component node — the named unit, construct-tagged. */
|
|
274
274
|
export interface SubsystemComponent {
|
|
275
|
-
|
|
275
|
+
/**
|
|
276
|
+
* Model-local stable alias. Referenced by relation / walkthrough `from` /
|
|
277
|
+
* `to`; unique per model. Edges point at the alias, not the location — a
|
|
278
|
+
* file move or symbol rename leaves edges intact. Code identity lives on
|
|
279
|
+
* `purl` + `file` + `symbol` and is what composed (multi-model) views
|
|
280
|
+
* join on, not this field.
|
|
281
|
+
*/
|
|
282
|
+
alias: string;
|
|
276
283
|
/** Display label. Prefer aligning with `symbol` when present. */
|
|
277
284
|
name: string;
|
|
278
285
|
construct: SubsystemConstruct;
|
|
@@ -333,9 +340,9 @@ export interface SubsystemComponent {
|
|
|
333
340
|
/** A topology relation between components (structural / module / type). */
|
|
334
341
|
export interface SubsystemRelation {
|
|
335
342
|
id: string;
|
|
336
|
-
/** Source component
|
|
343
|
+
/** Source component alias. */
|
|
337
344
|
from: string;
|
|
338
|
-
/** Target component
|
|
345
|
+
/** Target component alias (or external label). */
|
|
339
346
|
to: string;
|
|
340
347
|
relationType: SubsystemRelationType;
|
|
341
348
|
/** Concrete file/symbol evidence (often purls). */
|
|
@@ -355,15 +362,22 @@ export interface SubsystemComponentEdge {
|
|
|
355
362
|
}
|
|
356
363
|
|
|
357
364
|
export interface SubsystemWalkthroughStep {
|
|
358
|
-
/** Source component
|
|
365
|
+
/** Source component alias. */
|
|
359
366
|
from: string;
|
|
360
|
-
/** Target component
|
|
367
|
+
/** Target component alias. */
|
|
361
368
|
to: string;
|
|
362
369
|
/** Runtime seam label (Set B). */
|
|
363
370
|
mechanism: SubsystemWalkthroughMechanism;
|
|
364
371
|
file: string;
|
|
365
372
|
/** 1-based line within `file`. */
|
|
366
373
|
line: number;
|
|
374
|
+
/**
|
|
375
|
+
* File-anchored purl of the seam site (e.g.
|
|
376
|
+
* `pkg:github/owner/name#path/to/file.ts`), mirroring component `purl`.
|
|
377
|
+
* Required: readers resolve the checkout from this instead of guessing
|
|
378
|
+
* the repo from the step's endpoint components.
|
|
379
|
+
*/
|
|
380
|
+
purl: string;
|
|
367
381
|
/** Frame name for this hop (function/method/symbol). Optional. */
|
|
368
382
|
symbol?: string;
|
|
369
383
|
/**
|
package/src/validation.test.ts
CHANGED
|
@@ -3,14 +3,14 @@ import { validateSubsystemModelCrossField } from './validation';
|
|
|
3
3
|
import type { SubsystemModelDocument } from './types/subsystem-model';
|
|
4
4
|
|
|
5
5
|
function comp(
|
|
6
|
-
|
|
6
|
+
alias: string,
|
|
7
7
|
extra: Partial<SubsystemModelDocument['components'][number]> = {},
|
|
8
8
|
) {
|
|
9
9
|
return {
|
|
10
|
-
|
|
11
|
-
name:
|
|
10
|
+
alias,
|
|
11
|
+
name: alias,
|
|
12
12
|
construct: 'function' as const,
|
|
13
|
-
file: `src/${
|
|
13
|
+
file: `src/${alias}.ts`,
|
|
14
14
|
purl: 'pkg:github/acme/app',
|
|
15
15
|
...extra,
|
|
16
16
|
};
|
|
@@ -34,19 +34,19 @@ describe('validateSubsystemModelCrossField', () => {
|
|
|
34
34
|
{
|
|
35
35
|
id: 'w1',
|
|
36
36
|
title: 'flow',
|
|
37
|
-
steps: [{ from: 'a', to: 'b', mechanism: 'calls', file: 'src/a.ts', line: 1 }],
|
|
37
|
+
steps: [{ from: 'a', to: 'b', mechanism: 'calls', file: 'src/a.ts', line: 1, purl: 'pkg:github/acme/app#src/a.ts' }],
|
|
38
38
|
},
|
|
39
39
|
],
|
|
40
40
|
});
|
|
41
41
|
expect(validateSubsystemModelCrossField(d)).toEqual([]);
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
test('flags duplicate component
|
|
44
|
+
test('flags duplicate component aliases', () => {
|
|
45
45
|
const problems = validateSubsystemModelCrossField(
|
|
46
46
|
doc({ components: [comp('a'), comp('a')] }),
|
|
47
47
|
);
|
|
48
48
|
expect(problems).toHaveLength(1);
|
|
49
|
-
expect(problems[0]!.message).toContain('duplicate
|
|
49
|
+
expect(problems[0]!.message).toContain('duplicate alias');
|
|
50
50
|
});
|
|
51
51
|
|
|
52
52
|
test('flags relation endpoints that reference no component', () => {
|
|
@@ -68,7 +68,7 @@ describe('validateSubsystemModelCrossField', () => {
|
|
|
68
68
|
{
|
|
69
69
|
id: 'w1',
|
|
70
70
|
title: 'flow',
|
|
71
|
-
steps: [{ from: 'ghost', to: 'a', mechanism: 'calls', file: 'src/a.ts', line: 1 }],
|
|
71
|
+
steps: [{ from: 'ghost', to: 'a', mechanism: 'calls', file: 'src/a.ts', line: 1, purl: 'pkg:github/acme/app#src/a.ts' }],
|
|
72
72
|
},
|
|
73
73
|
],
|
|
74
74
|
}),
|
|
@@ -77,6 +77,23 @@ describe('validateSubsystemModelCrossField', () => {
|
|
|
77
77
|
expect(problems[0]!.path).toBe('/walkthroughs/0/steps/0/from');
|
|
78
78
|
});
|
|
79
79
|
|
|
80
|
+
test('flags walkthrough step purl fragments that mismatch the step file', () => {
|
|
81
|
+
const problems = validateSubsystemModelCrossField(
|
|
82
|
+
doc({
|
|
83
|
+
components: [comp('a')],
|
|
84
|
+
walkthroughs: [
|
|
85
|
+
{
|
|
86
|
+
id: 'w1',
|
|
87
|
+
title: 'flow',
|
|
88
|
+
steps: [{ from: 'a', to: 'a', mechanism: 'calls', file: 'src/a.ts', line: 1, purl: 'pkg:github/acme/app#src/other.ts' }],
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
}),
|
|
92
|
+
);
|
|
93
|
+
expect(problems).toHaveLength(1);
|
|
94
|
+
expect(problems[0]!.path).toBe('/walkthroughs/0/steps/0/purl');
|
|
95
|
+
});
|
|
96
|
+
|
|
80
97
|
test('module implies file, exempting external/proposed', () => {
|
|
81
98
|
const bad = validateSubsystemModelCrossField(
|
|
82
99
|
doc({ components: [comp('a', { module: 'src/host', file: '' })] }),
|
package/src/validation.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Cross-field validation for a subsystem model document.
|
|
3
3
|
*
|
|
4
4
|
* These are the rules the JSON Schema (`schemas/subsystem-model.schema.json`)
|
|
5
|
-
* cannot express — anything that spans fields or arrays:
|
|
5
|
+
* cannot express — anything that spans fields or arrays: alias uniqueness,
|
|
6
6
|
* referential integrity between relations/walkthroughs and components, and the
|
|
7
7
|
* `module` implies `file` invariant. Structural checks (types, `required`,
|
|
8
8
|
* enums, ranges, closed objects) belong to the schema and are enforced per
|
|
@@ -39,17 +39,17 @@ export function validateSubsystemModelCrossField(
|
|
|
39
39
|
const relations = doc.relations ?? [];
|
|
40
40
|
const walkthroughs = doc.walkthroughs ?? [];
|
|
41
41
|
|
|
42
|
-
// Component
|
|
43
|
-
// relations and walkthrough steps.
|
|
42
|
+
// Component aliases must be unique, and the set is the referential target
|
|
43
|
+
// for relations and walkthrough steps.
|
|
44
44
|
const ids = new Set<string>();
|
|
45
45
|
components.forEach((c, i) => {
|
|
46
|
-
if (ids.has(c.
|
|
46
|
+
if (ids.has(c.alias)) {
|
|
47
47
|
problems.push({
|
|
48
|
-
path: `/components/${i}/
|
|
49
|
-
message: `component ${JSON.stringify(c.
|
|
48
|
+
path: `/components/${i}/alias`,
|
|
49
|
+
message: `component ${JSON.stringify(c.alias)}: duplicate alias`,
|
|
50
50
|
});
|
|
51
51
|
} else {
|
|
52
|
-
ids.add(c.
|
|
52
|
+
ids.add(c.alias);
|
|
53
53
|
}
|
|
54
54
|
// A grounded component that claims a `module` needs a `file` to ground the
|
|
55
55
|
// frame. Externals / proposed carry no file by design.
|
|
@@ -58,7 +58,7 @@ export function validateSubsystemModelCrossField(
|
|
|
58
58
|
if (module && !file && !isUngrounded(c)) {
|
|
59
59
|
problems.push({
|
|
60
60
|
path: `/components/${i}/module`,
|
|
61
|
-
message: `component ${JSON.stringify(c.
|
|
61
|
+
message: `component ${JSON.stringify(c.alias)}: module ${JSON.stringify(module)} is set but file is empty — a module frame needs a file to ground it (mark the component proposed if it is not placed yet).`,
|
|
62
62
|
});
|
|
63
63
|
}
|
|
64
64
|
});
|
|
@@ -67,13 +67,13 @@ export function validateSubsystemModelCrossField(
|
|
|
67
67
|
if (!ids.has(r.from)) {
|
|
68
68
|
problems.push({
|
|
69
69
|
path: `/relations/${i}/from`,
|
|
70
|
-
message: `relation ${JSON.stringify(r.id)}: from ${JSON.stringify(r.from)} does not match any component
|
|
70
|
+
message: `relation ${JSON.stringify(r.id)}: from ${JSON.stringify(r.from)} does not match any component alias`,
|
|
71
71
|
});
|
|
72
72
|
}
|
|
73
73
|
if (!ids.has(r.to)) {
|
|
74
74
|
problems.push({
|
|
75
75
|
path: `/relations/${i}/to`,
|
|
76
|
-
message: `relation ${JSON.stringify(r.id)}: to ${JSON.stringify(r.to)} does not match any component
|
|
76
|
+
message: `relation ${JSON.stringify(r.id)}: to ${JSON.stringify(r.to)} does not match any component alias`,
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
79
|
});
|
|
@@ -83,15 +83,27 @@ export function validateSubsystemModelCrossField(
|
|
|
83
83
|
if (!ids.has(step.from)) {
|
|
84
84
|
problems.push({
|
|
85
85
|
path: `/walkthroughs/${wi}/steps/${si}/from`,
|
|
86
|
-
message: `walkthrough ${JSON.stringify(w.id)}: step ${si} from ${JSON.stringify(step.from)} does not match any component
|
|
86
|
+
message: `walkthrough ${JSON.stringify(w.id)}: step ${si} from ${JSON.stringify(step.from)} does not match any component alias`,
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
89
|
if (!ids.has(step.to)) {
|
|
90
90
|
problems.push({
|
|
91
91
|
path: `/walkthroughs/${wi}/steps/${si}/to`,
|
|
92
|
-
message: `walkthrough ${JSON.stringify(w.id)}: step ${si} to ${JSON.stringify(step.to)} does not match any component
|
|
92
|
+
message: `walkthrough ${JSON.stringify(w.id)}: step ${si} to ${JSON.stringify(step.to)} does not match any component alias`,
|
|
93
93
|
});
|
|
94
94
|
}
|
|
95
|
+
// A file-anchored step purl names its own site: the fragment must be
|
|
96
|
+
// the step file. Repo-only purls still resolve, so only the anchored
|
|
97
|
+
// form is checked.
|
|
98
|
+
if (typeof step.purl === 'string' && step.purl.includes('#')) {
|
|
99
|
+
const fragment = step.purl.split('#').slice(1).join('#');
|
|
100
|
+
if (fragment !== step.file) {
|
|
101
|
+
problems.push({
|
|
102
|
+
path: `/walkthroughs/${wi}/steps/${si}/purl`,
|
|
103
|
+
message: `walkthrough ${JSON.stringify(w.id)}: step ${si} purl fragment ${JSON.stringify(fragment)} does not match step file ${JSON.stringify(step.file)}`,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
95
107
|
});
|
|
96
108
|
});
|
|
97
109
|
|