@vibecheckai/cli 3.2.6 → 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.
- package/bin/registry.js +192 -5
- package/bin/runners/lib/agent-firewall/change-packet/builder.js +280 -6
- package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
- package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
- package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
- package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
- package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
- package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
- package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
- package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
- package/bin/runners/lib/agent-firewall/logger.js +141 -0
- package/bin/runners/lib/agent-firewall/policy/loader.js +312 -4
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +113 -1
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +133 -6
- package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
- package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
- package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
- package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
- package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
- package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
- package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
- package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
- package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
- package/bin/runners/lib/agent-firewall/risk/thresholds.js +321 -0
- package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
- package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
- package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
- package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
- package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
- package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
- package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
- package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
- package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
- package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
- package/bin/runners/lib/analyzers.js +81 -18
- package/bin/runners/lib/authority-badge.js +425 -0
- package/bin/runners/lib/cli-output.js +7 -1
- package/bin/runners/lib/error-handler.js +16 -9
- package/bin/runners/lib/exit-codes.js +275 -0
- package/bin/runners/lib/global-flags.js +37 -0
- package/bin/runners/lib/help-formatter.js +413 -0
- package/bin/runners/lib/logger.js +38 -0
- package/bin/runners/lib/unified-cli-output.js +604 -0
- package/bin/runners/lib/upsell.js +148 -0
- package/bin/runners/runApprove.js +1200 -0
- package/bin/runners/runAuth.js +324 -95
- package/bin/runners/runCheckpoint.js +39 -21
- package/bin/runners/runClassify.js +859 -0
- package/bin/runners/runContext.js +136 -24
- package/bin/runners/runDoctor.js +108 -68
- package/bin/runners/runFix.js +6 -5
- package/bin/runners/runGuard.js +212 -118
- package/bin/runners/runInit.js +3 -2
- package/bin/runners/runMcp.js +130 -52
- package/bin/runners/runPolish.js +43 -20
- package/bin/runners/runProve.js +1 -2
- package/bin/runners/runReport.js +3 -2
- package/bin/runners/runScan.js +63 -44
- package/bin/runners/runShip.js +3 -4
- package/bin/runners/runValidate.js +19 -2
- package/bin/runners/runWatch.js +104 -53
- package/bin/vibecheck.js +106 -19
- package/mcp-server/HARDENING_SUMMARY.md +299 -0
- package/mcp-server/agent-firewall-interceptor.js +367 -31
- package/mcp-server/authority-tools.js +569 -0
- package/mcp-server/conductor/conflict-resolver.js +588 -0
- package/mcp-server/conductor/execution-planner.js +544 -0
- package/mcp-server/conductor/index.js +377 -0
- package/mcp-server/conductor/lock-manager.js +615 -0
- package/mcp-server/conductor/request-queue.js +550 -0
- package/mcp-server/conductor/session-manager.js +500 -0
- package/mcp-server/conductor/tools.js +510 -0
- package/mcp-server/index.js +1149 -243
- package/mcp-server/lib/{api-client.js → api-client.cjs} +40 -4
- package/mcp-server/lib/logger.cjs +30 -0
- package/mcp-server/logger.js +173 -0
- package/mcp-server/package.json +2 -2
- package/mcp-server/premium-tools.js +2 -2
- package/mcp-server/tier-auth.js +245 -35
- package/mcp-server/truth-firewall-tools.js +145 -15
- package/mcp-server/vibecheck-tools.js +2 -2
- package/package.json +2 -3
- package/mcp-server/index.old.js +0 -4137
- 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
|
+
};
|