@letterblack/lbe-exec 1.2.16 → 1.2.17

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/dist/cli.js CHANGED
@@ -404,7 +404,7 @@ var init_localPolicy = __esm({
404
404
  "src/core/localPolicy.js"() {
405
405
  init_auditLog();
406
406
  init_atomicWrite();
407
- POLICY_FILE = "lbe.policy.json";
407
+ POLICY_FILE = ".lbe/policy.json";
408
408
  AUDIT_FILE = ".lbe/audit.jsonl";
409
409
  }
410
410
  });
@@ -2363,12 +2363,8 @@ This project has LetterBlack LBE (Local-first execution Governance) active.
2363
2363
 
2364
2364
  ## Your role as an agent
2365
2365
 
2366
- You do not have direct access to the file system or shell in this workspace.
2367
- Every file write, file read, file delete, and shell command must go through the
2368
- LBE executor. The executor validates every action against the project policy,
2369
- signs it, audits it, and either allows or blocks it \u2014 transparently.
2370
-
2371
- You do not need to know how this works. You only need to use the right methods.
2366
+ Every file write, delete, and shell command must go through the LBE executor.
2367
+ The executor validates each action against the project policy and audits it.
2372
2368
 
2373
2369
  ## How to perform actions
2374
2370
 
@@ -2376,143 +2372,83 @@ You do not need to know how this works. You only need to use the right methods.
2376
2372
  import { createLocalExecutor } from '@letterblack/lbe-exec';
2377
2373
  const lbe = createLocalExecutor({ rootDir: process.cwd() });
2378
2374
 
2379
- // File operations
2380
2375
  await lbe.writeFile('output/report.md', content);
2381
2376
  await lbe.readFile('src/config.json');
2382
2377
  await lbe.patchFile('src/index.js', patch);
2383
2378
  await lbe.deleteFile('tmp/scratch.txt');
2384
-
2385
- // Shell (only explicitly allowlisted commands run)
2386
2379
  await lbe.runShell('node', ['scripts/build.js']);
2387
2380
  \`\`\`
2388
2381
 
2389
2382
  ## What you must never do
2390
2383
 
2391
- - Call file system APIs directly (fs.writeFile, fs.readFile, etc.)
2392
- - Call child_process or exec directly
2393
- - Modify \`lbe.policy.json\` directly \u2014 propose a rule via \`lbe.policy.proposeRule()\`
2394
- - Attempt to bypass, patch, or disable the executor
2395
-
2396
- ## Proposing a new policy rule
2384
+ - Call fs.* or child_process.* directly
2385
+ - Modify \`.lbe/policy.json\` directly \u2014 propose a rule via \`lbe.policy.proposeRule()\`
2386
+ - Attempt to bypass or disable the executor
2397
2387
 
2398
- If you believe a rule should be added or removed, propose it and let the
2399
- controller decide:
2388
+ ## Proposing a policy rule
2400
2389
 
2401
2390
  \`\`\`js
2402
2391
  const proposal = lbe.policy.proposeRule({
2403
- effect: 'deny',
2404
- type: 'path',
2405
- pattern: 'secrets/**',
2392
+ effect: 'deny', type: 'path', pattern: 'secrets/**',
2406
2393
  from: 'agent: these files should never be modified'
2407
2394
  });
2408
- // Return proposal to the user. Never call lbe.policy.addRule() yourself.
2395
+ // Return proposal to the user \u2014 never call lbe.policy.addRule() yourself.
2409
2396
  \`\`\`
2410
2397
 
2411
2398
  ## Result shape
2412
2399
 
2413
- Every method returns:
2414
- \`\`\`
2415
- { ok: boolean, decision: 'allow' | 'deny' | 'observe', executed: boolean }
2416
- \`\`\`
2417
-
2418
- If \`ok\` is false, the action was blocked. Check \`result.error.message\` for reason.
2400
+ \`{ ok: boolean, decision: 'allow' | 'deny' | 'observe', executed: boolean }\`
2419
2401
 
2420
- ## Current policy
2402
+ ## Files
2421
2403
 
2422
- See \`lbe.policy.json\` in the project root.
2423
- See \`.lbe/audit.jsonl\` for the execution audit trail.
2424
-
2425
- ## CLI
2426
-
2427
- \`\`\`bash
2428
- npx lbe-exec status # mode, rule count, audit entry count
2429
- npx lbe-exec policy # list active rules
2430
- npx lbe-exec observe # switch to observer mode
2431
- npx lbe-exec enforce # switch to enforcement mode
2432
- \`\`\`
2404
+ - Policy: \`.lbe/policy.json\`
2405
+ - Audit: \`.lbe/audit.jsonl\`
2406
+ - Status: \`npx lbe-exec status\`
2433
2407
  `;
2434
2408
  }
2435
- function claudeMdSection() {
2436
- return `<!-- lbe-governance -->
2437
- ## LBE Execution Governance
2438
-
2439
- This project has LetterBlack LBE active. All file and shell operations must
2440
- route through the LBE executor \u2014 do not use file system tools directly.
2441
-
2442
- ### Use these methods
2443
-
2444
- \`\`\`js
2445
- import { createLocalExecutor } from '@letterblack/lbe-exec';
2446
- const lbe = createLocalExecutor({ rootDir: process.cwd() });
2447
-
2448
- await lbe.writeFile('path/to/file', content);
2449
- await lbe.readFile('path/to/file');
2450
- await lbe.patchFile('path/to/file', patch);
2451
- await lbe.deleteFile('path/to/file');
2452
- await lbe.runShell('node', ['script.js']);
2453
- \`\`\`
2454
-
2455
- ### Rules
2456
-
2457
- - Never call \`fs.*\` or \`child_process.*\` directly
2458
- - Never write to \`lbe.policy.json\` directly \u2014 use \`lbe.policy.proposeRule()\`
2459
- - Every blocked action has a reason in \`result.error.message\`
2460
- - Audit trail is in \`.lbe/audit.jsonl\`
2461
-
2462
- See \`.lbe/AGENT_CONTRACT.md\` for the full agent contract.
2463
- <!-- /lbe-governance -->`;
2464
- }
2465
- function copilotInstructionsContent() {
2466
- return `# LBE Governance \u2014 Copilot Instructions
2467
-
2468
- This project has LetterBlack LBE active. All file and shell operations must
2469
- route through the LBE executor.
2470
-
2471
- ## Required
2472
-
2473
- Use \`@letterblack/lbe-exec\` for all file and shell actions:
2474
-
2475
- \`\`\`js
2476
- const lbe = createLocalExecutor({ rootDir: process.cwd() });
2477
- await lbe.writeFile(path, content);
2478
- await lbe.readFile(path);
2479
- await lbe.runShell(cmd, args);
2480
- \`\`\`
2481
-
2482
- ## Forbidden
2483
-
2484
- - Direct \`fs.*\` calls
2485
- - Direct \`child_process.*\` or \`exec\` calls
2486
- - Writing to \`lbe.policy.json\` directly
2487
-
2488
- See \`.lbe/AGENT_CONTRACT.md\` for the full contract.
2489
- `;
2490
- }
2491
- function writeAgentGovernanceFiles(cwd) {
2409
+ function writeAgentContract(cwd) {
2492
2410
  const lbeDir = path4.join(cwd, ".lbe");
2493
2411
  fs4.mkdirSync(lbeDir, { recursive: true });
2494
2412
  fs4.writeFileSync(path4.join(lbeDir, "AGENT_CONTRACT.md"), agentContractContent());
2495
- const claudePath = path4.join(cwd, "CLAUDE.md");
2496
- const section = claudeMdSection();
2497
- if (fs4.existsSync(claudePath)) {
2498
- const existing = fs4.readFileSync(claudePath, "utf8");
2499
- if (!existing.includes("<!-- lbe-governance -->")) {
2500
- fs4.appendFileSync(claudePath, "\n\n" + section + "\n");
2413
+ }
2414
+ function migrateLegacyRootFiles(cwd) {
2415
+ const lbeDir = path4.join(cwd, ".lbe");
2416
+ fs4.mkdirSync(lbeDir, { recursive: true });
2417
+ const migrations = [
2418
+ ["lbe.policy.json", ".lbe/policy.json"],
2419
+ ["lbe.workspace.json", ".lbe/workspace.json"]
2420
+ ];
2421
+ const removed = [];
2422
+ for (const [src, dest] of migrations) {
2423
+ const srcPath = path4.join(cwd, src);
2424
+ const destPath = path4.join(cwd, dest);
2425
+ if (fs4.existsSync(srcPath) && !fs4.existsSync(destPath)) {
2426
+ fs4.renameSync(srcPath, destPath);
2427
+ removed.push(src + " \u2192 " + dest);
2428
+ } else if (fs4.existsSync(srcPath)) {
2429
+ fs4.unlinkSync(srcPath);
2430
+ removed.push(src + " (removed \u2014 .lbe/ version exists)");
2431
+ }
2432
+ }
2433
+ const toDelete = ["CLAUDE.md", path4.join(".github", "copilot-instructions.md")];
2434
+ for (const rel of toDelete) {
2435
+ const p = path4.join(cwd, rel);
2436
+ if (fs4.existsSync(p)) {
2437
+ const content = fs4.readFileSync(p, "utf8");
2438
+ if (content.includes("lbe-governance") || content.includes("LetterBlack LBE")) {
2439
+ fs4.unlinkSync(p);
2440
+ removed.push(rel + " (removed \u2014 LBE-generated file)");
2441
+ }
2501
2442
  }
2502
- } else {
2503
- fs4.writeFileSync(claudePath, section + "\n");
2504
- }
2505
- const githubDir = path4.join(cwd, ".github");
2506
- fs4.mkdirSync(githubDir, { recursive: true });
2507
- const copilotPath = path4.join(githubDir, "copilot-instructions.md");
2508
- if (!fs4.existsSync(copilotPath)) {
2509
- fs4.writeFileSync(copilotPath, copilotInstructionsContent());
2510
2443
  }
2444
+ return removed;
2511
2445
  }
2512
2446
  async function initCommand(opts2 = {}) {
2513
2447
  const cwd = process.cwd();
2514
2448
  const yes = opts2.yes || opts2.y || !process.stdin.isTTY;
2515
- const outPath = path4.join(cwd, "lbe.workspace.json");
2449
+ const lbeDir = path4.join(cwd, ".lbe");
2450
+ fs4.mkdirSync(lbeDir, { recursive: true });
2451
+ const outPath = path4.join(lbeDir, "workspace.json");
2516
2452
  console.log("\nScanning workspace...\n");
2517
2453
  const { projectTypes, primaryType: primaryType2, semantics, enforcement } = scanWorkspace(cwd);
2518
2454
  console.log(formatSummary(projectTypes, semantics, enforcement));
@@ -2537,21 +2473,24 @@ async function initCommand(opts2 = {}) {
2537
2473
  enforcement: finalEnforcement
2538
2474
  };
2539
2475
  fs4.writeFileSync(outPath, JSON.stringify(contract, null, 2));
2540
- console.log("\u2713 Wrote lbe.workspace.json");
2476
+ console.log("\u2713 Wrote .lbe/workspace.json");
2541
2477
  setupCrypto(cwd);
2542
- const localPolicyPath = path4.join(cwd, "lbe.policy.json");
2478
+ const localPolicyPath = path4.join(lbeDir, "policy.json");
2543
2479
  if (!fs4.existsSync(localPolicyPath)) {
2544
2480
  fs4.writeFileSync(localPolicyPath, JSON.stringify({ version: 1, mode: "observe", workspace: cwd, rules: [] }, null, 2) + "\n");
2545
2481
  }
2546
- const localAuditPath = path4.join(cwd, ".lbe", "audit.jsonl");
2482
+ const localAuditPath = path4.join(lbeDir, "audit.jsonl");
2547
2483
  if (!fs4.existsSync(localAuditPath)) fs4.writeFileSync(localAuditPath, "");
2548
- console.log("\u2713 Keys and policy ready");
2549
- writeAgentGovernanceFiles(cwd);
2484
+ console.log("\u2713 Keys and policy ready (.lbe/)");
2485
+ writeAgentContract(cwd);
2550
2486
  console.log("\u2713 Agent contract written \u2192 .lbe/AGENT_CONTRACT.md");
2551
- console.log("\u2713 CLAUDE.md updated with LBE governance section");
2552
- console.log("\u2713 .github/copilot-instructions.md ready\n");
2553
- console.log("Done. Any AI agent that reads project context will follow LBE governance automatically.");
2554
- console.log("Run npx lbe status to see mode, rules, and audit entry count.\n");
2487
+ const migrated = migrateLegacyRootFiles(cwd);
2488
+ if (migrated.length) {
2489
+ console.log("\n\u2713 Migrated legacy files:");
2490
+ for (const m of migrated) console.log(" " + m);
2491
+ }
2492
+ console.log("\nDone. All LBE state is in .lbe/");
2493
+ console.log("Run npx lbe-exec status to verify.\n");
2555
2494
  return { success: true, contract };
2556
2495
  }
2557
2496
 
@@ -2571,7 +2510,8 @@ var opts = Object.fromEntries(
2571
2510
  var positional = rest.filter((v) => !v.startsWith("--") && rest[rest.indexOf(v) - 1]?.startsWith("--") === false);
2572
2511
  var __dir = path15.dirname(fileURLToPath2(import.meta.url));
2573
2512
  function loadPolicy() {
2574
- const p = path15.join(process.cwd(), "lbe.policy.json");
2513
+ const cwd = process.cwd();
2514
+ const p = fs14.existsSync(path15.join(cwd, ".lbe", "policy.json")) ? path15.join(cwd, ".lbe", "policy.json") : path15.join(cwd, "lbe.policy.json");
2575
2515
  return fs14.existsSync(p) ? JSON.parse(fs14.readFileSync(p, "utf8")) : null;
2576
2516
  }
2577
2517
  function findHookPath() {
@@ -2895,7 +2835,7 @@ switch (cmd) {
2895
2835
  case "policy": {
2896
2836
  const policy = loadPolicy();
2897
2837
  if (!policy) {
2898
- console.log("No lbe.policy.json found. Run: npx lbe-exec init");
2838
+ console.log("No policy found. Run: npx lbe-exec init");
2899
2839
  break;
2900
2840
  }
2901
2841
  if (!policy.rules?.length) {
package/dist/index.js CHANGED
@@ -1490,7 +1490,7 @@ function verifyAuditLogIntegrity(logPath, options = {}) {
1490
1490
  import fs8 from "fs";
1491
1491
  import path9 from "path";
1492
1492
  import crypto4 from "crypto";
1493
- var POLICY_FILE = "lbe.policy.json";
1493
+ var POLICY_FILE = ".lbe/policy.json";
1494
1494
  var AUDIT_FILE = ".lbe/audit.jsonl";
1495
1495
  function glob(pattern) {
1496
1496
  const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&");
@@ -14,7 +14,10 @@ const MODE = process.env.LBE_MODE || 'observe';
14
14
  // ── Policy loader (inline CJS — ESM cannot be require()'d synchronously) ────
15
15
 
16
16
  function loadPolicy() {
17
- const policyPath = path.join(ROOT_DIR, 'lbe.policy.json');
17
+ // .lbe/policy.json is canonical. Fall back to legacy lbe.policy.json in root.
18
+ const policyPath = fs.existsSync(path.join(ROOT_DIR, '.lbe', 'policy.json'))
19
+ ? path.join(ROOT_DIR, '.lbe', 'policy.json')
20
+ : path.join(ROOT_DIR, 'lbe.policy.json');
18
21
  try {
19
22
  if (fs.existsSync(policyPath)) {
20
23
  return JSON.parse(fs.readFileSync(policyPath, 'utf8'));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letterblack/lbe-exec",
3
- "version": "1.2.16",
3
+ "version": "1.2.17",
4
4
  "description": "Local host-signed execution layer for LetterBlack LBE.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",