@productbrain/cli 0.1.0-beta.1440 → 0.1.0-beta.1470

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 (64) hide show
  1. package/README.md +1 -0
  2. package/dist/__tests__/audit.test.js +16 -0
  3. package/dist/__tests__/audit.test.js.map +1 -1
  4. package/dist/__tests__/method-publish-coherency.test.d.ts +9 -0
  5. package/dist/__tests__/method-publish-coherency.test.d.ts.map +1 -0
  6. package/dist/__tests__/method-publish-coherency.test.js +71 -0
  7. package/dist/__tests__/method-publish-coherency.test.js.map +1 -0
  8. package/dist/__tests__/promote.test.js +91 -3
  9. package/dist/__tests__/promote.test.js.map +1 -1
  10. package/dist/commands/audit.d.ts.map +1 -1
  11. package/dist/commands/audit.js +9 -1
  12. package/dist/commands/audit.js.map +1 -1
  13. package/dist/commands/method.d.ts.map +1 -1
  14. package/dist/commands/method.js +10 -1
  15. package/dist/commands/method.js.map +1 -1
  16. package/dist/commands/orient.d.ts +6 -0
  17. package/dist/commands/orient.d.ts.map +1 -1
  18. package/dist/commands/orient.js.map +1 -1
  19. package/dist/commands/promote.d.ts +8 -0
  20. package/dist/commands/promote.d.ts.map +1 -1
  21. package/dist/commands/promote.js +36 -3
  22. package/dist/commands/promote.js.map +1 -1
  23. package/dist/commands/scoreboard.d.ts +28 -0
  24. package/dist/commands/scoreboard.d.ts.map +1 -0
  25. package/dist/commands/scoreboard.js +40 -0
  26. package/dist/commands/scoreboard.js.map +1 -0
  27. package/dist/commands/update.d.ts +8 -0
  28. package/dist/commands/update.d.ts.map +1 -1
  29. package/dist/commands/update.js +26 -0
  30. package/dist/commands/update.js.map +1 -1
  31. package/dist/formatters/orient.d.ts +34 -0
  32. package/dist/formatters/orient.d.ts.map +1 -1
  33. package/dist/formatters/orient.js +39 -0
  34. package/dist/formatters/orient.js.map +1 -1
  35. package/dist/formatters/promote.d.ts +5 -0
  36. package/dist/formatters/promote.d.ts.map +1 -1
  37. package/dist/formatters/promote.js +7 -0
  38. package/dist/formatters/promote.js.map +1 -1
  39. package/dist/formatters/scoreboard.d.ts +11 -0
  40. package/dist/formatters/scoreboard.d.ts.map +1 -0
  41. package/dist/formatters/scoreboard.js +48 -0
  42. package/dist/formatters/scoreboard.js.map +1 -0
  43. package/dist/index.js +28 -1
  44. package/dist/index.js.map +1 -1
  45. package/dist/lib/client.d.ts.map +1 -1
  46. package/dist/lib/client.js +2 -0
  47. package/dist/lib/client.js.map +1 -1
  48. package/dist/scoreboard/diagnose.d.ts +182 -0
  49. package/dist/scoreboard/diagnose.d.ts.map +1 -0
  50. package/dist/scoreboard/diagnose.js +250 -0
  51. package/dist/scoreboard/diagnose.js.map +1 -0
  52. package/dist/scoreboard/diagnose.test.d.ts +12 -0
  53. package/dist/scoreboard/diagnose.test.d.ts.map +1 -0
  54. package/dist/scoreboard/diagnose.test.js +192 -0
  55. package/dist/scoreboard/diagnose.test.js.map +1 -0
  56. package/dist/scoreboard/localDrift.d.ts +23 -0
  57. package/dist/scoreboard/localDrift.d.ts.map +1 -0
  58. package/dist/scoreboard/localDrift.js +111 -0
  59. package/dist/scoreboard/localDrift.js.map +1 -0
  60. package/dist/scoreboard/localDrift.test.d.ts +9 -0
  61. package/dist/scoreboard/localDrift.test.d.ts.map +1 -0
  62. package/dist/scoreboard/localDrift.test.js +82 -0
  63. package/dist/scoreboard/localDrift.test.js.map +1 -0
  64. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnose.test.js","sourceRoot":"","sources":["../../src/scoreboard/diagnose.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Flywheel scoreboard M5 — LOCAL-PULL drift, computed at the CLI (DEC-1284).
3
+ *
4
+ * The data layer deliberately exposes only the SERVER-side projection-generation time
5
+ * (`materialization.latestMaterializedAt`) — a Convex query cannot stat the worktree's files
6
+ * (DEC-1284). The TRUE M5 the spec asks for is LOCAL-pull staleness: how far the agent's pulled
7
+ * `.productbrain/` projection lags the server projection (or its absolute age). Only the CLI can
8
+ * compute it, by stat-ing the local projection files' mtime. This module is that computation.
9
+ *
10
+ * Fail-soft: if `.productbrain/` is absent or no projection files are found, returns an
11
+ * `unavailableReason` so the diagnosis layer renders `unmeasured` — NEVER a fake `ok`.
12
+ */
13
+ import type { LocalDriftM5 } from './diagnose.js';
14
+ /**
15
+ * computeLocalDrift — the M5 local-pull drift (A5).
16
+ *
17
+ * @param serverMaterializedAt the data layer's `materialization.latestMaterializedAt` (ms epoch,
18
+ * or null when the workspace never materialized server-side).
19
+ * @param now injectable clock for tests (defaults to Date.now()).
20
+ * @param startDir injectable start dir for tests (defaults to process.cwd()).
21
+ */
22
+ export declare function computeLocalDrift(serverMaterializedAt: number | null, now?: number, startDir?: string): LocalDriftM5;
23
+ //# sourceMappingURL=localDrift.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localDrift.d.ts","sourceRoot":"","sources":["../../src/scoreboard/localDrift.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAwClD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,oBAAoB,EAAE,MAAM,GAAG,IAAI,EACnC,GAAG,GAAE,MAAmB,EACxB,QAAQ,GAAE,MAAsB,GAC/B,YAAY,CAkDd"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Flywheel scoreboard M5 — LOCAL-PULL drift, computed at the CLI (DEC-1284).
3
+ *
4
+ * The data layer deliberately exposes only the SERVER-side projection-generation time
5
+ * (`materialization.latestMaterializedAt`) — a Convex query cannot stat the worktree's files
6
+ * (DEC-1284). The TRUE M5 the spec asks for is LOCAL-pull staleness: how far the agent's pulled
7
+ * `.productbrain/` projection lags the server projection (or its absolute age). Only the CLI can
8
+ * compute it, by stat-ing the local projection files' mtime. This module is that computation.
9
+ *
10
+ * Fail-soft: if `.productbrain/` is absent or no projection files are found, returns an
11
+ * `unavailableReason` so the diagnosis layer renders `unmeasured` — NEVER a fake `ok`.
12
+ */
13
+ import { existsSync, statSync, readdirSync } from 'fs';
14
+ import { resolve } from 'path';
15
+ import { findProjectRoot } from '../lib/config.js';
16
+ /**
17
+ * The `pb handshake`-written projection files whose mtime tracks the local pull. These are the
18
+ * gitignored projections regenerated per worktree (context.md / briefing.md / generated/). We
19
+ * take the NEWEST mtime across whatever projection files exist — that is the most recent pull.
20
+ * `config.json` is excluded: it is committed + static, not a projection, so it never reflects a
21
+ * handshake pull.
22
+ */
23
+ const PROJECTION_FILES = ['context.md', 'briefing.md'];
24
+ const PROJECTION_DIRS = ['generated', 'rules'];
25
+ /** Newest mtime (ms) across a set of candidate paths, or null if none exist. */
26
+ function newestMtime(paths) {
27
+ let newest = null;
28
+ for (const p of paths) {
29
+ try {
30
+ if (!existsSync(p))
31
+ continue;
32
+ const st = statSync(p);
33
+ const mtime = st.mtimeMs;
34
+ if (newest === null || mtime > newest)
35
+ newest = mtime;
36
+ }
37
+ catch {
38
+ // unreadable path — skip, fail-soft
39
+ }
40
+ }
41
+ return newest;
42
+ }
43
+ /** Collect file paths one level deep inside a projection directory. */
44
+ function filesInDir(dir) {
45
+ try {
46
+ if (!existsSync(dir))
47
+ return [];
48
+ return readdirSync(dir, { withFileTypes: true })
49
+ .filter((e) => e.isFile())
50
+ .map((e) => resolve(dir, e.name));
51
+ }
52
+ catch {
53
+ return [];
54
+ }
55
+ }
56
+ /**
57
+ * computeLocalDrift — the M5 local-pull drift (A5).
58
+ *
59
+ * @param serverMaterializedAt the data layer's `materialization.latestMaterializedAt` (ms epoch,
60
+ * or null when the workspace never materialized server-side).
61
+ * @param now injectable clock for tests (defaults to Date.now()).
62
+ * @param startDir injectable start dir for tests (defaults to process.cwd()).
63
+ */
64
+ export function computeLocalDrift(serverMaterializedAt, now = Date.now(), startDir = process.cwd()) {
65
+ const projectRoot = findProjectRoot(startDir);
66
+ if (!projectRoot) {
67
+ return {
68
+ localProjectionMtime: null,
69
+ serverMaterializedAt,
70
+ localLagMs: null,
71
+ localAgeMs: null,
72
+ unavailableReason: 'no .productbrain/ project root found (walked up from CWD)',
73
+ };
74
+ }
75
+ const pbDir = resolve(projectRoot, '.productbrain');
76
+ if (!existsSync(pbDir)) {
77
+ return {
78
+ localProjectionMtime: null,
79
+ serverMaterializedAt,
80
+ localLagMs: null,
81
+ localAgeMs: null,
82
+ unavailableReason: `.productbrain/ missing at ${projectRoot}`,
83
+ };
84
+ }
85
+ const candidatePaths = [
86
+ ...PROJECTION_FILES.map((f) => resolve(pbDir, f)),
87
+ ...PROJECTION_DIRS.flatMap((d) => filesInDir(resolve(pbDir, d))),
88
+ ];
89
+ const localProjectionMtime = newestMtime(candidatePaths);
90
+ if (localProjectionMtime === null) {
91
+ return {
92
+ localProjectionMtime: null,
93
+ serverMaterializedAt,
94
+ localLagMs: null,
95
+ localAgeMs: null,
96
+ unavailableReason: 'no .productbrain/ projection files (context.md / briefing.md / generated/ / rules/) found — run pb handshake',
97
+ };
98
+ }
99
+ // local-lag = how far the local pull lags the server projection. Positive = server is newer
100
+ // (local is stale). Clamp at 0 (a local mtime ahead of the server is not "negative staleness").
101
+ const localLagMs = serverMaterializedAt === null ? null : Math.max(0, serverMaterializedAt - localProjectionMtime);
102
+ // local-age = absolute age of the local projection vs now.
103
+ const localAgeMs = Math.max(0, now - localProjectionMtime);
104
+ return {
105
+ localProjectionMtime,
106
+ serverMaterializedAt,
107
+ localLagMs,
108
+ localAgeMs,
109
+ };
110
+ }
111
+ //# sourceMappingURL=localDrift.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localDrift.js","sourceRoot":"","sources":["../../src/scoreboard/localDrift.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * M5 local-pull drift unit tests (A5, DEC-1284).
3
+ *
4
+ * Exercises computeLocalDrift over a real temp `.productbrain/` so the stat path is genuinely
5
+ * driven (not mocked): a config-bearing root (so findProjectRoot resolves) + a projection file
6
+ * whose mtime is the local pull. Asserts the lag/age math, the clamp, and the fail-soft branches.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=localDrift.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localDrift.test.d.ts","sourceRoot":"","sources":["../../src/scoreboard/localDrift.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * M5 local-pull drift unit tests (A5, DEC-1284).
3
+ *
4
+ * Exercises computeLocalDrift over a real temp `.productbrain/` so the stat path is genuinely
5
+ * driven (not mocked): a config-bearing root (so findProjectRoot resolves) + a projection file
6
+ * whose mtime is the local pull. Asserts the lag/age math, the clamp, and the fail-soft branches.
7
+ */
8
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
9
+ import { mkdtempSync, mkdirSync, writeFileSync, utimesSync, rmSync } from 'fs';
10
+ import { tmpdir } from 'os';
11
+ import { resolve } from 'path';
12
+ import { computeLocalDrift } from './localDrift.js';
13
+ let root;
14
+ function setMtime(path, ms) {
15
+ const secs = ms / 1000;
16
+ utimesSync(path, secs, secs);
17
+ }
18
+ beforeEach(() => {
19
+ root = mkdtempSync(resolve(tmpdir(), 'pb-m5-'));
20
+ const pb = resolve(root, '.productbrain');
21
+ mkdirSync(pb, { recursive: true });
22
+ // config.json makes this a CLI project root (findProjectRoot requires it).
23
+ writeFileSync(resolve(pb, 'config.json'), JSON.stringify({ siteUrl: 'https://example.test' }));
24
+ });
25
+ afterEach(() => {
26
+ rmSync(root, { recursive: true, force: true });
27
+ });
28
+ describe('computeLocalDrift', () => {
29
+ it('fails soft to unavailable when no projection files exist', () => {
30
+ const d = computeLocalDrift(5_000, 10_000, root);
31
+ expect(d.localProjectionMtime).toBeNull();
32
+ expect(d.localLagMs).toBeNull();
33
+ expect(d.localAgeMs).toBeNull();
34
+ expect(d.unavailableReason).toMatch(/projection files/);
35
+ });
36
+ it('computes lag (server − local) and age (now − local) from the newest projection mtime', () => {
37
+ const pb = resolve(root, '.productbrain');
38
+ const ctx = resolve(pb, 'context.md');
39
+ writeFileSync(ctx, '# context');
40
+ setMtime(ctx, 1_000);
41
+ // Also write a newer briefing — newest mtime should win.
42
+ const brief = resolve(pb, 'briefing.md');
43
+ writeFileSync(brief, '# briefing');
44
+ setMtime(brief, 3_000);
45
+ const d = computeLocalDrift(5_000 /* server */, 10_000 /* now */, root);
46
+ expect(d.localProjectionMtime).toBe(3_000);
47
+ expect(d.serverMaterializedAt).toBe(5_000);
48
+ expect(d.localLagMs).toBe(2_000); // 5000 − 3000
49
+ expect(d.localAgeMs).toBe(7_000); // 10000 − 3000
50
+ expect(d.unavailableReason).toBeUndefined();
51
+ });
52
+ it('clamps lag at 0 when the local pull is newer than the server materialization', () => {
53
+ const pb = resolve(root, '.productbrain');
54
+ const ctx = resolve(pb, 'context.md');
55
+ writeFileSync(ctx, '# context');
56
+ setMtime(ctx, 9_000);
57
+ const d = computeLocalDrift(5_000, 10_000, root);
58
+ expect(d.localLagMs).toBe(0); // max(0, 5000 − 9000)
59
+ expect(d.localAgeMs).toBe(1_000);
60
+ });
61
+ it('returns null lag when the server never materialized', () => {
62
+ const pb = resolve(root, '.productbrain');
63
+ const ctx = resolve(pb, 'context.md');
64
+ writeFileSync(ctx, '# context');
65
+ setMtime(ctx, 2_000);
66
+ const d = computeLocalDrift(null, 10_000, root);
67
+ expect(d.localLagMs).toBeNull();
68
+ expect(d.localAgeMs).toBe(8_000);
69
+ });
70
+ it('reports unavailable when no project root is found', () => {
71
+ const bare = mkdtempSync(resolve(tmpdir(), 'pb-noroot-'));
72
+ try {
73
+ const d = computeLocalDrift(5_000, 10_000, bare);
74
+ expect(d.localProjectionMtime).toBeNull();
75
+ expect(d.unavailableReason).toMatch(/project root|missing/i);
76
+ }
77
+ finally {
78
+ rmSync(bare, { recursive: true, force: true });
79
+ }
80
+ });
81
+ });
82
+ //# sourceMappingURL=localDrift.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localDrift.test.js","sourceRoot":"","sources":["../../src/scoreboard/localDrift.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC/E,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,IAAI,IAAY,CAAC;AAEjB,SAAS,QAAQ,CAAC,IAAY,EAAE,EAAU;IACxC,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC;IACvB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED,UAAU,CAAC,GAAG,EAAE;IACd,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;IAChD,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAC1C,SAAS,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnC,2EAA2E;IAC3E,aAAa,CAAC,OAAO,CAAC,EAAE,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC,CAAC,CAAC;AACjG,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,GAAG,EAAE;IACb,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,CAAC,GAAG,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QACjD,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC1C,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sFAAsF,EAAE,GAAG,EAAE;QAC9F,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QAC1C,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;QACtC,aAAa,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAChC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACrB,yDAAyD;QACzD,MAAM,KAAK,GAAG,OAAO,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;QACzC,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;QACnC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAEvB,MAAM,CAAC,GAAG,iBAAiB,CAAC,KAAK,CAAC,YAAY,EAAE,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACxE,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc;QAChD,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe;QACjD,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,aAAa,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,GAAG,EAAE;QACtF,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QAC1C,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;QACtC,aAAa,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAChC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACrB,MAAM,CAAC,GAAG,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QACjD,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB;QACpD,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QAC1C,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;QACtC,aAAa,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAChC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACrB,MAAM,CAAC,GAAG,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QAChD,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;QAC1D,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;YACjD,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC1C,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;QAC/D,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@productbrain/cli",
3
- "version": "0.1.0-beta.1440",
3
+ "version": "0.1.0-beta.1470",
4
4
  "description": "Product Brain — Chain knowledge and write-back CLI",
5
5
  "type": "module",
6
6
  "bin": {