@vibecheckai/cli 3.7.0 → 3.9.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/README.md +135 -63
- package/bin/_deprecations.js +447 -19
- package/bin/_router.js +1 -1
- package/bin/registry.js +347 -280
- package/bin/runners/context/generators/cursor-enhanced.js +2439 -0
- package/bin/runners/lib/agent-firewall/enforcement/gateway.js +1059 -0
- package/bin/runners/lib/agent-firewall/enforcement/index.js +98 -0
- package/bin/runners/lib/agent-firewall/enforcement/mode.js +318 -0
- package/bin/runners/lib/agent-firewall/enforcement/orchestrator.js +484 -0
- package/bin/runners/lib/agent-firewall/enforcement/proof-artifact.js +418 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/change-event.schema.json +173 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/intent.schema.json +181 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/verdict.schema.json +222 -0
- package/bin/runners/lib/agent-firewall/enforcement/verdict-v2.js +333 -0
- package/bin/runners/lib/agent-firewall/index.js +200 -0
- package/bin/runners/lib/agent-firewall/integration/index.js +20 -0
- package/bin/runners/lib/agent-firewall/integration/ship-gate.js +437 -0
- package/bin/runners/lib/agent-firewall/intent/alignment-engine.js +634 -0
- package/bin/runners/lib/agent-firewall/intent/auto-detect.js +426 -0
- package/bin/runners/lib/agent-firewall/intent/index.js +102 -0
- package/bin/runners/lib/agent-firewall/intent/schema.js +352 -0
- package/bin/runners/lib/agent-firewall/intent/store.js +283 -0
- package/bin/runners/lib/agent-firewall/interception/fs-interceptor.js +502 -0
- package/bin/runners/lib/agent-firewall/interception/index.js +23 -0
- package/bin/runners/lib/agent-firewall/interceptor/base.js +7 -3
- package/bin/runners/lib/agent-firewall/session/collector.js +451 -0
- package/bin/runners/lib/agent-firewall/session/index.js +26 -0
- package/bin/runners/lib/artifact-envelope.js +540 -0
- package/bin/runners/lib/auth-shared.js +977 -0
- package/bin/runners/lib/checkpoint.js +941 -0
- package/bin/runners/lib/cleanup/engine.js +571 -0
- package/bin/runners/lib/cleanup/index.js +53 -0
- package/bin/runners/lib/cleanup/output.js +375 -0
- package/bin/runners/lib/cleanup/rules.js +1060 -0
- package/bin/runners/lib/doctor/diagnosis-receipt.js +454 -0
- package/bin/runners/lib/doctor/failure-signatures.js +526 -0
- package/bin/runners/lib/doctor/fix-script.js +336 -0
- package/bin/runners/lib/doctor/modules/build-tools.js +453 -0
- package/bin/runners/lib/doctor/modules/index.js +62 -3
- package/bin/runners/lib/doctor/modules/os-quirks.js +706 -0
- package/bin/runners/lib/doctor/modules/repo-integrity.js +485 -0
- package/bin/runners/lib/doctor/safe-repair.js +384 -0
- package/bin/runners/lib/engine/ast-cache.js +210 -210
- package/bin/runners/lib/engine/auth-extractor.js +211 -211
- package/bin/runners/lib/engine/billing-extractor.js +112 -112
- package/bin/runners/lib/engine/enforcement-extractor.js +100 -100
- package/bin/runners/lib/engine/env-extractor.js +207 -207
- package/bin/runners/lib/engine/express-extractor.js +208 -208
- package/bin/runners/lib/engine/extractors.js +849 -849
- package/bin/runners/lib/engine/index.js +207 -207
- package/bin/runners/lib/engine/repo-index.js +514 -514
- package/bin/runners/lib/engine/types.js +124 -124
- package/bin/runners/lib/engines/attack-detector.js +1192 -0
- package/bin/runners/lib/entitlements-v2.js +2 -2
- package/bin/runners/lib/missions/briefing.js +427 -0
- package/bin/runners/lib/missions/checkpoint.js +753 -0
- package/bin/runners/lib/missions/hardening.js +851 -0
- package/bin/runners/lib/missions/plan.js +421 -32
- package/bin/runners/lib/missions/safety-gates.js +645 -0
- package/bin/runners/lib/missions/schema.js +478 -0
- package/bin/runners/lib/packs/bundle.js +675 -0
- package/bin/runners/lib/packs/evidence-pack.js +671 -0
- package/bin/runners/lib/packs/pack-factory.js +837 -0
- package/bin/runners/lib/packs/permissions-pack.js +686 -0
- package/bin/runners/lib/packs/proof-graph-pack.js +779 -0
- package/bin/runners/lib/safelist/index.js +96 -0
- package/bin/runners/lib/safelist/integration.js +334 -0
- package/bin/runners/lib/safelist/matcher.js +696 -0
- package/bin/runners/lib/safelist/schema.js +948 -0
- package/bin/runners/lib/safelist/store.js +438 -0
- package/bin/runners/lib/schemas/ship-manifest.schema.json +251 -0
- package/bin/runners/lib/ship-gate.js +832 -0
- package/bin/runners/lib/ship-manifest.js +1153 -0
- package/bin/runners/lib/ship-output.js +1 -1
- package/bin/runners/lib/unified-cli-output.js +710 -383
- package/bin/runners/lib/upsell.js +3 -3
- package/bin/runners/lib/why-tree.js +650 -0
- package/bin/runners/runAllowlist.js +33 -4
- package/bin/runners/runApprove.js +240 -1122
- package/bin/runners/runAudit.js +692 -0
- package/bin/runners/runAuth.js +325 -29
- package/bin/runners/runCheckpoint.js +442 -494
- package/bin/runners/runCleanup.js +343 -0
- package/bin/runners/runDoctor.js +269 -19
- package/bin/runners/runFix.js +411 -32
- package/bin/runners/runForge.js +411 -0
- package/bin/runners/runIntent.js +906 -0
- package/bin/runners/runKickoff.js +878 -0
- package/bin/runners/runLaunch.js +2000 -0
- package/bin/runners/runLink.js +785 -0
- package/bin/runners/runMcp.js +1741 -837
- package/bin/runners/runPacks.js +2089 -0
- package/bin/runners/runPolish.js +41 -0
- package/bin/runners/runReality.js +178 -1
- package/bin/runners/runSafelist.js +1190 -0
- package/bin/runners/runScan.js +21 -9
- package/bin/runners/runShield.js +1282 -0
- package/bin/runners/runShip.js +395 -16
- package/bin/vibecheck.js +34 -6
- package/mcp-server/README.md +117 -158
- package/mcp-server/handlers/index.ts +2 -2
- package/mcp-server/handlers/tool-handler.ts +50 -11
- package/mcp-server/index.js +16 -0
- package/mcp-server/intent-firewall-interceptor.js +529 -0
- package/mcp-server/lib/executor.ts +5 -5
- package/mcp-server/lib/index.ts +14 -4
- package/mcp-server/lib/sandbox.test.ts +4 -4
- package/mcp-server/lib/sandbox.ts +2 -2
- package/mcp-server/manifest.json +473 -0
- package/mcp-server/package.json +1 -1
- package/mcp-server/registry/tool-registry.js +315 -523
- package/mcp-server/registry/tools.json +442 -428
- package/mcp-server/registry.test.ts +18 -12
- package/mcp-server/tier-auth.js +68 -11
- package/mcp-server/tools-v3.js +70 -16
- package/mcp-server/tsconfig.json +1 -0
- package/package.json +2 -1
- package/bin/runners/runProof.zip +0 -0
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 🔥 FORGE - AI Brain Generator Runner
|
|
4
|
+
*
|
|
5
|
+
* Generates the smallest set of rules that produce the biggest accuracy lift.
|
|
6
|
+
* "Minimal but lethal" - 5-10 rules max by default, expandable tiers.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require("fs");
|
|
10
|
+
const path = require("path");
|
|
11
|
+
const crypto = require("crypto");
|
|
12
|
+
|
|
13
|
+
// Import CLI utilities for professional styling
|
|
14
|
+
const {
|
|
15
|
+
colors: c,
|
|
16
|
+
printBanner,
|
|
17
|
+
printCommandHeader,
|
|
18
|
+
printSectionHeader,
|
|
19
|
+
printTable,
|
|
20
|
+
highlight,
|
|
21
|
+
highlightPath,
|
|
22
|
+
highlightCode,
|
|
23
|
+
printSuccess,
|
|
24
|
+
printError,
|
|
25
|
+
printWarning,
|
|
26
|
+
formatNumber,
|
|
27
|
+
gradientText,
|
|
28
|
+
} = require("./cli-utils");
|
|
29
|
+
|
|
30
|
+
// Default configuration
|
|
31
|
+
const DEFAULT_CONFIG = {
|
|
32
|
+
maxRules: 10,
|
|
33
|
+
tier: "standard",
|
|
34
|
+
platforms: ["cursor", "windsurf"],
|
|
35
|
+
incremental: true,
|
|
36
|
+
generateContract: true,
|
|
37
|
+
generateTruthpack: true,
|
|
38
|
+
verbose: false,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Rule tier configurations
|
|
42
|
+
const TIER_CONFIGS = {
|
|
43
|
+
minimal: {
|
|
44
|
+
maxRules: 5,
|
|
45
|
+
features: ["architecture", "avoid", "types", "components", "testing"],
|
|
46
|
+
},
|
|
47
|
+
standard: {
|
|
48
|
+
maxRules: 10,
|
|
49
|
+
features: ["architecture", "avoid", "types", "components", "testing", "state", "data-flow", "environment", "hooks", "api-patterns"],
|
|
50
|
+
},
|
|
51
|
+
extended: {
|
|
52
|
+
maxRules: 20,
|
|
53
|
+
features: ["architecture", "avoid", "types", "components", "testing", "state", "data-flow", "environment", "hooks", "api-patterns", "security", "performance", "accessibility", "i18n", "error-handling", "logging", "caching", "database", "authentication", "authorization"],
|
|
54
|
+
},
|
|
55
|
+
comprehensive: {
|
|
56
|
+
maxRules: 50,
|
|
57
|
+
features: ["*"],
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Parse command line arguments
|
|
63
|
+
*/
|
|
64
|
+
function parseArgs(args) {
|
|
65
|
+
const opts = {
|
|
66
|
+
...DEFAULT_CONFIG,
|
|
67
|
+
help: false,
|
|
68
|
+
path: ".",
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
for (let i = 0; i < args.length; i++) {
|
|
72
|
+
const arg = args[i];
|
|
73
|
+
if (arg === "--help" || arg === "-h") opts.help = true;
|
|
74
|
+
if (arg === "--path" || arg === "-p") opts.path = args[++i];
|
|
75
|
+
if (arg.startsWith("--path=")) opts.path = arg.split("=")[1];
|
|
76
|
+
if (arg === "--tier" || arg === "-t") opts.tier = args[++i];
|
|
77
|
+
if (arg.startsWith("--tier=")) opts.tier = arg.split("=")[1];
|
|
78
|
+
if (arg === "--max-rules") opts.maxRules = parseInt(args[++i]);
|
|
79
|
+
if (arg.startsWith("--max-rules=")) opts.maxRules = parseInt(arg.split("=")[1]);
|
|
80
|
+
if (arg === "--no-incremental") opts.incremental = false;
|
|
81
|
+
if (arg === "--no-contract") opts.generateContract = false;
|
|
82
|
+
if (arg === "--no-truthpack") opts.generateTruthpack = false;
|
|
83
|
+
if (arg === "--verbose" || arg === "-v") opts.verbose = true;
|
|
84
|
+
if (arg === "--cursor-only") opts.platforms = ["cursor"];
|
|
85
|
+
if (arg === "--windsurf-only") opts.platforms = ["windsurf"];
|
|
86
|
+
if (arg === "minimal") opts.tier = "minimal";
|
|
87
|
+
if (arg === "standard") opts.tier = "standard";
|
|
88
|
+
if (arg === "extended") opts.tier = "extended";
|
|
89
|
+
if (arg === "comprehensive") opts.tier = "comprehensive";
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return opts;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Print help message
|
|
97
|
+
*/
|
|
98
|
+
function printHelp() {
|
|
99
|
+
console.log();
|
|
100
|
+
printBanner();
|
|
101
|
+
printCommandHeader("FORGE", "AI Brain Generator v1.0");
|
|
102
|
+
|
|
103
|
+
console.log(`${gradientText("Minimal but lethal", [c.red, c.yellow, c.green])} - Generate the smallest set of rules that produce the biggest accuracy lift.\n`);
|
|
104
|
+
|
|
105
|
+
console.log(`${c.yellow}USAGE${c.reset}`);
|
|
106
|
+
console.log(` ${c.cyan}vibecheck forge${c.reset} ${c.dim}[options] [tier]${c.reset}`);
|
|
107
|
+
console.log();
|
|
108
|
+
|
|
109
|
+
console.log(`${c.yellow}TIERS${c.reset}`);
|
|
110
|
+
const tiers = [
|
|
111
|
+
["minimal", "5 rules max", "Core essentials only"],
|
|
112
|
+
["standard", "10 rules max", "Balanced coverage (default)"],
|
|
113
|
+
["extended", "20 rules max", "Comprehensive coverage"],
|
|
114
|
+
["comprehensive", "50 rules max", "Everything included"],
|
|
115
|
+
];
|
|
116
|
+
printTable(["Tier", "Rules", "Description"], tiers);
|
|
117
|
+
console.log();
|
|
118
|
+
|
|
119
|
+
console.log(`${c.yellow}OPTIONS${c.reset}`);
|
|
120
|
+
const options = [
|
|
121
|
+
["--path, -p <dir>", "Project directory (default: current)"],
|
|
122
|
+
["--tier, -t <tier>", "Rule tier (minimal|standard|extended|comprehensive)"],
|
|
123
|
+
["--max-rules <n>", "Override max rules for tier"],
|
|
124
|
+
["--no-incremental", "Regenerate all rules (don't diff)"],
|
|
125
|
+
["--no-contract", "Skip AI contract generation"],
|
|
126
|
+
["--no-truthpack", "Skip truthpack generation"],
|
|
127
|
+
["--cursor-only", "Generate only Cursor rules"],
|
|
128
|
+
["--windsurf-only", "Generate only Windsurf rules"],
|
|
129
|
+
["--verbose, -v", "Show detailed output"],
|
|
130
|
+
["--help, -h", "Show this help"],
|
|
131
|
+
];
|
|
132
|
+
printTable(["Option", "Description"], options);
|
|
133
|
+
console.log();
|
|
134
|
+
|
|
135
|
+
console.log(`${c.yellow}OUTPUTS${c.reset}`);
|
|
136
|
+
const outputs = [
|
|
137
|
+
[".cursorrules", "Main Cursor rules file"],
|
|
138
|
+
[".cursor/rules/*.mdc", "MDC specification files"],
|
|
139
|
+
[".cursor/skills/", "Auto-generated skills"],
|
|
140
|
+
[".cursor/agents/", "Subagent definitions"],
|
|
141
|
+
[".cursor/hooks/", "Automation hooks"],
|
|
142
|
+
[".windsurf/rules/", "Windsurf rules"],
|
|
143
|
+
[".vibecheck/ai-contract.json", "AI Contract (JSON)"],
|
|
144
|
+
[".vibecheck/AI_CONTRACT.md", "Human-readable contract"],
|
|
145
|
+
[".vibecheck/truth/truthpack.json", "Truthpack"],
|
|
146
|
+
[".vibecheck/forge-manifest.json", "Manifest for incremental"],
|
|
147
|
+
];
|
|
148
|
+
printTable(["File", "Description"], outputs);
|
|
149
|
+
console.log();
|
|
150
|
+
|
|
151
|
+
console.log(`${c.yellow}EXAMPLES${c.reset}`);
|
|
152
|
+
console.log(` ${c.cyan}vibecheck forge${c.reset} ${c.dim}# Standard tier, incremental${c.reset}`);
|
|
153
|
+
console.log(` ${c.cyan}vibecheck forge minimal${c.reset} ${c.dim}# Minimal tier (5 rules)${c.reset}`);
|
|
154
|
+
console.log(` ${c.cyan}vibecheck forge --max-rules=7${c.reset} ${c.dim}# Custom rule count${c.reset}`);
|
|
155
|
+
console.log(` ${c.cyan}vibecheck forge --no-incremental${c.reset} ${c.dim}# Force full regeneration${c.reset}`);
|
|
156
|
+
console.log();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Main forge runner
|
|
161
|
+
*/
|
|
162
|
+
async function runForge(args) {
|
|
163
|
+
const opts = parseArgs(args);
|
|
164
|
+
|
|
165
|
+
if (opts.help) {
|
|
166
|
+
printHelp();
|
|
167
|
+
return 0;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const startTime = Date.now();
|
|
171
|
+
const projectPath = path.resolve(opts.path);
|
|
172
|
+
|
|
173
|
+
// Display header
|
|
174
|
+
console.log();
|
|
175
|
+
printBanner();
|
|
176
|
+
printCommandHeader("FORGE", "AI Brain Generator v1.0");
|
|
177
|
+
|
|
178
|
+
console.log(`${c.dim}Project:${c.reset} ${highlightPath(projectPath)}`);
|
|
179
|
+
console.log(`${c.dim}Tier:${c.reset} ${highlight(opts.tier)} (max ${opts.maxRules} rules)`);
|
|
180
|
+
console.log(`${c.dim}Mode:${c.reset} ${opts.incremental ? "Incremental" : "Full regeneration"}`);
|
|
181
|
+
console.log();
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
// Try to import TypeScript forge module
|
|
185
|
+
let forgeModule;
|
|
186
|
+
try {
|
|
187
|
+
forgeModule = require("../../packages/cli/src/forge");
|
|
188
|
+
} catch {
|
|
189
|
+
// Fall back to JavaScript implementation
|
|
190
|
+
forgeModule = null;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (forgeModule) {
|
|
194
|
+
// Use TypeScript implementation
|
|
195
|
+
const result = await forgeModule.forge(projectPath, opts);
|
|
196
|
+
|
|
197
|
+
printForgeResults(result, opts, startTime);
|
|
198
|
+
return 0;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Fallback: use existing context generator with forge wrapper
|
|
202
|
+
console.log(`${c.yellow}⚡ Using context generator with Forge enhancements...${c.reset}\n`);
|
|
203
|
+
|
|
204
|
+
const { runContext } = require("../../packages/cli/src/context");
|
|
205
|
+
const contextArgs = ["--path", projectPath, "--enhanced"];
|
|
206
|
+
|
|
207
|
+
if (opts.verbose) contextArgs.push("--verbose");
|
|
208
|
+
|
|
209
|
+
const result = await runContext(contextArgs);
|
|
210
|
+
|
|
211
|
+
// Generate additional forge-specific outputs
|
|
212
|
+
if (opts.generateContract) {
|
|
213
|
+
generateSimpleContract(projectPath);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (opts.generateTruthpack) {
|
|
217
|
+
generateSimpleTruthpack(projectPath);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const timeMs = Date.now() - startTime;
|
|
221
|
+
console.log(`\n${c.green}✓ Forge complete in ${timeMs}ms${c.reset}`);
|
|
222
|
+
|
|
223
|
+
return result;
|
|
224
|
+
} catch (error) {
|
|
225
|
+
printError(`Forge failed: ${error.message}`);
|
|
226
|
+
if (opts.verbose) {
|
|
227
|
+
console.error(error.stack);
|
|
228
|
+
}
|
|
229
|
+
return 1;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Print forge results
|
|
235
|
+
*/
|
|
236
|
+
function printForgeResults(result, opts, startTime) {
|
|
237
|
+
const timeMs = Date.now() - startTime;
|
|
238
|
+
|
|
239
|
+
printSectionHeader("FORGE COMPLETE");
|
|
240
|
+
|
|
241
|
+
console.log(`${c.green}🔥 Generated ${result.stats.rulesGenerated} rules in ${timeMs}ms${c.reset}\n`);
|
|
242
|
+
|
|
243
|
+
// Stats
|
|
244
|
+
const statsTable = [
|
|
245
|
+
["Rules Generated", formatNumber(result.stats.rulesGenerated)],
|
|
246
|
+
["Files Written", formatNumber(result.stats.filesWritten)],
|
|
247
|
+
["Rules Skipped", formatNumber(result.stats.rulesSkipped)],
|
|
248
|
+
["Rules Pruned", formatNumber(result.stats.rulesPruned)],
|
|
249
|
+
["Incremental", result.stats.incremental ? "Yes" : "No"],
|
|
250
|
+
["Time", `${timeMs}ms`],
|
|
251
|
+
];
|
|
252
|
+
printTable(["Metric", "Value"], statsTable);
|
|
253
|
+
console.log();
|
|
254
|
+
|
|
255
|
+
// Contract summary
|
|
256
|
+
if (result.contract) {
|
|
257
|
+
console.log(`${c.cyan}📜 AI Contract${c.reset}`);
|
|
258
|
+
console.log(` ${c.dim}Allowed actions:${c.reset} ${result.contract.allowed.length}`);
|
|
259
|
+
console.log(` ${c.dim}Forbidden actions:${c.reset} ${result.contract.forbidden.length}`);
|
|
260
|
+
console.log(` ${c.dim}Critical safety rules:${c.reset} ${result.contract.safetyRules.critical.length}`);
|
|
261
|
+
console.log();
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Truthpack summary
|
|
265
|
+
if (result.truthpack) {
|
|
266
|
+
console.log(`${c.cyan}📦 Truthpack${c.reset}`);
|
|
267
|
+
console.log(` ${c.dim}Sections:${c.reset} ${Object.keys(result.truthpack.sections).length}`);
|
|
268
|
+
console.log(` ${c.dim}Confidence:${c.reset} ${(result.truthpack.confidence * 100).toFixed(1)}%`);
|
|
269
|
+
console.log(` ${c.dim}Issues:${c.reset} ${result.truthpack.validationIssues.length}`);
|
|
270
|
+
console.log();
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Files list
|
|
274
|
+
console.log(`${c.cyan}Generated Files:${c.reset}`);
|
|
275
|
+
result.files.slice(0, 15).forEach((file, idx) => {
|
|
276
|
+
console.log(` ${c.dim}${idx + 1}.${c.reset} ${highlightPath(file)}`);
|
|
277
|
+
});
|
|
278
|
+
if (result.files.length > 15) {
|
|
279
|
+
console.log(` ${c.dim}... and ${result.files.length - 15} more${c.reset}`);
|
|
280
|
+
}
|
|
281
|
+
console.log();
|
|
282
|
+
|
|
283
|
+
// Summary banner
|
|
284
|
+
console.log(`${c.bgGreen}${c.black} 🔥 FORGE v1.0 - Minimal but lethal ${c.reset}\n`);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Generate a simple AI contract
|
|
289
|
+
*/
|
|
290
|
+
function generateSimpleContract(projectPath) {
|
|
291
|
+
const contract = {
|
|
292
|
+
version: "1.0.0",
|
|
293
|
+
generatedAt: new Date().toISOString(),
|
|
294
|
+
projectId: path.basename(projectPath),
|
|
295
|
+
allowed: [
|
|
296
|
+
"Create new files in appropriate directories",
|
|
297
|
+
"Modify existing source code files",
|
|
298
|
+
"Add or update dependencies",
|
|
299
|
+
"Create and run tests",
|
|
300
|
+
],
|
|
301
|
+
forbidden: [
|
|
302
|
+
"Commit secrets or credentials to code",
|
|
303
|
+
"Disable security checks",
|
|
304
|
+
"Use `any` type in TypeScript",
|
|
305
|
+
"Skip error handling",
|
|
306
|
+
],
|
|
307
|
+
requiresConfirmation: [
|
|
308
|
+
"Delete any file",
|
|
309
|
+
"Modify database schema",
|
|
310
|
+
"Change authentication logic",
|
|
311
|
+
],
|
|
312
|
+
fileBoundaries: {
|
|
313
|
+
mayCreate: ["src/**/*", "tests/**/*"],
|
|
314
|
+
mayNotModify: [".env", "*.lock", "node_modules/**"],
|
|
315
|
+
restrictedPatterns: ["**/auth/**", "**/config/**"],
|
|
316
|
+
},
|
|
317
|
+
codeStandards: {
|
|
318
|
+
mustFollow: ["Use TypeScript", "Follow existing patterns"],
|
|
319
|
+
mustAvoid: ["any type", "console.log in production"],
|
|
320
|
+
preferredPatterns: ["Functional components", "Custom hooks"],
|
|
321
|
+
},
|
|
322
|
+
safetyRules: {
|
|
323
|
+
critical: ["Never commit secrets", "Always validate input"],
|
|
324
|
+
high: ["Handle errors explicitly", "Use HTTPS"],
|
|
325
|
+
standard: ["Keep dependencies updated", "Write tests"],
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const vibecheckDir = path.join(projectPath, ".vibecheck");
|
|
330
|
+
if (!fs.existsSync(vibecheckDir)) {
|
|
331
|
+
fs.mkdirSync(vibecheckDir, { recursive: true });
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
fs.writeFileSync(
|
|
335
|
+
path.join(vibecheckDir, "ai-contract.json"),
|
|
336
|
+
JSON.stringify(contract, null, 2)
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
// Write human-readable version
|
|
340
|
+
const contractMd = `# AI Contract
|
|
341
|
+
|
|
342
|
+
> This document defines what AI agents may and may not do in this repository.
|
|
343
|
+
> Generated by Forge v1.0
|
|
344
|
+
|
|
345
|
+
## Permissions
|
|
346
|
+
|
|
347
|
+
### Allowed Actions
|
|
348
|
+
${contract.allowed.map(a => `- ✅ ${a}`).join("\n")}
|
|
349
|
+
|
|
350
|
+
### Forbidden Actions
|
|
351
|
+
${contract.forbidden.map(f => `- ❌ ${f}`).join("\n")}
|
|
352
|
+
|
|
353
|
+
### Requires Confirmation
|
|
354
|
+
${contract.requiresConfirmation.map(r => `- ⚠️ ${r}`).join("\n")}
|
|
355
|
+
|
|
356
|
+
## Safety Rules
|
|
357
|
+
|
|
358
|
+
### Critical (Never Violate)
|
|
359
|
+
${contract.safetyRules.critical.map(r => `- 🔴 ${r}`).join("\n")}
|
|
360
|
+
|
|
361
|
+
### High Priority
|
|
362
|
+
${contract.safetyRules.high.map(r => `- 🟠 ${r}`).join("\n")}
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
*Generated at: ${contract.generatedAt}*
|
|
366
|
+
`;
|
|
367
|
+
|
|
368
|
+
fs.writeFileSync(path.join(vibecheckDir, "AI_CONTRACT.md"), contractMd);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Generate a simple truthpack
|
|
373
|
+
*/
|
|
374
|
+
function generateSimpleTruthpack(projectPath) {
|
|
375
|
+
const truthpack = {
|
|
376
|
+
version: "2.0.0",
|
|
377
|
+
generatedAt: new Date().toISOString(),
|
|
378
|
+
projectPath: projectPath,
|
|
379
|
+
contentHash: crypto.createHash("sha256").update(projectPath).digest("hex").slice(0, 16),
|
|
380
|
+
sections: {
|
|
381
|
+
routes: { server: [], clientRefs: [], serverOnly: [], clientOnly: [], methodMismatches: [] },
|
|
382
|
+
env: { declared: [], used: [], unused: [], missing: [], sensitive: [] },
|
|
383
|
+
components: { components: [], maxDepth: 0, orphans: [] },
|
|
384
|
+
graph: { modules: {}, cycles: [], entryPoints: [], shared: [] },
|
|
385
|
+
},
|
|
386
|
+
confidence: 0.75,
|
|
387
|
+
validationIssues: [],
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
const truthDir = path.join(projectPath, ".vibecheck", "truth");
|
|
391
|
+
if (!fs.existsSync(truthDir)) {
|
|
392
|
+
fs.mkdirSync(truthDir, { recursive: true });
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
fs.writeFileSync(
|
|
396
|
+
path.join(truthDir, "truthpack.json"),
|
|
397
|
+
JSON.stringify(truthpack, null, 2)
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
module.exports = { runForge };
|
|
402
|
+
|
|
403
|
+
// Run if called directly
|
|
404
|
+
if (require.main === module) {
|
|
405
|
+
runForge(process.argv.slice(2))
|
|
406
|
+
.then(code => process.exit(code))
|
|
407
|
+
.catch(err => {
|
|
408
|
+
console.error(err);
|
|
409
|
+
process.exit(1);
|
|
410
|
+
});
|
|
411
|
+
}
|