@principal-ai/principal-view-cli 0.6.3 → 0.7.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.
Files changed (35) hide show
  1. package/dist/commands/formats.js +19 -19
  2. package/dist/commands/lint.js +44 -44
  3. package/dist/commands/workflow/index.d.ts +3 -0
  4. package/dist/commands/workflow/index.d.ts.map +1 -0
  5. package/dist/commands/{narrative → workflow}/index.js +3 -3
  6. package/dist/commands/workflow/inspect.d.ts.map +1 -0
  7. package/dist/commands/workflow/list.d.ts.map +1 -0
  8. package/dist/commands/{narrative → workflow}/list.js +32 -32
  9. package/dist/commands/workflow/render.d.ts.map +1 -0
  10. package/dist/commands/{narrative → workflow}/render.js +16 -16
  11. package/dist/commands/workflow/test.d.ts.map +1 -0
  12. package/dist/commands/{narrative → workflow}/test.js +8 -8
  13. package/dist/commands/{narrative → workflow}/utils.d.ts +4 -4
  14. package/dist/commands/workflow/utils.d.ts.map +1 -0
  15. package/dist/commands/{narrative → workflow}/utils.js +5 -5
  16. package/dist/commands/workflow/validate.d.ts.map +1 -0
  17. package/dist/commands/{narrative → workflow}/validate.js +21 -21
  18. package/dist/index.cjs +265 -265
  19. package/dist/index.cjs.map +3 -3
  20. package/dist/index.js +2 -2
  21. package/package.json +1 -1
  22. package/dist/commands/narrative/index.d.ts +0 -3
  23. package/dist/commands/narrative/index.d.ts.map +0 -1
  24. package/dist/commands/narrative/inspect.d.ts.map +0 -1
  25. package/dist/commands/narrative/list.d.ts.map +0 -1
  26. package/dist/commands/narrative/render.d.ts.map +0 -1
  27. package/dist/commands/narrative/test.d.ts.map +0 -1
  28. package/dist/commands/narrative/utils.d.ts.map +0 -1
  29. package/dist/commands/narrative/validate.d.ts.map +0 -1
  30. /package/dist/commands/{narrative → workflow}/inspect.d.ts +0 -0
  31. /package/dist/commands/{narrative → workflow}/inspect.js +0 -0
  32. /package/dist/commands/{narrative → workflow}/list.d.ts +0 -0
  33. /package/dist/commands/{narrative → workflow}/render.d.ts +0 -0
  34. /package/dist/commands/{narrative → workflow}/test.d.ts +0 -0
  35. /package/dist/commands/{narrative → workflow}/validate.d.ts +0 -0
@@ -14,9 +14,9 @@ ${chalk.bold('1. Canvas Files')} ${chalk.yellow('.otel.canvas')}
14
14
  Define OTEL event schemas and telemetry structure for a feature.
15
15
  These are the single source of truth for what events should be emitted.
16
16
 
17
- ${chalk.bold('2. Narrative Files')} ${chalk.yellow('.narrative.json')}
17
+ ${chalk.bold('2. Workflow Files')} ${chalk.yellow('.workflow.json')}
18
18
  Define scenarios and templates for rendering executions as human-readable
19
- narratives based on the emitted events.
19
+ workflows based on the emitted events.
20
20
 
21
21
  ${chalk.bold('3. Execution Files')} ${chalk.yellow('.otel.json')}
22
22
  Captured OTEL spans from test runs or production code, exported for
@@ -24,7 +24,7 @@ ${chalk.bold('3. Execution Files')} ${chalk.yellow('.otel.json')}
24
24
 
25
25
  Run ${chalk.cyan('npx @principal-ai/principal-view-cli formats <section>')} for details on:
26
26
  ${chalk.yellow('canvas')} .otel.canvas format and event schemas
27
- ${chalk.yellow('narrative')} .narrative.json format and scenario structure
27
+ ${chalk.yellow('workflow')} .workflow.json format and scenario structure
28
28
  ${chalk.yellow('execution')} .otel.json format for captured spans
29
29
  ${chalk.yellow('examples')} Complete example files
30
30
  `,
@@ -108,28 +108,28 @@ ${chalk.cyan('5. Required vs Optional attributes:')}
108
108
  ${chalk.bold('Validation:')}
109
109
  ${chalk.cyan('npx @principal-ai/principal-view-cli validate')}
110
110
  `,
111
- narrative: `
112
- ${chalk.bold.cyan('Narrative Format (.narrative.json)')}
111
+ workflow: `
112
+ ${chalk.bold.cyan('Workflow Format (.workflow.json)')}
113
113
  ${chalk.dim('═'.repeat(70))}
114
114
 
115
- Narrative files define scenarios for rendering execution data as human-readable
115
+ Workflow files define scenarios for rendering execution data as human-readable
116
116
  stories. They evaluate conditions against captured events to select the best
117
- matching narrative template.
117
+ matching workflow template.
118
118
 
119
119
  ${chalk.bold('File Location:')}
120
- ${chalk.dim('.principal-views/')}${chalk.yellow('<feature-name>.narrative.json')}
120
+ ${chalk.dim('.principal-views/')}${chalk.yellow('<feature-name>.workflow.json')}
121
121
  ${chalk.dim('(co-located with corresponding .otel.canvas file)')}
122
122
 
123
123
  ${chalk.bold('Required Structure:')}
124
124
  ${chalk.dim('┌────────────────────────────────────────────────────────────────────┐')}
125
125
  ${chalk.dim('│')} { ${chalk.dim('│')}
126
- ${chalk.dim('│')} ${chalk.green('"name"')}: "Feature Name", ${chalk.dim('// NOT "Feature Name Narratives"')} ${chalk.dim('│')}
127
- ${chalk.dim('│')} ${chalk.green('"description"')}: "What the feature does", ${chalk.dim('// Purpose, not "Narratives for..."')} ${chalk.dim('│')}
126
+ ${chalk.dim('│')} ${chalk.green('"name"')}: "Feature Name", ${chalk.dim('// NOT "Feature Name Workflows"')} ${chalk.dim('│')}
127
+ ${chalk.dim('│')} ${chalk.green('"description"')}: "What the feature does", ${chalk.dim('// Purpose, not "Workflows for..."')} ${chalk.dim('│')}
128
128
  ${chalk.dim('│')} ${chalk.green('"scenarios"')}: [ ${chalk.dim('│')}
129
129
  ${chalk.dim('│')} { ${chalk.dim('│')}
130
130
  ${chalk.dim('│')} ${chalk.yellow('"priority"')}: 1, ${chalk.dim('// Lower = higher priority')} ${chalk.dim('│')}
131
131
  ${chalk.dim('│')} ${chalk.yellow('"condition"')}: "...", ${chalk.dim('// JSONPath/logic expression')} ${chalk.dim('│')}
132
- ${chalk.dim('│')} ${chalk.yellow('"template"')}: { ${chalk.dim('// Narrative template')} ${chalk.dim('│')}
132
+ ${chalk.dim('│')} ${chalk.yellow('"template"')}: { ${chalk.dim('// Workflow template')} ${chalk.dim('│')}
133
133
  ${chalk.dim('│')} ${chalk.cyan('"summary"')}: "Completed {{count}} items", ${chalk.dim('// Handlebars template')} ${chalk.dim('│')}
134
134
  ${chalk.dim('│')} ${chalk.cyan('"events"')}: { ${chalk.dim('// Per-event templates')} ${chalk.dim('│')}
135
135
  ${chalk.dim('│')} "event.name": "Event {{attribute}} occurred" ${chalk.dim('│')}
@@ -142,14 +142,14 @@ ${chalk.dim('└─────────────────────
142
142
 
143
143
  ${chalk.bold('Naming Guidelines:')}
144
144
 
145
- ❌ DON'T append "Narratives" to the name:
146
- "name": "Package Processor Narratives"
145
+ ❌ DON'T append "Workflows" to the name:
146
+ "name": "Package Processor Workflows"
147
147
 
148
148
  ✅ DO use the feature name directly:
149
149
  "name": "Package Processor"
150
150
 
151
151
  ❌ DON'T prefix description with boilerplate:
152
- "description": "Human-readable narratives for package extraction..."
152
+ "description": "Human-readable workflows for package extraction..."
153
153
 
154
154
  ✅ DO describe the feature's purpose:
155
155
  "description": "Package extraction and analysis from repository file trees"
@@ -200,7 +200,7 @@ ${chalk.cyan('5. Template style:')}
200
200
  - Include key metrics and IDs
201
201
 
202
202
  ${chalk.bold('Validation:')}
203
- ${chalk.cyan('npx @principal-ai/principal-view-cli narrative validate')}
203
+ ${chalk.cyan('npx @principal-ai/principal-view-cli workflow validate')}
204
204
  `,
205
205
  execution: `
206
206
  ${chalk.bold.cyan('Execution Format (.otel.json)')}
@@ -399,9 +399,9 @@ ${chalk.yellow('.principal-views/data-validator.otel.canvas')}
399
399
  }
400
400
  }
401
401
 
402
- ${chalk.bold('Example 2: Narrative Scenarios')}
402
+ ${chalk.bold('Example 2: Workflow Scenarios')}
403
403
  ${chalk.dim('─'.repeat(70))}
404
- ${chalk.yellow('.principal-views/data-validator.narrative.json')}
404
+ ${chalk.yellow('.principal-views/data-validator.workflow.json')}
405
405
 
406
406
  {
407
407
  "name": "Data Validator",
@@ -501,7 +501,7 @@ ${chalk.yellow('__executions__/data-validator.otel.json')}
501
501
 
502
502
  ${chalk.bold('Next Steps:')}
503
503
  ${chalk.cyan('npx @principal-ai/principal-view-cli validate')} Validate canvas
504
- ${chalk.cyan('npx @principal-ai/principal-view-cli narrative validate')} Validate narratives
504
+ ${chalk.cyan('npx @principal-ai/principal-view-cli workflow validate')} Validate workflows
505
505
  ${chalk.cyan('npx @principal-ai/principal-view-cli validate-execution')} Validate execution
506
506
  `,
507
507
  };
@@ -509,7 +509,7 @@ export function createFormatsCommand() {
509
509
  const command = new Command('formats');
510
510
  command
511
511
  .description('Display documentation about file formats')
512
- .argument('[section]', 'Section to display: overview, canvas, narrative, execution, examples')
512
+ .argument('[section]', 'Section to display: overview, canvas, workflow, execution, examples')
513
513
  .action((section) => {
514
514
  const validSections = Object.keys(FORMAT_SECTIONS);
515
515
  if (!section) {
@@ -8,7 +8,7 @@ import chalk from 'chalk';
8
8
  import { globby } from 'globby';
9
9
  import yaml from 'js-yaml';
10
10
  // Node.js-specific imports (rules engine, config management, validators)
11
- import { createDefaultRulesEngine, validatePrivuConfig, mergeConfigs, getDefaultConfig, createNarrativeValidator, } from '@principal-ai/principal-view-core/node';
11
+ import { createDefaultRulesEngine, validatePrivuConfig, mergeConfigs, getDefaultConfig, createWorkflowValidator, } from '@principal-ai/principal-view-core/node';
12
12
  // ============================================================================
13
13
  // Config File Loading
14
14
  // ============================================================================
@@ -118,23 +118,23 @@ function loadGraphConfig(filePath) {
118
118
  }
119
119
  }
120
120
  /**
121
- * Load a narrative template file
121
+ * Load a workflow template file
122
122
  */
123
- function loadNarrativeTemplate(filePath) {
123
+ function loadWorkflowTemplate(filePath) {
124
124
  if (!existsSync(filePath)) {
125
125
  return null;
126
126
  }
127
127
  try {
128
128
  const raw = readFileSync(filePath, 'utf8');
129
- const narrative = JSON.parse(raw);
130
- return { narrative, raw };
129
+ const workflow = JSON.parse(raw);
130
+ return { workflow, raw };
131
131
  }
132
132
  catch {
133
133
  return null;
134
134
  }
135
135
  }
136
136
  /**
137
- * Load a canvas file for narrative validation
137
+ * Load a canvas file for workflow validation
138
138
  */
139
139
  function loadCanvas(filePath) {
140
140
  if (!existsSync(filePath)) {
@@ -159,8 +159,8 @@ function loadCanvas(filePath) {
159
159
  */
160
160
  function getFileType(filePath) {
161
161
  const name = basename(filePath).toLowerCase();
162
- if (name.endsWith('.narrative.json')) {
163
- return 'narrative';
162
+ if (name.endsWith('.workflow.json')) {
163
+ return 'workflow';
164
164
  }
165
165
  if (name.endsWith('.canvas') || name.endsWith('.otel.canvas')) {
166
166
  return 'canvas';
@@ -347,7 +347,7 @@ export function createLintCommand() {
347
347
  expandDirectories: false,
348
348
  });
349
349
  // Filter out library files, config files, and execution artifacts
350
- // INCLUDE both canvas files and narrative templates for linting
350
+ // INCLUDE both canvas files and workflow templates for linting
351
351
  const configFiles = matchedFiles.filter((f) => {
352
352
  const name = basename(f).toLowerCase();
353
353
  const isLibraryFile = name.startsWith('library.');
@@ -380,45 +380,45 @@ export function createLintCommand() {
380
380
  }
381
381
  // Create validators
382
382
  const engine = createDefaultRulesEngine();
383
- const narrativeValidator = createNarrativeValidator();
383
+ const workflowValidator = createWorkflowValidator();
384
384
  // Lint each file
385
385
  const results = new Map();
386
- // PHASE 1: Group narratives by canvas and collect all events used
387
- const narrativesByCanvas = new Map();
386
+ // PHASE 1: Group workflows by canvas and collect all events used
387
+ const workflowsByCanvas = new Map();
388
388
  const canvasEventMap = new Map();
389
389
  for (const filePath of configFiles) {
390
390
  const absolutePath = resolve(cwd, filePath);
391
391
  const relativePath = relative(cwd, absolutePath);
392
392
  const fileType = getFileType(absolutePath);
393
- if (fileType === 'narrative') {
394
- const loaded = loadNarrativeTemplate(absolutePath);
393
+ if (fileType === 'workflow') {
394
+ const loaded = loadWorkflowTemplate(absolutePath);
395
395
  if (!loaded)
396
396
  continue;
397
- const canvasPath = loaded.narrative.canvas
398
- ? resolve(dirname(absolutePath), loaded.narrative.canvas)
397
+ const canvasPath = loaded.workflow.canvas
398
+ ? resolve(dirname(absolutePath), loaded.workflow.canvas)
399
399
  : undefined;
400
400
  if (canvasPath) {
401
401
  const canvasKey = relative(cwd, canvasPath);
402
- // Group narrative by canvas
403
- if (!narrativesByCanvas.has(canvasKey)) {
404
- narrativesByCanvas.set(canvasKey, []);
402
+ // Group workflow by canvas
403
+ if (!workflowsByCanvas.has(canvasKey)) {
404
+ workflowsByCanvas.set(canvasKey, []);
405
405
  canvasEventMap.set(canvasKey, new Set());
406
406
  }
407
- narrativesByCanvas.get(canvasKey).push({ absolutePath, relativePath, loaded });
408
- // Collect events from this narrative
409
- const narrativeEvents = canvasEventMap.get(canvasKey);
410
- for (const scenario of loaded.narrative.scenarios) {
407
+ workflowsByCanvas.get(canvasKey).push({ absolutePath, relativePath, loaded });
408
+ // Collect events from this workflow
409
+ const workflowEvents = canvasEventMap.get(canvasKey);
410
+ for (const scenario of loaded.workflow.scenarios) {
411
411
  if (scenario.condition?.requires) {
412
412
  for (const eventPattern of scenario.condition.requires) {
413
413
  if (!eventPattern.includes('*')) {
414
- narrativeEvents.add(eventPattern);
414
+ workflowEvents.add(eventPattern);
415
415
  }
416
416
  }
417
417
  }
418
418
  if (scenario.template?.events) {
419
419
  for (const eventName of Object.keys(scenario.template.events)) {
420
420
  if (!eventName.includes('*')) {
421
- narrativeEvents.add(eventName);
421
+ workflowEvents.add(eventName);
422
422
  }
423
423
  }
424
424
  }
@@ -431,9 +431,9 @@ export function createLintCommand() {
431
431
  const absolutePath = resolve(cwd, filePath);
432
432
  const relativePath = relative(cwd, absolutePath);
433
433
  const fileType = getFileType(absolutePath);
434
- if (fileType === 'narrative') {
435
- // Validate narrative template
436
- const loaded = loadNarrativeTemplate(absolutePath);
434
+ if (fileType === 'workflow') {
435
+ // Validate workflow template
436
+ const loaded = loadWorkflowTemplate(absolutePath);
437
437
  if (!loaded) {
438
438
  // File couldn't be loaded - report as error
439
439
  results.set(relativePath, {
@@ -442,7 +442,7 @@ export function createLintCommand() {
442
442
  ruleId: 'parse-error',
443
443
  severity: 'error',
444
444
  file: relativePath,
445
- message: `Could not parse narrative file: ${filePath}`,
445
+ message: `Could not parse workflow file: ${filePath}`,
446
446
  impact: 'File cannot be validated',
447
447
  fixable: false,
448
448
  },
@@ -456,25 +456,25 @@ export function createLintCommand() {
456
456
  continue;
457
457
  }
458
458
  // Load the referenced canvas if it exists
459
- const canvasPath = loaded.narrative.canvas
460
- ? resolve(dirname(absolutePath), loaded.narrative.canvas)
459
+ const canvasPath = loaded.workflow.canvas
460
+ ? resolve(dirname(absolutePath), loaded.workflow.canvas)
461
461
  : undefined;
462
462
  const canvas = canvasPath ? loadCanvas(canvasPath) : undefined;
463
- // Get all events used across narratives for this canvas
463
+ // Get all events used across workflows for this canvas
464
464
  const canvasKey = canvasPath ? relative(cwd, canvasPath) : undefined;
465
- const allNarrativeEvents = canvasKey ? canvasEventMap.get(canvasKey) : undefined;
466
- // Run narrative validation with canvas-wide event knowledge
467
- const narrativeResult = await narrativeValidator.validate({
468
- narrative: loaded.narrative,
469
- narrativePath: relativePath,
465
+ const allWorkflowEvents = canvasKey ? canvasEventMap.get(canvasKey) : undefined;
466
+ // Run workflow validation with canvas-wide event knowledge
467
+ const workflowResult = await workflowValidator.validate({
468
+ workflow: loaded.workflow,
469
+ workflowPath: relativePath,
470
470
  canvas: canvas ?? undefined,
471
471
  canvasPath: canvasKey,
472
472
  basePath: dirname(absolutePath),
473
473
  rawContent: loaded.raw,
474
- allNarrativeEvents,
474
+ allWorkflowEvents,
475
475
  });
476
- // Convert narrative violations to graph violations format
477
- const violations = narrativeResult.violations.map((v) => ({
476
+ // Convert workflow violations to graph violations format
477
+ const violations = workflowResult.violations.map((v) => ({
478
478
  ruleId: v.ruleId,
479
479
  severity: v.severity,
480
480
  file: v.file,
@@ -487,10 +487,10 @@ export function createLintCommand() {
487
487
  }));
488
488
  results.set(relativePath, {
489
489
  violations,
490
- errorCount: narrativeResult.errorCount,
491
- warningCount: narrativeResult.warningCount,
492
- fixableCount: narrativeResult.fixableCount,
493
- byCategory: { schema: 0, reference: 0, structure: 0, pattern: 0, library: 0 }, // Could categorize narrative rules
490
+ errorCount: workflowResult.errorCount,
491
+ warningCount: workflowResult.warningCount,
492
+ fixableCount: workflowResult.fixableCount,
493
+ byCategory: { schema: 0, reference: 0, structure: 0, pattern: 0, library: 0 }, // Could categorize workflow rules
494
494
  byRule: countByRule(violations),
495
495
  });
496
496
  }
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createWorkflowCommand(): Command;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,wBAAgB,qBAAqB,IAAI,OAAO,CAY/C"}
@@ -4,10 +4,10 @@ import { createInspectCommand } from './inspect.js';
4
4
  import { createRenderCommand } from './render.js';
5
5
  import { createTestCommand } from './test.js';
6
6
  import { createListCommand } from './list.js';
7
- export function createNarrativeCommand() {
8
- const command = new Command('narrative');
7
+ export function createWorkflowCommand() {
8
+ const command = new Command('workflow');
9
9
  command
10
- .description('Validate, test, and debug narrative templates')
10
+ .description('Validate, test, and debug workflow templates')
11
11
  .addCommand(createValidateCommand())
12
12
  .addCommand(createInspectCommand())
13
13
  .addCommand(createRenderCommand())
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/inspect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuBpC,wBAAgB,oBAAoB,IAAI,OAAO,CAiI9C"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,wBAAgB,iBAAiB,IAAI,OAAO,CA6G3C"}
@@ -3,11 +3,11 @@ import chalk from 'chalk';
3
3
  import { access } from 'node:fs/promises';
4
4
  import { resolve, dirname, join } from 'node:path';
5
5
  import { globby } from 'globby';
6
- import { loadNarrative } from './utils.js';
6
+ import { loadWorkflow } from './utils.js';
7
7
  export function createListCommand() {
8
8
  const command = new Command('list');
9
9
  command
10
- .description('List all narrative files in project')
10
+ .description('List all workflow files in project')
11
11
  .argument('[dir]', 'Directory to search (default: .principal-views/)')
12
12
  .option('--json', 'Output as JSON')
13
13
  .option('--show-canvas', 'Show linked canvas files')
@@ -15,19 +15,19 @@ export function createListCommand() {
15
15
  try {
16
16
  const searchDir = dir || '.principal-views';
17
17
  const searchPath = resolve(process.cwd(), searchDir);
18
- // Find all .narrative.json files
19
- const files = await globby('**/*.narrative.json', {
18
+ // Find all .workflow.json files
19
+ const files = await globby('**/*.workflow.json', {
20
20
  cwd: searchPath,
21
21
  ignore: ['node_modules/**', '.git/**', '__executions__/**'],
22
22
  });
23
- // Load each narrative and check canvas existence
24
- const narratives = await Promise.all(files.map(async (file) => {
23
+ // Load each workflow and check canvas existence
24
+ const workflows = await Promise.all(files.map(async (file) => {
25
25
  const fullPath = join(searchPath, file);
26
- const narrative = await loadNarrative(fullPath);
26
+ const workflow = await loadWorkflow(fullPath);
27
27
  let canvasExists;
28
- if (options.showCanvas && narrative.canvas) {
29
- const narrativeDir = dirname(fullPath);
30
- const canvasPath = resolve(narrativeDir, narrative.canvas);
28
+ if (options.showCanvas && workflow.canvas) {
29
+ const workflowDir = dirname(fullPath);
30
+ const canvasPath = resolve(workflowDir, workflow.canvas);
31
31
  try {
32
32
  await access(canvasPath);
33
33
  canvasExists = true;
@@ -36,22 +36,22 @@ export function createListCommand() {
36
36
  canvasExists = false;
37
37
  }
38
38
  }
39
- const defaultCount = narrative.scenarios.filter((s) => s.condition.default).length;
39
+ const defaultCount = workflow.scenarios.filter((s) => s.condition.default).length;
40
40
  return {
41
41
  file: join(searchDir, file),
42
- canvas: narrative.canvas,
42
+ canvas: workflow.canvas,
43
43
  canvasExists,
44
- scenarioCount: narrative.scenarios.length,
44
+ scenarioCount: workflow.scenarios.length,
45
45
  defaultCount,
46
- mode: narrative.mode,
47
- name: narrative.name,
46
+ mode: workflow.mode,
47
+ name: workflow.name,
48
48
  };
49
49
  }));
50
50
  if (options.json) {
51
51
  const output = {
52
52
  searchDir,
53
- count: narratives.length,
54
- narratives: narratives.map((n) => ({
53
+ count: workflows.length,
54
+ workflows: workflows.map((n) => ({
55
55
  file: n.file,
56
56
  name: n.name,
57
57
  canvas: n.canvas,
@@ -64,31 +64,31 @@ export function createListCommand() {
64
64
  console.log(JSON.stringify(output, null, 2));
65
65
  }
66
66
  else {
67
- console.log(chalk.bold('\nNarrative Templates:'));
67
+ console.log(chalk.bold('\nWorkflow Templates:'));
68
68
  console.log('━'.repeat(60));
69
- if (narratives.length === 0) {
70
- console.log(chalk.yellow(`\nNo narrative templates found in ${searchDir}`));
69
+ if (workflows.length === 0) {
70
+ console.log(chalk.yellow(`\nNo workflow templates found in ${searchDir}`));
71
71
  console.log();
72
72
  return;
73
73
  }
74
- for (const narrative of narratives) {
75
- console.log(chalk.bold(`\n${narrative.file}`));
76
- if (narrative.name) {
77
- console.log(chalk.gray(` Name: ${narrative.name}`));
74
+ for (const workflow of workflows) {
75
+ console.log(chalk.bold(`\n${workflow.file}`));
76
+ if (workflow.name) {
77
+ console.log(chalk.gray(` Name: ${workflow.name}`));
78
78
  }
79
- if (options.showCanvas && narrative.canvas) {
80
- const status = narrative.canvasExists
79
+ if (options.showCanvas && workflow.canvas) {
80
+ const status = workflow.canvasExists
81
81
  ? chalk.green('✓')
82
82
  : chalk.red('✗');
83
- console.log(chalk.gray(` Canvas: ${narrative.canvas} ${status}`));
83
+ console.log(chalk.gray(` Canvas: ${workflow.canvas} ${status}`));
84
84
  }
85
- else if (narrative.canvas) {
86
- console.log(chalk.gray(` Canvas: ${narrative.canvas}`));
85
+ else if (workflow.canvas) {
86
+ console.log(chalk.gray(` Canvas: ${workflow.canvas}`));
87
87
  }
88
- console.log(chalk.gray(` Scenarios: ${narrative.scenarioCount} (${narrative.defaultCount} default)`));
89
- console.log(chalk.gray(` Mode: ${narrative.mode}`));
88
+ console.log(chalk.gray(` Scenarios: ${workflow.scenarioCount} (${workflow.defaultCount} default)`));
89
+ console.log(chalk.gray(` Mode: ${workflow.mode}`));
90
90
  }
91
- console.log(chalk.bold(`\nFound ${narratives.length} narrative template(s)`));
91
+ console.log(chalk.bold(`\nFound ${workflows.length} workflow template(s)`));
92
92
  console.log();
93
93
  }
94
94
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBpC,wBAAgB,mBAAmB,IAAI,OAAO,CAmH7C"}
@@ -1,21 +1,21 @@
1
1
  import { Command } from 'commander';
2
2
  import chalk from 'chalk';
3
- import { renderNarrative } from '@principal-ai/principal-view-core';
4
- import { loadNarrative, loadExecution, executionToEvents, resolvePath, } from './utils.js';
3
+ import { renderWorkflow } from '@principal-ai/principal-view-core';
4
+ import { loadWorkflow, loadExecution, executionToEvents, resolvePath, } from './utils.js';
5
5
  export function createRenderCommand() {
6
6
  const command = new Command('render');
7
7
  command
8
- .description('Render narrative template using execution data')
9
- .argument('<narrative>', 'Path to .narrative.json file')
8
+ .description('Render workflow template using execution data')
9
+ .argument('<workflow>', 'Path to .workflow.json file')
10
10
  .argument('<execution>', 'Path to .otel.json execution file')
11
11
  .option('--mode <mode>', 'Override rendering mode: span-tree, timeline')
12
12
  .option('--scenario <id>', 'Force specific scenario (skip auto-selection)')
13
13
  .option('--json', 'Output structured result as JSON')
14
14
  .option('--format <format>', 'Output format: text (default), markdown, json', 'text')
15
15
  .option('--show-metadata', 'Include rendering metadata in output')
16
- .action(async (narrativePath, executionPath, options) => {
16
+ .action(async (workflowPath, executionPath, options) => {
17
17
  try {
18
- const narrative = await loadNarrative(resolvePath(narrativePath));
18
+ const workflow = await loadWorkflow(resolvePath(workflowPath));
19
19
  const executionData = await loadExecution(resolvePath(executionPath));
20
20
  const events = executionToEvents(executionData);
21
21
  // Override mode if specified
@@ -24,26 +24,26 @@ export function createRenderCommand() {
24
24
  if (!validModes.includes(options.mode)) {
25
25
  throw new Error(`Invalid mode: ${options.mode}. Must be one of: ${validModes.join(', ')}`);
26
26
  }
27
- narrative.mode = options.mode;
27
+ workflow.mode = options.mode;
28
28
  }
29
- // Render narrative
30
- const result = renderNarrative(narrative, events);
29
+ // Render workflow
30
+ const result = renderWorkflow(workflow, events);
31
31
  // Get the selected scenario from the result
32
- const selectedScenario = narrative.scenarios.find((s) => s.id === result.scenarioId);
32
+ const selectedScenario = workflow.scenarios.find((s) => s.id === result.scenarioId);
33
33
  // Force scenario if specified
34
34
  if (options.scenario) {
35
- const scenario = narrative.scenarios.find((s) => s.id === options.scenario);
35
+ const scenario = workflow.scenarios.find((s) => s.id === options.scenario);
36
36
  if (!scenario) {
37
37
  throw new Error(`Scenario not found: ${options.scenario}`);
38
38
  }
39
- // Note: This would require a way to force scenario in renderNarrative API
39
+ // Note: This would require a way to force scenario in renderWorkflow API
40
40
  // For now, we'll just validate the scenario exists
41
41
  }
42
42
  if (options.json) {
43
43
  const output = {
44
- narrative: narrativePath,
44
+ workflow: workflowPath,
45
45
  execution: executionPath,
46
- mode: narrative.mode,
46
+ mode: workflow.mode,
47
47
  scenario: {
48
48
  id: selectedScenario?.id,
49
49
  priority: selectedScenario?.priority,
@@ -59,9 +59,9 @@ export function createRenderCommand() {
59
59
  else {
60
60
  // Text output
61
61
  if (!options.format || options.format === 'text') {
62
- console.log(chalk.gray(`Rendering: ${narrativePath}`));
62
+ console.log(chalk.gray(`Rendering: ${workflowPath}`));
63
63
  console.log(chalk.gray(`Execution: ${executionPath}`));
64
- console.log(chalk.gray(`Mode: ${narrative.mode}`));
64
+ console.log(chalk.gray(`Mode: ${workflow.mode}`));
65
65
  if (selectedScenario) {
66
66
  console.log(chalk.gray(`Scenario: ${selectedScenario.id} (priority: ${selectedScenario.priority})`));
67
67
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsBpC,wBAAgB,iBAAiB,IAAI,OAAO,CAuL3C"}
@@ -1,25 +1,25 @@
1
1
  import { Command } from 'commander';
2
2
  import chalk from 'chalk';
3
3
  import { selectScenario, matchesCondition, computeAggregates, hasEventMatching, } from '@principal-ai/principal-view-core';
4
- import { loadNarrative, loadExecution, executionToEvents, resolvePath, formatValue, } from './utils.js';
4
+ import { loadWorkflow, loadExecution, executionToEvents, resolvePath, formatValue, } from './utils.js';
5
5
  export function createTestCommand() {
6
6
  const command = new Command('test');
7
7
  command
8
8
  .description('Test scenario matching and show why scenarios match or don\'t match')
9
- .argument('<narrative>', 'Path to .narrative.json file')
9
+ .argument('<workflow>', 'Path to .workflow.json file')
10
10
  .argument('<execution>', 'Path to .otel.json execution file')
11
11
  .option('--show-all', 'Show all scenarios (not just matches)')
12
12
  .option('--show-aggregates', 'Display computed aggregates')
13
13
  .option('--json', 'Output as JSON')
14
- .action(async (narrativePath, executionPath, options) => {
14
+ .action(async (workflowPath, executionPath, options) => {
15
15
  try {
16
- const narrative = await loadNarrative(resolvePath(narrativePath));
16
+ const workflow = await loadWorkflow(resolvePath(workflowPath));
17
17
  const executionData = await loadExecution(resolvePath(executionPath));
18
18
  const events = executionToEvents(executionData);
19
19
  // Compute aggregates
20
20
  const aggregates = computeAggregates(events);
21
21
  // Test each scenario
22
- const scenarioResults = narrative.scenarios.map((scenario) => {
22
+ const scenarioResults = workflow.scenarios.map((scenario) => {
23
23
  const condition = scenario.condition;
24
24
  const matched = matchesCondition(condition, events, aggregates);
25
25
  let reason;
@@ -60,11 +60,11 @@ export function createTestCommand() {
60
60
  };
61
61
  });
62
62
  // Select the winning scenario
63
- const matchResult = selectScenario(narrative, events, aggregates);
63
+ const matchResult = selectScenario(workflow, events, aggregates);
64
64
  const selectedScenario = matchResult.scenario;
65
65
  if (options.json) {
66
66
  const output = {
67
- narrative: narrativePath,
67
+ workflow: workflowPath,
68
68
  execution: executionPath,
69
69
  scenarios: scenarioResults.map((r) => ({
70
70
  id: r.scenario.id,
@@ -81,7 +81,7 @@ export function createTestCommand() {
81
81
  }
82
82
  else {
83
83
  // Text output
84
- console.log(chalk.bold(`\nTesting: ${narrativePath}`));
84
+ console.log(chalk.bold(`\nTesting: ${workflowPath}`));
85
85
  console.log(chalk.gray(`Execution: ${executionPath}\n`));
86
86
  console.log(chalk.bold('Scenario Matching Results:'));
87
87
  console.log('━'.repeat(60));
@@ -1,9 +1,9 @@
1
- import type { NarrativeTemplate, OtelEvent } from '@principal-ai/principal-view-core';
1
+ import type { WorkflowTemplate, OtelEvent } from '@principal-ai/principal-view-core';
2
2
  import { type ExecutionData } from '@principal-ai/principal-view-core';
3
3
  /**
4
- * Load a narrative template from a file
4
+ * Load a workflow template from a file
5
5
  */
6
- export declare function loadNarrative(filePath: string): Promise<NarrativeTemplate>;
6
+ export declare function loadWorkflow(filePath: string): Promise<WorkflowTemplate>;
7
7
  /**
8
8
  * Load execution data from a .otel.json file
9
9
  *
@@ -11,7 +11,7 @@ export declare function loadNarrative(filePath: string): Promise<NarrativeTempla
11
11
  */
12
12
  export declare function loadExecution(filePath: string): Promise<ExecutionData>;
13
13
  /**
14
- * Convert execution data to OtelEvent array format expected by narrative APIs
14
+ * Convert execution data to OtelEvent array format expected by workflow APIs
15
15
  */
16
16
  export declare function executionToEvents(execution: ExecutionData): OtelEvent[];
17
17
  /**
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AACrF,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAE3F;;GAEG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAU9E;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAc5E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,aAAa,GAAG,SAAS,EAAE,CAmBvE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAKtE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAWzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAoBzC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,OAAO,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAazB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAS1E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAclD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C"}