@principal-ai/principal-view-cli 0.2.1 → 0.2.3

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/index.cjs CHANGED
@@ -228747,7 +228747,7 @@ function hasOtelFeatures(canvas) {
228747
228747
  }
228748
228748
  return false;
228749
228749
  }
228750
- function validateCanvas(canvas, filePath, library) {
228750
+ function validateCanvas(canvas, filePath, library, repositoryPath) {
228751
228751
  const issues = [];
228752
228752
  if (!canvas || typeof canvas !== "object") {
228753
228753
  issues.push({ type: "error", message: "Canvas must be an object" });
@@ -229019,6 +229019,33 @@ function validateCanvas(canvas, filePath, library) {
229019
229019
  issues
229020
229020
  );
229021
229021
  }
229022
+ const hasOtelFeatures2 = nodePv.otel !== void 0 || nodePv.events !== void 0;
229023
+ if (hasOtelFeatures2) {
229024
+ if (!Array.isArray(nodePv.sources) || nodePv.sources.length === 0) {
229025
+ issues.push({
229026
+ type: "error",
229027
+ message: `Node "${nodeLabel}" has OTEL features but is missing required "pv.sources" field`,
229028
+ path: `${nodePath2}.pv.sources`,
229029
+ suggestion: 'Add at least one source file reference, e.g.: "sources": ["src/services/MyService.ts"]'
229030
+ });
229031
+ }
229032
+ }
229033
+ if (Array.isArray(nodePv.sources) && repositoryPath) {
229034
+ nodePv.sources.forEach((source, sourceIndex) => {
229035
+ if (typeof source === "string") {
229036
+ const cleanPath = source.replace(/\*/g, "");
229037
+ const fullPath = (0, import_node_path5.resolve)(repositoryPath, cleanPath);
229038
+ if (!(0, import_node_fs4.existsSync)(fullPath)) {
229039
+ issues.push({
229040
+ type: "error",
229041
+ message: `Node "${nodeLabel}" references non-existent source file: ${source}`,
229042
+ path: `${nodePath2}.pv.sources[${sourceIndex}]`,
229043
+ suggestion: `Verify the file path is correct relative to repository root: ${repositoryPath}`
229044
+ });
229045
+ }
229046
+ }
229047
+ });
229048
+ }
229022
229049
  if (Array.isArray(nodePv.actions)) {
229023
229050
  nodePv.actions.forEach((action, actionIndex) => {
229024
229051
  if (action && typeof action === "object") {
@@ -229230,7 +229257,7 @@ function validateCanvas(canvas, filePath, library) {
229230
229257
  }
229231
229258
  return issues;
229232
229259
  }
229233
- function validateFile(filePath, library) {
229260
+ function validateFile(filePath, library, repositoryPath) {
229234
229261
  const absolutePath = (0, import_node_path5.resolve)(filePath);
229235
229262
  const relativePath = (0, import_node_path5.relative)(process.cwd(), absolutePath);
229236
229263
  if (!(0, import_node_fs4.existsSync)(absolutePath)) {
@@ -229243,7 +229270,7 @@ function validateFile(filePath, library) {
229243
229270
  try {
229244
229271
  const content = (0, import_node_fs4.readFileSync)(absolutePath, "utf8");
229245
229272
  const canvas = JSON.parse(content);
229246
- const issues = validateCanvas(canvas, relativePath, library);
229273
+ const issues = validateCanvas(canvas, relativePath, library, repositoryPath);
229247
229274
  const hasErrors = issues.some((i) => i.type === "error");
229248
229275
  return {
229249
229276
  file: relativePath,
@@ -229264,7 +229291,10 @@ function createValidateCommand() {
229264
229291
  command.description("Validate .canvas configuration files").argument(
229265
229292
  "[files...]",
229266
229293
  "Files or glob patterns to validate (defaults to .principal-views/*.canvas)"
229267
- ).option("-q, --quiet", "Only output errors").option("--json", "Output results as JSON").action(async (files, options) => {
229294
+ ).option("-q, --quiet", "Only output errors").option("--json", "Output results as JSON").option(
229295
+ "-r, --repository <path>",
229296
+ "Repository root path for validating source file references (defaults to current directory)"
229297
+ ).action(async (files, options) => {
229268
229298
  try {
229269
229299
  const patterns = files.length > 0 ? files : [".principal-views/*.canvas"];
229270
229300
  const matchedFiles = await globby(patterns, {
@@ -229282,6 +229312,7 @@ function createValidateCommand() {
229282
229312
  }
229283
229313
  const principalViewsDir = (0, import_node_path5.resolve)(process.cwd(), ".principal-views");
229284
229314
  const library = loadLibrary(principalViewsDir);
229315
+ const repositoryPath = options.repository ? (0, import_node_path5.resolve)(options.repository) : process.cwd();
229285
229316
  let libraryResult = null;
229286
229317
  if (library && Object.keys(library.raw).length > 0) {
229287
229318
  const libraryIssues = validateLibrary(library);
@@ -229292,7 +229323,9 @@ function createValidateCommand() {
229292
229323
  issues: libraryIssues
229293
229324
  };
229294
229325
  }
229295
- const results = matchedFiles.map((f) => validateFile(f, library));
229326
+ const results = matchedFiles.map(
229327
+ (f) => validateFile(f, library, repositoryPath)
229328
+ );
229296
229329
  const allResults = libraryResult ? [libraryResult, ...results] : results;
229297
229330
  const validCount = allResults.filter((r) => r.isValid).length;
229298
229331
  const invalidCount = allResults.length - validCount;
@@ -241078,6 +241111,478 @@ function createSchemaCommand() {
241078
241111
  return command;
241079
241112
  }
241080
241113
 
241114
+ // src/commands/formats.ts
241115
+ var FORMAT_SECTIONS = {
241116
+ overview: `
241117
+ ${source_default.bold.cyan("Principal View OTEL File Formats")}
241118
+ ${source_default.dim("\u2550".repeat(70))}
241119
+
241120
+ The Principal View OTEL workflow uses three main file types:
241121
+
241122
+ ${source_default.bold("1. Canvas Files")} ${source_default.yellow(".otel.canvas")}
241123
+ Define OTEL event schemas and telemetry structure for a feature.
241124
+ These are the single source of truth for what events should be emitted.
241125
+
241126
+ ${source_default.bold("2. Narrative Files")} ${source_default.yellow(".narrative.json")}
241127
+ Define scenarios and templates for rendering executions as human-readable
241128
+ narratives based on the emitted events.
241129
+
241130
+ ${source_default.bold("3. Execution Files")} ${source_default.yellow(".otel.json")}
241131
+ Captured OTEL spans from test runs or production code, exported for
241132
+ visualization and validation against canvas schemas.
241133
+
241134
+ Run ${source_default.cyan("npx @principal-ai/principal-view-cli formats <section>")} for details on:
241135
+ ${source_default.yellow("canvas")} .otel.canvas format and event schemas
241136
+ ${source_default.yellow("narrative")} .narrative.json format and scenario structure
241137
+ ${source_default.yellow("execution")} .otel.json format for captured spans
241138
+ ${source_default.yellow("examples")} Complete example files
241139
+ `,
241140
+ canvas: `
241141
+ ${source_default.bold.cyan("Canvas Format (.otel.canvas)")}
241142
+ ${source_default.dim("\u2550".repeat(70))}
241143
+
241144
+ Canvas files define the OTEL event schemas for a feature. They document what
241145
+ events should be emitted and what attributes each event must/may contain.
241146
+
241147
+ ${source_default.bold("File Location:")}
241148
+ ${source_default.dim(".principal-views/")}${source_default.yellow("<feature-name>.otel.canvas")}
241149
+
241150
+ ${source_default.bold("Required Structure:")}
241151
+ ${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")}
241152
+ ${source_default.dim("\u2502")} { ${source_default.dim("\u2502")}
241153
+ ${source_default.dim("\u2502")} ${source_default.green('"nodes"')}: [ ${source_default.dim("// Array of event schemas")} ${source_default.dim("\u2502")}
241154
+ ${source_default.dim("\u2502")} { ${source_default.dim("\u2502")}
241155
+ ${source_default.dim("\u2502")} ${source_default.yellow('"id"')}: "event-id", ${source_default.dim("// Unique identifier")} ${source_default.dim("\u2502")}
241156
+ ${source_default.dim("\u2502")} ${source_default.yellow('"type"')}: "text", ${source_default.dim("\u2502")}
241157
+ ${source_default.dim("\u2502")} ${source_default.yellow('"text"')}: "# Event Name", ${source_default.dim("// Markdown description")} ${source_default.dim("\u2502")}
241158
+ ${source_default.dim("\u2502")} ${source_default.yellow('"x"')}: 0, ${source_default.yellow('"y"')}: 0, ${source_default.yellow('"width"')}: 200, ${source_default.yellow('"height"')}: 100, ${source_default.dim("\u2502")}
241159
+ ${source_default.dim("\u2502")} ${source_default.green('"pv"')}: { ${source_default.dim("\u2502")}
241160
+ ${source_default.dim("\u2502")} ${source_default.cyan('"otelEvent"')}: { ${source_default.dim("// OTEL event definition")} ${source_default.dim("\u2502")}
241161
+ ${source_default.dim("\u2502")} ${source_default.yellow('"name"')}: "feature.event.name", ${source_default.dim("\u2502")}
241162
+ ${source_default.dim("\u2502")} ${source_default.cyan('"attributes"')}: { ${source_default.dim("// Required & optional attrs")} ${source_default.dim("\u2502")}
241163
+ ${source_default.dim("\u2502")} ${source_default.green('"required"')}: ["attr.name", ...], ${source_default.dim("\u2502")}
241164
+ ${source_default.dim("\u2502")} ${source_default.green('"optional"')}: ["attr.name", ...] ${source_default.dim("\u2502")}
241165
+ ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
241166
+ ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
241167
+ ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
241168
+ ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
241169
+ ${source_default.dim("\u2502")} ], ${source_default.dim("\u2502")}
241170
+ ${source_default.dim("\u2502")} ${source_default.green('"edges"')}: [], ${source_default.dim("// Optional: event relationships")} ${source_default.dim("\u2502")}
241171
+ ${source_default.dim("\u2502")} ${source_default.green('"pv"')}: { ${source_default.dim("\u2502")}
241172
+ ${source_default.dim("\u2502")} ${source_default.yellow('"name"')}: "Feature Name", ${source_default.dim('// Feature name (NOT "...Canvas")')} ${source_default.dim("\u2502")}
241173
+ ${source_default.dim("\u2502")} ${source_default.yellow('"version"')}: "1.0.0" ${source_default.dim("\u2502")}
241174
+ ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
241175
+ ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
241176
+ ${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")}
241177
+
241178
+ ${source_default.bold("Event Schema Best Practices:")}
241179
+
241180
+ ${source_default.cyan("1. Canvas represents complete, encompassing functionality:")}
241181
+ \u2705 API route - Full request/response cycle
241182
+ \u2705 CLI command - Complete tool execution
241183
+ \u2705 Business operation - End-to-end workflow
241184
+ \u274C Individual helper functions (too granular)
241185
+
241186
+ ${source_default.cyan("2. Event naming convention:")}
241187
+ ${source_default.yellow("<feature>.<operation>.<state>")}
241188
+ Examples:
241189
+ - validation.started
241190
+ - validation.complete
241191
+ - validation.error
241192
+ - import.parsing.complete
241193
+
241194
+ ${source_default.cyan("3. Start simple (2-4 events):")}
241195
+ - ${source_default.green("started")} - When feature begins
241196
+ - ${source_default.green("complete")} - When feature succeeds
241197
+ - ${source_default.green("error")} - When feature fails
241198
+ - (optional) progress events for clear intermediate steps
241199
+
241200
+ ${source_default.cyan("4. Attribute naming conventions:")}
241201
+ ${source_default.yellow("<category>.<name>")}
241202
+ - input.* (input.size, input.recordCount)
241203
+ - output.* (output.count, output.success)
241204
+ - result.* (result.validCount, result.invalidCount)
241205
+ - error.* (error.type, error.message, error.stage)
241206
+ - duration.* (duration.ms)
241207
+
241208
+ ${source_default.cyan("5. Required vs Optional attributes:")}
241209
+ - ${source_default.green("required")}: Essential data needed for validation
241210
+ - ${source_default.yellow("optional")}: Nice-to-have context, won't fail validation if missing
241211
+
241212
+ ${source_default.bold("Validation:")}
241213
+ ${source_default.cyan("npx @principal-ai/principal-view-cli validate")}
241214
+ `,
241215
+ narrative: `
241216
+ ${source_default.bold.cyan("Narrative Format (.narrative.json)")}
241217
+ ${source_default.dim("\u2550".repeat(70))}
241218
+
241219
+ Narrative files define scenarios for rendering execution data as human-readable
241220
+ stories. They evaluate conditions against captured events to select the best
241221
+ matching narrative template.
241222
+
241223
+ ${source_default.bold("File Location:")}
241224
+ ${source_default.dim(".principal-views/")}${source_default.yellow("<feature-name>.narrative.json")}
241225
+ ${source_default.dim("(co-located with corresponding .otel.canvas file)")}
241226
+
241227
+ ${source_default.bold("Required Structure:")}
241228
+ ${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")}
241229
+ ${source_default.dim("\u2502")} { ${source_default.dim("\u2502")}
241230
+ ${source_default.dim("\u2502")} ${source_default.green('"name"')}: "Feature Name", ${source_default.dim('// NOT "Feature Name Narratives"')} ${source_default.dim("\u2502")}
241231
+ ${source_default.dim("\u2502")} ${source_default.green('"description"')}: "What the feature does", ${source_default.dim('// Purpose, not "Narratives for..."')} ${source_default.dim("\u2502")}
241232
+ ${source_default.dim("\u2502")} ${source_default.green('"scenarios"')}: [ ${source_default.dim("\u2502")}
241233
+ ${source_default.dim("\u2502")} { ${source_default.dim("\u2502")}
241234
+ ${source_default.dim("\u2502")} ${source_default.yellow('"priority"')}: 1, ${source_default.dim("// Lower = higher priority")} ${source_default.dim("\u2502")}
241235
+ ${source_default.dim("\u2502")} ${source_default.yellow('"condition"')}: "...", ${source_default.dim("// JSONPath/logic expression")} ${source_default.dim("\u2502")}
241236
+ ${source_default.dim("\u2502")} ${source_default.yellow('"template"')}: { ${source_default.dim("// Narrative template")} ${source_default.dim("\u2502")}
241237
+ ${source_default.dim("\u2502")} ${source_default.cyan('"summary"')}: "...", ${source_default.dim("// One-line summary")} ${source_default.dim("\u2502")}
241238
+ ${source_default.dim("\u2502")} ${source_default.cyan('"details"')}: [ ${source_default.dim("// Step-by-step details")} ${source_default.dim("\u2502")}
241239
+ ${source_default.dim("\u2502")} "Step 1: ...", ${source_default.dim("\u2502")}
241240
+ ${source_default.dim("\u2502")} "Step 2: ...", ${source_default.dim("\u2502")}
241241
+ ${source_default.dim("\u2502")} ] ${source_default.dim("\u2502")}
241242
+ ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
241243
+ ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
241244
+ ${source_default.dim("\u2502")} ] ${source_default.dim("\u2502")}
241245
+ ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
241246
+ ${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")}
241247
+
241248
+ ${source_default.bold("Naming Guidelines:")}
241249
+
241250
+ \u274C DON'T append "Narratives" to the name:
241251
+ "name": "Package Processor Narratives"
241252
+
241253
+ \u2705 DO use the feature name directly:
241254
+ "name": "Package Processor"
241255
+
241256
+ \u274C DON'T prefix description with boilerplate:
241257
+ "description": "Human-readable narratives for package extraction..."
241258
+
241259
+ \u2705 DO describe the feature's purpose:
241260
+ "description": "Package extraction and analysis from repository file trees"
241261
+
241262
+ ${source_default.bold("Scenario Best Practices:")}
241263
+
241264
+ ${source_default.cyan("1. Priority ordering (scenarios evaluated in order):")}
241265
+ - ${source_default.green("1-10")} Specific scenarios (success/failure cases)
241266
+ - ${source_default.yellow("999")} Fallback scenario (catches anything)
241267
+
241268
+ ${source_default.cyan("2. Standard scenario set:")}
241269
+ - ${source_default.green("Success")} (priority 1): Feature completed successfully
241270
+ - ${source_default.yellow("Failure")} (priority 2): Feature encountered error
241271
+ - ${source_default.dim("Fallback")} (priority 999): Generic execution captured
241272
+
241273
+ ${source_default.cyan("3. Template interpolation:")}
241274
+ Use {{path.to.value}} to reference event attributes
241275
+ Examples:
241276
+ - {{record.count}}
241277
+ - {{error.message}}
241278
+ - {{result.invalidCount}}
241279
+
241280
+ ${source_default.cyan("4. Template style:")}
241281
+ - Clear, concise summary line
241282
+ - 3-5 detail steps showing workflow
241283
+ - Use emojis for visual scanning (\u2705 \u274C \u{1F4CB})
241284
+ - Include key metrics and IDs
241285
+
241286
+ ${source_default.bold("Validation:")}
241287
+ ${source_default.cyan("npx @principal-ai/principal-view-cli narrative validate")}
241288
+ `,
241289
+ execution: `
241290
+ ${source_default.bold.cyan("Execution Format (.otel.json)")}
241291
+ ${source_default.dim("\u2550".repeat(70))}
241292
+
241293
+ Execution files contain captured OTEL spans from test runs or production code.
241294
+ These files are exported by your test infrastructure and used for visualization
241295
+ and validation against canvas schemas.
241296
+
241297
+ ${source_default.bold("File Location:")}
241298
+ ${source_default.yellow("__executions__/")}${source_default.dim("<feature-name>.otel.json")}
241299
+ ${source_default.dim("(auto-generated by test infrastructure)")}
241300
+
241301
+ ${source_default.bold("IMPORTANT:")} __executions__/ directory must be committed to git!
241302
+
241303
+ ${source_default.bold("File Structure:")}
241304
+ ${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
+ ${source_default.dim("\u2502")} { ${source_default.dim("\u2502")}
241306
+ ${source_default.dim("\u2502")} ${source_default.green('"exportedAt"')}: "2025-01-21T10:30:00.000Z", ${source_default.dim("// ISO timestamp")} ${source_default.dim("\u2502")}
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")}
241310
+ ${source_default.dim("\u2502")} { ${source_default.dim("\u2502")}
241311
+ ${source_default.dim("\u2502")} ${source_default.yellow('"traceId"')}: "4bf92f3577b34da6...", ${source_default.dim("// 32 hex chars")} ${source_default.dim("\u2502")}
241312
+ ${source_default.dim("\u2502")} ${source_default.yellow('"spanId"')}: "00f067aa0ba902b7", ${source_default.dim("// 16 hex chars")} ${source_default.dim("\u2502")}
241313
+ ${source_default.dim("\u2502")} ${source_default.yellow('"parentSpanId"')}: "abc123...", ${source_default.dim("// Parent span (null for root)")} ${source_default.dim("\u2502")}
241314
+ ${source_default.dim("\u2502")} ${source_default.yellow('"name"')}: "test:feature-name", ${source_default.dim("// Span name")} ${source_default.dim("\u2502")}
241315
+ ${source_default.dim("\u2502")} ${source_default.yellow('"kind"')}: "INTERNAL", ${source_default.dim("// Span kind")} ${source_default.dim("\u2502")}
241316
+ ${source_default.dim("\u2502")} ${source_default.yellow('"startTime"')}: 1703548800000, ${source_default.dim("// Unix ms")} ${source_default.dim("\u2502")}
241317
+ ${source_default.dim("\u2502")} ${source_default.yellow('"endTime"')}: 1703548800050, ${source_default.dim("// Unix ms")} ${source_default.dim("\u2502")}
241318
+ ${source_default.dim("\u2502")} ${source_default.yellow('"duration"')}: 50, ${source_default.dim("// Duration in ms")} ${source_default.dim("\u2502")}
241319
+ ${source_default.dim("\u2502")} ${source_default.yellow('"attributes"')}: { ${source_default.dim("// Event attributes")} ${source_default.dim("\u2502")}
241320
+ ${source_default.dim("\u2502")} "input.size": 42, ${source_default.dim("\u2502")}
241321
+ ${source_default.dim("\u2502")} "output.success": true ${source_default.dim("\u2502")}
241322
+ ${source_default.dim("\u2502")} }, ${source_default.dim("\u2502")}
241323
+ ${source_default.dim("\u2502")} ${source_default.yellow('"status"')}: { ${source_default.dim("\u2502")}
241324
+ ${source_default.dim("\u2502")} "code": "OK" ${source_default.dim("// OK, ERROR, UNSET")} ${source_default.dim("\u2502")}
241325
+ ${source_default.dim("\u2502")} }, ${source_default.dim("\u2502")}
241326
+ ${source_default.dim("\u2502")} ${source_default.yellow('"events"')}: [] ${source_default.dim("// Optional span events")} ${source_default.dim("\u2502")}
241327
+ ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
241328
+ ${source_default.dim("\u2502")} ] ${source_default.dim("\u2502")}
241329
+ ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
241330
+ ${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
+
241332
+ ${source_default.bold("Field Descriptions:")}
241333
+
241334
+ ${source_default.cyan("exportedAt")} ${source_default.dim("(string, required)")}
241335
+ ISO 8601 timestamp when the file was exported
241336
+
241337
+ ${source_default.cyan("serviceName")} ${source_default.dim("(string, required)")}
241338
+ Name of the service/test suite that generated these spans
241339
+
241340
+ ${source_default.cyan("spanCount")} ${source_default.dim("(number, required)")}
241341
+ Total number of spans in this execution
241342
+
241343
+ ${source_default.cyan("spans")} ${source_default.dim("(array, required)")}
241344
+ Array of span objects containing OTEL trace data
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
241353
+
241354
+ ${source_default.cyan("parentSpanId")} ${source_default.dim("(string | null)")}
241355
+ Parent span ID, or null for root span
241356
+
241357
+ ${source_default.cyan("name")} ${source_default.dim("(string)")}
241358
+ Descriptive name for the operation
241359
+
241360
+ ${source_default.cyan("kind")} ${source_default.dim("(string)")}
241361
+ Span kind: INTERNAL, CLIENT, SERVER, PRODUCER, CONSUMER
241362
+
241363
+ ${source_default.cyan("startTime")} ${source_default.dim("(number)")}
241364
+ Unix timestamp in milliseconds when span started
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
241380
+
241381
+ ${source_default.bold("Generation:")}
241382
+ Set up test infrastructure with OTEL exporters that write to __executions__/
241383
+ See: docs/guides/adding-opentelemetry-to-tests.md
241384
+
241385
+ ${source_default.bold("Validation:")}
241386
+ ${source_default.cyan("npx @principal-ai/principal-view-cli validate-execution <file>")}
241387
+ `,
241388
+ examples: `
241389
+ ${source_default.bold.cyan("Complete File Examples")}
241390
+ ${source_default.dim("\u2550".repeat(70))}
241391
+
241392
+ ${source_default.bold("Example 1: Data Validator Canvas")}
241393
+ ${source_default.dim("\u2500".repeat(70))}
241394
+ ${source_default.yellow(".principal-views/data-validator.otel.canvas")}
241395
+
241396
+ {
241397
+ "nodes": [
241398
+ {
241399
+ "id": "validation-started",
241400
+ "type": "text",
241401
+ "text": "# validation.started\\n\\nEmitted when validation begins",
241402
+ "x": 0, "y": 0, "width": 200, "height": 100,
241403
+ "pv": {
241404
+ "otelEvent": {
241405
+ "name": "validation.started",
241406
+ "attributes": {
241407
+ "required": ["input.recordCount"],
241408
+ "optional": ["input.source"]
241409
+ }
241410
+ }
241411
+ }
241412
+ },
241413
+ {
241414
+ "id": "validation-complete",
241415
+ "type": "text",
241416
+ "text": "# validation.complete\\n\\nEmitted when validation succeeds",
241417
+ "x": 250, "y": 0, "width": 200, "height": 100,
241418
+ "pv": {
241419
+ "otelEvent": {
241420
+ "name": "validation.complete",
241421
+ "attributes": {
241422
+ "required": ["result.validCount", "result.invalidCount"],
241423
+ "optional": ["duration.ms"]
241424
+ }
241425
+ }
241426
+ }
241427
+ },
241428
+ {
241429
+ "id": "validation-error",
241430
+ "type": "text",
241431
+ "text": "# validation.error\\n\\nEmitted when validation fails",
241432
+ "x": 500, "y": 0, "width": 200, "height": 100,
241433
+ "pv": {
241434
+ "otelEvent": {
241435
+ "name": "validation.error",
241436
+ "attributes": {
241437
+ "required": ["error.type", "error.message"],
241438
+ "optional": ["error.stage"]
241439
+ }
241440
+ }
241441
+ }
241442
+ }
241443
+ ],
241444
+ "edges": [],
241445
+ "pv": {
241446
+ "name": "Data Validator",
241447
+ "version": "1.0.0"
241448
+ }
241449
+ }
241450
+
241451
+ ${source_default.bold("Example 2: Narrative Scenarios")}
241452
+ ${source_default.dim("\u2500".repeat(70))}
241453
+ ${source_default.yellow(".principal-views/data-validator.narrative.json")}
241454
+
241455
+ {
241456
+ "name": "Data Validator",
241457
+ "description": "Validates data records against defined schemas",
241458
+ "scenarios": [
241459
+ {
241460
+ "priority": 1,
241461
+ "condition": "events[?name=='validation.complete']",
241462
+ "template": {
241463
+ "summary": "\u2705 Validated {{result.validCount}} records successfully",
241464
+ "details": [
241465
+ "\u{1F50D} Started validation",
241466
+ "\u{1F4CA} Processed {{input.recordCount}} records",
241467
+ "\u2705 {{result.validCount}} valid",
241468
+ "\u274C {{result.invalidCount}} invalid"
241469
+ ]
241470
+ }
241471
+ },
241472
+ {
241473
+ "priority": 2,
241474
+ "condition": "events[?name=='validation.error']",
241475
+ "template": {
241476
+ "summary": "\u274C Validation failed: {{error.message}}",
241477
+ "details": [
241478
+ "\u{1F50D} Started validation",
241479
+ "\u{1F4A5} Error occurred: {{error.message}}",
241480
+ "\u{1F3F7}\uFE0F Error type: {{error.type}}"
241481
+ ]
241482
+ }
241483
+ },
241484
+ {
241485
+ "priority": 999,
241486
+ "condition": "true",
241487
+ "template": {
241488
+ "summary": "\u{1F4CB} Validation execution captured",
241489
+ "details": [
241490
+ "\u{1F4E6} Captured {{spans.length}} events",
241491
+ "\u23F1\uFE0F Duration: {{duration.ms}}ms"
241492
+ ]
241493
+ }
241494
+ }
241495
+ ]
241496
+ }
241497
+
241498
+ ${source_default.bold("Example 3: Execution File")}
241499
+ ${source_default.dim("\u2500".repeat(70))}
241500
+ ${source_default.yellow("__executions__/data-validator.otel.json")}
241501
+
241502
+ {
241503
+ "exportedAt": "2025-01-21T10:30:45.123Z",
241504
+ "serviceName": "my-app-tests",
241505
+ "spanCount": 3,
241506
+ "spans": [
241507
+ {
241508
+ "traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
241509
+ "spanId": "00f067aa0ba902b7",
241510
+ "parentSpanId": null,
241511
+ "name": "test:data-validator",
241512
+ "kind": "INTERNAL",
241513
+ "startTime": 1703548800000,
241514
+ "endTime": 1703548800150,
241515
+ "duration": 150,
241516
+ "attributes": {
241517
+ "test.name": "data validator success case"
241518
+ },
241519
+ "status": { "code": "OK" },
241520
+ "events": []
241521
+ },
241522
+ {
241523
+ "traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
241524
+ "spanId": "abc123def4567890",
241525
+ "parentSpanId": "00f067aa0ba902b7",
241526
+ "name": "validation.started",
241527
+ "kind": "INTERNAL",
241528
+ "startTime": 1703548800010,
241529
+ "endTime": 1703548800015,
241530
+ "duration": 5,
241531
+ "attributes": {
241532
+ "input.recordCount": 100,
241533
+ "input.source": "test-data.csv"
241534
+ },
241535
+ "status": { "code": "OK" },
241536
+ "events": []
241537
+ },
241538
+ {
241539
+ "traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
241540
+ "spanId": "def789abc1234567",
241541
+ "parentSpanId": "00f067aa0ba902b7",
241542
+ "name": "validation.complete",
241543
+ "kind": "INTERNAL",
241544
+ "startTime": 1703548800140,
241545
+ "endTime": 1703548800145,
241546
+ "duration": 5,
241547
+ "attributes": {
241548
+ "result.validCount": 95,
241549
+ "result.invalidCount": 5,
241550
+ "duration.ms": 130
241551
+ },
241552
+ "status": { "code": "OK" },
241553
+ "events": []
241554
+ }
241555
+ ]
241556
+ }
241557
+
241558
+ ${source_default.bold("Next Steps:")}
241559
+ ${source_default.cyan("npx @principal-ai/principal-view-cli validate")} Validate canvas
241560
+ ${source_default.cyan("npx @principal-ai/principal-view-cli narrative validate")} Validate narratives
241561
+ ${source_default.cyan("npx @principal-ai/principal-view-cli validate-execution")} Validate execution
241562
+ `
241563
+ };
241564
+ function createFormatsCommand() {
241565
+ const command = new Command("formats");
241566
+ command.description("Display documentation about file formats").argument(
241567
+ "[section]",
241568
+ "Section to display: overview, canvas, narrative, execution, examples"
241569
+ ).action((section) => {
241570
+ const validSections = Object.keys(FORMAT_SECTIONS);
241571
+ if (!section) {
241572
+ console.log(FORMAT_SECTIONS.overview);
241573
+ return;
241574
+ }
241575
+ const normalizedSection = section.toLowerCase();
241576
+ if (!validSections.includes(normalizedSection)) {
241577
+ console.log(source_default.red(`Unknown section: ${section}`));
241578
+ console.log(`Valid sections: ${validSections.join(", ")}`);
241579
+ process.exit(1);
241580
+ }
241581
+ console.log(FORMAT_SECTIONS[normalizedSection]);
241582
+ });
241583
+ return command;
241584
+ }
241585
+
241081
241586
  // src/commands/doctor.ts
241082
241587
  var import_node_fs8 = require("node:fs");
241083
241588
  var import_node_path9 = require("node:path");
@@ -242886,7 +243391,7 @@ function createNarrativeCommand() {
242886
243391
  }
242887
243392
 
242888
243393
  // src/index.ts
242889
- var VERSION2 = "0.2.1";
243394
+ var VERSION2 = "0.2.3";
242890
243395
  var program2 = new Command();
242891
243396
  program2.name("privu").description("Principal View CLI - Validate and manage .canvas configuration files").version(VERSION2);
242892
243397
  program2.addCommand(createInitCommand());
@@ -242896,6 +243401,7 @@ program2.addCommand(createValidateExecutionCommand());
242896
243401
  program2.addCommand(createLintCommand());
242897
243402
  program2.addCommand(createListCommand());
242898
243403
  program2.addCommand(createSchemaCommand());
243404
+ program2.addCommand(createFormatsCommand());
242899
243405
  program2.addCommand(createDoctorCommand());
242900
243406
  program2.addCommand(createHooksCommand());
242901
243407
  program2.addCommand(createCoverageCommand());