@vibecheckai/cli 3.2.5 → 3.3.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 (197) hide show
  1. package/bin/.generated +25 -25
  2. package/bin/dev/run-v2-torture.js +30 -30
  3. package/bin/registry.js +192 -5
  4. package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -295
  5. package/bin/runners/lib/agent-firewall/change-packet/builder.js +280 -6
  6. package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
  7. package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
  8. package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
  9. package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
  10. package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
  11. package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
  12. package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
  13. package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
  14. package/bin/runners/lib/agent-firewall/logger.js +141 -0
  15. package/bin/runners/lib/agent-firewall/policy/loader.js +312 -4
  16. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +113 -1
  17. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +133 -6
  18. package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
  19. package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
  20. package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
  21. package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
  22. package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
  23. package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
  24. package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
  25. package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
  26. package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
  27. package/bin/runners/lib/agent-firewall/risk/thresholds.js +321 -0
  28. package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
  29. package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
  30. package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
  31. package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
  32. package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
  33. package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
  34. package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
  35. package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
  36. package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
  37. package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
  38. package/bin/runners/lib/analyzers.js +81 -18
  39. package/bin/runners/lib/api-client.js +269 -0
  40. package/bin/runners/lib/auth-truth.js +193 -193
  41. package/bin/runners/lib/authority-badge.js +425 -0
  42. package/bin/runners/lib/backup.js +62 -62
  43. package/bin/runners/lib/billing.js +107 -107
  44. package/bin/runners/lib/claims.js +118 -118
  45. package/bin/runners/lib/cli-output.js +7 -1
  46. package/bin/runners/lib/cli-ui.js +540 -540
  47. package/bin/runners/lib/contracts/auth-contract.js +202 -202
  48. package/bin/runners/lib/contracts/env-contract.js +181 -181
  49. package/bin/runners/lib/contracts/external-contract.js +206 -206
  50. package/bin/runners/lib/contracts/guard.js +168 -168
  51. package/bin/runners/lib/contracts/index.js +89 -89
  52. package/bin/runners/lib/contracts/plan-validator.js +311 -311
  53. package/bin/runners/lib/contracts/route-contract.js +199 -199
  54. package/bin/runners/lib/contracts.js +804 -804
  55. package/bin/runners/lib/detect.js +89 -89
  56. package/bin/runners/lib/doctor/autofix.js +254 -254
  57. package/bin/runners/lib/doctor/index.js +37 -37
  58. package/bin/runners/lib/doctor/modules/dependencies.js +325 -325
  59. package/bin/runners/lib/doctor/modules/index.js +46 -46
  60. package/bin/runners/lib/doctor/modules/network.js +250 -250
  61. package/bin/runners/lib/doctor/modules/project.js +312 -312
  62. package/bin/runners/lib/doctor/modules/runtime.js +224 -224
  63. package/bin/runners/lib/doctor/modules/security.js +348 -348
  64. package/bin/runners/lib/doctor/modules/system.js +213 -213
  65. package/bin/runners/lib/doctor/modules/vibecheck.js +394 -394
  66. package/bin/runners/lib/doctor/reporter.js +262 -262
  67. package/bin/runners/lib/doctor/service.js +262 -262
  68. package/bin/runners/lib/doctor/types.js +113 -113
  69. package/bin/runners/lib/doctor/ui.js +263 -263
  70. package/bin/runners/lib/doctor-v2.js +608 -608
  71. package/bin/runners/lib/drift.js +425 -425
  72. package/bin/runners/lib/enforcement.js +72 -72
  73. package/bin/runners/lib/enterprise-detect.js +603 -603
  74. package/bin/runners/lib/enterprise-init.js +942 -942
  75. package/bin/runners/lib/env-resolver.js +417 -417
  76. package/bin/runners/lib/env-template.js +66 -66
  77. package/bin/runners/lib/env.js +189 -189
  78. package/bin/runners/lib/error-handler.js +16 -9
  79. package/bin/runners/lib/exit-codes.js +275 -0
  80. package/bin/runners/lib/extractors/client-calls.js +990 -990
  81. package/bin/runners/lib/extractors/fastify-route-dump.js +573 -573
  82. package/bin/runners/lib/extractors/fastify-routes.js +426 -426
  83. package/bin/runners/lib/extractors/index.js +363 -363
  84. package/bin/runners/lib/extractors/next-routes.js +524 -524
  85. package/bin/runners/lib/extractors/proof-graph.js +431 -431
  86. package/bin/runners/lib/extractors/route-matcher.js +451 -451
  87. package/bin/runners/lib/extractors/truthpack-v2.js +377 -377
  88. package/bin/runners/lib/extractors/ui-bindings.js +547 -547
  89. package/bin/runners/lib/findings-schema.js +281 -281
  90. package/bin/runners/lib/firewall-prompt.js +50 -50
  91. package/bin/runners/lib/global-flags.js +37 -0
  92. package/bin/runners/lib/graph/graph-builder.js +265 -265
  93. package/bin/runners/lib/graph/html-renderer.js +413 -413
  94. package/bin/runners/lib/graph/index.js +32 -32
  95. package/bin/runners/lib/graph/runtime-collector.js +215 -215
  96. package/bin/runners/lib/graph/static-extractor.js +518 -518
  97. package/bin/runners/lib/help-formatter.js +413 -0
  98. package/bin/runners/lib/html-report.js +650 -650
  99. package/bin/runners/lib/llm.js +75 -75
  100. package/bin/runners/lib/logger.js +38 -0
  101. package/bin/runners/lib/meter.js +61 -61
  102. package/bin/runners/lib/missions/evidence.js +126 -126
  103. package/bin/runners/lib/patch.js +40 -40
  104. package/bin/runners/lib/permissions/auth-model.js +213 -213
  105. package/bin/runners/lib/permissions/idor-prover.js +205 -205
  106. package/bin/runners/lib/permissions/index.js +45 -45
  107. package/bin/runners/lib/permissions/matrix-builder.js +198 -198
  108. package/bin/runners/lib/pkgjson.js +28 -28
  109. package/bin/runners/lib/policy.js +295 -295
  110. package/bin/runners/lib/preflight.js +142 -142
  111. package/bin/runners/lib/reality/correlation-detectors.js +359 -359
  112. package/bin/runners/lib/reality/index.js +318 -318
  113. package/bin/runners/lib/reality/request-hashing.js +416 -416
  114. package/bin/runners/lib/reality/request-mapper.js +453 -453
  115. package/bin/runners/lib/reality/safety-rails.js +463 -463
  116. package/bin/runners/lib/reality/semantic-snapshot.js +408 -408
  117. package/bin/runners/lib/reality/toast-detector.js +393 -393
  118. package/bin/runners/lib/reality-findings.js +84 -84
  119. package/bin/runners/lib/receipts.js +179 -179
  120. package/bin/runners/lib/redact.js +29 -29
  121. package/bin/runners/lib/replay/capsule-manager.js +154 -154
  122. package/bin/runners/lib/replay/index.js +263 -263
  123. package/bin/runners/lib/replay/player.js +348 -348
  124. package/bin/runners/lib/replay/recorder.js +331 -331
  125. package/bin/runners/lib/report.js +135 -135
  126. package/bin/runners/lib/route-detection.js +1140 -1140
  127. package/bin/runners/lib/sandbox/index.js +59 -59
  128. package/bin/runners/lib/sandbox/proof-chain.js +399 -399
  129. package/bin/runners/lib/sandbox/sandbox-runner.js +205 -205
  130. package/bin/runners/lib/sandbox/worktree.js +174 -174
  131. package/bin/runners/lib/schema-validator.js +350 -350
  132. package/bin/runners/lib/schemas/contracts.schema.json +160 -160
  133. package/bin/runners/lib/schemas/finding.schema.json +100 -100
  134. package/bin/runners/lib/schemas/mission-pack.schema.json +206 -206
  135. package/bin/runners/lib/schemas/proof-graph.schema.json +176 -176
  136. package/bin/runners/lib/schemas/reality-report.schema.json +162 -162
  137. package/bin/runners/lib/schemas/share-pack.schema.json +180 -180
  138. package/bin/runners/lib/schemas/ship-report.schema.json +117 -117
  139. package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -303
  140. package/bin/runners/lib/schemas/validator.js +438 -438
  141. package/bin/runners/lib/score-history.js +282 -282
  142. package/bin/runners/lib/share-pack.js +239 -239
  143. package/bin/runners/lib/snippets.js +67 -67
  144. package/bin/runners/lib/unified-cli-output.js +604 -0
  145. package/bin/runners/lib/upsell.js +658 -510
  146. package/bin/runners/lib/usage.js +153 -153
  147. package/bin/runners/lib/validate-patch.js +156 -156
  148. package/bin/runners/lib/verdict-engine.js +628 -628
  149. package/bin/runners/reality/engine.js +917 -917
  150. package/bin/runners/reality/flows.js +122 -122
  151. package/bin/runners/reality/report.js +378 -378
  152. package/bin/runners/reality/session.js +193 -193
  153. package/bin/runners/runAgent.d.ts +5 -0
  154. package/bin/runners/runApprove.js +1200 -0
  155. package/bin/runners/runAuth.js +324 -95
  156. package/bin/runners/runCheckpoint.js +39 -21
  157. package/bin/runners/runClassify.js +859 -0
  158. package/bin/runners/runContext.js +136 -24
  159. package/bin/runners/runDoctor.js +108 -68
  160. package/bin/runners/runFirewall.d.ts +5 -0
  161. package/bin/runners/runFirewallHook.d.ts +5 -0
  162. package/bin/runners/runFix.js +6 -5
  163. package/bin/runners/runGuard.js +262 -168
  164. package/bin/runners/runInit.js +3 -2
  165. package/bin/runners/runMcp.js +130 -52
  166. package/bin/runners/runPolish.js +43 -20
  167. package/bin/runners/runProve.js +1 -2
  168. package/bin/runners/runReport.js +3 -2
  169. package/bin/runners/runScan.js +145 -44
  170. package/bin/runners/runShip.js +3 -4
  171. package/bin/runners/runTruth.d.ts +5 -0
  172. package/bin/runners/runValidate.js +19 -2
  173. package/bin/runners/runWatch.js +104 -53
  174. package/bin/vibecheck.js +106 -19
  175. package/mcp-server/HARDENING_SUMMARY.md +299 -0
  176. package/mcp-server/agent-firewall-interceptor.js +367 -31
  177. package/mcp-server/authority-tools.js +569 -0
  178. package/mcp-server/conductor/conflict-resolver.js +588 -0
  179. package/mcp-server/conductor/execution-planner.js +544 -0
  180. package/mcp-server/conductor/index.js +377 -0
  181. package/mcp-server/conductor/lock-manager.js +615 -0
  182. package/mcp-server/conductor/request-queue.js +550 -0
  183. package/mcp-server/conductor/session-manager.js +500 -0
  184. package/mcp-server/conductor/tools.js +510 -0
  185. package/mcp-server/index.js +1199 -208
  186. package/mcp-server/lib/api-client.cjs +305 -0
  187. package/mcp-server/lib/logger.cjs +30 -0
  188. package/mcp-server/logger.js +173 -0
  189. package/mcp-server/package.json +2 -2
  190. package/mcp-server/premium-tools.js +2 -2
  191. package/mcp-server/tier-auth.js +351 -136
  192. package/mcp-server/tools/index.js +72 -72
  193. package/mcp-server/truth-firewall-tools.js +145 -15
  194. package/mcp-server/vibecheck-tools.js +2 -2
  195. package/package.json +2 -3
  196. package/mcp-server/index.old.js +0 -4137
  197. package/mcp-server/package-lock.json +0 -165
@@ -0,0 +1,420 @@
1
+ /**
2
+ * Lawbook Invariant Schema
3
+ *
4
+ * Defines the YAML DSL for organizational invariant rules.
5
+ * Invariants are rules that must ALWAYS hold true in the codebase.
6
+ *
7
+ * Codename: Lawbook
8
+ */
9
+
10
+ "use strict";
11
+
12
+ /**
13
+ * Invariant rule types
14
+ */
15
+ const INVARIANT_TYPES = {
16
+ // File/path based rules
17
+ NO_MODIFY: "no-modify", // Files/paths that cannot be modified
18
+ NO_DELETE: "no-delete", // Files/paths that cannot be deleted
19
+ NO_CREATE: "no-create", // Patterns that cannot be created
20
+ REQUIRE_APPROVAL: "require-approval", // Changes require approval
21
+
22
+ // Code pattern rules
23
+ NEVER: "never", // Pattern must never appear
24
+ ALWAYS: "always", // Pattern must always be present
25
+ BEFORE: "before", // Pattern A must come before pattern B
26
+ AFTER: "after", // Pattern A must come after pattern B
27
+ MAINTAINS: "maintains", // Property must be maintained
28
+
29
+ // Architectural rules
30
+ ALL_THROUGH: "all-through", // All X must go through Y
31
+ NO_DIRECT: "no-direct", // No direct access to X (use Y instead)
32
+ LAYER_BOUNDARY: "layer-boundary", // Enforce architectural layers
33
+
34
+ // Environment rules
35
+ ENV_MUST_BE_REGISTERED: "env-must-be-registered", // All env vars must be in registry
36
+ ENV_REQUIRED: "env-required", // Specific env vars required
37
+
38
+ // Dependency rules
39
+ DEPENDENCY_LOCKED: "dependency-locked", // Dependency version locked
40
+ NO_DEPENDENCY: "no-dependency", // Certain dependencies forbidden
41
+ };
42
+
43
+ /**
44
+ * Invariant severity levels
45
+ */
46
+ const INVARIANT_SEVERITY = {
47
+ BLOCK: "block", // Absolutely cannot proceed
48
+ ERROR: "error", // Serious violation
49
+ WARNING: "warning", // Should be addressed
50
+ INFO: "info", // Advisory
51
+ };
52
+
53
+ /**
54
+ * Invariant scope types
55
+ */
56
+ const SCOPE_TYPES = {
57
+ FILE: "file", // Single file
58
+ DIRECTORY: "directory", // Directory and subdirectories
59
+ GLOB: "glob", // Glob pattern
60
+ REGEX: "regex", // Regex pattern
61
+ ALL: "all", // Entire codebase
62
+ };
63
+
64
+ /**
65
+ * JSON Schema for invariant definitions
66
+ */
67
+ const INVARIANT_SCHEMA = {
68
+ $schema: "http://json-schema.org/draft-07/schema#",
69
+ title: "VibeCheck Lawbook Invariant",
70
+ type: "object",
71
+ required: ["id", "rule"],
72
+ properties: {
73
+ id: {
74
+ type: "string",
75
+ description: "Unique identifier for this invariant",
76
+ pattern: "^[a-z0-9-]+$",
77
+ },
78
+ description: {
79
+ type: "string",
80
+ description: "Human-readable description of this invariant",
81
+ },
82
+ rule: {
83
+ type: "string",
84
+ enum: Object.values(INVARIANT_TYPES),
85
+ description: "Type of invariant rule",
86
+ },
87
+ scope: {
88
+ type: "string",
89
+ description: "Glob pattern defining where this rule applies",
90
+ },
91
+ target: {
92
+ type: "string",
93
+ description: "Target path/file for 'all-through' rules",
94
+ },
95
+ pattern: {
96
+ type: "string",
97
+ description: "Regex pattern to match/exclude",
98
+ },
99
+ exclude: {
100
+ oneOf: [
101
+ { type: "string" },
102
+ { type: "array", items: { type: "string" } },
103
+ ],
104
+ description: "Paths/patterns excluded from this rule",
105
+ },
106
+ violations: {
107
+ type: "array",
108
+ items: {
109
+ type: "object",
110
+ properties: {
111
+ pattern: { type: "string" },
112
+ exclude: {
113
+ oneOf: [
114
+ { type: "string" },
115
+ { type: "array", items: { type: "string" } },
116
+ ],
117
+ },
118
+ message: { type: "string" },
119
+ },
120
+ },
121
+ description: "Specific violation patterns to detect",
122
+ },
123
+ severity: {
124
+ type: "string",
125
+ enum: Object.values(INVARIANT_SEVERITY),
126
+ default: "error",
127
+ description: "Severity level when violated",
128
+ },
129
+ introduced: {
130
+ type: "string",
131
+ format: "date",
132
+ description: "Date this invariant was introduced",
133
+ },
134
+ incident: {
135
+ type: "string",
136
+ description: "Related incident ID that prompted this invariant",
137
+ },
138
+ owner: {
139
+ type: "string",
140
+ description: "Team/person responsible for this invariant",
141
+ },
142
+ registry: {
143
+ type: "string",
144
+ description: "Registry file for env-must-be-registered rules",
145
+ },
146
+ message: {
147
+ type: "string",
148
+ description: "Custom message when violated",
149
+ },
150
+ autofix: {
151
+ type: "object",
152
+ properties: {
153
+ enabled: { type: "boolean", default: false },
154
+ action: { type: "string" },
155
+ template: { type: "string" },
156
+ },
157
+ description: "Auto-fix configuration",
158
+ },
159
+ metadata: {
160
+ type: "object",
161
+ description: "Additional metadata",
162
+ },
163
+ },
164
+ };
165
+
166
+ /**
167
+ * Schema for the full lawbook YAML file
168
+ */
169
+ const LAWBOOK_FILE_SCHEMA = {
170
+ $schema: "http://json-schema.org/draft-07/schema#",
171
+ title: "VibeCheck Lawbook",
172
+ type: "object",
173
+ properties: {
174
+ version: {
175
+ type: "string",
176
+ default: "1.0.0",
177
+ description: "Lawbook schema version",
178
+ },
179
+ name: {
180
+ type: "string",
181
+ description: "Name of this invariant library",
182
+ },
183
+ description: {
184
+ type: "string",
185
+ description: "Description of this invariant library",
186
+ },
187
+ extends: {
188
+ oneOf: [
189
+ { type: "string" },
190
+ { type: "array", items: { type: "string" } },
191
+ ],
192
+ description: "Other lawbooks this extends",
193
+ },
194
+ invariants: {
195
+ type: "array",
196
+ items: { $ref: "#/definitions/invariant" },
197
+ description: "List of invariant rules",
198
+ },
199
+ groups: {
200
+ type: "object",
201
+ additionalProperties: {
202
+ type: "array",
203
+ items: { type: "string" },
204
+ },
205
+ description: "Named groups of invariant IDs",
206
+ },
207
+ },
208
+ definitions: {
209
+ invariant: INVARIANT_SCHEMA,
210
+ },
211
+ };
212
+
213
+ /**
214
+ * Create a default invariant template
215
+ * @param {string} id - Invariant ID
216
+ * @param {string} rule - Rule type
217
+ * @returns {Object} Invariant template
218
+ */
219
+ function createInvariantTemplate(id, rule) {
220
+ return {
221
+ id,
222
+ rule,
223
+ description: "",
224
+ scope: "**/*",
225
+ severity: INVARIANT_SEVERITY.ERROR,
226
+ introduced: new Date().toISOString().split("T")[0],
227
+ metadata: {},
228
+ };
229
+ }
230
+
231
+ /**
232
+ * Validate an invariant against the schema
233
+ * @param {Object} invariant - Invariant to validate
234
+ * @returns {Object} Validation result
235
+ */
236
+ function validateInvariant(invariant) {
237
+ const errors = [];
238
+
239
+ // Check required fields
240
+ if (!invariant.id) {
241
+ errors.push({ field: "id", message: "Invariant ID is required" });
242
+ } else if (!/^[a-z0-9-]+$/.test(invariant.id)) {
243
+ errors.push({ field: "id", message: "Invariant ID must be lowercase alphanumeric with hyphens" });
244
+ }
245
+
246
+ if (!invariant.rule) {
247
+ errors.push({ field: "rule", message: "Rule type is required" });
248
+ } else if (!Object.values(INVARIANT_TYPES).includes(invariant.rule)) {
249
+ errors.push({ field: "rule", message: `Unknown rule type: ${invariant.rule}` });
250
+ }
251
+
252
+ // Validate severity
253
+ if (invariant.severity && !Object.values(INVARIANT_SEVERITY).includes(invariant.severity)) {
254
+ errors.push({ field: "severity", message: `Unknown severity: ${invariant.severity}` });
255
+ }
256
+
257
+ // Rule-specific validation
258
+ if (invariant.rule === INVARIANT_TYPES.ALL_THROUGH && !invariant.target) {
259
+ errors.push({ field: "target", message: "all-through rules require a target" });
260
+ }
261
+
262
+ if ((invariant.rule === INVARIANT_TYPES.NEVER || invariant.rule === INVARIANT_TYPES.ALWAYS) && !invariant.pattern) {
263
+ errors.push({ field: "pattern", message: `${invariant.rule} rules require a pattern` });
264
+ }
265
+
266
+ if (invariant.rule === INVARIANT_TYPES.ENV_MUST_BE_REGISTERED && !invariant.registry) {
267
+ errors.push({ field: "registry", message: "env-must-be-registered rules require a registry file" });
268
+ }
269
+
270
+ return {
271
+ valid: errors.length === 0,
272
+ errors,
273
+ };
274
+ }
275
+
276
+ /**
277
+ * Parse a lawbook YAML string
278
+ * @param {string} content - YAML content
279
+ * @returns {Object} Parsed lawbook
280
+ */
281
+ function parseLawbook(content) {
282
+ // Try to use js-yaml if available
283
+ try {
284
+ const yaml = require("js-yaml");
285
+ return yaml.load(content);
286
+ } catch {
287
+ // Fallback: basic YAML-like parsing for simple cases
288
+ return parseSimpleLawbook(content);
289
+ }
290
+ }
291
+
292
+ /**
293
+ * Simple lawbook parser for basic YAML structures
294
+ * @param {string} content - YAML content
295
+ * @returns {Object} Parsed lawbook
296
+ */
297
+ function parseSimpleLawbook(content) {
298
+ const lines = content.split("\n");
299
+ const lawbook = {
300
+ version: "1.0.0",
301
+ invariants: [],
302
+ };
303
+
304
+ let currentInvariant = null;
305
+ let currentKey = null;
306
+ let indent = 0;
307
+
308
+ for (const line of lines) {
309
+ const trimmed = line.trim();
310
+
311
+ // Skip comments and empty lines
312
+ if (!trimmed || trimmed.startsWith("#")) continue;
313
+
314
+ // Check indent level
315
+ const currentIndent = line.search(/\S/);
316
+
317
+ // Key-value pair
318
+ const kvMatch = trimmed.match(/^(\w+):\s*(.*)$/);
319
+ if (kvMatch) {
320
+ const [, key, value] = kvMatch;
321
+
322
+ if (key === "invariants") {
323
+ // Start of invariants array
324
+ continue;
325
+ }
326
+
327
+ if (currentIndent > indent && currentInvariant) {
328
+ // Nested property
329
+ currentInvariant[key] = value || undefined;
330
+ } else {
331
+ // Top-level property
332
+ lawbook[key] = value;
333
+ }
334
+
335
+ currentKey = key;
336
+ }
337
+
338
+ // Array item
339
+ if (trimmed.startsWith("- ")) {
340
+ const itemContent = trimmed.slice(2).trim();
341
+
342
+ if (itemContent.startsWith("id:")) {
343
+ // New invariant
344
+ if (currentInvariant) {
345
+ lawbook.invariants.push(currentInvariant);
346
+ }
347
+ currentInvariant = { id: itemContent.slice(3).trim() };
348
+ indent = currentIndent;
349
+ }
350
+ }
351
+ }
352
+
353
+ // Push last invariant
354
+ if (currentInvariant) {
355
+ lawbook.invariants.push(currentInvariant);
356
+ }
357
+
358
+ return lawbook;
359
+ }
360
+
361
+ /**
362
+ * Serialize a lawbook to YAML string
363
+ * @param {Object} lawbook - Lawbook to serialize
364
+ * @returns {string} YAML string
365
+ */
366
+ function serializeLawbook(lawbook) {
367
+ try {
368
+ const yaml = require("js-yaml");
369
+ return yaml.dump(lawbook, {
370
+ indent: 2,
371
+ lineWidth: 120,
372
+ noRefs: true,
373
+ });
374
+ } catch {
375
+ // Fallback: simple serialization
376
+ return JSON.stringify(lawbook, null, 2);
377
+ }
378
+ }
379
+
380
+ /**
381
+ * Create a default lawbook template
382
+ * @param {string} name - Lawbook name
383
+ * @returns {Object} Default lawbook
384
+ */
385
+ function createDefaultLawbook(name = "project-invariants") {
386
+ return {
387
+ version: "1.0.0",
388
+ name,
389
+ description: "Project-specific invariant rules",
390
+ invariants: [
391
+ {
392
+ id: "example-no-console",
393
+ description: "No console.log in production code",
394
+ rule: INVARIANT_TYPES.NEVER,
395
+ scope: "src/**/*.{ts,tsx,js,jsx}",
396
+ pattern: "console\\.log\\(",
397
+ exclude: ["**/*.test.*", "**/*.spec.*"],
398
+ severity: INVARIANT_SEVERITY.WARNING,
399
+ introduced: new Date().toISOString().split("T")[0],
400
+ },
401
+ ],
402
+ groups: {
403
+ security: [],
404
+ architecture: [],
405
+ quality: [],
406
+ },
407
+ };
408
+ }
409
+
410
+ module.exports = {
411
+ INVARIANT_TYPES,
412
+ INVARIANT_SEVERITY,
413
+ INVARIANT_SCHEMA,
414
+ LAWBOOK_FILE_SCHEMA,
415
+ createInvariantTemplate,
416
+ validateInvariant,
417
+ parseLawbook,
418
+ serializeLawbook,
419
+ createDefaultLawbook,
420
+ };
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Agent Firewall Logger Utility
3
+ *
4
+ * Centralized logging for agent-firewall modules.
5
+ * Provides structured logging without console.* calls.
6
+ */
7
+
8
+ "use strict";
9
+
10
+ /**
11
+ * Log levels
12
+ */
13
+ const LOG_LEVELS = {
14
+ DEBUG: 0,
15
+ INFO: 1,
16
+ WARN: 2,
17
+ ERROR: 3,
18
+ SILENT: 4,
19
+ };
20
+
21
+ /**
22
+ * Current log level (from environment or default)
23
+ */
24
+ let currentLevel = LOG_LEVELS.INFO;
25
+
26
+ if (process.env.VIBECHECK_LOG_LEVEL) {
27
+ const envLevel = process.env.VIBECHECK_LOG_LEVEL.toUpperCase();
28
+ if (LOG_LEVELS[envLevel] !== undefined) {
29
+ currentLevel = LOG_LEVELS[envLevel];
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Log buffer for inspection
35
+ */
36
+ const logBuffer = [];
37
+ const MAX_BUFFER_SIZE = 500;
38
+
39
+ /**
40
+ * Write a log entry
41
+ * @param {number} level - Log level
42
+ * @param {string} levelName - Level name
43
+ * @param {string} module - Module name
44
+ * @param {string} message - Message
45
+ * @param {Error} [error] - Optional error
46
+ */
47
+ function writeLog(level, levelName, module, message, error) {
48
+ if (level < currentLevel) return;
49
+
50
+ const entry = {
51
+ timestamp: new Date().toISOString(),
52
+ level: levelName,
53
+ module,
54
+ message,
55
+ error: error ? { message: error.message, stack: error.stack } : null,
56
+ };
57
+
58
+ // Buffer for later inspection
59
+ logBuffer.push(entry);
60
+ if (logBuffer.length > MAX_BUFFER_SIZE) {
61
+ logBuffer.shift();
62
+ }
63
+
64
+ // Only write to stderr in debug mode or for warnings/errors
65
+ const formatted = `[${entry.timestamp}] [${levelName}] [${module}] ${message}`;
66
+ if (level >= LOG_LEVELS.WARN || process.env.VIBECHECK_DEBUG) {
67
+ process.stderr.write(formatted + '\n');
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Create a logger for a module
73
+ * @param {string} moduleName - Module name
74
+ * @returns {Object} Logger
75
+ */
76
+ function createLogger(moduleName) {
77
+ return {
78
+ debug: function(msg) { writeLog(LOG_LEVELS.DEBUG, 'DEBUG', moduleName, msg); },
79
+ info: function(msg) { writeLog(LOG_LEVELS.INFO, 'INFO', moduleName, msg); },
80
+ warn: function(msg, err) { writeLog(LOG_LEVELS.WARN, 'WARN', moduleName, msg, err || null); },
81
+ error: function(msg, err) { writeLog(LOG_LEVELS.ERROR, 'ERROR', moduleName, msg, err || null); },
82
+ };
83
+ }
84
+
85
+ /**
86
+ * Get error message safely
87
+ * @param {*} error - Error
88
+ * @returns {string} Message
89
+ */
90
+ function getErrorMessage(error) {
91
+ if (error instanceof Error) return error.message;
92
+ if (typeof error === 'string') return error;
93
+ if (error && typeof error === 'object' && 'message' in error) {
94
+ return String(error.message);
95
+ }
96
+ return String(error);
97
+ }
98
+
99
+ /**
100
+ * Set log level
101
+ * @param {string|number} level - Level
102
+ */
103
+ function setLogLevel(level) {
104
+ if (typeof level === 'string') {
105
+ const upper = level.toUpperCase();
106
+ if (LOG_LEVELS[upper] !== undefined) {
107
+ currentLevel = LOG_LEVELS[upper];
108
+ }
109
+ } else if (typeof level === 'number') {
110
+ currentLevel = level;
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Get recent logs
116
+ * @param {number} count - Count
117
+ * @returns {Object[]} Logs
118
+ */
119
+ function getRecentLogs(count) {
120
+ return logBuffer.slice(-(count || 100));
121
+ }
122
+
123
+ // Pre-created loggers
124
+ const lawbookLogger = createLogger('Lawbook');
125
+ const timeMachineLogger = createLogger('TimeMachine');
126
+ const realityLogger = createLogger('Reality');
127
+ const criticLogger = createLogger('Critic');
128
+ const simulatorLogger = createLogger('Simulator');
129
+
130
+ module.exports = {
131
+ createLogger,
132
+ getErrorMessage,
133
+ setLogLevel,
134
+ getRecentLogs,
135
+ LOG_LEVELS,
136
+ lawbookLogger,
137
+ timeMachineLogger,
138
+ realityLogger,
139
+ criticLogger,
140
+ simulatorLogger,
141
+ };