@attalabs/vinaya 0.1.1 → 0.1.2

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 (44) hide show
  1. package/aeg-root/contracts/archivist-tranche-archivist.md +92 -0
  2. package/aeg-root/contracts/brief-developer.md +140 -0
  3. package/aeg-root/contracts/developer-reviewer.md +106 -0
  4. package/aeg-root/contracts/planner-brief.md +130 -0
  5. package/aeg-root/contracts/reviewer-archivist.md +96 -0
  6. package/aeg-root/contracts/tranche-archivist-planner.md +116 -0
  7. package/aeg-root/coordination.md +293 -0
  8. package/aeg-root/enforcement.md +159 -0
  9. package/aeg-root/glossary.md +32 -0
  10. package/aeg-root/process.md +371 -0
  11. package/aeg-root/roles/archivist.md +167 -0
  12. package/aeg-root/roles/brief-author.md +108 -0
  13. package/aeg-root/roles/developer.md +429 -0
  14. package/aeg-root/roles/planner.md +285 -0
  15. package/aeg-root/roles/principal.md +107 -0
  16. package/aeg-root/roles/reviewer.md +130 -0
  17. package/aeg-root/roles/security.md +121 -0
  18. package/aeg-root/roles/tranche-archivist.md +257 -0
  19. package/aeg-root/skills/aeg/SKILL.md +90 -0
  20. package/aeg-root/skills/aeg-roles/SKILL.md +58 -0
  21. package/aeg-root/skills/brief-authoring/SKILL.md +497 -0
  22. package/aeg-root/state-machine.md +642 -0
  23. package/aeg-root/templates/brief-template.md +103 -0
  24. package/aeg-root/templates/issue-rationale-template.md +35 -0
  25. package/aeg-root/templates/pr-report-template.md +68 -0
  26. package/aeg-root/tranche-model.md +304 -0
  27. package/dist/checks/bin/check-branch-topology.js +2840 -0
  28. package/dist/checks/bin/check-brief-shape.js +2775 -0
  29. package/dist/checks/bin/check-closes-n.js +2824 -0
  30. package/dist/checks/bin/check-coherence.js +2922 -0
  31. package/dist/checks/bin/check-dead-branch-push.js +2799 -0
  32. package/dist/checks/bin/check-dispatch-readiness.js +2923 -0
  33. package/dist/checks/bin/check-doc-coverage-push.js +2818 -0
  34. package/dist/checks/bin/check-doc-coverage.js +2816 -0
  35. package/dist/checks/bin/check-first-push-dispatch.js +2888 -0
  36. package/dist/checks/bin/check-issue-assignment.js +2863 -0
  37. package/dist/checks/bin/check-no-disk-state.js +2811 -0
  38. package/dist/checks/bin/check-reader-resolvable-prose.js +2820 -0
  39. package/dist/checks/bin/check-registry-gates.js +2923 -0
  40. package/dist/checks/bin/check-review-gate.js +2826 -0
  41. package/dist/checks/bin/check-single-plan-pr.js +2810 -0
  42. package/dist/checks/bin/check-test-plan.js +2775 -0
  43. package/dist/index.js +110 -94
  44. package/package.json +4 -2
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { readFileSync as readFileSync11 } from "node:fs";
5
- import { dirname as dirname5, join as join14 } from "node:path";
5
+ import { dirname as dirname5, join as join15 } from "node:path";
6
6
  import { fileURLToPath as fileURLToPath2 } from "node:url";
7
7
 
8
8
  // src/commands/archive.ts
@@ -1244,6 +1244,7 @@ function emitCheckError(error) {
1244
1244
  }
1245
1245
 
1246
1246
  // src/checks/registry.ts
1247
+ import { existsSync as existsSync3 } from "node:fs";
1247
1248
  import { join as join3 } from "node:path";
1248
1249
 
1249
1250
  // src/lib/package-root.ts
@@ -1262,96 +1263,102 @@ function packageRoot(moduleUrl) {
1262
1263
  }
1263
1264
 
1264
1265
  // src/checks/registry.ts
1265
- var BIN_DIR = join3(packageRoot(import.meta.url), "src", "checks", "bin");
1266
+ var DIST_BIN_DIR = join3(packageRoot(import.meta.url), "dist", "checks", "bin");
1267
+ var SRC_BIN_DIR = join3(packageRoot(import.meta.url), "src", "checks", "bin");
1268
+ var BIN_DIR = existsSync3(DIST_BIN_DIR) ? DIST_BIN_DIR : SRC_BIN_DIR;
1269
+ var BIN_EXT = BIN_DIR === DIST_BIN_DIR ? ".js" : ".ts";
1270
+ function bin(name) {
1271
+ return join3(BIN_DIR, `${name}${BIN_EXT}`);
1272
+ }
1266
1273
  function coreCheckRegistry() {
1267
1274
  return [
1268
1275
  {
1269
1276
  name: "brief-shape",
1270
- run: join3(BIN_DIR, "check-brief-shape.ts"),
1277
+ run: bin("check-brief-shape"),
1271
1278
  scope: "diff",
1272
1279
  timeoutMs: 15000
1273
1280
  },
1274
1281
  {
1275
1282
  name: "doc-coverage",
1276
- run: join3(BIN_DIR, "check-doc-coverage.ts"),
1283
+ run: bin("check-doc-coverage"),
1277
1284
  scope: "diff",
1278
1285
  timeoutMs: 15000
1279
1286
  },
1280
1287
  {
1281
1288
  name: "coherence",
1282
- run: join3(BIN_DIR, "check-coherence.ts"),
1289
+ run: bin("check-coherence"),
1283
1290
  scope: "full",
1284
1291
  timeoutMs: 30000
1285
1292
  },
1286
1293
  {
1287
1294
  name: "dispatch-readiness",
1288
- run: join3(BIN_DIR, "check-dispatch-readiness.ts"),
1295
+ run: bin("check-dispatch-readiness"),
1289
1296
  scope: "full",
1290
1297
  timeoutMs: 30000
1291
1298
  },
1292
1299
  {
1293
1300
  name: "closes-n",
1294
- run: join3(BIN_DIR, "check-closes-n.ts"),
1301
+ run: bin("check-closes-n"),
1295
1302
  scope: "diff",
1296
1303
  timeoutMs: 15000
1297
1304
  },
1298
1305
  {
1299
1306
  name: "single-plan-pr",
1300
- run: join3(BIN_DIR, "check-single-plan-pr.ts"),
1307
+ run: bin("check-single-plan-pr"),
1301
1308
  scope: "diff",
1302
1309
  timeoutMs: 15000
1303
1310
  },
1304
1311
  {
1305
1312
  name: "test-plan",
1306
- run: join3(BIN_DIR, "check-test-plan.ts"),
1313
+ run: bin("check-test-plan"),
1307
1314
  scope: "diff",
1308
1315
  timeoutMs: 15000
1309
1316
  },
1310
1317
  {
1311
1318
  name: "no-disk-state",
1312
- run: join3(BIN_DIR, "check-no-disk-state.ts"),
1319
+ run: bin("check-no-disk-state"),
1313
1320
  scope: "diff",
1314
1321
  timeoutMs: 15000
1315
1322
  },
1316
1323
  {
1317
1324
  name: "registry-gates",
1318
- run: join3(BIN_DIR, "check-registry-gates.ts"),
1325
+ run: bin("check-registry-gates"),
1319
1326
  scope: "full",
1320
1327
  timeoutMs: 30000
1321
1328
  },
1322
1329
  {
1323
1330
  name: "review-gate",
1324
- run: join3(BIN_DIR, "check-review-gate.ts"),
1331
+ run: bin("check-review-gate"),
1325
1332
  scope: "full",
1326
1333
  timeoutMs: 30000
1327
1334
  },
1328
1335
  {
1329
1336
  name: "branch-topology",
1330
- run: join3(BIN_DIR, "check-branch-topology.ts"),
1337
+ run: bin("check-branch-topology"),
1331
1338
  scope: "full",
1332
1339
  timeoutMs: 30000
1333
1340
  },
1334
1341
  {
1335
1342
  name: "dead-branch-push",
1336
- run: join3(BIN_DIR, "check-dead-branch-push.ts"),
1343
+ run: bin("check-dead-branch-push"),
1337
1344
  scope: "full",
1338
1345
  timeoutMs: 30000
1339
1346
  },
1340
1347
  {
1341
1348
  name: "first-push-dispatch",
1342
- run: join3(BIN_DIR, "check-first-push-dispatch.ts"),
1349
+ run: bin("check-first-push-dispatch"),
1343
1350
  scope: "full",
1344
1351
  timeoutMs: 30000
1345
1352
  },
1346
1353
  {
1347
1354
  name: "doc-coverage-push",
1348
- run: join3(BIN_DIR, "check-doc-coverage-push.ts"),
1355
+ run: bin("check-doc-coverage-push"),
1349
1356
  scope: "diff",
1350
1357
  timeoutMs: 15000
1351
1358
  },
1352
1359
  {
1353
1360
  name: "issue-assignment",
1354
- run: join3(BIN_DIR, "check-issue-assignment.ts"),
1361
+ run: bin("check-issue-assignment"),
1355
1362
  scope: "full",
1356
1363
  timeoutMs: 30000
1357
1364
  }
@@ -1487,7 +1494,7 @@ async function runChecks(specs, opts) {
1487
1494
  }
1488
1495
 
1489
1496
  // src/lib/config.ts
1490
- import { existsSync as existsSync3, mkdirSync, readFileSync, writeFileSync } from "node:fs";
1497
+ import { existsSync as existsSync4, mkdirSync, readFileSync, writeFileSync } from "node:fs";
1491
1498
  import { homedir } from "node:os";
1492
1499
  import { dirname as dirname2, join as join4 } from "node:path";
1493
1500
  import { z } from "zod";
@@ -1562,7 +1569,7 @@ function findLocalConfig() {
1562
1569
  let dir = process.cwd();
1563
1570
  while (true) {
1564
1571
  const candidate = join4(dir, LOCAL_CONFIG_FILENAME);
1565
- if (existsSync3(candidate))
1572
+ if (existsSync4(candidate))
1566
1573
  return candidate;
1567
1574
  const parent = dirname2(dir);
1568
1575
  if (parent === dir)
@@ -1574,7 +1581,7 @@ function configPath() {
1574
1581
  const local = findLocalConfig();
1575
1582
  if (local)
1576
1583
  return local;
1577
- if (existsSync3(GLOBAL_CONFIG_PATH))
1584
+ if (existsSync4(GLOBAL_CONFIG_PATH))
1578
1585
  return GLOBAL_CONFIG_PATH;
1579
1586
  return null;
1580
1587
  }
@@ -1688,7 +1695,7 @@ async function checkCommand(args) {
1688
1695
 
1689
1696
  // src/commands/demo.ts
1690
1697
  import { execFileSync as execFileSync5, spawnSync } from "node:child_process";
1691
- import { existsSync as existsSync4, readFileSync as readFileSync2, rmSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
1698
+ import { existsSync as existsSync5, readFileSync as readFileSync2, rmSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
1692
1699
  import { isAbsolute, join as join5 } from "node:path";
1693
1700
  var DEMO_BRANCH_PREFIX = "vinaya/demo-break-";
1694
1701
  var FIXTURE_PATH = ".vinaya-demo-brief.md";
@@ -1696,6 +1703,13 @@ var STATE_FILENAME = "vinaya-demo-state.json";
1696
1703
  function gitCapture(repoRoot, args) {
1697
1704
  return execFileSync5("git", args, { cwd: repoRoot, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
1698
1705
  }
1706
+ function currentBranchName(repoRoot) {
1707
+ try {
1708
+ return gitCapture(repoRoot, ["symbolic-ref", "--short", "HEAD"]);
1709
+ } catch {
1710
+ return "HEAD";
1711
+ }
1712
+ }
1699
1713
  function branchExists(repoRoot, name) {
1700
1714
  try {
1701
1715
  execFileSync5("git", ["rev-parse", "--verify", "--quiet", `refs/heads/${name}`], {
@@ -1722,9 +1736,9 @@ function gitDirAbs(repoRoot) {
1722
1736
  return isAbsolute(raw) ? raw : join5(repoRoot, raw);
1723
1737
  }
1724
1738
  function recoverFromCrash(repoRoot, statePath) {
1725
- const currentBranch = gitCapture(repoRoot, ["rev-parse", "--abbrev-ref", "HEAD"]);
1739
+ const currentBranch = currentBranchName(repoRoot);
1726
1740
  let state = null;
1727
- if (existsSync4(statePath)) {
1741
+ if (existsSync5(statePath)) {
1728
1742
  try {
1729
1743
  state = JSON.parse(readFileSync2(statePath, "utf-8"));
1730
1744
  } catch {
@@ -1796,14 +1810,14 @@ function cleanup(repoRoot, originalBranch, demoBranch, statePath) {
1796
1810
  gitCapture(repoRoot, ["clean", "-fd"]);
1797
1811
  gitCapture(repoRoot, ["checkout", originalBranch]);
1798
1812
  gitCapture(repoRoot, ["branch", "-D", demoBranch]);
1799
- if (existsSync4(statePath))
1813
+ if (existsSync5(statePath))
1800
1814
  rmSync(statePath, { force: true });
1801
1815
  }
1802
1816
  async function runDemoBreak(repoRoot, args) {
1803
1817
  const keep = args.includes("--keep");
1804
1818
  const hookDir = resolveHookDir(repoRoot);
1805
1819
  const hookPath = join5(repoRoot, hookDir, "pre-commit");
1806
- if (!existsSync4(hookPath)) {
1820
+ if (!existsSync5(hookPath)) {
1807
1821
  console.error("Vinaya hooks are not installed in this repo. Run `vinaya init` first.");
1808
1822
  return 1;
1809
1823
  }
@@ -1814,7 +1828,7 @@ async function runDemoBreak(repoRoot, args) {
1814
1828
  console.error("Working tree has uncommitted changes. Commit or stash them before running `vinaya demo break` — " + "the demo never touches a dirty tree.");
1815
1829
  return 1;
1816
1830
  }
1817
- const originalBranch = gitCapture(repoRoot, ["rev-parse", "--abbrev-ref", "HEAD"]);
1831
+ const originalBranch = currentBranchName(repoRoot);
1818
1832
  if (originalBranch === "HEAD") {
1819
1833
  console.error("Cannot run `vinaya demo break` from a detached HEAD — checkout a branch first.");
1820
1834
  return 1;
@@ -1861,7 +1875,7 @@ Attempting to commit…
1861
1875
  process.stdout.write(`✓ Commit passed — the fix worked.
1862
1876
  `);
1863
1877
  if (keep) {
1864
- if (existsSync4(statePath))
1878
+ if (existsSync5(statePath))
1865
1879
  unlinkSync(statePath);
1866
1880
  process.stdout.write(`
1867
1881
  --keep: leaving \`${demoBranch}\` checked out for you to inspect. Clean up with:
@@ -1888,10 +1902,11 @@ async function demoBreakCommand(args) {
1888
1902
  }
1889
1903
 
1890
1904
  // src/commands/doctor.ts
1891
- import { existsSync as existsSync6, readFileSync as readFileSync4, statSync } from "node:fs";
1892
- import { join as join7 } from "node:path";
1905
+ import { existsSync as existsSync7, readFileSync as readFileSync4, statSync } from "node:fs";
1906
+ import { join as join8 } from "node:path";
1893
1907
 
1894
1908
  // src/lib/artifacts.ts
1909
+ import { join as join6 } from "node:path";
1895
1910
  var CONFIG_PATH = "vinaya.config.json";
1896
1911
  var DOCTRINE_POINTER_PATH = "VINAYA.md";
1897
1912
  var CHECKS_WORKFLOW_PATH = ".github/workflows/vinaya-checks.yml";
@@ -2093,15 +2108,14 @@ function prePushBody() {
2093
2108
  npx --no-install @attalabs/vinaya check --all || exit 1`;
2094
2109
  }
2095
2110
  function doctrinePointer() {
2111
+ const doctrineRoot = join6(packageRoot(import.meta.url), "aeg-root");
2096
2112
  return `<!-- ${MANAGED_NOTE} -->
2097
2113
  # Vinaya doctrine — read this first
2098
2114
 
2099
2115
  This repo is governed by Vinaya. The full, canonical doctrine (roles,
2100
- contracts, the state machine, the ring gates) currently lives in the
2101
- \`attalabs\` monorepo's \`aeg-root/\` (public GitHub source) bundling it into
2102
- the installed \`vinaya\` npm package, so it ships and updates cleanly via
2103
- \`vinaya upgrade\` with no in-repo copy to drift, is planned but not yet
2104
- shipped.
2116
+ contracts, the state machine, the ring gates) ships inside the installed
2117
+ \`@attalabs/vinaya\` npm package itself no in-repo copy to drift, and
2118
+ \`vinaya upgrade\` regenerates this pointer if the install location changes.
2105
2119
 
2106
2120
  An agent working in this repo follows the governed flow by reading two things:
2107
2121
 
@@ -2113,10 +2127,12 @@ An agent working in this repo follows the governed flow by reading two things:
2113
2127
  Live task status is derived from the forge (Issues, labels, comments) via
2114
2128
  \`vinaya check\` — it is never written into a file here.
2115
2129
 
2116
- To view the doctrine text today: read \`aeg-root/\` in the \`attalabs\`
2117
- monorepo; \`vinaya doctor\` reports what is installed in this repo. Once
2118
- in-package bundling ships, the package's own reference content becomes the
2119
- source of truth.
2130
+ To read the doctrine text, it is bundled at this install's own resolved
2131
+ path:
2132
+
2133
+ ${doctrineRoot}
2134
+
2135
+ \`vinaya doctor\` reports what is installed in this repo.
2120
2136
  `;
2121
2137
  }
2122
2138
  function starterDocOwners() {
@@ -2256,8 +2272,8 @@ function buildInitProductOps(name) {
2256
2272
  }
2257
2273
 
2258
2274
  // src/lib/ops.ts
2259
- import { chmodSync, existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync3, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
2260
- import { dirname as dirname3, join as join6, resolve, sep } from "node:path";
2275
+ import { chmodSync, existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync3, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
2276
+ import { dirname as dirname3, join as join7, resolve, sep } from "node:path";
2261
2277
  var MARKER_NS = "vinaya:managed";
2262
2278
  function markerLines(marker, comment) {
2263
2279
  const [open, close] = comment === "hash" ? ["#", ""] : ["<!--", " -->"];
@@ -2273,7 +2289,7 @@ ${op.body}
2273
2289
  ${end}`;
2274
2290
  }
2275
2291
  function abs(repoRoot, relPath) {
2276
- return join6(repoRoot, relPath);
2292
+ return join7(repoRoot, relPath);
2277
2293
  }
2278
2294
  function containedAbs(repoRoot, relPath) {
2279
2295
  const root = resolve(repoRoot);
@@ -2284,7 +2300,7 @@ function containedAbs(repoRoot, relPath) {
2284
2300
  }
2285
2301
  function fileContains(repoRoot, relPath, needle) {
2286
2302
  const p = abs(repoRoot, relPath);
2287
- if (!existsSync5(p))
2303
+ if (!existsSync6(p))
2288
2304
  return false;
2289
2305
  return readFileSync3(p, "utf-8").includes(needle);
2290
2306
  }
@@ -2294,7 +2310,7 @@ function planInstall(ops, repoRoot, ownedFiles = new Set) {
2294
2310
  for (const op of ops) {
2295
2311
  switch (op.kind) {
2296
2312
  case "create-file": {
2297
- const exists = existsSync5(abs(repoRoot, op.path));
2313
+ const exists = existsSync6(abs(repoRoot, op.path));
2298
2314
  let action;
2299
2315
  if (!exists)
2300
2316
  action = "create";
@@ -2312,7 +2328,7 @@ function planInstall(ops, repoRoot, ownedFiles = new Set) {
2312
2328
  let action;
2313
2329
  if (fileContains(repoRoot, op.path, begin))
2314
2330
  action = "skip-present";
2315
- else if (existsSync5(abs(repoRoot, op.path)))
2331
+ else if (existsSync6(abs(repoRoot, op.path)))
2316
2332
  action = "append";
2317
2333
  else
2318
2334
  action = "create-host";
@@ -2507,7 +2523,7 @@ function planEject(manifest, repoRoot) {
2507
2523
  escapes.push(b.path);
2508
2524
  continue;
2509
2525
  }
2510
- if (!existsSync5(p)) {
2526
+ if (!existsSync6(p)) {
2511
2527
  actions.push({
2512
2528
  kind: "strip-block",
2513
2529
  path: b.path,
@@ -2536,7 +2552,7 @@ function planEject(manifest, repoRoot) {
2536
2552
  escapes.push(f);
2537
2553
  continue;
2538
2554
  }
2539
- actions.push({ kind: "delete-file", path: f, present: existsSync5(p) });
2555
+ actions.push({ kind: "delete-file", path: f, present: existsSync6(p) });
2540
2556
  }
2541
2557
  for (const name of manifest.labels) {
2542
2558
  actions.push({ kind: "report-label", name });
@@ -2593,7 +2609,7 @@ function applyEject(plan, repoRoot) {
2593
2609
 
2594
2610
  // src/commands/doctor.ts
2595
2611
  function readVersion() {
2596
- const pkg = JSON.parse(readFileSync4(join7(packageRoot(import.meta.url), "package.json"), "utf-8"));
2612
+ const pkg = JSON.parse(readFileSync4(join8(packageRoot(import.meta.url), "package.json"), "utf-8"));
2597
2613
  return pkg.version;
2598
2614
  }
2599
2615
  function realDeps3() {
@@ -2612,8 +2628,8 @@ var info = (check, message) => ({ check, severity: "info", message });
2612
2628
  var warn = (check, message) => ({ check, severity: "warn", message });
2613
2629
  var error = (check, message) => ({ check, severity: "error", message });
2614
2630
  function readConfig(repoRoot) {
2615
- const p = join7(repoRoot, CONFIG_PATH);
2616
- if (!existsSync6(p))
2631
+ const p = join8(repoRoot, CONFIG_PATH);
2632
+ if (!existsSync7(p))
2617
2633
  return { kind: "missing" };
2618
2634
  let raw;
2619
2635
  try {
@@ -2646,8 +2662,8 @@ function diagnoseInstall(repoRoot, ctx, manifest) {
2646
2662
  for (const op of buildInitOps(ctx)) {
2647
2663
  if (op.kind === "create-file") {
2648
2664
  const check = labelForPath(op.path);
2649
- const abs2 = join7(repoRoot, op.path);
2650
- const exists = existsSync6(abs2);
2665
+ const abs2 = join8(repoRoot, op.path);
2666
+ const exists = existsSync7(abs2);
2651
2667
  const owned = ownedFiles.has(op.path);
2652
2668
  if (!exists) {
2653
2669
  findings.push(owned ? error(check, `${op.path} is recorded as vinaya-managed but missing on disk — run \`vinaya upgrade\`.`) : error(check, `${op.path} is not installed — run \`vinaya init\`.`));
@@ -2670,9 +2686,9 @@ function diagnoseInstall(repoRoot, ctx, manifest) {
2670
2686
  }
2671
2687
  } else if (op.kind === "managed-block") {
2672
2688
  const check = "hooks";
2673
- const abs2 = join7(repoRoot, op.path);
2689
+ const abs2 = join8(repoRoot, op.path);
2674
2690
  const owned = ownedBlocks.has(blockKey(op.path, op.marker));
2675
- if (!existsSync6(abs2)) {
2691
+ if (!existsSync7(abs2)) {
2676
2692
  findings.push(owned ? error(check, `${op.path} is missing — likely a fresh clone (raw git hooks aren't tracked by git). Run \`vinaya upgrade\` to restore it.`) : info(check, `${op.path} is not installed.`));
2677
2693
  continue;
2678
2694
  }
@@ -2701,8 +2717,8 @@ function diagnoseInstall(repoRoot, ctx, manifest) {
2701
2717
  function diagnoseCustomChecks(repoRoot, config) {
2702
2718
  const findings = [];
2703
2719
  for (const [name, entry2] of Object.entries(config.checks ?? {})) {
2704
- const scriptAbs = join7(repoRoot, entry2.run);
2705
- findings.push(existsSync6(scriptAbs) ? ok("checks", `custom check '${name}' → ${entry2.run}`) : error("checks", `custom check '${name}' points at a missing script: ${entry2.run}`));
2720
+ const scriptAbs = join8(repoRoot, entry2.run);
2721
+ findings.push(existsSync7(scriptAbs) ? ok("checks", `custom check '${name}' → ${entry2.run}`) : error("checks", `custom check '${name}' points at a missing script: ${entry2.run}`));
2706
2722
  }
2707
2723
  return findings;
2708
2724
  }
@@ -2790,8 +2806,8 @@ async function doctorCommand(args) {
2790
2806
  }
2791
2807
 
2792
2808
  // src/commands/eject.ts
2793
- import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
2794
- import { join as join8 } from "node:path";
2809
+ import { existsSync as existsSync8, readFileSync as readFileSync5 } from "node:fs";
2810
+ import { join as join9 } from "node:path";
2795
2811
 
2796
2812
  // src/lib/prompt.ts
2797
2813
  var stdinBuffer = "";
@@ -2872,8 +2888,8 @@ function parse(args) {
2872
2888
  return { dryRun: args.includes("--dry-run"), yes: args.includes("--yes") };
2873
2889
  }
2874
2890
  function readManifest(repoRoot) {
2875
- const p = join8(repoRoot, CONFIG_PATH);
2876
- if (!existsSync7(p))
2891
+ const p = join9(repoRoot, CONFIG_PATH);
2892
+ if (!existsSync8(p))
2877
2893
  return { kind: "none" };
2878
2894
  let raw;
2879
2895
  try {
@@ -2960,8 +2976,8 @@ async function ejectCommand(args) {
2960
2976
  }
2961
2977
 
2962
2978
  // src/commands/init.ts
2963
- import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "node:fs";
2964
- import { join as join9 } from "node:path";
2979
+ import { existsSync as existsSync9, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "node:fs";
2980
+ import { join as join10 } from "node:path";
2965
2981
  function realDeps5() {
2966
2982
  return {
2967
2983
  detectRepo: detectGitRepo,
@@ -2981,8 +2997,8 @@ function flags(args) {
2981
2997
  }
2982
2998
  var PRODUCT_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
2983
2999
  function readManifest2(repoRoot) {
2984
- const p = join9(repoRoot, CONFIG_PATH);
2985
- if (!existsSync8(p))
3000
+ const p = join10(repoRoot, CONFIG_PATH);
3001
+ if (!existsSync9(p))
2986
3002
  return null;
2987
3003
  try {
2988
3004
  return VinayaConfigSchema.parse(JSON.parse(readFileSync6(p, "utf-8"))).managed ?? null;
@@ -2991,7 +3007,7 @@ function readManifest2(repoRoot) {
2991
3007
  }
2992
3008
  }
2993
3009
  function writeManifest(repoRoot, manifest) {
2994
- const configAbs = join9(repoRoot, CONFIG_PATH);
3010
+ const configAbs = join10(repoRoot, CONFIG_PATH);
2995
3011
  const seed = JSON.parse(readFileSync6(configAbs, "utf-8"));
2996
3012
  writeFileSync4(configAbs, `${JSON.stringify({ ...seed, managed: manifest }, null, 2)}
2997
3013
  `, "utf-8");
@@ -3134,7 +3150,7 @@ import { execFileSync as execFileSync6 } from "node:child_process";
3134
3150
  import { mkdtempSync, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "node:fs";
3135
3151
  import { readFileSync as readFileSync7 } from "node:fs";
3136
3152
  import { tmpdir } from "node:os";
3137
- import { join as join10 } from "node:path";
3153
+ import { join as join11 } from "node:path";
3138
3154
  class ForgeArgError extends Error {
3139
3155
  }
3140
3156
  function locateBody(args) {
@@ -3167,8 +3183,8 @@ function resolveShippableArgs(args, bodyResult) {
3167
3183
  if (bodyResult?.source.kind !== "file") {
3168
3184
  return { finalArgs: args, cleanup: () => {} };
3169
3185
  }
3170
- const dir = mkdtempSync(join10(tmpdir(), "vinaya-forge-body-"));
3171
- const tempPath = join10(dir, "body.md");
3186
+ const dir = mkdtempSync(join11(tmpdir(), "vinaya-forge-body-"));
3187
+ const tempPath = join11(dir, "body.md");
3172
3188
  writeFileSync5(tempPath, bodyResult.body, "utf8");
3173
3189
  const finalArgs = [...args];
3174
3190
  const { argIndex, inlineForm } = bodyResult.source;
@@ -3440,10 +3456,10 @@ function issueEditCommand(args) {
3440
3456
  }
3441
3457
 
3442
3458
  // src/commands/new-check.ts
3443
- import { chmodSync as chmodSync2, existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "node:fs";
3444
- import { join as join11 } from "node:path";
3445
- var TEMPLATE_PATH = join11(packageRoot(import.meta.url), "templates", "custom-check.template.ts");
3446
- var CHECKS_DIR = join11("scripts", "vinaya-checks");
3459
+ import { chmodSync as chmodSync2, existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "node:fs";
3460
+ import { join as join12 } from "node:path";
3461
+ var TEMPLATE_PATH = join12(packageRoot(import.meta.url), "templates", "custom-check.template.ts");
3462
+ var CHECKS_DIR = join12("scripts", "vinaya-checks");
3447
3463
  var VALID_NAME = /^[a-z0-9][a-z0-9-]*$/;
3448
3464
  function newCheckCommand(args) {
3449
3465
  const name = args[0];
@@ -3451,11 +3467,11 @@ function newCheckCommand(args) {
3451
3467
  console.error("Usage: vinaya new check <name> (name: lowercase letters, digits, hyphens)");
3452
3468
  process.exit(2);
3453
3469
  }
3454
- const scriptsDir = join11(process.cwd(), CHECKS_DIR);
3455
- if (!existsSync9(scriptsDir))
3470
+ const scriptsDir = join12(process.cwd(), CHECKS_DIR);
3471
+ if (!existsSync10(scriptsDir))
3456
3472
  mkdirSync3(scriptsDir, { recursive: true });
3457
- const targetPath = join11(scriptsDir, `${name}.ts`);
3458
- if (existsSync9(targetPath)) {
3473
+ const targetPath = join12(scriptsDir, `${name}.ts`);
3474
+ if (existsSync10(targetPath)) {
3459
3475
  console.error(`Error: ${targetPath} already exists.`);
3460
3476
  process.exit(1);
3461
3477
  }
@@ -3463,7 +3479,7 @@ function newCheckCommand(args) {
3463
3479
  const contents = template.split("{{CHECK_NAME}}").join(name);
3464
3480
  writeFileSync6(targetPath, contents, "utf-8");
3465
3481
  chmodSync2(targetPath, 493);
3466
- const relPath = join11(CHECKS_DIR, `${name}.ts`);
3482
+ const relPath = join12(CHECKS_DIR, `${name}.ts`);
3467
3483
  const registration = JSON.stringify({ checks: { [name]: { run: `./${relPath}`, scope: "diff" } } }, null, 2);
3468
3484
  process.stdout.write(`Created ${relPath}
3469
3485
 
@@ -3623,14 +3639,14 @@ function prEditCommand(args) {
3623
3639
 
3624
3640
  // src/commands/studio.ts
3625
3641
  import { spawn as spawn2 } from "node:child_process";
3626
- import { existsSync as existsSync10, readFileSync as readFileSync9 } from "node:fs";
3627
- import { dirname as dirname4, join as join12 } from "node:path";
3642
+ import { existsSync as existsSync11, readFileSync as readFileSync9 } from "node:fs";
3643
+ import { dirname as dirname4, join as join13 } from "node:path";
3628
3644
  function resolveStudioTarget(cwd) {
3629
3645
  let dir = cwd;
3630
3646
  for (;; ) {
3631
- const webDir = join12(dir, "apps", "vinaya", "web");
3632
- const pkgPath = join12(webDir, "package.json");
3633
- if (existsSync10(pkgPath)) {
3647
+ const webDir = join13(dir, "apps", "vinaya", "web");
3648
+ const pkgPath = join13(webDir, "package.json");
3649
+ if (existsSync11(pkgPath)) {
3634
3650
  try {
3635
3651
  const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
3636
3652
  if (pkg.name === "@atta/vinaya-web") {
@@ -3665,8 +3681,8 @@ async function runStudio(cwd, args) {
3665
3681
  }
3666
3682
 
3667
3683
  // src/commands/upgrade.ts
3668
- import { existsSync as existsSync11, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "node:fs";
3669
- import { join as join13 } from "node:path";
3684
+ import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "node:fs";
3685
+ import { join as join14 } from "node:path";
3670
3686
  function realDeps6() {
3671
3687
  return {
3672
3688
  detectRepo: detectGitRepo,
@@ -3682,8 +3698,8 @@ function flags2(args) {
3682
3698
  return { dryRun: args.includes("--dry-run"), yes: args.includes("--yes") };
3683
3699
  }
3684
3700
  function readManifest3(repoRoot) {
3685
- const p = join13(repoRoot, CONFIG_PATH);
3686
- if (!existsSync11(p))
3701
+ const p = join14(repoRoot, CONFIG_PATH);
3702
+ if (!existsSync12(p))
3687
3703
  return { kind: "missing" };
3688
3704
  let raw;
3689
3705
  try {
@@ -3703,7 +3719,7 @@ function readManifest3(repoRoot) {
3703
3719
  return { kind: "ok", manifest: parsed.data.managed };
3704
3720
  }
3705
3721
  function writeManifestVersion(repoRoot, manifest) {
3706
- const configAbs = join13(repoRoot, CONFIG_PATH);
3722
+ const configAbs = join14(repoRoot, CONFIG_PATH);
3707
3723
  const seed = JSON.parse(readFileSync10(configAbs, "utf-8"));
3708
3724
  const updated = { ...manifest, version: MANAGED_MANIFEST_VERSION };
3709
3725
  writeFileSync7(configAbs, `${JSON.stringify({ ...seed, managed: updated }, null, 2)}
@@ -3717,8 +3733,8 @@ function planUpgrade(ops, repoRoot, manifest) {
3717
3733
  const ownedBlocks = new Set(manifest.blocks.map((b) => blockKey(b.path, b.marker)));
3718
3734
  for (const op of ops) {
3719
3735
  if (op.kind === "create-file") {
3720
- const abs2 = join13(repoRoot, op.path);
3721
- const exists = existsSync11(abs2);
3736
+ const abs2 = join14(repoRoot, op.path);
3737
+ const exists = existsSync12(abs2);
3722
3738
  const owned = ownedFiles.has(op.path);
3723
3739
  let action;
3724
3740
  if (op.path === CONFIG_PATH) {
@@ -3736,12 +3752,12 @@ function planUpgrade(ops, repoRoot, manifest) {
3736
3752
  }
3737
3753
  entries.push({ kind: "create-file", op, action });
3738
3754
  } else if (op.kind === "managed-block") {
3739
- const abs2 = join13(repoRoot, op.path);
3755
+ const abs2 = join14(repoRoot, op.path);
3740
3756
  const owned = ownedBlocks.has(blockKey(op.path, op.marker));
3741
3757
  let action;
3742
3758
  if (!owned) {
3743
3759
  action = "not-installed";
3744
- } else if (!existsSync11(abs2)) {
3760
+ } else if (!existsSync12(abs2)) {
3745
3761
  action = "recreate-host";
3746
3762
  hasChanges = true;
3747
3763
  } else {
@@ -3821,7 +3837,7 @@ function renderUpgradeDiff(plan) {
3821
3837
  `);
3822
3838
  }
3823
3839
  function regenerateBlock(repoRoot, op) {
3824
- const abs2 = join13(repoRoot, op.path);
3840
+ const abs2 = join14(repoRoot, op.path);
3825
3841
  const content = readFileSync10(abs2, "utf-8");
3826
3842
  const stripped = stripBlockFromContent(content, op.marker, op.comment);
3827
3843
  if (stripped !== null) {
@@ -3835,7 +3851,7 @@ function applyUpgrade(plan, repoRoot) {
3835
3851
  for (const e of plan.entries) {
3836
3852
  if (e.kind === "create-file") {
3837
3853
  if (e.action === "regenerate" || e.action === "recreate") {
3838
- writeFileWithDirs(join13(repoRoot, e.op.path), e.op.content, e.op.mode);
3854
+ writeFileWithDirs(join14(repoRoot, e.op.path), e.op.content, e.op.mode);
3839
3855
  }
3840
3856
  } else {
3841
3857
  if (e.action === "recreate-host")
@@ -4234,9 +4250,9 @@ function printHelp() {
4234
4250
  }
4235
4251
 
4236
4252
  // src/index.ts
4237
- var PACKAGE_ROOT = join14(dirname5(fileURLToPath2(import.meta.url)), "..");
4253
+ var PACKAGE_ROOT = join15(dirname5(fileURLToPath2(import.meta.url)), "..");
4238
4254
  function readVersion2() {
4239
- const pkg = JSON.parse(readFileSync11(join14(PACKAGE_ROOT, "package.json"), "utf-8"));
4255
+ const pkg = JSON.parse(readFileSync11(join15(PACKAGE_ROOT, "package.json"), "utf-8"));
4240
4256
  return pkg.version;
4241
4257
  }
4242
4258
  var [, , command, ...args] = process.argv;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@attalabs/vinaya",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Vinaya — Agentic Engineering Harness. Deterministic checks every AI coding agent must satisfy before merge.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -11,6 +11,7 @@
11
11
  "files": [
12
12
  "dist",
13
13
  "templates",
14
+ "aeg-root",
14
15
  "README.md"
15
16
  ],
16
17
  "publishConfig": {
@@ -36,7 +37,8 @@
36
37
  },
37
38
  "scripts": {
38
39
  "build": "bun scripts/build.ts",
39
- "prepack": "bun scripts/build.ts",
40
+ "bundle-doctrine": "bun scripts/bundle-doctrine.ts",
41
+ "prepack": "bun scripts/build.ts && bun scripts/bundle-doctrine.ts",
40
42
  "test": "bun test",
41
43
  "typecheck": "tsc --noEmit",
42
44
  "lint": "biome check src tests scripts",