codebyplan 1.13.38 → 1.13.39

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
@@ -14,7 +14,7 @@ var VERSION, PACKAGE_NAME;
14
14
  var init_version = __esm({
15
15
  "src/lib/version.ts"() {
16
16
  "use strict";
17
- VERSION = "1.13.38";
17
+ VERSION = "1.13.39";
18
18
  PACKAGE_NAME = "codebyplan";
19
19
  }
20
20
  });
@@ -3134,6 +3134,11 @@ async function writeCodebyplanDirectory(projectPath, selectedRepo, deviceId) {
3134
3134
  JSON.stringify({}, null, 2) + "\n",
3135
3135
  "utf-8"
3136
3136
  );
3137
+ await writeFile7(
3138
+ join12(codebyplanDir, "architecture.json"),
3139
+ JSON.stringify({ version: 1, modules: [] }, null, 2) + "\n",
3140
+ "utf-8"
3141
+ );
3137
3142
  const statuslinePath = join12(codebyplanDir, "statusline.json");
3138
3143
  let statuslineExists = false;
3139
3144
  try {
@@ -3151,7 +3156,7 @@ async function writeCodebyplanDirectory(projectPath, selectedRepo, deviceId) {
3151
3156
  await writeLocalConfig(projectPath, { device_id: deviceId });
3152
3157
  console.log(` Created ${codebyplanDir}/`);
3153
3158
  console.log(
3154
- ` repo.json, server.json, git.json, shipment.json, vendor.json, e2e.json, eslint.json, statusline.json`
3159
+ ` repo.json, server.json, git.json, shipment.json, vendor.json, e2e.json, eslint.json, architecture.json, statusline.json`
3155
3160
  );
3156
3161
  console.log(` device.local.json (gitignored)`);
3157
3162
  const gitignoreAction = await ensureManagedGitignoreBlock(projectPath);
@@ -7142,6 +7147,425 @@ var init_upload_e2e_images = __esm({
7142
7147
  }
7143
7148
  });
7144
7149
 
7150
+ // src/cli/arch-map.ts
7151
+ var arch_map_exports = {};
7152
+ __export(arch_map_exports, {
7153
+ mapFileSlug: () => mapFileSlug,
7154
+ runArchMapCommand: () => runArchMapCommand,
7155
+ updateFrontmatterFields: () => updateFrontmatterFields
7156
+ });
7157
+ import { readFile as readFile17, writeFile as writeFile13 } from "node:fs/promises";
7158
+ import { existsSync as existsSync5, readdirSync as readdirSync2 } from "node:fs";
7159
+ import { join as join23 } from "node:path";
7160
+ import { spawnSync as spawnSync7 } from "node:child_process";
7161
+ function normalizeModulePath(modulePath) {
7162
+ return modulePath.replace(/\/+$/, "");
7163
+ }
7164
+ function repoRootFromCodebyplanDir(codebyplanDir) {
7165
+ return codebyplanDir.endsWith("/.codebyplan") ? codebyplanDir.slice(0, codebyplanDir.lastIndexOf("/")) : codebyplanDir;
7166
+ }
7167
+ function mapFileSlug(modulePath) {
7168
+ const slug = modulePath.replace(/\//g, "-").replace(/^\./, "dot-");
7169
+ return `${slug}.md`;
7170
+ }
7171
+ async function resolveCodebyplanDir(startDir) {
7172
+ try {
7173
+ const found = await findCodebyplanConfig(startDir);
7174
+ if (!found) return null;
7175
+ if (found.path.endsWith("/repo.json")) {
7176
+ return found.path.slice(0, found.path.lastIndexOf("/"));
7177
+ }
7178
+ return found.path.slice(0, found.path.lastIndexOf("/"));
7179
+ } catch {
7180
+ return null;
7181
+ }
7182
+ }
7183
+ async function readArchitectureConfig(codebyplanDir) {
7184
+ const filePath = join23(codebyplanDir, "architecture.json");
7185
+ try {
7186
+ const raw = await readFile17(filePath, "utf-8");
7187
+ const parsed = JSON.parse(raw);
7188
+ if (typeof parsed !== "object" || parsed === null || !Array.isArray(parsed.modules)) {
7189
+ return { version: 1, modules: [] };
7190
+ }
7191
+ return parsed;
7192
+ } catch {
7193
+ return { version: 1, modules: [] };
7194
+ }
7195
+ }
7196
+ async function writeArchitectureConfig(codebyplanDir, config) {
7197
+ const filePath = join23(codebyplanDir, "architecture.json");
7198
+ await writeFile13(filePath, JSON.stringify(config, null, 2) + "\n", "utf-8");
7199
+ }
7200
+ function resolveGitSha(modulePath, cwd) {
7201
+ try {
7202
+ const result = spawnSync7(
7203
+ "git",
7204
+ ["log", "--format=%H", "-1", "--", modulePath],
7205
+ { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
7206
+ );
7207
+ if (result.status !== 0 || result.error) return null;
7208
+ const sha = (result.stdout ?? "").trim();
7209
+ return sha.length > 0 ? sha : null;
7210
+ } catch {
7211
+ return null;
7212
+ }
7213
+ }
7214
+ async function discoverModulePaths(projectRoot) {
7215
+ const paths = [];
7216
+ const workspacePath = join23(projectRoot, "pnpm-workspace.yaml");
7217
+ let patterns = [];
7218
+ try {
7219
+ const raw = await readFile17(workspacePath, "utf-8");
7220
+ const lines = raw.split("\n");
7221
+ let inPackages = false;
7222
+ for (const line of lines) {
7223
+ const trimmed = line.trim();
7224
+ if (trimmed.split("#")[0].trim() === "packages:") {
7225
+ inPackages = true;
7226
+ continue;
7227
+ }
7228
+ if (inPackages) {
7229
+ if (trimmed.startsWith("-")) {
7230
+ const pat = trimmed.slice(1).trim().replace(/['"]/g, "");
7231
+ patterns.push(pat);
7232
+ } else if (trimmed && !trimmed.startsWith("#")) {
7233
+ break;
7234
+ }
7235
+ }
7236
+ }
7237
+ } catch {
7238
+ patterns = ["apps/*", "packages/*"];
7239
+ }
7240
+ for (const pattern of patterns) {
7241
+ if (pattern.endsWith("/*")) {
7242
+ const dir = pattern.slice(0, -2);
7243
+ const absDir = join23(projectRoot, dir);
7244
+ try {
7245
+ if (existsSync5(absDir)) {
7246
+ const entries = readdirSync2(absDir, { withFileTypes: true });
7247
+ for (const entry of entries) {
7248
+ if (entry.isDirectory()) {
7249
+ paths.push(`${dir}/${entry.name}`);
7250
+ }
7251
+ }
7252
+ }
7253
+ } catch {
7254
+ }
7255
+ } else if (!pattern.includes("*")) {
7256
+ const absPath = join23(projectRoot, pattern);
7257
+ if (existsSync5(absPath)) {
7258
+ paths.push(pattern);
7259
+ }
7260
+ }
7261
+ }
7262
+ const crossCutting = ["supabase", ".github", "scripts"];
7263
+ for (const dir of crossCutting) {
7264
+ const absPath = join23(projectRoot, dir);
7265
+ try {
7266
+ if (existsSync5(absPath)) {
7267
+ paths.push(dir);
7268
+ }
7269
+ } catch {
7270
+ }
7271
+ }
7272
+ return paths;
7273
+ }
7274
+ async function runStatus(projectRoot) {
7275
+ console.log("\n CodeByPlan arch-map status\n");
7276
+ try {
7277
+ const codebyplanDir = await resolveCodebyplanDir(projectRoot);
7278
+ const repoRoot = codebyplanDir ? repoRootFromCodebyplanDir(codebyplanDir) : projectRoot;
7279
+ const config = codebyplanDir ? await readArchitectureConfig(codebyplanDir) : { version: 1, modules: [] };
7280
+ const manifestByPath = /* @__PURE__ */ new Map();
7281
+ for (const entry of config.modules) {
7282
+ manifestByPath.set(normalizeModulePath(entry.path), entry);
7283
+ }
7284
+ let modulePaths = [];
7285
+ try {
7286
+ modulePaths = await discoverModulePaths(repoRoot);
7287
+ } catch {
7288
+ console.warn(" Warning: could not discover modules from workspace");
7289
+ }
7290
+ if (modulePaths.length === 0 && config.modules.length === 0) {
7291
+ console.log(" No modules found.\n");
7292
+ return;
7293
+ }
7294
+ const allPaths = /* @__PURE__ */ new Set([
7295
+ ...modulePaths.map(normalizeModulePath),
7296
+ ...config.modules.map((e) => normalizeModulePath(e.path))
7297
+ ]);
7298
+ console.log(
7299
+ " Module".padEnd(40) + "Map".padEnd(8) + "Stamped".padEnd(12) + "Status"
7300
+ );
7301
+ console.log(" " + "-".repeat(70));
7302
+ for (const modPath of allPaths) {
7303
+ const entry = manifestByPath.get(modPath);
7304
+ const hasMap = !!entry;
7305
+ const stamped = entry?.generated_from_sha != null;
7306
+ let freshness = "-";
7307
+ if (stamped && entry) {
7308
+ const currentSha = resolveGitSha(modPath, repoRoot);
7309
+ if (currentSha == null) {
7310
+ freshness = "unknown";
7311
+ } else if (currentSha === entry.generated_from_sha) {
7312
+ freshness = "fresh";
7313
+ } else {
7314
+ freshness = "stale";
7315
+ }
7316
+ }
7317
+ console.log(
7318
+ " " + modPath.padEnd(38) + (hasMap ? "yes" : "no").padEnd(8) + (stamped ? "yes" : "no").padEnd(12) + freshness
7319
+ );
7320
+ }
7321
+ console.log();
7322
+ } catch (err) {
7323
+ console.warn(
7324
+ ` Warning: arch-map status error: ${err instanceof Error ? err.message : String(err)}`
7325
+ );
7326
+ }
7327
+ }
7328
+ async function runDrift(projectRoot) {
7329
+ console.log("\n CodeByPlan arch-map drift\n");
7330
+ try {
7331
+ const codebyplanDir = await resolveCodebyplanDir(projectRoot);
7332
+ if (!codebyplanDir) {
7333
+ console.log(" No .codebyplan/ directory found \u2014 no manifest to check.");
7334
+ console.log();
7335
+ return;
7336
+ }
7337
+ const repoRoot = repoRootFromCodebyplanDir(codebyplanDir);
7338
+ const config = await readArchitectureConfig(codebyplanDir);
7339
+ const stamped = config.modules.filter((e) => e.generated_from_sha != null);
7340
+ if (stamped.length === 0) {
7341
+ console.log(" No stamped modules found \u2014 run arch-map stamp first.");
7342
+ console.log();
7343
+ return;
7344
+ }
7345
+ let driftCount = 0;
7346
+ for (const entry of stamped) {
7347
+ const currentSha = resolveGitSha(entry.path, repoRoot);
7348
+ if (currentSha == null) {
7349
+ console.log(
7350
+ ` ? ${entry.path} \u2014 could not resolve current SHA (git unavailable or path not tracked)`
7351
+ );
7352
+ continue;
7353
+ }
7354
+ if (currentSha !== entry.generated_from_sha) {
7355
+ console.log(` DRIFTED ${entry.path}`);
7356
+ console.log(` stamped: ${entry.generated_from_sha}`);
7357
+ console.log(` current: ${currentSha}`);
7358
+ driftCount++;
7359
+ }
7360
+ }
7361
+ if (driftCount === 0) {
7362
+ console.log(" All stamped modules are fresh.");
7363
+ } else {
7364
+ console.log(`
7365
+ ${driftCount} module(s) have drifted since last stamp.`);
7366
+ }
7367
+ console.log();
7368
+ } catch (err) {
7369
+ console.warn(
7370
+ ` Warning: arch-map drift error: ${err instanceof Error ? err.message : String(err)}`
7371
+ );
7372
+ }
7373
+ }
7374
+ function updateFrontmatterFields(content, fields) {
7375
+ const lines = content.split("\n");
7376
+ if (lines.length === 0 || lines[0] !== "---") {
7377
+ return null;
7378
+ }
7379
+ let closeIndex = -1;
7380
+ for (let i = 1; i < lines.length; i++) {
7381
+ if (lines[i] === "---") {
7382
+ closeIndex = i;
7383
+ break;
7384
+ }
7385
+ }
7386
+ if (closeIndex === -1) {
7387
+ return null;
7388
+ }
7389
+ const result = lines.map((line, idx) => {
7390
+ if (idx === 0 || idx >= closeIndex) {
7391
+ return line;
7392
+ }
7393
+ if (/^generated_from_sha:\s*/.test(line)) {
7394
+ return `generated_from_sha: ${fields.generated_from_sha}`;
7395
+ }
7396
+ if (/^generated_at:\s*/.test(line)) {
7397
+ return `generated_at: ${fields.generated_at}`;
7398
+ }
7399
+ if (fields.depth !== void 0 && /^depth:\s*/.test(line)) {
7400
+ return `depth: ${fields.depth}`;
7401
+ }
7402
+ return line;
7403
+ });
7404
+ return result.join("\n");
7405
+ }
7406
+ async function runStamp(modulePath, sha, depthArg, projectRoot) {
7407
+ const codebyplanDir = await resolveCodebyplanDir(projectRoot);
7408
+ if (!codebyplanDir) {
7409
+ process.stderr.write(
7410
+ " Error: no .codebyplan/ directory found. Run `codebyplan setup` first.\n"
7411
+ );
7412
+ process.exit(1);
7413
+ }
7414
+ const repoRoot = repoRootFromCodebyplanDir(codebyplanDir);
7415
+ let resolvedSha = sha;
7416
+ if (!resolvedSha) {
7417
+ resolvedSha = resolveGitSha(modulePath, repoRoot);
7418
+ if (!resolvedSha) {
7419
+ process.stderr.write(
7420
+ ` Error: could not resolve SHA for ${modulePath}. Provide --sha <value>.
7421
+ `
7422
+ );
7423
+ process.exit(1);
7424
+ }
7425
+ }
7426
+ const config = await readArchitectureConfig(codebyplanDir);
7427
+ const now = (/* @__PURE__ */ new Date()).toISOString();
7428
+ const mapFile = mapFileSlug(modulePath);
7429
+ const mapFilePath = `.claude/architecture/${mapFile}`;
7430
+ const existingIndex = config.modules.findIndex((e) => e.path === modulePath);
7431
+ if (existingIndex >= 0) {
7432
+ config.modules[existingIndex] = {
7433
+ ...config.modules[existingIndex],
7434
+ map_file: mapFilePath,
7435
+ generated_from_sha: resolvedSha,
7436
+ generated_at: now,
7437
+ ...depthArg !== null ? { depth: depthArg } : {}
7438
+ };
7439
+ } else {
7440
+ config.modules.push({
7441
+ path: modulePath,
7442
+ map_file: mapFilePath,
7443
+ generated_from_sha: resolvedSha,
7444
+ depth: depthArg ?? "skeleton",
7445
+ generated_at: now
7446
+ });
7447
+ }
7448
+ await writeArchitectureConfig(codebyplanDir, config);
7449
+ const stampedEntry = existingIndex >= 0 ? config.modules[existingIndex] : config.modules[config.modules.length - 1];
7450
+ const mapAbsPath = join23(repoRoot, stampedEntry.map_file);
7451
+ let mapContent = null;
7452
+ try {
7453
+ mapContent = await readFile17(mapAbsPath, "utf-8");
7454
+ } catch {
7455
+ console.warn(
7456
+ " Warning: map file " + stampedEntry.map_file + " not found \u2014 stamped manifest only"
7457
+ );
7458
+ }
7459
+ if (mapContent !== null) {
7460
+ const updated = updateFrontmatterFields(mapContent, {
7461
+ generated_from_sha: resolvedSha,
7462
+ generated_at: now,
7463
+ ...depthArg !== null ? { depth: depthArg } : {}
7464
+ });
7465
+ if (updated === null) {
7466
+ console.warn(
7467
+ " Warning: no frontmatter block in " + stampedEntry.map_file + " \u2014 stamped manifest only"
7468
+ );
7469
+ } else if (!updated.includes(`generated_from_sha: ${resolvedSha}`) || !updated.includes(`generated_at: ${now}`)) {
7470
+ console.warn(
7471
+ " Warning: " + stampedEntry.map_file + " frontmatter missing generated_from_sha/generated_at \u2014 not mirrored (manifest stamped)"
7472
+ );
7473
+ } else {
7474
+ try {
7475
+ await writeFile13(mapAbsPath, updated, "utf-8");
7476
+ } catch (writeErr) {
7477
+ console.warn(
7478
+ " Warning: could not write map file " + stampedEntry.map_file + " \u2014 " + (writeErr instanceof Error ? writeErr.message : String(writeErr)) + " \u2014 stamped manifest only"
7479
+ );
7480
+ }
7481
+ }
7482
+ }
7483
+ console.log(` Stamped ${modulePath} @ ${resolvedSha.slice(0, 8)} (${now})`);
7484
+ }
7485
+ async function runArchMapCommand(rest) {
7486
+ const subcommand = rest[0];
7487
+ const projectRoot = process.cwd();
7488
+ if (subcommand === "status") {
7489
+ await runStatus(projectRoot);
7490
+ return;
7491
+ }
7492
+ if (subcommand === "drift") {
7493
+ await runDrift(projectRoot);
7494
+ return;
7495
+ }
7496
+ if (subcommand === "stamp") {
7497
+ const rawModulePath = rest[1];
7498
+ if (!rawModulePath) {
7499
+ process.stderr.write(
7500
+ " Usage: codebyplan arch-map stamp <module> [--sha <value>]\n"
7501
+ );
7502
+ process.exit(1);
7503
+ }
7504
+ if (rawModulePath.startsWith("/")) {
7505
+ process.stderr.write(
7506
+ " Error: module path must be relative to the repo root (e.g. apps/web), not absolute.\n"
7507
+ );
7508
+ process.exit(1);
7509
+ }
7510
+ const modulePath = normalizeModulePath(rawModulePath);
7511
+ if (modulePath.split("/").length > 2) {
7512
+ console.warn(
7513
+ ` Warning: ${modulePath} has more than 2 path segments; expected a top-level module path (e.g. apps/web).`
7514
+ );
7515
+ }
7516
+ let sha = null;
7517
+ const shaIdx = rest.indexOf("--sha");
7518
+ if (shaIdx !== -1) {
7519
+ const shaVal = rest[shaIdx + 1];
7520
+ if (!shaVal || shaVal.startsWith("--")) {
7521
+ process.stderr.write(" Error: --sha requires a value.\n");
7522
+ process.exit(1);
7523
+ }
7524
+ if (!/^[0-9a-f]{40}$/i.test(shaVal)) {
7525
+ process.stderr.write(
7526
+ " Error: --sha value does not look like a git SHA (expected 40 hex chars).\n"
7527
+ );
7528
+ process.exit(1);
7529
+ }
7530
+ sha = shaVal;
7531
+ }
7532
+ let depthArg = null;
7533
+ const depthIdx = rest.indexOf("--depth");
7534
+ if (depthIdx !== -1) {
7535
+ const depthVal = rest[depthIdx + 1];
7536
+ if (!depthVal || depthVal.startsWith("--")) {
7537
+ process.stderr.write(" Error: --depth requires a value.\n");
7538
+ process.exit(1);
7539
+ }
7540
+ if (depthVal !== "skeleton" && depthVal !== "deep") {
7541
+ process.stderr.write(" Error: --depth must be skeleton or deep.\n");
7542
+ process.exit(1);
7543
+ }
7544
+ depthArg = depthVal;
7545
+ }
7546
+ await runStamp(modulePath, sha, depthArg, projectRoot);
7547
+ return;
7548
+ }
7549
+ console.log(`
7550
+ codebyplan arch-map \u2014 Architecture map pipeline
7551
+
7552
+ Note: arch-map commands are intended to run from the repo root.
7553
+
7554
+ Usage:
7555
+ codebyplan arch-map status List all modules and map freshness
7556
+ codebyplan arch-map drift Report modules drifted since last stamp
7557
+ codebyplan arch-map stamp <module> Stamp a module with its current git SHA
7558
+ codebyplan arch-map stamp <module> --sha <sha> Stamp with an explicit SHA
7559
+ codebyplan arch-map stamp <module> --depth <skeleton|deep> Stamp with an explicit depth
7560
+ `);
7561
+ }
7562
+ var init_arch_map = __esm({
7563
+ "src/cli/arch-map.ts"() {
7564
+ "use strict";
7565
+ init_flags();
7566
+ }
7567
+ });
7568
+
7145
7569
  // src/lib/worktree-port-resolver.ts
7146
7570
  async function resolveWorktreePortAllocations(repoId, projectPath) {
7147
7571
  let resolvedWorktreeId;
@@ -7231,19 +7655,19 @@ var init_worktree_port_resolver = __esm({
7231
7655
  });
7232
7656
 
7233
7657
  // src/lib/migrate-local-config.ts
7234
- import { mkdir as mkdir7, readFile as readFile17, unlink as unlink3, writeFile as writeFile13 } from "node:fs/promises";
7235
- import { join as join23 } from "node:path";
7658
+ import { mkdir as mkdir7, readFile as readFile18, unlink as unlink3, writeFile as writeFile14 } from "node:fs/promises";
7659
+ import { join as join24 } from "node:path";
7236
7660
  function legacySharedPath(projectPath) {
7237
- return join23(projectPath, ".codebyplan.json");
7661
+ return join24(projectPath, ".codebyplan.json");
7238
7662
  }
7239
7663
  function legacyLocalPath(projectPath) {
7240
- return join23(projectPath, ".codebyplan.local.json");
7664
+ return join24(projectPath, ".codebyplan.local.json");
7241
7665
  }
7242
7666
  function newDirPath(projectPath) {
7243
- return join23(projectPath, ".codebyplan");
7667
+ return join24(projectPath, ".codebyplan");
7244
7668
  }
7245
7669
  function sentinelPath(projectPath) {
7246
- return join23(projectPath, ".codebyplan", "repo.json");
7670
+ return join24(projectPath, ".codebyplan", "repo.json");
7247
7671
  }
7248
7672
  async function statSafe(p) {
7249
7673
  const { stat: stat2 } = await import("node:fs/promises");
@@ -7282,7 +7706,7 @@ async function runLocalMigration(projectPath) {
7282
7706
  }
7283
7707
  let legacyRaw;
7284
7708
  try {
7285
- legacyRaw = await readFile17(legacySharedPath(projectPath), "utf-8");
7709
+ legacyRaw = await readFile18(legacySharedPath(projectPath), "utf-8");
7286
7710
  } catch {
7287
7711
  return {
7288
7712
  migrated: true,
@@ -7309,7 +7733,7 @@ async function runLocalMigration(projectPath) {
7309
7733
  let deviceId;
7310
7734
  let deviceWrittenByHelper = false;
7311
7735
  try {
7312
- const localRaw = await readFile17(legacyLocalPath(projectPath), "utf-8");
7736
+ const localRaw = await readFile18(legacyLocalPath(projectPath), "utf-8");
7313
7737
  const localParsed = JSON.parse(localRaw);
7314
7738
  if (typeof localParsed.device_id === "string") {
7315
7739
  deviceId = localParsed.device_id;
@@ -7336,8 +7760,8 @@ async function runLocalMigration(projectPath) {
7336
7760
  if ("repo_id" in cfg) repoJson.repo_id = cfg.repo_id;
7337
7761
  if ("organization_id" in cfg) repoJson.organization_id = cfg.organization_id;
7338
7762
  if ("project_id" in cfg) repoJson.project_id = cfg.project_id;
7339
- await writeFile13(
7340
- join23(projectPath, ".codebyplan", "repo.json"),
7763
+ await writeFile14(
7764
+ join24(projectPath, ".codebyplan", "repo.json"),
7341
7765
  JSON.stringify(repoJson, null, 2) + "\n",
7342
7766
  "utf-8"
7343
7767
  );
@@ -7349,8 +7773,8 @@ async function runLocalMigration(projectPath) {
7349
7773
  serverJson.auto_push_enabled = cfg.auto_push_enabled;
7350
7774
  if ("port_allocations" in cfg)
7351
7775
  serverJson.port_allocations = cfg.port_allocations;
7352
- await writeFile13(
7353
- join23(projectPath, ".codebyplan", "server.json"),
7776
+ await writeFile14(
7777
+ join24(projectPath, ".codebyplan", "server.json"),
7354
7778
  JSON.stringify(serverJson, null, 2) + "\n",
7355
7779
  "utf-8"
7356
7780
  );
@@ -7358,44 +7782,44 @@ async function runLocalMigration(projectPath) {
7358
7782
  const gitJson = {};
7359
7783
  if ("git_branch" in cfg) gitJson.git_branch = cfg.git_branch;
7360
7784
  if ("branch_config" in cfg) gitJson.branch_config = cfg.branch_config;
7361
- await writeFile13(
7362
- join23(projectPath, ".codebyplan", "git.json"),
7785
+ await writeFile14(
7786
+ join24(projectPath, ".codebyplan", "git.json"),
7363
7787
  JSON.stringify(gitJson, null, 2) + "\n",
7364
7788
  "utf-8"
7365
7789
  );
7366
7790
  filesChanged.push(".codebyplan/git.json");
7367
7791
  const shipmentJson = {};
7368
7792
  if ("shipment" in cfg) shipmentJson.shipment = cfg.shipment;
7369
- await writeFile13(
7370
- join23(projectPath, ".codebyplan", "shipment.json"),
7793
+ await writeFile14(
7794
+ join24(projectPath, ".codebyplan", "shipment.json"),
7371
7795
  JSON.stringify(shipmentJson, null, 2) + "\n",
7372
7796
  "utf-8"
7373
7797
  );
7374
7798
  filesChanged.push(".codebyplan/shipment.json");
7375
7799
  const vendorJson = {};
7376
- await writeFile13(
7377
- join23(projectPath, ".codebyplan", "vendor.json"),
7800
+ await writeFile14(
7801
+ join24(projectPath, ".codebyplan", "vendor.json"),
7378
7802
  JSON.stringify(vendorJson, null, 2) + "\n",
7379
7803
  "utf-8"
7380
7804
  );
7381
7805
  filesChanged.push(".codebyplan/vendor.json");
7382
7806
  const e2eJson = {};
7383
- await writeFile13(
7384
- join23(projectPath, ".codebyplan", "e2e.json"),
7807
+ await writeFile14(
7808
+ join24(projectPath, ".codebyplan", "e2e.json"),
7385
7809
  JSON.stringify(e2eJson, null, 2) + "\n",
7386
7810
  "utf-8"
7387
7811
  );
7388
7812
  filesChanged.push(".codebyplan/e2e.json");
7389
7813
  const eslintJson = {};
7390
- await writeFile13(
7391
- join23(projectPath, ".codebyplan", "eslint.json"),
7814
+ await writeFile14(
7815
+ join24(projectPath, ".codebyplan", "eslint.json"),
7392
7816
  JSON.stringify(eslintJson, null, 2) + "\n",
7393
7817
  "utf-8"
7394
7818
  );
7395
7819
  filesChanged.push(".codebyplan/eslint.json");
7396
7820
  if (!deviceWrittenByHelper) {
7397
- await writeFile13(
7398
- join23(projectPath, ".codebyplan", "device.local.json"),
7821
+ await writeFile14(
7822
+ join24(projectPath, ".codebyplan", "device.local.json"),
7399
7823
  JSON.stringify({ device_id: deviceId }, null, 2) + "\n",
7400
7824
  "utf-8"
7401
7825
  );
@@ -7407,9 +7831,9 @@ async function runLocalMigration(projectPath) {
7407
7831
  "Migration write incomplete: .codebyplan/repo.json was not persisted. Re-run migration to retry from a clean state."
7408
7832
  );
7409
7833
  }
7410
- const gitignorePath = join23(projectPath, ".gitignore");
7834
+ const gitignorePath = join24(projectPath, ".gitignore");
7411
7835
  try {
7412
- const gitignoreContent = await readFile17(gitignorePath, "utf-8");
7836
+ const gitignoreContent = await readFile18(gitignorePath, "utf-8");
7413
7837
  const legacyLine = ".codebyplan.local.json";
7414
7838
  const newLine = ".codebyplan/device.local.json";
7415
7839
  const hasLegacy = gitignoreContent.split("\n").some((l) => l.trimEnd() === legacyLine);
@@ -7428,7 +7852,7 @@ async function runLocalMigration(projectPath) {
7428
7852
  updated = gitignoreContent;
7429
7853
  }
7430
7854
  if (updated !== gitignoreContent) {
7431
- await writeFile13(gitignorePath, updated, "utf-8");
7855
+ await writeFile14(gitignorePath, updated, "utf-8");
7432
7856
  filesChanged.push(".gitignore");
7433
7857
  }
7434
7858
  } catch {
@@ -7469,8 +7893,8 @@ __export(config_exports, {
7469
7893
  readVendorConfig: () => readVendorConfig,
7470
7894
  runConfig: () => runConfig
7471
7895
  });
7472
- import { mkdir as mkdir8, readFile as readFile18, writeFile as writeFile14 } from "node:fs/promises";
7473
- import { join as join24 } from "node:path";
7896
+ import { mkdir as mkdir8, readFile as readFile19, writeFile as writeFile15 } from "node:fs/promises";
7897
+ import { join as join25 } from "node:path";
7474
7898
  async function runConfig() {
7475
7899
  const flags = parseFlags(3);
7476
7900
  const dryRun = hasFlag("dry-run", 3);
@@ -7503,7 +7927,7 @@ async function runConfig() {
7503
7927
  console.log("\n Config complete.\n");
7504
7928
  }
7505
7929
  async function syncConfigToFile(repoId, projectPath, dryRun) {
7506
- const codebyplanDir = join24(projectPath, ".codebyplan");
7930
+ const codebyplanDir = join25(projectPath, ".codebyplan");
7507
7931
  const {
7508
7932
  resolvedWorktreeId,
7509
7933
  portAllocations,
@@ -7571,6 +7995,10 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
7571
7995
  const vendorPayload = {};
7572
7996
  const e2ePayload = {};
7573
7997
  const eslintPayload = {};
7998
+ const architecturePayload = {
7999
+ version: 1,
8000
+ modules: []
8001
+ };
7574
8002
  if (dryRun) {
7575
8003
  console.log(" Config would be updated (dry-run).");
7576
8004
  return;
@@ -7583,20 +8011,25 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
7583
8011
  { name: "shipment.json", payload: shipmentPayload },
7584
8012
  { name: "vendor.json", payload: vendorPayload },
7585
8013
  { name: "e2e.json", payload: e2ePayload, createOnly: true },
7586
- { name: "eslint.json", payload: eslintPayload, createOnly: true }
8014
+ { name: "eslint.json", payload: eslintPayload, createOnly: true },
8015
+ {
8016
+ name: "architecture.json",
8017
+ payload: architecturePayload,
8018
+ createOnly: true
8019
+ }
7587
8020
  ];
7588
8021
  let anyUpdated = false;
7589
8022
  for (const { name, payload, createOnly } of files) {
7590
- const filePath = join24(codebyplanDir, name);
8023
+ const filePath = join25(codebyplanDir, name);
7591
8024
  const newJson = JSON.stringify(payload, null, 2) + "\n";
7592
8025
  let currentJson = "";
7593
8026
  try {
7594
- currentJson = await readFile18(filePath, "utf-8");
8027
+ currentJson = await readFile19(filePath, "utf-8");
7595
8028
  } catch {
7596
8029
  }
7597
8030
  if (createOnly && currentJson !== "") continue;
7598
8031
  if (currentJson === newJson) continue;
7599
- await writeFile14(filePath, newJson, "utf-8");
8032
+ await writeFile15(filePath, newJson, "utf-8");
7600
8033
  console.log(` Updated .codebyplan/${name}`);
7601
8034
  anyUpdated = true;
7602
8035
  }
@@ -7606,8 +8039,8 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
7606
8039
  }
7607
8040
  async function readRepoConfig(projectPath) {
7608
8041
  try {
7609
- const raw = await readFile18(
7610
- join24(projectPath, ".codebyplan", "repo.json"),
8042
+ const raw = await readFile19(
8043
+ join25(projectPath, ".codebyplan", "repo.json"),
7611
8044
  "utf-8"
7612
8045
  );
7613
8046
  return JSON.parse(raw);
@@ -7617,8 +8050,8 @@ async function readRepoConfig(projectPath) {
7617
8050
  }
7618
8051
  async function readServerConfig(projectPath) {
7619
8052
  try {
7620
- const raw = await readFile18(
7621
- join24(projectPath, ".codebyplan", "server.json"),
8053
+ const raw = await readFile19(
8054
+ join25(projectPath, ".codebyplan", "server.json"),
7622
8055
  "utf-8"
7623
8056
  );
7624
8057
  return JSON.parse(raw);
@@ -7628,8 +8061,8 @@ async function readServerConfig(projectPath) {
7628
8061
  }
7629
8062
  async function readGitConfig(projectPath) {
7630
8063
  try {
7631
- const raw = await readFile18(
7632
- join24(projectPath, ".codebyplan", "git.json"),
8064
+ const raw = await readFile19(
8065
+ join25(projectPath, ".codebyplan", "git.json"),
7633
8066
  "utf-8"
7634
8067
  );
7635
8068
  return JSON.parse(raw);
@@ -7639,8 +8072,8 @@ async function readGitConfig(projectPath) {
7639
8072
  }
7640
8073
  async function readShipmentConfig(projectPath) {
7641
8074
  try {
7642
- const raw = await readFile18(
7643
- join24(projectPath, ".codebyplan", "shipment.json"),
8075
+ const raw = await readFile19(
8076
+ join25(projectPath, ".codebyplan", "shipment.json"),
7644
8077
  "utf-8"
7645
8078
  );
7646
8079
  return JSON.parse(raw);
@@ -7650,8 +8083,8 @@ async function readShipmentConfig(projectPath) {
7650
8083
  }
7651
8084
  async function readVendorConfig(projectPath) {
7652
8085
  try {
7653
- const raw = await readFile18(
7654
- join24(projectPath, ".codebyplan", "vendor.json"),
8086
+ const raw = await readFile19(
8087
+ join25(projectPath, ".codebyplan", "vendor.json"),
7655
8088
  "utf-8"
7656
8089
  );
7657
8090
  return JSON.parse(raw);
@@ -7661,8 +8094,8 @@ async function readVendorConfig(projectPath) {
7661
8094
  }
7662
8095
  async function readE2eConfig2(projectPath) {
7663
8096
  try {
7664
- const raw = await readFile18(
7665
- join24(projectPath, ".codebyplan", "e2e.json"),
8097
+ const raw = await readFile19(
8098
+ join25(projectPath, ".codebyplan", "e2e.json"),
7666
8099
  "utf-8"
7667
8100
  );
7668
8101
  return JSON.parse(raw);
@@ -7672,8 +8105,8 @@ async function readE2eConfig2(projectPath) {
7672
8105
  }
7673
8106
  async function readServerLocalConfig(projectPath) {
7674
8107
  try {
7675
- const raw = await readFile18(
7676
- join24(projectPath, ".codebyplan", "server.local.json"),
8108
+ const raw = await readFile19(
8109
+ join25(projectPath, ".codebyplan", "server.local.json"),
7677
8110
  "utf-8"
7678
8111
  );
7679
8112
  return JSON.parse(raw);
@@ -7728,14 +8161,14 @@ var init_server_detect = __esm({
7728
8161
  });
7729
8162
 
7730
8163
  // src/lib/port-verify.ts
7731
- import { readFile as readFile19 } from "node:fs/promises";
8164
+ import { readFile as readFile20 } from "node:fs/promises";
7732
8165
  async function verifyPorts(projectPath, portAllocations) {
7733
8166
  const mismatches = [];
7734
8167
  const allocatedPorts = new Set(portAllocations.map((a) => a.port));
7735
8168
  const packageJsonPaths = await findPackageJsonFiles(projectPath, projectPath);
7736
8169
  for (const pkgPath of packageJsonPaths) {
7737
8170
  try {
7738
- const raw = await readFile19(pkgPath, "utf-8");
8171
+ const raw = await readFile20(pkgPath, "utf-8");
7739
8172
  const pkg = JSON.parse(raw);
7740
8173
  const scriptPort = detectPortFromScripts(pkg);
7741
8174
  if (scriptPort !== null && !allocatedPorts.has(scriptPort)) {
@@ -7798,7 +8231,7 @@ async function findUnallocatedApps(projectPath, portAllocations) {
7798
8231
  }
7799
8232
  let pkg;
7800
8233
  try {
7801
- const raw = await readFile19(`${app.absPath}/package.json`, "utf-8");
8234
+ const raw = await readFile20(`${app.absPath}/package.json`, "utf-8");
7802
8235
  pkg = JSON.parse(raw);
7803
8236
  } catch {
7804
8237
  continue;
@@ -7848,8 +8281,8 @@ __export(ports_exports, {
7848
8281
  parseEnvFile: () => parseEnvFile,
7849
8282
  runPorts: () => runPorts
7850
8283
  });
7851
- import { mkdir as mkdir9, readFile as readFile20, writeFile as writeFile15 } from "node:fs/promises";
7852
- import { join as join25 } from "node:path";
8284
+ import { mkdir as mkdir9, readFile as readFile21, writeFile as writeFile16 } from "node:fs/promises";
8285
+ import { join as join26 } from "node:path";
7853
8286
  async function runPorts() {
7854
8287
  const flags = parseFlags(3);
7855
8288
  const dryRun = hasFlag("dry-run", 3);
@@ -7970,12 +8403,12 @@ async function writeServerLocalConfig(repoId, projectPath, dryRun) {
7970
8403
  // and ServerLocalConfig.port_allocations is typed the same — honest end-to-end.
7971
8404
  port_allocations: portAllocations
7972
8405
  };
7973
- const codebyplanDir = join25(projectPath, ".codebyplan");
7974
- const filePath = join25(codebyplanDir, "server.local.json");
8406
+ const codebyplanDir = join26(projectPath, ".codebyplan");
8407
+ const filePath = join26(codebyplanDir, "server.local.json");
7975
8408
  const newJson = JSON.stringify(payload, null, 2) + "\n";
7976
8409
  let currentJson = "";
7977
8410
  try {
7978
- currentJson = await readFile20(filePath, "utf-8");
8411
+ currentJson = await readFile21(filePath, "utf-8");
7979
8412
  } catch {
7980
8413
  }
7981
8414
  if (currentJson === newJson) {
@@ -7987,17 +8420,17 @@ async function writeServerLocalConfig(repoId, projectPath, dryRun) {
7987
8420
  return;
7988
8421
  }
7989
8422
  await mkdir9(codebyplanDir, { recursive: true });
7990
- await writeFile15(filePath, newJson, "utf-8");
8423
+ await writeFile16(filePath, newJson, "utf-8");
7991
8424
  console.log(
7992
8425
  ` Updated .codebyplan/server.local.json (worktree ${resolvedWorktreeId ?? "\u2014"}, ${portAllocations.length} allocation${portAllocations.length === 1 ? "" : "s"}).`
7993
8426
  );
7994
8427
  }
7995
8428
  async function provisionE2eEnv(projectPath, dryRun) {
7996
- const relSource = join25("apps", "web", ".env.local");
7997
- const sourcePath = join25(projectPath, relSource);
8429
+ const relSource = join26("apps", "web", ".env.local");
8430
+ const sourcePath = join26(projectPath, relSource);
7998
8431
  let sourceRaw;
7999
8432
  try {
8000
- sourceRaw = await readFile20(sourcePath, "utf-8");
8433
+ sourceRaw = await readFile21(sourcePath, "utf-8");
8001
8434
  } catch {
8002
8435
  console.warn(
8003
8436
  ` Skipped .codebyplan/e2e.env \u2014 source ${relSource} not found.`
@@ -8026,12 +8459,12 @@ async function provisionE2eEnv(projectPath, dryRun) {
8026
8459
  );
8027
8460
  return;
8028
8461
  }
8029
- const codebyplanDir = join25(projectPath, ".codebyplan");
8030
- const filePath = join25(codebyplanDir, "e2e.env");
8462
+ const codebyplanDir = join26(projectPath, ".codebyplan");
8463
+ const filePath = join26(codebyplanDir, "e2e.env");
8031
8464
  const newContent = lines.join("\n") + "\n";
8032
8465
  let currentContent = "";
8033
8466
  try {
8034
- currentContent = await readFile20(filePath, "utf-8");
8467
+ currentContent = await readFile21(filePath, "utf-8");
8035
8468
  } catch {
8036
8469
  }
8037
8470
  if (currentContent === newContent) {
@@ -8043,7 +8476,7 @@ async function provisionE2eEnv(projectPath, dryRun) {
8043
8476
  return;
8044
8477
  }
8045
8478
  await mkdir9(codebyplanDir, { recursive: true });
8046
- await writeFile15(filePath, newContent, "utf-8");
8479
+ await writeFile16(filePath, newContent, "utf-8");
8047
8480
  console.log(
8048
8481
  ` Provisioned .codebyplan/e2e.env (${lines.length} var${lines.length === 1 ? "" : "s"}).`
8049
8482
  );
@@ -8093,7 +8526,7 @@ __export(tech_stack_exports, {
8093
8526
  runFullTechStack: () => runFullTechStack,
8094
8527
  runTechStack: () => runTechStack
8095
8528
  });
8096
- import { existsSync as existsSync5 } from "node:fs";
8529
+ import { existsSync as existsSync6 } from "node:fs";
8097
8530
  async function runTechStack() {
8098
8531
  const flags = parseFlags(3);
8099
8532
  const dryRun = hasFlag("dry-run", 3);
@@ -8266,7 +8699,7 @@ async function runFullTechStack(dryRun) {
8266
8699
  continue;
8267
8700
  }
8268
8701
  const localWorktrees = worktrees.filter(
8269
- (wt) => wt.path ? existsSync5(wt.path) : false
8702
+ (wt) => wt.path ? existsSync6(wt.path) : false
8270
8703
  );
8271
8704
  if (localWorktrees.length === 0) {
8272
8705
  console.log(` skipping ${repo.name} \u2014 no local worktree on this device`);
@@ -8366,7 +8799,7 @@ var init_claude_plan = __esm({
8366
8799
  // src/cli/claude/status.ts
8367
8800
  var status_exports = {};
8368
8801
  __export(status_exports, {
8369
- runStatus: () => runStatus
8802
+ runStatus: () => runStatus2
8370
8803
  });
8371
8804
  import * as fs6 from "node:fs";
8372
8805
  import * as path7 from "node:path";
@@ -8433,7 +8866,7 @@ function resolveCurrentBranch2() {
8433
8866
  }
8434
8867
  }
8435
8868
  }
8436
- async function runStatus(argv) {
8869
+ async function runStatus2(argv) {
8437
8870
  const checked_at = (/* @__PURE__ */ new Date()).toISOString();
8438
8871
  const writeCache = argv.includes("--write-cache");
8439
8872
  const quiet = argv.includes("--quiet");
@@ -9618,11 +10051,11 @@ var generate_exports = {};
9618
10051
  __export(generate_exports, {
9619
10052
  runGenerate: () => runGenerate
9620
10053
  });
9621
- import { readFile as readFile21, mkdir as mkdir10, writeFile as writeFile16 } from "node:fs/promises";
9622
- import { join as join30, resolve as resolve8 } from "node:path";
10054
+ import { readFile as readFile22, mkdir as mkdir10, writeFile as writeFile17 } from "node:fs/promises";
10055
+ import { join as join31, resolve as resolve8 } from "node:path";
9623
10056
  async function readJsonFile3(filePath) {
9624
10057
  try {
9625
- const raw = await readFile21(filePath, "utf-8");
10058
+ const raw = await readFile22(filePath, "utf-8");
9626
10059
  return JSON.parse(raw);
9627
10060
  } catch {
9628
10061
  return null;
@@ -9630,7 +10063,7 @@ async function readJsonFile3(filePath) {
9630
10063
  }
9631
10064
  async function readPkgName(absPath) {
9632
10065
  try {
9633
- const raw = await readFile21(join30(absPath, "package.json"), "utf-8");
10066
+ const raw = await readFile22(join31(absPath, "package.json"), "utf-8");
9634
10067
  const pkg = JSON.parse(raw);
9635
10068
  return typeof pkg.name === "string" ? pkg.name : null;
9636
10069
  } catch {
@@ -9644,7 +10077,7 @@ async function runGenerate(opts) {
9644
10077
  const rootDir = resolve8(projectDir);
9645
10078
  let packageManager;
9646
10079
  try {
9647
- const raw = await readFile21(join30(rootDir, "package.json"), "utf-8");
10080
+ const raw = await readFile22(join31(rootDir, "package.json"), "utf-8");
9648
10081
  const pkg = JSON.parse(raw);
9649
10082
  if (typeof pkg.packageManager === "string") {
9650
10083
  packageManager = pkg.packageManager;
@@ -9652,7 +10085,7 @@ async function runGenerate(opts) {
9652
10085
  } catch {
9653
10086
  }
9654
10087
  const serverJson = await readJsonFile3(
9655
- join30(rootDir, ".codebyplan", "server.json")
10088
+ join31(rootDir, ".codebyplan", "server.json")
9656
10089
  );
9657
10090
  const ports = [];
9658
10091
  for (const alloc of serverJson?.port_allocations ?? []) {
@@ -9665,7 +10098,7 @@ async function runGenerate(opts) {
9665
10098
  }
9666
10099
  }
9667
10100
  const gitJson = await readJsonFile3(
9668
- join30(rootDir, ".codebyplan", "git.json")
10101
+ join31(rootDir, ".codebyplan", "git.json")
9669
10102
  );
9670
10103
  const branchModel = gitJson?.branch_config?.production ? {
9671
10104
  production: gitJson.branch_config.production,
@@ -9674,7 +10107,7 @@ async function runGenerate(opts) {
9674
10107
  )
9675
10108
  } : void 0;
9676
10109
  const shipmentJson = await readJsonFile3(
9677
- join30(rootDir, ".codebyplan", "shipment.json")
10110
+ join31(rootDir, ".codebyplan", "shipment.json")
9678
10111
  );
9679
10112
  const shipmentSurfaces = [];
9680
10113
  const rawSurfaces = shipmentJson?.shipment?.surfaces ?? shipmentJson?.surfaces ?? {};
@@ -9745,10 +10178,10 @@ async function runGenerate(opts) {
9745
10178
  const structureMdContent = generateStructureMd(config);
9746
10179
  const agentsContent = generateAgentsMd(structureMdContent);
9747
10180
  if (check) {
9748
- const agentsMdPath2 = join30(rootDir, "AGENTS.md");
10181
+ const agentsMdPath2 = join31(rootDir, "AGENTS.md");
9749
10182
  let existingAgents = null;
9750
10183
  try {
9751
- existingAgents = await readFile21(agentsMdPath2, "utf-8");
10184
+ existingAgents = await readFile22(agentsMdPath2, "utf-8");
9752
10185
  } catch {
9753
10186
  existingAgents = null;
9754
10187
  }
@@ -9784,16 +10217,16 @@ async function runGenerate(opts) {
9784
10217
  process.stdout.write(agentsContent);
9785
10218
  return;
9786
10219
  }
9787
- const outputDir = join30(rootDir, ".claude", "generated");
10220
+ const outputDir = join31(rootDir, ".claude", "generated");
9788
10221
  await mkdir10(outputDir, { recursive: true });
9789
- const outputPath = join30(outputDir, "structure.md");
9790
- await writeFile16(outputPath, structureMdContent, "utf-8");
10222
+ const outputPath = join31(outputDir, "structure.md");
10223
+ await writeFile17(outputPath, structureMdContent, "utf-8");
9791
10224
  process.stdout.write(`Wrote: .claude/generated/structure.md
9792
10225
  `);
9793
- const agentsMdPath = join30(rootDir, "AGENTS.md");
10226
+ const agentsMdPath = join31(rootDir, "AGENTS.md");
9794
10227
  let existingAgentsContent = null;
9795
10228
  try {
9796
- existingAgentsContent = await readFile21(agentsMdPath, "utf-8");
10229
+ existingAgentsContent = await readFile22(agentsMdPath, "utf-8");
9797
10230
  } catch {
9798
10231
  existingAgentsContent = null;
9799
10232
  }
@@ -9801,7 +10234,7 @@ async function runGenerate(opts) {
9801
10234
  process.stdout.write(`Up to date: AGENTS.md
9802
10235
  `);
9803
10236
  } else {
9804
- await writeFile16(agentsMdPath, agentsContent, "utf-8");
10237
+ await writeFile17(agentsMdPath, agentsContent, "utf-8");
9805
10238
  process.stdout.write(`Wrote: AGENTS.md
9806
10239
  `);
9807
10240
  }
@@ -9821,11 +10254,11 @@ __export(readme_exports, {
9821
10254
  runReadme: () => runReadme,
9822
10255
  runReadmeCommand: () => runReadmeCommand
9823
10256
  });
9824
- import { readFile as readFile22, writeFile as writeFile17 } from "node:fs/promises";
9825
- import { join as join31, resolve as resolve9, relative as relative8 } from "node:path";
10257
+ import { readFile as readFile23, writeFile as writeFile18 } from "node:fs/promises";
10258
+ import { join as join32, resolve as resolve9, relative as relative8 } from "node:path";
9826
10259
  async function readJsonFile4(filePath) {
9827
10260
  try {
9828
- const raw = await readFile22(filePath, "utf-8");
10261
+ const raw = await readFile23(filePath, "utf-8");
9829
10262
  return JSON.parse(raw);
9830
10263
  } catch {
9831
10264
  return null;
@@ -9894,7 +10327,7 @@ async function discoverUnits(rootDir, rootPkgJson) {
9894
10327
  const discovered = await discoverMonorepoApps(rootDir);
9895
10328
  for (const app of discovered) {
9896
10329
  const pkgJson = await readJsonFile4(
9897
- join31(app.absPath, "package.json")
10330
+ join32(app.absPath, "package.json")
9898
10331
  );
9899
10332
  pkgJsonByPath.set(app.absPath, pkgJson);
9900
10333
  allPackages.push({
@@ -9920,7 +10353,7 @@ async function runReadme(opts) {
9920
10353
  const init = opts.init ?? opts["init"] ?? false;
9921
10354
  const rootDir = resolve9(projectDir);
9922
10355
  const rootPkgJson = await readJsonFile4(
9923
- join31(rootDir, "package.json")
10356
+ join32(rootDir, "package.json")
9924
10357
  );
9925
10358
  const { units, allPackages, pkgJsonByPath } = await discoverUnits(
9926
10359
  rootDir,
@@ -9929,11 +10362,11 @@ async function runReadme(opts) {
9929
10362
  const driftUnits = [];
9930
10363
  const missingUnits = [];
9931
10364
  for (const unit of units) {
9932
- const readmePath = join31(unit.absPath, "README.md");
9933
- const relPath = unit.isRoot ? "README.md" : join31(relative8(rootDir, unit.absPath), "README.md");
10365
+ const readmePath = join32(unit.absPath, "README.md");
10366
+ const relPath = unit.isRoot ? "README.md" : join32(relative8(rootDir, unit.absPath), "README.md");
9934
10367
  let existingContent = null;
9935
10368
  try {
9936
- existingContent = await readFile22(readmePath, "utf-8");
10369
+ existingContent = await readFile23(readmePath, "utf-8");
9937
10370
  } catch {
9938
10371
  existingContent = null;
9939
10372
  }
@@ -9968,7 +10401,7 @@ ${newContent}
9968
10401
  `
9969
10402
  );
9970
10403
  } else {
9971
- await writeFile17(readmePath, newContent, "utf-8");
10404
+ await writeFile18(readmePath, newContent, "utf-8");
9972
10405
  process.stdout.write(`Wrote (scaffold): ${relPath}
9973
10406
  `);
9974
10407
  }
@@ -10006,7 +10439,7 @@ ${newContent}
10006
10439
  `
10007
10440
  );
10008
10441
  } else {
10009
- await writeFile17(readmePath, newContent, "utf-8");
10442
+ await writeFile18(readmePath, newContent, "utf-8");
10010
10443
  process.stdout.write(`Wrote (refresh): ${relPath}
10011
10444
  `);
10012
10445
  }
@@ -10025,7 +10458,7 @@ ${newContent}
10025
10458
  `
10026
10459
  );
10027
10460
  } else {
10028
- await writeFile17(readmePath, newContent, "utf-8");
10461
+ await writeFile18(readmePath, newContent, "utf-8");
10029
10462
  process.stdout.write(`Wrote (init): ${relPath}
10030
10463
  `);
10031
10464
  }
@@ -10113,15 +10546,15 @@ __export(migrate_memory_exports, {
10113
10546
  runMigrateMemory: () => runMigrateMemory
10114
10547
  });
10115
10548
  import {
10116
- readFile as readFile23,
10117
- writeFile as writeFile18,
10549
+ readFile as readFile24,
10550
+ writeFile as writeFile19,
10118
10551
  mkdir as mkdir11,
10119
10552
  unlink as unlink4,
10120
10553
  rmdir,
10121
10554
  readdir as readdir4
10122
10555
  } from "node:fs/promises";
10123
- import { existsSync as existsSync10 } from "node:fs";
10124
- import { join as join32, resolve as resolve10, dirname as dirname11, sep as sep2 } from "node:path";
10556
+ import { existsSync as existsSync11 } from "node:fs";
10557
+ import { join as join33, resolve as resolve10, dirname as dirname11, sep as sep2 } from "node:path";
10125
10558
  import { homedir as homedir8 } from "node:os";
10126
10559
  function encodeProjectPath(absPath) {
10127
10560
  return resolve10(absPath).replace(/[/\\]/g, "-");
@@ -10132,7 +10565,7 @@ function resolveAutoMemoryDir(opts) {
10132
10565
  }
10133
10566
  const projectDir = opts.projectDir ?? process.cwd();
10134
10567
  const encoded = encodeProjectPath(projectDir);
10135
- return join32(homedir8(), ".claude", "projects", encoded, "memory");
10568
+ return join33(homedir8(), ".claude", "projects", encoded, "memory");
10136
10569
  }
10137
10570
  function parseFrontmatter(content) {
10138
10571
  content = content.replace(/\r\n/g, "\n");
@@ -10198,10 +10631,10 @@ async function inventoryFiles(dir) {
10198
10631
  }
10199
10632
  const results = [];
10200
10633
  for (const filename of filenames) {
10201
- const sourcePath = join32(dir, filename);
10634
+ const sourcePath = join33(dir, filename);
10202
10635
  let raw;
10203
10636
  try {
10204
- raw = await readFile23(sourcePath, "utf-8");
10637
+ raw = await readFile24(sourcePath, "utf-8");
10205
10638
  } catch (err) {
10206
10639
  const msg = err instanceof Error ? err.message : String(err);
10207
10640
  results.push({
@@ -10287,8 +10720,8 @@ async function applyPlan(plan, opts) {
10287
10720
  if (entry.suggested_action !== "keep") continue;
10288
10721
  if (!entry.suggested_target?.startsWith("nested:")) continue;
10289
10722
  const relPath = entry.suggested_target.slice("nested:".length);
10290
- const targetDir = resolve10(join32(projectDir, relPath));
10291
- const targetFile = join32(targetDir, "CLAUDE.md");
10723
+ const targetDir = resolve10(join33(projectDir, relPath));
10724
+ const targetFile = join33(targetDir, "CLAUDE.md");
10292
10725
  if (!targetDir.startsWith(resolve10(projectDir) + sep2)) {
10293
10726
  process.stderr.write(
10294
10727
  `migrate-memory: skipping unsafe suggested_target "${entry.suggested_target}" \u2014 resolves outside projectDir
@@ -10320,11 +10753,11 @@ ${anchor}
10320
10753
  await mkdir11(targetDir, { recursive: true });
10321
10754
  let existing = "";
10322
10755
  try {
10323
- existing = await readFile23(targetFile, "utf-8");
10756
+ existing = await readFile24(targetFile, "utf-8");
10324
10757
  } catch {
10325
10758
  }
10326
10759
  if (!existing.includes(anchor)) {
10327
- await writeFile18(targetFile, existing + appendContent, "utf-8");
10760
+ await writeFile19(targetFile, existing + appendContent, "utf-8");
10328
10761
  }
10329
10762
  if (resolve10(entry.source_path).startsWith(resolve10(plan.auto_memory_dir) + sep2)) {
10330
10763
  try {
@@ -10338,7 +10771,7 @@ ${anchor}
10338
10771
  );
10339
10772
  }
10340
10773
  }
10341
- const rootClaudeMd = join32(projectDir, ".claude", "CLAUDE.md");
10774
+ const rootClaudeMd = join33(projectDir, ".claude", "CLAUDE.md");
10342
10775
  if (dryRun) {
10343
10776
  process.stdout.write(
10344
10777
  `[dry-run] Would ensure ${rootClaudeMd} contains: ${IMPORT_LINE}
@@ -10347,12 +10780,12 @@ ${anchor}
10347
10780
  } else {
10348
10781
  let claudeMdContent = "";
10349
10782
  try {
10350
- claudeMdContent = await readFile23(rootClaudeMd, "utf-8");
10783
+ claudeMdContent = await readFile24(rootClaudeMd, "utf-8");
10351
10784
  } catch {
10352
10785
  await mkdir11(dirname11(rootClaudeMd), { recursive: true });
10353
10786
  }
10354
10787
  if (!claudeMdContent.includes(IMPORT_LINE)) {
10355
- await writeFile18(
10788
+ await writeFile19(
10356
10789
  rootClaudeMd,
10357
10790
  claudeMdContent + `
10358
10791
  ${IMPORT_LINE}
@@ -10382,8 +10815,8 @@ ${IMPORT_LINE}
10382
10815
  } catch {
10383
10816
  }
10384
10817
  }
10385
- const memoryMd = join32(plan.auto_memory_dir, "MEMORY.md");
10386
- const safeRmdirBase = join32(homedir8(), ".claude", "projects");
10818
+ const memoryMd = join33(plan.auto_memory_dir, "MEMORY.md");
10819
+ const safeRmdirBase = join33(homedir8(), ".claude", "projects");
10387
10820
  if (dryRun) {
10388
10821
  process.stdout.write(`[dry-run] Would delete MEMORY.md: ${memoryMd}
10389
10822
  `);
@@ -10436,7 +10869,7 @@ async function runMigrateMemory(opts) {
10436
10869
  if (applyFile) {
10437
10870
  let planJson;
10438
10871
  try {
10439
- planJson = await readFile23(resolve10(applyFile), "utf-8");
10872
+ planJson = await readFile24(resolve10(applyFile), "utf-8");
10440
10873
  } catch (err) {
10441
10874
  const msg = err instanceof Error ? err.message : String(err);
10442
10875
  process.stderr.write(
@@ -10464,7 +10897,7 @@ async function runMigrateMemory(opts) {
10464
10897
  );
10465
10898
  return;
10466
10899
  }
10467
- if (!existsSync10(autoMemoryDir)) {
10900
+ if (!existsSync11(autoMemoryDir)) {
10468
10901
  process.stdout.write(
10469
10902
  JSON.stringify(
10470
10903
  {
@@ -10651,6 +11084,12 @@ void (async () => {
10651
11084
  await runUploadE2eImagesCommand2(rest);
10652
11085
  process.exit(0);
10653
11086
  }
11087
+ if (arg === "arch-map") {
11088
+ const { runArchMapCommand: runArchMapCommand2 } = await Promise.resolve().then(() => (init_arch_map(), arch_map_exports));
11089
+ const rest = process.argv.slice(3);
11090
+ await runArchMapCommand2(rest);
11091
+ process.exit(0);
11092
+ }
10654
11093
  if (arg === "config") {
10655
11094
  const { runConfig: runConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
10656
11095
  await runConfig2();
@@ -10676,8 +11115,8 @@ void (async () => {
10676
11115
  const flagArgs = process.argv.slice(3);
10677
11116
  const parsed = parseClaudeFlags(flagArgs);
10678
11117
  if (subcommand === "status") {
10679
- const { runStatus: runStatus2 } = await Promise.resolve().then(() => (init_status(), status_exports));
10680
- await runStatus2(process.argv.slice(4));
11118
+ const { runStatus: runStatus3 } = await Promise.resolve().then(() => (init_status(), status_exports));
11119
+ await runStatus3(process.argv.slice(4));
10681
11120
  return;
10682
11121
  }
10683
11122
  if (subcommand === "install") {
@@ -10795,6 +11234,7 @@ void (async () => {
10795
11234
  codebyplan create-project Create a new project within an organization (interactive prompt)
10796
11235
  codebyplan create-repo Create a new repository within a project (interactive prompt)
10797
11236
  codebyplan config Sync repo config from DB to .codebyplan/ files
11237
+ codebyplan arch-map Map architecture modules (status/drift/stamp)
10798
11238
  codebyplan ports Verify port allocations against local package.json scripts
10799
11239
  codebyplan tech-stack Detect and sync tech stack dependencies
10800
11240
  (--full-tech-stack: sync every local worktree on this device)