@principal-ai/principal-view-cli 0.4.0 → 0.4.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"formats.d.ts","sourceRoot":"","sources":["../../src/commands/formats.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAycpC,wBAAgB,oBAAoB,IAAI,OAAO,CA6B9C"}
1
+ {"version":3,"file":"formats.d.ts","sourceRoot":"","sources":["../../src/commands/formats.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAufpC,wBAAgB,oBAAoB,IAAI,OAAO,CA6B9C"}
@@ -48,13 +48,18 @@ ${chalk.dim('│')} ${chalk.yellow('"type"')}: "text",
48
48
  ${chalk.dim('│')} ${chalk.yellow('"text"')}: "# Event Name", ${chalk.dim('// Markdown description')} ${chalk.dim('│')}
49
49
  ${chalk.dim('│')} ${chalk.yellow('"x"')}: 0, ${chalk.yellow('"y"')}: 0, ${chalk.yellow('"width"')}: 200, ${chalk.yellow('"height"')}: 100, ${chalk.dim('│')}
50
50
  ${chalk.dim('│')} ${chalk.green('"pv"')}: { ${chalk.dim('│')}
51
- ${chalk.dim('│')} ${chalk.cyan('"otelEvent"')}: { ${chalk.dim('// OTEL event definition')} ${chalk.dim('│')}
52
- ${chalk.dim('│')} ${chalk.yellow('"name"')}: "feature.event.name", ${chalk.dim('│')}
53
- ${chalk.dim('│')} ${chalk.cyan('"attributes"')}: { ${chalk.dim('// Required & optional attrs')} ${chalk.dim('│')}
54
- ${chalk.dim('│')} ${chalk.green('"required"')}: ["attr.name", ...], ${chalk.dim('│')}
55
- ${chalk.dim('│')} ${chalk.green('"optional"')}: ["attr.name", ...] ${chalk.dim('│')}
56
- ${chalk.dim('│')} } ${chalk.dim('│')}
57
- ${chalk.dim('│')} } ${chalk.dim('│')}
51
+ ${chalk.dim('│')} ${chalk.cyan('"event"')}: "feature.event.name", ${chalk.dim('// Event name')} ${chalk.dim('│')}
52
+ ${chalk.dim('│')} ${chalk.cyan('"sources"')}: ["src/file.ts"], ${chalk.dim('// Source files')} ${chalk.dim('│')}
53
+ ${chalk.dim('│')} ${chalk.cyan('"otel"')}: { ${chalk.dim('// OTEL metadata')} ${chalk.dim('│')}
54
+ ${chalk.dim('│')} ${chalk.yellow('"kind"')}: "event", ${chalk.dim('│')}
55
+ ${chalk.dim('│')} ${chalk.yellow('"category"')}: "lifecycle" ${chalk.dim('│')}
56
+ ${chalk.dim('│')} }, ${chalk.dim('│')}
57
+ ${chalk.dim('│')} ${chalk.cyan('"dataSchema"')}: { ${chalk.dim('// Attribute definitions')} ${chalk.dim('│')}
58
+ ${chalk.dim('│')} ${chalk.yellow('"attr.name"')}: { ${chalk.dim('│')}
59
+ ${chalk.dim('│')} ${chalk.green('"type"')}: "string", ${chalk.dim('│')}
60
+ ${chalk.dim('│')} ${chalk.green('"required"')}: true ${chalk.dim('│')}
61
+ ${chalk.dim('│')} } ${chalk.dim('│')}
62
+ ${chalk.dim('│')} } ${chalk.dim('│')}
58
63
  ${chalk.dim('│')} } ${chalk.dim('│')}
59
64
  ${chalk.dim('│')} } ${chalk.dim('│')}
60
65
  ${chalk.dim('│')} ], ${chalk.dim('│')}
@@ -125,11 +130,10 @@ ${chalk.dim('│')} {
125
130
  ${chalk.dim('│')} ${chalk.yellow('"priority"')}: 1, ${chalk.dim('// Lower = higher priority')} ${chalk.dim('│')}
126
131
  ${chalk.dim('│')} ${chalk.yellow('"condition"')}: "...", ${chalk.dim('// JSONPath/logic expression')} ${chalk.dim('│')}
127
132
  ${chalk.dim('│')} ${chalk.yellow('"template"')}: { ${chalk.dim('// Narrative template')} ${chalk.dim('│')}
128
- ${chalk.dim('│')} ${chalk.cyan('"summary"')}: "...", ${chalk.dim('// One-line summary')} ${chalk.dim('│')}
129
- ${chalk.dim('│')} ${chalk.cyan('"details"')}: [ ${chalk.dim('// Step-by-step details')} ${chalk.dim('│')}
130
- ${chalk.dim('│')} "Step 1: ...", ${chalk.dim('│')}
131
- ${chalk.dim('│')} "Step 2: ...", ${chalk.dim('│')}
132
- ${chalk.dim('│')} ] ${chalk.dim('│')}
133
+ ${chalk.dim('│')} ${chalk.cyan('"summary"')}: "Completed {{count}} items", ${chalk.dim('// Handlebars template')} ${chalk.dim('│')}
134
+ ${chalk.dim('│')} ${chalk.cyan('"events"')}: { ${chalk.dim('// Per-event templates')} ${chalk.dim('│')}
135
+ ${chalk.dim('│')} "event.name": "Event {{attribute}} occurred" ${chalk.dim('│')}
136
+ ${chalk.dim('│')} } ${chalk.dim('│')}
133
137
  ${chalk.dim('│')} } ${chalk.dim('│')}
134
138
  ${chalk.dim('│')} } ${chalk.dim('│')}
135
139
  ${chalk.dim('│')} ] ${chalk.dim('│')}
@@ -161,12 +165,26 @@ ${chalk.cyan('2. Standard scenario set:')}
161
165
  - ${chalk.yellow('Failure')} (priority 2): Feature encountered error
162
166
  - ${chalk.dim('Fallback')} (priority 999): Generic execution captured
163
167
 
164
- ${chalk.cyan('3. Template interpolation:')}
165
- Use {{path.to.value}} to reference event attributes
166
- Examples:
167
- - {{record.count}}
168
- - {{error.message}}
169
- - {{result.invalidCount}}
168
+ ${chalk.cyan('3. Template syntax (Handlebars):')}
169
+ Templates use Handlebars syntax for dynamic content:
170
+
171
+ ${chalk.bold('Variables:')}
172
+ - {{variable}} Simple variable
173
+ - {{result.count}} Nested property
174
+ - {{error.message}} Deeply nested
175
+
176
+ ${chalk.bold('Conditionals:')}
177
+ - {{#if condition}}...{{/if}} If block
178
+ - {{#if condition}}...{{else}}...{{/if}} If-else
179
+ - {{#if (eq status "ok")}}✅{{else}}❌{{/if}} Comparison
180
+
181
+ ${chalk.bold('Loops:')}
182
+ - {{#each items}}{{this}}{{/each}} Iterate array
183
+ - {{#each items}}{{@index}}: {{this}}{{/each}} With index
184
+
185
+ ${chalk.bold('Comparison helpers:')}
186
+ - eq, ne, lt, gt, lte, gte, and, or, not
187
+ - Example: {{#if (gt count 10)}}Many{{/if}}
170
188
 
171
189
  ${chalk.cyan('4. Template style:')}
172
190
  - Clear, concise summary line
@@ -292,11 +310,20 @@ ${chalk.yellow('.principal-views/data-validator.otel.canvas')}
292
310
  "text": "# validation.started\\n\\nEmitted when validation begins",
293
311
  "x": 0, "y": 0, "width": 200, "height": 100,
294
312
  "pv": {
295
- "otelEvent": {
296
- "name": "validation.started",
297
- "attributes": {
298
- "required": ["input.recordCount"],
299
- "optional": ["input.source"]
313
+ "event": "validation.started",
314
+ "sources": ["src/validator.ts"],
315
+ "otel": {
316
+ "kind": "event",
317
+ "category": "lifecycle"
318
+ },
319
+ "dataSchema": {
320
+ "input.recordCount": {
321
+ "type": "number",
322
+ "required": true
323
+ },
324
+ "input.source": {
325
+ "type": "string",
326
+ "required": false
300
327
  }
301
328
  }
302
329
  }
@@ -307,11 +334,24 @@ ${chalk.yellow('.principal-views/data-validator.otel.canvas')}
307
334
  "text": "# validation.complete\\n\\nEmitted when validation succeeds",
308
335
  "x": 250, "y": 0, "width": 200, "height": 100,
309
336
  "pv": {
310
- "otelEvent": {
311
- "name": "validation.complete",
312
- "attributes": {
313
- "required": ["result.validCount", "result.invalidCount"],
314
- "optional": ["duration.ms"]
337
+ "event": "validation.complete",
338
+ "sources": ["src/validator.ts"],
339
+ "otel": {
340
+ "kind": "event",
341
+ "category": "lifecycle"
342
+ },
343
+ "dataSchema": {
344
+ "result.validCount": {
345
+ "type": "number",
346
+ "required": true
347
+ },
348
+ "result.invalidCount": {
349
+ "type": "number",
350
+ "required": true
351
+ },
352
+ "duration.ms": {
353
+ "type": "number",
354
+ "required": false
315
355
  }
316
356
  }
317
357
  }
@@ -322,11 +362,24 @@ ${chalk.yellow('.principal-views/data-validator.otel.canvas')}
322
362
  "text": "# validation.error\\n\\nEmitted when validation fails",
323
363
  "x": 500, "y": 0, "width": 200, "height": 100,
324
364
  "pv": {
325
- "otelEvent": {
326
- "name": "validation.error",
327
- "attributes": {
328
- "required": ["error.type", "error.message"],
329
- "optional": ["error.stage"]
365
+ "event": "validation.error",
366
+ "sources": ["src/validator.ts"],
367
+ "otel": {
368
+ "kind": "event",
369
+ "category": "error"
370
+ },
371
+ "dataSchema": {
372
+ "error.type": {
373
+ "type": "string",
374
+ "required": true
375
+ },
376
+ "error.message": {
377
+ "type": "string",
378
+ "required": true
379
+ },
380
+ "error.stage": {
381
+ "type": "string",
382
+ "required": false
330
383
  }
331
384
  }
332
385
  }
@@ -351,36 +404,29 @@ ${chalk.yellow('.principal-views/data-validator.narrative.json')}
351
404
  "priority": 1,
352
405
  "condition": "events[?name=='validation.complete']",
353
406
  "template": {
354
- "summary": "Validated {{result.validCount}} records successfully",
355
- "details": [
356
- "🔍 Started validation",
357
- "📊 Processed {{input.recordCount}} records",
358
- "✅ {{result.validCount}} valid",
359
- "❌ {{result.invalidCount}} invalid"
360
- ]
407
+ "summary": "Validated {{result.validCount}} records successfully",
408
+ "events": {
409
+ "validation.started": "Started validation of {{input.recordCount}} records",
410
+ "validation.complete": "Processed {{result.validCount}} valid and {{result.invalidCount}} invalid records"
411
+ }
361
412
  }
362
413
  },
363
414
  {
364
415
  "priority": 2,
365
416
  "condition": "events[?name=='validation.error']",
366
417
  "template": {
367
- "summary": "Validation failed: {{error.message}}",
368
- "details": [
369
- "🔍 Started validation",
370
- "💥 Error occurred: {{error.message}}",
371
- "🏷️ Error type: {{error.type}}"
372
- ]
418
+ "summary": "Validation failed: {{error.message}}",
419
+ "events": {
420
+ "validation.started": "Started validation",
421
+ "validation.error": "Error occurred: {{error.message}} (type: {{error.type}})"
422
+ }
373
423
  }
374
424
  },
375
425
  {
376
426
  "priority": 999,
377
427
  "condition": "true",
378
428
  "template": {
379
- "summary": "📋 Validation execution captured",
380
- "details": [
381
- "📦 Captured {{spans.length}} events",
382
- "⏱️ Duration: {{duration.ms}}ms"
383
- ]
429
+ "summary": "Validation execution captured ({{spans.length}} events, {{duration.ms}}ms)"
384
430
  }
385
431
  }
386
432
  ]
package/dist/index.cjs CHANGED
@@ -241190,19 +241190,6 @@ function getNestedValue(obj, path4) {
241190
241190
  }
241191
241191
  return current;
241192
241192
  }
241193
- function setNestedValue(obj, path4, value) {
241194
- const keys = path4.split(".");
241195
- let current = obj;
241196
- for (let i = 0; i < keys.length - 1; i++) {
241197
- const key = keys[i];
241198
- if (current[key] === void 0 || typeof current[key] !== "object") {
241199
- current[key] = {};
241200
- }
241201
- current = current[key];
241202
- }
241203
- const lastKey = keys[keys.length - 1];
241204
- current[lastKey] = value;
241205
- }
241206
241193
  function computeAggregates(events) {
241207
241194
  const aggregates = {
241208
241195
  // Event counts
@@ -241216,15 +241203,12 @@ function computeAggregates(events) {
241216
241203
  "warnLogs.count": events.filter((e) => e.type === "log" && (e.severityNumber ?? 0) >= 13 && (e.severityNumber ?? 0) <= 16).length,
241217
241204
  "debugLogs.count": events.filter((e) => e.type === "log" && (e.severityNumber ?? 0) >= 5 && (e.severityNumber ?? 0) <= 8).length
241218
241205
  };
241219
- for (const event of events) {
241206
+ const summaryEventPatterns = [".complete", ".summary", ".error", ".started"];
241207
+ const summaryEvents = events.filter((e) => summaryEventPatterns.some((pattern) => e.name.endsWith(pattern)));
241208
+ for (const event of summaryEvents) {
241220
241209
  if (event.attributes) {
241221
241210
  for (const [key, value] of Object.entries(event.attributes)) {
241222
- if (getNestedValue(aggregates, key) === void 0) {
241223
- setNestedValue(aggregates, key, value);
241224
- if (key.includes(".")) {
241225
- aggregates[key] = value;
241226
- }
241227
- }
241211
+ aggregates[key] = value;
241228
241212
  }
241229
241213
  }
241230
241214
  }
@@ -241334,7 +241318,25 @@ function renderSpanTree(tree, scenario, context, formatting2) {
241334
241318
  const parts = [];
241335
241319
  for (const node of tree) {
241336
241320
  const indent = (formatting2.indentPerLevel || " ").repeat(node.depth);
241337
- const eventContext = { ...context, ...node.span.attributes, span: node.span };
241321
+ const eventContext = { ...context };
241322
+ if (node.span.attributes) {
241323
+ for (const [key, value] of Object.entries(node.span.attributes)) {
241324
+ if (key.includes(".")) {
241325
+ const parts2 = key.split(".");
241326
+ let current = eventContext;
241327
+ for (let i = 0; i < parts2.length - 1; i++) {
241328
+ if (!current[parts2[i]] || typeof current[parts2[i]] !== "object") {
241329
+ current[parts2[i]] = {};
241330
+ }
241331
+ current = current[parts2[i]];
241332
+ }
241333
+ current[parts2[parts2.length - 1]] = value;
241334
+ } else {
241335
+ eventContext[key] = value;
241336
+ }
241337
+ }
241338
+ }
241339
+ eventContext.span = node.span;
241338
241340
  if (scenario.template.span) {
241339
241341
  const spanText = parseTemplate(scenario.template.span, eventContext);
241340
241342
  parts.push(indent + spanText);
@@ -241368,7 +241370,24 @@ function renderTimeline(events, scenario, context, formatting2) {
241368
241370
  return aTime - bTime;
241369
241371
  });
241370
241372
  for (const event of sorted) {
241371
- const eventContext = { ...context, ...event.attributes };
241373
+ const eventContext = { ...context };
241374
+ if (event.attributes) {
241375
+ for (const [key, value] of Object.entries(event.attributes)) {
241376
+ if (key.includes(".")) {
241377
+ const parts2 = key.split(".");
241378
+ let current = eventContext;
241379
+ for (let i = 0; i < parts2.length - 1; i++) {
241380
+ if (!current[parts2[i]] || typeof current[parts2[i]] !== "object") {
241381
+ current[parts2[i]] = {};
241382
+ }
241383
+ current = current[parts2[i]];
241384
+ }
241385
+ current[parts2[parts2.length - 1]] = value;
241386
+ } else {
241387
+ eventContext[key] = value;
241388
+ }
241389
+ }
241390
+ }
241372
241391
  let eventText;
241373
241392
  if (event.type === "log") {
241374
241393
  eventText = renderLog(event, scenario, { ...eventContext, log: event }, formatting2);
@@ -241688,8 +241707,8 @@ var NarrativeValidator = class {
241688
241707
  }
241689
241708
  const canvasEvents = /* @__PURE__ */ new Set();
241690
241709
  for (const node of canvas.nodes) {
241691
- if (node.pv?.event?.name) {
241692
- canvasEvents.add(node.pv.event.name);
241710
+ if (node.pv?.event && typeof node.pv.event === "string") {
241711
+ canvasEvents.add(node.pv.event);
241693
241712
  }
241694
241713
  }
241695
241714
  const narrativeEvents = /* @__PURE__ */ new Set();
@@ -241703,7 +241722,9 @@ var NarrativeValidator = class {
241703
241722
  }
241704
241723
  if (scenario.template?.events) {
241705
241724
  for (const eventName of Object.keys(scenario.template.events)) {
241706
- narrativeEvents.add(eventName);
241725
+ if (!eventName.includes("*")) {
241726
+ narrativeEvents.add(eventName);
241727
+ }
241707
241728
  }
241708
241729
  }
241709
241730
  }
@@ -242119,7 +242140,7 @@ var NarrativeValidator = class {
242119
242140
  path: path4,
242120
242141
  message: `Incomplete conditional expression: ${expr}`,
242121
242142
  impact: "Template will fail to render",
242122
- suggestion: 'Conditional format: {condition ? "true" : "false"}',
242143
+ suggestion: "Use Handlebars syntax: {{#if condition}}true{{else}}false{{/if}}",
242123
242144
  fixable: false
242124
242145
  });
242125
242146
  }
@@ -247618,13 +247639,18 @@ ${source_default.dim("\u2502")} ${source_default.yellow('"type"')}: "text"
247618
247639
  ${source_default.dim("\u2502")} ${source_default.yellow('"text"')}: "# Event Name", ${source_default.dim("// Markdown description")} ${source_default.dim("\u2502")}
247619
247640
  ${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")}
247620
247641
  ${source_default.dim("\u2502")} ${source_default.green('"pv"')}: { ${source_default.dim("\u2502")}
247621
- ${source_default.dim("\u2502")} ${source_default.cyan('"otelEvent"')}: { ${source_default.dim("// OTEL event definition")} ${source_default.dim("\u2502")}
247622
- ${source_default.dim("\u2502")} ${source_default.yellow('"name"')}: "feature.event.name", ${source_default.dim("\u2502")}
247623
- ${source_default.dim("\u2502")} ${source_default.cyan('"attributes"')}: { ${source_default.dim("// Required & optional attrs")} ${source_default.dim("\u2502")}
247624
- ${source_default.dim("\u2502")} ${source_default.green('"required"')}: ["attr.name", ...], ${source_default.dim("\u2502")}
247625
- ${source_default.dim("\u2502")} ${source_default.green('"optional"')}: ["attr.name", ...] ${source_default.dim("\u2502")}
247626
- ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
247627
- ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
247642
+ ${source_default.dim("\u2502")} ${source_default.cyan('"event"')}: "feature.event.name", ${source_default.dim("// Event name")} ${source_default.dim("\u2502")}
247643
+ ${source_default.dim("\u2502")} ${source_default.cyan('"sources"')}: ["src/file.ts"], ${source_default.dim("// Source files")} ${source_default.dim("\u2502")}
247644
+ ${source_default.dim("\u2502")} ${source_default.cyan('"otel"')}: { ${source_default.dim("// OTEL metadata")} ${source_default.dim("\u2502")}
247645
+ ${source_default.dim("\u2502")} ${source_default.yellow('"kind"')}: "event", ${source_default.dim("\u2502")}
247646
+ ${source_default.dim("\u2502")} ${source_default.yellow('"category"')}: "lifecycle" ${source_default.dim("\u2502")}
247647
+ ${source_default.dim("\u2502")} }, ${source_default.dim("\u2502")}
247648
+ ${source_default.dim("\u2502")} ${source_default.cyan('"dataSchema"')}: { ${source_default.dim("// Attribute definitions")} ${source_default.dim("\u2502")}
247649
+ ${source_default.dim("\u2502")} ${source_default.yellow('"attr.name"')}: { ${source_default.dim("\u2502")}
247650
+ ${source_default.dim("\u2502")} ${source_default.green('"type"')}: "string", ${source_default.dim("\u2502")}
247651
+ ${source_default.dim("\u2502")} ${source_default.green('"required"')}: true ${source_default.dim("\u2502")}
247652
+ ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
247653
+ ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
247628
247654
  ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
247629
247655
  ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
247630
247656
  ${source_default.dim("\u2502")} ], ${source_default.dim("\u2502")}
@@ -247695,11 +247721,10 @@ ${source_default.dim("\u2502")} {
247695
247721
  ${source_default.dim("\u2502")} ${source_default.yellow('"priority"')}: 1, ${source_default.dim("// Lower = higher priority")} ${source_default.dim("\u2502")}
247696
247722
  ${source_default.dim("\u2502")} ${source_default.yellow('"condition"')}: "...", ${source_default.dim("// JSONPath/logic expression")} ${source_default.dim("\u2502")}
247697
247723
  ${source_default.dim("\u2502")} ${source_default.yellow('"template"')}: { ${source_default.dim("// Narrative template")} ${source_default.dim("\u2502")}
247698
- ${source_default.dim("\u2502")} ${source_default.cyan('"summary"')}: "...", ${source_default.dim("// One-line summary")} ${source_default.dim("\u2502")}
247699
- ${source_default.dim("\u2502")} ${source_default.cyan('"details"')}: [ ${source_default.dim("// Step-by-step details")} ${source_default.dim("\u2502")}
247700
- ${source_default.dim("\u2502")} "Step 1: ...", ${source_default.dim("\u2502")}
247701
- ${source_default.dim("\u2502")} "Step 2: ...", ${source_default.dim("\u2502")}
247702
- ${source_default.dim("\u2502")} ] ${source_default.dim("\u2502")}
247724
+ ${source_default.dim("\u2502")} ${source_default.cyan('"summary"')}: "Completed {{count}} items", ${source_default.dim("// Handlebars template")} ${source_default.dim("\u2502")}
247725
+ ${source_default.dim("\u2502")} ${source_default.cyan('"events"')}: { ${source_default.dim("// Per-event templates")} ${source_default.dim("\u2502")}
247726
+ ${source_default.dim("\u2502")} "event.name": "Event {{attribute}} occurred" ${source_default.dim("\u2502")}
247727
+ ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
247703
247728
  ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
247704
247729
  ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
247705
247730
  ${source_default.dim("\u2502")} ] ${source_default.dim("\u2502")}
@@ -247731,12 +247756,26 @@ ${source_default.cyan("2. Standard scenario set:")}
247731
247756
  - ${source_default.yellow("Failure")} (priority 2): Feature encountered error
247732
247757
  - ${source_default.dim("Fallback")} (priority 999): Generic execution captured
247733
247758
 
247734
- ${source_default.cyan("3. Template interpolation:")}
247735
- Use {{path.to.value}} to reference event attributes
247736
- Examples:
247737
- - {{record.count}}
247738
- - {{error.message}}
247739
- - {{result.invalidCount}}
247759
+ ${source_default.cyan("3. Template syntax (Handlebars):")}
247760
+ Templates use Handlebars syntax for dynamic content:
247761
+
247762
+ ${source_default.bold("Variables:")}
247763
+ - {{variable}} Simple variable
247764
+ - {{result.count}} Nested property
247765
+ - {{error.message}} Deeply nested
247766
+
247767
+ ${source_default.bold("Conditionals:")}
247768
+ - {{#if condition}}...{{/if}} If block
247769
+ - {{#if condition}}...{{else}}...{{/if}} If-else
247770
+ - {{#if (eq status "ok")}}\u2705{{else}}\u274C{{/if}} Comparison
247771
+
247772
+ ${source_default.bold("Loops:")}
247773
+ - {{#each items}}{{this}}{{/each}} Iterate array
247774
+ - {{#each items}}{{@index}}: {{this}}{{/each}} With index
247775
+
247776
+ ${source_default.bold("Comparison helpers:")}
247777
+ - eq, ne, lt, gt, lte, gte, and, or, not
247778
+ - Example: {{#if (gt count 10)}}Many{{/if}}
247740
247779
 
247741
247780
  ${source_default.cyan("4. Template style:")}
247742
247781
  - Clear, concise summary line
@@ -247862,11 +247901,20 @@ ${source_default.yellow(".principal-views/data-validator.otel.canvas")}
247862
247901
  "text": "# validation.started\\n\\nEmitted when validation begins",
247863
247902
  "x": 0, "y": 0, "width": 200, "height": 100,
247864
247903
  "pv": {
247865
- "otelEvent": {
247866
- "name": "validation.started",
247867
- "attributes": {
247868
- "required": ["input.recordCount"],
247869
- "optional": ["input.source"]
247904
+ "event": "validation.started",
247905
+ "sources": ["src/validator.ts"],
247906
+ "otel": {
247907
+ "kind": "event",
247908
+ "category": "lifecycle"
247909
+ },
247910
+ "dataSchema": {
247911
+ "input.recordCount": {
247912
+ "type": "number",
247913
+ "required": true
247914
+ },
247915
+ "input.source": {
247916
+ "type": "string",
247917
+ "required": false
247870
247918
  }
247871
247919
  }
247872
247920
  }
@@ -247877,11 +247925,24 @@ ${source_default.yellow(".principal-views/data-validator.otel.canvas")}
247877
247925
  "text": "# validation.complete\\n\\nEmitted when validation succeeds",
247878
247926
  "x": 250, "y": 0, "width": 200, "height": 100,
247879
247927
  "pv": {
247880
- "otelEvent": {
247881
- "name": "validation.complete",
247882
- "attributes": {
247883
- "required": ["result.validCount", "result.invalidCount"],
247884
- "optional": ["duration.ms"]
247928
+ "event": "validation.complete",
247929
+ "sources": ["src/validator.ts"],
247930
+ "otel": {
247931
+ "kind": "event",
247932
+ "category": "lifecycle"
247933
+ },
247934
+ "dataSchema": {
247935
+ "result.validCount": {
247936
+ "type": "number",
247937
+ "required": true
247938
+ },
247939
+ "result.invalidCount": {
247940
+ "type": "number",
247941
+ "required": true
247942
+ },
247943
+ "duration.ms": {
247944
+ "type": "number",
247945
+ "required": false
247885
247946
  }
247886
247947
  }
247887
247948
  }
@@ -247892,11 +247953,24 @@ ${source_default.yellow(".principal-views/data-validator.otel.canvas")}
247892
247953
  "text": "# validation.error\\n\\nEmitted when validation fails",
247893
247954
  "x": 500, "y": 0, "width": 200, "height": 100,
247894
247955
  "pv": {
247895
- "otelEvent": {
247896
- "name": "validation.error",
247897
- "attributes": {
247898
- "required": ["error.type", "error.message"],
247899
- "optional": ["error.stage"]
247956
+ "event": "validation.error",
247957
+ "sources": ["src/validator.ts"],
247958
+ "otel": {
247959
+ "kind": "event",
247960
+ "category": "error"
247961
+ },
247962
+ "dataSchema": {
247963
+ "error.type": {
247964
+ "type": "string",
247965
+ "required": true
247966
+ },
247967
+ "error.message": {
247968
+ "type": "string",
247969
+ "required": true
247970
+ },
247971
+ "error.stage": {
247972
+ "type": "string",
247973
+ "required": false
247900
247974
  }
247901
247975
  }
247902
247976
  }
@@ -247921,36 +247995,29 @@ ${source_default.yellow(".principal-views/data-validator.narrative.json")}
247921
247995
  "priority": 1,
247922
247996
  "condition": "events[?name=='validation.complete']",
247923
247997
  "template": {
247924
- "summary": "\u2705 Validated {{result.validCount}} records successfully",
247925
- "details": [
247926
- "\u{1F50D} Started validation",
247927
- "\u{1F4CA} Processed {{input.recordCount}} records",
247928
- "\u2705 {{result.validCount}} valid",
247929
- "\u274C {{result.invalidCount}} invalid"
247930
- ]
247998
+ "summary": "Validated {{result.validCount}} records successfully",
247999
+ "events": {
248000
+ "validation.started": "Started validation of {{input.recordCount}} records",
248001
+ "validation.complete": "Processed {{result.validCount}} valid and {{result.invalidCount}} invalid records"
248002
+ }
247931
248003
  }
247932
248004
  },
247933
248005
  {
247934
248006
  "priority": 2,
247935
248007
  "condition": "events[?name=='validation.error']",
247936
248008
  "template": {
247937
- "summary": "\u274C Validation failed: {{error.message}}",
247938
- "details": [
247939
- "\u{1F50D} Started validation",
247940
- "\u{1F4A5} Error occurred: {{error.message}}",
247941
- "\u{1F3F7}\uFE0F Error type: {{error.type}}"
247942
- ]
248009
+ "summary": "Validation failed: {{error.message}}",
248010
+ "events": {
248011
+ "validation.started": "Started validation",
248012
+ "validation.error": "Error occurred: {{error.message}} (type: {{error.type}})"
248013
+ }
247943
248014
  }
247944
248015
  },
247945
248016
  {
247946
248017
  "priority": 999,
247947
248018
  "condition": "true",
247948
248019
  "template": {
247949
- "summary": "\u{1F4CB} Validation execution captured",
247950
- "details": [
247951
- "\u{1F4E6} Captured {{spans.length}} events",
247952
- "\u23F1\uFE0F Duration: {{duration.ms}}ms"
247953
- ]
248020
+ "summary": "Validation execution captured ({{spans.length}} events, {{duration.ms}}ms)"
247954
248021
  }
247955
248022
  }
247956
248023
  ]