@iamu-dev/iamu 0.2.0-beta.10 → 0.2.0-beta.11

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/index.js CHANGED
@@ -5363,9 +5363,9 @@ function pidIsDead(rec) {
5363
5363
  async function isStale(lockPath, rec, staleMs, now) {
5364
5364
  if (rec === null) {
5365
5365
  try {
5366
- const stat2 = await fs5.stat(lockPath);
5367
- if (stat2.size === 0) {
5368
- const mtime = stat2.birthtimeMs && stat2.birthtimeMs > 0 ? stat2.birthtimeMs : stat2.mtimeMs;
5366
+ const stat3 = await fs5.stat(lockPath);
5367
+ if (stat3.size === 0) {
5368
+ const mtime = stat3.birthtimeMs && stat3.birthtimeMs > 0 ? stat3.birthtimeMs : stat3.mtimeMs;
5369
5369
  if (now - mtime <= staleMs) {
5370
5370
  return false;
5371
5371
  }
@@ -12184,15 +12184,15 @@ function resolveApiUrl(configured) {
12184
12184
  assertSecureApiUrl(url, configured ? "API URL" : "IAMU_API_URL");
12185
12185
  return url;
12186
12186
  }
12187
- function parseStore(raw, path30) {
12187
+ function parseStore(raw, path31) {
12188
12188
  let parsed;
12189
12189
  try {
12190
12190
  parsed = JSON.parse(raw);
12191
12191
  } catch (err) {
12192
- throw new CredentialsFileError(path30, "not valid JSON", err);
12192
+ throw new CredentialsFileError(path31, "not valid JSON", err);
12193
12193
  }
12194
12194
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
12195
- throw new CredentialsFileError(path30, "expected a JSON object");
12195
+ throw new CredentialsFileError(path31, "expected a JSON object");
12196
12196
  }
12197
12197
  return parsed;
12198
12198
  }
@@ -12200,26 +12200,26 @@ function isNotFound(err) {
12200
12200
  return typeof err === "object" && err !== null && err.code === "ENOENT";
12201
12201
  }
12202
12202
  async function readCredentialsStore() {
12203
- const path30 = getCredentialsPath();
12203
+ const path31 = getCredentialsPath();
12204
12204
  let raw;
12205
12205
  try {
12206
- raw = await readFile(path30, "utf-8");
12206
+ raw = await readFile(path31, "utf-8");
12207
12207
  } catch (err) {
12208
12208
  if (isNotFound(err)) return {};
12209
12209
  warnUnreadableStoreOnce(err);
12210
12210
  throw err;
12211
12211
  }
12212
12212
  try {
12213
- return parseStore(raw, path30);
12213
+ return parseStore(raw, path31);
12214
12214
  } catch (err) {
12215
12215
  warnUnreadableStoreOnce(err);
12216
12216
  throw err;
12217
12217
  }
12218
12218
  }
12219
12219
  async function writeCredentialsStore(store) {
12220
- const path30 = getCredentialsPath();
12221
- await mkdir(dirname(path30), { recursive: true, mode: 448 });
12222
- await atomicWriteFile(path30, `${JSON.stringify(store, null, 2)}
12220
+ const path31 = getCredentialsPath();
12221
+ await mkdir(dirname(path31), { recursive: true, mode: 448 });
12222
+ await atomicWriteFile(path31, `${JSON.stringify(store, null, 2)}
12223
12223
  `, {
12224
12224
  mode: 384
12225
12225
  });
@@ -12239,16 +12239,16 @@ function resolveApiKey(apiUrl) {
12239
12239
  } catch {
12240
12240
  return null;
12241
12241
  }
12242
- const path30 = getCredentialsPath();
12242
+ const path31 = getCredentialsPath();
12243
12243
  let raw;
12244
12244
  try {
12245
- raw = readFileSync(path30, "utf-8");
12245
+ raw = readFileSync(path31, "utf-8");
12246
12246
  } catch (err) {
12247
12247
  if (!isNotFound(err)) warnUnreadableStoreOnce(err);
12248
12248
  return null;
12249
12249
  }
12250
12250
  try {
12251
- const entry = parseStore(raw, path30)[url];
12251
+ const entry = parseStore(raw, path31)[url];
12252
12252
  if (typeof entry !== "object" || entry === null) return null;
12253
12253
  const token = entry.token;
12254
12254
  return typeof token === "string" && token ? token : null;
@@ -12287,12 +12287,12 @@ var init_credentials = __esm({
12287
12287
  * @param reason - What is wrong with it.
12288
12288
  * @param cause - Underlying parse error, if any.
12289
12289
  */
12290
- constructor(path30, reason, cause) {
12290
+ constructor(path31, reason, cause) {
12291
12291
  super(
12292
- `Credentials file ${path30} is corrupt (${reason}). Fix it by hand, or delete it and run \`iamu auth login\` again.`,
12292
+ `Credentials file ${path31} is corrupt (${reason}). Fix it by hand, or delete it and run \`iamu auth login\` again.`,
12293
12293
  {
12294
12294
  cause,
12295
- suggestedAction: `Delete ${path30} and run \`iamu auth login\`, or set IAMU_TOKEN.`
12295
+ suggestedAction: `Delete ${path31} and run \`iamu auth login\`, or set IAMU_TOKEN.`
12296
12296
  }
12297
12297
  );
12298
12298
  }
@@ -12301,84 +12301,11 @@ var init_credentials = __esm({
12301
12301
  }
12302
12302
  });
12303
12303
 
12304
- // src/commands/cloud-push.ts
12305
- import chalk3 from "chalk";
12306
- async function pushRunToCloud(projectRoot, runId) {
12307
- const config = await readConfig(projectRoot);
12308
- if (!config.cloud_linked) return void 0;
12309
- const apiKey = resolveApiKey(config.cloud_api_url) ?? void 0;
12310
- const result = await mirrorLocalWalkthrough(projectRoot, runId, { apiKey });
12311
- const onCloud = result.mirrored || result.status === "already_pushed";
12312
- return {
12313
- mirrored: result.mirrored,
12314
- status: result.status,
12315
- ...result.skippedReason ? { skipped_reason: result.skippedReason } : {},
12316
- ...onCloud ? {
12317
- url: getCloudDashboardUrl(
12318
- config.cloud_api_url,
12319
- config.cloud_project_id,
12320
- result.runCloudId ?? toCloudRunUuid(runId)
12321
- )
12322
- } : {}
12323
- };
12324
- }
12325
- async function projectDashboardUrl(projectRoot) {
12326
- const config = await readConfig(projectRoot);
12327
- if (!config.cloud_linked) return null;
12328
- return getCloudDashboardUrl(config.cloud_api_url, config.cloud_project_id);
12329
- }
12330
- async function pushedRunUrl(projectRoot, runId) {
12331
- const config = await readConfig(projectRoot);
12332
- if (!config.cloud_linked) return null;
12333
- const lastPush = await readLastPush(projectRoot);
12334
- if (!lastPush[`walkthrough:${runId}`]) return null;
12335
- return getCloudDashboardUrl(
12336
- config.cloud_api_url,
12337
- config.cloud_project_id,
12338
- toCloudRunUuid(runId)
12339
- );
12340
- }
12341
- function printCloudRunInfo(info) {
12342
- if (!info) return;
12343
- console.log();
12344
- if (info.url) {
12345
- const state = info.mirrored ? "pushed" : "already pushed";
12346
- console.log(` ${chalk3.dim("cloud:")} ${chalk3.green(state)}`);
12347
- console.log(` ${chalk3.dim("view:")} ${chalk3.underline(info.url)}`);
12348
- return;
12349
- }
12350
- if (info.status === "enqueued") {
12351
- console.log(
12352
- ` ${chalk3.dim("cloud:")} ${chalk3.yellow("queued")} ${chalk3.dim("(will retry on next `iamu sync`)")}`
12353
- );
12354
- return;
12355
- }
12356
- const reason = info.skipped_reason ?? "unknown";
12357
- const remedy = SKIP_REMEDY[reason];
12358
- console.log(
12359
- ` ${chalk3.dim("cloud:")} ${chalk3.dim(`skipped (${reason})`)}${remedy ? chalk3.dim(` \u2014 ${remedy}`) : ""}`
12360
- );
12361
- }
12362
- var SKIP_REMEDY;
12363
- var init_cloud_push = __esm({
12364
- "src/commands/cloud-push.ts"() {
12365
- "use strict";
12366
- init_dist2();
12367
- init_cloud_url();
12368
- init_credentials();
12369
- SKIP_REMEDY = {
12370
- no_api_key: "run `iamu auth login` to restore credentials",
12371
- bundle_too_large: "reduce screenshot count or resolution, then `iamu sync`",
12372
- cloud_conflict: "this cloud does not accept updates to a pushed run yet"
12373
- };
12374
- }
12375
- });
12376
-
12377
12304
  // src/commands/context.ts
12378
- import chalk4 from "chalk";
12305
+ import chalk3 from "chalk";
12379
12306
  import { ZodError } from "zod";
12380
12307
  function commandError(message, opts) {
12381
- const formatted = opts?.json ? JSON.stringify({ error: message }) : chalk4.red(` ${message}`);
12308
+ const formatted = opts?.json ? JSON.stringify({ error: message }) : chalk3.red(` ${message}`);
12382
12309
  console.error(formatted);
12383
12310
  process.exitCode = 1;
12384
12311
  }
@@ -12400,7 +12327,7 @@ async function resolveProject(opts) {
12400
12327
  commandError("No iamu/ found. Run: iamu init", opts);
12401
12328
  } else {
12402
12329
  console.error(
12403
- chalk4.red(" No iamu/ found.") + chalk4.dim(" Run: iamu init")
12330
+ chalk3.red(" No iamu/ found.") + chalk3.dim(" Run: iamu init")
12404
12331
  );
12405
12332
  process.exitCode = 1;
12406
12333
  }
@@ -12443,7 +12370,7 @@ async function resolveCloudProject(opts) {
12443
12370
  commandError("Not authenticated. Run `iamu auth login` first.", opts);
12444
12371
  } else {
12445
12372
  console.error(
12446
- chalk4.red(" Not authenticated.") + chalk4.dim(" Run `iamu auth login` first.")
12373
+ chalk3.red(" Not authenticated.") + chalk3.dim(" Run `iamu auth login` first.")
12447
12374
  );
12448
12375
  process.exitCode = 1;
12449
12376
  }
@@ -12481,6 +12408,334 @@ var init_context4 = __esm({
12481
12408
  }
12482
12409
  });
12483
12410
 
12411
+ // src/commands/live-run-client.ts
12412
+ import { readFile as readFile2, stat } from "fs/promises";
12413
+ import path18 from "path";
12414
+ import chalk4 from "chalk";
12415
+ async function loadLiveRunMeta(runDirPath) {
12416
+ try {
12417
+ const raw = await readFile2(path18.join(runDirPath, "live.json"), "utf8");
12418
+ const parsed = JSON.parse(raw);
12419
+ if (typeof parsed?.walkthrough_id === "string" && typeof parsed?.viewer_url === "string" && typeof parsed?.project_id === "string" && typeof parsed?.api_url === "string" && typeof parsed?.last_seq === "number") {
12420
+ return parsed;
12421
+ }
12422
+ return null;
12423
+ } catch {
12424
+ return null;
12425
+ }
12426
+ }
12427
+ async function saveLiveRunMeta(runDirPath, meta) {
12428
+ await atomicWriteFile(
12429
+ path18.join(runDirPath, "live.json"),
12430
+ JSON.stringify(meta, null, 2) + "\n"
12431
+ );
12432
+ }
12433
+ async function registerLiveRun(params) {
12434
+ if (process.env.IAMU_LIVE === "0") {
12435
+ return null;
12436
+ }
12437
+ try {
12438
+ const config = await readConfig(params.projectRoot).catch(() => null);
12439
+ if (!config?.cloud_linked || !config.cloud_project_id || !config.cloud_api_url) {
12440
+ return null;
12441
+ }
12442
+ const apiKey = resolveApiKey(config.cloud_api_url);
12443
+ if (!apiKey) {
12444
+ return null;
12445
+ }
12446
+ const scenario = await readEntity(
12447
+ params.projectRoot,
12448
+ "scenario",
12449
+ params.scenarioSlug
12450
+ ).catch(() => null);
12451
+ const scenarioId = scenario?.frontmatter?.id;
12452
+ if (!scenarioId) {
12453
+ return null;
12454
+ }
12455
+ const runDirPath = resolveRunDir(params.projectRoot, params.runId);
12456
+ if (!runDirPath) {
12457
+ return null;
12458
+ }
12459
+ const walkthroughId = toCloudRunUuid(params.runId);
12460
+ const apiUrl = config.cloud_api_url.replace(/\/$/, "");
12461
+ const endpoint = `${apiUrl}/api/projects/${encodeURIComponent(config.cloud_project_id)}/live-runs`;
12462
+ const fetcher = params.fetchFn ?? globalThis.fetch;
12463
+ const postLiveRun = () => fetcher(endpoint, {
12464
+ method: "POST",
12465
+ headers: {
12466
+ Authorization: `Bearer ${apiKey}`,
12467
+ "Content-Type": "application/json"
12468
+ },
12469
+ body: JSON.stringify({
12470
+ run_id: walkthroughId,
12471
+ scenario_id: scenarioId,
12472
+ target_url: params.targetUrl,
12473
+ started_at: params.startedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
12474
+ lenses: params.lenses ?? ["persona"]
12475
+ }),
12476
+ signal: AbortSignal.timeout(REGISTER_TIMEOUT_MS)
12477
+ });
12478
+ let res = await postLiveRun();
12479
+ if (res.status === 422) {
12480
+ const data2 = await res.json().catch(() => null);
12481
+ if (data2?.code === "unknown_scenario") {
12482
+ console.log(
12483
+ chalk4.dim(
12484
+ ` ${symbols.info} Scenario not on cloud yet. Auto-syncing to enable live stream...`
12485
+ )
12486
+ );
12487
+ try {
12488
+ await runSync(params.projectRoot, {
12489
+ apiKey,
12490
+ fetch: fetcher,
12491
+ timeoutMs: REGISTER_TIMEOUT_MS
12492
+ });
12493
+ res = await postLiveRun();
12494
+ if (!res.ok) {
12495
+ console.log(
12496
+ chalk4.dim(
12497
+ ` ${symbols.info} Scenario sync deferred. Run \`iamu sync\` to follow future runs live.`
12498
+ )
12499
+ );
12500
+ return null;
12501
+ }
12502
+ } catch {
12503
+ console.log(
12504
+ chalk4.dim(
12505
+ ` ${symbols.info} Scenario sync deferred. Run \`iamu sync\` to follow future runs live.`
12506
+ )
12507
+ );
12508
+ return null;
12509
+ }
12510
+ } else {
12511
+ return null;
12512
+ }
12513
+ }
12514
+ if (!res.ok) {
12515
+ return null;
12516
+ }
12517
+ const data = await res.json();
12518
+ const meta = {
12519
+ walkthrough_id: data.walkthrough_id,
12520
+ viewer_url: data.viewer_url,
12521
+ project_id: config.cloud_project_id,
12522
+ api_url: config.cloud_api_url,
12523
+ last_seq: 0
12524
+ };
12525
+ await saveLiveRunMeta(runDirPath, meta);
12526
+ return {
12527
+ walkthroughId: data.walkthrough_id,
12528
+ viewerUrl: data.viewer_url,
12529
+ status: data.status
12530
+ };
12531
+ } catch {
12532
+ return null;
12533
+ }
12534
+ }
12535
+ async function sendLiveEvents(projectRoot, runId, buildEvents, fetchFn) {
12536
+ try {
12537
+ const runDirPath = resolveRunDir(projectRoot, runId);
12538
+ if (!runDirPath) return {};
12539
+ const meta = await loadLiveRunMeta(runDirPath);
12540
+ if (!meta) return {};
12541
+ const config = await readConfig(projectRoot).catch(() => null);
12542
+ if (!config?.cloud_linked) return {};
12543
+ const apiKey = resolveApiKey(meta.api_url) ?? resolveApiKey(config.cloud_api_url);
12544
+ if (!apiKey) return {};
12545
+ const raw = buildEvents(meta.last_seq + 1);
12546
+ const events = Array.isArray(raw) ? raw : [raw];
12547
+ if (events.length === 0) return {};
12548
+ const maxSeq = Math.max(...events.map((e) => e.seq));
12549
+ meta.last_seq = Math.max(meta.last_seq, maxSeq);
12550
+ await saveLiveRunMeta(runDirPath, meta).catch(() => {
12551
+ });
12552
+ const apiUrl = meta.api_url.replace(/\/$/, "");
12553
+ const endpoint = `${apiUrl}/api/projects/${encodeURIComponent(meta.project_id)}/live-runs/${encodeURIComponent(meta.walkthrough_id)}/events`;
12554
+ const fetcher = fetchFn ?? globalThis.fetch;
12555
+ const res = await fetcher(endpoint, {
12556
+ method: "POST",
12557
+ headers: {
12558
+ Authorization: `Bearer ${apiKey}`,
12559
+ "Content-Type": "application/json"
12560
+ },
12561
+ body: JSON.stringify({ events }),
12562
+ signal: AbortSignal.timeout(EVENT_TIMEOUT_MS)
12563
+ });
12564
+ if (!res.ok) {
12565
+ return {};
12566
+ }
12567
+ const data = await res.json().catch(() => null);
12568
+ return {
12569
+ accepted_seq: data?.accepted_seq,
12570
+ cancelled: data?.cancelled === true
12571
+ };
12572
+ } catch {
12573
+ return {};
12574
+ }
12575
+ }
12576
+ async function sendLiveStep(projectRoot, runId, step, screenshotPath, fetchFn) {
12577
+ try {
12578
+ const runDirPath = resolveRunDir(projectRoot, runId);
12579
+ if (!runDirPath) return {};
12580
+ const meta = await loadLiveRunMeta(runDirPath);
12581
+ if (!meta) return {};
12582
+ let screenshot_base64;
12583
+ if (screenshotPath) {
12584
+ try {
12585
+ const fileStat = await stat(screenshotPath);
12586
+ if (fileStat.isFile() && fileStat.size <= MAX_LIVE_SCREENSHOT_BYTES) {
12587
+ const buf = await readFile2(screenshotPath);
12588
+ screenshot_base64 = buf.toString("base64");
12589
+ }
12590
+ } catch {
12591
+ }
12592
+ }
12593
+ return await sendLiveEvents(
12594
+ projectRoot,
12595
+ runId,
12596
+ (seq2) => ({
12597
+ seq: seq2,
12598
+ type: "step",
12599
+ step: {
12600
+ number: step.step_number,
12601
+ title: step.action,
12602
+ persona_reasoning: step.note ?? void 0,
12603
+ grounding: step.grounding ?? void 0,
12604
+ page_url: step.url ?? void 0,
12605
+ surface: step.surface ?? void 0,
12606
+ ...screenshot_base64 ? { screenshot_base64 } : {}
12607
+ }
12608
+ }),
12609
+ fetchFn
12610
+ );
12611
+ } catch {
12612
+ return {};
12613
+ }
12614
+ }
12615
+ async function sendLivePhase(projectRoot, runId, phase, fetchFn) {
12616
+ return sendLiveEvents(
12617
+ projectRoot,
12618
+ runId,
12619
+ (seq2) => ({
12620
+ seq: seq2,
12621
+ type: "phase",
12622
+ phase
12623
+ }),
12624
+ fetchFn
12625
+ );
12626
+ }
12627
+ async function sendLiveFinding(projectRoot, runId, finding, fetchFn) {
12628
+ return sendLiveEvents(
12629
+ projectRoot,
12630
+ runId,
12631
+ (seq2) => ({
12632
+ seq: seq2,
12633
+ type: "finding",
12634
+ finding: {
12635
+ id: finding.id,
12636
+ title: finding.title,
12637
+ type: finding.type,
12638
+ severity: finding.severity,
12639
+ ui_fact: finding.ui_fact ?? void 0,
12640
+ consequence: finding.consequence ?? void 0,
12641
+ step_number: finding.step_number ?? void 0,
12642
+ task_impact: finding.task_impact ?? void 0,
12643
+ confidence: finding.confidence ?? void 0
12644
+ }
12645
+ }),
12646
+ fetchFn
12647
+ );
12648
+ }
12649
+ var REGISTER_TIMEOUT_MS, EVENT_TIMEOUT_MS, MAX_LIVE_SCREENSHOT_BYTES;
12650
+ var init_live_run_client = __esm({
12651
+ "src/commands/live-run-client.ts"() {
12652
+ "use strict";
12653
+ init_dist2();
12654
+ init_symbols();
12655
+ init_context4();
12656
+ init_credentials();
12657
+ REGISTER_TIMEOUT_MS = 3e3;
12658
+ EVENT_TIMEOUT_MS = 1500;
12659
+ MAX_LIVE_SCREENSHOT_BYTES = 5 * 1024 * 1024;
12660
+ }
12661
+ });
12662
+
12663
+ // src/commands/cloud-push.ts
12664
+ import chalk5 from "chalk";
12665
+ async function pushRunToCloud(projectRoot, runId) {
12666
+ const config = await readConfig(projectRoot);
12667
+ if (!config.cloud_linked) return void 0;
12668
+ await sendLivePhase(projectRoot, runId, "publishing").catch(() => {
12669
+ });
12670
+ const apiKey = resolveApiKey(config.cloud_api_url) ?? void 0;
12671
+ const result = await mirrorLocalWalkthrough(projectRoot, runId, { apiKey });
12672
+ const onCloud = result.mirrored || result.status === "already_pushed";
12673
+ return {
12674
+ mirrored: result.mirrored,
12675
+ status: result.status,
12676
+ ...result.skippedReason ? { skipped_reason: result.skippedReason } : {},
12677
+ ...onCloud ? {
12678
+ url: getCloudDashboardUrl(
12679
+ config.cloud_api_url,
12680
+ config.cloud_project_id,
12681
+ result.runCloudId ?? toCloudRunUuid(runId)
12682
+ )
12683
+ } : {}
12684
+ };
12685
+ }
12686
+ async function projectDashboardUrl(projectRoot) {
12687
+ const config = await readConfig(projectRoot);
12688
+ if (!config.cloud_linked) return null;
12689
+ return getCloudDashboardUrl(config.cloud_api_url, config.cloud_project_id);
12690
+ }
12691
+ async function pushedRunUrl(projectRoot, runId) {
12692
+ const config = await readConfig(projectRoot);
12693
+ if (!config.cloud_linked) return null;
12694
+ const lastPush = await readLastPush(projectRoot);
12695
+ if (!lastPush[`walkthrough:${runId}`]) return null;
12696
+ return getCloudDashboardUrl(
12697
+ config.cloud_api_url,
12698
+ config.cloud_project_id,
12699
+ toCloudRunUuid(runId)
12700
+ );
12701
+ }
12702
+ function printCloudRunInfo(info) {
12703
+ if (!info) return;
12704
+ console.log();
12705
+ if (info.url) {
12706
+ const state = info.mirrored ? "pushed" : "already pushed";
12707
+ console.log(` ${chalk5.dim("cloud:")} ${chalk5.green(state)}`);
12708
+ console.log(` ${chalk5.dim("view:")} ${chalk5.underline(info.url)}`);
12709
+ return;
12710
+ }
12711
+ if (info.status === "enqueued") {
12712
+ console.log(
12713
+ ` ${chalk5.dim("cloud:")} ${chalk5.yellow("queued")} ${chalk5.dim("(will retry on next `iamu sync`)")}`
12714
+ );
12715
+ return;
12716
+ }
12717
+ const reason = info.skipped_reason ?? "unknown";
12718
+ const remedy = SKIP_REMEDY[reason];
12719
+ console.log(
12720
+ ` ${chalk5.dim("cloud:")} ${chalk5.dim(`skipped (${reason})`)}${remedy ? chalk5.dim(` \u2014 ${remedy}`) : ""}`
12721
+ );
12722
+ }
12723
+ var SKIP_REMEDY;
12724
+ var init_cloud_push = __esm({
12725
+ "src/commands/cloud-push.ts"() {
12726
+ "use strict";
12727
+ init_dist2();
12728
+ init_cloud_url();
12729
+ init_credentials();
12730
+ init_live_run_client();
12731
+ SKIP_REMEDY = {
12732
+ no_api_key: "run `iamu auth login` to restore credentials",
12733
+ bundle_too_large: "reduce screenshot count or resolution, then `iamu sync`",
12734
+ cloud_conflict: "this cloud does not accept updates to a pushed run yet"
12735
+ };
12736
+ }
12737
+ });
12738
+
12484
12739
  // src/adapters/claude-plugin.ts
12485
12740
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
12486
12741
  import { homedir as homedir2 } from "os";
@@ -12712,10 +12967,10 @@ var init_templates = __esm({
12712
12967
 
12713
12968
  // src/commands/skills.ts
12714
12969
  import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
12715
- import { mkdir as mkdir2, readFile as readFile2, rm, rmdir, writeFile } from "fs/promises";
12970
+ import { mkdir as mkdir2, readFile as readFile3, rm, rmdir, writeFile } from "fs/promises";
12716
12971
  import { dirname as dirname3, join as join4, resolve as resolve2 } from "path";
12717
12972
  import { fileURLToPath as fileURLToPath2 } from "url";
12718
- import chalk5 from "chalk";
12973
+ import chalk6 from "chalk";
12719
12974
  function getVersion() {
12720
12975
  try {
12721
12976
  const thisDir = dirname3(fileURLToPath2(import.meta.url));
@@ -12805,22 +13060,22 @@ function commandsFromSkills(templates) {
12805
13060
  }
12806
13061
  async function needsWrite(filePath, content) {
12807
13062
  try {
12808
- const existing = await readFile2(filePath, "utf-8");
13063
+ const existing = await readFile3(filePath, "utf-8");
12809
13064
  return existing !== content;
12810
13065
  } catch {
12811
13066
  return true;
12812
13067
  }
12813
13068
  }
12814
- function isCliWrittenSkill(path30) {
13069
+ function isCliWrittenSkill(path31) {
12815
13070
  try {
12816
- return /^generatedBy:/m.test(readFileSync3(path30, "utf-8"));
13071
+ return /^generatedBy:/m.test(readFileSync3(path31, "utf-8"));
12817
13072
  } catch {
12818
13073
  return false;
12819
13074
  }
12820
13075
  }
12821
- function isCliWrittenPrompt(path30) {
13076
+ function isCliWrittenPrompt(path31) {
12822
13077
  try {
12823
- const content = readFileSync3(path30, "utf-8");
13078
+ const content = readFileSync3(path31, "utf-8");
12824
13079
  return content.includes("iamu") || /^generatedBy:/m.test(content);
12825
13080
  } catch {
12826
13081
  return false;
@@ -12832,8 +13087,8 @@ function planSkillFiles(hosts, projectRoot, version) {
12832
13087
  for (const host of hosts) {
12833
13088
  if (pluginProvidesSkills(host, projectRoot)) {
12834
13089
  for (const name of skillTemplates.keys()) {
12835
- const path30 = join4(host.getSkillsDir(projectRoot), name, "SKILL.md");
12836
- if (isCliWrittenSkill(path30)) files.push({ host, path: path30, content: null });
13090
+ const path31 = join4(host.getSkillsDir(projectRoot), name, "SKILL.md");
13091
+ if (isCliWrittenSkill(path31)) files.push({ host, path: path31, content: null });
12837
13092
  }
12838
13093
  } else if (host.supportsSkills) {
12839
13094
  const skillsDir = host.getSkillsDir(projectRoot);
@@ -12989,7 +13244,7 @@ async function installSkillsForHosts(hosts, projectRoot, version, opts) {
12989
13244
  );
12990
13245
  } else {
12991
13246
  console.log(
12992
- ` ${symbols.success} ${chalk5.dim(`${host.name} \u2014 up to date`)}`
13247
+ ` ${symbols.success} ${chalk6.dim(`${host.name} \u2014 up to date`)}`
12993
13248
  );
12994
13249
  }
12995
13250
  }
@@ -13014,11 +13269,11 @@ var sync_exports = {};
13014
13269
  __export(sync_exports, {
13015
13270
  sync: () => sync
13016
13271
  });
13017
- import chalk6 from "chalk";
13272
+ import chalk7 from "chalk";
13018
13273
  async function warnStaleSkills(projectRoot) {
13019
13274
  try {
13020
13275
  if ((await findStaleSkills(projectRoot)).length > 0) {
13021
- console.log(chalk6.yellow(` ${STALE_SKILLS_MESSAGE}`));
13276
+ console.log(chalk7.yellow(` ${STALE_SKILLS_MESSAGE}`));
13022
13277
  }
13023
13278
  } catch {
13024
13279
  }
@@ -13046,11 +13301,11 @@ function describeCounts(byType) {
13046
13301
  function printPendingDeletes(pending) {
13047
13302
  console.log();
13048
13303
  console.log(
13049
- chalk6.yellow(
13304
+ chalk7.yellow(
13050
13305
  ` \u26A0 ${pending.total} local deletion${pending.total !== 1 ? "s" : ""} not sent to the cloud \u2014 check the list, then run \`iamu sync --confirm-deletes\``
13051
13306
  )
13052
13307
  );
13053
- console.log(chalk6.dim(` Why: ${pending.reasons.join("; ")}`));
13308
+ console.log(chalk7.dim(` Why: ${pending.reasons.join("; ")}`));
13054
13309
  const byType = /* @__PURE__ */ new Map();
13055
13310
  for (const e of pending.entities) {
13056
13311
  const list2 = byType.get(e.type) ?? [];
@@ -13062,18 +13317,18 @@ function printPendingDeletes(pending) {
13062
13317
  ` ${describeDeletionCount(type2, list2.length)}${type2 === "unknown" ? " (synced before this CLI recorded types; by id)" : ""}:`
13063
13318
  );
13064
13319
  for (const e of list2.slice(0, MAX_LISTED_PER_TYPE)) {
13065
- console.log(chalk6.dim(` ${e.label}`));
13320
+ console.log(chalk7.dim(` ${e.label}`));
13066
13321
  }
13067
13322
  if (list2.length > MAX_LISTED_PER_TYPE) {
13068
13323
  console.log(
13069
- chalk6.dim(
13324
+ chalk7.dim(
13070
13325
  ` \u2026 and ${list2.length - MAX_LISTED_PER_TYPE} more (\`iamu sync --json\` lists all)`
13071
13326
  )
13072
13327
  );
13073
13328
  }
13074
13329
  }
13075
13330
  console.log(
13076
- chalk6.dim(
13331
+ chalk7.dim(
13077
13332
  " To keep an entity on the cloud instead, restore its file (`iamu pull` brings entities back; runs cannot be pulled)."
13078
13333
  )
13079
13334
  );
@@ -13112,24 +13367,24 @@ async function sync(opts) {
13112
13367
  } else {
13113
13368
  if (!quiet) console.log();
13114
13369
  console.log(
13115
- ` ${chalk6.bold("Sync Status:")} ${totalPending === 0 ? chalk6.green("in sync") : chalk6.yellow(`${totalPending} item(s) to sync`)}`
13370
+ ` ${chalk7.bold("Sync Status:")} ${totalPending === 0 ? chalk7.green("in sync") : chalk7.yellow(`${totalPending} item(s) to sync`)}`
13116
13371
  );
13117
13372
  if (totalPending > 0) {
13118
13373
  if (pendingNew > 0)
13119
- console.log(chalk6.dim(` ${pendingNew} new entity file(s)`));
13374
+ console.log(chalk7.dim(` ${pendingNew} new entity file(s)`));
13120
13375
  if (pendingUpdates > 0)
13121
13376
  console.log(
13122
- chalk6.dim(` ${pendingUpdates} modified entity file(s)`)
13377
+ chalk7.dim(` ${pendingUpdates} modified entity file(s)`)
13123
13378
  );
13124
13379
  if (pendingWalkthroughs > 0)
13125
13380
  console.log(
13126
- chalk6.dim(` ${pendingWalkthroughs} unpushed walkthrough run(s)`)
13381
+ chalk7.dim(` ${pendingWalkthroughs} unpushed walkthrough run(s)`)
13127
13382
  );
13128
13383
  if (pendingRetries > 0)
13129
- console.log(chalk6.dim(` ${pendingRetries} queued retry item(s)`));
13384
+ console.log(chalk7.dim(` ${pendingRetries} queued retry item(s)`));
13130
13385
  if (deletions && pendingDeletions > 0)
13131
13386
  console.log(
13132
- chalk6.dim(
13387
+ chalk7.dim(
13133
13388
  ` ${pendingDeletions} local deletion(s): ${describeCounts(deletions.by_type)}${deletions.needs_confirm ? " \u2014 needs `iamu sync --confirm-deletes`" : ""}`
13134
13389
  )
13135
13390
  );
@@ -13186,23 +13441,23 @@ async function sync(opts) {
13186
13441
  Object.entries(result.deleted.cloud_by_type).filter(([, n]) => n > 0)
13187
13442
  );
13188
13443
  console.log(
13189
- Object.keys(removed).length > 0 ? ` ${chalk6.green("\u2713")} Deleted on cloud: ${describeCounts(removed)}` : ` ${chalk6.green("\u2713")} Nothing left to delete on the cloud \u2014 ${describeCounts(result.deleted.by_type)} ${result.deleted.total === 1 ? "was" : "were"} already gone there`
13444
+ Object.keys(removed).length > 0 ? ` ${chalk7.green("\u2713")} Deleted on cloud: ${describeCounts(removed)}` : ` ${chalk7.green("\u2713")} Nothing left to delete on the cloud \u2014 ${describeCounts(result.deleted.by_type)} ${result.deleted.total === 1 ? "was" : "were"} already gone there`
13190
13445
  );
13191
13446
  }
13192
13447
  if (result.pending_deletes) printPendingDeletes(result.pending_deletes);
13193
13448
  if (result.held_deletes) {
13194
13449
  const n = result.held_deletes.length;
13195
13450
  console.log(
13196
- chalk6.yellow(` ${n} local deletion${n !== 1 ? "s" : ""} held back:`)
13451
+ chalk7.yellow(` ${n} local deletion${n !== 1 ? "s" : ""} held back:`)
13197
13452
  );
13198
13453
  for (const h of result.held_deletes) {
13199
13454
  console.log(
13200
- ` ${describeDeletionCount(h.type, 1).replace(/^1 /, "")} ${h.label}${chalk6.dim(` \u2014 ${h.reason}`)}`
13455
+ ` ${describeDeletionCount(h.type, 1).replace(/^1 /, "")} ${h.label}${chalk7.dim(` \u2014 ${h.reason}`)}`
13201
13456
  );
13202
13457
  }
13203
13458
  if (result.held_deletes.some((h) => h.branches)) {
13204
13459
  console.log(
13205
- chalk6.dim(
13460
+ chalk7.dim(
13206
13461
  " A file still on another branch usually means you switched branches, not that you deleted it. If you did delete it, `iamu sync --confirm-deletes` sends it anyway."
13207
13462
  )
13208
13463
  );
@@ -13210,12 +13465,12 @@ async function sync(opts) {
13210
13465
  }
13211
13466
  if (result.drain.drained > 0) {
13212
13467
  console.log(
13213
- chalk6.dim(` Drained ${result.drain.drained} retry-queue items`)
13468
+ chalk7.dim(` Drained ${result.drain.drained} retry-queue items`)
13214
13469
  );
13215
13470
  }
13216
13471
  if (result.draftsSkipped > 0) {
13217
13472
  console.log(
13218
- chalk6.dim(
13473
+ chalk7.dim(
13219
13474
  ` ${result.draftsSkipped} draft scenarios skipped \u2014 bind a persona to push`
13220
13475
  )
13221
13476
  );
@@ -13224,7 +13479,7 @@ async function sync(opts) {
13224
13479
  if (enqueuedTotal > 0) {
13225
13480
  const total = enqueuedTotal;
13226
13481
  console.log(
13227
- chalk6.yellow(
13482
+ chalk7.yellow(
13228
13483
  ` ${total} items enqueued for retry (will retry next sync)`
13229
13484
  )
13230
13485
  );
@@ -13237,7 +13492,7 @@ async function sync(opts) {
13237
13492
  );
13238
13493
  console.log();
13239
13494
  console.log(
13240
- chalk6.yellow(
13495
+ chalk7.yellow(
13241
13496
  ` \u26A0 --keep-mine replaced ${n} cloud change${n !== 1 ? "s" : ""}:`
13242
13497
  )
13243
13498
  );
@@ -13247,11 +13502,11 @@ async function sync(opts) {
13247
13502
  const slug = slugs.get(o.entity_id);
13248
13503
  const named = slug ? `${slug} (${o.entity_id})` : o.entity_id;
13249
13504
  console.log(
13250
- ` ${chalk6.yellow("\u26A0")} ${o.type} ${named} \u2014 overwrote ${who}'s change from ${when}`
13505
+ ` ${chalk7.yellow("\u26A0")} ${o.type} ${named} \u2014 overwrote ${who}'s change from ${when}`
13251
13506
  );
13252
13507
  }
13253
13508
  console.log(
13254
- chalk6.dim(
13509
+ chalk7.dim(
13255
13510
  " Their version is gone from cloud \u2014 `iamu pull --force` now returns yours."
13256
13511
  )
13257
13512
  );
@@ -13259,7 +13514,7 @@ async function sync(opts) {
13259
13514
  if (result.conflicts.length > 0) {
13260
13515
  console.log();
13261
13516
  console.log(
13262
- chalk6.yellow(
13517
+ chalk7.yellow(
13263
13518
  ` ${result.conflicts.length} conflict${result.conflicts.length !== 1 ? "s" : ""} detected:`
13264
13519
  )
13265
13520
  );
@@ -13271,12 +13526,12 @@ async function sync(opts) {
13271
13526
  );
13272
13527
  }
13273
13528
  console.log(
13274
- chalk6.dim(
13529
+ chalk7.dim(
13275
13530
  " Resolve: copy your edits aside, run `iamu pull --force` to take the cloud version, re-apply, then sync"
13276
13531
  )
13277
13532
  );
13278
13533
  console.log(
13279
- chalk6.dim(
13534
+ chalk7.dim(
13280
13535
  " Or keep yours: `iamu sync --keep-mine` re-pushes your version over theirs"
13281
13536
  )
13282
13537
  );
@@ -13286,26 +13541,26 @@ async function sync(opts) {
13286
13541
  }
13287
13542
  for (const f of result.drain.failures) {
13288
13543
  console.error(
13289
- ` ${symbols.error} ${f.label ?? f.entity_id}: ${chalk6.dim(f.error)}`
13544
+ ` ${symbols.error} ${f.label ?? f.entity_id}: ${chalk7.dim(f.error)}`
13290
13545
  );
13291
13546
  }
13292
13547
  if (result.drain.dropped > 0) {
13293
13548
  console.error(
13294
- chalk6.yellow(
13549
+ chalk7.yellow(
13295
13550
  ` ${result.drain.dropped} queued push${result.drain.dropped !== 1 ? "es were" : " was"} dropped from the retry queue \u2014 they can never succeed as queued (see above)`
13296
13551
  )
13297
13552
  );
13298
13553
  }
13299
13554
  for (const w of result.drain.warnings) {
13300
- console.error(` ${symbols.warning} retry queue: ${chalk6.dim(w)}`);
13555
+ console.error(` ${symbols.warning} retry queue: ${chalk7.dim(w)}`);
13301
13556
  }
13302
13557
  for (const n of result.notices ?? []) {
13303
- console.log(chalk6.dim(` ${n}`));
13558
+ console.log(chalk7.dim(` ${n}`));
13304
13559
  }
13305
13560
  if (totalPushed > 0) {
13306
13561
  const dashboard = await projectDashboardUrl(projectRoot);
13307
13562
  if (dashboard) {
13308
- console.log(` ${chalk6.dim("view:")} ${chalk6.underline(dashboard)}`);
13563
+ console.log(` ${chalk7.dim("view:")} ${chalk7.underline(dashboard)}`);
13309
13564
  }
13310
13565
  }
13311
13566
  if (failed) {
@@ -13336,7 +13591,7 @@ var pull_exports = {};
13336
13591
  __export(pull_exports, {
13337
13592
  pull: () => pull
13338
13593
  });
13339
- import chalk7 from "chalk";
13594
+ import chalk8 from "chalk";
13340
13595
  async function pull(opts) {
13341
13596
  if (opts?.force && opts?.preview) {
13342
13597
  commandError("--force and --preview are mutually exclusive.", opts);
@@ -13366,13 +13621,13 @@ async function pull(opts) {
13366
13621
  if (result.drain.failures.length > 0) {
13367
13622
  for (const f of result.drain.failures) {
13368
13623
  console.error(
13369
- ` ${symbols.error} drain: ${f.entity_id}: ${chalk7.dim(f.error)}`
13624
+ ` ${symbols.error} drain: ${f.entity_id}: ${chalk8.dim(f.error)}`
13370
13625
  );
13371
13626
  }
13372
13627
  }
13373
13628
  if (!quiet) console.log();
13374
13629
  if (result.preview) {
13375
- console.log(chalk7.dim(" Preview mode \u2014 no files written."));
13630
+ console.log(chalk8.dim(" Preview mode \u2014 no files written."));
13376
13631
  }
13377
13632
  const types2 = Object.entries(result.pulls);
13378
13633
  let totalWritten = 0;
@@ -13399,11 +13654,11 @@ async function pull(opts) {
13399
13654
  console.error(` ${symbols.error} ${type2}: ${err}`);
13400
13655
  }
13401
13656
  for (const warning of summary.warnings) {
13402
- console.error(` ${chalk7.yellow("\u26A0")} ${type2}: ${warning}`);
13657
+ console.error(` ${chalk8.yellow("\u26A0")} ${type2}: ${warning}`);
13403
13658
  }
13404
13659
  for (const { slug } of summary.diverged) {
13405
13660
  console.error(
13406
- ` ${chalk7.yellow("\u26A0")} ${type2} ${slug}: changed locally and in the cloud \u2014 keep yours with \`iamu sync --keep-mine\`, or take the cloud copy with \`iamu pull --force\``
13661
+ ` ${chalk8.yellow("\u26A0")} ${type2} ${slug}: changed locally and in the cloud \u2014 keep yours with \`iamu sync --keep-mine\`, or take the cloud copy with \`iamu pull --force\``
13407
13662
  );
13408
13663
  }
13409
13664
  }
@@ -13418,7 +13673,7 @@ async function pull(opts) {
13418
13673
  }
13419
13674
  if (totalSkipped > 0) {
13420
13675
  console.log(
13421
- chalk7.dim(
13676
+ chalk8.dim(
13422
13677
  ` ${totalSkipped} entities skipped (up to date or kept local)`
13423
13678
  )
13424
13679
  );
@@ -13569,7 +13824,7 @@ var init_auth_token_input = __esm({
13569
13824
  });
13570
13825
 
13571
13826
  // src/commands/mcp-config.ts
13572
- import { readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
13827
+ import { readFile as readFile4, writeFile as writeFile2 } from "fs/promises";
13573
13828
  import { basename, dirname as dirname4 } from "path";
13574
13829
  import { mkdir as mkdir3 } from "fs/promises";
13575
13830
  function isVscodePath(mcpPath) {
@@ -13578,7 +13833,7 @@ function isVscodePath(mcpPath) {
13578
13833
  async function writeSyncMcpEntry(mcpPath) {
13579
13834
  let existing = {};
13580
13835
  try {
13581
- const raw = await readFile3(mcpPath, "utf-8");
13836
+ const raw = await readFile4(mcpPath, "utf-8");
13582
13837
  existing = JSON.parse(raw);
13583
13838
  } catch (err) {
13584
13839
  if (err.code === "ENOENT") {
@@ -13635,7 +13890,7 @@ __export(auth_exports, {
13635
13890
  import { execFile as execFile2 } from "child_process";
13636
13891
  import { platform } from "os";
13637
13892
  import { isCancel, select, spinner } from "@clack/prompts";
13638
- import chalk8 from "chalk";
13893
+ import chalk9 from "chalk";
13639
13894
  function openBrowser(url, run = spawnDetached) {
13640
13895
  try {
13641
13896
  const parsed = new URL(url);
@@ -13759,8 +14014,8 @@ async function reportAlreadyLinked(projectRoot, config, apiUrl, requested) {
13759
14014
  }
13760
14015
  console.log();
13761
14016
  console.log(` ${symbols.success} Already authenticated and cloud-linked.`);
13762
- console.log(` ${chalk8.dim("API:")} ${apiUrl}`);
13763
- console.log(` ${chalk8.dim("Project:")} ${config.cloud_project_id}`);
14017
+ console.log(` ${chalk9.dim("API:")} ${apiUrl}`);
14018
+ console.log(` ${chalk9.dim("Project:")} ${config.cloud_project_id}`);
13764
14019
  await registerSyncServer(projectRoot);
13765
14020
  console.log();
13766
14021
  }
@@ -13768,8 +14023,8 @@ async function obtainToken(apiUrl, providedToken, reusedToken, opts, t) {
13768
14023
  if (providedToken) {
13769
14024
  console.log();
13770
14025
  console.log(
13771
- chalk8.bold(
13772
- ` Authenticating with provided token for ${chalk8.cyan(apiUrl)}...`
14026
+ chalk9.bold(
14027
+ ` Authenticating with provided token for ${chalk9.cyan(apiUrl)}...`
13773
14028
  )
13774
14029
  );
13775
14030
  return { token: providedToken, email: null, tenantId: null };
@@ -13777,7 +14032,7 @@ async function obtainToken(apiUrl, providedToken, reusedToken, opts, t) {
13777
14032
  if (reusedToken) {
13778
14033
  console.log();
13779
14034
  console.log(
13780
- chalk8.bold(` Using stored credentials for ${chalk8.cyan(apiUrl)}...`)
14035
+ chalk9.bold(` Using stored credentials for ${chalk9.cyan(apiUrl)}...`)
13781
14036
  );
13782
14037
  return { token: reusedToken, email: null, tenantId: null };
13783
14038
  }
@@ -13797,17 +14052,17 @@ async function browserLogin(apiUrl, opts, t) {
13797
14052
  const isLocal = isLoopbackHost(new URL(apiUrl).hostname);
13798
14053
  console.log();
13799
14054
  console.log(
13800
- chalk8.bold(
13801
- ` Authenticating with ${isLocal ? "local " : ""}Iamu Cloud (${chalk8.cyan(apiUrl)})...`
14055
+ chalk9.bold(
14056
+ ` Authenticating with ${isLocal ? "local " : ""}Iamu Cloud (${chalk9.cyan(apiUrl)})...`
13802
14057
  )
13803
14058
  );
13804
14059
  const started = await startAuthSession(apiUrl, t.requestTimeoutMs);
13805
14060
  if (!started) return null;
13806
14061
  if (opts.browser !== false) {
13807
- console.log(` Opening browser: ${chalk8.cyan(started.loginUrl)}`);
14062
+ console.log(` Opening browser: ${chalk9.cyan(started.loginUrl)}`);
13808
14063
  openBrowser(started.loginUrl);
13809
14064
  } else {
13810
- console.log(` Log in at: ${chalk8.cyan(started.loginUrl)}`);
14065
+ console.log(` Log in at: ${chalk9.cyan(started.loginUrl)}`);
13811
14066
  }
13812
14067
  const s = spinner();
13813
14068
  s.start("Waiting for you to log in in browser...");
@@ -13815,11 +14070,11 @@ async function browserLogin(apiUrl, opts, t) {
13815
14070
  if (result.kind === "expired") {
13816
14071
  s.stop("Auth session expired.");
13817
14072
  console.error(
13818
- chalk8.red(`
14073
+ chalk9.red(`
13819
14074
  Auth session expired or failed (HTTP ${result.status}).`)
13820
14075
  );
13821
14076
  console.error(
13822
- chalk8.dim(" Re-run `iamu auth login` to start a new login session.\n")
14077
+ chalk9.dim(" Re-run `iamu auth login` to start a new login session.\n")
13823
14078
  );
13824
14079
  process.exitCode = 1;
13825
14080
  return null;
@@ -13827,12 +14082,12 @@ async function browserLogin(apiUrl, opts, t) {
13827
14082
  if (result.kind === "timeout") {
13828
14083
  s.stop("Authentication timed out.");
13829
14084
  console.error(
13830
- chalk8.red(
14085
+ chalk9.red(
13831
14086
  "\n Authentication timed out (no approval received within 2 minutes)."
13832
14087
  )
13833
14088
  );
13834
14089
  console.error(
13835
- chalk8.dim(
14090
+ chalk9.dim(
13836
14091
  " \u2022 Complete browser authorization faster, or authenticate non-interactively with --token <key>.\n \u2022 Local setup is unaffected \u2014 re-run `iamu auth login` anytime.\n"
13837
14092
  )
13838
14093
  );
@@ -13860,12 +14115,12 @@ async function startAuthSession(apiUrl, timeoutMs) {
13860
14115
  });
13861
14116
  if (!res.ok) {
13862
14117
  console.error(
13863
- chalk8.red(
14118
+ chalk9.red(
13864
14119
  ` Failed to start auth session at ${apiUrl}: ${res.text || `HTTP ${res.status}`}`
13865
14120
  )
13866
14121
  );
13867
14122
  console.error(
13868
- chalk8.dim(
14123
+ chalk9.dim(
13869
14124
  " \u2022 The cloud service may be experiencing downtime or maintenance.\n \u2022 Local setup is unaffected; continue with local workflows or retry later with `iamu auth login`.\n"
13870
14125
  )
13871
14126
  );
@@ -13880,11 +14135,11 @@ async function startAuthSession(apiUrl, timeoutMs) {
13880
14135
  return { sessionId: data.sessionId, loginUrl: data.loginUrl };
13881
14136
  } catch (err) {
13882
14137
  console.error(
13883
- chalk8.red(` Cannot reach Iamu Cloud (${apiUrl}).`) + chalk8.dim(`
14138
+ chalk9.red(` Cannot reach Iamu Cloud (${apiUrl}).`) + chalk9.dim(`
13884
14139
  Reason: ${errorMessage(err)}`)
13885
14140
  );
13886
14141
  console.error(
13887
- chalk8.dim(
14142
+ chalk9.dim(
13888
14143
  "\n \u2022 Check your internet connection or proxy settings.\n \u2022 If using a custom instance, pass --url <api-url> or set IAMU_API_URL.\n \u2022 Local setup is unaffected; continue with local workflows or retry later with `iamu auth login`.\n"
13889
14144
  )
13890
14145
  );
@@ -13932,22 +14187,22 @@ async function linkCloudProject(args) {
13932
14187
  cloudApiUrl: args.apiUrl,
13933
14188
  apiKey: args.token
13934
14189
  });
13935
- console.log(` ${symbols.success} Linked to ${chalk8.cyan(args.apiUrl)}`);
14190
+ console.log(` ${symbols.success} Linked to ${chalk9.cyan(args.apiUrl)}`);
13936
14191
  if (result.sync?.push?.pushed) {
13937
14192
  console.log(
13938
- ` ${chalk8.dim("Initial sync:")} ${result.sync.push.pushed} pushed`
14193
+ ` ${chalk9.dim("Initial sync:")} ${result.sync.push.pushed} pushed`
13939
14194
  );
13940
14195
  }
13941
14196
  } catch (err) {
13942
14197
  console.error(
13943
- chalk8.red(" Credentials saved, but linking the project failed.") + chalk8.dim(` (${errorMessage(err)})`)
14198
+ chalk9.red(" Credentials saved, but linking the project failed.") + chalk9.dim(` (${errorMessage(err)})`)
13944
14199
  );
13945
14200
  process.exitCode = 1;
13946
14201
  return;
13947
14202
  }
13948
14203
  await registerSyncServer(args.projectRoot);
13949
14204
  console.log(
13950
- ` ${chalk8.dim("Dashboard:")} ${chalk8.underline(getCloudDashboardUrl(args.apiUrl, cloudProjectId))}`
14205
+ ` ${chalk9.dim("Dashboard:")} ${chalk9.underline(getCloudDashboardUrl(args.apiUrl, cloudProjectId))}`
13951
14206
  );
13952
14207
  }
13953
14208
  async function listCloudProjects(args) {
@@ -13963,9 +14218,9 @@ async function listCloudProjects(args) {
13963
14218
  }
13964
14219
  if (!res.ok) {
13965
14220
  console.error(
13966
- chalk8.red(
14221
+ chalk9.red(
13967
14222
  ` Credentials saved, but could not list cloud projects (HTTP ${res.status}).`
13968
- ) + chalk8.dim(" Re-run iamu auth login.")
14223
+ ) + chalk9.dim(" Re-run iamu auth login.")
13969
14224
  );
13970
14225
  process.exitCode = 1;
13971
14226
  return null;
@@ -13975,7 +14230,7 @@ async function listCloudProjects(args) {
13975
14230
  return projects;
13976
14231
  } catch (err) {
13977
14232
  console.error(
13978
- chalk8.yellow(" Credentials saved but could not list projects.") + chalk8.dim(` (${errorMessage(err)})`)
14233
+ chalk9.yellow(" Credentials saved but could not list projects.") + chalk9.dim(` (${errorMessage(err)})`)
13979
14234
  );
13980
14235
  process.exitCode = 1;
13981
14236
  return null;
@@ -13988,7 +14243,7 @@ async function dropRejectedToken(apiUrl) {
13988
14243
  await writeCredentialsStore(store);
13989
14244
  }
13990
14245
  console.error(
13991
- chalk8.red(" Stored credentials were rejected and have been removed.") + chalk8.dim(" Run iamu auth login again to sign in.")
14246
+ chalk9.red(" Stored credentials were rejected and have been removed.") + chalk9.dim(" Run iamu auth login again to sign in.")
13992
14247
  );
13993
14248
  process.exitCode = 1;
13994
14249
  }
@@ -14016,34 +14271,34 @@ async function chooseCloudProject(args, projects) {
14016
14271
  function printProjectRefusal(reason, projects, { config, opts }) {
14017
14272
  if (reason === "unknown_project") {
14018
14273
  console.error(
14019
- chalk8.red(
14274
+ chalk9.red(
14020
14275
  ` Cloud project ${opts.project} is not one this account can see.`
14021
- ) + chalk8.dim(" Pick one of:")
14276
+ ) + chalk9.dim(" Pick one of:")
14022
14277
  );
14023
14278
  } else {
14024
14279
  if (opts.yes) {
14025
14280
  console.error(
14026
- chalk8.yellow(
14281
+ chalk9.yellow(
14027
14282
  ` --yes only links when the account has exactly one cloud project; it has ${projects.length}.`
14028
14283
  )
14029
14284
  );
14030
14285
  }
14031
14286
  console.error(
14032
- chalk8.yellow(
14287
+ chalk9.yellow(
14033
14288
  " Signed in. Choose the cloud project to link \u2014 re-run with --project:"
14034
14289
  )
14035
14290
  );
14036
14291
  }
14037
14292
  for (const p of projects) {
14038
14293
  console.error(
14039
- ` iamu auth login --project ${p.id} ${chalk8.dim(`${p.name} (${p.slug})`)}`
14294
+ ` iamu auth login --project ${p.id} ${chalk9.dim(`${p.name} (${p.slug})`)}`
14040
14295
  );
14041
14296
  }
14042
14297
  console.error(
14043
- ` iamu auth login --project new ${chalk8.dim(`create "${config.project_name}"`)}`
14298
+ ` iamu auth login --project new ${chalk9.dim(`create "${config.project_name}"`)}`
14044
14299
  );
14045
14300
  console.error(
14046
- chalk8.dim(" Credentials are stored; the re-run skips the browser.")
14301
+ chalk9.dim(" Credentials are stored; the re-run skips the browser.")
14047
14302
  );
14048
14303
  process.exitCode = 1;
14049
14304
  }
@@ -14062,7 +14317,7 @@ async function promptForProject(projects, args) {
14062
14317
  });
14063
14318
  if (isCancel(choice)) {
14064
14319
  process.exitCode = 130;
14065
- console.log(chalk8.dim(" Login cancelled."));
14320
+ console.log(chalk9.dim(" Login cancelled."));
14066
14321
  return null;
14067
14322
  }
14068
14323
  return choice === CREATE_NEW ? createCloudProject(args) : String(choice);
@@ -14089,7 +14344,7 @@ async function createCloudProject(args) {
14089
14344
  return id;
14090
14345
  } catch (err) {
14091
14346
  console.error(
14092
- chalk8.red(" Failed to create cloud project.") + chalk8.dim(` (${errorMessage(err)}) Try again with iamu auth login.`)
14347
+ chalk9.red(" Failed to create cloud project.") + chalk9.dim(` (${errorMessage(err)}) Try again with iamu auth login.`)
14093
14348
  );
14094
14349
  process.exitCode = 1;
14095
14350
  return null;
@@ -14104,13 +14359,13 @@ async function registerSyncServer(projectRoot) {
14104
14359
  registered.push(host.name);
14105
14360
  } catch (err) {
14106
14361
  console.error(
14107
- chalk8.yellow(` ${host.name}: iamu-sync MCP not registered`) + chalk8.dim(` (${err.message})`)
14362
+ chalk9.yellow(` ${host.name}: iamu-sync MCP not registered`) + chalk9.dim(` (${err.message})`)
14108
14363
  );
14109
14364
  }
14110
14365
  }
14111
14366
  if (registered.length > 0) {
14112
14367
  console.log(
14113
- ` ${symbols.success} iamu-sync MCP server registered for ${registered.join(", ")} ${chalk8.dim("\u2014 restart your agent session to load the team tools")}`
14368
+ ` ${symbols.success} iamu-sync MCP server registered for ${registered.join(", ")} ${chalk9.dim("\u2014 restart your agent session to load the team tools")}`
14114
14369
  );
14115
14370
  }
14116
14371
  }
@@ -14131,10 +14386,10 @@ async function authDisconnect() {
14131
14386
  }
14132
14387
  console.log();
14133
14388
  console.log(` ${symbols.success} Disconnected from cloud.`);
14134
- console.log(chalk8.dim(" Local entities preserved. Re-link anytime."));
14389
+ console.log(chalk9.dim(" Local entities preserved. Re-link anytime."));
14135
14390
  console.log();
14136
14391
  } catch (err) {
14137
- console.error(chalk8.red(` ${err.message}`));
14392
+ console.error(chalk9.red(` ${err.message}`));
14138
14393
  process.exitCode = 1;
14139
14394
  }
14140
14395
  }
@@ -14166,17 +14421,17 @@ async function authStatus(opts) {
14166
14421
  console.log();
14167
14422
  if (config.cloud_linked) {
14168
14423
  console.log(
14169
- ` ${symbols.success} Cloud-linked: ${chalk8.cyan(config.cloud_api_url)}`
14424
+ ` ${symbols.success} Cloud-linked: ${chalk9.cyan(config.cloud_api_url)}`
14170
14425
  );
14171
- console.log(` ${chalk8.dim("Project:")} ${config.cloud_project_id}`);
14426
+ console.log(` ${chalk9.dim("Project:")} ${config.cloud_project_id}`);
14172
14427
  console.log(
14173
- ` ${chalk8.dim("Token:")} ${token ? "stored" : chalk8.yellow("missing")}`
14428
+ ` ${chalk9.dim("Token:")} ${token ? "stored" : chalk9.yellow("missing")}`
14174
14429
  );
14175
14430
  } else {
14176
- console.log(` ${chalk8.dim("Local-only \u2014 not cloud-linked.")}`);
14431
+ console.log(` ${chalk9.dim("Local-only \u2014 not cloud-linked.")}`);
14177
14432
  if (token) {
14178
14433
  console.log(
14179
- ` ${chalk8.dim("Token stored for")} ${apiUrl} ${chalk8.dim("\u2014 run iamu auth login to link.")}`
14434
+ ` ${chalk9.dim("Token stored for")} ${apiUrl} ${chalk9.dim("\u2014 run iamu auth login to link.")}`
14180
14435
  );
14181
14436
  }
14182
14437
  }
@@ -14212,11 +14467,11 @@ var init_auth = __esm({
14212
14467
  });
14213
14468
 
14214
14469
  // src/ui/journey-diff.ts
14215
- import chalk9 from "chalk";
14470
+ import chalk10 from "chalk";
14216
14471
  function formatJourneyDiffTerminal(diff) {
14217
14472
  const lines = [];
14218
14473
  lines.push(
14219
- chalk9.bold(" Journey diff") + chalk9.dim(` (vs ${diff.baselineRunId.slice(0, 30)}\u2026):`)
14474
+ chalk10.bold(" Journey diff") + chalk10.dim(` (vs ${diff.baselineRunId.slice(0, 30)}\u2026):`)
14220
14475
  );
14221
14476
  for (const step of diff.steps) {
14222
14477
  let sym = " ";
@@ -14224,40 +14479,40 @@ function formatJourneyDiffTerminal(diff) {
14224
14479
  let statusColored = statusLabel;
14225
14480
  switch (step.status) {
14226
14481
  case "resolved":
14227
- sym = chalk9.green("\u2713");
14228
- statusColored = chalk9.green(statusLabel);
14482
+ sym = chalk10.green("\u2713");
14483
+ statusColored = chalk10.green(statusLabel);
14229
14484
  break;
14230
14485
  case "persists":
14231
- sym = chalk9.red("\u2716");
14232
- statusColored = chalk9.red(statusLabel);
14486
+ sym = chalk10.red("\u2716");
14487
+ statusColored = chalk10.red(statusLabel);
14233
14488
  break;
14234
14489
  case "regression":
14235
- sym = chalk9.yellow("!");
14236
- statusColored = chalk9.yellow(statusLabel);
14490
+ sym = chalk10.yellow("!");
14491
+ statusColored = chalk10.yellow(statusLabel);
14237
14492
  break;
14238
14493
  case "stalled":
14239
- sym = chalk9.red("\xD7");
14240
- statusColored = chalk9.red(statusLabel);
14494
+ sym = chalk10.red("\xD7");
14495
+ statusColored = chalk10.red(statusLabel);
14241
14496
  break;
14242
14497
  case "new_path":
14243
- sym = chalk9.cyan("+");
14244
- statusColored = chalk9.cyan(statusLabel);
14498
+ sym = chalk10.cyan("+");
14499
+ statusColored = chalk10.cyan(statusLabel);
14245
14500
  break;
14246
14501
  case "bypassed":
14247
- sym = chalk9.dim("\u25CB");
14248
- statusColored = chalk9.dim(statusLabel);
14502
+ sym = chalk10.dim("\u25CB");
14503
+ statusColored = chalk10.dim(statusLabel);
14249
14504
  break;
14250
14505
  default:
14251
- sym = chalk9.dim("\xB7");
14252
- statusColored = chalk9.dim(statusLabel);
14506
+ sym = chalk10.dim("\xB7");
14507
+ statusColored = chalk10.dim(statusLabel);
14253
14508
  break;
14254
14509
  }
14255
14510
  const route = journeyStepRoute(step);
14256
14511
  const action = step.currentStep?.action || step.baselineStep?.action || "(no action)";
14257
14512
  const stepNum = step.currentStep ? `[${step.currentStep.step_number}]` : step.baselineStep ? `[${step.baselineStep.step_number}b]` : `[${step.index}]`;
14258
- const note = step.status === "same" ? "" : chalk9.dim(` (${step.summary})`);
14513
+ const note = step.status === "same" ? "" : chalk10.dim(` (${step.summary})`);
14259
14514
  lines.push(
14260
- ` ${sym} ${chalk9.dim(stepNum.padEnd(5))} ${chalk9.dim(route.slice(0, 20).padEnd(21))} ${action.slice(0, 35).padEnd(36)} ${statusColored}${note}`
14515
+ ` ${sym} ${chalk10.dim(stepNum.padEnd(5))} ${chalk10.dim(route.slice(0, 20).padEnd(21))} ${action.slice(0, 35).padEnd(36)} ${statusColored}${note}`
14261
14516
  );
14262
14517
  }
14263
14518
  return lines.join("\n");
@@ -14274,7 +14529,7 @@ var init_journey_diff2 = __esm({
14274
14529
  });
14275
14530
 
14276
14531
  // src/ui/table.ts
14277
- import chalk10 from "chalk";
14532
+ import chalk11 from "chalk";
14278
14533
  function stripAnsi(str2) {
14279
14534
  return str2.replace(ANSI_REGEX, "");
14280
14535
  }
@@ -14320,7 +14575,7 @@ function formatTable(items, columns, options) {
14320
14575
  const headerParts = columns.map(
14321
14576
  (col, i) => padRight(col.header, colWidths[i])
14322
14577
  );
14323
- lines.push(` ${chalk10.dim(headerParts.join(" "))}`);
14578
+ lines.push(` ${chalk11.dim(headerParts.join(" "))}`);
14324
14579
  for (const item of items) {
14325
14580
  const rowParts = columns.map((col, i) => {
14326
14581
  let val = col.value(item);
@@ -14353,7 +14608,7 @@ import {
14353
14608
  readlinkSync,
14354
14609
  realpathSync as realpathSync2
14355
14610
  } from "fs";
14356
- import path18 from "path";
14611
+ import path19 from "path";
14357
14612
  function git(args, cwd) {
14358
14613
  return execFileSync("git", args, {
14359
14614
  cwd,
@@ -14364,13 +14619,13 @@ function git(args, cwd) {
14364
14619
  }
14365
14620
  function hashFile(absPath) {
14366
14621
  const hash = createHash4("sha256");
14367
- const stat2 = lstatSync(absPath);
14368
- if (stat2.isSymbolicLink()) {
14622
+ const stat3 = lstatSync(absPath);
14623
+ if (stat3.isSymbolicLink()) {
14369
14624
  hash.update(`symlink:${readlinkSync(absPath)}`);
14370
14625
  return hash.digest("hex");
14371
14626
  }
14372
- if (!stat2.isFile()) {
14373
- hash.update(`${stat2.isDirectory() ? "dir" : "other"}`);
14627
+ if (!stat3.isFile()) {
14628
+ hash.update(`${stat3.isDirectory() ? "dir" : "other"}`);
14374
14629
  return hash.digest("hex");
14375
14630
  }
14376
14631
  const fd = openSync(absPath, "r");
@@ -14406,8 +14661,8 @@ function detectWorktreeState(projectRoot, iamuDirName = IAMU_DIR) {
14406
14661
  const top = git(["rev-parse", "--show-toplevel"], projectRoot).toString("utf8").trim();
14407
14662
  if (!top) return void 0;
14408
14663
  const realTop = realpathSync2(top);
14409
- const realIamu = path18.join(realpathSync2(projectRoot), iamuDirName);
14410
- const iamuRel = path18.relative(realTop, realIamu).split(path18.sep).join("/");
14664
+ const realIamu = path19.join(realpathSync2(projectRoot), iamuDirName);
14665
+ const iamuRel = path19.relative(realTop, realIamu).split(path19.sep).join("/");
14411
14666
  const pathspec = iamuRel.startsWith("..") ? [":(top)"] : [":(top)", `:(top,exclude,literal)${iamuRel}`];
14412
14667
  const status2 = git(
14413
14668
  [
@@ -14437,7 +14692,7 @@ function detectWorktreeState(projectRoot, iamuDirName = IAMU_DIR) {
14437
14692
  );
14438
14693
  for (const file of sorted.slice(0, MAX_UNTRACKED_HASHED)) {
14439
14694
  const rel = file.replace(/\/$/, "");
14440
- hash.update(`${file}\0${hashFile(path18.join(realTop, rel))}
14695
+ hash.update(`${file}\0${hashFile(path19.join(realTop, rel))}
14441
14696
  `);
14442
14697
  }
14443
14698
  if (sorted.length > MAX_UNTRACKED_HASHED) {
@@ -14612,12 +14867,12 @@ __export(start_run_exports, {
14612
14867
  testabilityTarget: () => testabilityTarget
14613
14868
  });
14614
14869
  import fs24 from "fs/promises";
14615
- import path19 from "path";
14616
- import chalk11 from "chalk";
14870
+ import path20 from "path";
14871
+ import chalk12 from "chalk";
14617
14872
  async function testabilityTarget(projectRoot) {
14618
14873
  try {
14619
14874
  const raw = await fs24.readFile(
14620
- path19.join(projectRoot, "iamu", "testability.md"),
14875
+ path20.join(projectRoot, "iamu", "testability.md"),
14621
14876
  "utf8"
14622
14877
  );
14623
14878
  const { frontmatter } = parseFrontmatter(raw);
@@ -14801,19 +15056,28 @@ async function startRun(scenarioSlug, opts) {
14801
15056
  ...viewport ? { viewport } : {}
14802
15057
  };
14803
15058
  await atomicWriteFile(
14804
- path19.join(run.absPath, "walkthrough.json"),
15059
+ path20.join(run.absPath, "walkthrough.json"),
14805
15060
  JSON.stringify(manifest, null, 2) + "\n"
14806
15061
  );
15062
+ const liveRes = await registerLiveRun({
15063
+ projectRoot,
15064
+ runId: run.runId,
15065
+ scenarioSlug,
15066
+ targetUrl: start2.url,
15067
+ startedAt: manifest.created_at,
15068
+ lenses: manifest.lenses
15069
+ });
14807
15070
  if (opts.json) {
14808
15071
  console.log(
14809
15072
  JSON.stringify(
14810
15073
  {
14811
15074
  run_id: run.runId,
14812
- path: path19.relative(projectRoot, run.absPath),
15075
+ path: path20.relative(projectRoot, run.absPath),
14813
15076
  scenario_slug: scenarioSlug,
14814
15077
  target_url: start2.url,
14815
15078
  target_reachable: targetReachable,
14816
15079
  ...targetWarning ? { target_warning: targetWarning } : {},
15080
+ ...liveRes?.viewerUrl ? { live_viewer_url: liveRes.viewerUrl } : {},
14817
15081
  persona_slug: fm.persona,
14818
15082
  outline_slug: fm.outline,
14819
15083
  models,
@@ -14830,55 +15094,60 @@ async function startRun(scenarioSlug, opts) {
14830
15094
  return;
14831
15095
  }
14832
15096
  console.log();
14833
- console.log(` ${symbols.success} Run started: ${chalk11.cyan(run.runId)}`);
14834
- console.log(` ${chalk11.dim("scenario:")} ${scenarioSlug}`);
14835
- console.log(` ${chalk11.dim("persona:")} ${fm.persona}`);
14836
- console.log(` ${chalk11.dim("outline:")} ${fm.outline}`);
14837
- console.log(` ${chalk11.dim("target:")} ${start2.url}`);
15097
+ console.log(` ${symbols.success} Run started: ${chalk12.cyan(run.runId)}`);
15098
+ if (liveRes?.viewerUrl) {
15099
+ console.log(
15100
+ ` Follow this run live (beta): ${chalk12.cyan(liveRes.viewerUrl)}`
15101
+ );
15102
+ }
15103
+ console.log(` ${chalk12.dim("scenario:")} ${scenarioSlug}`);
15104
+ console.log(` ${chalk12.dim("persona:")} ${fm.persona}`);
15105
+ console.log(` ${chalk12.dim("outline:")} ${fm.outline}`);
15106
+ console.log(` ${chalk12.dim("target:")} ${start2.url}`);
14838
15107
  console.log(
14839
- ` ${chalk11.dim("models:")} walker: ${chalk11.cyan(walker)} \xB7 judge: ${chalk11.cyan(judge)} \xB7 matcher: ${chalk11.cyan(matcher)}`
15108
+ ` ${chalk12.dim("models:")} walker: ${chalk12.cyan(walker)} \xB7 judge: ${chalk12.cyan(judge)} \xB7 matcher: ${chalk12.cyan(matcher)}`
14840
15109
  );
14841
15110
  if (targetWarning) {
14842
- console.log(` ${symbols.warning} ${chalk11.yellow(targetWarning)}`);
15111
+ console.log(` ${symbols.warning} ${chalk12.yellow(targetWarning)}`);
14843
15112
  }
14844
- if (environment) console.log(` ${chalk11.dim("env:")} ${environment}`);
15113
+ if (environment) console.log(` ${chalk12.dim("env:")} ${environment}`);
14845
15114
  if (build) {
14846
- console.log(` ${chalk11.dim("build:")} ${formatBuild(build)}`);
15115
+ console.log(` ${chalk12.dim("build:")} ${formatBuild(build)}`);
14847
15116
  }
14848
15117
  if (viewport) {
14849
- console.log(` ${chalk11.dim("device:")} ${formatViewport(viewport)}`);
15118
+ console.log(` ${chalk12.dim("device:")} ${formatViewport(viewport)}`);
14850
15119
  }
14851
15120
  if (device?.warning) {
14852
- console.log(` ${chalk11.yellow("!")} ${device.warning}`);
15121
+ console.log(` ${chalk12.yellow("!")} ${device.warning}`);
14853
15122
  }
14854
15123
  if (revisit.length > 0) {
14855
15124
  console.log(
14856
- ` ${chalk11.dim("re-check:")} ${revisit.length} place${revisit.length === 1 ? "" : "s"} where fixes await a re-run`
15125
+ ` ${chalk12.dim("re-check:")} ${revisit.length} place${revisit.length === 1 ? "" : "s"} where fixes await a re-run`
14857
15126
  );
14858
15127
  }
14859
15128
  console.log(
14860
- ` ${chalk11.dim("path:")} ${path19.relative(projectRoot, run.absPath)}`
15129
+ ` ${chalk12.dim("path:")} ${path20.relative(projectRoot, run.absPath)}`
14861
15130
  );
14862
15131
  console.log();
14863
- console.log(` ${chalk11.bold("Next steps for blind execution:")}`);
15132
+ console.log(` ${chalk12.bold("Next steps for blind execution:")}`);
14864
15133
  console.log(
14865
- ` 1. Size browser: ${chalk11.cyan(`iamu browse start --run ${run.runId}`)}`
15134
+ ` 1. Size browser: ${chalk12.cyan(`iamu browse start --run ${run.runId}`)}`
14866
15135
  );
14867
15136
  console.log(
14868
- ` 2. Get walk prompt: ${chalk11.cyan(`iamu instructions walk --scenario ${scenarioSlug} --run ${run.runId}`)}`
15137
+ ` 2. Get walk prompt: ${chalk12.cyan(`iamu instructions walk --scenario ${scenarioSlug} --run ${run.runId}`)}`
14869
15138
  );
14870
15139
  console.log(
14871
- ` 3. Dispatch walker: Spawn a ${chalk11.yellow("fresh blind subagent")} with that prompt (do NOT script steps locally)`
15140
+ ` 3. Dispatch walker: Spawn a ${chalk12.yellow("fresh blind subagent")} with that prompt (do NOT script steps locally)`
14872
15141
  );
14873
15142
  console.log(
14874
- ` 4. Drive product: Walker records via ${chalk11.cyan(`iamu browse step --run ${run.runId} ...`)}`
15143
+ ` 4. Drive product: Walker records via ${chalk12.cyan(`iamu browse step --run ${run.runId} ...`)}`
14875
15144
  );
14876
15145
  console.log(
14877
- ` 5. Complete run: ${chalk11.cyan(`iamu complete ${run.runId}`)}`
15146
+ ` 5. Complete run: ${chalk12.cyan(`iamu complete ${run.runId}`)}`
14878
15147
  );
14879
15148
  console.log();
14880
15149
  console.log(
14881
- ` ${chalk11.dim("Tip: Ensure your agent session has terminal auto-approval enabled so walkthrough steps run unattended.")}`
15150
+ ` ${chalk12.dim("Tip: Ensure your agent session has terminal auto-approval enabled so walkthrough steps run unattended.")}`
14882
15151
  );
14883
15152
  console.log();
14884
15153
  }
@@ -14890,6 +15159,7 @@ var init_start_run = __esm({
14890
15159
  init_build_info();
14891
15160
  init_symbols();
14892
15161
  init_context4();
15162
+ init_live_run_client();
14893
15163
  }
14894
15164
  });
14895
15165
 
@@ -14899,8 +15169,8 @@ __export(report_exports, {
14899
15169
  report: () => report
14900
15170
  });
14901
15171
  import { promises as fs25 } from "fs";
14902
- import path20 from "path";
14903
- import chalk12 from "chalk";
15172
+ import path21 from "path";
15173
+ import chalk13 from "chalk";
14904
15174
  async function report(scenario, opts) {
14905
15175
  const ctx = await resolveProject(opts);
14906
15176
  if (!ctx) return;
@@ -14910,7 +15180,7 @@ async function report(scenario, opts) {
14910
15180
  if (opts?.json) {
14911
15181
  console.log("[]");
14912
15182
  } else {
14913
- console.log(chalk12.dim(" No runs yet. Run a walkthrough first."));
15183
+ console.log(chalk13.dim(" No runs yet. Run a walkthrough first."));
14914
15184
  }
14915
15185
  return;
14916
15186
  }
@@ -14919,7 +15189,7 @@ async function report(scenario, opts) {
14919
15189
  try {
14920
15190
  const dir = runDir(projectRoot, rid);
14921
15191
  const mRaw = await fs25.readFile(
14922
- path20.join(dir, "walkthrough.json"),
15192
+ path21.join(dir, "walkthrough.json"),
14923
15193
  "utf8"
14924
15194
  );
14925
15195
  const manifest = JSON.parse(mRaw);
@@ -14928,7 +15198,7 @@ async function report(scenario, opts) {
14928
15198
  let canonical = null;
14929
15199
  try {
14930
15200
  const cRaw = await fs25.readFile(
14931
- path20.join(dir, "canonical.json"),
15201
+ path21.join(dir, "canonical.json"),
14932
15202
  "utf8"
14933
15203
  );
14934
15204
  canonical = JSON.parse(cRaw);
@@ -14943,7 +15213,7 @@ async function report(scenario, opts) {
14943
15213
  console.log("[]");
14944
15214
  } else {
14945
15215
  const msg = scenario ? `No completed runs for scenario: ${scenario}` : "No completed runs yet.";
14946
- console.log(chalk12.dim(` ${msg}`));
15216
+ console.log(chalk13.dim(` ${msg}`));
14947
15217
  }
14948
15218
  return;
14949
15219
  }
@@ -14975,37 +15245,37 @@ async function report(scenario, opts) {
14975
15245
  const c = run.canonical;
14976
15246
  console.log();
14977
15247
  console.log(
14978
- chalk12.bold(` ${run.manifest.scenario_slug}`) + chalk12.dim(` \u2014 ${run.runId.slice(0, 30)}\u2026`)
15248
+ chalk13.bold(` ${run.manifest.scenario_slug}`) + chalk13.dim(` \u2014 ${run.runId.slice(0, 30)}\u2026`)
14979
15249
  );
14980
15250
  console.log(
14981
- ` ${chalk12.dim("url:")} ${run.manifest.target_url} ${chalk12.dim("completed:")} ${run.manifest.completed_at}`
15251
+ ` ${chalk13.dim("url:")} ${run.manifest.target_url} ${chalk13.dim("completed:")} ${run.manifest.completed_at}`
14982
15252
  );
14983
15253
  const env = run.manifest.environment ?? c?.environment;
14984
15254
  if (env) {
14985
- console.log(` ${chalk12.dim("env:")} ${env}`);
15255
+ console.log(` ${chalk13.dim("env:")} ${env}`);
14986
15256
  }
14987
15257
  const build = run.manifest.build ?? c?.build;
14988
15258
  if (build) {
14989
- console.log(` ${chalk12.dim("build:")} ${formatBuild(build)}`);
15259
+ console.log(` ${chalk13.dim("build:")} ${formatBuild(build)}`);
14990
15260
  }
14991
15261
  const viewport = run.manifest.viewport ?? c?.viewport;
14992
15262
  if (viewport) {
14993
- console.log(` ${chalk12.dim("device:")} ${formatViewport(viewport)}`);
15263
+ console.log(` ${chalk13.dim("device:")} ${formatViewport(viewport)}`);
14994
15264
  }
14995
15265
  const viewUrl = await pushedRunUrl(projectRoot, run.runId);
14996
15266
  if (viewUrl) {
14997
- console.log(` ${chalk12.dim("view:")} ${chalk12.underline(viewUrl)}`);
15267
+ console.log(` ${chalk13.dim("view:")} ${chalk13.underline(viewUrl)}`);
14998
15268
  }
14999
15269
  if (c) {
15000
15270
  const v = c.verification;
15001
15271
  if (v) {
15002
15272
  console.log();
15003
- console.log(chalk12.bold(" Since this scenario's last run:"));
15273
+ console.log(chalk13.bold(" Since this scenario's last run:"));
15004
15274
  if (v.resolved.length > 0)
15005
15275
  console.log(` ${symbols.success} ${v.resolved.length} resolved`);
15006
15276
  if (v.not_observed && v.not_observed.length > 0)
15007
15277
  console.log(
15008
- ` ${symbols.pending} ${v.not_observed.length} not seen this run ${chalk12.dim("(not evidence of a fix)")}`
15278
+ ` ${symbols.pending} ${v.not_observed.length} not seen this run ${chalk13.dim("(not evidence of a fix)")}`
15009
15279
  );
15010
15280
  if (v.persists.length > 0)
15011
15281
  console.log(` ${symbols.error} ${v.persists.length} persists`);
@@ -15031,20 +15301,20 @@ async function report(scenario, opts) {
15031
15301
  }
15032
15302
  console.log();
15033
15303
  if (c.findings.length === 0) {
15034
- console.log(chalk12.dim(" No findings."));
15304
+ console.log(chalk13.dim(" No findings."));
15035
15305
  } else {
15036
15306
  const hinders = c.findings.filter(
15037
15307
  (f) => f.type === "hinders" || f.type === "missing" || f.type === "incorrect"
15038
15308
  );
15039
15309
  const helps = c.findings.filter((f) => f.type === "helps");
15040
15310
  if (hinders.length > 0) {
15041
- console.log(chalk12.bold(" Issues:"));
15311
+ console.log(chalk13.bold(" Issues:"));
15042
15312
  const rows = formatTable(hinders, [
15043
15313
  {
15044
15314
  header: "severity",
15045
15315
  value: (f) => {
15046
15316
  const sev = f.severity ?? "\u2014";
15047
- return sev === "critical" ? chalk12.red(sev) : sev === "major" ? chalk12.yellow(sev) : chalk12.dim(sev);
15317
+ return sev === "critical" ? chalk13.red(sev) : sev === "major" ? chalk13.yellow(sev) : chalk13.dim(sev);
15048
15318
  }
15049
15319
  },
15050
15320
  { header: "type", value: (f) => f.type },
@@ -15054,24 +15324,24 @@ async function report(scenario, opts) {
15054
15324
  }
15055
15325
  if (helps.length > 0) {
15056
15326
  console.log();
15057
- console.log(chalk12.bold(" Strengths:"));
15327
+ console.log(chalk13.bold(" Strengths:"));
15058
15328
  for (const f of helps) {
15059
15329
  console.log(
15060
- ` ${chalk12.green("helps")} ${f.ui_fact ?? f.id}`
15330
+ ` ${chalk13.green("helps")} ${f.ui_fact ?? f.id}`
15061
15331
  );
15062
15332
  }
15063
15333
  }
15064
15334
  }
15065
15335
  if (c.human_test_overall?.answer) {
15066
15336
  console.log();
15067
- console.log(chalk12.bold(" Verdict: ") + c.human_test_overall.answer);
15337
+ console.log(chalk13.bold(" Verdict: ") + c.human_test_overall.answer);
15068
15338
  }
15069
15339
  }
15070
15340
  console.log();
15071
15341
  return;
15072
15342
  }
15073
15343
  console.log();
15074
- console.log(chalk12.bold(" Recent runs:"));
15344
+ console.log(chalk13.bold(" Recent runs:"));
15075
15345
  console.log();
15076
15346
  for (const run of completedRuns.slice(0, 10)) {
15077
15347
  const c = run.canonical;
@@ -15081,13 +15351,13 @@ async function report(scenario, opts) {
15081
15351
  ).length ?? 0;
15082
15352
  const verdict = c?.human_test_overall?.answer?.slice(0, 40) ?? "\u2014";
15083
15353
  console.log(
15084
- ` ${chalk12.cyan(String(run.manifest.scenario_slug).padEnd(35))} ${chalk12.dim("findings:")} ${hinders > 0 ? chalk12.yellow(String(hinders)) : chalk12.dim("0")}/${findings2} ${chalk12.dim(verdict)}`
15354
+ ` ${chalk13.cyan(String(run.manifest.scenario_slug).padEnd(35))} ${chalk13.dim("findings:")} ${hinders > 0 ? chalk13.yellow(String(hinders)) : chalk13.dim("0")}/${findings2} ${chalk13.dim(verdict)}`
15085
15355
  );
15086
15356
  }
15087
15357
  const dashboard = await projectDashboardUrl(projectRoot);
15088
15358
  if (dashboard) {
15089
15359
  console.log();
15090
- console.log(` ${chalk12.dim("cloud:")} ${chalk12.underline(dashboard)}`);
15360
+ console.log(` ${chalk13.dim("cloud:")} ${chalk13.underline(dashboard)}`);
15091
15361
  }
15092
15362
  console.log();
15093
15363
  }
@@ -15111,7 +15381,7 @@ __export(open_exports, {
15111
15381
  });
15112
15382
  import { existsSync as existsSync6 } from "fs";
15113
15383
  import { isCancel as isCancel2, select as select2 } from "@clack/prompts";
15114
- import chalk13 from "chalk";
15384
+ import chalk14 from "chalk";
15115
15385
  async function openDashboard(runId, opts) {
15116
15386
  const ctx = await resolveProject();
15117
15387
  if (!ctx) return;
@@ -15122,7 +15392,7 @@ async function openDashboard(runId, opts) {
15122
15392
  const pushed = await pushedRunUrl(projectRoot, runId);
15123
15393
  if (!pushed) {
15124
15394
  console.error(
15125
- ` ${chalk13.yellow(symbols.info)} Run ${runId} is not on Iamu Cloud yet. Run ${chalk13.cyan("iamu sync")} to push it.`
15395
+ ` ${chalk14.yellow(symbols.info)} Run ${runId} is not on Iamu Cloud yet. Run ${chalk14.cyan("iamu sync")} to push it.`
15126
15396
  );
15127
15397
  process.exitCode = 1;
15128
15398
  return;
@@ -15142,19 +15412,19 @@ async function openDashboard(runId, opts) {
15142
15412
  console.log(
15143
15413
  ` ${symbols.success} Opening Iamu Cloud ${runId ? "walkthrough" : "dashboard"}:`
15144
15414
  );
15145
- console.log(` ${chalk13.cyan(url)}`);
15415
+ console.log(` ${chalk14.cyan(url)}`);
15146
15416
  console.log();
15147
15417
  openBrowser(url);
15148
15418
  return;
15149
15419
  }
15150
15420
  const say = opts?.printOnly ? console.error : console.log;
15151
15421
  say();
15152
- say(` ${chalk13.yellow(symbols.info)} Project is not linked to Iamu Cloud.`);
15422
+ say(` ${chalk14.yellow(symbols.info)} Project is not linked to Iamu Cloud.`);
15153
15423
  say(
15154
- ` Run ${chalk13.cyan("iamu auth login")} to link and view live collaborative reports.`
15424
+ ` Run ${chalk14.cyan("iamu auth login")} to link and view live collaborative reports.`
15155
15425
  );
15156
15426
  say(
15157
- ` Or run ${chalk13.cyan("iamu report")} to inspect results in your terminal.
15427
+ ` Or run ${chalk14.cyan("iamu report")} to inspect results in your terminal.
15158
15428
  `
15159
15429
  );
15160
15430
  if (opts?.printOnly) {
@@ -15779,7 +16049,7 @@ var findings_exports = {};
15779
16049
  __export(findings_exports, {
15780
16050
  findings: () => findings
15781
16051
  });
15782
- import chalk14 from "chalk";
16052
+ import chalk15 from "chalk";
15783
16053
  async function findings(opts) {
15784
16054
  const ctx = await resolveProject(opts);
15785
16055
  if (!ctx) return;
@@ -15831,7 +16101,7 @@ async function findings(opts) {
15831
16101
  }
15832
16102
  if (filtered.length === 0) {
15833
16103
  const qualifier = opts?.open ? "open " : opts?.resolved ? "resolved " : opts?.dismissed ? "dismissed " : "";
15834
- console.log(chalk14.dim(` No ${qualifier}findings.`));
16104
+ console.log(chalk15.dim(` No ${qualifier}findings.`));
15835
16105
  return;
15836
16106
  }
15837
16107
  const groups = /* @__PURE__ */ new Map();
@@ -15863,13 +16133,13 @@ async function findings(opts) {
15863
16133
  const tb = typeOrder[b.frontmatter.type] ?? 9;
15864
16134
  return ta - tb;
15865
16135
  });
15866
- console.log(chalk14.bold(` ${scenario}`) + chalk14.dim(` (${items.length})`));
16136
+ console.log(chalk15.bold(` ${scenario}`) + chalk15.dim(` (${items.length})`));
15867
16137
  for (const e of items) {
15868
16138
  const sev = (e.frontmatter.severity ?? "\u2014").padEnd(11);
15869
- const sevColor = e.frontmatter.severity === "critical" ? chalk14.red : e.frontmatter.severity === "major" ? chalk14.yellow : chalk14.dim;
16139
+ const sevColor = e.frontmatter.severity === "critical" ? chalk15.red : e.frontmatter.severity === "major" ? chalk15.yellow : chalk15.dim;
15870
16140
  const fixState = fixStateOf(e.frontmatter.slug);
15871
16141
  const status2 = fixState ? FIX_STATE_LABEL[fixState] : e.frontmatter.triage_status ?? "open";
15872
- const statusColor = fixState === "verified" ? chalk14.green : fixState === "recurred" ? chalk14.red : fixState === "awaiting_rerun" ? chalk14.yellow : status2 === "dismissed" ? chalk14.dim : chalk14.white;
16142
+ const statusColor = fixState === "verified" ? chalk15.green : fixState === "recurred" ? chalk15.red : fixState === "awaiting_rerun" ? chalk15.yellow : status2 === "dismissed" ? chalk15.dim : chalk15.white;
15873
16143
  const title = e.frontmatter.title ?? e.frontmatter.ui_fact ?? e.frontmatter.slug;
15874
16144
  console.log(
15875
16145
  ` ${sevColor(sev)} ${e.frontmatter.type.padEnd(10)} ${statusColor(status2.padEnd(15))} ${title}`
@@ -15889,13 +16159,13 @@ async function findings(opts) {
15889
16159
  (e) => e.frontmatter.triage_status === "dismissed" || e.frontmatter.triage_status === "wont_fix"
15890
16160
  ).length;
15891
16161
  console.log(
15892
- chalk14.dim(
16162
+ chalk15.dim(
15893
16163
  ` ${total} total: ${open2} open, ${awaiting} awaiting re-run, ${verified} verified${recurred > 0 ? `, ${recurred} recurred` : ""}, ${dismissed} dismissed`
15894
16164
  )
15895
16165
  );
15896
16166
  if (awaiting > 0) {
15897
16167
  console.log(
15898
- chalk14.dim(
16168
+ chalk15.dim(
15899
16169
  " awaiting re-run = fix applied, no later run has shown it working yet \u2014 `iamu status` lists the scenarios to re-run"
15900
16170
  )
15901
16171
  );
@@ -15922,7 +16192,7 @@ var triage_exports = {};
15922
16192
  __export(triage_exports, {
15923
16193
  triage: () => triage
15924
16194
  });
15925
- import chalk15 from "chalk";
16195
+ import chalk16 from "chalk";
15926
16196
  function defaultRule(kind, findings2) {
15927
16197
  const titles = findings2.map((f) => f.frontmatter.title ?? f.frontmatter.ui_fact ?? f.slug).join("; ");
15928
16198
  return kind === "walker_error" ? `Earlier walkers got this wrong: ${titles}` : `Don't report: ${titles}`;
@@ -16084,13 +16354,13 @@ async function triage(refs, opts) {
16084
16354
  console.log();
16085
16355
  for (const f of loaded) {
16086
16356
  console.log(
16087
- ` ${chalk15.green("\u2713")} ${status2.data}${reason ? ` (${reason})` : ""}: ${chalk15.cyan(f.slug)}`
16357
+ ` ${chalk16.green("\u2713")} ${status2.data}${reason ? ` (${reason})` : ""}: ${chalk16.cyan(f.slug)}`
16088
16358
  );
16089
16359
  }
16090
16360
  if (guidance) {
16091
16361
  const where = scope.outline ? `outline ${scope.outline}` : scope.capability ? `capability ${scope.capability}` : "the whole project";
16092
16362
  console.log(
16093
- ` ${chalk15.green("\u2713")} Tester guidance: iamu/guidance/${guidance.slug}.md (${where}) \u2014 the next walk will not report this`
16363
+ ` ${chalk16.green("\u2713")} Tester guidance: iamu/guidance/${guidance.slug}.md (${where}) \u2014 the next walk will not report this`
16094
16364
  );
16095
16365
  }
16096
16366
  console.log();
@@ -16112,14 +16382,14 @@ var serve_exports = {};
16112
16382
  __export(serve_exports, {
16113
16383
  serve: () => serve
16114
16384
  });
16115
- import chalk16 from "chalk";
16385
+ import chalk17 from "chalk";
16116
16386
  async function serve(opts) {
16117
16387
  const printOnly = opts?.open === false;
16118
16388
  const say = printOnly ? console.error : console.log;
16119
16389
  say();
16120
- say(` ${chalk16.yellow(symbols.info)} The local web UI has been retired.`);
16390
+ say(` ${chalk17.yellow(symbols.info)} The local web UI has been retired.`);
16121
16391
  say(
16122
- ` ${printOnly ? "Printing the Iamu Cloud dashboard URL instead" : "Opening Iamu Cloud dashboard instead"}... (use ${chalk16.cyan("iamu open")} or ${chalk16.cyan("iamu report")})`
16392
+ ` ${printOnly ? "Printing the Iamu Cloud dashboard URL instead" : "Opening Iamu Cloud dashboard instead"}... (use ${chalk17.cyan("iamu open")} or ${chalk17.cyan("iamu report")})`
16123
16393
  );
16124
16394
  say();
16125
16395
  await openDashboard(void 0, { printOnly });
@@ -16142,7 +16412,7 @@ import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
16142
16412
  import { mkdir as mkdir4, writeFile as writeFile3 } from "fs/promises";
16143
16413
  import { basename as basename2, join as join5 } from "path";
16144
16414
  import { isCancel as isCancel3, multiselect, select as select3 } from "@clack/prompts";
16145
- import chalk17 from "chalk";
16415
+ import chalk18 from "chalk";
16146
16416
  function loadPromptTemplates() {
16147
16417
  const templates = /* @__PURE__ */ new Map();
16148
16418
  const templateDir = getTemplateDir("prompts");
@@ -16175,9 +16445,9 @@ async function init(opts) {
16175
16445
  const version = getVersion();
16176
16446
  if (!options.json) {
16177
16447
  console.log();
16178
- console.log(chalk17.bold(" Welcome to iamu"));
16448
+ console.log(chalk18.bold(" Welcome to iamu"));
16179
16449
  console.log(
16180
- chalk17.dim(
16450
+ chalk18.dim(
16181
16451
  " Scenario-driven development \u2014 test your product as realistic personas"
16182
16452
  )
16183
16453
  );
@@ -16188,7 +16458,7 @@ async function init(opts) {
16188
16458
  const config2 = await readConfig(projectRoot);
16189
16459
  if (!options.json) {
16190
16460
  console.log(
16191
- chalk17.yellow(" iamu/ already exists") + chalk17.dim(` (${config2?.project_name ?? "unknown"})`)
16461
+ chalk18.yellow(" iamu/ already exists") + chalk18.dim(` (${config2?.project_name ?? "unknown"})`)
16192
16462
  );
16193
16463
  }
16194
16464
  } else {
@@ -16244,7 +16514,7 @@ Audited and populated during /iamu:init.
16244
16514
  const detected = detectHosts(projectRoot);
16245
16515
  if (!options.json && detected.length > 0) {
16246
16516
  console.log(
16247
- chalk17.dim(" Detected: ") + detected.map((h) => h.name).join(", ") + chalk17.dim(" (pre-selected)")
16517
+ chalk18.dim(" Detected: ") + detected.map((h) => h.name).join(", ") + chalk18.dim(" (pre-selected)")
16248
16518
  );
16249
16519
  console.log();
16250
16520
  }
@@ -16265,7 +16535,7 @@ Audited and populated during /iamu:init.
16265
16535
  if (isCancel3(selected)) {
16266
16536
  process.exitCode = 130;
16267
16537
  if (!options.json) {
16268
- console.log(chalk17.dim(" Operation cancelled."));
16538
+ console.log(chalk18.dim(" Operation cancelled."));
16269
16539
  }
16270
16540
  return;
16271
16541
  }
@@ -16277,10 +16547,10 @@ Audited and populated during /iamu:init.
16277
16547
  }
16278
16548
  if (!options.json && selectedHosts.length === 0 && detected.length === 0) {
16279
16549
  console.log(
16280
- chalk17.dim(" No supported tools detected. Skills not installed.")
16550
+ chalk18.dim(" No supported tools detected. Skills not installed.")
16281
16551
  );
16282
16552
  console.log(
16283
- chalk17.dim(" Re-run `iamu init` after setting up your editor.")
16553
+ chalk18.dim(" Re-run `iamu init` after setting up your editor.")
16284
16554
  );
16285
16555
  }
16286
16556
  if (!options.json) console.log();
@@ -16325,7 +16595,7 @@ Audited and populated during /iamu:init.
16325
16595
  process.exitCode = prevExitCode;
16326
16596
  if (!options.json) {
16327
16597
  console.log(
16328
- chalk17.dim(
16598
+ chalk18.dim(
16329
16599
  " Cloud linking skipped. Your local setup is complete and fully functional."
16330
16600
  )
16331
16601
  );
@@ -16366,15 +16636,15 @@ Audited and populated during /iamu:init.
16366
16636
  if (!options.json) {
16367
16637
  console.log();
16368
16638
  console.log(
16369
- chalk17.bold(
16370
- ` ${symbols.success} Project configured: ${chalk17.cyan(projectName)}`
16639
+ chalk18.bold(
16640
+ ` ${symbols.success} Project configured: ${chalk18.cyan(projectName)}`
16371
16641
  )
16372
16642
  );
16373
16643
  console.log();
16374
16644
  if (selectedHosts.length > 0) {
16375
16645
  const toolNames = selectedHosts.map((h) => h.name).join(", ");
16376
16646
  console.log(
16377
- ` ${chalk17.dim("Tools:")} ${toolNames} ${chalk17.dim(`(${totalSkills} skills + ${totalCommands} commands installed)`)}`
16647
+ ` ${chalk18.dim("Tools:")} ${toolNames} ${chalk18.dim(`(${totalSkills} skills + ${totalCommands} commands installed)`)}`
16378
16648
  );
16379
16649
  }
16380
16650
  if (config.cloud_linked && config.cloud_project_id) {
@@ -16383,65 +16653,65 @@ Audited and populated during /iamu:init.
16383
16653
  config.cloud_project_id
16384
16654
  );
16385
16655
  console.log(
16386
- ` ${chalk17.dim("Cloud:")} ${chalk17.green("Linked")} \xB7 ${chalk17.cyan(dashboardUrl)}`
16656
+ ` ${chalk18.dim("Cloud:")} ${chalk18.green("Linked")} \xB7 ${chalk18.cyan(dashboardUrl)}`
16387
16657
  );
16388
16658
  } else {
16389
16659
  console.log(
16390
- ` ${chalk17.dim("Cloud:")} Local-only ${chalk17.dim("(link anytime with `iamu auth login`)")}`
16660
+ ` ${chalk18.dim("Cloud:")} Local-only ${chalk18.dim("(link anytime with `iamu auth login`)")}`
16391
16661
  );
16392
16662
  }
16393
16663
  console.log();
16394
16664
  if (freshInit) {
16395
- console.log(chalk17.bold(" Next steps:"));
16665
+ console.log(chalk18.bold(" Next steps:"));
16396
16666
  console.log();
16397
16667
  console.log(
16398
- ` ${chalk17.bold("1.")} Start your application's dev server:`
16668
+ ` ${chalk18.bold("1.")} Start your application's dev server:`
16399
16669
  );
16400
16670
  console.log(
16401
- ` ${chalk17.cyan("$ pnpm dev")} ${chalk17.dim("(or npm run dev)")}`
16671
+ ` ${chalk18.cyan("$ pnpm dev")} ${chalk18.dim("(or npm run dev)")}`
16402
16672
  );
16403
16673
  console.log();
16404
- console.log(` ${chalk17.bold("2.")} In your AI agent chat, run:`);
16674
+ console.log(` ${chalk18.bold("2.")} In your AI agent chat, run:`);
16405
16675
  console.log(
16406
- ` ${chalk17.cyan(setupCommand(projectRoot, selectedHosts))}`
16676
+ ` ${chalk18.cyan(setupCommand(projectRoot, selectedHosts))}`
16407
16677
  );
16408
16678
  console.log();
16409
16679
  console.log(
16410
- chalk17.dim(
16680
+ chalk18.dim(
16411
16681
  " Your agent will analyze your codebase, map user roles, and generate your first walkthrough scenario."
16412
16682
  )
16413
16683
  );
16414
16684
  console.log();
16415
- console.log(chalk17.bold(" Core workflow:"));
16685
+ console.log(chalk18.bold(" Core workflow:"));
16416
16686
  console.log(
16417
- chalk17.dim(" \u2022 ") + chalk17.cyan("/iamu:init") + chalk17.dim(" Map domain & scaffold inaugural scenario")
16687
+ chalk18.dim(" \u2022 ") + chalk18.cyan("/iamu:init") + chalk18.dim(" Map domain & scaffold inaugural scenario")
16418
16688
  );
16419
16689
  console.log(
16420
- chalk17.dim(" \u2022 ") + chalk17.cyan("iamu-run <slug>") + chalk17.dim(" Walk scenario in browser & record findings")
16690
+ chalk18.dim(" \u2022 ") + chalk18.cyan("iamu-run <slug>") + chalk18.dim(" Walk scenario in browser & record findings")
16421
16691
  );
16422
16692
  console.log(
16423
- chalk17.dim(" \u2022 ") + chalk17.cyan("iamu-findings") + chalk17.dim(" Triage persona feedback & apply code fixes")
16693
+ chalk18.dim(" \u2022 ") + chalk18.cyan("iamu-findings") + chalk18.dim(" Triage persona feedback & apply code fixes")
16424
16694
  );
16425
16695
  console.log(
16426
- chalk17.dim(" \u2022 ") + chalk17.cyan("iamu-propose") + chalk17.dim(" Brainstorm high-risk workflows & new personas")
16696
+ chalk18.dim(" \u2022 ") + chalk18.cyan("iamu-propose") + chalk18.dim(" Brainstorm high-risk workflows & new personas")
16427
16697
  );
16428
16698
  } else {
16429
- console.log(chalk17.bold(" Updated:"));
16699
+ console.log(chalk18.bold(" Updated:"));
16430
16700
  console.log();
16431
16701
  console.log(
16432
- chalk17.dim(" Skills and commands regenerated to latest version.")
16702
+ chalk18.dim(" Skills and commands regenerated to latest version.")
16433
16703
  );
16434
16704
  }
16435
16705
  console.log();
16436
16706
  console.log(
16437
- ` ${chalk17.dim("Docs:")} ${chalk17.underline("https://iamu.dev/docs")}`
16707
+ ` ${chalk18.dim("Docs:")} ${chalk18.underline("https://iamu.dev/docs")}`
16438
16708
  );
16439
16709
  console.log(
16440
- ` ${chalk17.dim("Quickstart:")} ${chalk17.underline("https://iamu.dev/quickstart")}`
16710
+ ` ${chalk18.dim("Quickstart:")} ${chalk18.underline("https://iamu.dev/quickstart")}`
16441
16711
  );
16442
16712
  if (config.cloud_linked && config.cloud_project_id) {
16443
16713
  console.log(
16444
- ` ${chalk17.dim("Dashboard:")} ${chalk17.underline(getCloudDashboardUrl(void 0, config.cloud_project_id))}`
16714
+ ` ${chalk18.dim("Dashboard:")} ${chalk18.underline(getCloudDashboardUrl(void 0, config.cloud_project_id))}`
16445
16715
  );
16446
16716
  }
16447
16717
  console.log();
@@ -16469,7 +16739,7 @@ __export(status_exports, {
16469
16739
  });
16470
16740
  import { existsSync as existsSync8 } from "fs";
16471
16741
  import { join as join6 } from "path";
16472
- import chalk18 from "chalk";
16742
+ import chalk19 from "chalk";
16473
16743
  function rerunCommand(projectRoot, scenario) {
16474
16744
  const claude = join6(projectRoot, ".claude");
16475
16745
  const skillOnly = existsSync8(join6(claude, "skills", "iamu-run")) && !existsSync8(join6(claude, "commands", "iamu", "run.md"));
@@ -16479,19 +16749,19 @@ function printRerun(projectRoot, rerun) {
16479
16749
  if (rerun.length === 0) return;
16480
16750
  const total = rerun.reduce((n, r) => n + r.awaiting, 0);
16481
16751
  console.log(
16482
- chalk18.bold(" Needs a re-run") + chalk18.dim(
16752
+ chalk19.bold(" Needs a re-run") + chalk19.dim(
16483
16753
  ` ${total} fix${total === 1 ? "" : "es"} awaiting proof from a later run`
16484
16754
  )
16485
16755
  );
16486
16756
  const width = Math.max(...rerun.map((r) => r.scenario.length));
16487
16757
  for (const r of rerun) {
16488
16758
  console.log(
16489
- ` ${chalk18.cyan(String(r.awaiting).padStart(2))} ${r.scenario.padEnd(width)}` + chalk18.dim(` ${r.reason}`)
16759
+ ` ${chalk19.cyan(String(r.awaiting).padStart(2))} ${r.scenario.padEnd(width)}` + chalk19.dim(` ${r.reason}`)
16490
16760
  );
16491
16761
  }
16492
16762
  const first = rerun[0].scenario;
16493
16763
  console.log(
16494
- chalk18.dim(" Next: in your agent, ") + rerunCommand(projectRoot, first) + chalk18.dim(
16764
+ chalk19.dim(" Next: in your agent, ") + rerunCommand(projectRoot, first) + chalk19.dim(
16495
16765
  rerun.length > 1 ? " (then the others, most fixes first)" : ""
16496
16766
  )
16497
16767
  );
@@ -16561,10 +16831,10 @@ async function status(opts) {
16561
16831
  }
16562
16832
  const quiet = isQuiet();
16563
16833
  if (!quiet) console.log();
16564
- console.log(chalk18.bold(" " + projectStatus.project.name));
16834
+ console.log(chalk19.bold(" " + projectStatus.project.name));
16565
16835
  if (!quiet) {
16566
16836
  console.log(
16567
- chalk18.dim(
16837
+ chalk19.dim(
16568
16838
  " " + (projectStatus.cloud.linked ? "cloud-linked" : "local-only")
16569
16839
  )
16570
16840
  );
@@ -16603,43 +16873,43 @@ async function status(opts) {
16603
16873
  ]
16604
16874
  ];
16605
16875
  for (const [label, count, invalid] of rows) {
16606
- const num = count === 0 ? chalk18.dim("0") : chalk18.cyan(String(count));
16607
- const inv = invalid > 0 ? chalk18.yellow(` (${symbols.warning} ${invalid} invalid)`) : "";
16876
+ const num = count === 0 ? chalk19.dim("0") : chalk19.cyan(String(count));
16877
+ const inv = invalid > 0 ? chalk19.yellow(` (${symbols.warning} ${invalid} invalid)`) : "";
16608
16878
  console.log(` ${padRight(label, 14)} ${num}${inv}`);
16609
16879
  }
16610
16880
  if (!quiet) console.log();
16611
- let ctxLabel = chalk18.dim("none");
16881
+ let ctxLabel = chalk19.dim("none");
16612
16882
  if (projectStatus.context.present) {
16613
16883
  if (projectStatus.context.richness === "thin") {
16614
16884
  const reasons = projectStatus.context.thin_reasons && projectStatus.context.thin_reasons.length > 0 ? ` (${projectStatus.context.thin_reasons.join(", ")})` : "";
16615
- ctxLabel = chalk18.yellow(`thin${reasons}`) + ` ${symbols.warning}`;
16885
+ ctxLabel = chalk19.yellow(`thin${reasons}`) + ` ${symbols.warning}`;
16616
16886
  } else {
16617
- ctxLabel = chalk18.green("complete");
16887
+ ctxLabel = chalk19.green("complete");
16618
16888
  }
16619
16889
  }
16620
16890
  console.log(` ${padRight("context", 14)} ${ctxLabel}`);
16621
16891
  console.log(
16622
- ` ${padRight("runs", 14)} ${runs.length === 0 ? chalk18.dim("0") : chalk18.cyan(String(runs.length))}${runs.length > 0 ? chalk18.dim(" last: " + runs.at(-1)) : ""}`
16892
+ ` ${padRight("runs", 14)} ${runs.length === 0 ? chalk19.dim("0") : chalk19.cyan(String(runs.length))}${runs.length > 0 ? chalk19.dim(" last: " + runs.at(-1)) : ""}`
16623
16893
  );
16624
16894
  if (incompleteRuns.length > 0) {
16625
16895
  console.log(
16626
- chalk18.yellow(` ${padRight("unfinished", 14)} ${incompleteRuns.length}`) + chalk18.dim(
16896
+ chalk19.yellow(` ${padRight("unfinished", 14)} ${incompleteRuns.length}`) + chalk19.dim(
16627
16897
  " never reached `iamu complete` \u2014 `iamu status --json` lists them"
16628
16898
  )
16629
16899
  );
16630
16900
  }
16631
16901
  if (projectStatus.requests && projectStatus.requests.open > 0) {
16632
16902
  console.log(
16633
- chalk18.cyan(
16903
+ chalk19.cyan(
16634
16904
  ` ${padRight("requests", 14)} ${projectStatus.requests.open}`
16635
- ) + chalk18.dim(" queued by the team \u2014 `/iamu:findings` to pick one up")
16905
+ ) + chalk19.dim(" queued by the team \u2014 `/iamu:findings` to pick one up")
16636
16906
  );
16637
16907
  }
16638
16908
  if (projectStatus.sync) {
16639
16909
  const { pending_new, pending_updates, pending_retries } = projectStatus.sync;
16640
16910
  if (pending_new > 0 || pending_updates > 0 || pending_retries > 0) {
16641
16911
  console.log(
16642
- chalk18.yellow(
16912
+ chalk19.yellow(
16643
16913
  ` ${padRight("unpushed", 14)} ${pending_new} new, ${pending_updates} modified, ${pending_retries} retries`
16644
16914
  )
16645
16915
  );
@@ -16649,14 +16919,14 @@ async function status(opts) {
16649
16919
  const n = deletions.count;
16650
16920
  const noun = `${n} local deletion${n === 1 ? "" : "s"}`;
16651
16921
  console.log(
16652
- chalk18.yellow(
16922
+ chalk19.yellow(
16653
16923
  deletions.needs_confirm ? ` ${padRight("deletions", 14)} ${noun} not yet synced \u2014 they need \`iamu sync --confirm-deletes\`` : ` ${padRight("deletions", 14)} ${noun} not yet synced \u2014 run \`iamu sync\``
16654
16924
  )
16655
16925
  );
16656
16926
  }
16657
16927
  if (deletions.held > 0) {
16658
16928
  console.log(
16659
- chalk18.dim(
16929
+ chalk19.dim(
16660
16930
  ` ${padRight("held", 14)} ${deletions.held} local deletion(s) will not be sent yet \u2014 \`iamu sync\` says why`
16661
16931
  )
16662
16932
  );
@@ -16671,17 +16941,17 @@ async function status(opts) {
16671
16941
  if (allWarnings.length > 0) {
16672
16942
  if (!quiet) console.log();
16673
16943
  console.log(
16674
- chalk18.yellow(` ${symbols.warning} Warnings (${allWarnings.length}):`)
16944
+ chalk19.yellow(` ${symbols.warning} Warnings (${allWarnings.length}):`)
16675
16945
  );
16676
16946
  for (const w of allWarnings) {
16677
- console.log(chalk18.dim(` \u2022 ${w}`));
16947
+ console.log(chalk19.dim(` \u2022 ${w}`));
16678
16948
  }
16679
16949
  }
16680
16950
  if (!quiet) {
16681
16951
  console.log();
16682
16952
  printRerun(projectRoot, rerun);
16683
16953
  if (staleSkills.length > 0) {
16684
- console.log(chalk18.yellow(` ${STALE_SKILLS_MESSAGE}`));
16954
+ console.log(chalk19.yellow(` ${STALE_SKILLS_MESSAGE}`));
16685
16955
  console.log();
16686
16956
  }
16687
16957
  console.log();
@@ -16804,7 +17074,7 @@ var init_browse_actions = __esm({
16804
17074
 
16805
17075
  // src/commands/browse-driver.ts
16806
17076
  import { execFile as execFile3, spawn } from "child_process";
16807
- import { readFile as readFile4 } from "fs/promises";
17077
+ import { readFile as readFile5 } from "fs/promises";
16808
17078
  async function probeCdp(port, timeoutMs = CDP_PROBE_TIMEOUT_MS) {
16809
17079
  try {
16810
17080
  const res = await fetch(`http://127.0.0.1:${port}/json/version`, {
@@ -16820,7 +17090,7 @@ async function probeCdp(port, timeoutMs = CDP_PROBE_TIMEOUT_MS) {
16820
17090
  async function readProcessCommandLine(pid, platform2 = process.platform) {
16821
17091
  if (!Number.isInteger(pid) || pid <= 0 || platform2 === "win32") return null;
16822
17092
  if (platform2 === "linux") {
16823
- const raw = await readFile4(`/proc/${pid}/cmdline`, "utf8").catch(() => "");
17093
+ const raw = await readFile5(`/proc/${pid}/cmdline`, "utf8").catch(() => "");
16824
17094
  if (raw) return raw.split("\0").join(" ").trim();
16825
17095
  }
16826
17096
  return new Promise((resolve3) => {
@@ -16931,7 +17201,7 @@ var init_browse_driver = __esm({
16931
17201
 
16932
17202
  // src/commands/step-numbering.ts
16933
17203
  import { open, readdir, unlink } from "fs/promises";
16934
- import path21 from "path";
17204
+ import path22 from "path";
16935
17205
  function stepFileName(stepNumber2) {
16936
17206
  return `${String(stepNumber2).padStart(3, "0")}.json`;
16937
17207
  }
@@ -16953,7 +17223,7 @@ async function reserveStepFile(stepsDir, limit) {
16953
17223
  if (candidate > limit.maxSteps) {
16954
17224
  throw new Error(stepLimitMessage(limit.maxSteps, limit.runId));
16955
17225
  }
16956
- const stepPath = path21.join(stepsDir, stepFileName(candidate));
17226
+ const stepPath = path22.join(stepsDir, stepFileName(candidate));
16957
17227
  try {
16958
17228
  const handle = await open(stepPath, "wx");
16959
17229
  await handle.close();
@@ -16984,9 +17254,9 @@ __export(step_exports, {
16984
17254
  recordStep: () => recordStep,
16985
17255
  stepCommand: () => stepCommand
16986
17256
  });
16987
- import { copyFile, mkdir as mkdir5, stat } from "fs/promises";
16988
- import path22 from "path";
16989
- import chalk19 from "chalk";
17257
+ import { copyFile, mkdir as mkdir5, stat as stat2 } from "fs/promises";
17258
+ import path23 from "path";
17259
+ import chalk20 from "chalk";
16990
17260
  function parseMaxSteps(val) {
16991
17261
  if (typeof val === "number" && Number.isFinite(val) && val > 0) return val;
16992
17262
  if (typeof val === "string" && val.trim().length > 0) {
@@ -17004,8 +17274,8 @@ async function recordStep(input) {
17004
17274
  if (!runDirPath) {
17005
17275
  throw new Error(`Run directory not found for run "${input.runId}"`);
17006
17276
  }
17007
- const stepsDir = path22.join(runDirPath, "steps");
17008
- const screenshotsDir = path22.join(runDirPath, "screenshots");
17277
+ const stepsDir = path23.join(runDirPath, "steps");
17278
+ const screenshotsDir = path23.join(runDirPath, "screenshots");
17009
17279
  await mkdir5(stepsDir, { recursive: true });
17010
17280
  await mkdir5(screenshotsDir, { recursive: true });
17011
17281
  const shotSource = input.shot ? await existingShot(input.shot) : null;
@@ -17019,11 +17289,11 @@ async function recordStep(input) {
17019
17289
  let finalScreenshotPath = null;
17020
17290
  if (shotSource) {
17021
17291
  const destName = `step-${stepNumber2}.png`;
17022
- finalScreenshotPath = path22.join(screenshotsDir, destName);
17023
- if (path22.resolve(finalScreenshotPath) !== shotSource) {
17292
+ finalScreenshotPath = path23.join(screenshotsDir, destName);
17293
+ if (path23.resolve(finalScreenshotPath) !== shotSource) {
17024
17294
  await copyFile(shotSource, finalScreenshotPath);
17025
17295
  }
17026
- screenshotRef = path22.join("screenshots", destName);
17296
+ screenshotRef = path23.join("screenshots", destName);
17027
17297
  }
17028
17298
  const parsedStep = runStepSchema.parse({
17029
17299
  step_number: stepNumber2,
@@ -17037,10 +17307,24 @@ async function recordStep(input) {
17037
17307
  ...input.extra ? { extra: input.extra } : {}
17038
17308
  });
17039
17309
  await writeStep(runDirPath, parsedStep);
17310
+ let cancelled = false;
17311
+ try {
17312
+ const liveRes = await sendLiveStep(
17313
+ input.projectRoot,
17314
+ input.runId,
17315
+ parsedStep,
17316
+ finalScreenshotPath
17317
+ );
17318
+ if (liveRes.cancelled) {
17319
+ cancelled = true;
17320
+ }
17321
+ } catch {
17322
+ }
17040
17323
  return {
17041
17324
  step: parsedStep,
17042
17325
  stepPath,
17043
- screenshotPath: finalScreenshotPath
17326
+ screenshotPath: finalScreenshotPath,
17327
+ cancelled
17044
17328
  };
17045
17329
  } catch (err) {
17046
17330
  await reservation.release();
@@ -17048,8 +17332,8 @@ async function recordStep(input) {
17048
17332
  }
17049
17333
  }
17050
17334
  async function existingShot(shot) {
17051
- const resolved = path22.resolve(shot);
17052
- const isFile = await stat(resolved).then((s) => s.isFile()).catch(() => false);
17335
+ const resolved = path23.resolve(shot);
17336
+ const isFile = await stat2(resolved).then((s) => s.isFile()).catch(() => false);
17053
17337
  if (!isFile) {
17054
17338
  throw new Error(
17055
17339
  `Screenshot not found: ${resolved} \u2014 save the screenshot first, or omit --shot.`
@@ -17085,12 +17369,42 @@ async function stepCommand(runArg, opts) {
17085
17369
  grounding: opts.grounding,
17086
17370
  maxSteps: opts.maxSteps
17087
17371
  });
17372
+ if (res.cancelled) {
17373
+ if (opts.json) {
17374
+ console.log(
17375
+ JSON.stringify(
17376
+ {
17377
+ step_number: res.step.step_number,
17378
+ cancelled: true,
17379
+ path: path23.relative(projectRoot, res.stepPath),
17380
+ action: res.step.action,
17381
+ note: res.step.note,
17382
+ url: res.step.url,
17383
+ screenshot: res.step.screenshot,
17384
+ surface: res.step.surface
17385
+ },
17386
+ null,
17387
+ 2
17388
+ )
17389
+ );
17390
+ } else {
17391
+ console.log();
17392
+ console.log(
17393
+ chalk20.red(
17394
+ "The user stopped this run from the live viewer. End the walk now."
17395
+ )
17396
+ );
17397
+ console.log();
17398
+ }
17399
+ process.exitCode = 1;
17400
+ return;
17401
+ }
17088
17402
  if (opts.json) {
17089
17403
  console.log(
17090
17404
  JSON.stringify(
17091
17405
  {
17092
17406
  step_number: res.step.step_number,
17093
- path: path22.relative(projectRoot, res.stepPath),
17407
+ path: path23.relative(projectRoot, res.stepPath),
17094
17408
  action: res.step.action,
17095
17409
  note: res.step.note,
17096
17410
  url: res.step.url,
@@ -17105,19 +17419,19 @@ async function stepCommand(runArg, opts) {
17105
17419
  }
17106
17420
  console.log();
17107
17421
  console.log(
17108
- ` ${symbols.success} Step ${chalk19.cyan(String(res.step.step_number))} recorded: ${res.step.action}`
17422
+ ` ${symbols.success} Step ${chalk20.cyan(String(res.step.step_number))} recorded: ${res.step.action}`
17109
17423
  );
17110
17424
  if (res.step.note) {
17111
- console.log(` ${chalk19.dim("note:")} ${res.step.note}`);
17425
+ console.log(` ${chalk20.dim("note:")} ${res.step.note}`);
17112
17426
  }
17113
17427
  if (res.step.url) {
17114
- console.log(` ${chalk19.dim("url:")} ${res.step.url}`);
17428
+ console.log(` ${chalk20.dim("url:")} ${res.step.url}`);
17115
17429
  }
17116
17430
  if (res.step.screenshot) {
17117
- console.log(` ${chalk19.dim("shot:")} ${res.step.screenshot}`);
17431
+ console.log(` ${chalk20.dim("shot:")} ${res.step.screenshot}`);
17118
17432
  }
17119
17433
  console.log(
17120
- ` ${chalk19.dim("file:")} ${path22.relative(projectRoot, res.stepPath)}`
17434
+ ` ${chalk20.dim("file:")} ${path23.relative(projectRoot, res.stepPath)}`
17121
17435
  );
17122
17436
  console.log();
17123
17437
  } catch (err) {
@@ -17132,6 +17446,7 @@ var init_step = __esm({
17132
17446
  init_dist();
17133
17447
  init_symbols();
17134
17448
  init_context4();
17449
+ init_live_run_client();
17135
17450
  init_step_numbering();
17136
17451
  DEFAULT_MAX_STEPS = 50;
17137
17452
  }
@@ -17160,21 +17475,21 @@ import {
17160
17475
  } from "fs";
17161
17476
  import { rm as rm2 } from "fs/promises";
17162
17477
  import { homedir as homedir3 } from "os";
17163
- import path23 from "path";
17164
- import chalk20 from "chalk";
17478
+ import path24 from "path";
17479
+ import chalk21 from "chalk";
17165
17480
  function stateDir() {
17166
- return path23.join(
17167
- process.env.IAMU_HOME ?? path23.join(homedir3(), ".iamu"),
17481
+ return path24.join(
17482
+ process.env.IAMU_HOME ?? path24.join(homedir3(), ".iamu"),
17168
17483
  "browse"
17169
17484
  );
17170
17485
  }
17171
17486
  function profileDir() {
17172
- return path23.join(stateDir(), "profile");
17487
+ return path24.join(stateDir(), "profile");
17173
17488
  }
17174
17489
  function readBrowseState() {
17175
17490
  try {
17176
17491
  return JSON.parse(
17177
- readFileSync6(path23.join(stateDir(), "state.json"), "utf8")
17492
+ readFileSync6(path24.join(stateDir(), "state.json"), "utf8")
17178
17493
  );
17179
17494
  } catch {
17180
17495
  return null;
@@ -17182,13 +17497,13 @@ function readBrowseState() {
17182
17497
  }
17183
17498
  function writeState(state) {
17184
17499
  mkdirSync(stateDir(), { recursive: true });
17185
- writeFileSync(path23.join(stateDir(), "state.json"), JSON.stringify(state));
17500
+ writeFileSync(path24.join(stateDir(), "state.json"), JSON.stringify(state));
17186
17501
  }
17187
17502
  function fail(message, opts) {
17188
17503
  if (opts?.json) {
17189
17504
  console.error(JSON.stringify({ error: message }));
17190
17505
  } else {
17191
- console.error(chalk20.red(` ${message}`));
17506
+ console.error(chalk21.red(` ${message}`));
17192
17507
  }
17193
17508
  process.exitCode = 1;
17194
17509
  }
@@ -17245,7 +17560,7 @@ async function requestedViewport(opts) {
17245
17560
  let manifest;
17246
17561
  try {
17247
17562
  manifest = JSON.parse(
17248
- readFileSync6(path23.join(dir, "walkthrough.json"), "utf8")
17563
+ readFileSync6(path24.join(dir, "walkthrough.json"), "utf8")
17249
17564
  );
17250
17565
  } catch {
17251
17566
  fail(
@@ -17277,7 +17592,7 @@ async function convergeRunning(opts, driver, port, requested, previous) {
17277
17592
  writeState({ port, viewport, pid: previous?.pid });
17278
17593
  if (sameSize(current, viewport)) {
17279
17594
  report2(opts, { reused: true, port, viewport }, [
17280
- ` ${chalk20.green("\u2713")} Browser reused ${chalk20.dim(`(CDP :${port}, viewport ${sizeLabel(viewport)})`)}`
17595
+ ` ${chalk21.green("\u2713")} Browser reused ${chalk21.dim(`(CDP :${port}, viewport ${sizeLabel(viewport)})`)}`
17281
17596
  ]);
17282
17597
  return;
17283
17598
  }
@@ -17286,7 +17601,7 @@ async function convergeRunning(opts, driver, port, requested, previous) {
17286
17601
  } catch {
17287
17602
  }
17288
17603
  report2(opts, { resized: true, from: current, to: viewport, port }, [
17289
- ` ${chalk20.green("\u2713")} Browser resized ${sizeLabel(current)} \u2192 ${sizeLabel(viewport)} ${chalk20.dim(`(CDP :${port})`)}`
17604
+ ` ${chalk21.green("\u2713")} Browser resized ${sizeLabel(current)} \u2192 ${sizeLabel(viewport)} ${chalk21.dim(`(CDP :${port})`)}`
17290
17605
  ]);
17291
17606
  }
17292
17607
  function chromeArgs(opts, port, headless) {
@@ -17330,7 +17645,7 @@ async function start(opts, driver = cdpDriver) {
17330
17645
  for (let i = 0; i < 75; i++) {
17331
17646
  if (await driver.isRunning(port)) {
17332
17647
  report2(opts, { ready: true, port, viewport, headless }, [
17333
- ` ${chalk20.green("\u2713")} Browser ready ${chalk20.dim(`(CDP :${port}${viewport ? `, viewport ${sizeLabel(viewport)}` : ""}${headless ? ", headless" : ""})`)}`
17648
+ ` ${chalk21.green("\u2713")} Browser ready ${chalk21.dim(`(CDP :${port}${viewport ? `, viewport ${sizeLabel(viewport)}` : ""}${headless ? ", headless" : ""})`)}`
17334
17649
  ]);
17335
17650
  return;
17336
17651
  }
@@ -17351,10 +17666,10 @@ async function stop(opts, driver) {
17351
17666
  await driver.closeBrowser(state.port);
17352
17667
  if (state.pid) await reapBrowser(state.pid, profileDir(), driver);
17353
17668
  try {
17354
- unlinkSync(path23.join(stateDir(), "state.json"));
17669
+ unlinkSync(path24.join(stateDir(), "state.json"));
17355
17670
  } catch {
17356
17671
  }
17357
- report2(opts, { stopped: true }, [` ${chalk20.green("\u2713")} Browser stopped`]);
17672
+ report2(opts, { stopped: true }, [` ${chalk21.green("\u2713")} Browser stopped`]);
17358
17673
  }
17359
17674
  async function waitForVisualStability(page, maxWaitMs = 300) {
17360
17675
  let timer;
@@ -17417,8 +17732,8 @@ async function withPage(opts, driver, fn, target) {
17417
17732
  let screenshot = null;
17418
17733
  if (opts.shot) {
17419
17734
  await waitForVisualStability(page);
17420
- screenshot = path23.resolve(opts.shot);
17421
- mkdirSync(path23.dirname(screenshot), { recursive: true });
17735
+ screenshot = path24.resolve(opts.shot);
17736
+ mkdirSync(path24.dirname(screenshot), { recursive: true });
17422
17737
  await page.screenshot({ path: screenshot, fullPage: Boolean(opts.full) });
17423
17738
  }
17424
17739
  return { url: page.url(), title: await page.title(), screenshot };
@@ -17497,23 +17812,24 @@ function printStep(opts, record, projectRoot) {
17497
17812
  if (opts.json) {
17498
17813
  const doc = {
17499
17814
  step_number: step.step_number,
17500
- path: path23.relative(projectRoot, record.stepPath),
17815
+ path: path24.relative(projectRoot, record.stepPath),
17501
17816
  action: step.action,
17502
17817
  note: step.note,
17503
17818
  url: step.url,
17504
17819
  screenshot: step.screenshot,
17505
- surface: step.surface
17820
+ surface: step.surface,
17821
+ ...record.cancelled ? { cancelled: true } : {}
17506
17822
  };
17507
17823
  console.log(JSON.stringify(doc, null, 2));
17508
17824
  return;
17509
17825
  }
17510
17826
  console.log(
17511
- ` ${chalk20.green("\u2713")} Step ${chalk20.cyan(String(step.step_number))} recorded: ${step.action}`
17827
+ ` ${chalk21.green("\u2713")} Step ${chalk21.cyan(String(step.step_number))} recorded: ${step.action}`
17512
17828
  );
17513
- if (step.note) console.log(` ${chalk20.dim("note:")} ${step.note}`);
17514
- if (step.url) console.log(` ${chalk20.dim("url:")} ${step.url}`);
17829
+ if (step.note) console.log(` ${chalk21.dim("note:")} ${step.note}`);
17830
+ if (step.url) console.log(` ${chalk21.dim("url:")} ${step.url}`);
17515
17831
  if (step.screenshot) {
17516
- console.log(` ${chalk20.dim("screenshot:")} ${step.screenshot}`);
17832
+ console.log(` ${chalk21.dim("screenshot:")} ${step.screenshot}`);
17517
17833
  }
17518
17834
  }
17519
17835
  async function browseStep(args, opts, driver) {
@@ -17571,10 +17887,10 @@ async function browseStep(args, opts, driver) {
17571
17887
  const runDirPath = resolveRunDir(ctx.projectRoot, opts.run);
17572
17888
  if (!runDirPath) return;
17573
17889
  const maxSteps = parseMaxSteps(opts.maxSteps);
17574
- if (await peekNextStepNumber(path23.join(runDirPath, "steps")) > maxSteps) {
17890
+ if (await peekNextStepNumber(path24.join(runDirPath, "steps")) > maxSteps) {
17575
17891
  return fail(stepLimitMessage(maxSteps, opts.run), opts);
17576
17892
  }
17577
- const pendingShot = path23.join(
17893
+ const pendingShot = path24.join(
17578
17894
  runDirPath,
17579
17895
  "screenshots",
17580
17896
  `.pending-${randomUUID7()}.png`
@@ -17598,6 +17914,19 @@ async function browseStep(args, opts, driver) {
17598
17914
  maxSteps
17599
17915
  });
17600
17916
  printStep(opts, record, ctx.projectRoot);
17917
+ if (record.cancelled) {
17918
+ if (!opts.json) {
17919
+ console.log();
17920
+ console.log(
17921
+ chalk21.red(
17922
+ "The user stopped this run from the live viewer. End the walk now."
17923
+ )
17924
+ );
17925
+ console.log();
17926
+ }
17927
+ process.exitCode = 1;
17928
+ return;
17929
+ }
17601
17930
  } catch (err) {
17602
17931
  fail(err instanceof Error ? err.message : String(err), opts);
17603
17932
  } finally {
@@ -17654,7 +17983,7 @@ __export(doctor_exports, {
17654
17983
  import { createServer } from "net";
17655
17984
  import { existsSync as existsSync10, promises as fs26 } from "fs";
17656
17985
  import { join as join7 } from "path";
17657
- import chalk21 from "chalk";
17986
+ import chalk22 from "chalk";
17658
17987
  function checkPortAvailable(port) {
17659
17988
  return new Promise((resolve3) => {
17660
17989
  const server = createServer();
@@ -18161,7 +18490,7 @@ async function doctor(opts) {
18161
18490
  return;
18162
18491
  }
18163
18492
  console.log();
18164
- console.log(chalk21.bold(" Iamu System Diagnostics"));
18493
+ console.log(chalk22.bold(" Iamu System Diagnostics"));
18165
18494
  console.log();
18166
18495
  const categories = [
18167
18496
  { key: "runtime", title: "Runtime & System" },
@@ -18174,13 +18503,13 @@ async function doctor(opts) {
18174
18503
  for (const cat of categories) {
18175
18504
  const catChecks = result.checks.filter((c) => c.category === cat.key);
18176
18505
  if (catChecks.length === 0) continue;
18177
- console.log(chalk21.bold(` ${cat.title}:`));
18506
+ console.log(chalk22.bold(` ${cat.title}:`));
18178
18507
  for (const check of catChecks) {
18179
- const sym = check.status === "ok" ? symbols.success : check.status === "warn" ? chalk21.yellow("\u25CB") : symbols.error;
18180
- console.log(` ${sym} ${check.name}: ${chalk21.dim(check.message)}`);
18508
+ const sym = check.status === "ok" ? symbols.success : check.status === "warn" ? chalk22.yellow("\u25CB") : symbols.error;
18509
+ console.log(` ${sym} ${check.name}: ${chalk22.dim(check.message)}`);
18181
18510
  if (check.remedy) {
18182
18511
  console.log(
18183
- ` ${chalk21.cyan("\u21B3 Remedy:")} ${chalk21.dim(check.remedy)}`
18512
+ ` ${chalk22.cyan("\u21B3 Remedy:")} ${chalk22.dim(check.remedy)}`
18184
18513
  );
18185
18514
  }
18186
18515
  }
@@ -18188,15 +18517,15 @@ async function doctor(opts) {
18188
18517
  }
18189
18518
  if (result.ok && result.summary.warn === 0) {
18190
18519
  console.log(
18191
- ` ${symbols.success} ${chalk21.green.bold("All systems operational.")}`
18520
+ ` ${symbols.success} ${chalk22.green.bold("All systems operational.")}`
18192
18521
  );
18193
18522
  } else if (result.ok) {
18194
18523
  console.log(
18195
- ` ${symbols.warning} ${chalk21.yellow.bold(`${result.summary.warn} warning(s) detected.`)} (Walkthroughs can still run)`
18524
+ ` ${symbols.warning} ${chalk22.yellow.bold(`${result.summary.warn} warning(s) detected.`)} (Walkthroughs can still run)`
18196
18525
  );
18197
18526
  } else {
18198
18527
  console.log(
18199
- ` ${symbols.error} ${chalk21.red.bold(`${result.summary.error} error(s) and ${result.summary.warn} warning(s) detected.`)}`
18528
+ ` ${symbols.error} ${chalk22.red.bold(`${result.summary.error} error(s) and ${result.summary.warn} warning(s) detected.`)}`
18200
18529
  );
18201
18530
  process.exitCode = 1;
18202
18531
  }
@@ -18293,20 +18622,20 @@ var list_exports = {};
18293
18622
  __export(list_exports, {
18294
18623
  list: () => list
18295
18624
  });
18296
- import chalk22 from "chalk";
18625
+ import chalk23 from "chalk";
18297
18626
  function severityColor(severity) {
18298
18627
  const raw = (severity ?? "\u2014").trim();
18299
18628
  switch (raw) {
18300
18629
  case "critical":
18301
- return chalk22.red(raw);
18630
+ return chalk23.red(raw);
18302
18631
  case "major":
18303
- return chalk22.yellow(raw);
18632
+ return chalk23.yellow(raw);
18304
18633
  case "minor":
18305
- return chalk22.cyan(raw);
18634
+ return chalk23.cyan(raw);
18306
18635
  case "observation":
18307
- return chalk22.dim(raw);
18636
+ return chalk23.dim(raw);
18308
18637
  default:
18309
- return chalk22.dim(raw);
18638
+ return chalk23.dim(raw);
18310
18639
  }
18311
18640
  }
18312
18641
  async function list(type2, opts) {
@@ -18361,16 +18690,16 @@ async function list(type2, opts) {
18361
18690
  for (const [t, c] of counts) {
18362
18691
  const label = PLURAL_LABELS[t].padEnd(14);
18363
18692
  if (!c) {
18364
- console.log(` ${label} ${chalk22.dim("error")}`);
18693
+ console.log(` ${label} ${chalk23.dim("error")}`);
18365
18694
  continue;
18366
18695
  }
18367
- const count = c.count === 0 ? chalk22.dim("0") : chalk22.cyan(String(c.count));
18368
- const warn = c.invalid > 0 ? chalk22.yellow(` (${c.invalid} invalid)`) : "";
18696
+ const count = c.count === 0 ? chalk23.dim("0") : chalk23.cyan(String(c.count));
18697
+ const warn = c.invalid > 0 ? chalk23.yellow(` (${c.invalid} invalid)`) : "";
18369
18698
  console.log(` ${label} ${count}${warn}`);
18370
18699
  }
18371
18700
  console.log();
18372
18701
  console.log(
18373
- chalk22.dim(" Run 'iamu list <type>' for details (e.g. iamu list personas)")
18702
+ chalk23.dim(" Run 'iamu list <type>' for details (e.g. iamu list personas)")
18374
18703
  );
18375
18704
  console.log();
18376
18705
  }
@@ -18396,7 +18725,7 @@ async function listSingleType(projectRoot, type2, capabilityFilter, diffFilter,
18396
18725
  if (!diffResult || diffResult.files.length === 0) {
18397
18726
  if (!opts.json) {
18398
18727
  console.log(
18399
- chalk22.dim(
18728
+ chalk23.dim(
18400
18729
  ` No git diff detected against ${diffResult?.baseRef ?? "base ref"}.`
18401
18730
  )
18402
18731
  );
@@ -18443,10 +18772,10 @@ async function listSingleType(projectRoot, type2, capabilityFilter, diffFilter,
18443
18772
  return;
18444
18773
  }
18445
18774
  if (entities.length === 0) {
18446
- console.log(chalk22.dim(` No ${PLURAL_LABELS[type2]} found.`));
18775
+ console.log(chalk23.dim(` No ${PLURAL_LABELS[type2]} found.`));
18447
18776
  if (!diffFilter) {
18448
18777
  console.log(
18449
- chalk22.dim(
18778
+ chalk23.dim(
18450
18779
  ` Run \`iamu new ${type2} --name "..."\` to create your first ${type2}.`
18451
18780
  )
18452
18781
  );
@@ -18457,10 +18786,10 @@ async function listSingleType(projectRoot, type2, capabilityFilter, diffFilter,
18457
18786
  if (isTty) {
18458
18787
  console.log();
18459
18788
  console.log(
18460
- chalk22.bold(` ${PLURAL_LABELS[type2]}`) + chalk22.dim(` (${entities.length})`)
18789
+ chalk23.bold(` ${PLURAL_LABELS[type2]}`) + chalk23.dim(` (${entities.length})`)
18461
18790
  );
18462
18791
  if (diffNotice) {
18463
- console.log(chalk22.cyan(` ${diffNotice}`));
18792
+ console.log(chalk23.cyan(` ${diffNotice}`));
18464
18793
  }
18465
18794
  console.log();
18466
18795
  }
@@ -18478,7 +18807,7 @@ async function listSingleType(projectRoot, type2, capabilityFilter, diffFilter,
18478
18807
  },
18479
18808
  {
18480
18809
  header: "role",
18481
- value: (e) => chalk22.dim(e.frontmatter.role ?? "")
18810
+ value: (e) => chalk23.dim(e.frontmatter.role ?? "")
18482
18811
  }
18483
18812
  ]);
18484
18813
  break;
@@ -18518,7 +18847,7 @@ async function listSingleType(projectRoot, type2, capabilityFilter, diffFilter,
18518
18847
  },
18519
18848
  {
18520
18849
  header: "title",
18521
- value: (e) => e.frontmatter.title ?? chalk22.dim("(no title)")
18850
+ value: (e) => e.frontmatter.title ?? chalk23.dim("(no title)")
18522
18851
  }
18523
18852
  ]);
18524
18853
  break;
@@ -18544,7 +18873,7 @@ async function listSingleType(projectRoot, type2, capabilityFilter, diffFilter,
18544
18873
  },
18545
18874
  {
18546
18875
  header: "capability",
18547
- value: (e) => chalk22.dim(
18876
+ value: (e) => chalk23.dim(
18548
18877
  e.frontmatter.primary_capability ?? e.frontmatter.capability ?? ""
18549
18878
  )
18550
18879
  },
@@ -18593,7 +18922,7 @@ async function listSingleType(projectRoot, type2, capabilityFilter, diffFilter,
18593
18922
  },
18594
18923
  {
18595
18924
  header: "rule",
18596
- value: (e) => parseGuidanceBody(e.body).rule || chalk22.dim("(no rule)")
18925
+ value: (e) => parseGuidanceBody(e.body).rule || chalk23.dim("(no rule)")
18597
18926
  }
18598
18927
  ]);
18599
18928
  break;
@@ -18606,10 +18935,10 @@ async function listSingleType(projectRoot, type2, capabilityFilter, diffFilter,
18606
18935
  if (isTty) {
18607
18936
  console.log();
18608
18937
  console.log(
18609
- chalk22.yellow(` ${warnings.length} invalid file(s) skipped:`)
18938
+ chalk23.yellow(` ${warnings.length} invalid file(s) skipped:`)
18610
18939
  );
18611
18940
  for (const w of warnings) {
18612
- console.log(chalk22.dim(` ${w.path}: ${w.error}`));
18941
+ console.log(chalk23.dim(` ${w.path}: ${w.error}`));
18613
18942
  }
18614
18943
  } else {
18615
18944
  for (const w of warnings) {
@@ -18648,12 +18977,12 @@ __export(validate_exports, {
18648
18977
  });
18649
18978
  import { randomUUID as randomUUID8 } from "crypto";
18650
18979
  import { promises as fs27 } from "fs";
18651
- import path24 from "path";
18652
- import chalk23 from "chalk";
18980
+ import path25 from "path";
18981
+ import chalk24 from "chalk";
18653
18982
  function inferTypeFromPath(filePath, projectRoot) {
18654
- const rel = path24.relative(path24.join(projectRoot, "iamu"), filePath);
18655
- if (rel.startsWith("..") || path24.isAbsolute(rel)) return null;
18656
- const segments = rel.split(path24.sep);
18983
+ const rel = path25.relative(path25.join(projectRoot, "iamu"), filePath);
18984
+ if (rel.startsWith("..") || path25.isAbsolute(rel)) return null;
18985
+ const segments = rel.split(path25.sep);
18657
18986
  if (segments.length < 2) return null;
18658
18987
  return TYPE_BY_ALIAS.get(segments[0]) ?? null;
18659
18988
  }
@@ -18683,7 +19012,7 @@ function validateFile(filePath, raw, projectRoot) {
18683
19012
  );
18684
19013
  return result;
18685
19014
  }
18686
- if (path24.basename(filePath) === "context.yml") {
19015
+ if (path25.basename(filePath) === "context.yml") {
18687
19016
  applyZodValidation(contextFrontmatterSchema, frontmatter, result);
18688
19017
  const warnings = [];
18689
19018
  const hasNotes = Boolean(
@@ -18743,7 +19072,7 @@ async function buildRepairLookups(projectRoot) {
18743
19072
  }
18744
19073
  }
18745
19074
  const runScenario = /* @__PURE__ */ new Map();
18746
- const runsDir2 = path24.join(projectRoot, "iamu", ".runs");
19075
+ const runsDir2 = path25.join(projectRoot, "iamu", ".runs");
18747
19076
  let runIds = [];
18748
19077
  try {
18749
19078
  runIds = await fs27.readdir(runsDir2);
@@ -18753,7 +19082,7 @@ async function buildRepairLookups(projectRoot) {
18753
19082
  try {
18754
19083
  const manifest = JSON.parse(
18755
19084
  await fs27.readFile(
18756
- path24.join(runsDir2, runId, "walkthrough.json"),
19085
+ path25.join(runsDir2, runId, "walkthrough.json"),
18757
19086
  "utf8"
18758
19087
  )
18759
19088
  );
@@ -18784,7 +19113,7 @@ async function fixFindings(projectRoot, results, dryRun) {
18784
19113
  parsed.frontmatter,
18785
19114
  {
18786
19115
  ...lookups,
18787
- fileSlug: path24.basename(result.path, ".md"),
19116
+ fileSlug: path25.basename(result.path, ".md"),
18788
19117
  newId: randomUUID8,
18789
19118
  body: parsed.body
18790
19119
  }
@@ -18819,7 +19148,7 @@ async function validate(filePath, opts) {
18819
19148
  if (process.exitCode === 1) return;
18820
19149
  const results = [];
18821
19150
  if (filePath) {
18822
- const abs = path24.isAbsolute(filePath) ? filePath : path24.resolve(process.cwd(), filePath);
19151
+ const abs = path25.isAbsolute(filePath) ? filePath : path25.resolve(process.cwd(), filePath);
18823
19152
  try {
18824
19153
  const raw = await fs27.readFile(abs, "utf8");
18825
19154
  results.push(validateFile(abs, raw, projectRoot));
@@ -18831,7 +19160,7 @@ async function validate(filePath, opts) {
18831
19160
  return;
18832
19161
  }
18833
19162
  } else if (opts.run) {
18834
- const findingsDir = path24.join(projectRoot, "iamu", ENTITY_DIRS.finding);
19163
+ const findingsDir = path25.join(projectRoot, "iamu", ENTITY_DIRS.finding);
18835
19164
  let names = [];
18836
19165
  try {
18837
19166
  names = await fs27.readdir(findingsDir);
@@ -18839,7 +19168,7 @@ async function validate(filePath, opts) {
18839
19168
  }
18840
19169
  for (const name of names) {
18841
19170
  if (!name.endsWith(".md")) continue;
18842
- const abs = path24.join(findingsDir, name);
19171
+ const abs = path25.join(findingsDir, name);
18843
19172
  try {
18844
19173
  const raw = await fs27.readFile(abs, "utf8");
18845
19174
  const { frontmatter } = parseFrontmatter(raw);
@@ -18848,7 +19177,7 @@ async function validate(filePath, opts) {
18848
19177
  }
18849
19178
  } catch {
18850
19179
  results.push({
18851
- path: path24.relative(projectRoot, abs),
19180
+ path: path25.relative(projectRoot, abs),
18852
19181
  valid: false,
18853
19182
  errors: ["Cannot read file or parse frontmatter"]
18854
19183
  });
@@ -18874,14 +19203,14 @@ async function validate(filePath, opts) {
18874
19203
  )
18875
19204
  );
18876
19205
  } else {
18877
- console.log(chalk23.dim(` No findings found for run "${opts.run}".`));
19206
+ console.log(chalk24.dim(` No findings found for run "${opts.run}".`));
18878
19207
  }
18879
19208
  return;
18880
19209
  }
18881
19210
  } else {
18882
19211
  const typesToCheck = typeFilter ? ENTITY_TYPES.filter((t) => typeFilter.has(t)) : ENTITY_TYPES;
18883
19212
  for (const type2 of typesToCheck) {
18884
- const iamuTypeDir = path24.join(projectRoot, "iamu", ENTITY_DIRS[type2]);
19213
+ const iamuTypeDir = path25.join(projectRoot, "iamu", ENTITY_DIRS[type2]);
18885
19214
  let names;
18886
19215
  try {
18887
19216
  names = await fs27.readdir(iamuTypeDir);
@@ -18890,20 +19219,20 @@ async function validate(filePath, opts) {
18890
19219
  }
18891
19220
  for (const name of names) {
18892
19221
  if (!name.endsWith(".md")) continue;
18893
- const abs = path24.join(iamuTypeDir, name);
19222
+ const abs = path25.join(iamuTypeDir, name);
18894
19223
  try {
18895
19224
  const raw = await fs27.readFile(abs, "utf8");
18896
19225
  results.push(validateFile(abs, raw, projectRoot));
18897
19226
  } catch {
18898
19227
  results.push({
18899
- path: path24.relative(projectRoot, abs),
19228
+ path: path25.relative(projectRoot, abs),
18900
19229
  valid: false,
18901
19230
  errors: ["Cannot read file"]
18902
19231
  });
18903
19232
  }
18904
19233
  }
18905
19234
  }
18906
- const ctxPath = path24.join(projectRoot, "iamu", "context.yml");
19235
+ const ctxPath = path25.join(projectRoot, "iamu", "context.yml");
18907
19236
  try {
18908
19237
  const raw = await fs27.readFile(ctxPath, "utf8");
18909
19238
  results.push(validateFile(ctxPath, raw, projectRoot));
@@ -18924,19 +19253,19 @@ async function validate(filePath, opts) {
18924
19253
  valid,
18925
19254
  errors: results.filter((r) => !r.valid).flatMap(
18926
19255
  (r) => r.errors.map((e) => ({
18927
- path: path24.relative(projectRoot, r.path),
19256
+ path: path25.relative(projectRoot, r.path),
18928
19257
  message: e
18929
19258
  }))
18930
19259
  ),
18931
19260
  warnings: results.filter((r) => r.warnings && r.warnings.length > 0).flatMap(
18932
19261
  (r) => (r.warnings ?? []).map((w) => ({
18933
- path: path24.relative(projectRoot, r.path),
19262
+ path: path25.relative(projectRoot, r.path),
18934
19263
  message: w
18935
19264
  }))
18936
19265
  ),
18937
19266
  ...opts.fix ? {
18938
19267
  repaired: repaired.map((r) => ({
18939
- path: path24.relative(projectRoot, r.path),
19268
+ path: path25.relative(projectRoot, r.path),
18940
19269
  changes: r.repairs,
18941
19270
  valid: r.valid
18942
19271
  }))
@@ -18958,30 +19287,30 @@ async function validate(filePath, opts) {
18958
19287
  }
18959
19288
  let hasErrors = false;
18960
19289
  for (const r of results) {
18961
- const relPath = path24.relative(projectRoot, r.path);
19290
+ const relPath = path25.relative(projectRoot, r.path);
18962
19291
  if (r.valid) {
18963
19292
  if (r.warnings && r.warnings.length > 0) {
18964
- console.log(` ${symbols.warning} ` + chalk23.yellow(relPath));
19293
+ console.log(` ${symbols.warning} ` + chalk24.yellow(relPath));
18965
19294
  for (const w of r.warnings) {
18966
- console.log(chalk23.yellow(` \u2022 ${w}`));
19295
+ console.log(chalk24.yellow(` \u2022 ${w}`));
18967
19296
  }
18968
19297
  } else {
18969
- console.log(` ${symbols.success} ` + chalk23.dim(relPath));
19298
+ console.log(` ${symbols.success} ` + chalk24.dim(relPath));
18970
19299
  }
18971
19300
  for (const change of r.repairs ?? []) {
18972
- console.log(` ${symbols.modified} ` + chalk23.dim(change));
19301
+ console.log(` ${symbols.modified} ` + chalk24.dim(change));
18973
19302
  }
18974
19303
  } else {
18975
19304
  hasErrors = true;
18976
19305
  console.log(` ${symbols.error} ` + relPath);
18977
19306
  for (const change of r.repairs ?? []) {
18978
- console.log(` ${symbols.modified} ` + chalk23.dim(change));
19307
+ console.log(` ${symbols.modified} ` + chalk24.dim(change));
18979
19308
  }
18980
19309
  for (const e of r.errors) {
18981
- console.log(chalk23.dim(" " + e));
19310
+ console.log(chalk24.dim(" " + e));
18982
19311
  }
18983
19312
  for (const w of r.warnings ?? []) {
18984
- console.log(chalk23.yellow(" \u2022 " + w));
19313
+ console.log(chalk24.yellow(" \u2022 " + w));
18985
19314
  }
18986
19315
  }
18987
19316
  }
@@ -18994,7 +19323,7 @@ async function validate(filePath, opts) {
18994
19323
  );
18995
19324
  }
18996
19325
  if (results.length === 0) {
18997
- console.log(chalk23.dim(" No files to validate."));
19326
+ console.log(chalk24.dim(" No files to validate."));
18998
19327
  }
18999
19328
  if (hasErrors) {
19000
19329
  process.exitCode = 1;
@@ -19032,9 +19361,9 @@ __export(update_exports, {
19032
19361
  update: () => update
19033
19362
  });
19034
19363
  import { existsSync as existsSync11, readFileSync as readFileSync7 } from "fs";
19035
- import { mkdir as mkdir6, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
19364
+ import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile4 } from "fs/promises";
19036
19365
  import { join as join8 } from "path";
19037
- import chalk24 from "chalk";
19366
+ import chalk25 from "chalk";
19038
19367
  async function update(opts) {
19039
19368
  const ctx = await resolveProject();
19040
19369
  if (!ctx) return;
@@ -19061,7 +19390,7 @@ async function update(opts) {
19061
19390
  const dest = join8(promptsDir, file);
19062
19391
  let existing = "";
19063
19392
  try {
19064
- existing = await readFile5(dest, "utf-8");
19393
+ existing = await readFile6(dest, "utf-8");
19065
19394
  } catch {
19066
19395
  }
19067
19396
  if (existing !== content) {
@@ -19079,13 +19408,13 @@ async function update(opts) {
19079
19408
  opts?.host
19080
19409
  );
19081
19410
  if (error) {
19082
- console.error(chalk24.red(` ${symbols.error} ${error}`));
19411
+ console.error(chalk25.red(` ${symbols.error} ${error}`));
19083
19412
  process.exitCode = 1;
19084
19413
  return;
19085
19414
  }
19086
19415
  if (targetHosts.length === 0) {
19087
19416
  console.log(
19088
- chalk24.dim(
19417
+ chalk25.dim(
19089
19418
  " No supported agent hosts detected. Specify with `iamu update --host <name>` or run `iamu init`."
19090
19419
  )
19091
19420
  );
@@ -19139,7 +19468,7 @@ __export(new_entity_exports, {
19139
19468
  newEntity: () => newEntity
19140
19469
  });
19141
19470
  import { randomUUID as randomUUID9 } from "crypto";
19142
- import chalk25 from "chalk";
19471
+ import chalk26 from "chalk";
19143
19472
  function defaultFrontmatter(type2, id, slug, name, opts) {
19144
19473
  const base = { id, slug };
19145
19474
  const description = opts.description ? { description: opts.description } : {};
@@ -19265,9 +19594,9 @@ async function newEntity(type2, opts) {
19265
19594
  }
19266
19595
  console.log();
19267
19596
  console.log(
19268
- ` ${symbols.success} Created ${entityType}: ${chalk25.cyan(slug)}`
19597
+ ` ${symbols.success} Created ${entityType}: ${chalk26.cyan(slug)}`
19269
19598
  );
19270
- console.log(` ${chalk25.dim("path:")} ${record.path}`);
19599
+ console.log(` ${chalk26.dim("path:")} ${record.path}`);
19271
19600
  console.log();
19272
19601
  } catch (err) {
19273
19602
  commandError(
@@ -19408,7 +19737,7 @@ async function crawlFrom(page, opts, origin, takeBlocked) {
19408
19737
  const byKey = /* @__PURE__ */ new Map();
19409
19738
  const byPlaceView = /* @__PURE__ */ new Map();
19410
19739
  const signatureOf = (s) => exploreSignature(s.headings, s.title);
19411
- function addSurface(state, place, view, path30, depth) {
19740
+ function addSurface(state, place, view, path31, depth) {
19412
19741
  const key = exploreSurfaceKey(place, view);
19413
19742
  const surface = {
19414
19743
  key,
@@ -19420,7 +19749,7 @@ async function crawlFrom(page, opts, origin, takeBlocked) {
19420
19749
  headings: state.headings,
19421
19750
  fields: state.fields,
19422
19751
  depth,
19423
- path: path30,
19752
+ path: path31,
19424
19753
  actions: []
19425
19754
  };
19426
19755
  surfaces.push(surface);
@@ -19438,9 +19767,9 @@ ${surface.signature}`, key);
19438
19767
  });
19439
19768
  await settle(page, settleMs);
19440
19769
  }
19441
- async function replay(path30) {
19442
- if (!("goto" in (path30[0] ?? {}))) await goto(opts.startUrl);
19443
- for (const step of path30) {
19770
+ async function replay(path31) {
19771
+ if (!("goto" in (path31[0] ?? {}))) await goto(opts.startUrl);
19772
+ for (const step of path31) {
19444
19773
  if ("goto" in step) {
19445
19774
  await goto(step.goto);
19446
19775
  } else {
@@ -19564,8 +19893,8 @@ ${sig}`, key);
19564
19893
  if (stats.surfaces >= budget.max_surfaces) {
19565
19894
  stats.truncated = true;
19566
19895
  } else {
19567
- const path30 = !sameDoc && view === null ? [{ goto: after.url }] : [...surface.path, ...via, click];
19568
- addSurface(after, place, view, path30, surface.depth + 1);
19896
+ const path31 = !sameDoc && view === null ? [{ goto: after.url }] : [...surface.path, ...via, click];
19897
+ addSurface(after, place, view, path31, surface.depth + 1);
19569
19898
  }
19570
19899
  }
19571
19900
  }
@@ -19766,11 +20095,11 @@ __export(explore_exports, {
19766
20095
  exploreRun: () => exploreRun
19767
20096
  });
19768
20097
  import { promises as fs28 } from "fs";
19769
- import path25 from "path";
19770
- import chalk26 from "chalk";
20098
+ import path26 from "path";
20099
+ import chalk27 from "chalk";
19771
20100
  function fail2(message, json2) {
19772
20101
  if (json2) console.error(JSON.stringify({ error: message }));
19773
- else console.error(chalk26.red(` ${message}`));
20102
+ else console.error(chalk27.red(` ${message}`));
19774
20103
  process.exitCode = 1;
19775
20104
  }
19776
20105
  function positiveInt(raw, fallback, flag) {
@@ -19784,7 +20113,7 @@ function positiveInt(raw, fallback, flag) {
19784
20113
  async function testabilityTarget2(projectRoot) {
19785
20114
  try {
19786
20115
  const raw = await fs28.readFile(
19787
- path25.join(projectRoot, "iamu", "testability.md"),
20116
+ path26.join(projectRoot, "iamu", "testability.md"),
19788
20117
  "utf8"
19789
20118
  );
19790
20119
  const { frontmatter } = parseFrontmatter(raw);
@@ -19873,7 +20202,7 @@ async function exploreRun(url, opts) {
19873
20202
  }
19874
20203
  const quiet = opts.json || process.env.IAMU_QUIET === "1";
19875
20204
  if (!quiet) {
19876
- console.error(chalk26.dim(` Exploring ${startUrl} (read-only)\u2026`));
20205
+ console.error(chalk27.dim(` Exploring ${startUrl} (read-only)\u2026`));
19877
20206
  }
19878
20207
  const now = /* @__PURE__ */ new Date();
19879
20208
  let opened = null;
@@ -19884,7 +20213,7 @@ async function exploreRun(url, opts) {
19884
20213
  startUrl,
19885
20214
  budget,
19886
20215
  deny,
19887
- log: quiet ? void 0 : (line) => console.error(chalk26.dim(line))
20216
+ log: quiet ? void 0 : (line) => console.error(chalk27.dim(line))
19888
20217
  });
19889
20218
  } catch (err) {
19890
20219
  fail2(err.message.split("\n")[0], opts.json);
@@ -19904,7 +20233,7 @@ async function exploreRun(url, opts) {
19904
20233
  surfaces: result.surfaces
19905
20234
  };
19906
20235
  const file = await writeExploreMap(ctx.projectRoot, map2);
19907
- const rel = path25.relative(process.cwd(), file);
20236
+ const rel = path26.relative(process.cwd(), file);
19908
20237
  if (opts.json) {
19909
20238
  console.log(JSON.stringify({ id: map2.id, path: rel, stats: map2.stats }));
19910
20239
  return;
@@ -19912,17 +20241,17 @@ async function exploreRun(url, opts) {
19912
20241
  const s = map2.stats;
19913
20242
  console.log(
19914
20243
  `
19915
- ${chalk26.bold(`${s.surfaces} surfaces`)} \xB7 ${s.actions_tried} controls tried \xB7 ${s.skipped} skipped \xB7 ${s.blocked_requests} writes blocked${s.errors ? ` \xB7 ${s.errors} errors` : ""}`
20244
+ ${chalk27.bold(`${s.surfaces} surfaces`)} \xB7 ${s.actions_tried} controls tried \xB7 ${s.skipped} skipped \xB7 ${s.blocked_requests} writes blocked${s.errors ? ` \xB7 ${s.errors} errors` : ""}`
19916
20245
  );
19917
20246
  if (s.truncated) {
19918
20247
  console.log(
19919
- chalk26.yellow(
20248
+ chalk27.yellow(
19920
20249
  " Stopped by the budget before the product ran out \u2014 raise --max-surfaces / --max-actions / --max-depth to go further."
19921
20250
  )
19922
20251
  );
19923
20252
  }
19924
20253
  console.log(` Map: ${rel}`);
19925
- console.log(chalk26.dim(" Next: iamu explore coverage"));
20254
+ console.log(chalk27.dim(" Next: iamu explore coverage"));
19926
20255
  }
19927
20256
  async function resolveMapId(projectRoot, id, offsetFromEnd = 1) {
19928
20257
  if (id && id !== "latest") return id;
@@ -19950,7 +20279,7 @@ async function exploreList(opts) {
19950
20279
  }
19951
20280
  for (const r of rows) {
19952
20281
  console.log(
19953
- ` ${r.id} ${r.surfaces} surfaces ${chalk26.dim(r.target_url)}`
20282
+ ` ${r.id} ${r.surfaces} surfaces ${chalk27.dim(r.target_url)}`
19954
20283
  );
19955
20284
  }
19956
20285
  }
@@ -19979,7 +20308,7 @@ async function exploreCoverageCommand(mapId, opts) {
19979
20308
  Map ${id} (${map2.surfaces.length} surfaces) against ${cov.runs} runs, ${cov.steps} steps`
19980
20309
  );
19981
20310
  console.log(
19982
- ` ${chalk26.green(`${cov.reached} reached`)} \xB7 ${chalk26.yellow(`${cov.place_only} URL reached, view unclear`)} \xB7 ${chalk26.red(`${cov.unreached} never reached`)}`
20311
+ ` ${chalk27.green(`${cov.reached} reached`)} \xB7 ${chalk27.yellow(`${cov.place_only} URL reached, view unclear`)} \xB7 ${chalk27.red(`${cov.unreached} never reached`)}`
19983
20312
  );
19984
20313
  const section = (title, rows, color) => {
19985
20314
  if (rows.length === 0) return;
@@ -19987,23 +20316,23 @@ async function exploreCoverageCommand(mapId, opts) {
19987
20316
  ${color(title)}`);
19988
20317
  for (const r of rows) {
19989
20318
  console.log(
19990
- ` ${r.key.padEnd(32)} ${r.label}${chalk26.dim(` (depth ${r.depth})`)}`
20319
+ ` ${r.key.padEnd(32)} ${r.label}${chalk27.dim(` (depth ${r.depth})`)}`
19991
20320
  );
19992
20321
  }
19993
20322
  };
19994
20323
  section(
19995
20324
  "Never reached by a run",
19996
20325
  cov.surfaces.filter((s) => s.status === "unreached"),
19997
- chalk26.red
20326
+ chalk27.red
19998
20327
  );
19999
20328
  section(
20000
20329
  "URL reached, but no step names this view",
20001
20330
  cov.surfaces.filter((s) => s.status === "place_only"),
20002
- chalk26.yellow
20331
+ chalk27.yellow
20003
20332
  );
20004
20333
  if (cov.run_only_places.length > 0) {
20005
20334
  console.log(`
20006
- ${chalk26.cyan("Walked by runs, not in the map")}`);
20335
+ ${chalk27.cyan("Walked by runs, not in the map")}`);
20007
20336
  for (const p of cov.run_only_places) {
20008
20337
  console.log(
20009
20338
  ` ${p.place.padEnd(32)} ${p.steps} steps, ${p.runs.length} runs`
@@ -20012,7 +20341,7 @@ async function exploreCoverageCommand(mapId, opts) {
20012
20341
  }
20013
20342
  if (cov.runs === 0) {
20014
20343
  console.log(
20015
- chalk26.dim(
20344
+ chalk27.dim(
20016
20345
  "\n No runs yet \u2014 every surface counts as never reached. Walk a scenario first (iamu-run)."
20017
20346
  )
20018
20347
  );
@@ -20048,27 +20377,27 @@ async function exploreDiffCommand(a, b, opts) {
20048
20377
  console.log(`
20049
20378
  ${idA} \u2192 ${idB}`);
20050
20379
  console.log(
20051
- ` ${chalk26.bold(`${pct}% of surfaces match`)} (${d.common} shared, ${d.only_a.length} only in the first, ${d.only_b.length} only in the second)`
20380
+ ` ${chalk27.bold(`${pct}% of surfaces match`)} (${d.common} shared, ${d.only_a.length} only in the first, ${d.only_b.length} only in the second)`
20052
20381
  );
20053
20382
  if (d.only_a.length > 0) {
20054
20383
  console.log(`
20055
- ${chalk26.red("Only in the first")}`);
20384
+ ${chalk27.red("Only in the first")}`);
20056
20385
  for (const s of d.only_a) console.log(` ${s.key.padEnd(32)} ${s.label}`);
20057
20386
  }
20058
20387
  if (d.only_b.length > 0) {
20059
20388
  console.log(`
20060
- ${chalk26.green("Only in the second")}`);
20389
+ ${chalk27.green("Only in the second")}`);
20061
20390
  for (const s of d.only_b) console.log(` ${s.key.padEnd(32)} ${s.label}`);
20062
20391
  }
20063
20392
  if (d.changed_actions.length > 0) {
20064
20393
  console.log(
20065
20394
  `
20066
- ${chalk26.yellow(`Controls differ on ${d.changed_actions.length} shared surfaces`)}`
20395
+ ${chalk27.yellow(`Controls differ on ${d.changed_actions.length} shared surfaces`)}`
20067
20396
  );
20068
20397
  for (const c of d.changed_actions) {
20069
20398
  console.log(` ${c.key} ${c.label}`);
20070
- for (const x of c.only_a) console.log(chalk26.red(` - ${x}`));
20071
- for (const x of c.only_b) console.log(chalk26.green(` + ${x}`));
20399
+ for (const x of c.only_a) console.log(chalk27.red(` - ${x}`));
20400
+ for (const x of c.only_b) console.log(chalk27.green(` + ${x}`));
20072
20401
  }
20073
20402
  }
20074
20403
  }
@@ -20282,7 +20611,7 @@ __export(instructions_walk_exports, {
20282
20611
  });
20283
20612
  import { existsSync as existsSync12, readFileSync as readFileSync8 } from "fs";
20284
20613
  import { join as join9 } from "path";
20285
- import chalk27 from "chalk";
20614
+ import chalk28 from "chalk";
20286
20615
  function selfCommand() {
20287
20616
  const q = (p) => /[\s"'$]/.test(p) ? JSON.stringify(p) : p;
20288
20617
  return `${q(process.execPath)} ${q(process.argv[1] ?? "iamu")}`;
@@ -20654,40 +20983,40 @@ async function instructionsWalk(opts) {
20654
20983
  return;
20655
20984
  }
20656
20985
  console.log();
20657
- console.log(chalk27.bold(" Walk instructions"));
20658
- console.log(` ${chalk27.dim("scenario:")} ${sfm.slug}`);
20659
- console.log(` ${chalk27.dim("persona:")} ${pfm.name} (${pfm.role})`);
20660
- console.log(` ${chalk27.dim("outline:")} ${ofm.title}`);
20986
+ console.log(chalk28.bold(" Walk instructions"));
20987
+ console.log(` ${chalk28.dim("scenario:")} ${sfm.slug}`);
20988
+ console.log(` ${chalk28.dim("persona:")} ${pfm.name} (${pfm.role})`);
20989
+ console.log(` ${chalk28.dim("outline:")} ${ofm.title}`);
20661
20990
  if (sfm.state?.description || sfm.state?.approximation) {
20662
20991
  console.log(
20663
- ` ${chalk27.dim("state:")} ${sfm.state.description ? sfm.state.description : sfm.state.approximation ?? ""}`
20992
+ ` ${chalk28.dim("state:")} ${sfm.state.description ? sfm.state.description : sfm.state.approximation ?? ""}`
20664
20993
  );
20665
20994
  }
20666
- if (targetUrl) console.log(` ${chalk27.dim("target:")} ${targetUrl}`);
20995
+ if (targetUrl) console.log(` ${chalk28.dim("target:")} ${targetUrl}`);
20667
20996
  console.log(
20668
- ` ${chalk27.dim("access:")} ${projectAccess || personaAccess ? `${projectAccess ? "project" : ""}${projectAccess && personaAccess ? " + " : ""}${personaAccess ? "persona" : ""}` : "not recorded (walker would run as whoever is signed in)"}`
20997
+ ` ${chalk28.dim("access:")} ${projectAccess || personaAccess ? `${projectAccess ? "project" : ""}${projectAccess && personaAccess ? " + " : ""}${personaAccess ? "persona" : ""}` : "not recorded (walker would run as whoever is signed in)"}`
20669
20998
  );
20670
20999
  console.log(
20671
- ` ${chalk27.dim("dismissed:")} ${dismissedFacts.length} findings to skip`
21000
+ ` ${chalk28.dim("dismissed:")} ${dismissedFacts.length} findings to skip`
20672
21001
  );
20673
21002
  console.log(
20674
- ` ${chalk27.dim("guidance:")} ${guidance.length} tester guidance rule${guidance.length === 1 ? "" : "s"}`
21003
+ ` ${chalk28.dim("guidance:")} ${guidance.length} tester guidance rule${guidance.length === 1 ? "" : "s"}`
20675
21004
  );
20676
21005
  if (untestableBoundaries.length > 0) {
20677
21006
  console.log(
20678
- ` ${chalk27.dim("boundaries:")} ${untestableBoundaries.length} untestable boundaries to avoid`
21007
+ ` ${chalk28.dim("boundaries:")} ${untestableBoundaries.length} untestable boundaries to avoid`
20679
21008
  );
20680
21009
  }
20681
21010
  if (revisit.length > 0) {
20682
21011
  console.log(
20683
- ` ${chalk27.dim("re-check:")} ${revisit.length} place${revisit.length === 1 ? "" : "s"} where fixes await a re-run`
21012
+ ` ${chalk28.dim("re-check:")} ${revisit.length} place${revisit.length === 1 ? "" : "s"} where fixes await a re-run`
20684
21013
  );
20685
21014
  }
20686
21015
  console.log(
20687
- ` ${chalk27.dim("methodology:")} ${methodology ? "loaded" : "missing (run iamu update)"}`
21016
+ ` ${chalk28.dim("methodology:")} ${methodology ? "loaded" : "missing (run iamu update)"}`
20688
21017
  );
20689
21018
  console.log();
20690
- console.log(chalk27.dim(" Use --json to get the full instruction bundle."));
21019
+ console.log(chalk28.dim(" Use --json to get the full instruction bundle."));
20691
21020
  console.log();
20692
21021
  }
20693
21022
  var SCREEN;
@@ -20712,9 +21041,9 @@ __export(new_finding_exports, {
20712
21041
  newFinding: () => newFinding
20713
21042
  });
20714
21043
  import { randomUUID as randomUUID10 } from "crypto";
20715
- import { access, readFile as readFile6 } from "fs/promises";
20716
- import path26 from "path";
20717
- import chalk28 from "chalk";
21044
+ import { access, readFile as readFile7 } from "fs/promises";
21045
+ import path27 from "path";
21046
+ import chalk29 from "chalk";
20718
21047
  async function newFinding(opts) {
20719
21048
  const ctx = await resolveProject(opts);
20720
21049
  if (!ctx) return;
@@ -20780,7 +21109,7 @@ async function newFinding(opts) {
20780
21109
  }
20781
21110
  try {
20782
21111
  await access(
20783
- path26.join(runDirPath, "steps", `${String(n).padStart(3, "0")}.json`)
21112
+ path27.join(runDirPath, "steps", `${String(n).padStart(3, "0")}.json`)
20784
21113
  );
20785
21114
  } catch {
20786
21115
  commandError(
@@ -20794,8 +21123,8 @@ async function newFinding(opts) {
20794
21123
  let scenarioSlug = opts.scenario;
20795
21124
  if (!scenarioSlug) {
20796
21125
  try {
20797
- const manifestRaw = await readFile6(
20798
- path26.join(runDirPath, "walkthrough.json"),
21126
+ const manifestRaw = await readFile7(
21127
+ path27.join(runDirPath, "walkthrough.json"),
20799
21128
  "utf8"
20800
21129
  );
20801
21130
  const manifest = JSON.parse(manifestRaw);
@@ -20868,6 +21197,18 @@ async function newFinding(opts) {
20868
21197
  ].join("\n");
20869
21198
  try {
20870
21199
  const record = await writeEntity(projectRoot, "finding", frontmatter, body);
21200
+ sendLiveFinding(projectRoot, opts.run, {
21201
+ id,
21202
+ title: opts.title,
21203
+ type: opts.type,
21204
+ severity: opts.severity,
21205
+ ui_fact: uiFact,
21206
+ consequence,
21207
+ step_number: opts.step ? Number(opts.step) : void 0,
21208
+ task_impact: opts.taskImpact,
21209
+ confidence: opts.confidence
21210
+ }).catch(() => {
21211
+ });
20871
21212
  if (opts.json) {
20872
21213
  console.log(
20873
21214
  JSON.stringify(
@@ -20884,10 +21225,10 @@ async function newFinding(opts) {
20884
21225
  return;
20885
21226
  }
20886
21227
  console.log();
20887
- console.log(` ${symbols.success} Created finding: ${chalk28.cyan(slug)}`);
20888
- console.log(` ${chalk28.dim("path:")} ${record.path}`);
20889
- console.log(` ${chalk28.dim("id:")} ${id}`);
20890
- for (const w of warnings) console.log(` ${chalk28.yellow("!")} ${w}`);
21228
+ console.log(` ${symbols.success} Created finding: ${chalk29.cyan(slug)}`);
21229
+ console.log(` ${chalk29.dim("path:")} ${record.path}`);
21230
+ console.log(` ${chalk29.dim("id:")} ${id}`);
21231
+ for (const w of warnings) console.log(` ${chalk29.yellow("!")} ${w}`);
20891
21232
  console.log();
20892
21233
  } catch (err) {
20893
21234
  commandError(
@@ -20903,6 +21244,7 @@ var init_new_finding = __esm({
20903
21244
  init_dist();
20904
21245
  init_symbols();
20905
21246
  init_context4();
21247
+ init_live_run_client();
20906
21248
  }
20907
21249
  });
20908
21250
 
@@ -20913,7 +21255,7 @@ __export(view_results_exports, {
20913
21255
  promptViewResults: () => promptViewResults
20914
21256
  });
20915
21257
  import { isCancel as isCancel4, select as select4 } from "@clack/prompts";
20916
- import chalk29 from "chalk";
21258
+ import chalk30 from "chalk";
20917
21259
  function launchCloudDashboard(config, runId) {
20918
21260
  const cloudRunId = runId ? toCloudRunUuid(runId) : void 0;
20919
21261
  const url = getCloudDashboardUrl(
@@ -20922,7 +21264,7 @@ function launchCloudDashboard(config, runId) {
20922
21264
  cloudRunId
20923
21265
  );
20924
21266
  console.log();
20925
- console.log(` ${symbols.success} Opening Iamu Cloud: ${chalk29.cyan(url)}
21267
+ console.log(` ${symbols.success} Opening Iamu Cloud: ${chalk30.cyan(url)}
20926
21268
  `);
20927
21269
  openBrowser(url);
20928
21270
  }
@@ -20991,8 +21333,8 @@ __export(evaluate_exports, {
20991
21333
  evaluateRecord: () => evaluateRecord
20992
21334
  });
20993
21335
  import { promises as fs29 } from "fs";
20994
- import path27 from "path";
20995
- import chalk30 from "chalk";
21336
+ import path28 from "path";
21337
+ import chalk31 from "chalk";
20996
21338
  import { z as z25 } from "zod";
20997
21339
  function formatIssues(error) {
20998
21340
  return error.issues.map(
@@ -21022,7 +21364,7 @@ async function evaluate(runId, opts) {
21022
21364
  const resolved = await resolveProjectAndRunDir(runId, opts);
21023
21365
  if (!resolved) return;
21024
21366
  const { projectRoot, runDirPath } = resolved;
21025
- const canonicalPath = path27.join(runDirPath, "canonical.json");
21367
+ const canonicalPath = path28.join(runDirPath, "canonical.json");
21026
21368
  let canonical;
21027
21369
  try {
21028
21370
  const raw = await fs29.readFile(canonicalPath, "utf8");
@@ -21081,15 +21423,15 @@ async function evaluate(runId, opts) {
21081
21423
  )
21082
21424
  };
21083
21425
  const prompt = composeJudgePrompt(input);
21084
- const promptFilePath = opts?.promptFile ?? path27.join(runDirPath, "judge_prompt.md");
21426
+ const promptFilePath = opts?.promptFile ?? path28.join(runDirPath, "judge_prompt.md");
21085
21427
  await fs29.writeFile(promptFilePath, prompt, "utf8");
21086
21428
  if (opts?.json) {
21087
21429
  console.log(
21088
21430
  JSON.stringify(
21089
21431
  {
21090
21432
  ...input,
21091
- prompt_file: path27.relative(projectRoot, promptFilePath),
21092
- prompt_file_abs: path27.resolve(promptFilePath),
21433
+ prompt_file: path28.relative(projectRoot, promptFilePath),
21434
+ prompt_file_abs: path28.resolve(promptFilePath),
21093
21435
  judge_prompt: prompt
21094
21436
  },
21095
21437
  null,
@@ -21104,7 +21446,9 @@ async function evaluateRecord(runId, opts) {
21104
21446
  const resolved = await resolveProjectAndRunDir(runId, opts);
21105
21447
  if (!resolved) return;
21106
21448
  const { projectRoot, runDirPath } = resolved;
21107
- const canonicalPath = path27.join(runDirPath, "canonical.json");
21449
+ sendLivePhase(projectRoot, runId, "judging").catch(() => {
21450
+ });
21451
+ const canonicalPath = path28.join(runDirPath, "canonical.json");
21108
21452
  let canonical;
21109
21453
  try {
21110
21454
  const raw = await fs29.readFile(canonicalPath, "utf8");
@@ -21172,8 +21516,8 @@ ${formatIssues(fileResult.error)}`,
21172
21516
  overall: inputVerdicts.overall
21173
21517
  });
21174
21518
  const reportContent = renderCanonicalMarkdown(canonicalForReport);
21175
- const verdictsPath = path27.join(runDirPath, "verdicts.json");
21176
- const reportPath = path27.join(runDirPath, "report.md");
21519
+ const verdictsPath = path28.join(runDirPath, "verdicts.json");
21520
+ const reportPath = path28.join(runDirPath, "report.md");
21177
21521
  await Promise.all([
21178
21522
  atomicWriteFile(
21179
21523
  verdictsPath,
@@ -21193,8 +21537,8 @@ ${formatIssues(fileResult.error)}`,
21193
21537
  JSON.stringify(
21194
21538
  {
21195
21539
  runId,
21196
- verdictsPath: path27.relative(projectRoot, verdictsPath),
21197
- reportPath: path27.relative(projectRoot, reportPath),
21540
+ verdictsPath: path28.relative(projectRoot, verdictsPath),
21541
+ reportPath: path28.relative(projectRoot, reportPath),
21198
21542
  verdictsCount: validatedVerdicts.length,
21199
21543
  linkedCount: linked.length,
21200
21544
  ...cloudInfo ? { cloud: cloudInfo } : {}
@@ -21207,18 +21551,18 @@ ${formatIssues(fileResult.error)}`,
21207
21551
  }
21208
21552
  console.log();
21209
21553
  console.log(
21210
- ` ${symbols.success} Recorded ${validatedVerdicts.length} verdicts for run ${chalk30.cyan(runId)}`
21554
+ ` ${symbols.success} Recorded ${validatedVerdicts.length} verdicts for run ${chalk31.cyan(runId)}`
21211
21555
  );
21212
21556
  if (linked.length > 0) {
21213
21557
  console.log(
21214
- ` ${chalk30.dim("linked:")} ${linked.length} finding${linked.length === 1 ? "" : "s"} to the human test${linked.length === 1 ? "" : "s"} citing ${linked.length === 1 ? "it" : "them"}`
21558
+ ` ${chalk31.dim("linked:")} ${linked.length} finding${linked.length === 1 ? "" : "s"} to the human test${linked.length === 1 ? "" : "s"} citing ${linked.length === 1 ? "it" : "them"}`
21215
21559
  );
21216
21560
  }
21217
21561
  console.log(
21218
- ` ${chalk30.dim("verdicts:")} ${path27.relative(projectRoot, verdictsPath)}`
21562
+ ` ${chalk31.dim("verdicts:")} ${path28.relative(projectRoot, verdictsPath)}`
21219
21563
  );
21220
21564
  console.log(
21221
- ` ${chalk30.dim("report:")} ${path27.relative(projectRoot, reportPath)}`
21565
+ ` ${chalk31.dim("report:")} ${path28.relative(projectRoot, reportPath)}`
21222
21566
  );
21223
21567
  printCloudRunInfo(cloudInfo);
21224
21568
  await promptViewResults(projectRoot, { ...opts, runId });
@@ -21232,6 +21576,7 @@ var init_evaluate = __esm({
21232
21576
  init_symbols();
21233
21577
  init_cloud_push();
21234
21578
  init_context4();
21579
+ init_live_run_client();
21235
21580
  init_view_results();
21236
21581
  verdictValueSchema = z25.enum(["yes", "partial", "no", "not_applicable"]);
21237
21582
  idList = z25.array(z25.string()).optional();
@@ -21283,18 +21628,20 @@ __export(complete_exports, {
21283
21628
  validateCanonicalWalkthrough: () => validateCanonicalWalkthrough
21284
21629
  });
21285
21630
  import { promises as fs30 } from "fs";
21286
- import path28 from "path";
21287
- import chalk31 from "chalk";
21631
+ import path29 from "path";
21632
+ import chalk32 from "chalk";
21288
21633
  async function complete(runId, opts) {
21289
21634
  const run = await loadRun(runId, opts);
21290
21635
  if (!run) return;
21636
+ sendLivePhase(run.projectRoot, runId, "completing").catch(() => {
21637
+ });
21291
21638
  if (run.manifest.status === "completed" && !opts?.force) {
21292
21639
  await reportAlreadyCompleted(run, opts);
21293
21640
  return;
21294
21641
  }
21295
21642
  if (!opts?.json) {
21296
21643
  console.log();
21297
- console.log(chalk31.bold(" Assembling canonical JSON\u2026"));
21644
+ console.log(chalk32.bold(" Assembling canonical JSON\u2026"));
21298
21645
  }
21299
21646
  const provenanceAudit = auditStepProvenance(
21300
21647
  await readStepsForRun(run.projectRoot, runId)
@@ -21308,7 +21655,7 @@ async function complete(runId, opts) {
21308
21655
  let judgeReported;
21309
21656
  try {
21310
21657
  const verdictsRaw = await fs30.readFile(
21311
- path28.join(run.runDirPath, "verdicts.json"),
21658
+ path29.join(run.runDirPath, "verdicts.json"),
21312
21659
  "utf8"
21313
21660
  );
21314
21661
  const parsed = JSON.parse(verdictsRaw);
@@ -21365,7 +21712,7 @@ async function loadRun(runId, opts) {
21365
21712
  commandError(`Run not found: ${runId}`, opts);
21366
21713
  return null;
21367
21714
  }
21368
- const manifestPath = path28.join(runDirPath, "walkthrough.json");
21715
+ const manifestPath = path29.join(runDirPath, "walkthrough.json");
21369
21716
  let manifest;
21370
21717
  try {
21371
21718
  manifest = JSON.parse(
@@ -21382,7 +21729,7 @@ async function reportAlreadyCompleted(run, opts) {
21382
21729
  if (opts?.json) {
21383
21730
  try {
21384
21731
  const raw = await fs30.readFile(
21385
- path28.join(run.runDirPath, "canonical.json"),
21732
+ path29.join(run.runDirPath, "canonical.json"),
21386
21733
  "utf8"
21387
21734
  );
21388
21735
  console.log(raw.trim());
@@ -21402,18 +21749,18 @@ async function reportAlreadyCompleted(run, opts) {
21402
21749
  return;
21403
21750
  }
21404
21751
  console.log();
21405
- console.log(chalk31.bold(" Run: ") + chalk31.cyan(runId));
21406
- console.log(` status ${chalk31.green("completed")}`);
21752
+ console.log(chalk32.bold(" Run: ") + chalk32.cyan(runId));
21753
+ console.log(` status ${chalk32.green("completed")}`);
21407
21754
  if (manifest.completed_at) {
21408
- console.log(` completed ${chalk31.dim(manifest.completed_at)}`);
21755
+ console.log(` completed ${chalk32.dim(manifest.completed_at)}`);
21409
21756
  }
21410
21757
  const viewUrl = await pushedRunUrl(run.projectRoot, runId);
21411
21758
  if (viewUrl) {
21412
- console.log(` view ${chalk31.underline(viewUrl)}`);
21759
+ console.log(` view ${chalk32.underline(viewUrl)}`);
21413
21760
  }
21414
21761
  console.log();
21415
21762
  console.log(
21416
- chalk31.dim(
21763
+ chalk32.dim(
21417
21764
  " Already completed \u2014 nothing to do. Use --force to reassemble the report."
21418
21765
  )
21419
21766
  );
@@ -21429,13 +21776,13 @@ function reportStrictProvenanceFailure(audit, opts) {
21429
21776
  }
21430
21777
  console.error();
21431
21778
  console.error(
21432
- chalk31.red(` ${symbols.error} Strict provenance audit failed:`)
21779
+ chalk32.red(` ${symbols.error} Strict provenance audit failed:`)
21433
21780
  );
21434
21781
  for (const w of audit.warnings) {
21435
- console.error(chalk31.red(` \u2022 ${w}`));
21782
+ console.error(chalk32.red(` \u2022 ${w}`));
21436
21783
  }
21437
21784
  console.error(
21438
- chalk31.dim(
21785
+ chalk32.dim(
21439
21786
  " Run was flagged as synthetic / scripted. Remove --strict-provenance to complete anyway."
21440
21787
  )
21441
21788
  );
@@ -21476,41 +21823,41 @@ function completeJsonPayload(canonical, extras) {
21476
21823
  function printCompletionSummary(run, completedAt, assembled, extras, provenanceAudit) {
21477
21824
  const { runId, projectRoot, manifest } = run;
21478
21825
  const { canonical } = assembled;
21479
- const count = (n) => n === 0 ? chalk31.dim("0") : chalk31.cyan(String(n));
21480
- console.log(chalk31.bold(" Run: ") + chalk31.cyan(runId));
21481
- console.log(` scenario ${chalk31.dim(manifest.scenario_slug)}`);
21482
- console.log(` url ${chalk31.dim(manifest.target_url)}`);
21826
+ const count = (n) => n === 0 ? chalk32.dim("0") : chalk32.cyan(String(n));
21827
+ console.log(chalk32.bold(" Run: ") + chalk32.cyan(runId));
21828
+ console.log(` scenario ${chalk32.dim(manifest.scenario_slug)}`);
21829
+ console.log(` url ${chalk32.dim(manifest.target_url)}`);
21483
21830
  if (manifest.environment) {
21484
- console.log(` env ${chalk31.dim(manifest.environment)}`);
21831
+ console.log(` env ${chalk32.dim(manifest.environment)}`);
21485
21832
  }
21486
21833
  if (manifest.build) {
21487
- console.log(` build ${chalk31.dim(formatBuild(manifest.build))}`);
21834
+ console.log(` build ${chalk32.dim(formatBuild(manifest.build))}`);
21488
21835
  }
21489
21836
  if (manifest.viewport) {
21490
- console.log(` device ${chalk31.dim(formatViewport(manifest.viewport))}`);
21837
+ console.log(` device ${chalk32.dim(formatViewport(manifest.viewport))}`);
21491
21838
  }
21492
- console.log(` status ${chalk31.green("completed")}`);
21839
+ console.log(` status ${chalk32.green("completed")}`);
21493
21840
  console.log(` findings ${count(canonical.findings.length)}`);
21494
21841
  console.log(` steps ${count(canonical.steps.length)}`);
21495
- console.log(` started ${chalk31.dim(manifest.created_at)}`);
21496
- console.log(` completed ${chalk31.dim(completedAt)}`);
21842
+ console.log(` started ${chalk32.dim(manifest.created_at)}`);
21843
+ console.log(` completed ${chalk32.dim(completedAt)}`);
21497
21844
  const models = manifest.models;
21498
21845
  if (models?.velocity_sec_per_step != null) {
21499
21846
  console.log(
21500
- ` velocity ${chalk31.cyan(`~${models.velocity_sec_per_step}s/step`)} ${chalk31.dim(`(${models.total_duration_sec}s total)`)}`
21847
+ ` velocity ${chalk32.cyan(`~${models.velocity_sec_per_step}s/step`)} ${chalk32.dim(`(${models.total_duration_sec}s total)`)}`
21501
21848
  );
21502
21849
  }
21503
21850
  if (models && (models.walker || models.judge || models.matcher)) {
21504
21851
  const w = models.walker_reported ? `${models.walker} (${models.walker_reported})` : models.walker ?? "fast";
21505
21852
  const j = models.judge_reported ? `${models.judge} (${models.judge_reported})` : models.judge ?? "thorough";
21506
- console.log(` models ${chalk31.dim(`walker: ${w} \xB7 judge: ${j}`)}`);
21853
+ console.log(` models ${chalk32.dim(`walker: ${w} \xB7 judge: ${j}`)}`);
21507
21854
  }
21508
21855
  console.log();
21509
21856
  console.log(
21510
- ` ${chalk31.dim("canonical:")} ${chalk31.dim(path28.relative(projectRoot, assembled.canonicalPath))}`
21857
+ ` ${chalk32.dim("canonical:")} ${chalk32.dim(path29.relative(projectRoot, assembled.canonicalPath))}`
21511
21858
  );
21512
21859
  console.log(
21513
- ` ${chalk31.dim("report:")} ${chalk31.dim(path28.relative(projectRoot, assembled.reportPath))}`
21860
+ ` ${chalk32.dim("report:")} ${chalk32.dim(path29.relative(projectRoot, assembled.reportPath))}`
21514
21861
  );
21515
21862
  if (extras.viewportWarning) {
21516
21863
  console.log();
@@ -21518,7 +21865,7 @@ function printCompletionSummary(run, completedAt, assembled, extras, provenanceA
21518
21865
  }
21519
21866
  if (extras.codeWarning) {
21520
21867
  console.log();
21521
- console.log(` ${chalk31.yellow("!")} ${extras.codeWarning}`);
21868
+ console.log(` ${chalk32.yellow("!")} ${extras.codeWarning}`);
21522
21869
  }
21523
21870
  if (extras.revisit) printRevisit(extras.revisit);
21524
21871
  if (assembled.verification) printVerification(assembled.verification);
@@ -21530,13 +21877,13 @@ function printProvenanceWarnings(audit) {
21530
21877
  if (audit.warnings.length === 0) return;
21531
21878
  console.log();
21532
21879
  console.log(
21533
- ` ${symbols.warning} ${chalk31.yellow("Step provenance audit flagged suspicious timing:")}`
21880
+ ` ${symbols.warning} ${chalk32.yellow("Step provenance audit flagged suspicious timing:")}`
21534
21881
  );
21535
21882
  for (const w of audit.warnings) {
21536
- console.log(` ${chalk31.dim("\u2022")} ${w}`);
21883
+ console.log(` ${chalk32.dim("\u2022")} ${w}`);
21537
21884
  }
21538
21885
  console.log(
21539
- chalk31.dim(
21886
+ chalk32.dim(
21540
21887
  " Run appears to be programmatically batch-generated rather than an interactive walkthrough."
21541
21888
  )
21542
21889
  );
@@ -21568,7 +21915,7 @@ function screenshotFitsViewport(width, expected) {
21568
21915
  }
21569
21916
  async function screenshotSizeWarning(runDirPath, viewport) {
21570
21917
  if (!viewport) return null;
21571
- const dir = path28.join(runDirPath, "screenshots");
21918
+ const dir = path29.join(runDirPath, "screenshots");
21572
21919
  let first;
21573
21920
  try {
21574
21921
  first = (await fs30.readdir(dir)).filter((f) => f.toLowerCase().endsWith(".png")).sort((a, b) => a.localeCompare(b, void 0, { numeric: true }))[0];
@@ -21578,7 +21925,7 @@ async function screenshotSizeWarning(runDirPath, viewport) {
21578
21925
  if (!first) return null;
21579
21926
  let size = null;
21580
21927
  try {
21581
- const handle = await fs30.open(path28.join(dir, first), "r");
21928
+ const handle = await fs30.open(path29.join(dir, first), "r");
21582
21929
  try {
21583
21930
  const head = Buffer.alloc(24);
21584
21931
  const { bytesRead } = await handle.read(head, 0, 24, 0);
@@ -21595,7 +21942,7 @@ async function screenshotSizeWarning(runDirPath, viewport) {
21595
21942
  async function readWalkerSummary(runDirPath) {
21596
21943
  try {
21597
21944
  const data = JSON.parse(
21598
- await fs30.readFile(path28.join(runDirPath, "summary.json"), "utf8")
21945
+ await fs30.readFile(path29.join(runDirPath, "summary.json"), "utf8")
21599
21946
  );
21600
21947
  const strings = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string" && x.trim() !== "") : void 0;
21601
21948
  const model = typeof data.model === "string" && data.model.trim() !== "" ? data.model.trim() : void 0;
@@ -21704,7 +22051,7 @@ function validateCanonicalWalkthrough(canonical) {
21704
22051
  async function applyRecordedVerdicts(canonical, runDirPath) {
21705
22052
  try {
21706
22053
  const recorded = JSON.parse(
21707
- await fs30.readFile(path28.join(runDirPath, "verdicts.json"), "utf8")
22054
+ await fs30.readFile(path29.join(runDirPath, "verdicts.json"), "utf8")
21708
22055
  );
21709
22056
  if (Array.isArray(recorded.verdicts)) {
21710
22057
  return applyVerdicts(canonical, recorded);
@@ -21714,7 +22061,7 @@ async function applyRecordedVerdicts(canonical, runDirPath) {
21714
22061
  return canonical;
21715
22062
  }
21716
22063
  async function persistCanonical(runDirPath, canonical) {
21717
- const canonicalPath = path28.join(runDirPath, "canonical.json");
22064
+ const canonicalPath = path29.join(runDirPath, "canonical.json");
21718
22065
  await atomicWriteFile(
21719
22066
  canonicalPath,
21720
22067
  `${JSON.stringify(canonical, null, 2)}
@@ -21723,7 +22070,7 @@ async function persistCanonical(runDirPath, canonical) {
21723
22070
  return canonicalPath;
21724
22071
  }
21725
22072
  async function persistReport(runDirPath, canonical) {
21726
- const reportPath = path28.join(runDirPath, "report.md");
22073
+ const reportPath = path29.join(runDirPath, "report.md");
21727
22074
  await atomicWriteFile(reportPath, renderCanonicalMarkdown(canonical));
21728
22075
  return reportPath;
21729
22076
  }
@@ -21823,17 +22170,17 @@ function placeLabel(p) {
21823
22170
  function printRevisit(r) {
21824
22171
  const missed = r.places.filter((p) => !p.reached);
21825
22172
  console.log();
21826
- const head = ` ${chalk31.bold("Re-check places:")} reached ${r.reached} of ${r.requested}`;
22173
+ const head = ` ${chalk32.bold("Re-check places:")} reached ${r.reached} of ${r.requested}`;
21827
22174
  if (missed.length === 0) {
21828
- console.log(`${head} ${chalk31.green("\u2713")}`);
22175
+ console.log(`${head} ${chalk32.green("\u2713")}`);
21829
22176
  return;
21830
22177
  }
21831
22178
  console.log(`${head} \u2014 not reached:`);
21832
22179
  for (const p of missed) {
21833
- console.log(` ${chalk31.yellow("\u25CB")} ${placeLabel(p)}`);
22180
+ console.log(` ${chalk32.yellow("\u25CB")} ${placeLabel(p)}`);
21834
22181
  }
21835
22182
  console.log(
21836
- chalk31.dim(
22183
+ chalk32.dim(
21837
22184
  " Fixes there stay awaiting a re-run until a walk gets there."
21838
22185
  )
21839
22186
  );
@@ -21841,7 +22188,7 @@ function printRevisit(r) {
21841
22188
  function printVerification(verification) {
21842
22189
  console.log();
21843
22190
  console.log(
21844
- chalk31.bold(" Since this scenario's last run") + chalk31.dim(` (${verification.baseline_run_id.slice(0, 30)}\u2026)`) + chalk31.bold(":")
22191
+ chalk32.bold(" Since this scenario's last run") + chalk32.dim(` (${verification.baseline_run_id.slice(0, 30)}\u2026)`) + chalk32.bold(":")
21845
22192
  );
21846
22193
  if (verification.resolved.length > 0) {
21847
22194
  console.log(
@@ -21850,7 +22197,7 @@ function printVerification(verification) {
21850
22197
  }
21851
22198
  if (verification.not_observed.length > 0) {
21852
22199
  console.log(
21853
- ` ${symbols.pending} ${verification.not_observed.length} not seen this run ${chalk31.dim("(not evidence of a fix)")}`
22200
+ ` ${symbols.pending} ${verification.not_observed.length} not seen this run ${chalk32.dim("(not evidence of a fix)")}`
21854
22201
  );
21855
22202
  }
21856
22203
  if (verification.persists.length > 0) {
@@ -21879,6 +22226,7 @@ var init_complete = __esm({
21879
22226
  init_cloud_push();
21880
22227
  init_context4();
21881
22228
  init_evaluate();
22229
+ init_live_run_client();
21882
22230
  init_worktree_state();
21883
22231
  init_start_run();
21884
22232
  init_view_results();
@@ -21892,13 +22240,13 @@ __export(match_exports, {
21892
22240
  matchRecord: () => matchRecord
21893
22241
  });
21894
22242
  import { promises as fs31 } from "fs";
21895
- import path29 from "path";
21896
- import chalk32 from "chalk";
22243
+ import path30 from "path";
22244
+ import chalk33 from "chalk";
21897
22245
  async function completedManifest2(runDirPath, runId, opts) {
21898
22246
  let manifest;
21899
22247
  try {
21900
22248
  manifest = JSON.parse(
21901
- await fs31.readFile(path29.join(runDirPath, "walkthrough.json"), "utf8")
22249
+ await fs31.readFile(path30.join(runDirPath, "walkthrough.json"), "utf8")
21902
22250
  );
21903
22251
  } catch {
21904
22252
  commandError(`Run not found: ${runId}`, opts);
@@ -21927,7 +22275,7 @@ async function match(runId, opts) {
21927
22275
  );
21928
22276
  const needed = input.current.length > 0 && (input.prior.length > 0 || (input.guidance ?? []).length > 0);
21929
22277
  const prompt = needed ? composeMatchPrompt(input) : null;
21930
- const promptFilePath = opts?.promptFile ?? path29.join(runDirPath, "match_prompt.md");
22278
+ const promptFilePath = opts?.promptFile ?? path30.join(runDirPath, "match_prompt.md");
21931
22279
  if (prompt) {
21932
22280
  await fs31.writeFile(promptFilePath, prompt, "utf8");
21933
22281
  } else {
@@ -21942,8 +22290,8 @@ async function match(runId, opts) {
21942
22290
  {
21943
22291
  ...input,
21944
22292
  needed,
21945
- prompt_file: prompt ? path29.relative(ctx.projectRoot, promptFilePath) : null,
21946
- prompt_file_abs: prompt ? path29.resolve(promptFilePath) : null,
22293
+ prompt_file: prompt ? path30.relative(ctx.projectRoot, promptFilePath) : null,
22294
+ prompt_file_abs: prompt ? path30.resolve(promptFilePath) : null,
21947
22295
  match_prompt: prompt
21948
22296
  },
21949
22297
  null,
@@ -21954,7 +22302,7 @@ async function match(runId, opts) {
21954
22302
  }
21955
22303
  if (!prompt) {
21956
22304
  console.log(
21957
- chalk32.dim(
22305
+ chalk33.dim(
21958
22306
  " No earlier findings or tester guidance for this scenario to match against \u2014 nothing to do."
21959
22307
  )
21960
22308
  );
@@ -21966,6 +22314,8 @@ async function matchRecord(runId, opts) {
21966
22314
  const resolved = await resolveProjectAndRunDir(runId, opts);
21967
22315
  if (!resolved) return;
21968
22316
  const { projectRoot, runDirPath } = resolved;
22317
+ sendLivePhase(projectRoot, runId, "matching").catch(() => {
22318
+ });
21969
22319
  const manifest = await completedManifest2(runDirPath, runId, opts);
21970
22320
  if (!manifest) return;
21971
22321
  let answer;
@@ -22011,17 +22361,17 @@ async function matchRecord(runId, opts) {
22011
22361
  }
22012
22362
  console.log();
22013
22363
  console.log(
22014
- ` ${chalk32.green("\u2713")} Matched ${result.linked} finding${result.linked === 1 ? "" : "s"} to earlier ones, ${result.new} first seen, ${result.rechecked_fixed} earlier re-checked fixed`
22364
+ ` ${chalk33.green("\u2713")} Matched ${result.linked} finding${result.linked === 1 ? "" : "s"} to earlier ones, ${result.new} first seen, ${result.rechecked_fixed} earlier re-checked fixed`
22015
22365
  );
22016
22366
  if (result.suppressed > 0) {
22017
22367
  console.log(
22018
- ` ${chalk32.yellow("!")} ${result.suppressed} finding${result.suppressed === 1 ? "" : "s"} match tester guidance (flagged with suppressed_by_guidance \u2014 dismiss them in triage if the rule holds)`
22368
+ ` ${chalk33.yellow("!")} ${result.suppressed} finding${result.suppressed === 1 ? "" : "s"} match tester guidance (flagged with suppressed_by_guidance \u2014 dismiss them in triage if the rule holds)`
22019
22369
  );
22020
22370
  }
22021
22371
  if (verification) printVerification(verification);
22022
22372
  console.log();
22023
22373
  console.log(
22024
- chalk32.dim(" Run `iamu sync` to push the linked findings to the cloud.")
22374
+ chalk33.dim(" Run `iamu sync` to push the linked findings to the cloud.")
22025
22375
  );
22026
22376
  console.log();
22027
22377
  }
@@ -22032,6 +22382,7 @@ var init_match = __esm({
22032
22382
  init_dist();
22033
22383
  init_complete();
22034
22384
  init_context4();
22385
+ init_live_run_client();
22035
22386
  }
22036
22387
  });
22037
22388
 
@@ -22042,7 +22393,7 @@ __export(prune_exports, {
22042
22393
  prune: () => prune
22043
22394
  });
22044
22395
  import { confirm, isCancel as isCancel5 } from "@clack/prompts";
22045
- import chalk33 from "chalk";
22396
+ import chalk34 from "chalk";
22046
22397
  function formatBytes(bytes) {
22047
22398
  if (bytes <= 0) return "0 B";
22048
22399
  if (bytes < 1024) return `${bytes} B`;
@@ -22088,7 +22439,7 @@ async function prune(opts = {}) {
22088
22439
  });
22089
22440
  if (preview.prunedRuns.length === 0) {
22090
22441
  console.log(
22091
- chalk33.dim(" No runs match the pruning criteria. Nothing to prune.")
22442
+ chalk34.dim(" No runs match the pruning criteria. Nothing to prune.")
22092
22443
  );
22093
22444
  return preview;
22094
22445
  }
@@ -22097,7 +22448,7 @@ async function prune(opts = {}) {
22097
22448
  message: `Prune ${mode} ${preview.prunedRuns.length} run(s) and reclaim ${formatBytes(preview.totalBytesReclaimed)}?`
22098
22449
  });
22099
22450
  if (isCancel5(confirmed) || !confirmed) {
22100
- console.log(chalk33.yellow(" Pruning cancelled."));
22451
+ console.log(chalk34.yellow(" Pruning cancelled."));
22101
22452
  return;
22102
22453
  }
22103
22454
  }
@@ -22108,14 +22459,14 @@ async function prune(opts = {}) {
22108
22459
  }
22109
22460
  if (result.dryRun) {
22110
22461
  console.log(
22111
- chalk33.cyan(
22462
+ chalk34.cyan(
22112
22463
  `
22113
22464
  [DRY RUN] Would prune ${result.prunedRuns.length} of ${result.totalRunsScanned} run(s):`
22114
22465
  )
22115
22466
  );
22116
22467
  } else {
22117
22468
  console.log(
22118
- chalk33.bold(
22469
+ chalk34.bold(
22119
22470
  `
22120
22471
  ${symbols.success} Pruned ${result.prunedRuns.length} of ${result.totalRunsScanned} run(s):`
22121
22472
  )
@@ -22123,18 +22474,18 @@ async function prune(opts = {}) {
22123
22474
  }
22124
22475
  if (result.prunedRuns.length === 0) {
22125
22476
  console.log(
22126
- chalk33.dim(" No runs matched the pruning criteria. Nothing pruned.")
22477
+ chalk34.dim(" No runs matched the pruning criteria. Nothing pruned.")
22127
22478
  );
22128
22479
  } else {
22129
22480
  for (const run of result.prunedRuns) {
22130
22481
  const mode = run.fullyDeleted ? "removed" : "screenshots purged";
22131
22482
  const count = run.screenshotsDeleted > 0 ? `${run.screenshotsDeleted} screenshots, ` : "";
22132
22483
  console.log(
22133
- ` ${chalk33.dim("\u2022")} ${chalk33.bold(run.runId)} ${chalk33.dim(`(${run.scenarioSlug ?? "unknown scenario"})`)}: ${chalk33.yellow(formatBytes(run.bytesReclaimed))} (${count}${mode})`
22484
+ ` ${chalk34.dim("\u2022")} ${chalk34.bold(run.runId)} ${chalk34.dim(`(${run.scenarioSlug ?? "unknown scenario"})`)}: ${chalk34.yellow(formatBytes(run.bytesReclaimed))} (${count}${mode})`
22134
22485
  );
22135
22486
  }
22136
22487
  console.log(
22137
- chalk33.dim(
22488
+ chalk34.dim(
22138
22489
  `
22139
22490
  Total reclaimed: ${formatBytes(result.totalBytesReclaimed)} (${result.totalScreenshotsDeleted} screenshots deleted)
22140
22491
  `
@@ -22323,9 +22674,9 @@ function registerProjectCommands(program) {
22323
22674
  "after",
22324
22675
  "\nExamples:\n $ iamu validate --all\n $ iamu validate --all --fix --dry-run\n $ iamu validate iamu/personas/maria.md"
22325
22676
  ).action(
22326
- async (path30, opts) => {
22677
+ async (path31, opts) => {
22327
22678
  const { validate: validate2 } = await Promise.resolve().then(() => (init_validate(), validate_exports));
22328
- await validate2(path30, opts);
22679
+ await validate2(path31, opts);
22329
22680
  }
22330
22681
  );
22331
22682
  program.command("update").helpGroup("Project:").description("Update and repair agent skills and prompts to latest version").option(
@@ -22626,7 +22977,7 @@ function registerAllCommands(program) {
22626
22977
 
22627
22978
  // src/ui/panic.ts
22628
22979
  init_logger();
22629
- import chalk34 from "chalk";
22980
+ import chalk35 from "chalk";
22630
22981
  var handlersRegistered = false;
22631
22982
  var customSigintHandler = null;
22632
22983
  function registerSigintCleanup(handler) {
@@ -22638,17 +22989,17 @@ function registerSigintCleanup(handler) {
22638
22989
  function logFatalAndExit(title, errOrReason) {
22639
22990
  process.stderr.write("\x1B[?25h");
22640
22991
  if (isVerbose()) {
22641
- console.error(chalk34.red(`
22992
+ console.error(chalk35.red(`
22642
22993
  ${title}:`));
22643
22994
  console.error(
22644
22995
  errOrReason instanceof Error ? errOrReason.stack || errOrReason : errOrReason
22645
22996
  );
22646
22997
  } else {
22647
22998
  const msg = errOrReason instanceof Error ? errOrReason.message : String(errOrReason);
22648
- console.error(chalk34.red(`
22999
+ console.error(chalk35.red(`
22649
23000
  Fatal Error: ${msg}`));
22650
23001
  console.error(
22651
- chalk34.dim(
23002
+ chalk35.dim(
22652
23003
  " Run with --verbose or DEBUG=1 to view the full stack trace.\n"
22653
23004
  )
22654
23005
  );
@@ -22667,7 +23018,7 @@ function setupProcessHandlers() {
22667
23018
  }
22668
23019
  process.exit(130);
22669
23020
  } else {
22670
- console.error(chalk34.dim("\n Operation cancelled."));
23021
+ console.error(chalk35.dim("\n Operation cancelled."));
22671
23022
  process.exit(130);
22672
23023
  }
22673
23024
  });