praetom 0.1.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 (102) hide show
  1. package/README.md +82 -0
  2. package/dist/_esm-loader.d.ts +49 -0
  3. package/dist/_esm-loader.d.ts.map +1 -0
  4. package/dist/_esm-loader.js +131 -0
  5. package/dist/_esm-loader.js.map +1 -0
  6. package/dist/_internal.d.ts +63 -0
  7. package/dist/_internal.d.ts.map +1 -0
  8. package/dist/_internal.js +357 -0
  9. package/dist/_internal.js.map +1 -0
  10. package/dist/browser.d.ts +90 -0
  11. package/dist/browser.d.ts.map +1 -0
  12. package/dist/browser.js +357 -0
  13. package/dist/browser.js.map +1 -0
  14. package/dist/cli/cli.d.ts +3 -0
  15. package/dist/cli/cli.d.ts.map +1 -0
  16. package/dist/cli/cli.js +97 -0
  17. package/dist/cli/cli.js.map +1 -0
  18. package/dist/cli/commands/discover.d.ts +3 -0
  19. package/dist/cli/commands/discover.d.ts.map +1 -0
  20. package/dist/cli/commands/discover.js +15 -0
  21. package/dist/cli/commands/discover.js.map +1 -0
  22. package/dist/cli/commands/features.d.ts +5 -0
  23. package/dist/cli/commands/features.d.ts.map +1 -0
  24. package/dist/cli/commands/features.js +83 -0
  25. package/dist/cli/commands/features.js.map +1 -0
  26. package/dist/cli/commands/init.d.ts +3 -0
  27. package/dist/cli/commands/init.d.ts.map +1 -0
  28. package/dist/cli/commands/init.js +52 -0
  29. package/dist/cli/commands/init.js.map +1 -0
  30. package/dist/cli/commands/login.d.ts +20 -0
  31. package/dist/cli/commands/login.d.ts.map +1 -0
  32. package/dist/cli/commands/login.js +138 -0
  33. package/dist/cli/commands/login.js.map +1 -0
  34. package/dist/cli/commands/logout.d.ts +3 -0
  35. package/dist/cli/commands/logout.d.ts.map +1 -0
  36. package/dist/cli/commands/logout.js +15 -0
  37. package/dist/cli/commands/logout.js.map +1 -0
  38. package/dist/cli/commands/rotate.d.ts +3 -0
  39. package/dist/cli/commands/rotate.d.ts.map +1 -0
  40. package/dist/cli/commands/rotate.js +33 -0
  41. package/dist/cli/commands/rotate.js.map +1 -0
  42. package/dist/cli/commands/status.d.ts +3 -0
  43. package/dist/cli/commands/status.d.ts.map +1 -0
  44. package/dist/cli/commands/status.js +54 -0
  45. package/dist/cli/commands/status.js.map +1 -0
  46. package/dist/cli/commands/uninstall.d.ts +3 -0
  47. package/dist/cli/commands/uninstall.d.ts.map +1 -0
  48. package/dist/cli/commands/uninstall.js +63 -0
  49. package/dist/cli/commands/uninstall.js.map +1 -0
  50. package/dist/cli/commands/usage.d.ts +3 -0
  51. package/dist/cli/commands/usage.d.ts.map +1 -0
  52. package/dist/cli/commands/usage.js +19 -0
  53. package/dist/cli/commands/usage.js.map +1 -0
  54. package/dist/cli/commands/whoami.d.ts +3 -0
  55. package/dist/cli/commands/whoami.d.ts.map +1 -0
  56. package/dist/cli/commands/whoami.js +37 -0
  57. package/dist/cli/commands/whoami.js.map +1 -0
  58. package/dist/cli/util/agent-env.d.ts +13 -0
  59. package/dist/cli/util/agent-env.d.ts.map +1 -0
  60. package/dist/cli/util/agent-env.js +28 -0
  61. package/dist/cli/util/agent-env.js.map +1 -0
  62. package/dist/cli/util/api.d.ts +36 -0
  63. package/dist/cli/util/api.d.ts.map +1 -0
  64. package/dist/cli/util/api.js +84 -0
  65. package/dist/cli/util/api.js.map +1 -0
  66. package/dist/cli/util/auth-file.d.ts +25 -0
  67. package/dist/cli/util/auth-file.d.ts.map +1 -0
  68. package/dist/cli/util/auth-file.js +74 -0
  69. package/dist/cli/util/auth-file.js.map +1 -0
  70. package/dist/cli/util/git.d.ts +28 -0
  71. package/dist/cli/util/git.d.ts.map +1 -0
  72. package/dist/cli/util/git.js +103 -0
  73. package/dist/cli/util/git.js.map +1 -0
  74. package/dist/cli/util/run.d.ts +26 -0
  75. package/dist/cli/util/run.d.ts.map +1 -0
  76. package/dist/cli/util/run.js +31 -0
  77. package/dist/cli/util/run.js.map +1 -0
  78. package/dist/edge.d.ts +34 -0
  79. package/dist/edge.d.ts.map +1 -0
  80. package/dist/edge.js +127 -0
  81. package/dist/edge.js.map +1 -0
  82. package/dist/server.d.ts +69 -0
  83. package/dist/server.d.ts.map +1 -0
  84. package/dist/server.js +193 -0
  85. package/dist/server.js.map +1 -0
  86. package/dist/vite/index.d.ts +48 -0
  87. package/dist/vite/index.d.ts.map +1 -0
  88. package/dist/vite/index.js +138 -0
  89. package/dist/vite/index.js.map +1 -0
  90. package/dist/webpack/index.d.ts +64 -0
  91. package/dist/webpack/index.d.ts.map +1 -0
  92. package/dist/webpack/index.js +106 -0
  93. package/dist/webpack/index.js.map +1 -0
  94. package/dist/webpack/loader.d.ts +27 -0
  95. package/dist/webpack/loader.d.ts.map +1 -0
  96. package/dist/webpack/loader.js +54 -0
  97. package/dist/webpack/loader.js.map +1 -0
  98. package/dist/webpack/shared.d.ts +25 -0
  99. package/dist/webpack/shared.d.ts.map +1 -0
  100. package/dist/webpack/shared.js +63 -0
  101. package/dist/webpack/shared.js.map +1 -0
  102. package/package.json +79 -0
@@ -0,0 +1,357 @@
1
+ /**
2
+ * praetom — client-side customer API.
3
+ *
4
+ * Two exports, mirroring /server:
5
+ * - register({ ingestId }) — call once at boot (root layout / entry)
6
+ * - emit(eventName, payload?) — point-in-time event from business logic
7
+ *
8
+ * // In a Next.js root layout or _app.tsx:
9
+ * import { register } from "praetom";
10
+ * register({ ingestId: "praetom_..." }); // DSN-style, public OK
11
+ *
12
+ * // Inside a component's interaction handler:
13
+ * import { emit } from "praetom";
14
+ * <button onClick={() => {
15
+ * emit("checkout:button-clicked");
16
+ * submit();
17
+ * }} />
18
+ *
19
+ * Auto-instrumentation: praetom's DB names the components that count
20
+ * as feature entry points. The praetom/vite (and webpack/rollup
21
+ * variants to follow) read the same config at build time and inject the
22
+ * wrap automatically — no source-level feature() calls in customer code.
23
+ *
24
+ * v1 internals:
25
+ * • No native AsyncLocalStorage → module-level "current feature" stack.
26
+ * Safe for single-threaded JS in the common case (one user action =
27
+ * one in-flight feature). Concurrent features in true parallel (e.g.
28
+ * two Promise.all-ed unrelated wraps) may attribute fetches to
29
+ * whichever wrap was entered last; accepted for v1.
30
+ * • Wire shape mirrors the server: OTLP/JSON via beacon on page hide,
31
+ * or via fetch on interval flush. Same trace context propagation via
32
+ * W3C traceparent.
33
+ */
34
+ const DEFAULT_OTLP_ENDPOINT = "https://praetom.com/api/otlp/v1/traces";
35
+ const DEFAULT_CONFIG_ENDPOINT = "https://praetom.com/api/runtime/config";
36
+ const FLUSH_INTERVAL_MS = 5_000;
37
+ const FLUSH_BATCH_SIZE = 50;
38
+ let _config = null;
39
+ let _featureMap = [];
40
+ const _stack = [];
41
+ let _buffer = [];
42
+ let _flushTimer = null;
43
+ let _fetchPatched = false;
44
+ export async function register(opts) {
45
+ const silent = opts.silent ?? false;
46
+ const warn = silent
47
+ ? () => { }
48
+ : (msg) => {
49
+ // eslint-disable-next-line no-console
50
+ console.warn(`[praetom] ${msg}`);
51
+ };
52
+ if (!opts.ingestId) {
53
+ warn("register() called without ingestId; instrumentation disabled");
54
+ return;
55
+ }
56
+ _config = {
57
+ ingestId: opts.ingestId,
58
+ endpoint: opts.endpoint ?? DEFAULT_OTLP_ENDPOINT,
59
+ configEndpoint: opts.configEndpoint ?? DEFAULT_CONFIG_ENDPOINT,
60
+ silent,
61
+ };
62
+ const repo = resolveRepo(opts.repo);
63
+ if (!repo) {
64
+ warn("could not detect repo; pass repo to register() or set data-praetom-repo on <script>");
65
+ return;
66
+ }
67
+ try {
68
+ const res = await fetch(`${_config.configEndpoint}?repo=${encodeURIComponent(repo)}`, { headers: { authorization: `Bearer ${_config.ingestId}` } });
69
+ if (!res.ok) {
70
+ warn(`runtime/config fetch failed: HTTP ${res.status}`);
71
+ return;
72
+ }
73
+ const data = (await res.json());
74
+ _featureMap = data.features ?? [];
75
+ }
76
+ catch (e) {
77
+ warn(`runtime/config fetch error: ${e.message}`);
78
+ return;
79
+ }
80
+ patchFetch();
81
+ installFlushHooks();
82
+ }
83
+ function resolveRepo(override) {
84
+ if (override)
85
+ return override;
86
+ if (typeof document !== "undefined") {
87
+ const el = document.currentScript;
88
+ if (el?.dataset.praetomRepo)
89
+ return el.dataset.praetomRepo;
90
+ const tag = document.querySelector("[data-praetom-repo]");
91
+ if (tag?.dataset.praetomRepo)
92
+ return tag.dataset.praetomRepo;
93
+ }
94
+ return null;
95
+ }
96
+ /**
97
+ * Internal — wrap a callback as a feature entry point. NOT a public
98
+ * export. The bundler plugin (`praetom/vite` and friends)
99
+ * generates code that calls this around the entry symbols praetom's
100
+ * DB names. Customer source code does not contain feature() calls.
101
+ */
102
+ async function feature(slug, fn) {
103
+ const ctx = {
104
+ traceId: randHex(16),
105
+ spanId: randHex(8),
106
+ slug,
107
+ };
108
+ const startMs = Date.now();
109
+ _stack.push(ctx);
110
+ try {
111
+ const result = await fn();
112
+ record(ctx, null, startMs, false);
113
+ return result;
114
+ }
115
+ catch (e) {
116
+ record(ctx, null, startMs, true);
117
+ throw e;
118
+ }
119
+ finally {
120
+ const i = _stack.lastIndexOf(ctx);
121
+ if (i >= 0)
122
+ _stack.splice(i, 1);
123
+ }
124
+ }
125
+ /**
126
+ * Fire a point-in-time event tagged with the current feature context
127
+ * if one exists. Use inside component code to mark interactions,
128
+ * business events, or latency-relevant moments that the entry-point
129
+ * wrap doesn't capture.
130
+ */
131
+ export function emit(eventName, payload) {
132
+ if (!_config)
133
+ return;
134
+ const ctx = currentContext();
135
+ const now = Date.now();
136
+ const attrs = payload
137
+ ? Object.fromEntries(Object.entries(payload)
138
+ .filter(([, v]) => v != null)
139
+ .map(([k, v]) => [k, typeof v === "string" ? v : JSON.stringify(v)]))
140
+ : undefined;
141
+ _buffer.push({
142
+ featureSlug: ctx?.slug ?? eventName,
143
+ traceId: ctx?.traceId ?? randHex(16),
144
+ spanId: randHex(8),
145
+ parentSpanId: ctx?.spanId ?? null,
146
+ startMs: now,
147
+ endMs: now,
148
+ isError: false,
149
+ name: eventName,
150
+ attributes: attrs,
151
+ });
152
+ if (_buffer.length >= FLUSH_BATCH_SIZE) {
153
+ void flushNow();
154
+ return;
155
+ }
156
+ if (!_flushTimer) {
157
+ _flushTimer = setTimeout(() => {
158
+ _flushTimer = null;
159
+ void flushNow();
160
+ }, FLUSH_INTERVAL_MS);
161
+ }
162
+ }
163
+ /**
164
+ * Internal escape hatch for the bundler plugin's generated code. NOT
165
+ * a public export. Exported under an underscored name so the build-
166
+ * tool plugin can import it without polluting the customer-facing
167
+ * surface. May be removed once the plugin codegen stabilizes.
168
+ */
169
+ export const __praetomFeature = feature;
170
+ /**
171
+ * Browser counterpart of the server's `__praetomWrapEntryPoint`. Same
172
+ * shape so the bundler plugin can emit a single `__praetomWrapEntryPoint`
173
+ * call regardless of build layer; browser ignores `entryName` since
174
+ * there's no HTTP request context to continue a trace from.
175
+ */
176
+ export function __praetomWrapEntryPoint(slug, _entryName, original) {
177
+ const wrapped = function (...args) {
178
+ return feature(slug, async () => {
179
+ const result = original.apply(this, args);
180
+ return result instanceof Promise ? result : Promise.resolve(result);
181
+ });
182
+ };
183
+ Object.defineProperty(wrapped, "name", { value: _entryName });
184
+ return wrapped;
185
+ }
186
+ function currentContext() {
187
+ return _stack.length > 0 ? _stack[_stack.length - 1] : null;
188
+ }
189
+ function record(ctx, parentSpanId, startMs, isError) {
190
+ if (!_config)
191
+ return;
192
+ _buffer.push({
193
+ featureSlug: ctx.slug,
194
+ traceId: ctx.traceId,
195
+ spanId: ctx.spanId,
196
+ parentSpanId,
197
+ startMs,
198
+ endMs: Date.now(),
199
+ isError,
200
+ });
201
+ if (_buffer.length >= FLUSH_BATCH_SIZE) {
202
+ void flushNow();
203
+ return;
204
+ }
205
+ if (!_flushTimer) {
206
+ _flushTimer = setTimeout(() => {
207
+ _flushTimer = null;
208
+ void flushNow();
209
+ }, FLUSH_INTERVAL_MS);
210
+ }
211
+ }
212
+ function patchFetch() {
213
+ if (_fetchPatched)
214
+ return;
215
+ if (typeof globalThis.fetch !== "function")
216
+ return;
217
+ const original = globalThis.fetch.bind(globalThis);
218
+ globalThis.fetch = ((input, init) => {
219
+ const ctx = currentContext();
220
+ if (!ctx)
221
+ return original(input, init);
222
+ const headers = new Headers(init?.headers ?? {});
223
+ if (!headers.has("traceparent")) {
224
+ headers.set("traceparent", `00-${ctx.traceId}-${ctx.spanId}-01`);
225
+ }
226
+ return original(input, { ...init, headers });
227
+ });
228
+ _fetchPatched = true;
229
+ }
230
+ function installFlushHooks() {
231
+ if (typeof window === "undefined")
232
+ return;
233
+ // sendBeacon on page hide is the right primitive for in-flight spans.
234
+ window.addEventListener("pagehide", () => {
235
+ flushViaBeacon();
236
+ });
237
+ window.addEventListener("visibilitychange", () => {
238
+ if (document.visibilityState === "hidden") {
239
+ flushViaBeacon();
240
+ }
241
+ });
242
+ }
243
+ function flushViaBeacon() {
244
+ if (!_config)
245
+ return;
246
+ if (_buffer.length === 0)
247
+ return;
248
+ if (typeof navigator === "undefined" || typeof navigator.sendBeacon !== "function") {
249
+ void flushNow();
250
+ return;
251
+ }
252
+ const spans = _buffer;
253
+ _buffer = [];
254
+ const body = JSON.stringify(encodeOtlp(spans));
255
+ const blob = new Blob([body], { type: "application/json" });
256
+ // sendBeacon doesn't let us set Authorization. We pass the ingest ID
257
+ // as a query parameter for beacon flushes only; the receiver accepts
258
+ // both header and query forms (handled in a follow-up to the OTLP
259
+ // route — until that ships, beacon flushes may be dropped at the
260
+ // edge. flushNow() with fetch+Authorization still works as the
261
+ // primary path; beacon is the unload fallback.)
262
+ const url = `${_config.endpoint}?ingest=${encodeURIComponent(_config.ingestId)}`;
263
+ navigator.sendBeacon(url, blob);
264
+ }
265
+ async function flushNow() {
266
+ if (!_config)
267
+ return;
268
+ if (_buffer.length === 0)
269
+ return;
270
+ const spans = _buffer;
271
+ _buffer = [];
272
+ const body = encodeOtlp(spans);
273
+ try {
274
+ await fetch(_config.endpoint, {
275
+ method: "POST",
276
+ headers: {
277
+ "content-type": "application/json",
278
+ authorization: `Bearer ${_config.ingestId}`,
279
+ },
280
+ body: JSON.stringify(body),
281
+ keepalive: true,
282
+ });
283
+ }
284
+ catch {
285
+ // network error — drop, same as server side.
286
+ }
287
+ }
288
+ function randHex(bytes) {
289
+ // Web Crypto API is widely supported; fall back to Math.random for
290
+ // hyper-old environments (tracing IDs only — not cryptographically
291
+ // sensitive in the DSN-low-trust model).
292
+ if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
293
+ const arr = new Uint8Array(bytes);
294
+ crypto.getRandomValues(arr);
295
+ return [...arr].map((b) => b.toString(16).padStart(2, "0")).join("");
296
+ }
297
+ let out = "";
298
+ for (let i = 0; i < bytes; i++) {
299
+ out += Math.floor(Math.random() * 256)
300
+ .toString(16)
301
+ .padStart(2, "0");
302
+ }
303
+ return out;
304
+ }
305
+ function encodeOtlp(spans) {
306
+ return {
307
+ resourceSpans: [
308
+ {
309
+ scopeSpans: [
310
+ {
311
+ scope: { name: "praetom", version: "0.4.0" },
312
+ spans: spans.map((s) => {
313
+ const attrs = [
314
+ { key: "praetom.feature", value: { stringValue: s.featureSlug } },
315
+ ];
316
+ if (s.attributes) {
317
+ for (const [k, v] of Object.entries(s.attributes)) {
318
+ attrs.push({ key: k, value: { stringValue: v } });
319
+ }
320
+ }
321
+ return {
322
+ traceId: s.traceId,
323
+ spanId: s.spanId,
324
+ parentSpanId: s.parentSpanId ?? undefined,
325
+ name: s.name ?? s.featureSlug,
326
+ kind: 3, // SPAN_KIND_CLIENT — browser-initiated
327
+ startTimeUnixNano: `${s.startMs}000000`,
328
+ endTimeUnixNano: `${s.endMs}000000`,
329
+ attributes: attrs,
330
+ status: { code: s.isError ? 2 : 1 },
331
+ };
332
+ }),
333
+ },
334
+ ],
335
+ },
336
+ ],
337
+ };
338
+ }
339
+ /**
340
+ * Test-only — reset module state between tests.
341
+ */
342
+ export function _resetForTests() {
343
+ _config = null;
344
+ _featureMap = [];
345
+ _stack.length = 0;
346
+ _buffer = [];
347
+ _flushTimer = null;
348
+ _fetchPatched = false;
349
+ }
350
+ /**
351
+ * Read the current feature map. Useful for v1.5 bundler-plugin work
352
+ * where the plugin asks the runtime which paths to wrap.
353
+ */
354
+ export function getFeatureMap() {
355
+ return _featureMap;
356
+ }
357
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { initCommand } from "./commands/init.js";
4
+ import { loginCommand } from "./commands/login.js";
5
+ import { logoutCommand } from "./commands/logout.js";
6
+ import { whoamiCommand } from "./commands/whoami.js";
7
+ import { statusCommand } from "./commands/status.js";
8
+ import { usageCommand } from "./commands/usage.js";
9
+ import { featuresAddCommand, featuresListCommand, featuresShowCommand, } from "./commands/features.js";
10
+ import { rotateCommand } from "./commands/rotate.js";
11
+ import { uninstallCommand } from "./commands/uninstall.js";
12
+ import { discoverCommand } from "./commands/discover.js";
13
+ import { detectAgent } from "./util/agent-env.js";
14
+ import { runCommand } from "./util/run.js";
15
+ const program = new Command();
16
+ program
17
+ .name("praetom")
18
+ .description("Install praetom into a repository, manage features, rotate ingest tokens.")
19
+ .version("0.1.0", "-v, --version")
20
+ .option("--workspace <slug>", "override the workspace")
21
+ .option("--repo <owner/name>", "override the repository")
22
+ .option("--json", "machine-readable output (auto-enabled when invoked from an AI coding agent)")
23
+ .option("--non-interactive", "fail instead of prompting; for automation");
24
+ program
25
+ .command("init")
26
+ .description("Authenticate, connect the current repository, open the install pull request.")
27
+ .action(() => runCommand(program, initCommand));
28
+ program
29
+ .command("login")
30
+ .description("Open a browser to authenticate this terminal session.")
31
+ .action(() => runCommand(program, loginCommand));
32
+ program
33
+ .command("logout")
34
+ .description("Clear the local authentication artifact.")
35
+ .action(() => runCommand(program, logoutCommand));
36
+ program
37
+ .command("whoami")
38
+ .description("Print the currently authenticated user.")
39
+ .action(() => runCommand(program, whoamiCommand));
40
+ program
41
+ .command("status")
42
+ .description("Show the install lifecycle for the current repository.")
43
+ .action(() => runCommand(program, statusCommand));
44
+ program
45
+ .command("usage")
46
+ .description("Workspace usage — span volume, discovery runs, MCP calls.")
47
+ .action(() => runCommand(program, usageCommand));
48
+ const features = program
49
+ .command("features")
50
+ .description("Manage features in this workspace.");
51
+ features
52
+ .command("list")
53
+ .description("List features defined in the workspace.")
54
+ .action(() => runCommand(program, featuresListCommand));
55
+ features
56
+ .command("add <name>")
57
+ .description("Create a feature; opens an editor for the description.")
58
+ .action((name) => runCommand(program, (ctx) => featuresAddCommand(ctx, name)));
59
+ features
60
+ .command("show <slug>")
61
+ .description("Full detail for a feature.")
62
+ .action((slug) => runCommand(program, (ctx) => featuresShowCommand(ctx, slug)));
63
+ program
64
+ .command("rotate")
65
+ .description("Rotate the per-repository ingest token; opens a pull request swapping it in.")
66
+ .action(() => runCommand(program, rotateCommand));
67
+ program
68
+ .command("uninstall")
69
+ .description("Open a pull request removing praetom wiring; revoke the per-repository token.")
70
+ .action(() => runCommand(program, uninstallCommand));
71
+ program
72
+ .command("discover")
73
+ .description("Run feature discovery on the current repository.")
74
+ .action(() => runCommand(program, discoverCommand));
75
+ // Agent auto-detection: flip --json on by default when running inside one of
76
+ // the known AI coding agents, so the agent gets parseable output without the
77
+ // user having to pass the flag.
78
+ const agent = detectAgent();
79
+ if (agent) {
80
+ const opts = program.opts();
81
+ if (opts["json"] === undefined)
82
+ opts["json"] = true;
83
+ if (opts["nonInteractive"] === undefined)
84
+ opts["nonInteractive"] = true;
85
+ }
86
+ program.parseAsync(process.argv).catch((err) => {
87
+ const msg = err instanceof Error ? err.message : String(err);
88
+ const opts = program.opts();
89
+ if (opts.json) {
90
+ process.stdout.write(JSON.stringify({ ok: false, error: msg }) + "\n");
91
+ }
92
+ else {
93
+ process.stderr.write(`praetom: ${msg}\n`);
94
+ }
95
+ process.exit(1);
96
+ });
97
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { RunContext } from "../util/run.js";
2
+ export declare function discoverCommand(ctx: RunContext): void;
3
+ //# sourceMappingURL=discover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/discover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAgB,eAAe,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAerD"}
@@ -0,0 +1,15 @@
1
+ export function discoverCommand(ctx) {
2
+ const message = "praetom discover isn't implemented yet (v0.1). " +
3
+ "Run discovery via your AI coding agent today: praetom's MCP plugin exposes " +
4
+ "`start_discovery` and `accept_discovery_candidates`. From Claude Code, that " +
5
+ "looks like: `@praetom map this repository` then `accept all` once the " +
6
+ "candidates list streams in.";
7
+ if (ctx.json) {
8
+ process.stdout.write(JSON.stringify({ ok: false, error: "not_implemented", command: "discover" }) + "\n");
9
+ }
10
+ else {
11
+ process.stderr.write(`${message}\n`);
12
+ }
13
+ process.exit(2);
14
+ }
15
+ //# sourceMappingURL=discover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.js","sourceRoot":"","sources":["../../../src/cli/commands/discover.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAAC,GAAe;IAC7C,MAAM,OAAO,GACX,iDAAiD;QACjD,6EAA6E;QAC7E,8EAA8E;QAC9E,wEAAwE;QACxE,6BAA6B,CAAC;IAChC,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,GAAG,IAAI,CACpF,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { RunContext } from "../util/run.js";
2
+ export declare function featuresListCommand(ctx: RunContext): Promise<void>;
3
+ export declare function featuresShowCommand(ctx: RunContext, slug: string): Promise<void>;
4
+ export declare function featuresAddCommand(ctx: RunContext, name: string): Promise<void>;
5
+ //# sourceMappingURL=features.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/features.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAkCjD,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BxE;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,UAAU,EACf,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,UAAU,EACf,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CA4Cf"}
@@ -0,0 +1,83 @@
1
+ import { createInterface } from "node:readline/promises";
2
+ import { apiRequest, workspaceQuery } from "../util/api.js";
3
+ export async function featuresListCommand(ctx) {
4
+ const res = await apiRequest("/api/cli/features", {
5
+ query: workspaceQuery(ctx),
6
+ });
7
+ if (ctx.json) {
8
+ process.stdout.write(JSON.stringify(res) + "\n");
9
+ return;
10
+ }
11
+ if (res.count === 0) {
12
+ process.stdout.write(`No features in ${res.workspaceSlug} yet.\n`);
13
+ return;
14
+ }
15
+ process.stdout.write(`${res.count} feature(s) in ${res.workspaceSlug}:\n\n`);
16
+ for (const f of res.features) {
17
+ const tags = [];
18
+ if (f.instrumentationScore)
19
+ tags.push(`${Math.round(f.instrumentationScore.score * 100)}% instrumented`);
20
+ if (f.activitySignal?.commits_30d != null)
21
+ tags.push(`${f.activitySignal.commits_30d} commits/30d`);
22
+ if (f.criticVerdict)
23
+ tags.push(f.criticVerdict);
24
+ process.stdout.write(` ${f.slug.padEnd(28)} ${f.event}\n`);
25
+ if (tags.length > 0)
26
+ process.stdout.write(` ${" ".repeat(28)} ${tags.join(" · ")}\n`);
27
+ }
28
+ }
29
+ export async function featuresShowCommand(ctx, slug) {
30
+ const res = await apiRequest(`/api/cli/features/${encodeURIComponent(slug)}`, { query: workspaceQuery(ctx) });
31
+ if (ctx.json) {
32
+ process.stdout.write(JSON.stringify(res) + "\n");
33
+ return;
34
+ }
35
+ const f = res.feature;
36
+ process.stdout.write(`${f.slug} (workspace: ${res.workspaceSlug})\n` +
37
+ `${"─".repeat(60)}\n\n` +
38
+ `${f.plainEnglish}\n\n` +
39
+ `created ${f.createdAt}\n` +
40
+ (f.signalsRefreshedAt ? `signals ${f.signalsRefreshedAt}\n` : "") +
41
+ (f.criticVerdict ? `verdict ${f.criticVerdict}\n` : "") +
42
+ (f.criticCritique ? `\ncritique:\n ${f.criticCritique}\n` : ""));
43
+ }
44
+ export async function featuresAddCommand(ctx, name) {
45
+ const slug = name.trim().toLowerCase();
46
+ if (!/^[a-z][a-z0-9-_]*$/.test(slug)) {
47
+ fail(ctx, "slug must start with a letter and contain only lowercase letters, digits, hyphens, or underscores");
48
+ }
49
+ if (ctx.nonInteractive) {
50
+ fail(ctx, "praetom features add: --non-interactive set; cannot prompt for description. Use the dashboard for now.");
51
+ }
52
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
53
+ process.stdout.write(`Creating feature \`${slug}\`. Press enter to skip optional fields.\n\n`);
54
+ const event = (await rl.question("Event (one sentence — what happens): ")).trim();
55
+ if (!event) {
56
+ rl.close();
57
+ fail(ctx, "event is required");
58
+ }
59
+ const description = (await rl.question("Description (optional): ")).trim();
60
+ const healthy = (await rl.question("Healthy (optional): ")).trim();
61
+ const incident = (await rl.question("Incident (optional): ")).trim();
62
+ rl.close();
63
+ const result = await apiRequest("/api/cli/features", {
64
+ method: "POST",
65
+ body: { slug, event, description, healthy, incident },
66
+ query: workspaceQuery(ctx),
67
+ });
68
+ if (ctx.json) {
69
+ process.stdout.write(JSON.stringify(result) + "\n");
70
+ return;
71
+ }
72
+ process.stdout.write(`\nCreated feature \`${result.slug}\`.\n`);
73
+ }
74
+ function fail(ctx, message) {
75
+ if (ctx.json) {
76
+ process.stdout.write(JSON.stringify({ ok: false, error: message }) + "\n");
77
+ }
78
+ else {
79
+ process.stderr.write(`${message}\n`);
80
+ }
81
+ process.exit(1);
82
+ }
83
+ //# sourceMappingURL=features.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features.js","sourceRoot":"","sources":["../../../src/cli/commands/features.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { RunContext } from "../util/run.js";
2
+ export declare function initCommand(ctx: RunContext): Promise<void>;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAYjD,wBAAsB,WAAW,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAmDhE"}