@principal-ai/principal-studio-cli 0.35.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.
Files changed (184) hide show
  1. package/README.md +172 -0
  2. package/dist/commands/agent-session.d.ts +3 -0
  3. package/dist/commands/agent-session.d.ts.map +1 -0
  4. package/dist/commands/agent-session.js +67 -0
  5. package/dist/commands/agent-sessions.d.ts +11 -0
  6. package/dist/commands/agent-sessions.d.ts.map +1 -0
  7. package/dist/commands/agent-sessions.js +39 -0
  8. package/dist/commands/auxiliary/index.d.ts +3 -0
  9. package/dist/commands/auxiliary/index.d.ts.map +1 -0
  10. package/dist/commands/auxiliary/index.js +9 -0
  11. package/dist/commands/auxiliary/validate.d.ts +3 -0
  12. package/dist/commands/auxiliary/validate.d.ts.map +1 -0
  13. package/dist/commands/auxiliary/validate.js +123 -0
  14. package/dist/commands/collector/check.d.ts +6 -0
  15. package/dist/commands/collector/check.d.ts.map +1 -0
  16. package/dist/commands/collector/check.js +153 -0
  17. package/dist/commands/collector/diagnose.d.ts +6 -0
  18. package/dist/commands/collector/diagnose.d.ts.map +1 -0
  19. package/dist/commands/collector/diagnose.js +229 -0
  20. package/dist/commands/collector/index.d.ts +6 -0
  21. package/dist/commands/collector/index.d.ts.map +1 -0
  22. package/dist/commands/collector/index.js +16 -0
  23. package/dist/commands/collector/status.d.ts +6 -0
  24. package/dist/commands/collector/status.d.ts.map +1 -0
  25. package/dist/commands/collector/status.js +77 -0
  26. package/dist/commands/collector/utils.d.ts +92 -0
  27. package/dist/commands/collector/utils.d.ts.map +1 -0
  28. package/dist/commands/collector/utils.js +154 -0
  29. package/dist/commands/coverage.d.ts +9 -0
  30. package/dist/commands/coverage.d.ts.map +1 -0
  31. package/dist/commands/coverage.js +252 -0
  32. package/dist/commands/create.d.ts +6 -0
  33. package/dist/commands/create.d.ts.map +1 -0
  34. package/dist/commands/create.js +50 -0
  35. package/dist/commands/events/index.d.ts +3 -0
  36. package/dist/commands/events/index.d.ts.map +1 -0
  37. package/dist/commands/events/index.js +9 -0
  38. package/dist/commands/events/validate.d.ts +3 -0
  39. package/dist/commands/events/validate.d.ts.map +1 -0
  40. package/dist/commands/events/validate.js +124 -0
  41. package/dist/commands/formats.d.ts +6 -0
  42. package/dist/commands/formats.d.ts.map +1 -0
  43. package/dist/commands/formats.js +1118 -0
  44. package/dist/commands/hooks.d.ts +9 -0
  45. package/dist/commands/hooks.d.ts.map +1 -0
  46. package/dist/commands/hooks.js +295 -0
  47. package/dist/commands/inbox.d.ts +13 -0
  48. package/dist/commands/inbox.d.ts.map +1 -0
  49. package/dist/commands/inbox.js +179 -0
  50. package/dist/commands/init.d.ts +6 -0
  51. package/dist/commands/init.d.ts.map +1 -0
  52. package/dist/commands/init.js +220 -0
  53. package/dist/commands/lint.d.ts +11 -0
  54. package/dist/commands/lint.d.ts.map +1 -0
  55. package/dist/commands/lint.js +71 -0
  56. package/dist/commands/list.d.ts +6 -0
  57. package/dist/commands/list.d.ts.map +1 -0
  58. package/dist/commands/list.js +78 -0
  59. package/dist/commands/migrate-nodes.d.ts +9 -0
  60. package/dist/commands/migrate-nodes.d.ts.map +1 -0
  61. package/dist/commands/migrate-nodes.js +363 -0
  62. package/dist/commands/migrate-scopes-to-canvas.d.ts +3 -0
  63. package/dist/commands/migrate-scopes-to-canvas.d.ts.map +1 -0
  64. package/dist/commands/migrate-scopes-to-canvas.js +143 -0
  65. package/dist/commands/migration.d.ts +6 -0
  66. package/dist/commands/migration.d.ts.map +1 -0
  67. package/dist/commands/migration.js +247 -0
  68. package/dist/commands/open-studio.d.ts +10 -0
  69. package/dist/commands/open-studio.d.ts.map +1 -0
  70. package/dist/commands/open-studio.js +32 -0
  71. package/dist/commands/opencode/fetch.d.ts +3 -0
  72. package/dist/commands/opencode/fetch.d.ts.map +1 -0
  73. package/dist/commands/opencode/fetch.js +25 -0
  74. package/dist/commands/opencode/index.d.ts +3 -0
  75. package/dist/commands/opencode/index.d.ts.map +1 -0
  76. package/dist/commands/opencode/index.js +11 -0
  77. package/dist/commands/opencode/list-sessions.d.ts +3 -0
  78. package/dist/commands/opencode/list-sessions.d.ts.map +1 -0
  79. package/dist/commands/opencode/list-sessions.js +20 -0
  80. package/dist/commands/repo.d.ts +18 -0
  81. package/dist/commands/repo.d.ts.map +1 -0
  82. package/dist/commands/repo.js +233 -0
  83. package/dist/commands/schema.d.ts +6 -0
  84. package/dist/commands/schema.d.ts.map +1 -0
  85. package/dist/commands/schema.js +367 -0
  86. package/dist/commands/scopes/index.d.ts +3 -0
  87. package/dist/commands/scopes/index.d.ts.map +1 -0
  88. package/dist/commands/scopes/index.js +9 -0
  89. package/dist/commands/scopes/validate.d.ts +3 -0
  90. package/dist/commands/scopes/validate.d.ts.map +1 -0
  91. package/dist/commands/scopes/validate.js +187 -0
  92. package/dist/commands/setup.d.ts +6 -0
  93. package/dist/commands/setup.d.ts.map +1 -0
  94. package/dist/commands/setup.js +406 -0
  95. package/dist/commands/starred-collections.d.ts +12 -0
  96. package/dist/commands/starred-collections.d.ts.map +1 -0
  97. package/dist/commands/starred-collections.js +310 -0
  98. package/dist/commands/subsystem-model.d.ts +11 -0
  99. package/dist/commands/subsystem-model.d.ts.map +1 -0
  100. package/dist/commands/subsystem-model.js +249 -0
  101. package/dist/commands/topic.d.ts +15 -0
  102. package/dist/commands/topic.d.ts.map +1 -0
  103. package/dist/commands/topic.js +683 -0
  104. package/dist/commands/tour.d.ts +23 -0
  105. package/dist/commands/tour.d.ts.map +1 -0
  106. package/dist/commands/tour.js +783 -0
  107. package/dist/commands/trace/flow.d.ts +6 -0
  108. package/dist/commands/trace/flow.d.ts.map +1 -0
  109. package/dist/commands/trace/flow.js +158 -0
  110. package/dist/commands/trace/index.d.ts +6 -0
  111. package/dist/commands/trace/index.d.ts.map +1 -0
  112. package/dist/commands/trace/index.js +20 -0
  113. package/dist/commands/trace/inspect.d.ts +6 -0
  114. package/dist/commands/trace/inspect.d.ts.map +1 -0
  115. package/dist/commands/trace/inspect.js +187 -0
  116. package/dist/commands/trace/list.d.ts +6 -0
  117. package/dist/commands/trace/list.d.ts.map +1 -0
  118. package/dist/commands/trace/list.js +145 -0
  119. package/dist/commands/trace/registrations.d.ts +6 -0
  120. package/dist/commands/trace/registrations.d.ts.map +1 -0
  121. package/dist/commands/trace/registrations.js +81 -0
  122. package/dist/commands/trace/validate.d.ts +6 -0
  123. package/dist/commands/trace/validate.d.ts.map +1 -0
  124. package/dist/commands/trace/validate.js +276 -0
  125. package/dist/commands/trail.d.ts +36 -0
  126. package/dist/commands/trail.d.ts.map +1 -0
  127. package/dist/commands/trail.js +622 -0
  128. package/dist/commands/validate.d.ts +12 -0
  129. package/dist/commands/validate.d.ts.map +1 -0
  130. package/dist/commands/validate.js +3334 -0
  131. package/dist/commands/workflow/implementation.d.ts +3 -0
  132. package/dist/commands/workflow/implementation.d.ts.map +1 -0
  133. package/dist/commands/workflow/implementation.js +51 -0
  134. package/dist/commands/workflow/index.d.ts +3 -0
  135. package/dist/commands/workflow/index.d.ts.map +1 -0
  136. package/dist/commands/workflow/index.js +19 -0
  137. package/dist/commands/workflow/inspect.d.ts +3 -0
  138. package/dist/commands/workflow/inspect.d.ts.map +1 -0
  139. package/dist/commands/workflow/inspect.js +123 -0
  140. package/dist/commands/workflow/list.d.ts +3 -0
  141. package/dist/commands/workflow/list.d.ts.map +1 -0
  142. package/dist/commands/workflow/list.js +95 -0
  143. package/dist/commands/workflow/render.d.ts +3 -0
  144. package/dist/commands/workflow/render.d.ts.map +1 -0
  145. package/dist/commands/workflow/render.js +88 -0
  146. package/dist/commands/workflow/test.d.ts +3 -0
  147. package/dist/commands/workflow/test.d.ts.map +1 -0
  148. package/dist/commands/workflow/test.js +141 -0
  149. package/dist/commands/workflow/utils.d.ts +49 -0
  150. package/dist/commands/workflow/utils.d.ts.map +1 -0
  151. package/dist/commands/workflow/utils.js +164 -0
  152. package/dist/commands/workflow/validate.d.ts +3 -0
  153. package/dist/commands/workflow/validate.d.ts.map +1 -0
  154. package/dist/commands/workflow/validate.js +344 -0
  155. package/dist/file-utils.d.ts +15 -0
  156. package/dist/file-utils.d.ts.map +1 -0
  157. package/dist/file-utils.js +29 -0
  158. package/dist/index.cjs +285718 -0
  159. package/dist/index.cjs.map +7 -0
  160. package/dist/index.d.ts +8 -0
  161. package/dist/index.d.ts.map +1 -0
  162. package/dist/index.js +81 -0
  163. package/dist/lib/bridge-ipc.d.ts +29 -0
  164. package/dist/lib/bridge-ipc.d.ts.map +1 -0
  165. package/dist/lib/bridge-ipc.js +128 -0
  166. package/dist/lib/github-user.d.ts +17 -0
  167. package/dist/lib/github-user.d.ts.map +1 -0
  168. package/dist/lib/github-user.js +53 -0
  169. package/dist/lib/open-url.d.ts +11 -0
  170. package/dist/lib/open-url.d.ts.map +1 -0
  171. package/dist/lib/open-url.js +45 -0
  172. package/dist/lib/subsystem-model-store.d.ts +74 -0
  173. package/dist/lib/subsystem-model-store.d.ts.map +1 -0
  174. package/dist/lib/subsystem-model-store.js +292 -0
  175. package/dist/lib/tour-cache.d.ts +26 -0
  176. package/dist/lib/tour-cache.d.ts.map +1 -0
  177. package/dist/lib/tour-cache.js +46 -0
  178. package/dist/lib/trail-cache.d.ts +40 -0
  179. package/dist/lib/trail-cache.d.ts.map +1 -0
  180. package/dist/lib/trail-cache.js +97 -0
  181. package/dist/lib/viewer-ipc.d.ts +44 -0
  182. package/dist/lib/viewer-ipc.d.ts.map +1 -0
  183. package/dist/lib/viewer-ipc.js +68 -0
  184. package/package.json +68 -0
package/README.md ADDED
@@ -0,0 +1,172 @@
1
+ # Principal View CLI
2
+
3
+ A command-line tool for validating and managing `.canvas` configuration files for the Principal View Framework.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @principal-ai/principal-studio-cli
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ After installation, use the `principal-ai` command:
14
+
15
+ ```bash
16
+ principal-ai --help
17
+ ```
18
+
19
+ Or run without installing via npx:
20
+
21
+ ```bash
22
+ npx @principal-ai/principal-studio-cli --help
23
+ ```
24
+
25
+ ### Commands
26
+
27
+ #### `init` - Initialize Project Structure
28
+
29
+ Set up a new `.principal-views` folder with template files:
30
+
31
+ ```bash
32
+ principal-ai init
33
+ principal-ai init --name my-architecture
34
+ principal-ai init --force # Overwrite existing files
35
+ ```
36
+
37
+ #### `validate` - Validate Canvas Files
38
+
39
+ Strict validation of `.canvas` configuration files:
40
+
41
+ ```bash
42
+ principal-ai validate # Validates all .principal-views/*.canvas files
43
+ principal-ai validate path/to/file.canvas
44
+ principal-ai validate "**/*.canvas" # Glob pattern
45
+ principal-ai validate --quiet # Only output errors
46
+ principal-ai validate --json # Output as JSON
47
+ ```
48
+
49
+ **Validation checks:**
50
+
51
+ - Required `pv` extension with name and version
52
+ - All nodes have required fields (id, type, x, y, width, height)
53
+ - Custom node types must have `pv.nodeType` and valid `pv.shape`
54
+ - Edge references point to existing nodes
55
+ - Edge types reference defined edge type definitions
56
+
57
+ #### `list` (alias: `ls`) - List Canvas Files
58
+
59
+ Display all canvas files in the project with metadata:
60
+
61
+ ```bash
62
+ principal-ai list
63
+ principal-ai ls --all # Search all directories
64
+ principal-ai ls --json # Output as JSON
65
+ ```
66
+
67
+ #### `schema` - Display Format Documentation
68
+
69
+ Show detailed documentation about the canvas format:
70
+
71
+ ```bash
72
+ principal-ai schema # Overview
73
+ principal-ai schema nodes # Node types, shapes, colors
74
+ principal-ai schema edges # Edge properties and styles
75
+ principal-ai schema pv # Principal View extension fields
76
+ principal-ai schema examples # Complete examples
77
+ ```
78
+
79
+ #### `doctor` - Configuration Health Check
80
+
81
+ Check configuration staleness and validate source patterns:
82
+
83
+ ```bash
84
+ principal-ai doctor
85
+ principal-ai doctor --quiet # Only show errors and warnings
86
+ principal-ai doctor --errors-only # For pre-commit hooks
87
+ principal-ai doctor --json # Output as JSON
88
+ ```
89
+
90
+ ## Canvas Format
91
+
92
+ Canvas files follow the [JSON Canvas](https://jsoncanvas.org/) specification with Principal View extensions that maintain compatibility with standard tools like Obsidian.
93
+
94
+ ### Required Structure
95
+
96
+ ```json
97
+ {
98
+ "nodes": [...],
99
+ "edges": [...],
100
+ "pv": {
101
+ "name": "my-architecture",
102
+ "version": "1.0.0"
103
+ }
104
+ }
105
+ ```
106
+
107
+ ### Node Types
108
+
109
+ **Standard types** (no additional metadata required):
110
+
111
+ - `text` - Text content
112
+ - `group` - Container for other nodes
113
+ - `file` - File reference
114
+ - `link` - URL link
115
+
116
+ **Custom types** require `pv` extension:
117
+
118
+ ```json
119
+ {
120
+ "id": "node-1",
121
+ "type": "custom",
122
+ "x": 0,
123
+ "y": 0,
124
+ "width": 200,
125
+ "height": 100,
126
+ "pv": {
127
+ "nodeType": "service",
128
+ "shape": "rectangle"
129
+ }
130
+ }
131
+ ```
132
+
133
+ **Available shapes:** `circle`, `rectangle`, `hexagon`, `diamond`, `custom`
134
+
135
+ ### Edge Types
136
+
137
+ Define reusable edge styles at the canvas level:
138
+
139
+ ```json
140
+ {
141
+ "pv": {
142
+ "edgeTypes": {
143
+ "data-flow": {
144
+ "style": "dashed",
145
+ "color": "#3498db",
146
+ "width": 2
147
+ }
148
+ }
149
+ }
150
+ }
151
+ ```
152
+
153
+ Use in edges:
154
+
155
+ ```json
156
+ {
157
+ "id": "edge-1",
158
+ "fromNode": "node-1",
159
+ "toNode": "node-2",
160
+ "pv": {
161
+ "edgeType": "data-flow"
162
+ }
163
+ }
164
+ ```
165
+
166
+ ## Requirements
167
+
168
+ - Node.js >= 18
169
+
170
+ ## License
171
+
172
+ Apache-2.0
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createAgentSessionCommand(): Command;
3
+ //# sourceMappingURL=agent-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-session.d.ts","sourceRoot":"","sources":["../../src/commands/agent-session.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,wBAAgB,yBAAyB,IAAI,OAAO,CAuGnD"}
@@ -0,0 +1,67 @@
1
+ import { writeFile } from 'node:fs/promises';
2
+ import { Command } from 'commander';
3
+ import { accumulateEvents, buildAgentSessionFixture, collectRepositories, fetchRawEvents, listAgentSessions, normalizeEvents, normalizeEventsWithAdapter, } from '@principal-ai/subsystems-core/node';
4
+ export function createAgentSessionCommand() {
5
+ const command = new Command('agent-session')
6
+ .description('Read agent sessions and normalize them into universal events (Cline + Codex + opencode + pi + grok)');
7
+ command
8
+ .command('list')
9
+ .description('List top-level sessions from all supported agents (Cline + Codex + opencode + pi + grok)')
10
+ .option('--db-path <path>', 'Path to opencode.db (defaults to XDG data dir)')
11
+ .action((options) => {
12
+ const sessions = listAgentSessions({ dbPath: options.dbPath });
13
+ process.stdout.write(JSON.stringify(sessions, null, 2) + '\n');
14
+ });
15
+ command
16
+ .command('fetch <session-id>')
17
+ .description('Fetch a session and print its normalized universal events as JSON')
18
+ .option('--agent <cline|codex|opencode|pi|grok>', 'Force agent detection (defaults to auto-detect)')
19
+ .option('--db-path <path>', 'Path to opencode.db (defaults to XDG data dir)')
20
+ .option('--raw', 'Output raw universal events before repo normalization')
21
+ .option('--view <normalized|accumulated|both>', 'Which pipeline stage to return (defaults to both)', 'both')
22
+ .action(async (sessionId, options) => {
23
+ const { agent, events } = fetchRawEvents(sessionId, {
24
+ agent: options.agent,
25
+ dbPath: options.dbPath,
26
+ });
27
+ if (options.raw) {
28
+ process.stdout.write(JSON.stringify({ agent, events }, null, 2) + '\n');
29
+ return;
30
+ }
31
+ const view = options.view ?? 'both';
32
+ const normalized = await normalizeEvents(events);
33
+ const accumulated = accumulateEvents(normalized);
34
+ const repos = collectRepositories(normalized);
35
+ const payload = { agent, sessionId, repos };
36
+ if (view === 'normalized' || view === 'both')
37
+ payload.normalized = normalized;
38
+ if (view === 'accumulated' || view === 'both')
39
+ payload.accumulated = accumulated;
40
+ process.stdout.write(JSON.stringify(payload, null, 2) + '\n');
41
+ });
42
+ command
43
+ .command('fixture <session-id>')
44
+ .description('Generate a frozen File City agent-session fixture JSON (Cline + Codex + opencode + pi + grok)')
45
+ .option('--agent <cline|codex|opencode|pi|grok>', 'Force agent detection (defaults to auto-detect)')
46
+ .option('--db-path <path>', 'Path to opencode.db (defaults to XDG data dir)')
47
+ .option('-o, --out <path>', 'Output file path (defaults to <session-id>.fixture.json)')
48
+ .action(async (sessionId, options) => {
49
+ const { agent, events, sessionMeta } = fetchRawEvents(sessionId, {
50
+ agent: options.agent,
51
+ dbPath: options.dbPath,
52
+ });
53
+ const { normalized } = await normalizeEventsWithAdapter(events, sessionMeta.workingDirectory);
54
+ const fixture = buildAgentSessionFixture({
55
+ agent,
56
+ sessionId,
57
+ sessionMeta,
58
+ normalizedEvents: normalized,
59
+ rawEventCount: events.length,
60
+ });
61
+ const outPath = options.out ?? `${sessionId}.fixture.json`;
62
+ await writeFile(outPath, JSON.stringify(fixture, null, 2));
63
+ process.stderr.write(`Wrote ${agent} fixture to ${outPath}\n`);
64
+ process.stdout.write(JSON.stringify(fixture.session, null, 2) + '\n');
65
+ });
66
+ return command;
67
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * `principal-ai agent-sessions` — open the Agent Sessions viewer.
3
+ *
4
+ * Launches the standalone principal-studio bundle pointed straight at the Agent
5
+ * Sessions tab (recent opencode sessions rendered as File City). If a viewer
6
+ * is already running, hands the tab switch off to it via the IPC socket
7
+ * instead of spawning a second instance.
8
+ */
9
+ import { Command } from 'commander';
10
+ export declare function createAgentSessionsCommand(): Command;
11
+ //# sourceMappingURL=agent-sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-sessions.d.ts","sourceRoot":"","sources":["../../src/commands/agent-sessions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,0BAA0B,IAAI,OAAO,CAiCpD"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * `principal-ai agent-sessions` — open the Agent Sessions viewer.
3
+ *
4
+ * Launches the standalone principal-studio bundle pointed straight at the Agent
5
+ * Sessions tab (recent opencode sessions rendered as File City). If a viewer
6
+ * is already running, hands the tab switch off to it via the IPC socket
7
+ * instead of spawning a second instance.
8
+ */
9
+ import { spawn } from 'node:child_process';
10
+ import { Command } from 'commander';
11
+ import { handoffToRunning } from '../lib/viewer-ipc.js';
12
+ import { resolveViewerLaunch } from './trail.js';
13
+ const AGENT_SESSIONS_TAB_ID = 'agent-sessions';
14
+ export function createAgentSessionsCommand() {
15
+ return new Command('agent-sessions')
16
+ .description('Open the Agent Sessions viewer — recent opencode sessions rendered as File City')
17
+ .option('--viewer-dir <path>', 'Path to the @principal-ai/subsystems-studio package (overrides PRINCIPAL_STUDIO_DIR)')
18
+ .action(async (options) => {
19
+ // Prefer a running viewer: switch it to the Agent Sessions tab and exit
20
+ // without spawning — a second instance couldn't bind the IPC socket.
21
+ if (await handoffToRunning({ kind: 'ACTIVATE_TAB', tabId: AGENT_SESSIONS_TAB_ID })) {
22
+ process.stderr.write('Agent Sessions opened in the running viewer.\n');
23
+ return;
24
+ }
25
+ const launch = resolveViewerLaunch(options.viewerDir);
26
+ const env = {
27
+ ...process.env,
28
+ PRINCIPAL_STUDIO_START_TAB: AGENT_SESSIONS_TAB_ID,
29
+ };
30
+ process.stderr.write('Launching Agent Sessions viewer…\n');
31
+ const child = launch.kind === 'installed'
32
+ ? spawn(launch.bin, [], { env, stdio: 'inherit' })
33
+ : spawn('bun', ['start'], { cwd: launch.dir, env, stdio: 'inherit' });
34
+ child.on('error', (err) => {
35
+ process.stderr.write(`Failed to launch viewer: ${err.message}\n`);
36
+ process.exit(1);
37
+ });
38
+ });
39
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createAuxiliaryCommand(): Command;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/auxiliary/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,sBAAsB,IAAI,OAAO,CAQhD"}
@@ -0,0 +1,9 @@
1
+ import { Command } from 'commander';
2
+ import { createValidateCommand } from './validate.js';
3
+ export function createAuxiliaryCommand() {
4
+ const command = new Command('auxiliary');
5
+ command
6
+ .description('Manage and validate the auxiliary manifest (project regions outside the OTEL surface)')
7
+ .addCommand(createValidateCommand());
8
+ return command;
9
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createValidateCommand(): Command;
3
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/commands/auxiliary/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2BpC,wBAAgB,qBAAqB,IAAI,OAAO,CAsH/C"}
@@ -0,0 +1,123 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { resolve } from 'node:path';
4
+ import { readFileSync, existsSync } from 'node:fs';
5
+ import { AuxiliaryManifestValidator, validateAreaScopeDisjoint, CanvasDiscovery, } from '@principal-ai/subsystems-core/node';
6
+ import { FilesystemService, NodeFileSystemAdapter } from '@principal-ai/codebase-composition/node';
7
+ import { NodeFileSystemAdapter as RepoNodeFileSystemAdapter } from '@principal-ai/repository-abstraction/node';
8
+ const MANIFEST_RELATIVE_PATH = '.principal-views/auxiliary.manifest.json';
9
+ export function createValidateCommand() {
10
+ const command = new Command('validate');
11
+ command
12
+ .description('Validate auxiliary.manifest.json against the filesystem and scope paths')
13
+ .option('--json', 'Output as JSON')
14
+ .option('-d, --dir <path>', 'Project directory (default: cwd)')
15
+ .action(async (options) => {
16
+ try {
17
+ const baseDir = options.dir || process.cwd();
18
+ const manifestPath = MANIFEST_RELATIVE_PATH;
19
+ const manifestFullPath = resolve(baseDir, manifestPath);
20
+ if (!existsSync(manifestFullPath)) {
21
+ if (options.json) {
22
+ console.log(JSON.stringify({ valid: true, manifestPresent: false, violations: [] }, null, 2));
23
+ }
24
+ else {
25
+ console.log(chalk.gray(`No ${manifestPath} found — auxiliary manifest is optional, nothing to validate.`));
26
+ }
27
+ return;
28
+ }
29
+ let manifest;
30
+ try {
31
+ manifest = JSON.parse(readFileSync(manifestFullPath, 'utf-8'));
32
+ }
33
+ catch (err) {
34
+ console.error(chalk.red('Error:'), `Failed to parse ${manifestPath}: ${err.message}`);
35
+ process.exit(1);
36
+ }
37
+ const ownFileResult = await new AuxiliaryManifestValidator(new RepoNodeFileSystemAdapter()).validate({
38
+ manifest,
39
+ manifestPath,
40
+ basePath: baseDir,
41
+ });
42
+ // Cross-check: areas must not overlap any scope path. Discover the
43
+ // scopes canvas the same way `pv scopes validate` does.
44
+ const service = new FilesystemService(new NodeFileSystemAdapter());
45
+ const fileTree = await service.buildFileSystemTreeFromPath(baseDir);
46
+ const discovery = new CanvasDiscovery();
47
+ const discoveryResult = await discovery.discover(fileTree, {
48
+ fileReader: async (p) => readFileSync(resolve(baseDir, p), 'utf-8'),
49
+ includeContent: true,
50
+ });
51
+ const scopesDiscovered = discoveryResult.canvases.find((c) => c.type === 'scopes');
52
+ let scopesCanvas;
53
+ let scopesCanvasPath;
54
+ if (scopesDiscovered) {
55
+ scopesCanvasPath = scopesDiscovered.path;
56
+ const withContent = scopesDiscovered;
57
+ scopesCanvas = withContent.content;
58
+ if (!scopesCanvas) {
59
+ try {
60
+ scopesCanvas = JSON.parse(readFileSync(resolve(baseDir, scopesDiscovered.path), 'utf-8'));
61
+ }
62
+ catch {
63
+ // leave undefined; cross-check will be skipped
64
+ }
65
+ }
66
+ }
67
+ const crossViolations = scopesCanvas
68
+ ? validateAreaScopeDisjoint({ manifest, manifestPath, scopesCanvas, scopesCanvasPath })
69
+ : [];
70
+ const violations = [...ownFileResult.violations, ...crossViolations];
71
+ const errors = violations.filter((v) => v.severity === 'error');
72
+ const warnings = violations.filter((v) => v.severity === 'warn');
73
+ const valid = errors.length === 0;
74
+ if (options.json) {
75
+ console.log(JSON.stringify({
76
+ valid,
77
+ manifestPresent: true,
78
+ areaCount: (manifest.areas || []).length,
79
+ violations,
80
+ }, null, 2));
81
+ }
82
+ else {
83
+ console.log(chalk.bold('\nAuxiliary Manifest Validation\n'));
84
+ console.log('━'.repeat(60));
85
+ console.log(chalk.bold('\nManifest:'));
86
+ console.log(chalk.gray(' • File:'), manifestPath);
87
+ console.log(chalk.gray(' • Areas:'), (manifest.areas || []).length);
88
+ if (violations.length > 0) {
89
+ console.log(chalk.bold('\nIssues:'));
90
+ console.log('━'.repeat(60));
91
+ for (const v of violations) {
92
+ const label = v.severity === 'error' ? chalk.red('error') : chalk.yellow('warning');
93
+ console.log(`\n${label}: ${v.message}`);
94
+ if (v.path)
95
+ console.log(chalk.gray(` Location: ${v.path}`));
96
+ if (v.impact)
97
+ console.log(chalk.gray(` Impact: ${v.impact}`));
98
+ if (v.suggestion)
99
+ console.log(chalk.cyan(` Suggestion: ${v.suggestion}`));
100
+ }
101
+ }
102
+ console.log(chalk.bold('\nSummary:'));
103
+ if (valid) {
104
+ console.log(chalk.green(' ✓ Auxiliary manifest is valid'));
105
+ }
106
+ else {
107
+ console.log(chalk.red(` ✗ ${errors.length} error(s)`));
108
+ }
109
+ if (warnings.length > 0) {
110
+ console.log(chalk.yellow(` ⚠ ${warnings.length} warning(s)`));
111
+ }
112
+ console.log();
113
+ }
114
+ if (!valid)
115
+ process.exit(1);
116
+ }
117
+ catch (error) {
118
+ console.error(chalk.red('Error:'), error.message);
119
+ process.exit(1);
120
+ }
121
+ });
122
+ return command;
123
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * collector check - Send a test trace to verify end-to-end connectivity
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function createCheckCommand(): Command;
6
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../src/commands/collector/check.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBpC,wBAAgB,kBAAkB,IAAI,OAAO,CAwK5C"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * collector check - Send a test trace to verify end-to-end connectivity
3
+ */
4
+ import { Command } from 'commander';
5
+ import chalk from 'chalk';
6
+ import { DEFAULT_COLLECTOR_PORT, checkHealth, getServiceStats, createTestTrace, sendTestTrace, } from './utils.js';
7
+ const DEFAULT_TEST_SERVICE = 'principal-cli-test';
8
+ export function createCheckCommand() {
9
+ const command = new Command('check');
10
+ command
11
+ .description('Send a test trace to verify collector connectivity')
12
+ .option('-p, --port <port>', `Collector port (default: ${DEFAULT_COLLECTOR_PORT})`)
13
+ .option('-s, --service <name>', `Service name for test trace (default: ${DEFAULT_TEST_SERVICE})`)
14
+ .option('--auth-token <token>', 'Bearer token if auth is required')
15
+ .option('--json', 'Output as JSON')
16
+ .action(async (options) => {
17
+ try {
18
+ const port = options.port ? parseInt(options.port, 10) : DEFAULT_COLLECTOR_PORT;
19
+ const serviceName = options.service || DEFAULT_TEST_SERVICE;
20
+ const endpoint = `http://localhost:${port}`;
21
+ const checks = {
22
+ health: { passed: false, latencyMs: 0, error: undefined },
23
+ sendTrace: {
24
+ passed: false,
25
+ traceId: undefined,
26
+ latencyMs: 0,
27
+ error: undefined,
28
+ },
29
+ verifyReceipt: {
30
+ passed: false,
31
+ foundInStats: false,
32
+ error: undefined,
33
+ },
34
+ };
35
+ const suggestions = [];
36
+ // Step 1: Health check
37
+ const healthStart = Date.now();
38
+ const health = await checkHealth(port);
39
+ checks.health.latencyMs = Date.now() - healthStart;
40
+ checks.health.passed = health !== null;
41
+ if (!checks.health.passed) {
42
+ checks.health.error = 'Collector not reachable';
43
+ suggestions.push(`Verify the collector is running on port ${port}`);
44
+ suggestions.push(`Try: curl ${endpoint}/health`);
45
+ }
46
+ // Step 2: Send test trace
47
+ if (checks.health.passed) {
48
+ const trace = createTestTrace(serviceName);
49
+ const traceId = trace.resourceSpans[0].scopeSpans[0].spans[0].traceId;
50
+ const result = await sendTestTrace(port, trace, options.authToken);
51
+ checks.sendTrace.passed = result.success;
52
+ checks.sendTrace.latencyMs = result.latencyMs;
53
+ checks.sendTrace.traceId = traceId;
54
+ if (!result.success) {
55
+ checks.sendTrace.error = result.error;
56
+ if (result.statusCode === 401) {
57
+ suggestions.push('The collector requires authentication.');
58
+ suggestions.push('Use --auth-token <token> to provide a Bearer token.');
59
+ }
60
+ else if (result.statusCode === 403) {
61
+ suggestions.push('Access forbidden. Check collector auth configuration.');
62
+ }
63
+ else {
64
+ suggestions.push(`Failed to send trace: ${result.error}`);
65
+ }
66
+ }
67
+ }
68
+ // Step 3: Verify trace was received
69
+ if (checks.sendTrace.passed) {
70
+ // Wait a moment for the trace to be processed
71
+ await new Promise((resolve) => setTimeout(resolve, 100));
72
+ const stats = await getServiceStats(port);
73
+ if (stats && stats.services[serviceName]) {
74
+ checks.verifyReceipt.passed = true;
75
+ checks.verifyReceipt.foundInStats = true;
76
+ }
77
+ else {
78
+ checks.verifyReceipt.passed = false;
79
+ checks.verifyReceipt.error = 'Trace not found in service stats';
80
+ suggestions.push('The trace was accepted but not stored.');
81
+ suggestions.push(`Service "${serviceName}" may not be in the allowlist.`);
82
+ suggestions.push('Check collector configuration for allowedServices setting.');
83
+ }
84
+ }
85
+ const overallPassed = checks.health.passed && checks.sendTrace.passed && checks.verifyReceipt.passed;
86
+ if (options.json) {
87
+ console.log(JSON.stringify({
88
+ checks,
89
+ endpoint: `${endpoint}/v1/traces`,
90
+ overallPassed,
91
+ suggestions,
92
+ }, null, 2));
93
+ }
94
+ else {
95
+ console.log(chalk.bold('\nCollector Connectivity Check'));
96
+ console.log('━'.repeat(60));
97
+ // Health check
98
+ const healthStatus = checks.health.passed
99
+ ? chalk.green('✓ healthy')
100
+ : chalk.red('✗ unreachable');
101
+ console.log(`\n 1. Health check.............. ${healthStatus}`);
102
+ // Send trace
103
+ if (checks.health.passed) {
104
+ const sendStatus = checks.sendTrace.passed
105
+ ? chalk.green(`✓ accepted`) +
106
+ chalk.gray(` (trace: ${checks.sendTrace.traceId?.slice(0, 8)}...)`)
107
+ : chalk.red(`✗ ${checks.sendTrace.error}`);
108
+ console.log(` 2. Sending test trace........ ${sendStatus}`);
109
+ }
110
+ else {
111
+ console.log(` 2. Sending test trace........ ${chalk.gray('─ skipped')}`);
112
+ }
113
+ // Verify receipt
114
+ if (checks.sendTrace.passed) {
115
+ const verifyStatus = checks.verifyReceipt.passed
116
+ ? chalk.green('✓ trace found in /services/stats')
117
+ : chalk.red('✗ trace not found');
118
+ console.log(` 3. Verifying receipt......... ${verifyStatus}`);
119
+ }
120
+ else {
121
+ console.log(` 3. Verifying receipt......... ${chalk.gray('─ skipped')}`);
122
+ }
123
+ // Latency
124
+ if (checks.sendTrace.passed) {
125
+ console.log(` 4. Roundtrip latency......... ${checks.sendTrace.latencyMs}ms`);
126
+ }
127
+ console.log('\n' + '━'.repeat(60));
128
+ if (overallPassed) {
129
+ console.log(chalk.green('✓ Collector is correctly configured and receiving traces.'));
130
+ console.log(chalk.gray(`\nYour client should send traces to:`));
131
+ console.log(` ${endpoint}/v1/traces`);
132
+ }
133
+ else {
134
+ if (suggestions.length > 0) {
135
+ console.log();
136
+ for (const suggestion of suggestions) {
137
+ console.log(chalk.yellow(` ${suggestion}`));
138
+ }
139
+ }
140
+ }
141
+ console.log();
142
+ }
143
+ if (!overallPassed) {
144
+ process.exit(1);
145
+ }
146
+ }
147
+ catch (error) {
148
+ console.error(chalk.red('Error:'), error.message);
149
+ process.exit(1);
150
+ }
151
+ });
152
+ return command;
153
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * collector diagnose - Comprehensive diagnostic for troubleshooting collector issues
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function createDiagnoseCommand(): Command;
6
+ //# sourceMappingURL=diagnose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnose.d.ts","sourceRoot":"","sources":["../../../src/commands/collector/diagnose.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgCpC,wBAAgB,qBAAqB,IAAI,OAAO,CAgQ/C"}