@principal-ai/principal-view-cli 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/formats.js +69 -69
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +52 -13
- package/dist/index.cjs +110 -75
- package/dist/index.cjs.map +2 -2
- package/package.json +2 -2
package/dist/commands/formats.js
CHANGED
|
@@ -181,100 +181,100 @@ ${chalk.bold('Validation:')}
|
|
|
181
181
|
${chalk.bold.cyan('Execution Format (.otel.json)')}
|
|
182
182
|
${chalk.dim('═'.repeat(70))}
|
|
183
183
|
|
|
184
|
-
Execution files
|
|
185
|
-
These files are exported by
|
|
184
|
+
Execution files use the ${chalk.bold('standard OTLP (OpenTelemetry Protocol) JSON format')}.
|
|
185
|
+
These files are exported by OpenTelemetry SDK and used for visualization
|
|
186
186
|
and validation against canvas schemas.
|
|
187
187
|
|
|
188
188
|
${chalk.bold('File Location:')}
|
|
189
189
|
${chalk.yellow('__executions__/')}${chalk.dim('<feature-name>.otel.json')}
|
|
190
|
-
${chalk.dim('(auto-generated by test infrastructure)')}
|
|
190
|
+
${chalk.dim('(auto-generated by test infrastructure with OpenTelemetry SDK)')}
|
|
191
191
|
|
|
192
192
|
${chalk.bold('IMPORTANT:')} __executions__/ directory must be committed to git!
|
|
193
193
|
|
|
194
|
-
${chalk.bold('File Structure:')}
|
|
194
|
+
${chalk.bold('File Structure (OTLP JSON Format):')}
|
|
195
195
|
${chalk.dim('┌────────────────────────────────────────────────────────────────────┐')}
|
|
196
196
|
${chalk.dim('│')} { ${chalk.dim('│')}
|
|
197
|
-
${chalk.dim('│')} ${chalk.green('"
|
|
198
|
-
${chalk.dim('│')} ${chalk.green('"serviceName"')}: "my-service", ${chalk.dim('// Service name')} ${chalk.dim('│')}
|
|
199
|
-
${chalk.dim('│')} ${chalk.green('"spanCount"')}: 5, ${chalk.dim('// Total spans')} ${chalk.dim('│')}
|
|
200
|
-
${chalk.dim('│')} ${chalk.green('"spans"')}: [ ${chalk.dim('│')}
|
|
197
|
+
${chalk.dim('│')} ${chalk.green('"resourceSpans"')}: [ ${chalk.dim('// OTLP root structure')} ${chalk.dim('│')}
|
|
201
198
|
${chalk.dim('│')} { ${chalk.dim('│')}
|
|
202
|
-
${chalk.dim('│')} ${chalk.yellow('"
|
|
203
|
-
${chalk.dim('│')}
|
|
204
|
-
${chalk.dim('│')}
|
|
205
|
-
${chalk.dim('│')}
|
|
206
|
-
${chalk.dim('│')}
|
|
207
|
-
${chalk.dim('│')} ${chalk.yellow('"
|
|
208
|
-
${chalk.dim('│')}
|
|
209
|
-
${chalk.dim('│')}
|
|
210
|
-
${chalk.dim('│')}
|
|
211
|
-
${chalk.dim('│')}
|
|
212
|
-
${chalk.dim('│')}
|
|
213
|
-
${chalk.dim('│')}
|
|
214
|
-
${chalk.dim('│')} ${chalk.
|
|
215
|
-
${chalk.dim('│')}
|
|
216
|
-
${chalk.dim('│')}
|
|
217
|
-
${chalk.dim('│')}
|
|
199
|
+
${chalk.dim('│')} ${chalk.yellow('"resource"')}: { ${chalk.dim('│')}
|
|
200
|
+
${chalk.dim('│')} ${chalk.cyan('"attributes"')}: [ ${chalk.dim('│')}
|
|
201
|
+
${chalk.dim('│')} { "key": "service.name", "value": { "stringValue": "..." }} ${chalk.dim('│')}
|
|
202
|
+
${chalk.dim('│')} ] ${chalk.dim('│')}
|
|
203
|
+
${chalk.dim('│')} }, ${chalk.dim('│')}
|
|
204
|
+
${chalk.dim('│')} ${chalk.yellow('"scopeSpans"')}: [ ${chalk.dim('│')}
|
|
205
|
+
${chalk.dim('│')} { ${chalk.dim('│')}
|
|
206
|
+
${chalk.dim('│')} ${chalk.cyan('"scope"')}: { "name": "...", "version": "..." }, ${chalk.dim('│')}
|
|
207
|
+
${chalk.dim('│')} ${chalk.cyan('"spans"')}: [ ${chalk.dim('│')}
|
|
208
|
+
${chalk.dim('│')} { ${chalk.dim('│')}
|
|
209
|
+
${chalk.dim('│')} "traceId": "4bf92f3577b34da6...", ${chalk.dim('// 32 hex chars')} ${chalk.dim('│')}
|
|
210
|
+
${chalk.dim('│')} "spanId": "00f067aa0ba902b7", ${chalk.dim('// 16 hex chars')} ${chalk.dim('│')}
|
|
211
|
+
${chalk.dim('│')} "name": "test:feature-name", ${chalk.dim('// Span name')} ${chalk.dim('│')}
|
|
212
|
+
${chalk.dim('│')} "kind": 0, ${chalk.dim('// 0=INTERNAL')} ${chalk.dim('│')}
|
|
213
|
+
${chalk.dim('│')} "startTimeUnixNano": "1703...", ${chalk.dim('// Unix nanoseconds')} ${chalk.dim('│')}
|
|
214
|
+
${chalk.dim('│')} "endTimeUnixNano": "1703...", ${chalk.dim('// Unix nanoseconds')} ${chalk.dim('│')}
|
|
215
|
+
${chalk.dim('│')} "attributes": [ ${chalk.dim('// Key-value pairs')} ${chalk.dim('│')}
|
|
216
|
+
${chalk.dim('│')} { "key": "input.size", "value": { "intValue": 42 } } ${chalk.dim('│')}
|
|
217
|
+
${chalk.dim('│')} ], ${chalk.dim('│')}
|
|
218
|
+
${chalk.dim('│')} "events": [ ${chalk.dim('// Span events')} ${chalk.dim('│')}
|
|
219
|
+
${chalk.dim('│')} { ${chalk.dim('│')}
|
|
220
|
+
${chalk.dim('│')} "timeUnixNano": "1703...", ${chalk.dim('│')}
|
|
221
|
+
${chalk.dim('│')} "name": "validation.started", ${chalk.dim('│')}
|
|
222
|
+
${chalk.dim('│')} "attributes": [...] ${chalk.dim('│')}
|
|
223
|
+
${chalk.dim('│')} } ${chalk.dim('│')}
|
|
224
|
+
${chalk.dim('│')} ] ${chalk.dim('│')}
|
|
225
|
+
${chalk.dim('│')} } ${chalk.dim('│')}
|
|
226
|
+
${chalk.dim('│')} ] ${chalk.dim('│')}
|
|
227
|
+
${chalk.dim('│')} } ${chalk.dim('│')}
|
|
228
|
+
${chalk.dim('│')} ] ${chalk.dim('│')}
|
|
218
229
|
${chalk.dim('│')} } ${chalk.dim('│')}
|
|
219
230
|
${chalk.dim('│')} ] ${chalk.dim('│')}
|
|
220
231
|
${chalk.dim('│')} } ${chalk.dim('│')}
|
|
221
232
|
${chalk.dim('└────────────────────────────────────────────────────────────────────┘')}
|
|
222
233
|
|
|
223
|
-
${chalk.bold('
|
|
234
|
+
${chalk.bold('OTLP Format Details:')}
|
|
224
235
|
|
|
225
|
-
${chalk.cyan('
|
|
226
|
-
|
|
236
|
+
${chalk.cyan('resourceSpans')} ${chalk.dim('(array, required)')}
|
|
237
|
+
Root array containing resource-grouped spans
|
|
227
238
|
|
|
228
|
-
${chalk.cyan('
|
|
229
|
-
|
|
239
|
+
${chalk.cyan('resource.attributes')} ${chalk.dim('(array)')}
|
|
240
|
+
Metadata about the service (e.g., service.name)
|
|
230
241
|
|
|
231
|
-
${chalk.cyan('
|
|
232
|
-
|
|
242
|
+
${chalk.cyan('scopeSpans')} ${chalk.dim('(array, required)')}
|
|
243
|
+
Instrumentation scope-grouped spans
|
|
233
244
|
|
|
234
245
|
${chalk.cyan('spans')} ${chalk.dim('(array, required)')}
|
|
235
|
-
Array of span objects
|
|
236
|
-
|
|
237
|
-
${chalk.bold('Span
|
|
238
|
-
|
|
239
|
-
${chalk.cyan('traceId')} ${chalk.dim('(string
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
${chalk.cyan('
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
${chalk.cyan('
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
${chalk.cyan('
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
Unix timestamp in milliseconds when span started
|
|
256
|
-
|
|
257
|
-
${chalk.cyan('endTime')} ${chalk.dim('(number)')}
|
|
258
|
-
Unix timestamp in milliseconds when span ended
|
|
259
|
-
|
|
260
|
-
${chalk.cyan('duration')} ${chalk.dim('(number)')}
|
|
261
|
-
Duration in milliseconds (endTime - startTime)
|
|
262
|
-
|
|
263
|
-
${chalk.cyan('attributes')} ${chalk.dim('(object)')}
|
|
264
|
-
Key-value pairs of event attributes (validated against canvas schema)
|
|
265
|
-
|
|
266
|
-
${chalk.cyan('status')} ${chalk.dim('(object)')}
|
|
267
|
-
Status code (OK, ERROR, UNSET) and optional message
|
|
268
|
-
|
|
269
|
-
${chalk.cyan('events')} ${chalk.dim('(array)')}
|
|
270
|
-
Optional array of timestamped events within the span
|
|
246
|
+
Array of span objects with OTLP structure
|
|
247
|
+
|
|
248
|
+
${chalk.bold('Span Fields (OTLP Standard):')}
|
|
249
|
+
|
|
250
|
+
${chalk.cyan('traceId')} ${chalk.dim('(string)')} - Unique trace identifier (32 hex chars)
|
|
251
|
+
${chalk.cyan('spanId')} ${chalk.dim('(string)')} - Unique span identifier (16 hex chars)
|
|
252
|
+
${chalk.cyan('parentSpanId')} ${chalk.dim('(string, optional)')} - Parent span ID
|
|
253
|
+
${chalk.cyan('name')} ${chalk.dim('(string)')} - Operation name
|
|
254
|
+
${chalk.cyan('kind')} ${chalk.dim('(number)')} - 0=UNSPECIFIED, 1=INTERNAL, 2=SERVER, 3=CLIENT, 4=PRODUCER, 5=CONSUMER
|
|
255
|
+
${chalk.cyan('startTimeUnixNano')} ${chalk.dim('(string)')} - Start time in Unix nanoseconds
|
|
256
|
+
${chalk.cyan('endTimeUnixNano')} ${chalk.dim('(string)')} - End time in Unix nanoseconds
|
|
257
|
+
${chalk.cyan('attributes')} ${chalk.dim('(array)')} - Key-value pairs: [{ key, value: { stringValue|intValue|... } }]
|
|
258
|
+
${chalk.cyan('events')} ${chalk.dim('(array)')} - Span events with timestamps and attributes
|
|
259
|
+
${chalk.cyan('status')} ${chalk.dim('(object)')} - Status: { code: 1=OK, 2=ERROR }
|
|
260
|
+
|
|
261
|
+
${chalk.bold('Attribute Value Format:')}
|
|
262
|
+
{ "stringValue": "..." } ${chalk.dim('// For strings')}
|
|
263
|
+
{ "intValue": 42 } ${chalk.dim('// For integers')}
|
|
264
|
+
{ "doubleValue": 3.14 } ${chalk.dim('// For floats')}
|
|
265
|
+
{ "boolValue": true } ${chalk.dim('// For booleans')}
|
|
271
266
|
|
|
272
267
|
${chalk.bold('Generation:')}
|
|
273
|
-
|
|
274
|
-
|
|
268
|
+
Use OpenTelemetry SDK with OTLP JSON exporter
|
|
269
|
+
Example: @opentelemetry/sdk-trace-node + InMemorySpanExporter
|
|
270
|
+
See: tests/otel-setup.ts in the add-skill repository
|
|
275
271
|
|
|
276
272
|
${chalk.bold('Validation:')}
|
|
277
273
|
${chalk.cyan('npx @principal-ai/principal-view-cli validate-execution <file>')}
|
|
274
|
+
|
|
275
|
+
${chalk.bold('Resources:')}
|
|
276
|
+
OTLP Spec: https://opentelemetry.io/docs/specs/otlp/
|
|
277
|
+
OpenTelemetry JS: https://github.com/open-telemetry/opentelemetry-js
|
|
278
278
|
`,
|
|
279
279
|
examples: `
|
|
280
280
|
${chalk.bold.cyan('Complete File Examples')}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0sCpC,wBAAgB,qBAAqB,IAAI,OAAO,CAiI/C"}
|
|
@@ -225,7 +225,7 @@ const ALLOWED_CANVAS_FIELDS = {
|
|
|
225
225
|
'name',
|
|
226
226
|
'description',
|
|
227
227
|
'otel',
|
|
228
|
-
'
|
|
228
|
+
'event',
|
|
229
229
|
'shape',
|
|
230
230
|
'icon',
|
|
231
231
|
'fill',
|
|
@@ -346,7 +346,7 @@ function findSimilarField(field, allowedFields) {
|
|
|
346
346
|
* Check if a canvas has OTEL-related features
|
|
347
347
|
* Returns true if the canvas contains any of:
|
|
348
348
|
* 1. Nodes with pv.otel extension (kind, category)
|
|
349
|
-
* 2. Event
|
|
349
|
+
* 2. Event schema (pv.event with validation)
|
|
350
350
|
* 3. Canvas scope/audit config (OTEL log routing)
|
|
351
351
|
* 4. Resource matching for OTEL logs
|
|
352
352
|
*/
|
|
@@ -373,8 +373,8 @@ function hasOtelFeatures(canvas) {
|
|
|
373
373
|
if (nodePv.otel !== undefined) {
|
|
374
374
|
return true;
|
|
375
375
|
}
|
|
376
|
-
// Check for event
|
|
377
|
-
if (nodePv.
|
|
376
|
+
// Check for event schema (pv.event)
|
|
377
|
+
if (nodePv.event !== undefined) {
|
|
378
378
|
return true;
|
|
379
379
|
}
|
|
380
380
|
// Check for resourceMatch (OTEL log routing)
|
|
@@ -634,8 +634,19 @@ function validateCanvas(canvas, filePath, library, repositoryPath) {
|
|
|
634
634
|
if (nodePv.otel && typeof nodePv.otel === 'object') {
|
|
635
635
|
checkUnknownFields(nodePv.otel, ALLOWED_CANVAS_FIELDS.nodePvOtel, `${nodePath}.pv.otel`, issues);
|
|
636
636
|
}
|
|
637
|
+
// For .otel.canvas files: require event field on nodes with pv extension (except groups)
|
|
638
|
+
if (filePath.endsWith('.otel.canvas') && nodeType !== 'group') {
|
|
639
|
+
if (nodePv.event === undefined) {
|
|
640
|
+
issues.push({
|
|
641
|
+
type: 'error',
|
|
642
|
+
message: `Node "${nodeLabel}" in .otel.canvas file must have "pv.event" field`,
|
|
643
|
+
path: `${nodePath}.pv.event`,
|
|
644
|
+
suggestion: 'Add event name, e.g.: "event": "user.login" or "event": "order.created"',
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
}
|
|
637
648
|
// Validate source file references for OTEL event nodes
|
|
638
|
-
const hasOtelFeatures = nodePv.otel !== undefined || nodePv.
|
|
649
|
+
const hasOtelFeatures = nodePv.otel !== undefined || nodePv.event !== undefined;
|
|
639
650
|
if (hasOtelFeatures) {
|
|
640
651
|
// OTEL nodes must have at least one source file reference
|
|
641
652
|
if (!Array.isArray(nodePv.sources) || nodePv.sources.length === 0) {
|
|
@@ -646,22 +657,50 @@ function validateCanvas(canvas, filePath, library, repositoryPath) {
|
|
|
646
657
|
suggestion: 'Add at least one source file reference, e.g.: "sources": ["src/services/MyService.ts"]',
|
|
647
658
|
});
|
|
648
659
|
}
|
|
660
|
+
// For .otel.canvas files: nodes with event must have pv.otel for UI rendering
|
|
661
|
+
if (filePath.endsWith('.otel.canvas') && nodePv.event !== undefined && nodePv.otel === undefined) {
|
|
662
|
+
issues.push({
|
|
663
|
+
type: 'error',
|
|
664
|
+
message: `Node "${nodeLabel}" in .otel.canvas file has event but is missing "pv.otel" field required for UI badges`,
|
|
665
|
+
path: `${nodePath}.pv.otel`,
|
|
666
|
+
suggestion: 'Add OTEL metadata for UI rendering, e.g.: "otel": { "kind": "event", "category": "lifecycle", "isNew": true }',
|
|
667
|
+
});
|
|
668
|
+
}
|
|
649
669
|
}
|
|
650
|
-
// Validate
|
|
651
|
-
if (Array.isArray(nodePv.sources)
|
|
670
|
+
// Validate source file paths
|
|
671
|
+
if (Array.isArray(nodePv.sources)) {
|
|
652
672
|
nodePv.sources.forEach((source, sourceIndex) => {
|
|
653
673
|
if (typeof source === 'string') {
|
|
654
|
-
//
|
|
655
|
-
|
|
656
|
-
const fullPath = resolve(repositoryPath, cleanPath);
|
|
657
|
-
if (!existsSync(fullPath)) {
|
|
674
|
+
// Check for glob patterns
|
|
675
|
+
if (/[*?[\]{}]/.test(source)) {
|
|
658
676
|
issues.push({
|
|
659
677
|
type: 'error',
|
|
660
|
-
message: `Node "${nodeLabel}"
|
|
678
|
+
message: `Node "${nodeLabel}" has glob pattern in sources: ${source}`,
|
|
661
679
|
path: `${nodePath}.pv.sources[${sourceIndex}]`,
|
|
662
|
-
suggestion:
|
|
680
|
+
suggestion: 'Use exact file paths only. Glob patterns (*, ?, [], {}) are not supported in sources.',
|
|
663
681
|
});
|
|
664
682
|
}
|
|
683
|
+
// Check for line number suffix (e.g., "file.ts:123")
|
|
684
|
+
if (/:\d+$/.test(source)) {
|
|
685
|
+
issues.push({
|
|
686
|
+
type: 'error',
|
|
687
|
+
message: `Node "${nodeLabel}" has line number suffix in sources: ${source}`,
|
|
688
|
+
path: `${nodePath}.pv.sources[${sourceIndex}]`,
|
|
689
|
+
suggestion: 'Remove line number suffix. Use exact file paths only (e.g., "src/file.ts" not "src/file.ts:123").',
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
// Validate that source file exists (if repository path is provided)
|
|
693
|
+
if (repositoryPath) {
|
|
694
|
+
const fullPath = resolve(repositoryPath, source);
|
|
695
|
+
if (!existsSync(fullPath)) {
|
|
696
|
+
issues.push({
|
|
697
|
+
type: 'error',
|
|
698
|
+
message: `Node "${nodeLabel}" references non-existent source file: ${source}`,
|
|
699
|
+
path: `${nodePath}.pv.sources[${sourceIndex}]`,
|
|
700
|
+
suggestion: `Verify the file path is correct relative to repository root: ${repositoryPath}`,
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
}
|
|
665
704
|
}
|
|
666
705
|
});
|
|
667
706
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -228612,7 +228612,7 @@ var ALLOWED_CANVAS_FIELDS = {
|
|
|
228612
228612
|
"name",
|
|
228613
228613
|
"description",
|
|
228614
228614
|
"otel",
|
|
228615
|
-
"
|
|
228615
|
+
"event",
|
|
228616
228616
|
"shape",
|
|
228617
228617
|
"icon",
|
|
228618
228618
|
"fill",
|
|
@@ -228735,7 +228735,7 @@ function hasOtelFeatures(canvas) {
|
|
|
228735
228735
|
if (nodePv.otel !== void 0) {
|
|
228736
228736
|
return true;
|
|
228737
228737
|
}
|
|
228738
|
-
if (nodePv.
|
|
228738
|
+
if (nodePv.event !== void 0) {
|
|
228739
228739
|
return true;
|
|
228740
228740
|
}
|
|
228741
228741
|
if (nodePv.resourceMatch !== void 0) {
|
|
@@ -229019,7 +229019,17 @@ function validateCanvas(canvas, filePath, library, repositoryPath) {
|
|
|
229019
229019
|
issues
|
|
229020
229020
|
);
|
|
229021
229021
|
}
|
|
229022
|
-
|
|
229022
|
+
if (filePath.endsWith(".otel.canvas") && nodeType !== "group") {
|
|
229023
|
+
if (nodePv.event === void 0) {
|
|
229024
|
+
issues.push({
|
|
229025
|
+
type: "error",
|
|
229026
|
+
message: `Node "${nodeLabel}" in .otel.canvas file must have "pv.event" field`,
|
|
229027
|
+
path: `${nodePath2}.pv.event`,
|
|
229028
|
+
suggestion: 'Add event name, e.g.: "event": "user.login" or "event": "order.created"'
|
|
229029
|
+
});
|
|
229030
|
+
}
|
|
229031
|
+
}
|
|
229032
|
+
const hasOtelFeatures2 = nodePv.otel !== void 0 || nodePv.event !== void 0;
|
|
229023
229033
|
if (hasOtelFeatures2) {
|
|
229024
229034
|
if (!Array.isArray(nodePv.sources) || nodePv.sources.length === 0) {
|
|
229025
229035
|
issues.push({
|
|
@@ -229029,20 +229039,45 @@ function validateCanvas(canvas, filePath, library, repositoryPath) {
|
|
|
229029
229039
|
suggestion: 'Add at least one source file reference, e.g.: "sources": ["src/services/MyService.ts"]'
|
|
229030
229040
|
});
|
|
229031
229041
|
}
|
|
229042
|
+
if (filePath.endsWith(".otel.canvas") && nodePv.event !== void 0 && nodePv.otel === void 0) {
|
|
229043
|
+
issues.push({
|
|
229044
|
+
type: "error",
|
|
229045
|
+
message: `Node "${nodeLabel}" in .otel.canvas file has event but is missing "pv.otel" field required for UI badges`,
|
|
229046
|
+
path: `${nodePath2}.pv.otel`,
|
|
229047
|
+
suggestion: 'Add OTEL metadata for UI rendering, e.g.: "otel": { "kind": "event", "category": "lifecycle", "isNew": true }'
|
|
229048
|
+
});
|
|
229049
|
+
}
|
|
229032
229050
|
}
|
|
229033
|
-
if (Array.isArray(nodePv.sources)
|
|
229051
|
+
if (Array.isArray(nodePv.sources)) {
|
|
229034
229052
|
nodePv.sources.forEach((source, sourceIndex) => {
|
|
229035
229053
|
if (typeof source === "string") {
|
|
229036
|
-
|
|
229037
|
-
|
|
229038
|
-
|
|
229054
|
+
if (/[*?[\]{}]/.test(source)) {
|
|
229055
|
+
issues.push({
|
|
229056
|
+
type: "error",
|
|
229057
|
+
message: `Node "${nodeLabel}" has glob pattern in sources: ${source}`,
|
|
229058
|
+
path: `${nodePath2}.pv.sources[${sourceIndex}]`,
|
|
229059
|
+
suggestion: "Use exact file paths only. Glob patterns (*, ?, [], {}) are not supported in sources."
|
|
229060
|
+
});
|
|
229061
|
+
}
|
|
229062
|
+
if (/:\d+$/.test(source)) {
|
|
229039
229063
|
issues.push({
|
|
229040
229064
|
type: "error",
|
|
229041
|
-
message: `Node "${nodeLabel}"
|
|
229065
|
+
message: `Node "${nodeLabel}" has line number suffix in sources: ${source}`,
|
|
229042
229066
|
path: `${nodePath2}.pv.sources[${sourceIndex}]`,
|
|
229043
|
-
suggestion:
|
|
229067
|
+
suggestion: 'Remove line number suffix. Use exact file paths only (e.g., "src/file.ts" not "src/file.ts:123").'
|
|
229044
229068
|
});
|
|
229045
229069
|
}
|
|
229070
|
+
if (repositoryPath) {
|
|
229071
|
+
const fullPath = (0, import_node_path5.resolve)(repositoryPath, source);
|
|
229072
|
+
if (!(0, import_node_fs4.existsSync)(fullPath)) {
|
|
229073
|
+
issues.push({
|
|
229074
|
+
type: "error",
|
|
229075
|
+
message: `Node "${nodeLabel}" references non-existent source file: ${source}`,
|
|
229076
|
+
path: `${nodePath2}.pv.sources[${sourceIndex}]`,
|
|
229077
|
+
suggestion: `Verify the file path is correct relative to repository root: ${repositoryPath}`
|
|
229078
|
+
});
|
|
229079
|
+
}
|
|
229080
|
+
}
|
|
229046
229081
|
}
|
|
229047
229082
|
});
|
|
229048
229083
|
}
|
|
@@ -241290,100 +241325,100 @@ ${source_default.bold("Validation:")}
|
|
|
241290
241325
|
${source_default.bold.cyan("Execution Format (.otel.json)")}
|
|
241291
241326
|
${source_default.dim("\u2550".repeat(70))}
|
|
241292
241327
|
|
|
241293
|
-
Execution files
|
|
241294
|
-
These files are exported by
|
|
241328
|
+
Execution files use the ${source_default.bold("standard OTLP (OpenTelemetry Protocol) JSON format")}.
|
|
241329
|
+
These files are exported by OpenTelemetry SDK and used for visualization
|
|
241295
241330
|
and validation against canvas schemas.
|
|
241296
241331
|
|
|
241297
241332
|
${source_default.bold("File Location:")}
|
|
241298
241333
|
${source_default.yellow("__executions__/")}${source_default.dim("<feature-name>.otel.json")}
|
|
241299
|
-
${source_default.dim("(auto-generated by test infrastructure)")}
|
|
241334
|
+
${source_default.dim("(auto-generated by test infrastructure with OpenTelemetry SDK)")}
|
|
241300
241335
|
|
|
241301
241336
|
${source_default.bold("IMPORTANT:")} __executions__/ directory must be committed to git!
|
|
241302
241337
|
|
|
241303
|
-
${source_default.bold("File Structure:")}
|
|
241338
|
+
${source_default.bold("File Structure (OTLP JSON Format):")}
|
|
241304
241339
|
${source_default.dim("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510")}
|
|
241305
241340
|
${source_default.dim("\u2502")} { ${source_default.dim("\u2502")}
|
|
241306
|
-
${source_default.dim("\u2502")} ${source_default.green('"
|
|
241307
|
-
${source_default.dim("\u2502")} ${source_default.green('"serviceName"')}: "my-service", ${source_default.dim("// Service name")} ${source_default.dim("\u2502")}
|
|
241308
|
-
${source_default.dim("\u2502")} ${source_default.green('"spanCount"')}: 5, ${source_default.dim("// Total spans")} ${source_default.dim("\u2502")}
|
|
241309
|
-
${source_default.dim("\u2502")} ${source_default.green('"spans"')}: [ ${source_default.dim("\u2502")}
|
|
241341
|
+
${source_default.dim("\u2502")} ${source_default.green('"resourceSpans"')}: [ ${source_default.dim("// OTLP root structure")} ${source_default.dim("\u2502")}
|
|
241310
241342
|
${source_default.dim("\u2502")} { ${source_default.dim("\u2502")}
|
|
241311
|
-
${source_default.dim("\u2502")} ${source_default.yellow('"
|
|
241312
|
-
${source_default.dim("\u2502")}
|
|
241313
|
-
${source_default.dim("\u2502")}
|
|
241314
|
-
${source_default.dim("\u2502")}
|
|
241315
|
-
${source_default.dim("\u2502")}
|
|
241316
|
-
${source_default.dim("\u2502")} ${source_default.yellow('"
|
|
241317
|
-
${source_default.dim("\u2502")}
|
|
241318
|
-
${source_default.dim("\u2502")}
|
|
241319
|
-
${source_default.dim("\u2502")}
|
|
241320
|
-
${source_default.dim("\u2502")}
|
|
241321
|
-
${source_default.dim("\u2502")}
|
|
241322
|
-
${source_default.dim("\u2502")}
|
|
241323
|
-
${source_default.dim("\u2502")} ${source_default.
|
|
241324
|
-
${source_default.dim("\u2502")}
|
|
241325
|
-
${source_default.dim("\u2502")}
|
|
241326
|
-
${source_default.dim("\u2502")}
|
|
241343
|
+
${source_default.dim("\u2502")} ${source_default.yellow('"resource"')}: { ${source_default.dim("\u2502")}
|
|
241344
|
+
${source_default.dim("\u2502")} ${source_default.cyan('"attributes"')}: [ ${source_default.dim("\u2502")}
|
|
241345
|
+
${source_default.dim("\u2502")} { "key": "service.name", "value": { "stringValue": "..." }} ${source_default.dim("\u2502")}
|
|
241346
|
+
${source_default.dim("\u2502")} ] ${source_default.dim("\u2502")}
|
|
241347
|
+
${source_default.dim("\u2502")} }, ${source_default.dim("\u2502")}
|
|
241348
|
+
${source_default.dim("\u2502")} ${source_default.yellow('"scopeSpans"')}: [ ${source_default.dim("\u2502")}
|
|
241349
|
+
${source_default.dim("\u2502")} { ${source_default.dim("\u2502")}
|
|
241350
|
+
${source_default.dim("\u2502")} ${source_default.cyan('"scope"')}: { "name": "...", "version": "..." }, ${source_default.dim("\u2502")}
|
|
241351
|
+
${source_default.dim("\u2502")} ${source_default.cyan('"spans"')}: [ ${source_default.dim("\u2502")}
|
|
241352
|
+
${source_default.dim("\u2502")} { ${source_default.dim("\u2502")}
|
|
241353
|
+
${source_default.dim("\u2502")} "traceId": "4bf92f3577b34da6...", ${source_default.dim("// 32 hex chars")} ${source_default.dim("\u2502")}
|
|
241354
|
+
${source_default.dim("\u2502")} "spanId": "00f067aa0ba902b7", ${source_default.dim("// 16 hex chars")} ${source_default.dim("\u2502")}
|
|
241355
|
+
${source_default.dim("\u2502")} "name": "test:feature-name", ${source_default.dim("// Span name")} ${source_default.dim("\u2502")}
|
|
241356
|
+
${source_default.dim("\u2502")} "kind": 0, ${source_default.dim("// 0=INTERNAL")} ${source_default.dim("\u2502")}
|
|
241357
|
+
${source_default.dim("\u2502")} "startTimeUnixNano": "1703...", ${source_default.dim("// Unix nanoseconds")} ${source_default.dim("\u2502")}
|
|
241358
|
+
${source_default.dim("\u2502")} "endTimeUnixNano": "1703...", ${source_default.dim("// Unix nanoseconds")} ${source_default.dim("\u2502")}
|
|
241359
|
+
${source_default.dim("\u2502")} "attributes": [ ${source_default.dim("// Key-value pairs")} ${source_default.dim("\u2502")}
|
|
241360
|
+
${source_default.dim("\u2502")} { "key": "input.size", "value": { "intValue": 42 } } ${source_default.dim("\u2502")}
|
|
241361
|
+
${source_default.dim("\u2502")} ], ${source_default.dim("\u2502")}
|
|
241362
|
+
${source_default.dim("\u2502")} "events": [ ${source_default.dim("// Span events")} ${source_default.dim("\u2502")}
|
|
241363
|
+
${source_default.dim("\u2502")} { ${source_default.dim("\u2502")}
|
|
241364
|
+
${source_default.dim("\u2502")} "timeUnixNano": "1703...", ${source_default.dim("\u2502")}
|
|
241365
|
+
${source_default.dim("\u2502")} "name": "validation.started", ${source_default.dim("\u2502")}
|
|
241366
|
+
${source_default.dim("\u2502")} "attributes": [...] ${source_default.dim("\u2502")}
|
|
241367
|
+
${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
|
|
241368
|
+
${source_default.dim("\u2502")} ] ${source_default.dim("\u2502")}
|
|
241369
|
+
${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
|
|
241370
|
+
${source_default.dim("\u2502")} ] ${source_default.dim("\u2502")}
|
|
241371
|
+
${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
|
|
241372
|
+
${source_default.dim("\u2502")} ] ${source_default.dim("\u2502")}
|
|
241327
241373
|
${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
|
|
241328
241374
|
${source_default.dim("\u2502")} ] ${source_default.dim("\u2502")}
|
|
241329
241375
|
${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
|
|
241330
241376
|
${source_default.dim("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518")}
|
|
241331
241377
|
|
|
241332
|
-
${source_default.bold("
|
|
241378
|
+
${source_default.bold("OTLP Format Details:")}
|
|
241333
241379
|
|
|
241334
|
-
${source_default.cyan("
|
|
241335
|
-
|
|
241380
|
+
${source_default.cyan("resourceSpans")} ${source_default.dim("(array, required)")}
|
|
241381
|
+
Root array containing resource-grouped spans
|
|
241336
241382
|
|
|
241337
|
-
${source_default.cyan("
|
|
241338
|
-
|
|
241383
|
+
${source_default.cyan("resource.attributes")} ${source_default.dim("(array)")}
|
|
241384
|
+
Metadata about the service (e.g., service.name)
|
|
241339
241385
|
|
|
241340
|
-
${source_default.cyan("
|
|
241341
|
-
|
|
241386
|
+
${source_default.cyan("scopeSpans")} ${source_default.dim("(array, required)")}
|
|
241387
|
+
Instrumentation scope-grouped spans
|
|
241342
241388
|
|
|
241343
241389
|
${source_default.cyan("spans")} ${source_default.dim("(array, required)")}
|
|
241344
|
-
Array of span objects
|
|
241345
|
-
|
|
241346
|
-
${source_default.bold("Span Object Fields:")}
|
|
241347
|
-
|
|
241348
|
-
${source_default.cyan("traceId")} ${source_default.dim("(string, 32 hex chars)")}
|
|
241349
|
-
Unique identifier for the entire trace
|
|
241350
|
-
|
|
241351
|
-
${source_default.cyan("spanId")} ${source_default.dim("(string, 16 hex chars)")}
|
|
241352
|
-
Unique identifier for this specific span
|
|
241390
|
+
Array of span objects with OTLP structure
|
|
241353
241391
|
|
|
241354
|
-
${source_default.
|
|
241355
|
-
Parent span ID, or null for root span
|
|
241392
|
+
${source_default.bold("Span Fields (OTLP Standard):")}
|
|
241356
241393
|
|
|
241357
|
-
${source_default.cyan("
|
|
241358
|
-
|
|
241394
|
+
${source_default.cyan("traceId")} ${source_default.dim("(string)")} - Unique trace identifier (32 hex chars)
|
|
241395
|
+
${source_default.cyan("spanId")} ${source_default.dim("(string)")} - Unique span identifier (16 hex chars)
|
|
241396
|
+
${source_default.cyan("parentSpanId")} ${source_default.dim("(string, optional)")} - Parent span ID
|
|
241397
|
+
${source_default.cyan("name")} ${source_default.dim("(string)")} - Operation name
|
|
241398
|
+
${source_default.cyan("kind")} ${source_default.dim("(number)")} - 0=UNSPECIFIED, 1=INTERNAL, 2=SERVER, 3=CLIENT, 4=PRODUCER, 5=CONSUMER
|
|
241399
|
+
${source_default.cyan("startTimeUnixNano")} ${source_default.dim("(string)")} - Start time in Unix nanoseconds
|
|
241400
|
+
${source_default.cyan("endTimeUnixNano")} ${source_default.dim("(string)")} - End time in Unix nanoseconds
|
|
241401
|
+
${source_default.cyan("attributes")} ${source_default.dim("(array)")} - Key-value pairs: [{ key, value: { stringValue|intValue|... } }]
|
|
241402
|
+
${source_default.cyan("events")} ${source_default.dim("(array)")} - Span events with timestamps and attributes
|
|
241403
|
+
${source_default.cyan("status")} ${source_default.dim("(object)")} - Status: { code: 1=OK, 2=ERROR }
|
|
241359
241404
|
|
|
241360
|
-
${source_default.
|
|
241361
|
-
|
|
241362
|
-
|
|
241363
|
-
|
|
241364
|
-
|
|
241365
|
-
|
|
241366
|
-
${source_default.cyan("endTime")} ${source_default.dim("(number)")}
|
|
241367
|
-
Unix timestamp in milliseconds when span ended
|
|
241368
|
-
|
|
241369
|
-
${source_default.cyan("duration")} ${source_default.dim("(number)")}
|
|
241370
|
-
Duration in milliseconds (endTime - startTime)
|
|
241371
|
-
|
|
241372
|
-
${source_default.cyan("attributes")} ${source_default.dim("(object)")}
|
|
241373
|
-
Key-value pairs of event attributes (validated against canvas schema)
|
|
241374
|
-
|
|
241375
|
-
${source_default.cyan("status")} ${source_default.dim("(object)")}
|
|
241376
|
-
Status code (OK, ERROR, UNSET) and optional message
|
|
241377
|
-
|
|
241378
|
-
${source_default.cyan("events")} ${source_default.dim("(array)")}
|
|
241379
|
-
Optional array of timestamped events within the span
|
|
241405
|
+
${source_default.bold("Attribute Value Format:")}
|
|
241406
|
+
{ "stringValue": "..." } ${source_default.dim("// For strings")}
|
|
241407
|
+
{ "intValue": 42 } ${source_default.dim("// For integers")}
|
|
241408
|
+
{ "doubleValue": 3.14 } ${source_default.dim("// For floats")}
|
|
241409
|
+
{ "boolValue": true } ${source_default.dim("// For booleans")}
|
|
241380
241410
|
|
|
241381
241411
|
${source_default.bold("Generation:")}
|
|
241382
|
-
|
|
241383
|
-
|
|
241412
|
+
Use OpenTelemetry SDK with OTLP JSON exporter
|
|
241413
|
+
Example: @opentelemetry/sdk-trace-node + InMemorySpanExporter
|
|
241414
|
+
See: tests/otel-setup.ts in the add-skill repository
|
|
241384
241415
|
|
|
241385
241416
|
${source_default.bold("Validation:")}
|
|
241386
241417
|
${source_default.cyan("npx @principal-ai/principal-view-cli validate-execution <file>")}
|
|
241418
|
+
|
|
241419
|
+
${source_default.bold("Resources:")}
|
|
241420
|
+
OTLP Spec: https://opentelemetry.io/docs/specs/otlp/
|
|
241421
|
+
OpenTelemetry JS: https://github.com/open-telemetry/opentelemetry-js
|
|
241387
241422
|
`,
|
|
241388
241423
|
examples: `
|
|
241389
241424
|
${source_default.bold.cyan("Complete File Examples")}
|