@productbrain/cli 0.1.0-beta.2323 → 0.1.0-beta.2326

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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=boundary-manifest.real-file.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundary-manifest.real-file.test.d.ts","sourceRoot":"","sources":["../../src/generators/boundary-manifest.real-file.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Guard against the #366 session-start regression (PR #380 hotfix): PR #366's rewrite of
3
+ * `.productbrain/rules/architecture-boundaries.md` shipped `eval-isolation-no-production-import`
4
+ * (a `kind: policyBoundary, status: active` entry) with `chainRefs: []`. `pb session start` runs
5
+ * `runHandshake(...)`, which (whenever `boundary_enforcement_mode !== 'advisory'`) calls
6
+ * `generateBoundaryManifest` on this exact file — its `validateBoundaryRules` throws on any
7
+ * active policyBoundary with an empty `chainRefs`, so `session start` exited 1 and never
8
+ * persisted the session marker, taking every downstream `pb` write command down with it
9
+ * (SESSION_REQUIRED). `boundary-manifest.test.ts` (sibling file) only exercises the parser
10
+ * against synthetic in-memory fixtures via a mocked `fs` — nothing asserted that the REAL,
11
+ * COMMITTED file actually validates, which is exactly how #366 shipped a file that broke this
12
+ * path through CI unnoticed.
13
+ *
14
+ * This file does NOT mock `fs` — it reads the real repo-root
15
+ * `.productbrain/rules/architecture-boundaries.md` and runs it through the exact functions
16
+ * `pb session start` -> `runHandshake` -> `generateBoundaryManifest` calls, so a future rewrite
17
+ * that reintroduces an empty-chainRefs active policyBoundary (or any other validation failure)
18
+ * fails THIS test instead of shipping silently.
19
+ */
20
+ import { describe, expect, it } from 'vitest';
21
+ import { readFileSync } from 'fs';
22
+ import { fileURLToPath } from 'url';
23
+ import { dirname, join } from 'path';
24
+ import { generateBoundaryManifest, parseBoundaryRules } from './boundary-manifest.js';
25
+ const __dirname = dirname(fileURLToPath(import.meta.url));
26
+ // repo root: packages/cli/src/generators -> ../../../..
27
+ const REPO_ROOT = join(__dirname, '..', '..', '..', '..');
28
+ const PB_DIR = join(REPO_ROOT, '.productbrain');
29
+ const SOURCE_PATH = join(PB_DIR, 'rules', 'architecture-boundaries.md');
30
+ describe('boundary manifest generator — real committed file (session-start regression guard)', () => {
31
+ it('the committed architecture-boundaries.md is non-empty and has the expected frontmatter shape', () => {
32
+ // Sanity floor before the real assertion below — if this fails, REPO_ROOT resolution
33
+ // itself has drifted (e.g. the test moved), not the boundary data.
34
+ const raw = readFileSync(SOURCE_PATH, 'utf8');
35
+ expect(raw.length).toBeGreaterThan(0);
36
+ expect(raw.startsWith('---\n')).toBe(true);
37
+ });
38
+ it('every active policyBoundary in the committed file has a non-empty chainRefs (the exact #366 regression)', () => {
39
+ const raw = readFileSync(SOURCE_PATH, 'utf8');
40
+ const rules = parseBoundaryRules(raw);
41
+ expect(rules.length).toBeGreaterThan(0);
42
+ // Copilot review (PR #381): `rule.chainRefs` comes from hand-authored markdown parsed by
43
+ // parseBoundaryRules — a rule entry that omits the `chainRefs:` key entirely never gets
44
+ // the property set, so `rule.chainRefs` can be `undefined` (not just `[]`) at runtime,
45
+ // even though BoundaryRule's TS type claims `chainRefs: string[]` unconditionally. A bare
46
+ // `rule.chainRefs.length === 0` would throw a TypeError on that undefined case instead of
47
+ // failing with the clear assertion message below — treat "missing or not a non-empty
48
+ // array" as the SAME violation (this is exactly the #366 regression shape: an active
49
+ // policyBoundary with no usable chainRefs, however that absence is spelled).
50
+ const violations = rules.filter((rule) => rule.kind === 'policyBoundary' && rule.status === 'active' && !(Array.isArray(rule.chainRefs) && rule.chainRefs.length > 0));
51
+ expect(violations.map((rule) => rule.id), 'Every active policyBoundary needs at least one chainRef — an empty chainRefs here is ' +
52
+ 'exactly the #366 regression that made pb session start exit 1 (runHandshake -> ' +
53
+ 'generateBoundaryManifest -> validateBoundaryRules throws), which took every ' +
54
+ 'downstream pb write command down with it (SESSION_REQUIRED, deployed path).').toEqual([]);
55
+ });
56
+ it('generateBoundaryManifest does not throw against the real committed file — the exact pb session start -> runHandshake call path', () => {
57
+ // Calls the SAME function runHandshake calls (packages/cli/src/commands/handshake.ts,
58
+ // `boundaryManifestContent = ... : generateBoundaryManifest(pbDir)`), against the SAME
59
+ // real file on disk `pb session start` reads — no mock, no synthetic fixture.
60
+ expect(() => generateBoundaryManifest(PB_DIR)).not.toThrow();
61
+ const manifest = generateBoundaryManifest(PB_DIR);
62
+ expect(manifest).not.toBeNull();
63
+ // Parses back cleanly as the JSON shape generateBoundaryManifest documents.
64
+ const parsed = JSON.parse(manifest);
65
+ expect(parsed.schemaVersion).toBe(1);
66
+ expect(Array.isArray(parsed.rules)).toBe(true);
67
+ expect(parsed.rules.length).toBe(parseBoundaryRules(readFileSync(SOURCE_PATH, 'utf8')).length);
68
+ });
69
+ });
70
+ //# sourceMappingURL=boundary-manifest.real-file.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundary-manifest.real-file.test.js","sourceRoot":"","sources":["../../src/generators/boundary-manifest.real-file.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@productbrain/cli",
3
- "version": "0.1.0-beta.2323",
3
+ "version": "0.1.0-beta.2326",
4
4
  "description": "Product Brain — Chain knowledge and write-back CLI",
5
5
  "type": "module",
6
6
  "bin": {