@archme/cli 0.8.0 → 0.8.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 (2) hide show
  1. package/dist/cli.js +168 -50
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -10005,9 +10005,23 @@ async function tailLog(opts = {}) {
10005
10005
  await new Promise((resolve6, reject) => {
10006
10006
  let fileWatcher = null;
10007
10007
  let dirWatcher = null;
10008
+ let poller = null;
10009
+ let settled = false;
10008
10010
  const dir = dirname7(path7);
10009
10011
  const name = basename(path7);
10010
- const onChange = async () => {
10012
+ const stop = () => {
10013
+ settled = true;
10014
+ fileWatcher?.close();
10015
+ dirWatcher?.close();
10016
+ if (poller) clearInterval(poller);
10017
+ process.removeListener("SIGINT", handleSigint);
10018
+ };
10019
+ const fail = (err2) => {
10020
+ if (settled) return;
10021
+ stop();
10022
+ reject(err2);
10023
+ };
10024
+ const readNew = async () => {
10011
10025
  try {
10012
10026
  const st = await stat(path7);
10013
10027
  if (st.size < offset) offset = 0;
@@ -10020,61 +10034,50 @@ async function tailLog(opts = {}) {
10020
10034
  });
10021
10035
  offset = st.size;
10022
10036
  }
10037
+ if (!fileWatcher && !settled) attachFileWatcher();
10023
10038
  } catch (err2) {
10024
10039
  if (err2.code === "ENOENT") return;
10025
- reject(err2);
10040
+ fail(err2);
10026
10041
  }
10027
10042
  };
10028
- const attachFileWatcher = () => {
10029
- try {
10030
- fileWatcher = watch(path7, (event) => {
10031
- if (event === "change") void onChange();
10032
- });
10033
- } catch (err2) {
10034
- if (err2.code !== "ENOENT") {
10035
- reject(err2);
10036
- return;
10037
- }
10038
- attachDirWatcher();
10039
- }
10043
+ let chain = Promise.resolve();
10044
+ const drain = () => {
10045
+ if (settled) return;
10046
+ chain = chain.then(readNew);
10040
10047
  };
10041
- const attachDirWatcher = () => {
10048
+ const attachFileWatcher = () => {
10042
10049
  try {
10043
- dirWatcher = watch(dir, (_event, filename) => {
10044
- if (filename === name) {
10045
- void onChange().then(() => {
10046
- dirWatcher?.close();
10047
- dirWatcher = null;
10048
- attachFileWatcher();
10049
- });
10050
- }
10051
- });
10052
- } catch (err2) {
10053
- reject(err2);
10050
+ fileWatcher = watch(path7, () => drain());
10051
+ dirWatcher?.close();
10052
+ dirWatcher = null;
10053
+ } catch {
10054
+ fileWatcher = null;
10054
10055
  }
10055
10056
  };
10056
- stat(path7).then(
10057
- () => attachFileWatcher(),
10058
- (err2) => {
10059
- if (err2.code === "ENOENT") {
10060
- attachDirWatcher();
10061
- } else {
10062
- reject(err2);
10063
- }
10064
- }
10065
- );
10057
+ try {
10058
+ dirWatcher = watch(dir, (_event, filename) => {
10059
+ if (filename === name) drain();
10060
+ });
10061
+ } catch (err2) {
10062
+ fail(err2);
10063
+ return;
10064
+ }
10066
10065
  const handleSigint = () => {
10067
- fileWatcher?.close();
10068
- dirWatcher?.close();
10066
+ if (settled) return;
10067
+ stop();
10069
10068
  resolve6();
10070
10069
  };
10071
10070
  process.once("SIGINT", handleSigint);
10071
+ poller = setInterval(drain, FOLLOW_POLL_MS);
10072
+ drain();
10072
10073
  });
10073
10074
  }
10075
+ var FOLLOW_POLL_MS;
10074
10076
  var init_logs = __esm({
10075
10077
  "src/daemon/service/logs.ts"() {
10076
10078
  "use strict";
10077
10079
  init_paths();
10080
+ FOLLOW_POLL_MS = 500;
10078
10081
  }
10079
10082
  });
10080
10083
 
@@ -10344,10 +10347,31 @@ var init_preflight = __esm({
10344
10347
  });
10345
10348
 
10346
10349
  // ../shared/daemonModel.ts
10347
- var DEFAULT_CLAUDE_MODEL;
10350
+ function parseClaudeCodeVersion(output) {
10351
+ return /(\d+)\.(\d+)\.(\d+)/.exec(output ?? "")?.[0] ?? null;
10352
+ }
10353
+ function versionBelow(version, minimum) {
10354
+ const a2 = version.split(".").map(Number);
10355
+ const b = minimum.split(".").map(Number);
10356
+ for (let i2 = 0; i2 < Math.max(a2.length, b.length); i2++) {
10357
+ const d = (a2[i2] ?? 0) - (b[i2] ?? 0);
10358
+ if (d !== 0) return d < 0;
10359
+ }
10360
+ return false;
10361
+ }
10362
+ function runnableModel(requested, installedVersion) {
10363
+ const needs = MIN_CLAUDE_CODE_VERSION[requested];
10364
+ if (!needs || !installedVersion || !versionBelow(installedVersion, needs)) return { model: requested };
10365
+ return { model: FALLBACK_CLAUDE_MODEL, fellBack: { from: requested, needs } };
10366
+ }
10367
+ var DEFAULT_CLAUDE_MODEL, FALLBACK_CLAUDE_MODEL, MIN_CLAUDE_CODE_VERSION;
10348
10368
  var init_daemonModel = __esm({
10349
10369
  "../shared/daemonModel.ts"() {
10350
10370
  DEFAULT_CLAUDE_MODEL = "claude-opus-5-5";
10371
+ FALLBACK_CLAUDE_MODEL = "claude-opus-4-8";
10372
+ MIN_CLAUDE_CODE_VERSION = {
10373
+ "claude-opus-5-5": "2.1.280"
10374
+ };
10351
10375
  }
10352
10376
  });
10353
10377
 
@@ -10509,6 +10533,39 @@ var init_spawn_claude = __esm({
10509
10533
  }
10510
10534
  });
10511
10535
 
10536
+ // src/scan/claudeVersion.ts
10537
+ async function runClaudeVersion() {
10538
+ const r = await execa("claude", ["--version"], { reject: false, timeout: 15e3 });
10539
+ return r.exitCode === 0 ? String(r.stdout) : null;
10540
+ }
10541
+ function createClaudeVersionProbe(opts = {}) {
10542
+ const exec = opts.exec ?? runClaudeVersion;
10543
+ const now = opts.now ?? Date.now;
10544
+ const ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;
10545
+ let cached;
10546
+ return async () => {
10547
+ if (cached && now() - cached.at < ttlMs) return cached.version;
10548
+ let version = null;
10549
+ try {
10550
+ version = parseClaudeCodeVersion(await exec());
10551
+ } catch {
10552
+ version = null;
10553
+ }
10554
+ cached = { version, at: now() };
10555
+ return version;
10556
+ };
10557
+ }
10558
+ var DEFAULT_TTL_MS, claudeCodeVersion;
10559
+ var init_claudeVersion = __esm({
10560
+ "src/scan/claudeVersion.ts"() {
10561
+ "use strict";
10562
+ init_execa();
10563
+ init_daemonModel();
10564
+ DEFAULT_TTL_MS = 10 * 6e4;
10565
+ claudeCodeVersion = createClaudeVersionProbe();
10566
+ }
10567
+ });
10568
+
10512
10569
  // src/scan/model-pin.ts
10513
10570
  async function resolveModelPin(supabase) {
10514
10571
  try {
@@ -10522,10 +10579,30 @@ async function resolveModelPin(supabase) {
10522
10579
  return DEFAULT_CLAUDE_MODEL;
10523
10580
  }
10524
10581
  }
10582
+ async function resolveRunnableModel(supabase, deps = {}) {
10583
+ const requested = await resolveModelPin(supabase);
10584
+ const installed = await (deps.version ?? claudeCodeVersion)();
10585
+ const { model, fellBack } = runnableModel(requested, installed);
10586
+ if (fellBack) {
10587
+ const warned = deps.warned ?? warnedFallbacks;
10588
+ const key = `${fellBack.from}@${installed}`;
10589
+ if (!warned.has(key)) {
10590
+ warned.add(key);
10591
+ (deps.warn ?? console.warn)(
10592
+ `Claude Code ${installed} can't run ${fellBack.from} (needs ${fellBack.needs}+); running ${model} instead. Run \`claude update\` to use ${fellBack.from}.`
10593
+ );
10594
+ }
10595
+ }
10596
+ return model;
10597
+ }
10598
+ var warnedFallbacks;
10525
10599
  var init_model_pin = __esm({
10526
10600
  "src/scan/model-pin.ts"() {
10527
10601
  "use strict";
10528
10602
  init_spawn_claude();
10603
+ init_daemonModel();
10604
+ init_claudeVersion();
10605
+ warnedFallbacks = /* @__PURE__ */ new Set();
10529
10606
  }
10530
10607
  });
10531
10608
 
@@ -10646,7 +10723,7 @@ async function runDigestJob(ctx, job, deviceId, inFlight2, mcp) {
10646
10723
  mcpConfigPath = join8(dir, "mcp.json");
10647
10724
  await writeFile5(mcpConfigPath, JSON.stringify({ mcpServers: {} }));
10648
10725
  }
10649
- const model = await resolveModelPin(ctx.supabase);
10726
+ const model = await resolveRunnableModel(ctx.supabase);
10650
10727
  const proc = spawnClaude({
10651
10728
  prompt: buildDigestPrompt(payload),
10652
10729
  mcpConfigPath,
@@ -13220,6 +13297,13 @@ var init_sequenceChapters = __esm({
13220
13297
  }
13221
13298
  });
13222
13299
 
13300
+ // ../shared/architectureDiff.ts
13301
+ var init_architectureDiff = __esm({
13302
+ "../shared/architectureDiff.ts"() {
13303
+ init_storyChanges();
13304
+ }
13305
+ });
13306
+
13223
13307
  // ../shared/walkthrough.ts
13224
13308
  var MAX_WALKTHROUGH_STEPS, MAX_STEP_TITLE_CHARS;
13225
13309
  var init_walkthrough = __esm({
@@ -13227,6 +13311,7 @@ var init_walkthrough = __esm({
13227
13311
  init_storyChanges();
13228
13312
  init_sequenceChapters();
13229
13313
  init_validationCodes();
13314
+ init_architectureDiff();
13230
13315
  MAX_WALKTHROUGH_STEPS = 20;
13231
13316
  MAX_STEP_TITLE_CHARS = 60;
13232
13317
  }
@@ -13243,13 +13328,15 @@ var init_walkthroughGuidance = __esm({
13243
13328
  - **Steps are in reading order, not build order.** This is not an implementation plan and not a restatement of your sequencing section \u2014 start where a reviewer should start, and put each step where it makes the next one make sense.
13244
13329
  - **Group by idea.** One step is one coherent change, usually 3\u20138 elements. A one-element step is fine and often valuable: an independent fix that would otherwise be lost among the rest. Aim for a handful of steps; the cap is ${MAX_WALKTHROUGH_STEPS}.
13245
13330
  - **Titles are terse** \u2014 a handle, not a summary. Under ${MAX_STEP_TITLE_CHARS} characters. \`Markers move per-repo\`, not \`This step explains how the source marker moves onto a per-repo table\`.
13246
- - **Description is optional and usually absent.** Never restate the components, stories or connections the step already references \u2014 the reader is looking at them. Write one only for something the diagrams cannot show: a constraint, a consequence, a trade-off that is not visible in the graph.
13247
- - **Write it for someone meeting this change for the first time.** They know the system; they have NOT read your proposal body and were not in the design discussion. Say plainly what the step does and why it is there. Two sentences is plenty.
13331
+ - **Every step gets a short description** \u2014 the narration a reader follows while the diagrams move beside it, one step at a time. Two or three plain sentences: what this part of the change is, why it exists, and how it fits the rest, at a high level. Example: \`This is the daemon picking up GitHub's answer after it posts a comment, review or approval on your behalf, and recording whether it worked.\`
13332
+ - Not prescriptive: describe the change, do not tell the reviewer what to check or what to think of it.
13333
+ - Not dense: no condensed paragraph of identifiers, flags and edge cases crammed into one sentence. Never restate the components, stories or connections the step already references \u2014 the reader is looking at them.
13334
+ - **Write it for someone meeting this change for the first time.** They know the system; they have NOT read your proposal body and were not in the design discussion. Say plainly what the step does and why it is there.
13248
13335
  - Don't argue with objections the reader hasn't raised \u2014 no \`not just a nicety\`, no \`as discussed\`, no \`this is why it is its own step\`. They don't know how the walkthrough was assembled and haven't disagreed with you. A trade-off worth stating is information (\`X was considered; it breaks Y\`), not a rebuttal.
13249
13336
  - Don't use the change's OWN new vocabulary undefined. If the step introduces a term, say what it means in the same breath or use plain words.
13250
13337
  - Bad: \`A correctness item, not a phase-3 nicety: anchors are repo-relative paths, so two repos with the same conventional layout collide silently and seed stories from the wrong one.\`
13251
13338
  - Good: \`With two repos in one project a path like src/index.ts exists in both, so looking up which component owns a changed file can return the wrong repo's. Each repo now records the container its code lives under, and lookups search only that subtree.\`
13252
- - **Cover every story the change touches.** A changed story no step references is a change the reader will step straight past.
13339
+ - **Cover every change** \u2014 every story, component and connection the change touches \u2014 or \`set_walkthrough\` rejects the walkthrough and lists what is missing. Guided mode walks the steps and nothing after them, so anything no step reaches is a change the reviewer never sees. A connection is covered when a step names it, names both of its components, or names a story page that draws it as an arrow. Name a connection inside a component as \`<component path>::<id>\` (\`daemon::session_auth->key_account\`); a root connection by its plain id.
13253
13340
  - **Skip it for a small change.** A handful of elements needs no walkthrough; omit it rather than writing a step per element.
13254
13341
  - **Prefer CHAPTERS to narrow a diagram.** If a story's sequence carries \`%% chapter: <id> | <Label>\` markers, name the ones your step covers as \`chapters: [{ story, chapter }]\`, using the **id**, never the label \u2014 ids are stable across a rename, labels are not. A chapter is a page break the story's author already wrote, so it is sharper than naming components, where one hub the step mentions decides the whole view.`;
13255
13342
  }
@@ -16055,7 +16142,9 @@ function observeGithubPull(p) {
16055
16142
  createdAt: p.created_at ?? null,
16056
16143
  updatedAt: p.updated_at ?? null,
16057
16144
  mergedAt: p.merged_at ?? null,
16058
- closedAt: p.closed_at ?? null
16145
+ closedAt: p.closed_at ?? null,
16146
+ // Before the merge it is GitHub's throwaway test merge.
16147
+ mergeCommitSha: p.merged_at ? p.merge_commit_sha ?? null : null
16059
16148
  };
16060
16149
  }
16061
16150
  function metaKey(o2) {
@@ -16090,6 +16179,7 @@ function toItem(o2, action, sent) {
16090
16179
  created_at: o2.createdAt,
16091
16180
  merged_at: o2.mergedAt,
16092
16181
  closed_at: o2.closedAt,
16182
+ merge_commit_sha: o2.mergeCommitSha,
16093
16183
  body: o2.body,
16094
16184
  ...action === "synchronize" && sent.seq !== void 0 ? { seq: sent.seq } : {}
16095
16185
  };
@@ -16499,6 +16589,22 @@ var init_defaultBranch = __esm({
16499
16589
  }
16500
16590
  });
16501
16591
 
16592
+ // ../shared/prRefs.ts
16593
+ function pushCommitSubject(message) {
16594
+ if (message == null) return null;
16595
+ const [subject = "", ...body] = message.split("\n");
16596
+ const pr = MERGE_PR_SUBJECT.exec(subject.trim());
16597
+ const title = body.find((line) => line.trim())?.trim();
16598
+ return pr && title && !TRAILER_LINE.test(title) ? `${title} (#${pr[1]})` : subject;
16599
+ }
16600
+ var MERGE_PR_SUBJECT, TRAILER_LINE;
16601
+ var init_prRefs = __esm({
16602
+ "../shared/prRefs.ts"() {
16603
+ MERGE_PR_SUBJECT = /^Merge pull request #(\d+) from \S+$/;
16604
+ TRAILER_LINE = /^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)+:\s/;
16605
+ }
16606
+ });
16607
+
16502
16608
  // src/daemon/localGit.ts
16503
16609
  var localGit_exports = {};
16504
16610
  __export(localGit_exports, {
@@ -16567,13 +16673,14 @@ async function firstParentRange(dir, marker, tip) {
16567
16673
  async function readCommitMeta(dir, sha) {
16568
16674
  const { exitCode, stdout } = await git(
16569
16675
  dir,
16570
- ["show", "-s", "--format=%s%n%an%n%cI", sha],
16676
+ // %b last: it spans lines, and `pushCommitSubject` reads a merge commit's title from it.
16677
+ ["show", "-s", "--format=%an%n%cI%n%s%n%b", sha],
16571
16678
  { allowFail: true }
16572
16679
  );
16573
16680
  if (exitCode !== 0) return { message: "", authorName: null, committedAt: null };
16574
- const [message = "", authorName = "", committedAt = ""] = stdout.split("\n");
16681
+ const [authorName = "", committedAt = "", ...message] = stdout.split("\n");
16575
16682
  return {
16576
- message: message.trim(),
16683
+ message: (pushCommitSubject(message.join("\n")) ?? "").trim(),
16577
16684
  authorName: authorName.trim() || null,
16578
16685
  committedAt: committedAt.trim() || null
16579
16686
  };
@@ -16602,6 +16709,7 @@ var init_localGit = __esm({
16602
16709
  init_execa();
16603
16710
  init_preflight();
16604
16711
  init_defaultBranch();
16712
+ init_prRefs();
16605
16713
  GIT_TIMEOUT_MS = 10 * 60 * 1e3;
16606
16714
  }
16607
16715
  });
@@ -17051,6 +17159,7 @@ __export(run_exports, {
17051
17159
  buildClaudeExitMessage: () => buildClaudeExitMessage,
17052
17160
  buildDevices: () => buildDevices,
17053
17161
  buildDiffPrompt: () => buildDiffPrompt,
17162
+ claudeFailureDetail: () => claudeFailureDetail,
17054
17163
  computeDiff: () => computeDiff,
17055
17164
  parseClaudeResult: () => parseClaudeResult,
17056
17165
  probeMcpAuth: () => probeMcpAuth,
@@ -17074,6 +17183,12 @@ function attributeKillCause(result, recorded) {
17074
17183
  function buildClaudeExitMessage(exitCode, causeSuffix, stderr) {
17075
17184
  return `claude exited ${exitCode}${causeSuffix}: ${stderr.slice(0, 4e3)}`;
17076
17185
  }
17186
+ function claudeFailureDetail(stderr, stdout) {
17187
+ if (stderr.trim() || !stdout.trim()) return null;
17188
+ const parsed = parseClaudeResult(stdout);
17189
+ const text = (parsed.parsed ? parsed.summary : stdout).trim();
17190
+ return text ? text.slice(-FAILURE_DETAIL_MAX) : null;
17191
+ }
17077
17192
  async function routeShutdownInterrupt(id, cancelled2, fail, exitCode) {
17078
17193
  if (cancelled2.has(id)) return;
17079
17194
  if (exitCode === 0) {
@@ -18016,7 +18131,7 @@ async function runJob(ctx, job, claimDeviceId) {
18016
18131
  `MCP auth preflight failed after ${probe.attempts} attempt(s) (last status ${probe.lastStatus ?? "n/a"}): ${probe.detail}. Not spawning claude \u2014 the architecture would not be writable and the run would silently no-op. Failing the job so it retries with a freshly minted token.`
18017
18132
  );
18018
18133
  }
18019
- const model = await resolveModelPin(ctx.supabase);
18134
+ const model = await resolveRunnableModel(ctx.supabase, { warn: log });
18020
18135
  metrics.model = model;
18021
18136
  log(`spawning claude (mcp config at ${configPath}, model ${model})`);
18022
18137
  const proc = spawnClaude({
@@ -18054,6 +18169,8 @@ async function runJob(ctx, job, claimDeviceId) {
18054
18169
  if (result.exitCode !== 0) {
18055
18170
  const causeSuffix = cause ? ` (${result.signal ?? "exit"}, cause: ${cause})` : "";
18056
18171
  const stderr = result.stderr ? String(result.stderr) : "";
18172
+ const detail = claudeFailureDetail(stderr, result.stdout ? String(result.stdout) : "");
18173
+ if (detail) log(`claude output: ${detail.replace(/\n/g, " ")}`);
18057
18174
  throw new Error(buildClaudeExitMessage(result.exitCode, causeSuffix, stderr));
18058
18175
  }
18059
18176
  const runResult = parseClaudeResult(result.stdout ? String(result.stdout) : "");
@@ -18557,7 +18674,7 @@ ${signal} received, shutting down`);
18557
18674
  process.on("SIGINT", () => shutdown("SIGINT"));
18558
18675
  process.on("SIGTERM", () => shutdown("SIGTERM"));
18559
18676
  }
18560
- var HEARTBEAT_INTERVAL_MS, CLAUDE_TIMEOUT_MS, CLAUDE_LARGE_DIFF_TIMEOUT_MS, SAFETY_SWEEP_MS, LOG_STDOUT_CAP_BYTES, LOG_STDERR_CAP_BYTES, PRE_SPAWN_TOKEN_MIN_LIFETIME_MS, SUPABASE_URL, SUPABASE_ANON_KEY, ARCHME_DAEMON_CLIENT_ID, ARCHME_MCP_BASE_URL, CLONE_BASE_DIR, DAEMON_ID, LEASE_SECONDS, inFlight, cancelled, killReasons, activeCleanups, cloneMutex, shuttingDown, daemonVersion, pauseUntilMs, resumeTimer, currentSched, MAX_CONCURRENT_JOBS, ctxByJob, deviceByJob, DEFAULT_CLONE_BASE_DIR, INLINE_PATCH_BYTE_CAP, GIT_SHA_RE, CURATOR_PREAMBLE, CORE_PRINCIPLES, STORY_COVERAGE_GATE, NEW_STORY_GUIDANCE, STORY_DESCRIPTION_EDIT_RULE, PHASE_GUIDANCE, BASE_RULES, DIFF_RULES, finite, channelSeq, MultipleAccountsError, __testDispatch;
18677
+ var HEARTBEAT_INTERVAL_MS, CLAUDE_TIMEOUT_MS, CLAUDE_LARGE_DIFF_TIMEOUT_MS, SAFETY_SWEEP_MS, LOG_STDOUT_CAP_BYTES, LOG_STDERR_CAP_BYTES, FAILURE_DETAIL_MAX, PRE_SPAWN_TOKEN_MIN_LIFETIME_MS, SUPABASE_URL, SUPABASE_ANON_KEY, ARCHME_DAEMON_CLIENT_ID, ARCHME_MCP_BASE_URL, CLONE_BASE_DIR, DAEMON_ID, LEASE_SECONDS, inFlight, cancelled, killReasons, activeCleanups, cloneMutex, shuttingDown, daemonVersion, pauseUntilMs, resumeTimer, currentSched, MAX_CONCURRENT_JOBS, ctxByJob, deviceByJob, DEFAULT_CLONE_BASE_DIR, INLINE_PATCH_BYTE_CAP, GIT_SHA_RE, CURATOR_PREAMBLE, CORE_PRINCIPLES, STORY_COVERAGE_GATE, NEW_STORY_GUIDANCE, STORY_DESCRIPTION_EDIT_RULE, PHASE_GUIDANCE, BASE_RULES, DIFF_RULES, finite, channelSeq, MultipleAccountsError, __testDispatch;
18561
18678
  var init_run = __esm({
18562
18679
  "src/daemon/run.ts"() {
18563
18680
  "use strict";
@@ -18603,6 +18720,7 @@ var init_run = __esm({
18603
18720
  SAFETY_SWEEP_MS = 3e4;
18604
18721
  LOG_STDOUT_CAP_BYTES = 30 * 1024;
18605
18722
  LOG_STDERR_CAP_BYTES = 30 * 1024;
18723
+ FAILURE_DETAIL_MAX = 400;
18606
18724
  PRE_SPAWN_TOKEN_MIN_LIFETIME_MS = CLAUDE_LARGE_DIFF_TIMEOUT_MS + 5 * 60 * 1e3;
18607
18725
  inFlight = /* @__PURE__ */ new Map();
18608
18726
  cancelled = /* @__PURE__ */ new Set();
@@ -19983,7 +20101,7 @@ async function runScan(opts, deps = {}) {
19983
20101
  ...sourceRepo ? { source: await buildScanSource(opts.repoPath, sourceRepo, headSha) } : {}
19984
20102
  });
19985
20103
  try {
19986
- const model = await resolveModelPin(supabase);
20104
+ const model = await resolveRunnableModel(supabase, { warn: log });
19987
20105
  const interactive = opts.interactive !== false;
19988
20106
  log(
19989
20107
  interactive ? `starting claude (mcp config at ${configPath}, model ${model}) \u2014 this session is interactive; answer its questions as they come` : `spawning claude (mcp config at ${configPath}, model ${model}, timeout ${Math.round(SCAN_CLAUDE_TIMEOUT_MS / 6e4)} min)`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archme/cli",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Map your codebase into a living architecture diagram: run `archme init` in a repo to scan it, `archme daemon start` to keep it current on every commit.",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",