@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/bin.js +872 -521
- package/dist/commands/live-run-client.d.ts +127 -0
- package/dist/commands/step.d.ts +1 -0
- package/dist/index.js +938 -587
- package/dist/templates/prompts/walk.md +2 -0
- package/dist/templates/skills/iamu-run.md +13 -1
- package/dist/templates/skills/iamu-setup.md +219 -153
- package/package.json +3 -3
package/dist/bin.js
CHANGED
|
@@ -5364,9 +5364,9 @@ function pidIsDead(rec) {
|
|
|
5364
5364
|
async function isStale(lockPath, rec, staleMs, now) {
|
|
5365
5365
|
if (rec === null) {
|
|
5366
5366
|
try {
|
|
5367
|
-
const
|
|
5368
|
-
if (
|
|
5369
|
-
const mtime =
|
|
5367
|
+
const stat3 = await fs5.stat(lockPath);
|
|
5368
|
+
if (stat3.size === 0) {
|
|
5369
|
+
const mtime = stat3.birthtimeMs && stat3.birthtimeMs > 0 ? stat3.birthtimeMs : stat3.mtimeMs;
|
|
5370
5370
|
if (now - mtime <= staleMs) {
|
|
5371
5371
|
return false;
|
|
5372
5372
|
}
|
|
@@ -12112,15 +12112,15 @@ function resolveApiUrl(configured) {
|
|
|
12112
12112
|
assertSecureApiUrl(url, configured ? "API URL" : "IAMU_API_URL");
|
|
12113
12113
|
return url;
|
|
12114
12114
|
}
|
|
12115
|
-
function parseStore(raw,
|
|
12115
|
+
function parseStore(raw, path31) {
|
|
12116
12116
|
let parsed;
|
|
12117
12117
|
try {
|
|
12118
12118
|
parsed = JSON.parse(raw);
|
|
12119
12119
|
} catch (err) {
|
|
12120
|
-
throw new CredentialsFileError(
|
|
12120
|
+
throw new CredentialsFileError(path31, "not valid JSON", err);
|
|
12121
12121
|
}
|
|
12122
12122
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
12123
|
-
throw new CredentialsFileError(
|
|
12123
|
+
throw new CredentialsFileError(path31, "expected a JSON object");
|
|
12124
12124
|
}
|
|
12125
12125
|
return parsed;
|
|
12126
12126
|
}
|
|
@@ -12128,26 +12128,26 @@ function isNotFound(err) {
|
|
|
12128
12128
|
return typeof err === "object" && err !== null && err.code === "ENOENT";
|
|
12129
12129
|
}
|
|
12130
12130
|
async function readCredentialsStore() {
|
|
12131
|
-
const
|
|
12131
|
+
const path31 = getCredentialsPath();
|
|
12132
12132
|
let raw;
|
|
12133
12133
|
try {
|
|
12134
|
-
raw = await readFile(
|
|
12134
|
+
raw = await readFile(path31, "utf-8");
|
|
12135
12135
|
} catch (err) {
|
|
12136
12136
|
if (isNotFound(err)) return {};
|
|
12137
12137
|
warnUnreadableStoreOnce(err);
|
|
12138
12138
|
throw err;
|
|
12139
12139
|
}
|
|
12140
12140
|
try {
|
|
12141
|
-
return parseStore(raw,
|
|
12141
|
+
return parseStore(raw, path31);
|
|
12142
12142
|
} catch (err) {
|
|
12143
12143
|
warnUnreadableStoreOnce(err);
|
|
12144
12144
|
throw err;
|
|
12145
12145
|
}
|
|
12146
12146
|
}
|
|
12147
12147
|
async function writeCredentialsStore(store) {
|
|
12148
|
-
const
|
|
12149
|
-
await mkdir(dirname(
|
|
12150
|
-
await atomicWriteFile(
|
|
12148
|
+
const path31 = getCredentialsPath();
|
|
12149
|
+
await mkdir(dirname(path31), { recursive: true, mode: 448 });
|
|
12150
|
+
await atomicWriteFile(path31, `${JSON.stringify(store, null, 2)}
|
|
12151
12151
|
`, {
|
|
12152
12152
|
mode: 384
|
|
12153
12153
|
});
|
|
@@ -12167,16 +12167,16 @@ function resolveApiKey(apiUrl) {
|
|
|
12167
12167
|
} catch {
|
|
12168
12168
|
return null;
|
|
12169
12169
|
}
|
|
12170
|
-
const
|
|
12170
|
+
const path31 = getCredentialsPath();
|
|
12171
12171
|
let raw;
|
|
12172
12172
|
try {
|
|
12173
|
-
raw = readFileSync(
|
|
12173
|
+
raw = readFileSync(path31, "utf-8");
|
|
12174
12174
|
} catch (err) {
|
|
12175
12175
|
if (!isNotFound(err)) warnUnreadableStoreOnce(err);
|
|
12176
12176
|
return null;
|
|
12177
12177
|
}
|
|
12178
12178
|
try {
|
|
12179
|
-
const entry = parseStore(raw,
|
|
12179
|
+
const entry = parseStore(raw, path31)[url];
|
|
12180
12180
|
if (typeof entry !== "object" || entry === null) return null;
|
|
12181
12181
|
const token = entry.token;
|
|
12182
12182
|
return typeof token === "string" && token ? token : null;
|
|
@@ -12215,12 +12215,12 @@ var init_credentials = __esm({
|
|
|
12215
12215
|
* @param reason - What is wrong with it.
|
|
12216
12216
|
* @param cause - Underlying parse error, if any.
|
|
12217
12217
|
*/
|
|
12218
|
-
constructor(
|
|
12218
|
+
constructor(path31, reason, cause) {
|
|
12219
12219
|
super(
|
|
12220
|
-
`Credentials file ${
|
|
12220
|
+
`Credentials file ${path31} is corrupt (${reason}). Fix it by hand, or delete it and run \`iamu auth login\` again.`,
|
|
12221
12221
|
{
|
|
12222
12222
|
cause,
|
|
12223
|
-
suggestedAction: `Delete ${
|
|
12223
|
+
suggestedAction: `Delete ${path31} and run \`iamu auth login\`, or set IAMU_TOKEN.`
|
|
12224
12224
|
}
|
|
12225
12225
|
);
|
|
12226
12226
|
}
|
|
@@ -12429,11 +12429,265 @@ var init_cloud_url = __esm({
|
|
|
12429
12429
|
}
|
|
12430
12430
|
});
|
|
12431
12431
|
|
|
12432
|
-
// src/commands/
|
|
12432
|
+
// src/commands/live-run-client.ts
|
|
12433
|
+
import { readFile as readFile2, stat } from "fs/promises";
|
|
12434
|
+
import path18 from "path";
|
|
12433
12435
|
import chalk4 from "chalk";
|
|
12436
|
+
async function loadLiveRunMeta(runDirPath) {
|
|
12437
|
+
try {
|
|
12438
|
+
const raw = await readFile2(path18.join(runDirPath, "live.json"), "utf8");
|
|
12439
|
+
const parsed = JSON.parse(raw);
|
|
12440
|
+
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") {
|
|
12441
|
+
return parsed;
|
|
12442
|
+
}
|
|
12443
|
+
return null;
|
|
12444
|
+
} catch {
|
|
12445
|
+
return null;
|
|
12446
|
+
}
|
|
12447
|
+
}
|
|
12448
|
+
async function saveLiveRunMeta(runDirPath, meta) {
|
|
12449
|
+
await atomicWriteFile(
|
|
12450
|
+
path18.join(runDirPath, "live.json"),
|
|
12451
|
+
JSON.stringify(meta, null, 2) + "\n"
|
|
12452
|
+
);
|
|
12453
|
+
}
|
|
12454
|
+
async function registerLiveRun(params) {
|
|
12455
|
+
if (process.env.IAMU_LIVE === "0") {
|
|
12456
|
+
return null;
|
|
12457
|
+
}
|
|
12458
|
+
try {
|
|
12459
|
+
const config = await readConfig(params.projectRoot).catch(() => null);
|
|
12460
|
+
if (!config?.cloud_linked || !config.cloud_project_id || !config.cloud_api_url) {
|
|
12461
|
+
return null;
|
|
12462
|
+
}
|
|
12463
|
+
const apiKey = resolveApiKey(config.cloud_api_url);
|
|
12464
|
+
if (!apiKey) {
|
|
12465
|
+
return null;
|
|
12466
|
+
}
|
|
12467
|
+
const scenario = await readEntity(
|
|
12468
|
+
params.projectRoot,
|
|
12469
|
+
"scenario",
|
|
12470
|
+
params.scenarioSlug
|
|
12471
|
+
).catch(() => null);
|
|
12472
|
+
const scenarioId = scenario?.frontmatter?.id;
|
|
12473
|
+
if (!scenarioId) {
|
|
12474
|
+
return null;
|
|
12475
|
+
}
|
|
12476
|
+
const runDirPath = resolveRunDir(params.projectRoot, params.runId);
|
|
12477
|
+
if (!runDirPath) {
|
|
12478
|
+
return null;
|
|
12479
|
+
}
|
|
12480
|
+
const walkthroughId = toCloudRunUuid(params.runId);
|
|
12481
|
+
const apiUrl = config.cloud_api_url.replace(/\/$/, "");
|
|
12482
|
+
const endpoint = `${apiUrl}/api/projects/${encodeURIComponent(config.cloud_project_id)}/live-runs`;
|
|
12483
|
+
const fetcher = params.fetchFn ?? globalThis.fetch;
|
|
12484
|
+
const postLiveRun = () => fetcher(endpoint, {
|
|
12485
|
+
method: "POST",
|
|
12486
|
+
headers: {
|
|
12487
|
+
Authorization: `Bearer ${apiKey}`,
|
|
12488
|
+
"Content-Type": "application/json"
|
|
12489
|
+
},
|
|
12490
|
+
body: JSON.stringify({
|
|
12491
|
+
run_id: walkthroughId,
|
|
12492
|
+
scenario_id: scenarioId,
|
|
12493
|
+
target_url: params.targetUrl,
|
|
12494
|
+
started_at: params.startedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
12495
|
+
lenses: params.lenses ?? ["persona"]
|
|
12496
|
+
}),
|
|
12497
|
+
signal: AbortSignal.timeout(REGISTER_TIMEOUT_MS)
|
|
12498
|
+
});
|
|
12499
|
+
let res = await postLiveRun();
|
|
12500
|
+
if (res.status === 422) {
|
|
12501
|
+
const data2 = await res.json().catch(() => null);
|
|
12502
|
+
if (data2?.code === "unknown_scenario") {
|
|
12503
|
+
console.log(
|
|
12504
|
+
chalk4.dim(
|
|
12505
|
+
` ${symbols.info} Scenario not on cloud yet. Auto-syncing to enable live stream...`
|
|
12506
|
+
)
|
|
12507
|
+
);
|
|
12508
|
+
try {
|
|
12509
|
+
await runSync(params.projectRoot, {
|
|
12510
|
+
apiKey,
|
|
12511
|
+
fetch: fetcher,
|
|
12512
|
+
timeoutMs: REGISTER_TIMEOUT_MS
|
|
12513
|
+
});
|
|
12514
|
+
res = await postLiveRun();
|
|
12515
|
+
if (!res.ok) {
|
|
12516
|
+
console.log(
|
|
12517
|
+
chalk4.dim(
|
|
12518
|
+
` ${symbols.info} Scenario sync deferred. Run \`iamu sync\` to follow future runs live.`
|
|
12519
|
+
)
|
|
12520
|
+
);
|
|
12521
|
+
return null;
|
|
12522
|
+
}
|
|
12523
|
+
} catch {
|
|
12524
|
+
console.log(
|
|
12525
|
+
chalk4.dim(
|
|
12526
|
+
` ${symbols.info} Scenario sync deferred. Run \`iamu sync\` to follow future runs live.`
|
|
12527
|
+
)
|
|
12528
|
+
);
|
|
12529
|
+
return null;
|
|
12530
|
+
}
|
|
12531
|
+
} else {
|
|
12532
|
+
return null;
|
|
12533
|
+
}
|
|
12534
|
+
}
|
|
12535
|
+
if (!res.ok) {
|
|
12536
|
+
return null;
|
|
12537
|
+
}
|
|
12538
|
+
const data = await res.json();
|
|
12539
|
+
const meta = {
|
|
12540
|
+
walkthrough_id: data.walkthrough_id,
|
|
12541
|
+
viewer_url: data.viewer_url,
|
|
12542
|
+
project_id: config.cloud_project_id,
|
|
12543
|
+
api_url: config.cloud_api_url,
|
|
12544
|
+
last_seq: 0
|
|
12545
|
+
};
|
|
12546
|
+
await saveLiveRunMeta(runDirPath, meta);
|
|
12547
|
+
return {
|
|
12548
|
+
walkthroughId: data.walkthrough_id,
|
|
12549
|
+
viewerUrl: data.viewer_url,
|
|
12550
|
+
status: data.status
|
|
12551
|
+
};
|
|
12552
|
+
} catch {
|
|
12553
|
+
return null;
|
|
12554
|
+
}
|
|
12555
|
+
}
|
|
12556
|
+
async function sendLiveEvents(projectRoot, runId, buildEvents, fetchFn) {
|
|
12557
|
+
try {
|
|
12558
|
+
const runDirPath = resolveRunDir(projectRoot, runId);
|
|
12559
|
+
if (!runDirPath) return {};
|
|
12560
|
+
const meta = await loadLiveRunMeta(runDirPath);
|
|
12561
|
+
if (!meta) return {};
|
|
12562
|
+
const config = await readConfig(projectRoot).catch(() => null);
|
|
12563
|
+
if (!config?.cloud_linked) return {};
|
|
12564
|
+
const apiKey = resolveApiKey(meta.api_url) ?? resolveApiKey(config.cloud_api_url);
|
|
12565
|
+
if (!apiKey) return {};
|
|
12566
|
+
const raw = buildEvents(meta.last_seq + 1);
|
|
12567
|
+
const events = Array.isArray(raw) ? raw : [raw];
|
|
12568
|
+
if (events.length === 0) return {};
|
|
12569
|
+
const maxSeq = Math.max(...events.map((e) => e.seq));
|
|
12570
|
+
meta.last_seq = Math.max(meta.last_seq, maxSeq);
|
|
12571
|
+
await saveLiveRunMeta(runDirPath, meta).catch(() => {
|
|
12572
|
+
});
|
|
12573
|
+
const apiUrl = meta.api_url.replace(/\/$/, "");
|
|
12574
|
+
const endpoint = `${apiUrl}/api/projects/${encodeURIComponent(meta.project_id)}/live-runs/${encodeURIComponent(meta.walkthrough_id)}/events`;
|
|
12575
|
+
const fetcher = fetchFn ?? globalThis.fetch;
|
|
12576
|
+
const res = await fetcher(endpoint, {
|
|
12577
|
+
method: "POST",
|
|
12578
|
+
headers: {
|
|
12579
|
+
Authorization: `Bearer ${apiKey}`,
|
|
12580
|
+
"Content-Type": "application/json"
|
|
12581
|
+
},
|
|
12582
|
+
body: JSON.stringify({ events }),
|
|
12583
|
+
signal: AbortSignal.timeout(EVENT_TIMEOUT_MS)
|
|
12584
|
+
});
|
|
12585
|
+
if (!res.ok) {
|
|
12586
|
+
return {};
|
|
12587
|
+
}
|
|
12588
|
+
const data = await res.json().catch(() => null);
|
|
12589
|
+
return {
|
|
12590
|
+
accepted_seq: data?.accepted_seq,
|
|
12591
|
+
cancelled: data?.cancelled === true
|
|
12592
|
+
};
|
|
12593
|
+
} catch {
|
|
12594
|
+
return {};
|
|
12595
|
+
}
|
|
12596
|
+
}
|
|
12597
|
+
async function sendLiveStep(projectRoot, runId, step, screenshotPath, fetchFn) {
|
|
12598
|
+
try {
|
|
12599
|
+
const runDirPath = resolveRunDir(projectRoot, runId);
|
|
12600
|
+
if (!runDirPath) return {};
|
|
12601
|
+
const meta = await loadLiveRunMeta(runDirPath);
|
|
12602
|
+
if (!meta) return {};
|
|
12603
|
+
let screenshot_base64;
|
|
12604
|
+
if (screenshotPath) {
|
|
12605
|
+
try {
|
|
12606
|
+
const fileStat = await stat(screenshotPath);
|
|
12607
|
+
if (fileStat.isFile() && fileStat.size <= MAX_LIVE_SCREENSHOT_BYTES) {
|
|
12608
|
+
const buf = await readFile2(screenshotPath);
|
|
12609
|
+
screenshot_base64 = buf.toString("base64");
|
|
12610
|
+
}
|
|
12611
|
+
} catch {
|
|
12612
|
+
}
|
|
12613
|
+
}
|
|
12614
|
+
return await sendLiveEvents(
|
|
12615
|
+
projectRoot,
|
|
12616
|
+
runId,
|
|
12617
|
+
(seq2) => ({
|
|
12618
|
+
seq: seq2,
|
|
12619
|
+
type: "step",
|
|
12620
|
+
step: {
|
|
12621
|
+
number: step.step_number,
|
|
12622
|
+
title: step.action,
|
|
12623
|
+
persona_reasoning: step.note ?? void 0,
|
|
12624
|
+
grounding: step.grounding ?? void 0,
|
|
12625
|
+
page_url: step.url ?? void 0,
|
|
12626
|
+
surface: step.surface ?? void 0,
|
|
12627
|
+
...screenshot_base64 ? { screenshot_base64 } : {}
|
|
12628
|
+
}
|
|
12629
|
+
}),
|
|
12630
|
+
fetchFn
|
|
12631
|
+
);
|
|
12632
|
+
} catch {
|
|
12633
|
+
return {};
|
|
12634
|
+
}
|
|
12635
|
+
}
|
|
12636
|
+
async function sendLivePhase(projectRoot, runId, phase, fetchFn) {
|
|
12637
|
+
return sendLiveEvents(
|
|
12638
|
+
projectRoot,
|
|
12639
|
+
runId,
|
|
12640
|
+
(seq2) => ({
|
|
12641
|
+
seq: seq2,
|
|
12642
|
+
type: "phase",
|
|
12643
|
+
phase
|
|
12644
|
+
}),
|
|
12645
|
+
fetchFn
|
|
12646
|
+
);
|
|
12647
|
+
}
|
|
12648
|
+
async function sendLiveFinding(projectRoot, runId, finding, fetchFn) {
|
|
12649
|
+
return sendLiveEvents(
|
|
12650
|
+
projectRoot,
|
|
12651
|
+
runId,
|
|
12652
|
+
(seq2) => ({
|
|
12653
|
+
seq: seq2,
|
|
12654
|
+
type: "finding",
|
|
12655
|
+
finding: {
|
|
12656
|
+
id: finding.id,
|
|
12657
|
+
title: finding.title,
|
|
12658
|
+
type: finding.type,
|
|
12659
|
+
severity: finding.severity,
|
|
12660
|
+
ui_fact: finding.ui_fact ?? void 0,
|
|
12661
|
+
consequence: finding.consequence ?? void 0,
|
|
12662
|
+
step_number: finding.step_number ?? void 0,
|
|
12663
|
+
task_impact: finding.task_impact ?? void 0,
|
|
12664
|
+
confidence: finding.confidence ?? void 0
|
|
12665
|
+
}
|
|
12666
|
+
}),
|
|
12667
|
+
fetchFn
|
|
12668
|
+
);
|
|
12669
|
+
}
|
|
12670
|
+
var REGISTER_TIMEOUT_MS, EVENT_TIMEOUT_MS, MAX_LIVE_SCREENSHOT_BYTES;
|
|
12671
|
+
var init_live_run_client = __esm({
|
|
12672
|
+
"src/commands/live-run-client.ts"() {
|
|
12673
|
+
"use strict";
|
|
12674
|
+
init_dist2();
|
|
12675
|
+
init_symbols();
|
|
12676
|
+
init_context4();
|
|
12677
|
+
init_credentials();
|
|
12678
|
+
REGISTER_TIMEOUT_MS = 3e3;
|
|
12679
|
+
EVENT_TIMEOUT_MS = 1500;
|
|
12680
|
+
MAX_LIVE_SCREENSHOT_BYTES = 5 * 1024 * 1024;
|
|
12681
|
+
}
|
|
12682
|
+
});
|
|
12683
|
+
|
|
12684
|
+
// src/commands/cloud-push.ts
|
|
12685
|
+
import chalk5 from "chalk";
|
|
12434
12686
|
async function pushRunToCloud(projectRoot, runId) {
|
|
12435
12687
|
const config = await readConfig(projectRoot);
|
|
12436
12688
|
if (!config.cloud_linked) return void 0;
|
|
12689
|
+
await sendLivePhase(projectRoot, runId, "publishing").catch(() => {
|
|
12690
|
+
});
|
|
12437
12691
|
const apiKey = resolveApiKey(config.cloud_api_url) ?? void 0;
|
|
12438
12692
|
const result = await mirrorLocalWalkthrough(projectRoot, runId, { apiKey });
|
|
12439
12693
|
const onCloud = result.mirrored || result.status === "already_pushed";
|
|
@@ -12471,20 +12725,20 @@ function printCloudRunInfo(info) {
|
|
|
12471
12725
|
console.log();
|
|
12472
12726
|
if (info.url) {
|
|
12473
12727
|
const state = info.mirrored ? "pushed" : "already pushed";
|
|
12474
|
-
console.log(` ${
|
|
12475
|
-
console.log(` ${
|
|
12728
|
+
console.log(` ${chalk5.dim("cloud:")} ${chalk5.green(state)}`);
|
|
12729
|
+
console.log(` ${chalk5.dim("view:")} ${chalk5.underline(info.url)}`);
|
|
12476
12730
|
return;
|
|
12477
12731
|
}
|
|
12478
12732
|
if (info.status === "enqueued") {
|
|
12479
12733
|
console.log(
|
|
12480
|
-
` ${
|
|
12734
|
+
` ${chalk5.dim("cloud:")} ${chalk5.yellow("queued")} ${chalk5.dim("(will retry on next `iamu sync`)")}`
|
|
12481
12735
|
);
|
|
12482
12736
|
return;
|
|
12483
12737
|
}
|
|
12484
12738
|
const reason = info.skipped_reason ?? "unknown";
|
|
12485
12739
|
const remedy = SKIP_REMEDY[reason];
|
|
12486
12740
|
console.log(
|
|
12487
|
-
` ${
|
|
12741
|
+
` ${chalk5.dim("cloud:")} ${chalk5.dim(`skipped (${reason})`)}${remedy ? chalk5.dim(` \u2014 ${remedy}`) : ""}`
|
|
12488
12742
|
);
|
|
12489
12743
|
}
|
|
12490
12744
|
var SKIP_REMEDY;
|
|
@@ -12494,6 +12748,7 @@ var init_cloud_push = __esm({
|
|
|
12494
12748
|
init_dist2();
|
|
12495
12749
|
init_cloud_url();
|
|
12496
12750
|
init_credentials();
|
|
12751
|
+
init_live_run_client();
|
|
12497
12752
|
SKIP_REMEDY = {
|
|
12498
12753
|
no_api_key: "run `iamu auth login` to restore credentials",
|
|
12499
12754
|
bundle_too_large: "reduce screenshot count or resolution, then `iamu sync`",
|
|
@@ -12733,10 +12988,10 @@ var init_templates = __esm({
|
|
|
12733
12988
|
|
|
12734
12989
|
// src/commands/skills.ts
|
|
12735
12990
|
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
12736
|
-
import { mkdir as mkdir2, readFile as
|
|
12991
|
+
import { mkdir as mkdir2, readFile as readFile3, rm, rmdir, writeFile } from "fs/promises";
|
|
12737
12992
|
import { dirname as dirname3, join as join4, resolve as resolve2 } from "path";
|
|
12738
12993
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
12739
|
-
import
|
|
12994
|
+
import chalk6 from "chalk";
|
|
12740
12995
|
function getVersion() {
|
|
12741
12996
|
try {
|
|
12742
12997
|
const thisDir2 = dirname3(fileURLToPath2(import.meta.url));
|
|
@@ -12826,22 +13081,22 @@ function commandsFromSkills(templates) {
|
|
|
12826
13081
|
}
|
|
12827
13082
|
async function needsWrite(filePath, content) {
|
|
12828
13083
|
try {
|
|
12829
|
-
const existing = await
|
|
13084
|
+
const existing = await readFile3(filePath, "utf-8");
|
|
12830
13085
|
return existing !== content;
|
|
12831
13086
|
} catch {
|
|
12832
13087
|
return true;
|
|
12833
13088
|
}
|
|
12834
13089
|
}
|
|
12835
|
-
function isCliWrittenSkill(
|
|
13090
|
+
function isCliWrittenSkill(path31) {
|
|
12836
13091
|
try {
|
|
12837
|
-
return /^generatedBy:/m.test(readFileSync3(
|
|
13092
|
+
return /^generatedBy:/m.test(readFileSync3(path31, "utf-8"));
|
|
12838
13093
|
} catch {
|
|
12839
13094
|
return false;
|
|
12840
13095
|
}
|
|
12841
13096
|
}
|
|
12842
|
-
function isCliWrittenPrompt(
|
|
13097
|
+
function isCliWrittenPrompt(path31) {
|
|
12843
13098
|
try {
|
|
12844
|
-
const content = readFileSync3(
|
|
13099
|
+
const content = readFileSync3(path31, "utf-8");
|
|
12845
13100
|
return content.includes("iamu") || /^generatedBy:/m.test(content);
|
|
12846
13101
|
} catch {
|
|
12847
13102
|
return false;
|
|
@@ -12853,8 +13108,8 @@ function planSkillFiles(hosts, projectRoot, version2) {
|
|
|
12853
13108
|
for (const host of hosts) {
|
|
12854
13109
|
if (pluginProvidesSkills(host, projectRoot)) {
|
|
12855
13110
|
for (const name of skillTemplates.keys()) {
|
|
12856
|
-
const
|
|
12857
|
-
if (isCliWrittenSkill(
|
|
13111
|
+
const path31 = join4(host.getSkillsDir(projectRoot), name, "SKILL.md");
|
|
13112
|
+
if (isCliWrittenSkill(path31)) files.push({ host, path: path31, content: null });
|
|
12858
13113
|
}
|
|
12859
13114
|
} else if (host.supportsSkills) {
|
|
12860
13115
|
const skillsDir = host.getSkillsDir(projectRoot);
|
|
@@ -13010,7 +13265,7 @@ async function installSkillsForHosts(hosts, projectRoot, version2, opts) {
|
|
|
13010
13265
|
);
|
|
13011
13266
|
} else {
|
|
13012
13267
|
console.log(
|
|
13013
|
-
` ${symbols.success} ${
|
|
13268
|
+
` ${symbols.success} ${chalk6.dim(`${host.name} \u2014 up to date`)}`
|
|
13014
13269
|
);
|
|
13015
13270
|
}
|
|
13016
13271
|
}
|
|
@@ -13035,11 +13290,11 @@ var sync_exports = {};
|
|
|
13035
13290
|
__export(sync_exports, {
|
|
13036
13291
|
sync: () => sync
|
|
13037
13292
|
});
|
|
13038
|
-
import
|
|
13293
|
+
import chalk7 from "chalk";
|
|
13039
13294
|
async function warnStaleSkills(projectRoot) {
|
|
13040
13295
|
try {
|
|
13041
13296
|
if ((await findStaleSkills(projectRoot)).length > 0) {
|
|
13042
|
-
console.log(
|
|
13297
|
+
console.log(chalk7.yellow(` ${STALE_SKILLS_MESSAGE}`));
|
|
13043
13298
|
}
|
|
13044
13299
|
} catch {
|
|
13045
13300
|
}
|
|
@@ -13067,11 +13322,11 @@ function describeCounts(byType) {
|
|
|
13067
13322
|
function printPendingDeletes(pending) {
|
|
13068
13323
|
console.log();
|
|
13069
13324
|
console.log(
|
|
13070
|
-
|
|
13325
|
+
chalk7.yellow(
|
|
13071
13326
|
` \u26A0 ${pending.total} local deletion${pending.total !== 1 ? "s" : ""} not sent to the cloud \u2014 check the list, then run \`iamu sync --confirm-deletes\``
|
|
13072
13327
|
)
|
|
13073
13328
|
);
|
|
13074
|
-
console.log(
|
|
13329
|
+
console.log(chalk7.dim(` Why: ${pending.reasons.join("; ")}`));
|
|
13075
13330
|
const byType = /* @__PURE__ */ new Map();
|
|
13076
13331
|
for (const e of pending.entities) {
|
|
13077
13332
|
const list2 = byType.get(e.type) ?? [];
|
|
@@ -13083,18 +13338,18 @@ function printPendingDeletes(pending) {
|
|
|
13083
13338
|
` ${describeDeletionCount(type2, list2.length)}${type2 === "unknown" ? " (synced before this CLI recorded types; by id)" : ""}:`
|
|
13084
13339
|
);
|
|
13085
13340
|
for (const e of list2.slice(0, MAX_LISTED_PER_TYPE)) {
|
|
13086
|
-
console.log(
|
|
13341
|
+
console.log(chalk7.dim(` ${e.label}`));
|
|
13087
13342
|
}
|
|
13088
13343
|
if (list2.length > MAX_LISTED_PER_TYPE) {
|
|
13089
13344
|
console.log(
|
|
13090
|
-
|
|
13345
|
+
chalk7.dim(
|
|
13091
13346
|
` \u2026 and ${list2.length - MAX_LISTED_PER_TYPE} more (\`iamu sync --json\` lists all)`
|
|
13092
13347
|
)
|
|
13093
13348
|
);
|
|
13094
13349
|
}
|
|
13095
13350
|
}
|
|
13096
13351
|
console.log(
|
|
13097
|
-
|
|
13352
|
+
chalk7.dim(
|
|
13098
13353
|
" To keep an entity on the cloud instead, restore its file (`iamu pull` brings entities back; runs cannot be pulled)."
|
|
13099
13354
|
)
|
|
13100
13355
|
);
|
|
@@ -13133,24 +13388,24 @@ async function sync(opts) {
|
|
|
13133
13388
|
} else {
|
|
13134
13389
|
if (!quiet) console.log();
|
|
13135
13390
|
console.log(
|
|
13136
|
-
` ${
|
|
13391
|
+
` ${chalk7.bold("Sync Status:")} ${totalPending === 0 ? chalk7.green("in sync") : chalk7.yellow(`${totalPending} item(s) to sync`)}`
|
|
13137
13392
|
);
|
|
13138
13393
|
if (totalPending > 0) {
|
|
13139
13394
|
if (pendingNew > 0)
|
|
13140
|
-
console.log(
|
|
13395
|
+
console.log(chalk7.dim(` ${pendingNew} new entity file(s)`));
|
|
13141
13396
|
if (pendingUpdates > 0)
|
|
13142
13397
|
console.log(
|
|
13143
|
-
|
|
13398
|
+
chalk7.dim(` ${pendingUpdates} modified entity file(s)`)
|
|
13144
13399
|
);
|
|
13145
13400
|
if (pendingWalkthroughs > 0)
|
|
13146
13401
|
console.log(
|
|
13147
|
-
|
|
13402
|
+
chalk7.dim(` ${pendingWalkthroughs} unpushed walkthrough run(s)`)
|
|
13148
13403
|
);
|
|
13149
13404
|
if (pendingRetries > 0)
|
|
13150
|
-
console.log(
|
|
13405
|
+
console.log(chalk7.dim(` ${pendingRetries} queued retry item(s)`));
|
|
13151
13406
|
if (deletions && pendingDeletions > 0)
|
|
13152
13407
|
console.log(
|
|
13153
|
-
|
|
13408
|
+
chalk7.dim(
|
|
13154
13409
|
` ${pendingDeletions} local deletion(s): ${describeCounts(deletions.by_type)}${deletions.needs_confirm ? " \u2014 needs `iamu sync --confirm-deletes`" : ""}`
|
|
13155
13410
|
)
|
|
13156
13411
|
);
|
|
@@ -13207,23 +13462,23 @@ async function sync(opts) {
|
|
|
13207
13462
|
Object.entries(result.deleted.cloud_by_type).filter(([, n]) => n > 0)
|
|
13208
13463
|
);
|
|
13209
13464
|
console.log(
|
|
13210
|
-
Object.keys(removed).length > 0 ? ` ${
|
|
13465
|
+
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`
|
|
13211
13466
|
);
|
|
13212
13467
|
}
|
|
13213
13468
|
if (result.pending_deletes) printPendingDeletes(result.pending_deletes);
|
|
13214
13469
|
if (result.held_deletes) {
|
|
13215
13470
|
const n = result.held_deletes.length;
|
|
13216
13471
|
console.log(
|
|
13217
|
-
|
|
13472
|
+
chalk7.yellow(` ${n} local deletion${n !== 1 ? "s" : ""} held back:`)
|
|
13218
13473
|
);
|
|
13219
13474
|
for (const h of result.held_deletes) {
|
|
13220
13475
|
console.log(
|
|
13221
|
-
` ${describeDeletionCount(h.type, 1).replace(/^1 /, "")} ${h.label}${
|
|
13476
|
+
` ${describeDeletionCount(h.type, 1).replace(/^1 /, "")} ${h.label}${chalk7.dim(` \u2014 ${h.reason}`)}`
|
|
13222
13477
|
);
|
|
13223
13478
|
}
|
|
13224
13479
|
if (result.held_deletes.some((h) => h.branches)) {
|
|
13225
13480
|
console.log(
|
|
13226
|
-
|
|
13481
|
+
chalk7.dim(
|
|
13227
13482
|
" 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."
|
|
13228
13483
|
)
|
|
13229
13484
|
);
|
|
@@ -13231,12 +13486,12 @@ async function sync(opts) {
|
|
|
13231
13486
|
}
|
|
13232
13487
|
if (result.drain.drained > 0) {
|
|
13233
13488
|
console.log(
|
|
13234
|
-
|
|
13489
|
+
chalk7.dim(` Drained ${result.drain.drained} retry-queue items`)
|
|
13235
13490
|
);
|
|
13236
13491
|
}
|
|
13237
13492
|
if (result.draftsSkipped > 0) {
|
|
13238
13493
|
console.log(
|
|
13239
|
-
|
|
13494
|
+
chalk7.dim(
|
|
13240
13495
|
` ${result.draftsSkipped} draft scenarios skipped \u2014 bind a persona to push`
|
|
13241
13496
|
)
|
|
13242
13497
|
);
|
|
@@ -13245,7 +13500,7 @@ async function sync(opts) {
|
|
|
13245
13500
|
if (enqueuedTotal > 0) {
|
|
13246
13501
|
const total = enqueuedTotal;
|
|
13247
13502
|
console.log(
|
|
13248
|
-
|
|
13503
|
+
chalk7.yellow(
|
|
13249
13504
|
` ${total} items enqueued for retry (will retry next sync)`
|
|
13250
13505
|
)
|
|
13251
13506
|
);
|
|
@@ -13258,7 +13513,7 @@ async function sync(opts) {
|
|
|
13258
13513
|
);
|
|
13259
13514
|
console.log();
|
|
13260
13515
|
console.log(
|
|
13261
|
-
|
|
13516
|
+
chalk7.yellow(
|
|
13262
13517
|
` \u26A0 --keep-mine replaced ${n} cloud change${n !== 1 ? "s" : ""}:`
|
|
13263
13518
|
)
|
|
13264
13519
|
);
|
|
@@ -13268,11 +13523,11 @@ async function sync(opts) {
|
|
|
13268
13523
|
const slug = slugs.get(o.entity_id);
|
|
13269
13524
|
const named = slug ? `${slug} (${o.entity_id})` : o.entity_id;
|
|
13270
13525
|
console.log(
|
|
13271
|
-
` ${
|
|
13526
|
+
` ${chalk7.yellow("\u26A0")} ${o.type} ${named} \u2014 overwrote ${who}'s change from ${when}`
|
|
13272
13527
|
);
|
|
13273
13528
|
}
|
|
13274
13529
|
console.log(
|
|
13275
|
-
|
|
13530
|
+
chalk7.dim(
|
|
13276
13531
|
" Their version is gone from cloud \u2014 `iamu pull --force` now returns yours."
|
|
13277
13532
|
)
|
|
13278
13533
|
);
|
|
@@ -13280,7 +13535,7 @@ async function sync(opts) {
|
|
|
13280
13535
|
if (result.conflicts.length > 0) {
|
|
13281
13536
|
console.log();
|
|
13282
13537
|
console.log(
|
|
13283
|
-
|
|
13538
|
+
chalk7.yellow(
|
|
13284
13539
|
` ${result.conflicts.length} conflict${result.conflicts.length !== 1 ? "s" : ""} detected:`
|
|
13285
13540
|
)
|
|
13286
13541
|
);
|
|
@@ -13292,12 +13547,12 @@ async function sync(opts) {
|
|
|
13292
13547
|
);
|
|
13293
13548
|
}
|
|
13294
13549
|
console.log(
|
|
13295
|
-
|
|
13550
|
+
chalk7.dim(
|
|
13296
13551
|
" Resolve: copy your edits aside, run `iamu pull --force` to take the cloud version, re-apply, then sync"
|
|
13297
13552
|
)
|
|
13298
13553
|
);
|
|
13299
13554
|
console.log(
|
|
13300
|
-
|
|
13555
|
+
chalk7.dim(
|
|
13301
13556
|
" Or keep yours: `iamu sync --keep-mine` re-pushes your version over theirs"
|
|
13302
13557
|
)
|
|
13303
13558
|
);
|
|
@@ -13307,26 +13562,26 @@ async function sync(opts) {
|
|
|
13307
13562
|
}
|
|
13308
13563
|
for (const f of result.drain.failures) {
|
|
13309
13564
|
console.error(
|
|
13310
|
-
` ${symbols.error} ${f.label ?? f.entity_id}: ${
|
|
13565
|
+
` ${symbols.error} ${f.label ?? f.entity_id}: ${chalk7.dim(f.error)}`
|
|
13311
13566
|
);
|
|
13312
13567
|
}
|
|
13313
13568
|
if (result.drain.dropped > 0) {
|
|
13314
13569
|
console.error(
|
|
13315
|
-
|
|
13570
|
+
chalk7.yellow(
|
|
13316
13571
|
` ${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)`
|
|
13317
13572
|
)
|
|
13318
13573
|
);
|
|
13319
13574
|
}
|
|
13320
13575
|
for (const w of result.drain.warnings) {
|
|
13321
|
-
console.error(` ${symbols.warning} retry queue: ${
|
|
13576
|
+
console.error(` ${symbols.warning} retry queue: ${chalk7.dim(w)}`);
|
|
13322
13577
|
}
|
|
13323
13578
|
for (const n of result.notices ?? []) {
|
|
13324
|
-
console.log(
|
|
13579
|
+
console.log(chalk7.dim(` ${n}`));
|
|
13325
13580
|
}
|
|
13326
13581
|
if (totalPushed > 0) {
|
|
13327
13582
|
const dashboard = await projectDashboardUrl(projectRoot);
|
|
13328
13583
|
if (dashboard) {
|
|
13329
|
-
console.log(` ${
|
|
13584
|
+
console.log(` ${chalk7.dim("view:")} ${chalk7.underline(dashboard)}`);
|
|
13330
13585
|
}
|
|
13331
13586
|
}
|
|
13332
13587
|
if (failed) {
|
|
@@ -13357,7 +13612,7 @@ var pull_exports = {};
|
|
|
13357
13612
|
__export(pull_exports, {
|
|
13358
13613
|
pull: () => pull
|
|
13359
13614
|
});
|
|
13360
|
-
import
|
|
13615
|
+
import chalk8 from "chalk";
|
|
13361
13616
|
async function pull(opts) {
|
|
13362
13617
|
if (opts?.force && opts?.preview) {
|
|
13363
13618
|
commandError("--force and --preview are mutually exclusive.", opts);
|
|
@@ -13387,13 +13642,13 @@ async function pull(opts) {
|
|
|
13387
13642
|
if (result.drain.failures.length > 0) {
|
|
13388
13643
|
for (const f of result.drain.failures) {
|
|
13389
13644
|
console.error(
|
|
13390
|
-
` ${symbols.error} drain: ${f.entity_id}: ${
|
|
13645
|
+
` ${symbols.error} drain: ${f.entity_id}: ${chalk8.dim(f.error)}`
|
|
13391
13646
|
);
|
|
13392
13647
|
}
|
|
13393
13648
|
}
|
|
13394
13649
|
if (!quiet) console.log();
|
|
13395
13650
|
if (result.preview) {
|
|
13396
|
-
console.log(
|
|
13651
|
+
console.log(chalk8.dim(" Preview mode \u2014 no files written."));
|
|
13397
13652
|
}
|
|
13398
13653
|
const types2 = Object.entries(result.pulls);
|
|
13399
13654
|
let totalWritten = 0;
|
|
@@ -13420,11 +13675,11 @@ async function pull(opts) {
|
|
|
13420
13675
|
console.error(` ${symbols.error} ${type2}: ${err}`);
|
|
13421
13676
|
}
|
|
13422
13677
|
for (const warning of summary.warnings) {
|
|
13423
|
-
console.error(` ${
|
|
13678
|
+
console.error(` ${chalk8.yellow("\u26A0")} ${type2}: ${warning}`);
|
|
13424
13679
|
}
|
|
13425
13680
|
for (const { slug } of summary.diverged) {
|
|
13426
13681
|
console.error(
|
|
13427
|
-
` ${
|
|
13682
|
+
` ${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\``
|
|
13428
13683
|
);
|
|
13429
13684
|
}
|
|
13430
13685
|
}
|
|
@@ -13439,7 +13694,7 @@ async function pull(opts) {
|
|
|
13439
13694
|
}
|
|
13440
13695
|
if (totalSkipped > 0) {
|
|
13441
13696
|
console.log(
|
|
13442
|
-
|
|
13697
|
+
chalk8.dim(
|
|
13443
13698
|
` ${totalSkipped} entities skipped (up to date or kept local)`
|
|
13444
13699
|
)
|
|
13445
13700
|
);
|
|
@@ -13590,7 +13845,7 @@ var init_auth_token_input = __esm({
|
|
|
13590
13845
|
});
|
|
13591
13846
|
|
|
13592
13847
|
// src/commands/mcp-config.ts
|
|
13593
|
-
import { readFile as
|
|
13848
|
+
import { readFile as readFile4, writeFile as writeFile2 } from "fs/promises";
|
|
13594
13849
|
import { basename, dirname as dirname4 } from "path";
|
|
13595
13850
|
import { mkdir as mkdir3 } from "fs/promises";
|
|
13596
13851
|
function isVscodePath(mcpPath) {
|
|
@@ -13599,7 +13854,7 @@ function isVscodePath(mcpPath) {
|
|
|
13599
13854
|
async function writeSyncMcpEntry(mcpPath) {
|
|
13600
13855
|
let existing = {};
|
|
13601
13856
|
try {
|
|
13602
|
-
const raw = await
|
|
13857
|
+
const raw = await readFile4(mcpPath, "utf-8");
|
|
13603
13858
|
existing = JSON.parse(raw);
|
|
13604
13859
|
} catch (err) {
|
|
13605
13860
|
if (err.code === "ENOENT") {
|
|
@@ -13656,7 +13911,7 @@ __export(auth_exports, {
|
|
|
13656
13911
|
import { execFile as execFile2 } from "child_process";
|
|
13657
13912
|
import { platform } from "os";
|
|
13658
13913
|
import { isCancel, select, spinner } from "@clack/prompts";
|
|
13659
|
-
import
|
|
13914
|
+
import chalk9 from "chalk";
|
|
13660
13915
|
function openBrowser(url, run = spawnDetached) {
|
|
13661
13916
|
try {
|
|
13662
13917
|
const parsed = new URL(url);
|
|
@@ -13780,8 +14035,8 @@ async function reportAlreadyLinked(projectRoot, config, apiUrl, requested) {
|
|
|
13780
14035
|
}
|
|
13781
14036
|
console.log();
|
|
13782
14037
|
console.log(` ${symbols.success} Already authenticated and cloud-linked.`);
|
|
13783
|
-
console.log(` ${
|
|
13784
|
-
console.log(` ${
|
|
14038
|
+
console.log(` ${chalk9.dim("API:")} ${apiUrl}`);
|
|
14039
|
+
console.log(` ${chalk9.dim("Project:")} ${config.cloud_project_id}`);
|
|
13785
14040
|
await registerSyncServer(projectRoot);
|
|
13786
14041
|
console.log();
|
|
13787
14042
|
}
|
|
@@ -13789,8 +14044,8 @@ async function obtainToken(apiUrl, providedToken, reusedToken, opts, t) {
|
|
|
13789
14044
|
if (providedToken) {
|
|
13790
14045
|
console.log();
|
|
13791
14046
|
console.log(
|
|
13792
|
-
|
|
13793
|
-
` Authenticating with provided token for ${
|
|
14047
|
+
chalk9.bold(
|
|
14048
|
+
` Authenticating with provided token for ${chalk9.cyan(apiUrl)}...`
|
|
13794
14049
|
)
|
|
13795
14050
|
);
|
|
13796
14051
|
return { token: providedToken, email: null, tenantId: null };
|
|
@@ -13798,7 +14053,7 @@ async function obtainToken(apiUrl, providedToken, reusedToken, opts, t) {
|
|
|
13798
14053
|
if (reusedToken) {
|
|
13799
14054
|
console.log();
|
|
13800
14055
|
console.log(
|
|
13801
|
-
|
|
14056
|
+
chalk9.bold(` Using stored credentials for ${chalk9.cyan(apiUrl)}...`)
|
|
13802
14057
|
);
|
|
13803
14058
|
return { token: reusedToken, email: null, tenantId: null };
|
|
13804
14059
|
}
|
|
@@ -13818,17 +14073,17 @@ async function browserLogin(apiUrl, opts, t) {
|
|
|
13818
14073
|
const isLocal = isLoopbackHost(new URL(apiUrl).hostname);
|
|
13819
14074
|
console.log();
|
|
13820
14075
|
console.log(
|
|
13821
|
-
|
|
13822
|
-
` Authenticating with ${isLocal ? "local " : ""}Iamu Cloud (${
|
|
14076
|
+
chalk9.bold(
|
|
14077
|
+
` Authenticating with ${isLocal ? "local " : ""}Iamu Cloud (${chalk9.cyan(apiUrl)})...`
|
|
13823
14078
|
)
|
|
13824
14079
|
);
|
|
13825
14080
|
const started = await startAuthSession(apiUrl, t.requestTimeoutMs);
|
|
13826
14081
|
if (!started) return null;
|
|
13827
14082
|
if (opts.browser !== false) {
|
|
13828
|
-
console.log(` Opening browser: ${
|
|
14083
|
+
console.log(` Opening browser: ${chalk9.cyan(started.loginUrl)}`);
|
|
13829
14084
|
openBrowser(started.loginUrl);
|
|
13830
14085
|
} else {
|
|
13831
|
-
console.log(` Log in at: ${
|
|
14086
|
+
console.log(` Log in at: ${chalk9.cyan(started.loginUrl)}`);
|
|
13832
14087
|
}
|
|
13833
14088
|
const s = spinner();
|
|
13834
14089
|
s.start("Waiting for you to log in in browser...");
|
|
@@ -13836,11 +14091,11 @@ async function browserLogin(apiUrl, opts, t) {
|
|
|
13836
14091
|
if (result.kind === "expired") {
|
|
13837
14092
|
s.stop("Auth session expired.");
|
|
13838
14093
|
console.error(
|
|
13839
|
-
|
|
14094
|
+
chalk9.red(`
|
|
13840
14095
|
Auth session expired or failed (HTTP ${result.status}).`)
|
|
13841
14096
|
);
|
|
13842
14097
|
console.error(
|
|
13843
|
-
|
|
14098
|
+
chalk9.dim(" Re-run `iamu auth login` to start a new login session.\n")
|
|
13844
14099
|
);
|
|
13845
14100
|
process.exitCode = 1;
|
|
13846
14101
|
return null;
|
|
@@ -13848,12 +14103,12 @@ async function browserLogin(apiUrl, opts, t) {
|
|
|
13848
14103
|
if (result.kind === "timeout") {
|
|
13849
14104
|
s.stop("Authentication timed out.");
|
|
13850
14105
|
console.error(
|
|
13851
|
-
|
|
14106
|
+
chalk9.red(
|
|
13852
14107
|
"\n Authentication timed out (no approval received within 2 minutes)."
|
|
13853
14108
|
)
|
|
13854
14109
|
);
|
|
13855
14110
|
console.error(
|
|
13856
|
-
|
|
14111
|
+
chalk9.dim(
|
|
13857
14112
|
" \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"
|
|
13858
14113
|
)
|
|
13859
14114
|
);
|
|
@@ -13881,12 +14136,12 @@ async function startAuthSession(apiUrl, timeoutMs) {
|
|
|
13881
14136
|
});
|
|
13882
14137
|
if (!res.ok) {
|
|
13883
14138
|
console.error(
|
|
13884
|
-
|
|
14139
|
+
chalk9.red(
|
|
13885
14140
|
` Failed to start auth session at ${apiUrl}: ${res.text || `HTTP ${res.status}`}`
|
|
13886
14141
|
)
|
|
13887
14142
|
);
|
|
13888
14143
|
console.error(
|
|
13889
|
-
|
|
14144
|
+
chalk9.dim(
|
|
13890
14145
|
" \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"
|
|
13891
14146
|
)
|
|
13892
14147
|
);
|
|
@@ -13901,11 +14156,11 @@ async function startAuthSession(apiUrl, timeoutMs) {
|
|
|
13901
14156
|
return { sessionId: data.sessionId, loginUrl: data.loginUrl };
|
|
13902
14157
|
} catch (err) {
|
|
13903
14158
|
console.error(
|
|
13904
|
-
|
|
14159
|
+
chalk9.red(` Cannot reach Iamu Cloud (${apiUrl}).`) + chalk9.dim(`
|
|
13905
14160
|
Reason: ${errorMessage(err)}`)
|
|
13906
14161
|
);
|
|
13907
14162
|
console.error(
|
|
13908
|
-
|
|
14163
|
+
chalk9.dim(
|
|
13909
14164
|
"\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"
|
|
13910
14165
|
)
|
|
13911
14166
|
);
|
|
@@ -13953,22 +14208,22 @@ async function linkCloudProject(args) {
|
|
|
13953
14208
|
cloudApiUrl: args.apiUrl,
|
|
13954
14209
|
apiKey: args.token
|
|
13955
14210
|
});
|
|
13956
|
-
console.log(` ${symbols.success} Linked to ${
|
|
14211
|
+
console.log(` ${symbols.success} Linked to ${chalk9.cyan(args.apiUrl)}`);
|
|
13957
14212
|
if (result.sync?.push?.pushed) {
|
|
13958
14213
|
console.log(
|
|
13959
|
-
` ${
|
|
14214
|
+
` ${chalk9.dim("Initial sync:")} ${result.sync.push.pushed} pushed`
|
|
13960
14215
|
);
|
|
13961
14216
|
}
|
|
13962
14217
|
} catch (err) {
|
|
13963
14218
|
console.error(
|
|
13964
|
-
|
|
14219
|
+
chalk9.red(" Credentials saved, but linking the project failed.") + chalk9.dim(` (${errorMessage(err)})`)
|
|
13965
14220
|
);
|
|
13966
14221
|
process.exitCode = 1;
|
|
13967
14222
|
return;
|
|
13968
14223
|
}
|
|
13969
14224
|
await registerSyncServer(args.projectRoot);
|
|
13970
14225
|
console.log(
|
|
13971
|
-
` ${
|
|
14226
|
+
` ${chalk9.dim("Dashboard:")} ${chalk9.underline(getCloudDashboardUrl(args.apiUrl, cloudProjectId))}`
|
|
13972
14227
|
);
|
|
13973
14228
|
}
|
|
13974
14229
|
async function listCloudProjects(args) {
|
|
@@ -13984,9 +14239,9 @@ async function listCloudProjects(args) {
|
|
|
13984
14239
|
}
|
|
13985
14240
|
if (!res.ok) {
|
|
13986
14241
|
console.error(
|
|
13987
|
-
|
|
14242
|
+
chalk9.red(
|
|
13988
14243
|
` Credentials saved, but could not list cloud projects (HTTP ${res.status}).`
|
|
13989
|
-
) +
|
|
14244
|
+
) + chalk9.dim(" Re-run iamu auth login.")
|
|
13990
14245
|
);
|
|
13991
14246
|
process.exitCode = 1;
|
|
13992
14247
|
return null;
|
|
@@ -13996,7 +14251,7 @@ async function listCloudProjects(args) {
|
|
|
13996
14251
|
return projects;
|
|
13997
14252
|
} catch (err) {
|
|
13998
14253
|
console.error(
|
|
13999
|
-
|
|
14254
|
+
chalk9.yellow(" Credentials saved but could not list projects.") + chalk9.dim(` (${errorMessage(err)})`)
|
|
14000
14255
|
);
|
|
14001
14256
|
process.exitCode = 1;
|
|
14002
14257
|
return null;
|
|
@@ -14009,7 +14264,7 @@ async function dropRejectedToken(apiUrl) {
|
|
|
14009
14264
|
await writeCredentialsStore(store);
|
|
14010
14265
|
}
|
|
14011
14266
|
console.error(
|
|
14012
|
-
|
|
14267
|
+
chalk9.red(" Stored credentials were rejected and have been removed.") + chalk9.dim(" Run iamu auth login again to sign in.")
|
|
14013
14268
|
);
|
|
14014
14269
|
process.exitCode = 1;
|
|
14015
14270
|
}
|
|
@@ -14037,34 +14292,34 @@ async function chooseCloudProject(args, projects) {
|
|
|
14037
14292
|
function printProjectRefusal(reason, projects, { config, opts }) {
|
|
14038
14293
|
if (reason === "unknown_project") {
|
|
14039
14294
|
console.error(
|
|
14040
|
-
|
|
14295
|
+
chalk9.red(
|
|
14041
14296
|
` Cloud project ${opts.project} is not one this account can see.`
|
|
14042
|
-
) +
|
|
14297
|
+
) + chalk9.dim(" Pick one of:")
|
|
14043
14298
|
);
|
|
14044
14299
|
} else {
|
|
14045
14300
|
if (opts.yes) {
|
|
14046
14301
|
console.error(
|
|
14047
|
-
|
|
14302
|
+
chalk9.yellow(
|
|
14048
14303
|
` --yes only links when the account has exactly one cloud project; it has ${projects.length}.`
|
|
14049
14304
|
)
|
|
14050
14305
|
);
|
|
14051
14306
|
}
|
|
14052
14307
|
console.error(
|
|
14053
|
-
|
|
14308
|
+
chalk9.yellow(
|
|
14054
14309
|
" Signed in. Choose the cloud project to link \u2014 re-run with --project:"
|
|
14055
14310
|
)
|
|
14056
14311
|
);
|
|
14057
14312
|
}
|
|
14058
14313
|
for (const p of projects) {
|
|
14059
14314
|
console.error(
|
|
14060
|
-
` iamu auth login --project ${p.id} ${
|
|
14315
|
+
` iamu auth login --project ${p.id} ${chalk9.dim(`${p.name} (${p.slug})`)}`
|
|
14061
14316
|
);
|
|
14062
14317
|
}
|
|
14063
14318
|
console.error(
|
|
14064
|
-
` iamu auth login --project new ${
|
|
14319
|
+
` iamu auth login --project new ${chalk9.dim(`create "${config.project_name}"`)}`
|
|
14065
14320
|
);
|
|
14066
14321
|
console.error(
|
|
14067
|
-
|
|
14322
|
+
chalk9.dim(" Credentials are stored; the re-run skips the browser.")
|
|
14068
14323
|
);
|
|
14069
14324
|
process.exitCode = 1;
|
|
14070
14325
|
}
|
|
@@ -14083,7 +14338,7 @@ async function promptForProject(projects, args) {
|
|
|
14083
14338
|
});
|
|
14084
14339
|
if (isCancel(choice)) {
|
|
14085
14340
|
process.exitCode = 130;
|
|
14086
|
-
console.log(
|
|
14341
|
+
console.log(chalk9.dim(" Login cancelled."));
|
|
14087
14342
|
return null;
|
|
14088
14343
|
}
|
|
14089
14344
|
return choice === CREATE_NEW ? createCloudProject(args) : String(choice);
|
|
@@ -14110,7 +14365,7 @@ async function createCloudProject(args) {
|
|
|
14110
14365
|
return id;
|
|
14111
14366
|
} catch (err) {
|
|
14112
14367
|
console.error(
|
|
14113
|
-
|
|
14368
|
+
chalk9.red(" Failed to create cloud project.") + chalk9.dim(` (${errorMessage(err)}) Try again with iamu auth login.`)
|
|
14114
14369
|
);
|
|
14115
14370
|
process.exitCode = 1;
|
|
14116
14371
|
return null;
|
|
@@ -14125,13 +14380,13 @@ async function registerSyncServer(projectRoot) {
|
|
|
14125
14380
|
registered.push(host.name);
|
|
14126
14381
|
} catch (err) {
|
|
14127
14382
|
console.error(
|
|
14128
|
-
|
|
14383
|
+
chalk9.yellow(` ${host.name}: iamu-sync MCP not registered`) + chalk9.dim(` (${err.message})`)
|
|
14129
14384
|
);
|
|
14130
14385
|
}
|
|
14131
14386
|
}
|
|
14132
14387
|
if (registered.length > 0) {
|
|
14133
14388
|
console.log(
|
|
14134
|
-
` ${symbols.success} iamu-sync MCP server registered for ${registered.join(", ")} ${
|
|
14389
|
+
` ${symbols.success} iamu-sync MCP server registered for ${registered.join(", ")} ${chalk9.dim("\u2014 restart your agent session to load the team tools")}`
|
|
14135
14390
|
);
|
|
14136
14391
|
}
|
|
14137
14392
|
}
|
|
@@ -14152,10 +14407,10 @@ async function authDisconnect() {
|
|
|
14152
14407
|
}
|
|
14153
14408
|
console.log();
|
|
14154
14409
|
console.log(` ${symbols.success} Disconnected from cloud.`);
|
|
14155
|
-
console.log(
|
|
14410
|
+
console.log(chalk9.dim(" Local entities preserved. Re-link anytime."));
|
|
14156
14411
|
console.log();
|
|
14157
14412
|
} catch (err) {
|
|
14158
|
-
console.error(
|
|
14413
|
+
console.error(chalk9.red(` ${err.message}`));
|
|
14159
14414
|
process.exitCode = 1;
|
|
14160
14415
|
}
|
|
14161
14416
|
}
|
|
@@ -14187,17 +14442,17 @@ async function authStatus(opts) {
|
|
|
14187
14442
|
console.log();
|
|
14188
14443
|
if (config.cloud_linked) {
|
|
14189
14444
|
console.log(
|
|
14190
|
-
` ${symbols.success} Cloud-linked: ${
|
|
14445
|
+
` ${symbols.success} Cloud-linked: ${chalk9.cyan(config.cloud_api_url)}`
|
|
14191
14446
|
);
|
|
14192
|
-
console.log(` ${
|
|
14447
|
+
console.log(` ${chalk9.dim("Project:")} ${config.cloud_project_id}`);
|
|
14193
14448
|
console.log(
|
|
14194
|
-
` ${
|
|
14449
|
+
` ${chalk9.dim("Token:")} ${token ? "stored" : chalk9.yellow("missing")}`
|
|
14195
14450
|
);
|
|
14196
14451
|
} else {
|
|
14197
|
-
console.log(` ${
|
|
14452
|
+
console.log(` ${chalk9.dim("Local-only \u2014 not cloud-linked.")}`);
|
|
14198
14453
|
if (token) {
|
|
14199
14454
|
console.log(
|
|
14200
|
-
` ${
|
|
14455
|
+
` ${chalk9.dim("Token stored for")} ${apiUrl} ${chalk9.dim("\u2014 run iamu auth login to link.")}`
|
|
14201
14456
|
);
|
|
14202
14457
|
}
|
|
14203
14458
|
}
|
|
@@ -14233,11 +14488,11 @@ var init_auth = __esm({
|
|
|
14233
14488
|
});
|
|
14234
14489
|
|
|
14235
14490
|
// src/ui/journey-diff.ts
|
|
14236
|
-
import
|
|
14491
|
+
import chalk10 from "chalk";
|
|
14237
14492
|
function formatJourneyDiffTerminal(diff) {
|
|
14238
14493
|
const lines = [];
|
|
14239
14494
|
lines.push(
|
|
14240
|
-
|
|
14495
|
+
chalk10.bold(" Journey diff") + chalk10.dim(` (vs ${diff.baselineRunId.slice(0, 30)}\u2026):`)
|
|
14241
14496
|
);
|
|
14242
14497
|
for (const step of diff.steps) {
|
|
14243
14498
|
let sym = " ";
|
|
@@ -14245,40 +14500,40 @@ function formatJourneyDiffTerminal(diff) {
|
|
|
14245
14500
|
let statusColored = statusLabel;
|
|
14246
14501
|
switch (step.status) {
|
|
14247
14502
|
case "resolved":
|
|
14248
|
-
sym =
|
|
14249
|
-
statusColored =
|
|
14503
|
+
sym = chalk10.green("\u2713");
|
|
14504
|
+
statusColored = chalk10.green(statusLabel);
|
|
14250
14505
|
break;
|
|
14251
14506
|
case "persists":
|
|
14252
|
-
sym =
|
|
14253
|
-
statusColored =
|
|
14507
|
+
sym = chalk10.red("\u2716");
|
|
14508
|
+
statusColored = chalk10.red(statusLabel);
|
|
14254
14509
|
break;
|
|
14255
14510
|
case "regression":
|
|
14256
|
-
sym =
|
|
14257
|
-
statusColored =
|
|
14511
|
+
sym = chalk10.yellow("!");
|
|
14512
|
+
statusColored = chalk10.yellow(statusLabel);
|
|
14258
14513
|
break;
|
|
14259
14514
|
case "stalled":
|
|
14260
|
-
sym =
|
|
14261
|
-
statusColored =
|
|
14515
|
+
sym = chalk10.red("\xD7");
|
|
14516
|
+
statusColored = chalk10.red(statusLabel);
|
|
14262
14517
|
break;
|
|
14263
14518
|
case "new_path":
|
|
14264
|
-
sym =
|
|
14265
|
-
statusColored =
|
|
14519
|
+
sym = chalk10.cyan("+");
|
|
14520
|
+
statusColored = chalk10.cyan(statusLabel);
|
|
14266
14521
|
break;
|
|
14267
14522
|
case "bypassed":
|
|
14268
|
-
sym =
|
|
14269
|
-
statusColored =
|
|
14523
|
+
sym = chalk10.dim("\u25CB");
|
|
14524
|
+
statusColored = chalk10.dim(statusLabel);
|
|
14270
14525
|
break;
|
|
14271
14526
|
default:
|
|
14272
|
-
sym =
|
|
14273
|
-
statusColored =
|
|
14527
|
+
sym = chalk10.dim("\xB7");
|
|
14528
|
+
statusColored = chalk10.dim(statusLabel);
|
|
14274
14529
|
break;
|
|
14275
14530
|
}
|
|
14276
14531
|
const route = journeyStepRoute(step);
|
|
14277
14532
|
const action = step.currentStep?.action || step.baselineStep?.action || "(no action)";
|
|
14278
14533
|
const stepNum = step.currentStep ? `[${step.currentStep.step_number}]` : step.baselineStep ? `[${step.baselineStep.step_number}b]` : `[${step.index}]`;
|
|
14279
|
-
const note = step.status === "same" ? "" :
|
|
14534
|
+
const note = step.status === "same" ? "" : chalk10.dim(` (${step.summary})`);
|
|
14280
14535
|
lines.push(
|
|
14281
|
-
` ${sym} ${
|
|
14536
|
+
` ${sym} ${chalk10.dim(stepNum.padEnd(5))} ${chalk10.dim(route.slice(0, 20).padEnd(21))} ${action.slice(0, 35).padEnd(36)} ${statusColored}${note}`
|
|
14282
14537
|
);
|
|
14283
14538
|
}
|
|
14284
14539
|
return lines.join("\n");
|
|
@@ -14295,7 +14550,7 @@ var init_journey_diff2 = __esm({
|
|
|
14295
14550
|
});
|
|
14296
14551
|
|
|
14297
14552
|
// src/ui/table.ts
|
|
14298
|
-
import
|
|
14553
|
+
import chalk11 from "chalk";
|
|
14299
14554
|
function stripAnsi(str2) {
|
|
14300
14555
|
return str2.replace(ANSI_REGEX, "");
|
|
14301
14556
|
}
|
|
@@ -14341,7 +14596,7 @@ function formatTable(items, columns, options) {
|
|
|
14341
14596
|
const headerParts = columns.map(
|
|
14342
14597
|
(col, i) => padRight(col.header, colWidths[i])
|
|
14343
14598
|
);
|
|
14344
|
-
lines.push(` ${
|
|
14599
|
+
lines.push(` ${chalk11.dim(headerParts.join(" "))}`);
|
|
14345
14600
|
for (const item of items) {
|
|
14346
14601
|
const rowParts = columns.map((col, i) => {
|
|
14347
14602
|
let val = col.value(item);
|
|
@@ -14374,7 +14629,7 @@ import {
|
|
|
14374
14629
|
readlinkSync,
|
|
14375
14630
|
realpathSync as realpathSync2
|
|
14376
14631
|
} from "fs";
|
|
14377
|
-
import
|
|
14632
|
+
import path19 from "path";
|
|
14378
14633
|
function git(args, cwd) {
|
|
14379
14634
|
return execFileSync("git", args, {
|
|
14380
14635
|
cwd,
|
|
@@ -14385,13 +14640,13 @@ function git(args, cwd) {
|
|
|
14385
14640
|
}
|
|
14386
14641
|
function hashFile(absPath) {
|
|
14387
14642
|
const hash = createHash4("sha256");
|
|
14388
|
-
const
|
|
14389
|
-
if (
|
|
14643
|
+
const stat3 = lstatSync(absPath);
|
|
14644
|
+
if (stat3.isSymbolicLink()) {
|
|
14390
14645
|
hash.update(`symlink:${readlinkSync(absPath)}`);
|
|
14391
14646
|
return hash.digest("hex");
|
|
14392
14647
|
}
|
|
14393
|
-
if (!
|
|
14394
|
-
hash.update(`${
|
|
14648
|
+
if (!stat3.isFile()) {
|
|
14649
|
+
hash.update(`${stat3.isDirectory() ? "dir" : "other"}`);
|
|
14395
14650
|
return hash.digest("hex");
|
|
14396
14651
|
}
|
|
14397
14652
|
const fd = openSync(absPath, "r");
|
|
@@ -14427,8 +14682,8 @@ function detectWorktreeState(projectRoot, iamuDirName = IAMU_DIR) {
|
|
|
14427
14682
|
const top = git(["rev-parse", "--show-toplevel"], projectRoot).toString("utf8").trim();
|
|
14428
14683
|
if (!top) return void 0;
|
|
14429
14684
|
const realTop = realpathSync2(top);
|
|
14430
|
-
const realIamu =
|
|
14431
|
-
const iamuRel =
|
|
14685
|
+
const realIamu = path19.join(realpathSync2(projectRoot), iamuDirName);
|
|
14686
|
+
const iamuRel = path19.relative(realTop, realIamu).split(path19.sep).join("/");
|
|
14432
14687
|
const pathspec = iamuRel.startsWith("..") ? [":(top)"] : [":(top)", `:(top,exclude,literal)${iamuRel}`];
|
|
14433
14688
|
const status2 = git(
|
|
14434
14689
|
[
|
|
@@ -14458,7 +14713,7 @@ function detectWorktreeState(projectRoot, iamuDirName = IAMU_DIR) {
|
|
|
14458
14713
|
);
|
|
14459
14714
|
for (const file of sorted.slice(0, MAX_UNTRACKED_HASHED)) {
|
|
14460
14715
|
const rel = file.replace(/\/$/, "");
|
|
14461
|
-
hash.update(`${file}\0${hashFile(
|
|
14716
|
+
hash.update(`${file}\0${hashFile(path19.join(realTop, rel))}
|
|
14462
14717
|
`);
|
|
14463
14718
|
}
|
|
14464
14719
|
if (sorted.length > MAX_UNTRACKED_HASHED) {
|
|
@@ -14633,12 +14888,12 @@ __export(start_run_exports, {
|
|
|
14633
14888
|
testabilityTarget: () => testabilityTarget
|
|
14634
14889
|
});
|
|
14635
14890
|
import fs24 from "fs/promises";
|
|
14636
|
-
import
|
|
14637
|
-
import
|
|
14891
|
+
import path20 from "path";
|
|
14892
|
+
import chalk12 from "chalk";
|
|
14638
14893
|
async function testabilityTarget(projectRoot) {
|
|
14639
14894
|
try {
|
|
14640
14895
|
const raw = await fs24.readFile(
|
|
14641
|
-
|
|
14896
|
+
path20.join(projectRoot, "iamu", "testability.md"),
|
|
14642
14897
|
"utf8"
|
|
14643
14898
|
);
|
|
14644
14899
|
const { frontmatter } = parseFrontmatter(raw);
|
|
@@ -14822,19 +15077,28 @@ async function startRun(scenarioSlug, opts) {
|
|
|
14822
15077
|
...viewport ? { viewport } : {}
|
|
14823
15078
|
};
|
|
14824
15079
|
await atomicWriteFile(
|
|
14825
|
-
|
|
15080
|
+
path20.join(run.absPath, "walkthrough.json"),
|
|
14826
15081
|
JSON.stringify(manifest, null, 2) + "\n"
|
|
14827
15082
|
);
|
|
15083
|
+
const liveRes = await registerLiveRun({
|
|
15084
|
+
projectRoot,
|
|
15085
|
+
runId: run.runId,
|
|
15086
|
+
scenarioSlug,
|
|
15087
|
+
targetUrl: start2.url,
|
|
15088
|
+
startedAt: manifest.created_at,
|
|
15089
|
+
lenses: manifest.lenses
|
|
15090
|
+
});
|
|
14828
15091
|
if (opts.json) {
|
|
14829
15092
|
console.log(
|
|
14830
15093
|
JSON.stringify(
|
|
14831
15094
|
{
|
|
14832
15095
|
run_id: run.runId,
|
|
14833
|
-
path:
|
|
15096
|
+
path: path20.relative(projectRoot, run.absPath),
|
|
14834
15097
|
scenario_slug: scenarioSlug,
|
|
14835
15098
|
target_url: start2.url,
|
|
14836
15099
|
target_reachable: targetReachable,
|
|
14837
15100
|
...targetWarning ? { target_warning: targetWarning } : {},
|
|
15101
|
+
...liveRes?.viewerUrl ? { live_viewer_url: liveRes.viewerUrl } : {},
|
|
14838
15102
|
persona_slug: fm.persona,
|
|
14839
15103
|
outline_slug: fm.outline,
|
|
14840
15104
|
models,
|
|
@@ -14851,55 +15115,60 @@ async function startRun(scenarioSlug, opts) {
|
|
|
14851
15115
|
return;
|
|
14852
15116
|
}
|
|
14853
15117
|
console.log();
|
|
14854
|
-
console.log(` ${symbols.success} Run started: ${
|
|
14855
|
-
|
|
14856
|
-
|
|
14857
|
-
|
|
14858
|
-
|
|
15118
|
+
console.log(` ${symbols.success} Run started: ${chalk12.cyan(run.runId)}`);
|
|
15119
|
+
if (liveRes?.viewerUrl) {
|
|
15120
|
+
console.log(
|
|
15121
|
+
` Follow this run live (beta): ${chalk12.cyan(liveRes.viewerUrl)}`
|
|
15122
|
+
);
|
|
15123
|
+
}
|
|
15124
|
+
console.log(` ${chalk12.dim("scenario:")} ${scenarioSlug}`);
|
|
15125
|
+
console.log(` ${chalk12.dim("persona:")} ${fm.persona}`);
|
|
15126
|
+
console.log(` ${chalk12.dim("outline:")} ${fm.outline}`);
|
|
15127
|
+
console.log(` ${chalk12.dim("target:")} ${start2.url}`);
|
|
14859
15128
|
console.log(
|
|
14860
|
-
` ${
|
|
15129
|
+
` ${chalk12.dim("models:")} walker: ${chalk12.cyan(walker)} \xB7 judge: ${chalk12.cyan(judge)} \xB7 matcher: ${chalk12.cyan(matcher)}`
|
|
14861
15130
|
);
|
|
14862
15131
|
if (targetWarning) {
|
|
14863
|
-
console.log(` ${symbols.warning} ${
|
|
15132
|
+
console.log(` ${symbols.warning} ${chalk12.yellow(targetWarning)}`);
|
|
14864
15133
|
}
|
|
14865
|
-
if (environment) console.log(` ${
|
|
15134
|
+
if (environment) console.log(` ${chalk12.dim("env:")} ${environment}`);
|
|
14866
15135
|
if (build) {
|
|
14867
|
-
console.log(` ${
|
|
15136
|
+
console.log(` ${chalk12.dim("build:")} ${formatBuild(build)}`);
|
|
14868
15137
|
}
|
|
14869
15138
|
if (viewport) {
|
|
14870
|
-
console.log(` ${
|
|
15139
|
+
console.log(` ${chalk12.dim("device:")} ${formatViewport(viewport)}`);
|
|
14871
15140
|
}
|
|
14872
15141
|
if (device?.warning) {
|
|
14873
|
-
console.log(` ${
|
|
15142
|
+
console.log(` ${chalk12.yellow("!")} ${device.warning}`);
|
|
14874
15143
|
}
|
|
14875
15144
|
if (revisit.length > 0) {
|
|
14876
15145
|
console.log(
|
|
14877
|
-
` ${
|
|
15146
|
+
` ${chalk12.dim("re-check:")} ${revisit.length} place${revisit.length === 1 ? "" : "s"} where fixes await a re-run`
|
|
14878
15147
|
);
|
|
14879
15148
|
}
|
|
14880
15149
|
console.log(
|
|
14881
|
-
` ${
|
|
15150
|
+
` ${chalk12.dim("path:")} ${path20.relative(projectRoot, run.absPath)}`
|
|
14882
15151
|
);
|
|
14883
15152
|
console.log();
|
|
14884
|
-
console.log(` ${
|
|
15153
|
+
console.log(` ${chalk12.bold("Next steps for blind execution:")}`);
|
|
14885
15154
|
console.log(
|
|
14886
|
-
` 1. Size browser: ${
|
|
15155
|
+
` 1. Size browser: ${chalk12.cyan(`iamu browse start --run ${run.runId}`)}`
|
|
14887
15156
|
);
|
|
14888
15157
|
console.log(
|
|
14889
|
-
` 2. Get walk prompt: ${
|
|
15158
|
+
` 2. Get walk prompt: ${chalk12.cyan(`iamu instructions walk --scenario ${scenarioSlug} --run ${run.runId}`)}`
|
|
14890
15159
|
);
|
|
14891
15160
|
console.log(
|
|
14892
|
-
` 3. Dispatch walker: Spawn a ${
|
|
15161
|
+
` 3. Dispatch walker: Spawn a ${chalk12.yellow("fresh blind subagent")} with that prompt (do NOT script steps locally)`
|
|
14893
15162
|
);
|
|
14894
15163
|
console.log(
|
|
14895
|
-
` 4. Drive product: Walker records via ${
|
|
15164
|
+
` 4. Drive product: Walker records via ${chalk12.cyan(`iamu browse step --run ${run.runId} ...`)}`
|
|
14896
15165
|
);
|
|
14897
15166
|
console.log(
|
|
14898
|
-
` 5. Complete run: ${
|
|
15167
|
+
` 5. Complete run: ${chalk12.cyan(`iamu complete ${run.runId}`)}`
|
|
14899
15168
|
);
|
|
14900
15169
|
console.log();
|
|
14901
15170
|
console.log(
|
|
14902
|
-
` ${
|
|
15171
|
+
` ${chalk12.dim("Tip: Ensure your agent session has terminal auto-approval enabled so walkthrough steps run unattended.")}`
|
|
14903
15172
|
);
|
|
14904
15173
|
console.log();
|
|
14905
15174
|
}
|
|
@@ -14911,6 +15180,7 @@ var init_start_run = __esm({
|
|
|
14911
15180
|
init_build_info();
|
|
14912
15181
|
init_symbols();
|
|
14913
15182
|
init_context4();
|
|
15183
|
+
init_live_run_client();
|
|
14914
15184
|
}
|
|
14915
15185
|
});
|
|
14916
15186
|
|
|
@@ -14920,8 +15190,8 @@ __export(report_exports, {
|
|
|
14920
15190
|
report: () => report
|
|
14921
15191
|
});
|
|
14922
15192
|
import { promises as fs25 } from "fs";
|
|
14923
|
-
import
|
|
14924
|
-
import
|
|
15193
|
+
import path21 from "path";
|
|
15194
|
+
import chalk13 from "chalk";
|
|
14925
15195
|
async function report(scenario, opts) {
|
|
14926
15196
|
const ctx = await resolveProject(opts);
|
|
14927
15197
|
if (!ctx) return;
|
|
@@ -14931,7 +15201,7 @@ async function report(scenario, opts) {
|
|
|
14931
15201
|
if (opts?.json) {
|
|
14932
15202
|
console.log("[]");
|
|
14933
15203
|
} else {
|
|
14934
|
-
console.log(
|
|
15204
|
+
console.log(chalk13.dim(" No runs yet. Run a walkthrough first."));
|
|
14935
15205
|
}
|
|
14936
15206
|
return;
|
|
14937
15207
|
}
|
|
@@ -14940,7 +15210,7 @@ async function report(scenario, opts) {
|
|
|
14940
15210
|
try {
|
|
14941
15211
|
const dir = runDir(projectRoot, rid);
|
|
14942
15212
|
const mRaw = await fs25.readFile(
|
|
14943
|
-
|
|
15213
|
+
path21.join(dir, "walkthrough.json"),
|
|
14944
15214
|
"utf8"
|
|
14945
15215
|
);
|
|
14946
15216
|
const manifest = JSON.parse(mRaw);
|
|
@@ -14949,7 +15219,7 @@ async function report(scenario, opts) {
|
|
|
14949
15219
|
let canonical = null;
|
|
14950
15220
|
try {
|
|
14951
15221
|
const cRaw = await fs25.readFile(
|
|
14952
|
-
|
|
15222
|
+
path21.join(dir, "canonical.json"),
|
|
14953
15223
|
"utf8"
|
|
14954
15224
|
);
|
|
14955
15225
|
canonical = JSON.parse(cRaw);
|
|
@@ -14964,7 +15234,7 @@ async function report(scenario, opts) {
|
|
|
14964
15234
|
console.log("[]");
|
|
14965
15235
|
} else {
|
|
14966
15236
|
const msg = scenario ? `No completed runs for scenario: ${scenario}` : "No completed runs yet.";
|
|
14967
|
-
console.log(
|
|
15237
|
+
console.log(chalk13.dim(` ${msg}`));
|
|
14968
15238
|
}
|
|
14969
15239
|
return;
|
|
14970
15240
|
}
|
|
@@ -14996,37 +15266,37 @@ async function report(scenario, opts) {
|
|
|
14996
15266
|
const c = run.canonical;
|
|
14997
15267
|
console.log();
|
|
14998
15268
|
console.log(
|
|
14999
|
-
|
|
15269
|
+
chalk13.bold(` ${run.manifest.scenario_slug}`) + chalk13.dim(` \u2014 ${run.runId.slice(0, 30)}\u2026`)
|
|
15000
15270
|
);
|
|
15001
15271
|
console.log(
|
|
15002
|
-
` ${
|
|
15272
|
+
` ${chalk13.dim("url:")} ${run.manifest.target_url} ${chalk13.dim("completed:")} ${run.manifest.completed_at}`
|
|
15003
15273
|
);
|
|
15004
15274
|
const env = run.manifest.environment ?? c?.environment;
|
|
15005
15275
|
if (env) {
|
|
15006
|
-
console.log(` ${
|
|
15276
|
+
console.log(` ${chalk13.dim("env:")} ${env}`);
|
|
15007
15277
|
}
|
|
15008
15278
|
const build = run.manifest.build ?? c?.build;
|
|
15009
15279
|
if (build) {
|
|
15010
|
-
console.log(` ${
|
|
15280
|
+
console.log(` ${chalk13.dim("build:")} ${formatBuild(build)}`);
|
|
15011
15281
|
}
|
|
15012
15282
|
const viewport = run.manifest.viewport ?? c?.viewport;
|
|
15013
15283
|
if (viewport) {
|
|
15014
|
-
console.log(` ${
|
|
15284
|
+
console.log(` ${chalk13.dim("device:")} ${formatViewport(viewport)}`);
|
|
15015
15285
|
}
|
|
15016
15286
|
const viewUrl = await pushedRunUrl(projectRoot, run.runId);
|
|
15017
15287
|
if (viewUrl) {
|
|
15018
|
-
console.log(` ${
|
|
15288
|
+
console.log(` ${chalk13.dim("view:")} ${chalk13.underline(viewUrl)}`);
|
|
15019
15289
|
}
|
|
15020
15290
|
if (c) {
|
|
15021
15291
|
const v = c.verification;
|
|
15022
15292
|
if (v) {
|
|
15023
15293
|
console.log();
|
|
15024
|
-
console.log(
|
|
15294
|
+
console.log(chalk13.bold(" Since this scenario's last run:"));
|
|
15025
15295
|
if (v.resolved.length > 0)
|
|
15026
15296
|
console.log(` ${symbols.success} ${v.resolved.length} resolved`);
|
|
15027
15297
|
if (v.not_observed && v.not_observed.length > 0)
|
|
15028
15298
|
console.log(
|
|
15029
|
-
` ${symbols.pending} ${v.not_observed.length} not seen this run ${
|
|
15299
|
+
` ${symbols.pending} ${v.not_observed.length} not seen this run ${chalk13.dim("(not evidence of a fix)")}`
|
|
15030
15300
|
);
|
|
15031
15301
|
if (v.persists.length > 0)
|
|
15032
15302
|
console.log(` ${symbols.error} ${v.persists.length} persists`);
|
|
@@ -15052,20 +15322,20 @@ async function report(scenario, opts) {
|
|
|
15052
15322
|
}
|
|
15053
15323
|
console.log();
|
|
15054
15324
|
if (c.findings.length === 0) {
|
|
15055
|
-
console.log(
|
|
15325
|
+
console.log(chalk13.dim(" No findings."));
|
|
15056
15326
|
} else {
|
|
15057
15327
|
const hinders = c.findings.filter(
|
|
15058
15328
|
(f) => f.type === "hinders" || f.type === "missing" || f.type === "incorrect"
|
|
15059
15329
|
);
|
|
15060
15330
|
const helps = c.findings.filter((f) => f.type === "helps");
|
|
15061
15331
|
if (hinders.length > 0) {
|
|
15062
|
-
console.log(
|
|
15332
|
+
console.log(chalk13.bold(" Issues:"));
|
|
15063
15333
|
const rows = formatTable(hinders, [
|
|
15064
15334
|
{
|
|
15065
15335
|
header: "severity",
|
|
15066
15336
|
value: (f) => {
|
|
15067
15337
|
const sev = f.severity ?? "\u2014";
|
|
15068
|
-
return sev === "critical" ?
|
|
15338
|
+
return sev === "critical" ? chalk13.red(sev) : sev === "major" ? chalk13.yellow(sev) : chalk13.dim(sev);
|
|
15069
15339
|
}
|
|
15070
15340
|
},
|
|
15071
15341
|
{ header: "type", value: (f) => f.type },
|
|
@@ -15075,24 +15345,24 @@ async function report(scenario, opts) {
|
|
|
15075
15345
|
}
|
|
15076
15346
|
if (helps.length > 0) {
|
|
15077
15347
|
console.log();
|
|
15078
|
-
console.log(
|
|
15348
|
+
console.log(chalk13.bold(" Strengths:"));
|
|
15079
15349
|
for (const f of helps) {
|
|
15080
15350
|
console.log(
|
|
15081
|
-
` ${
|
|
15351
|
+
` ${chalk13.green("helps")} ${f.ui_fact ?? f.id}`
|
|
15082
15352
|
);
|
|
15083
15353
|
}
|
|
15084
15354
|
}
|
|
15085
15355
|
}
|
|
15086
15356
|
if (c.human_test_overall?.answer) {
|
|
15087
15357
|
console.log();
|
|
15088
|
-
console.log(
|
|
15358
|
+
console.log(chalk13.bold(" Verdict: ") + c.human_test_overall.answer);
|
|
15089
15359
|
}
|
|
15090
15360
|
}
|
|
15091
15361
|
console.log();
|
|
15092
15362
|
return;
|
|
15093
15363
|
}
|
|
15094
15364
|
console.log();
|
|
15095
|
-
console.log(
|
|
15365
|
+
console.log(chalk13.bold(" Recent runs:"));
|
|
15096
15366
|
console.log();
|
|
15097
15367
|
for (const run of completedRuns.slice(0, 10)) {
|
|
15098
15368
|
const c = run.canonical;
|
|
@@ -15102,13 +15372,13 @@ async function report(scenario, opts) {
|
|
|
15102
15372
|
).length ?? 0;
|
|
15103
15373
|
const verdict = c?.human_test_overall?.answer?.slice(0, 40) ?? "\u2014";
|
|
15104
15374
|
console.log(
|
|
15105
|
-
` ${
|
|
15375
|
+
` ${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)}`
|
|
15106
15376
|
);
|
|
15107
15377
|
}
|
|
15108
15378
|
const dashboard = await projectDashboardUrl(projectRoot);
|
|
15109
15379
|
if (dashboard) {
|
|
15110
15380
|
console.log();
|
|
15111
|
-
console.log(` ${
|
|
15381
|
+
console.log(` ${chalk13.dim("cloud:")} ${chalk13.underline(dashboard)}`);
|
|
15112
15382
|
}
|
|
15113
15383
|
console.log();
|
|
15114
15384
|
}
|
|
@@ -15132,7 +15402,7 @@ __export(open_exports, {
|
|
|
15132
15402
|
});
|
|
15133
15403
|
import { existsSync as existsSync6 } from "fs";
|
|
15134
15404
|
import { isCancel as isCancel2, select as select2 } from "@clack/prompts";
|
|
15135
|
-
import
|
|
15405
|
+
import chalk14 from "chalk";
|
|
15136
15406
|
async function openDashboard(runId, opts) {
|
|
15137
15407
|
const ctx = await resolveProject();
|
|
15138
15408
|
if (!ctx) return;
|
|
@@ -15143,7 +15413,7 @@ async function openDashboard(runId, opts) {
|
|
|
15143
15413
|
const pushed = await pushedRunUrl(projectRoot, runId);
|
|
15144
15414
|
if (!pushed) {
|
|
15145
15415
|
console.error(
|
|
15146
|
-
` ${
|
|
15416
|
+
` ${chalk14.yellow(symbols.info)} Run ${runId} is not on Iamu Cloud yet. Run ${chalk14.cyan("iamu sync")} to push it.`
|
|
15147
15417
|
);
|
|
15148
15418
|
process.exitCode = 1;
|
|
15149
15419
|
return;
|
|
@@ -15163,19 +15433,19 @@ async function openDashboard(runId, opts) {
|
|
|
15163
15433
|
console.log(
|
|
15164
15434
|
` ${symbols.success} Opening Iamu Cloud ${runId ? "walkthrough" : "dashboard"}:`
|
|
15165
15435
|
);
|
|
15166
|
-
console.log(` ${
|
|
15436
|
+
console.log(` ${chalk14.cyan(url)}`);
|
|
15167
15437
|
console.log();
|
|
15168
15438
|
openBrowser(url);
|
|
15169
15439
|
return;
|
|
15170
15440
|
}
|
|
15171
15441
|
const say = opts?.printOnly ? console.error : console.log;
|
|
15172
15442
|
say();
|
|
15173
|
-
say(` ${
|
|
15443
|
+
say(` ${chalk14.yellow(symbols.info)} Project is not linked to Iamu Cloud.`);
|
|
15174
15444
|
say(
|
|
15175
|
-
` Run ${
|
|
15445
|
+
` Run ${chalk14.cyan("iamu auth login")} to link and view live collaborative reports.`
|
|
15176
15446
|
);
|
|
15177
15447
|
say(
|
|
15178
|
-
` Or run ${
|
|
15448
|
+
` Or run ${chalk14.cyan("iamu report")} to inspect results in your terminal.
|
|
15179
15449
|
`
|
|
15180
15450
|
);
|
|
15181
15451
|
if (opts?.printOnly) {
|
|
@@ -15800,7 +16070,7 @@ var findings_exports = {};
|
|
|
15800
16070
|
__export(findings_exports, {
|
|
15801
16071
|
findings: () => findings
|
|
15802
16072
|
});
|
|
15803
|
-
import
|
|
16073
|
+
import chalk15 from "chalk";
|
|
15804
16074
|
async function findings(opts) {
|
|
15805
16075
|
const ctx = await resolveProject(opts);
|
|
15806
16076
|
if (!ctx) return;
|
|
@@ -15852,7 +16122,7 @@ async function findings(opts) {
|
|
|
15852
16122
|
}
|
|
15853
16123
|
if (filtered.length === 0) {
|
|
15854
16124
|
const qualifier = opts?.open ? "open " : opts?.resolved ? "resolved " : opts?.dismissed ? "dismissed " : "";
|
|
15855
|
-
console.log(
|
|
16125
|
+
console.log(chalk15.dim(` No ${qualifier}findings.`));
|
|
15856
16126
|
return;
|
|
15857
16127
|
}
|
|
15858
16128
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -15884,13 +16154,13 @@ async function findings(opts) {
|
|
|
15884
16154
|
const tb = typeOrder[b.frontmatter.type] ?? 9;
|
|
15885
16155
|
return ta - tb;
|
|
15886
16156
|
});
|
|
15887
|
-
console.log(
|
|
16157
|
+
console.log(chalk15.bold(` ${scenario}`) + chalk15.dim(` (${items.length})`));
|
|
15888
16158
|
for (const e of items) {
|
|
15889
16159
|
const sev = (e.frontmatter.severity ?? "\u2014").padEnd(11);
|
|
15890
|
-
const sevColor = e.frontmatter.severity === "critical" ?
|
|
16160
|
+
const sevColor = e.frontmatter.severity === "critical" ? chalk15.red : e.frontmatter.severity === "major" ? chalk15.yellow : chalk15.dim;
|
|
15891
16161
|
const fixState = fixStateOf(e.frontmatter.slug);
|
|
15892
16162
|
const status2 = fixState ? FIX_STATE_LABEL[fixState] : e.frontmatter.triage_status ?? "open";
|
|
15893
|
-
const statusColor = fixState === "verified" ?
|
|
16163
|
+
const statusColor = fixState === "verified" ? chalk15.green : fixState === "recurred" ? chalk15.red : fixState === "awaiting_rerun" ? chalk15.yellow : status2 === "dismissed" ? chalk15.dim : chalk15.white;
|
|
15894
16164
|
const title = e.frontmatter.title ?? e.frontmatter.ui_fact ?? e.frontmatter.slug;
|
|
15895
16165
|
console.log(
|
|
15896
16166
|
` ${sevColor(sev)} ${e.frontmatter.type.padEnd(10)} ${statusColor(status2.padEnd(15))} ${title}`
|
|
@@ -15910,13 +16180,13 @@ async function findings(opts) {
|
|
|
15910
16180
|
(e) => e.frontmatter.triage_status === "dismissed" || e.frontmatter.triage_status === "wont_fix"
|
|
15911
16181
|
).length;
|
|
15912
16182
|
console.log(
|
|
15913
|
-
|
|
16183
|
+
chalk15.dim(
|
|
15914
16184
|
` ${total} total: ${open2} open, ${awaiting} awaiting re-run, ${verified} verified${recurred > 0 ? `, ${recurred} recurred` : ""}, ${dismissed} dismissed`
|
|
15915
16185
|
)
|
|
15916
16186
|
);
|
|
15917
16187
|
if (awaiting > 0) {
|
|
15918
16188
|
console.log(
|
|
15919
|
-
|
|
16189
|
+
chalk15.dim(
|
|
15920
16190
|
" awaiting re-run = fix applied, no later run has shown it working yet \u2014 `iamu status` lists the scenarios to re-run"
|
|
15921
16191
|
)
|
|
15922
16192
|
);
|
|
@@ -15943,7 +16213,7 @@ var triage_exports = {};
|
|
|
15943
16213
|
__export(triage_exports, {
|
|
15944
16214
|
triage: () => triage
|
|
15945
16215
|
});
|
|
15946
|
-
import
|
|
16216
|
+
import chalk16 from "chalk";
|
|
15947
16217
|
function defaultRule(kind, findings2) {
|
|
15948
16218
|
const titles = findings2.map((f) => f.frontmatter.title ?? f.frontmatter.ui_fact ?? f.slug).join("; ");
|
|
15949
16219
|
return kind === "walker_error" ? `Earlier walkers got this wrong: ${titles}` : `Don't report: ${titles}`;
|
|
@@ -16105,13 +16375,13 @@ async function triage(refs, opts) {
|
|
|
16105
16375
|
console.log();
|
|
16106
16376
|
for (const f of loaded) {
|
|
16107
16377
|
console.log(
|
|
16108
|
-
` ${
|
|
16378
|
+
` ${chalk16.green("\u2713")} ${status2.data}${reason ? ` (${reason})` : ""}: ${chalk16.cyan(f.slug)}`
|
|
16109
16379
|
);
|
|
16110
16380
|
}
|
|
16111
16381
|
if (guidance) {
|
|
16112
16382
|
const where = scope.outline ? `outline ${scope.outline}` : scope.capability ? `capability ${scope.capability}` : "the whole project";
|
|
16113
16383
|
console.log(
|
|
16114
|
-
` ${
|
|
16384
|
+
` ${chalk16.green("\u2713")} Tester guidance: iamu/guidance/${guidance.slug}.md (${where}) \u2014 the next walk will not report this`
|
|
16115
16385
|
);
|
|
16116
16386
|
}
|
|
16117
16387
|
console.log();
|
|
@@ -16133,14 +16403,14 @@ var serve_exports = {};
|
|
|
16133
16403
|
__export(serve_exports, {
|
|
16134
16404
|
serve: () => serve
|
|
16135
16405
|
});
|
|
16136
|
-
import
|
|
16406
|
+
import chalk17 from "chalk";
|
|
16137
16407
|
async function serve(opts) {
|
|
16138
16408
|
const printOnly = opts?.open === false;
|
|
16139
16409
|
const say = printOnly ? console.error : console.log;
|
|
16140
16410
|
say();
|
|
16141
|
-
say(` ${
|
|
16411
|
+
say(` ${chalk17.yellow(symbols.info)} The local web UI has been retired.`);
|
|
16142
16412
|
say(
|
|
16143
|
-
` ${printOnly ? "Printing the Iamu Cloud dashboard URL instead" : "Opening Iamu Cloud dashboard instead"}... (use ${
|
|
16413
|
+
` ${printOnly ? "Printing the Iamu Cloud dashboard URL instead" : "Opening Iamu Cloud dashboard instead"}... (use ${chalk17.cyan("iamu open")} or ${chalk17.cyan("iamu report")})`
|
|
16144
16414
|
);
|
|
16145
16415
|
say();
|
|
16146
16416
|
await openDashboard(void 0, { printOnly });
|
|
@@ -16163,7 +16433,7 @@ import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
|
|
|
16163
16433
|
import { mkdir as mkdir4, writeFile as writeFile3 } from "fs/promises";
|
|
16164
16434
|
import { basename as basename2, join as join5 } from "path";
|
|
16165
16435
|
import { isCancel as isCancel3, multiselect, select as select3 } from "@clack/prompts";
|
|
16166
|
-
import
|
|
16436
|
+
import chalk18 from "chalk";
|
|
16167
16437
|
function loadPromptTemplates() {
|
|
16168
16438
|
const templates = /* @__PURE__ */ new Map();
|
|
16169
16439
|
const templateDir = getTemplateDir("prompts");
|
|
@@ -16196,9 +16466,9 @@ async function init(opts) {
|
|
|
16196
16466
|
const version2 = getVersion();
|
|
16197
16467
|
if (!options.json) {
|
|
16198
16468
|
console.log();
|
|
16199
|
-
console.log(
|
|
16469
|
+
console.log(chalk18.bold(" Welcome to iamu"));
|
|
16200
16470
|
console.log(
|
|
16201
|
-
|
|
16471
|
+
chalk18.dim(
|
|
16202
16472
|
" Scenario-driven development \u2014 test your product as realistic personas"
|
|
16203
16473
|
)
|
|
16204
16474
|
);
|
|
@@ -16209,7 +16479,7 @@ async function init(opts) {
|
|
|
16209
16479
|
const config2 = await readConfig(projectRoot);
|
|
16210
16480
|
if (!options.json) {
|
|
16211
16481
|
console.log(
|
|
16212
|
-
|
|
16482
|
+
chalk18.yellow(" iamu/ already exists") + chalk18.dim(` (${config2?.project_name ?? "unknown"})`)
|
|
16213
16483
|
);
|
|
16214
16484
|
}
|
|
16215
16485
|
} else {
|
|
@@ -16265,7 +16535,7 @@ Audited and populated during /iamu:init.
|
|
|
16265
16535
|
const detected = detectHosts(projectRoot);
|
|
16266
16536
|
if (!options.json && detected.length > 0) {
|
|
16267
16537
|
console.log(
|
|
16268
|
-
|
|
16538
|
+
chalk18.dim(" Detected: ") + detected.map((h) => h.name).join(", ") + chalk18.dim(" (pre-selected)")
|
|
16269
16539
|
);
|
|
16270
16540
|
console.log();
|
|
16271
16541
|
}
|
|
@@ -16286,7 +16556,7 @@ Audited and populated during /iamu:init.
|
|
|
16286
16556
|
if (isCancel3(selected)) {
|
|
16287
16557
|
process.exitCode = 130;
|
|
16288
16558
|
if (!options.json) {
|
|
16289
|
-
console.log(
|
|
16559
|
+
console.log(chalk18.dim(" Operation cancelled."));
|
|
16290
16560
|
}
|
|
16291
16561
|
return;
|
|
16292
16562
|
}
|
|
@@ -16298,10 +16568,10 @@ Audited and populated during /iamu:init.
|
|
|
16298
16568
|
}
|
|
16299
16569
|
if (!options.json && selectedHosts.length === 0 && detected.length === 0) {
|
|
16300
16570
|
console.log(
|
|
16301
|
-
|
|
16571
|
+
chalk18.dim(" No supported tools detected. Skills not installed.")
|
|
16302
16572
|
);
|
|
16303
16573
|
console.log(
|
|
16304
|
-
|
|
16574
|
+
chalk18.dim(" Re-run `iamu init` after setting up your editor.")
|
|
16305
16575
|
);
|
|
16306
16576
|
}
|
|
16307
16577
|
if (!options.json) console.log();
|
|
@@ -16346,7 +16616,7 @@ Audited and populated during /iamu:init.
|
|
|
16346
16616
|
process.exitCode = prevExitCode;
|
|
16347
16617
|
if (!options.json) {
|
|
16348
16618
|
console.log(
|
|
16349
|
-
|
|
16619
|
+
chalk18.dim(
|
|
16350
16620
|
" Cloud linking skipped. Your local setup is complete and fully functional."
|
|
16351
16621
|
)
|
|
16352
16622
|
);
|
|
@@ -16387,15 +16657,15 @@ Audited and populated during /iamu:init.
|
|
|
16387
16657
|
if (!options.json) {
|
|
16388
16658
|
console.log();
|
|
16389
16659
|
console.log(
|
|
16390
|
-
|
|
16391
|
-
` ${symbols.success} Project configured: ${
|
|
16660
|
+
chalk18.bold(
|
|
16661
|
+
` ${symbols.success} Project configured: ${chalk18.cyan(projectName)}`
|
|
16392
16662
|
)
|
|
16393
16663
|
);
|
|
16394
16664
|
console.log();
|
|
16395
16665
|
if (selectedHosts.length > 0) {
|
|
16396
16666
|
const toolNames = selectedHosts.map((h) => h.name).join(", ");
|
|
16397
16667
|
console.log(
|
|
16398
|
-
` ${
|
|
16668
|
+
` ${chalk18.dim("Tools:")} ${toolNames} ${chalk18.dim(`(${totalSkills} skills + ${totalCommands} commands installed)`)}`
|
|
16399
16669
|
);
|
|
16400
16670
|
}
|
|
16401
16671
|
if (config.cloud_linked && config.cloud_project_id) {
|
|
@@ -16404,65 +16674,65 @@ Audited and populated during /iamu:init.
|
|
|
16404
16674
|
config.cloud_project_id
|
|
16405
16675
|
);
|
|
16406
16676
|
console.log(
|
|
16407
|
-
` ${
|
|
16677
|
+
` ${chalk18.dim("Cloud:")} ${chalk18.green("Linked")} \xB7 ${chalk18.cyan(dashboardUrl)}`
|
|
16408
16678
|
);
|
|
16409
16679
|
} else {
|
|
16410
16680
|
console.log(
|
|
16411
|
-
` ${
|
|
16681
|
+
` ${chalk18.dim("Cloud:")} Local-only ${chalk18.dim("(link anytime with `iamu auth login`)")}`
|
|
16412
16682
|
);
|
|
16413
16683
|
}
|
|
16414
16684
|
console.log();
|
|
16415
16685
|
if (freshInit) {
|
|
16416
|
-
console.log(
|
|
16686
|
+
console.log(chalk18.bold(" Next steps:"));
|
|
16417
16687
|
console.log();
|
|
16418
16688
|
console.log(
|
|
16419
|
-
` ${
|
|
16689
|
+
` ${chalk18.bold("1.")} Start your application's dev server:`
|
|
16420
16690
|
);
|
|
16421
16691
|
console.log(
|
|
16422
|
-
` ${
|
|
16692
|
+
` ${chalk18.cyan("$ pnpm dev")} ${chalk18.dim("(or npm run dev)")}`
|
|
16423
16693
|
);
|
|
16424
16694
|
console.log();
|
|
16425
|
-
console.log(` ${
|
|
16695
|
+
console.log(` ${chalk18.bold("2.")} In your AI agent chat, run:`);
|
|
16426
16696
|
console.log(
|
|
16427
|
-
` ${
|
|
16697
|
+
` ${chalk18.cyan(setupCommand(projectRoot, selectedHosts))}`
|
|
16428
16698
|
);
|
|
16429
16699
|
console.log();
|
|
16430
16700
|
console.log(
|
|
16431
|
-
|
|
16701
|
+
chalk18.dim(
|
|
16432
16702
|
" Your agent will analyze your codebase, map user roles, and generate your first walkthrough scenario."
|
|
16433
16703
|
)
|
|
16434
16704
|
);
|
|
16435
16705
|
console.log();
|
|
16436
|
-
console.log(
|
|
16706
|
+
console.log(chalk18.bold(" Core workflow:"));
|
|
16437
16707
|
console.log(
|
|
16438
|
-
|
|
16708
|
+
chalk18.dim(" \u2022 ") + chalk18.cyan("/iamu:init") + chalk18.dim(" Map domain & scaffold inaugural scenario")
|
|
16439
16709
|
);
|
|
16440
16710
|
console.log(
|
|
16441
|
-
|
|
16711
|
+
chalk18.dim(" \u2022 ") + chalk18.cyan("iamu-run <slug>") + chalk18.dim(" Walk scenario in browser & record findings")
|
|
16442
16712
|
);
|
|
16443
16713
|
console.log(
|
|
16444
|
-
|
|
16714
|
+
chalk18.dim(" \u2022 ") + chalk18.cyan("iamu-findings") + chalk18.dim(" Triage persona feedback & apply code fixes")
|
|
16445
16715
|
);
|
|
16446
16716
|
console.log(
|
|
16447
|
-
|
|
16717
|
+
chalk18.dim(" \u2022 ") + chalk18.cyan("iamu-propose") + chalk18.dim(" Brainstorm high-risk workflows & new personas")
|
|
16448
16718
|
);
|
|
16449
16719
|
} else {
|
|
16450
|
-
console.log(
|
|
16720
|
+
console.log(chalk18.bold(" Updated:"));
|
|
16451
16721
|
console.log();
|
|
16452
16722
|
console.log(
|
|
16453
|
-
|
|
16723
|
+
chalk18.dim(" Skills and commands regenerated to latest version.")
|
|
16454
16724
|
);
|
|
16455
16725
|
}
|
|
16456
16726
|
console.log();
|
|
16457
16727
|
console.log(
|
|
16458
|
-
` ${
|
|
16728
|
+
` ${chalk18.dim("Docs:")} ${chalk18.underline("https://iamu.dev/docs")}`
|
|
16459
16729
|
);
|
|
16460
16730
|
console.log(
|
|
16461
|
-
` ${
|
|
16731
|
+
` ${chalk18.dim("Quickstart:")} ${chalk18.underline("https://iamu.dev/quickstart")}`
|
|
16462
16732
|
);
|
|
16463
16733
|
if (config.cloud_linked && config.cloud_project_id) {
|
|
16464
16734
|
console.log(
|
|
16465
|
-
` ${
|
|
16735
|
+
` ${chalk18.dim("Dashboard:")} ${chalk18.underline(getCloudDashboardUrl(void 0, config.cloud_project_id))}`
|
|
16466
16736
|
);
|
|
16467
16737
|
}
|
|
16468
16738
|
console.log();
|
|
@@ -16490,7 +16760,7 @@ __export(status_exports, {
|
|
|
16490
16760
|
});
|
|
16491
16761
|
import { existsSync as existsSync8 } from "fs";
|
|
16492
16762
|
import { join as join6 } from "path";
|
|
16493
|
-
import
|
|
16763
|
+
import chalk19 from "chalk";
|
|
16494
16764
|
function rerunCommand(projectRoot, scenario) {
|
|
16495
16765
|
const claude = join6(projectRoot, ".claude");
|
|
16496
16766
|
const skillOnly = existsSync8(join6(claude, "skills", "iamu-run")) && !existsSync8(join6(claude, "commands", "iamu", "run.md"));
|
|
@@ -16500,19 +16770,19 @@ function printRerun(projectRoot, rerun) {
|
|
|
16500
16770
|
if (rerun.length === 0) return;
|
|
16501
16771
|
const total = rerun.reduce((n, r) => n + r.awaiting, 0);
|
|
16502
16772
|
console.log(
|
|
16503
|
-
|
|
16773
|
+
chalk19.bold(" Needs a re-run") + chalk19.dim(
|
|
16504
16774
|
` ${total} fix${total === 1 ? "" : "es"} awaiting proof from a later run`
|
|
16505
16775
|
)
|
|
16506
16776
|
);
|
|
16507
16777
|
const width = Math.max(...rerun.map((r) => r.scenario.length));
|
|
16508
16778
|
for (const r of rerun) {
|
|
16509
16779
|
console.log(
|
|
16510
|
-
` ${
|
|
16780
|
+
` ${chalk19.cyan(String(r.awaiting).padStart(2))} ${r.scenario.padEnd(width)}` + chalk19.dim(` ${r.reason}`)
|
|
16511
16781
|
);
|
|
16512
16782
|
}
|
|
16513
16783
|
const first = rerun[0].scenario;
|
|
16514
16784
|
console.log(
|
|
16515
|
-
|
|
16785
|
+
chalk19.dim(" Next: in your agent, ") + rerunCommand(projectRoot, first) + chalk19.dim(
|
|
16516
16786
|
rerun.length > 1 ? " (then the others, most fixes first)" : ""
|
|
16517
16787
|
)
|
|
16518
16788
|
);
|
|
@@ -16582,10 +16852,10 @@ async function status(opts) {
|
|
|
16582
16852
|
}
|
|
16583
16853
|
const quiet = isQuiet();
|
|
16584
16854
|
if (!quiet) console.log();
|
|
16585
|
-
console.log(
|
|
16855
|
+
console.log(chalk19.bold(" " + projectStatus.project.name));
|
|
16586
16856
|
if (!quiet) {
|
|
16587
16857
|
console.log(
|
|
16588
|
-
|
|
16858
|
+
chalk19.dim(
|
|
16589
16859
|
" " + (projectStatus.cloud.linked ? "cloud-linked" : "local-only")
|
|
16590
16860
|
)
|
|
16591
16861
|
);
|
|
@@ -16624,43 +16894,43 @@ async function status(opts) {
|
|
|
16624
16894
|
]
|
|
16625
16895
|
];
|
|
16626
16896
|
for (const [label, count, invalid] of rows) {
|
|
16627
|
-
const num = count === 0 ?
|
|
16628
|
-
const inv = invalid > 0 ?
|
|
16897
|
+
const num = count === 0 ? chalk19.dim("0") : chalk19.cyan(String(count));
|
|
16898
|
+
const inv = invalid > 0 ? chalk19.yellow(` (${symbols.warning} ${invalid} invalid)`) : "";
|
|
16629
16899
|
console.log(` ${padRight(label, 14)} ${num}${inv}`);
|
|
16630
16900
|
}
|
|
16631
16901
|
if (!quiet) console.log();
|
|
16632
|
-
let ctxLabel =
|
|
16902
|
+
let ctxLabel = chalk19.dim("none");
|
|
16633
16903
|
if (projectStatus.context.present) {
|
|
16634
16904
|
if (projectStatus.context.richness === "thin") {
|
|
16635
16905
|
const reasons = projectStatus.context.thin_reasons && projectStatus.context.thin_reasons.length > 0 ? ` (${projectStatus.context.thin_reasons.join(", ")})` : "";
|
|
16636
|
-
ctxLabel =
|
|
16906
|
+
ctxLabel = chalk19.yellow(`thin${reasons}`) + ` ${symbols.warning}`;
|
|
16637
16907
|
} else {
|
|
16638
|
-
ctxLabel =
|
|
16908
|
+
ctxLabel = chalk19.green("complete");
|
|
16639
16909
|
}
|
|
16640
16910
|
}
|
|
16641
16911
|
console.log(` ${padRight("context", 14)} ${ctxLabel}`);
|
|
16642
16912
|
console.log(
|
|
16643
|
-
` ${padRight("runs", 14)} ${runs.length === 0 ?
|
|
16913
|
+
` ${padRight("runs", 14)} ${runs.length === 0 ? chalk19.dim("0") : chalk19.cyan(String(runs.length))}${runs.length > 0 ? chalk19.dim(" last: " + runs.at(-1)) : ""}`
|
|
16644
16914
|
);
|
|
16645
16915
|
if (incompleteRuns.length > 0) {
|
|
16646
16916
|
console.log(
|
|
16647
|
-
|
|
16917
|
+
chalk19.yellow(` ${padRight("unfinished", 14)} ${incompleteRuns.length}`) + chalk19.dim(
|
|
16648
16918
|
" never reached `iamu complete` \u2014 `iamu status --json` lists them"
|
|
16649
16919
|
)
|
|
16650
16920
|
);
|
|
16651
16921
|
}
|
|
16652
16922
|
if (projectStatus.requests && projectStatus.requests.open > 0) {
|
|
16653
16923
|
console.log(
|
|
16654
|
-
|
|
16924
|
+
chalk19.cyan(
|
|
16655
16925
|
` ${padRight("requests", 14)} ${projectStatus.requests.open}`
|
|
16656
|
-
) +
|
|
16926
|
+
) + chalk19.dim(" queued by the team \u2014 `/iamu:findings` to pick one up")
|
|
16657
16927
|
);
|
|
16658
16928
|
}
|
|
16659
16929
|
if (projectStatus.sync) {
|
|
16660
16930
|
const { pending_new, pending_updates, pending_retries } = projectStatus.sync;
|
|
16661
16931
|
if (pending_new > 0 || pending_updates > 0 || pending_retries > 0) {
|
|
16662
16932
|
console.log(
|
|
16663
|
-
|
|
16933
|
+
chalk19.yellow(
|
|
16664
16934
|
` ${padRight("unpushed", 14)} ${pending_new} new, ${pending_updates} modified, ${pending_retries} retries`
|
|
16665
16935
|
)
|
|
16666
16936
|
);
|
|
@@ -16670,14 +16940,14 @@ async function status(opts) {
|
|
|
16670
16940
|
const n = deletions.count;
|
|
16671
16941
|
const noun = `${n} local deletion${n === 1 ? "" : "s"}`;
|
|
16672
16942
|
console.log(
|
|
16673
|
-
|
|
16943
|
+
chalk19.yellow(
|
|
16674
16944
|
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\``
|
|
16675
16945
|
)
|
|
16676
16946
|
);
|
|
16677
16947
|
}
|
|
16678
16948
|
if (deletions.held > 0) {
|
|
16679
16949
|
console.log(
|
|
16680
|
-
|
|
16950
|
+
chalk19.dim(
|
|
16681
16951
|
` ${padRight("held", 14)} ${deletions.held} local deletion(s) will not be sent yet \u2014 \`iamu sync\` says why`
|
|
16682
16952
|
)
|
|
16683
16953
|
);
|
|
@@ -16692,17 +16962,17 @@ async function status(opts) {
|
|
|
16692
16962
|
if (allWarnings.length > 0) {
|
|
16693
16963
|
if (!quiet) console.log();
|
|
16694
16964
|
console.log(
|
|
16695
|
-
|
|
16965
|
+
chalk19.yellow(` ${symbols.warning} Warnings (${allWarnings.length}):`)
|
|
16696
16966
|
);
|
|
16697
16967
|
for (const w of allWarnings) {
|
|
16698
|
-
console.log(
|
|
16968
|
+
console.log(chalk19.dim(` \u2022 ${w}`));
|
|
16699
16969
|
}
|
|
16700
16970
|
}
|
|
16701
16971
|
if (!quiet) {
|
|
16702
16972
|
console.log();
|
|
16703
16973
|
printRerun(projectRoot, rerun);
|
|
16704
16974
|
if (staleSkills.length > 0) {
|
|
16705
|
-
console.log(
|
|
16975
|
+
console.log(chalk19.yellow(` ${STALE_SKILLS_MESSAGE}`));
|
|
16706
16976
|
console.log();
|
|
16707
16977
|
}
|
|
16708
16978
|
console.log();
|
|
@@ -16825,7 +17095,7 @@ var init_browse_actions = __esm({
|
|
|
16825
17095
|
|
|
16826
17096
|
// src/commands/browse-driver.ts
|
|
16827
17097
|
import { execFile as execFile3, spawn } from "child_process";
|
|
16828
|
-
import { readFile as
|
|
17098
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
16829
17099
|
async function probeCdp(port, timeoutMs = CDP_PROBE_TIMEOUT_MS) {
|
|
16830
17100
|
try {
|
|
16831
17101
|
const res = await fetch(`http://127.0.0.1:${port}/json/version`, {
|
|
@@ -16841,7 +17111,7 @@ async function probeCdp(port, timeoutMs = CDP_PROBE_TIMEOUT_MS) {
|
|
|
16841
17111
|
async function readProcessCommandLine(pid, platform2 = process.platform) {
|
|
16842
17112
|
if (!Number.isInteger(pid) || pid <= 0 || platform2 === "win32") return null;
|
|
16843
17113
|
if (platform2 === "linux") {
|
|
16844
|
-
const raw = await
|
|
17114
|
+
const raw = await readFile5(`/proc/${pid}/cmdline`, "utf8").catch(() => "");
|
|
16845
17115
|
if (raw) return raw.split("\0").join(" ").trim();
|
|
16846
17116
|
}
|
|
16847
17117
|
return new Promise((resolve4) => {
|
|
@@ -16952,7 +17222,7 @@ var init_browse_driver = __esm({
|
|
|
16952
17222
|
|
|
16953
17223
|
// src/commands/step-numbering.ts
|
|
16954
17224
|
import { open, readdir, unlink } from "fs/promises";
|
|
16955
|
-
import
|
|
17225
|
+
import path22 from "path";
|
|
16956
17226
|
function stepFileName(stepNumber2) {
|
|
16957
17227
|
return `${String(stepNumber2).padStart(3, "0")}.json`;
|
|
16958
17228
|
}
|
|
@@ -16974,7 +17244,7 @@ async function reserveStepFile(stepsDir, limit) {
|
|
|
16974
17244
|
if (candidate > limit.maxSteps) {
|
|
16975
17245
|
throw new Error(stepLimitMessage(limit.maxSteps, limit.runId));
|
|
16976
17246
|
}
|
|
16977
|
-
const stepPath =
|
|
17247
|
+
const stepPath = path22.join(stepsDir, stepFileName(candidate));
|
|
16978
17248
|
try {
|
|
16979
17249
|
const handle = await open(stepPath, "wx");
|
|
16980
17250
|
await handle.close();
|
|
@@ -17005,9 +17275,9 @@ __export(step_exports, {
|
|
|
17005
17275
|
recordStep: () => recordStep,
|
|
17006
17276
|
stepCommand: () => stepCommand
|
|
17007
17277
|
});
|
|
17008
|
-
import { copyFile, mkdir as mkdir5, stat } from "fs/promises";
|
|
17009
|
-
import
|
|
17010
|
-
import
|
|
17278
|
+
import { copyFile, mkdir as mkdir5, stat as stat2 } from "fs/promises";
|
|
17279
|
+
import path23 from "path";
|
|
17280
|
+
import chalk20 from "chalk";
|
|
17011
17281
|
function parseMaxSteps(val) {
|
|
17012
17282
|
if (typeof val === "number" && Number.isFinite(val) && val > 0) return val;
|
|
17013
17283
|
if (typeof val === "string" && val.trim().length > 0) {
|
|
@@ -17025,8 +17295,8 @@ async function recordStep(input) {
|
|
|
17025
17295
|
if (!runDirPath) {
|
|
17026
17296
|
throw new Error(`Run directory not found for run "${input.runId}"`);
|
|
17027
17297
|
}
|
|
17028
|
-
const stepsDir =
|
|
17029
|
-
const screenshotsDir =
|
|
17298
|
+
const stepsDir = path23.join(runDirPath, "steps");
|
|
17299
|
+
const screenshotsDir = path23.join(runDirPath, "screenshots");
|
|
17030
17300
|
await mkdir5(stepsDir, { recursive: true });
|
|
17031
17301
|
await mkdir5(screenshotsDir, { recursive: true });
|
|
17032
17302
|
const shotSource = input.shot ? await existingShot(input.shot) : null;
|
|
@@ -17040,11 +17310,11 @@ async function recordStep(input) {
|
|
|
17040
17310
|
let finalScreenshotPath = null;
|
|
17041
17311
|
if (shotSource) {
|
|
17042
17312
|
const destName = `step-${stepNumber2}.png`;
|
|
17043
|
-
finalScreenshotPath =
|
|
17044
|
-
if (
|
|
17313
|
+
finalScreenshotPath = path23.join(screenshotsDir, destName);
|
|
17314
|
+
if (path23.resolve(finalScreenshotPath) !== shotSource) {
|
|
17045
17315
|
await copyFile(shotSource, finalScreenshotPath);
|
|
17046
17316
|
}
|
|
17047
|
-
screenshotRef =
|
|
17317
|
+
screenshotRef = path23.join("screenshots", destName);
|
|
17048
17318
|
}
|
|
17049
17319
|
const parsedStep = runStepSchema.parse({
|
|
17050
17320
|
step_number: stepNumber2,
|
|
@@ -17058,10 +17328,24 @@ async function recordStep(input) {
|
|
|
17058
17328
|
...input.extra ? { extra: input.extra } : {}
|
|
17059
17329
|
});
|
|
17060
17330
|
await writeStep(runDirPath, parsedStep);
|
|
17331
|
+
let cancelled = false;
|
|
17332
|
+
try {
|
|
17333
|
+
const liveRes = await sendLiveStep(
|
|
17334
|
+
input.projectRoot,
|
|
17335
|
+
input.runId,
|
|
17336
|
+
parsedStep,
|
|
17337
|
+
finalScreenshotPath
|
|
17338
|
+
);
|
|
17339
|
+
if (liveRes.cancelled) {
|
|
17340
|
+
cancelled = true;
|
|
17341
|
+
}
|
|
17342
|
+
} catch {
|
|
17343
|
+
}
|
|
17061
17344
|
return {
|
|
17062
17345
|
step: parsedStep,
|
|
17063
17346
|
stepPath,
|
|
17064
|
-
screenshotPath: finalScreenshotPath
|
|
17347
|
+
screenshotPath: finalScreenshotPath,
|
|
17348
|
+
cancelled
|
|
17065
17349
|
};
|
|
17066
17350
|
} catch (err) {
|
|
17067
17351
|
await reservation.release();
|
|
@@ -17069,8 +17353,8 @@ async function recordStep(input) {
|
|
|
17069
17353
|
}
|
|
17070
17354
|
}
|
|
17071
17355
|
async function existingShot(shot) {
|
|
17072
|
-
const resolved =
|
|
17073
|
-
const isFile = await
|
|
17356
|
+
const resolved = path23.resolve(shot);
|
|
17357
|
+
const isFile = await stat2(resolved).then((s) => s.isFile()).catch(() => false);
|
|
17074
17358
|
if (!isFile) {
|
|
17075
17359
|
throw new Error(
|
|
17076
17360
|
`Screenshot not found: ${resolved} \u2014 save the screenshot first, or omit --shot.`
|
|
@@ -17106,12 +17390,42 @@ async function stepCommand(runArg, opts) {
|
|
|
17106
17390
|
grounding: opts.grounding,
|
|
17107
17391
|
maxSteps: opts.maxSteps
|
|
17108
17392
|
});
|
|
17393
|
+
if (res.cancelled) {
|
|
17394
|
+
if (opts.json) {
|
|
17395
|
+
console.log(
|
|
17396
|
+
JSON.stringify(
|
|
17397
|
+
{
|
|
17398
|
+
step_number: res.step.step_number,
|
|
17399
|
+
cancelled: true,
|
|
17400
|
+
path: path23.relative(projectRoot, res.stepPath),
|
|
17401
|
+
action: res.step.action,
|
|
17402
|
+
note: res.step.note,
|
|
17403
|
+
url: res.step.url,
|
|
17404
|
+
screenshot: res.step.screenshot,
|
|
17405
|
+
surface: res.step.surface
|
|
17406
|
+
},
|
|
17407
|
+
null,
|
|
17408
|
+
2
|
|
17409
|
+
)
|
|
17410
|
+
);
|
|
17411
|
+
} else {
|
|
17412
|
+
console.log();
|
|
17413
|
+
console.log(
|
|
17414
|
+
chalk20.red(
|
|
17415
|
+
"The user stopped this run from the live viewer. End the walk now."
|
|
17416
|
+
)
|
|
17417
|
+
);
|
|
17418
|
+
console.log();
|
|
17419
|
+
}
|
|
17420
|
+
process.exitCode = 1;
|
|
17421
|
+
return;
|
|
17422
|
+
}
|
|
17109
17423
|
if (opts.json) {
|
|
17110
17424
|
console.log(
|
|
17111
17425
|
JSON.stringify(
|
|
17112
17426
|
{
|
|
17113
17427
|
step_number: res.step.step_number,
|
|
17114
|
-
path:
|
|
17428
|
+
path: path23.relative(projectRoot, res.stepPath),
|
|
17115
17429
|
action: res.step.action,
|
|
17116
17430
|
note: res.step.note,
|
|
17117
17431
|
url: res.step.url,
|
|
@@ -17126,19 +17440,19 @@ async function stepCommand(runArg, opts) {
|
|
|
17126
17440
|
}
|
|
17127
17441
|
console.log();
|
|
17128
17442
|
console.log(
|
|
17129
|
-
` ${symbols.success} Step ${
|
|
17443
|
+
` ${symbols.success} Step ${chalk20.cyan(String(res.step.step_number))} recorded: ${res.step.action}`
|
|
17130
17444
|
);
|
|
17131
17445
|
if (res.step.note) {
|
|
17132
|
-
console.log(` ${
|
|
17446
|
+
console.log(` ${chalk20.dim("note:")} ${res.step.note}`);
|
|
17133
17447
|
}
|
|
17134
17448
|
if (res.step.url) {
|
|
17135
|
-
console.log(` ${
|
|
17449
|
+
console.log(` ${chalk20.dim("url:")} ${res.step.url}`);
|
|
17136
17450
|
}
|
|
17137
17451
|
if (res.step.screenshot) {
|
|
17138
|
-
console.log(` ${
|
|
17452
|
+
console.log(` ${chalk20.dim("shot:")} ${res.step.screenshot}`);
|
|
17139
17453
|
}
|
|
17140
17454
|
console.log(
|
|
17141
|
-
` ${
|
|
17455
|
+
` ${chalk20.dim("file:")} ${path23.relative(projectRoot, res.stepPath)}`
|
|
17142
17456
|
);
|
|
17143
17457
|
console.log();
|
|
17144
17458
|
} catch (err) {
|
|
@@ -17153,6 +17467,7 @@ var init_step = __esm({
|
|
|
17153
17467
|
init_dist();
|
|
17154
17468
|
init_symbols();
|
|
17155
17469
|
init_context4();
|
|
17470
|
+
init_live_run_client();
|
|
17156
17471
|
init_step_numbering();
|
|
17157
17472
|
DEFAULT_MAX_STEPS = 50;
|
|
17158
17473
|
}
|
|
@@ -17181,21 +17496,21 @@ import {
|
|
|
17181
17496
|
} from "fs";
|
|
17182
17497
|
import { rm as rm2 } from "fs/promises";
|
|
17183
17498
|
import { homedir as homedir3 } from "os";
|
|
17184
|
-
import
|
|
17185
|
-
import
|
|
17499
|
+
import path24 from "path";
|
|
17500
|
+
import chalk21 from "chalk";
|
|
17186
17501
|
function stateDir() {
|
|
17187
|
-
return
|
|
17188
|
-
process.env.IAMU_HOME ??
|
|
17502
|
+
return path24.join(
|
|
17503
|
+
process.env.IAMU_HOME ?? path24.join(homedir3(), ".iamu"),
|
|
17189
17504
|
"browse"
|
|
17190
17505
|
);
|
|
17191
17506
|
}
|
|
17192
17507
|
function profileDir() {
|
|
17193
|
-
return
|
|
17508
|
+
return path24.join(stateDir(), "profile");
|
|
17194
17509
|
}
|
|
17195
17510
|
function readBrowseState() {
|
|
17196
17511
|
try {
|
|
17197
17512
|
return JSON.parse(
|
|
17198
|
-
readFileSync6(
|
|
17513
|
+
readFileSync6(path24.join(stateDir(), "state.json"), "utf8")
|
|
17199
17514
|
);
|
|
17200
17515
|
} catch {
|
|
17201
17516
|
return null;
|
|
@@ -17203,13 +17518,13 @@ function readBrowseState() {
|
|
|
17203
17518
|
}
|
|
17204
17519
|
function writeState(state) {
|
|
17205
17520
|
mkdirSync(stateDir(), { recursive: true });
|
|
17206
|
-
writeFileSync(
|
|
17521
|
+
writeFileSync(path24.join(stateDir(), "state.json"), JSON.stringify(state));
|
|
17207
17522
|
}
|
|
17208
17523
|
function fail(message, opts) {
|
|
17209
17524
|
if (opts?.json) {
|
|
17210
17525
|
console.error(JSON.stringify({ error: message }));
|
|
17211
17526
|
} else {
|
|
17212
|
-
console.error(
|
|
17527
|
+
console.error(chalk21.red(` ${message}`));
|
|
17213
17528
|
}
|
|
17214
17529
|
process.exitCode = 1;
|
|
17215
17530
|
}
|
|
@@ -17266,7 +17581,7 @@ async function requestedViewport(opts) {
|
|
|
17266
17581
|
let manifest;
|
|
17267
17582
|
try {
|
|
17268
17583
|
manifest = JSON.parse(
|
|
17269
|
-
readFileSync6(
|
|
17584
|
+
readFileSync6(path24.join(dir, "walkthrough.json"), "utf8")
|
|
17270
17585
|
);
|
|
17271
17586
|
} catch {
|
|
17272
17587
|
fail(
|
|
@@ -17298,7 +17613,7 @@ async function convergeRunning(opts, driver, port, requested, previous) {
|
|
|
17298
17613
|
writeState({ port, viewport, pid: previous?.pid });
|
|
17299
17614
|
if (sameSize(current, viewport)) {
|
|
17300
17615
|
report2(opts, { reused: true, port, viewport }, [
|
|
17301
|
-
` ${
|
|
17616
|
+
` ${chalk21.green("\u2713")} Browser reused ${chalk21.dim(`(CDP :${port}, viewport ${sizeLabel(viewport)})`)}`
|
|
17302
17617
|
]);
|
|
17303
17618
|
return;
|
|
17304
17619
|
}
|
|
@@ -17307,7 +17622,7 @@ async function convergeRunning(opts, driver, port, requested, previous) {
|
|
|
17307
17622
|
} catch {
|
|
17308
17623
|
}
|
|
17309
17624
|
report2(opts, { resized: true, from: current, to: viewport, port }, [
|
|
17310
|
-
` ${
|
|
17625
|
+
` ${chalk21.green("\u2713")} Browser resized ${sizeLabel(current)} \u2192 ${sizeLabel(viewport)} ${chalk21.dim(`(CDP :${port})`)}`
|
|
17311
17626
|
]);
|
|
17312
17627
|
}
|
|
17313
17628
|
function chromeArgs(opts, port, headless) {
|
|
@@ -17351,7 +17666,7 @@ async function start(opts, driver = cdpDriver) {
|
|
|
17351
17666
|
for (let i = 0; i < 75; i++) {
|
|
17352
17667
|
if (await driver.isRunning(port)) {
|
|
17353
17668
|
report2(opts, { ready: true, port, viewport, headless }, [
|
|
17354
|
-
` ${
|
|
17669
|
+
` ${chalk21.green("\u2713")} Browser ready ${chalk21.dim(`(CDP :${port}${viewport ? `, viewport ${sizeLabel(viewport)}` : ""}${headless ? ", headless" : ""})`)}`
|
|
17355
17670
|
]);
|
|
17356
17671
|
return;
|
|
17357
17672
|
}
|
|
@@ -17372,10 +17687,10 @@ async function stop(opts, driver) {
|
|
|
17372
17687
|
await driver.closeBrowser(state.port);
|
|
17373
17688
|
if (state.pid) await reapBrowser(state.pid, profileDir(), driver);
|
|
17374
17689
|
try {
|
|
17375
|
-
unlinkSync(
|
|
17690
|
+
unlinkSync(path24.join(stateDir(), "state.json"));
|
|
17376
17691
|
} catch {
|
|
17377
17692
|
}
|
|
17378
|
-
report2(opts, { stopped: true }, [` ${
|
|
17693
|
+
report2(opts, { stopped: true }, [` ${chalk21.green("\u2713")} Browser stopped`]);
|
|
17379
17694
|
}
|
|
17380
17695
|
async function waitForVisualStability(page, maxWaitMs = 300) {
|
|
17381
17696
|
let timer;
|
|
@@ -17438,8 +17753,8 @@ async function withPage(opts, driver, fn, target) {
|
|
|
17438
17753
|
let screenshot = null;
|
|
17439
17754
|
if (opts.shot) {
|
|
17440
17755
|
await waitForVisualStability(page);
|
|
17441
|
-
screenshot =
|
|
17442
|
-
mkdirSync(
|
|
17756
|
+
screenshot = path24.resolve(opts.shot);
|
|
17757
|
+
mkdirSync(path24.dirname(screenshot), { recursive: true });
|
|
17443
17758
|
await page.screenshot({ path: screenshot, fullPage: Boolean(opts.full) });
|
|
17444
17759
|
}
|
|
17445
17760
|
return { url: page.url(), title: await page.title(), screenshot };
|
|
@@ -17518,23 +17833,24 @@ function printStep(opts, record, projectRoot) {
|
|
|
17518
17833
|
if (opts.json) {
|
|
17519
17834
|
const doc = {
|
|
17520
17835
|
step_number: step.step_number,
|
|
17521
|
-
path:
|
|
17836
|
+
path: path24.relative(projectRoot, record.stepPath),
|
|
17522
17837
|
action: step.action,
|
|
17523
17838
|
note: step.note,
|
|
17524
17839
|
url: step.url,
|
|
17525
17840
|
screenshot: step.screenshot,
|
|
17526
|
-
surface: step.surface
|
|
17841
|
+
surface: step.surface,
|
|
17842
|
+
...record.cancelled ? { cancelled: true } : {}
|
|
17527
17843
|
};
|
|
17528
17844
|
console.log(JSON.stringify(doc, null, 2));
|
|
17529
17845
|
return;
|
|
17530
17846
|
}
|
|
17531
17847
|
console.log(
|
|
17532
|
-
` ${
|
|
17848
|
+
` ${chalk21.green("\u2713")} Step ${chalk21.cyan(String(step.step_number))} recorded: ${step.action}`
|
|
17533
17849
|
);
|
|
17534
|
-
if (step.note) console.log(` ${
|
|
17535
|
-
if (step.url) console.log(` ${
|
|
17850
|
+
if (step.note) console.log(` ${chalk21.dim("note:")} ${step.note}`);
|
|
17851
|
+
if (step.url) console.log(` ${chalk21.dim("url:")} ${step.url}`);
|
|
17536
17852
|
if (step.screenshot) {
|
|
17537
|
-
console.log(` ${
|
|
17853
|
+
console.log(` ${chalk21.dim("screenshot:")} ${step.screenshot}`);
|
|
17538
17854
|
}
|
|
17539
17855
|
}
|
|
17540
17856
|
async function browseStep(args, opts, driver) {
|
|
@@ -17592,10 +17908,10 @@ async function browseStep(args, opts, driver) {
|
|
|
17592
17908
|
const runDirPath = resolveRunDir(ctx.projectRoot, opts.run);
|
|
17593
17909
|
if (!runDirPath) return;
|
|
17594
17910
|
const maxSteps = parseMaxSteps(opts.maxSteps);
|
|
17595
|
-
if (await peekNextStepNumber(
|
|
17911
|
+
if (await peekNextStepNumber(path24.join(runDirPath, "steps")) > maxSteps) {
|
|
17596
17912
|
return fail(stepLimitMessage(maxSteps, opts.run), opts);
|
|
17597
17913
|
}
|
|
17598
|
-
const pendingShot =
|
|
17914
|
+
const pendingShot = path24.join(
|
|
17599
17915
|
runDirPath,
|
|
17600
17916
|
"screenshots",
|
|
17601
17917
|
`.pending-${randomUUID7()}.png`
|
|
@@ -17619,6 +17935,19 @@ async function browseStep(args, opts, driver) {
|
|
|
17619
17935
|
maxSteps
|
|
17620
17936
|
});
|
|
17621
17937
|
printStep(opts, record, ctx.projectRoot);
|
|
17938
|
+
if (record.cancelled) {
|
|
17939
|
+
if (!opts.json) {
|
|
17940
|
+
console.log();
|
|
17941
|
+
console.log(
|
|
17942
|
+
chalk21.red(
|
|
17943
|
+
"The user stopped this run from the live viewer. End the walk now."
|
|
17944
|
+
)
|
|
17945
|
+
);
|
|
17946
|
+
console.log();
|
|
17947
|
+
}
|
|
17948
|
+
process.exitCode = 1;
|
|
17949
|
+
return;
|
|
17950
|
+
}
|
|
17622
17951
|
} catch (err) {
|
|
17623
17952
|
fail(err instanceof Error ? err.message : String(err), opts);
|
|
17624
17953
|
} finally {
|
|
@@ -17675,7 +18004,7 @@ __export(doctor_exports, {
|
|
|
17675
18004
|
import { createServer } from "net";
|
|
17676
18005
|
import { existsSync as existsSync10, promises as fs26 } from "fs";
|
|
17677
18006
|
import { join as join7 } from "path";
|
|
17678
|
-
import
|
|
18007
|
+
import chalk22 from "chalk";
|
|
17679
18008
|
function checkPortAvailable(port) {
|
|
17680
18009
|
return new Promise((resolve4) => {
|
|
17681
18010
|
const server = createServer();
|
|
@@ -18182,7 +18511,7 @@ async function doctor(opts) {
|
|
|
18182
18511
|
return;
|
|
18183
18512
|
}
|
|
18184
18513
|
console.log();
|
|
18185
|
-
console.log(
|
|
18514
|
+
console.log(chalk22.bold(" Iamu System Diagnostics"));
|
|
18186
18515
|
console.log();
|
|
18187
18516
|
const categories = [
|
|
18188
18517
|
{ key: "runtime", title: "Runtime & System" },
|
|
@@ -18195,13 +18524,13 @@ async function doctor(opts) {
|
|
|
18195
18524
|
for (const cat of categories) {
|
|
18196
18525
|
const catChecks = result.checks.filter((c) => c.category === cat.key);
|
|
18197
18526
|
if (catChecks.length === 0) continue;
|
|
18198
|
-
console.log(
|
|
18527
|
+
console.log(chalk22.bold(` ${cat.title}:`));
|
|
18199
18528
|
for (const check of catChecks) {
|
|
18200
|
-
const sym = check.status === "ok" ? symbols.success : check.status === "warn" ?
|
|
18201
|
-
console.log(` ${sym} ${check.name}: ${
|
|
18529
|
+
const sym = check.status === "ok" ? symbols.success : check.status === "warn" ? chalk22.yellow("\u25CB") : symbols.error;
|
|
18530
|
+
console.log(` ${sym} ${check.name}: ${chalk22.dim(check.message)}`);
|
|
18202
18531
|
if (check.remedy) {
|
|
18203
18532
|
console.log(
|
|
18204
|
-
` ${
|
|
18533
|
+
` ${chalk22.cyan("\u21B3 Remedy:")} ${chalk22.dim(check.remedy)}`
|
|
18205
18534
|
);
|
|
18206
18535
|
}
|
|
18207
18536
|
}
|
|
@@ -18209,15 +18538,15 @@ async function doctor(opts) {
|
|
|
18209
18538
|
}
|
|
18210
18539
|
if (result.ok && result.summary.warn === 0) {
|
|
18211
18540
|
console.log(
|
|
18212
|
-
` ${symbols.success} ${
|
|
18541
|
+
` ${symbols.success} ${chalk22.green.bold("All systems operational.")}`
|
|
18213
18542
|
);
|
|
18214
18543
|
} else if (result.ok) {
|
|
18215
18544
|
console.log(
|
|
18216
|
-
` ${symbols.warning} ${
|
|
18545
|
+
` ${symbols.warning} ${chalk22.yellow.bold(`${result.summary.warn} warning(s) detected.`)} (Walkthroughs can still run)`
|
|
18217
18546
|
);
|
|
18218
18547
|
} else {
|
|
18219
18548
|
console.log(
|
|
18220
|
-
` ${symbols.error} ${
|
|
18549
|
+
` ${symbols.error} ${chalk22.red.bold(`${result.summary.error} error(s) and ${result.summary.warn} warning(s) detected.`)}`
|
|
18221
18550
|
);
|
|
18222
18551
|
process.exitCode = 1;
|
|
18223
18552
|
}
|
|
@@ -18314,20 +18643,20 @@ var list_exports = {};
|
|
|
18314
18643
|
__export(list_exports, {
|
|
18315
18644
|
list: () => list
|
|
18316
18645
|
});
|
|
18317
|
-
import
|
|
18646
|
+
import chalk23 from "chalk";
|
|
18318
18647
|
function severityColor(severity) {
|
|
18319
18648
|
const raw = (severity ?? "\u2014").trim();
|
|
18320
18649
|
switch (raw) {
|
|
18321
18650
|
case "critical":
|
|
18322
|
-
return
|
|
18651
|
+
return chalk23.red(raw);
|
|
18323
18652
|
case "major":
|
|
18324
|
-
return
|
|
18653
|
+
return chalk23.yellow(raw);
|
|
18325
18654
|
case "minor":
|
|
18326
|
-
return
|
|
18655
|
+
return chalk23.cyan(raw);
|
|
18327
18656
|
case "observation":
|
|
18328
|
-
return
|
|
18657
|
+
return chalk23.dim(raw);
|
|
18329
18658
|
default:
|
|
18330
|
-
return
|
|
18659
|
+
return chalk23.dim(raw);
|
|
18331
18660
|
}
|
|
18332
18661
|
}
|
|
18333
18662
|
async function list(type2, opts) {
|
|
@@ -18382,16 +18711,16 @@ async function list(type2, opts) {
|
|
|
18382
18711
|
for (const [t, c] of counts) {
|
|
18383
18712
|
const label = PLURAL_LABELS[t].padEnd(14);
|
|
18384
18713
|
if (!c) {
|
|
18385
|
-
console.log(` ${label} ${
|
|
18714
|
+
console.log(` ${label} ${chalk23.dim("error")}`);
|
|
18386
18715
|
continue;
|
|
18387
18716
|
}
|
|
18388
|
-
const count = c.count === 0 ?
|
|
18389
|
-
const warn = c.invalid > 0 ?
|
|
18717
|
+
const count = c.count === 0 ? chalk23.dim("0") : chalk23.cyan(String(c.count));
|
|
18718
|
+
const warn = c.invalid > 0 ? chalk23.yellow(` (${c.invalid} invalid)`) : "";
|
|
18390
18719
|
console.log(` ${label} ${count}${warn}`);
|
|
18391
18720
|
}
|
|
18392
18721
|
console.log();
|
|
18393
18722
|
console.log(
|
|
18394
|
-
|
|
18723
|
+
chalk23.dim(" Run 'iamu list <type>' for details (e.g. iamu list personas)")
|
|
18395
18724
|
);
|
|
18396
18725
|
console.log();
|
|
18397
18726
|
}
|
|
@@ -18417,7 +18746,7 @@ async function listSingleType(projectRoot, type2, capabilityFilter, diffFilter,
|
|
|
18417
18746
|
if (!diffResult || diffResult.files.length === 0) {
|
|
18418
18747
|
if (!opts.json) {
|
|
18419
18748
|
console.log(
|
|
18420
|
-
|
|
18749
|
+
chalk23.dim(
|
|
18421
18750
|
` No git diff detected against ${diffResult?.baseRef ?? "base ref"}.`
|
|
18422
18751
|
)
|
|
18423
18752
|
);
|
|
@@ -18464,10 +18793,10 @@ async function listSingleType(projectRoot, type2, capabilityFilter, diffFilter,
|
|
|
18464
18793
|
return;
|
|
18465
18794
|
}
|
|
18466
18795
|
if (entities.length === 0) {
|
|
18467
|
-
console.log(
|
|
18796
|
+
console.log(chalk23.dim(` No ${PLURAL_LABELS[type2]} found.`));
|
|
18468
18797
|
if (!diffFilter) {
|
|
18469
18798
|
console.log(
|
|
18470
|
-
|
|
18799
|
+
chalk23.dim(
|
|
18471
18800
|
` Run \`iamu new ${type2} --name "..."\` to create your first ${type2}.`
|
|
18472
18801
|
)
|
|
18473
18802
|
);
|
|
@@ -18478,10 +18807,10 @@ async function listSingleType(projectRoot, type2, capabilityFilter, diffFilter,
|
|
|
18478
18807
|
if (isTty) {
|
|
18479
18808
|
console.log();
|
|
18480
18809
|
console.log(
|
|
18481
|
-
|
|
18810
|
+
chalk23.bold(` ${PLURAL_LABELS[type2]}`) + chalk23.dim(` (${entities.length})`)
|
|
18482
18811
|
);
|
|
18483
18812
|
if (diffNotice) {
|
|
18484
|
-
console.log(
|
|
18813
|
+
console.log(chalk23.cyan(` ${diffNotice}`));
|
|
18485
18814
|
}
|
|
18486
18815
|
console.log();
|
|
18487
18816
|
}
|
|
@@ -18499,7 +18828,7 @@ async function listSingleType(projectRoot, type2, capabilityFilter, diffFilter,
|
|
|
18499
18828
|
},
|
|
18500
18829
|
{
|
|
18501
18830
|
header: "role",
|
|
18502
|
-
value: (e) =>
|
|
18831
|
+
value: (e) => chalk23.dim(e.frontmatter.role ?? "")
|
|
18503
18832
|
}
|
|
18504
18833
|
]);
|
|
18505
18834
|
break;
|
|
@@ -18539,7 +18868,7 @@ async function listSingleType(projectRoot, type2, capabilityFilter, diffFilter,
|
|
|
18539
18868
|
},
|
|
18540
18869
|
{
|
|
18541
18870
|
header: "title",
|
|
18542
|
-
value: (e) => e.frontmatter.title ??
|
|
18871
|
+
value: (e) => e.frontmatter.title ?? chalk23.dim("(no title)")
|
|
18543
18872
|
}
|
|
18544
18873
|
]);
|
|
18545
18874
|
break;
|
|
@@ -18565,7 +18894,7 @@ async function listSingleType(projectRoot, type2, capabilityFilter, diffFilter,
|
|
|
18565
18894
|
},
|
|
18566
18895
|
{
|
|
18567
18896
|
header: "capability",
|
|
18568
|
-
value: (e) =>
|
|
18897
|
+
value: (e) => chalk23.dim(
|
|
18569
18898
|
e.frontmatter.primary_capability ?? e.frontmatter.capability ?? ""
|
|
18570
18899
|
)
|
|
18571
18900
|
},
|
|
@@ -18614,7 +18943,7 @@ async function listSingleType(projectRoot, type2, capabilityFilter, diffFilter,
|
|
|
18614
18943
|
},
|
|
18615
18944
|
{
|
|
18616
18945
|
header: "rule",
|
|
18617
|
-
value: (e) => parseGuidanceBody(e.body).rule ||
|
|
18946
|
+
value: (e) => parseGuidanceBody(e.body).rule || chalk23.dim("(no rule)")
|
|
18618
18947
|
}
|
|
18619
18948
|
]);
|
|
18620
18949
|
break;
|
|
@@ -18627,10 +18956,10 @@ async function listSingleType(projectRoot, type2, capabilityFilter, diffFilter,
|
|
|
18627
18956
|
if (isTty) {
|
|
18628
18957
|
console.log();
|
|
18629
18958
|
console.log(
|
|
18630
|
-
|
|
18959
|
+
chalk23.yellow(` ${warnings.length} invalid file(s) skipped:`)
|
|
18631
18960
|
);
|
|
18632
18961
|
for (const w of warnings) {
|
|
18633
|
-
console.log(
|
|
18962
|
+
console.log(chalk23.dim(` ${w.path}: ${w.error}`));
|
|
18634
18963
|
}
|
|
18635
18964
|
} else {
|
|
18636
18965
|
for (const w of warnings) {
|
|
@@ -18669,12 +18998,12 @@ __export(validate_exports, {
|
|
|
18669
18998
|
});
|
|
18670
18999
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
18671
19000
|
import { promises as fs27 } from "fs";
|
|
18672
|
-
import
|
|
18673
|
-
import
|
|
19001
|
+
import path25 from "path";
|
|
19002
|
+
import chalk24 from "chalk";
|
|
18674
19003
|
function inferTypeFromPath(filePath, projectRoot) {
|
|
18675
|
-
const rel =
|
|
18676
|
-
if (rel.startsWith("..") ||
|
|
18677
|
-
const segments = rel.split(
|
|
19004
|
+
const rel = path25.relative(path25.join(projectRoot, "iamu"), filePath);
|
|
19005
|
+
if (rel.startsWith("..") || path25.isAbsolute(rel)) return null;
|
|
19006
|
+
const segments = rel.split(path25.sep);
|
|
18678
19007
|
if (segments.length < 2) return null;
|
|
18679
19008
|
return TYPE_BY_ALIAS.get(segments[0]) ?? null;
|
|
18680
19009
|
}
|
|
@@ -18704,7 +19033,7 @@ function validateFile(filePath, raw, projectRoot) {
|
|
|
18704
19033
|
);
|
|
18705
19034
|
return result;
|
|
18706
19035
|
}
|
|
18707
|
-
if (
|
|
19036
|
+
if (path25.basename(filePath) === "context.yml") {
|
|
18708
19037
|
applyZodValidation(contextFrontmatterSchema, frontmatter, result);
|
|
18709
19038
|
const warnings = [];
|
|
18710
19039
|
const hasNotes = Boolean(
|
|
@@ -18764,7 +19093,7 @@ async function buildRepairLookups(projectRoot) {
|
|
|
18764
19093
|
}
|
|
18765
19094
|
}
|
|
18766
19095
|
const runScenario = /* @__PURE__ */ new Map();
|
|
18767
|
-
const runsDir2 =
|
|
19096
|
+
const runsDir2 = path25.join(projectRoot, "iamu", ".runs");
|
|
18768
19097
|
let runIds = [];
|
|
18769
19098
|
try {
|
|
18770
19099
|
runIds = await fs27.readdir(runsDir2);
|
|
@@ -18774,7 +19103,7 @@ async function buildRepairLookups(projectRoot) {
|
|
|
18774
19103
|
try {
|
|
18775
19104
|
const manifest = JSON.parse(
|
|
18776
19105
|
await fs27.readFile(
|
|
18777
|
-
|
|
19106
|
+
path25.join(runsDir2, runId, "walkthrough.json"),
|
|
18778
19107
|
"utf8"
|
|
18779
19108
|
)
|
|
18780
19109
|
);
|
|
@@ -18805,7 +19134,7 @@ async function fixFindings(projectRoot, results, dryRun) {
|
|
|
18805
19134
|
parsed.frontmatter,
|
|
18806
19135
|
{
|
|
18807
19136
|
...lookups,
|
|
18808
|
-
fileSlug:
|
|
19137
|
+
fileSlug: path25.basename(result.path, ".md"),
|
|
18809
19138
|
newId: randomUUID8,
|
|
18810
19139
|
body: parsed.body
|
|
18811
19140
|
}
|
|
@@ -18840,7 +19169,7 @@ async function validate(filePath, opts) {
|
|
|
18840
19169
|
if (process.exitCode === 1) return;
|
|
18841
19170
|
const results = [];
|
|
18842
19171
|
if (filePath) {
|
|
18843
|
-
const abs =
|
|
19172
|
+
const abs = path25.isAbsolute(filePath) ? filePath : path25.resolve(process.cwd(), filePath);
|
|
18844
19173
|
try {
|
|
18845
19174
|
const raw = await fs27.readFile(abs, "utf8");
|
|
18846
19175
|
results.push(validateFile(abs, raw, projectRoot));
|
|
@@ -18852,7 +19181,7 @@ async function validate(filePath, opts) {
|
|
|
18852
19181
|
return;
|
|
18853
19182
|
}
|
|
18854
19183
|
} else if (opts.run) {
|
|
18855
|
-
const findingsDir =
|
|
19184
|
+
const findingsDir = path25.join(projectRoot, "iamu", ENTITY_DIRS.finding);
|
|
18856
19185
|
let names = [];
|
|
18857
19186
|
try {
|
|
18858
19187
|
names = await fs27.readdir(findingsDir);
|
|
@@ -18860,7 +19189,7 @@ async function validate(filePath, opts) {
|
|
|
18860
19189
|
}
|
|
18861
19190
|
for (const name of names) {
|
|
18862
19191
|
if (!name.endsWith(".md")) continue;
|
|
18863
|
-
const abs =
|
|
19192
|
+
const abs = path25.join(findingsDir, name);
|
|
18864
19193
|
try {
|
|
18865
19194
|
const raw = await fs27.readFile(abs, "utf8");
|
|
18866
19195
|
const { frontmatter } = parseFrontmatter(raw);
|
|
@@ -18869,7 +19198,7 @@ async function validate(filePath, opts) {
|
|
|
18869
19198
|
}
|
|
18870
19199
|
} catch {
|
|
18871
19200
|
results.push({
|
|
18872
|
-
path:
|
|
19201
|
+
path: path25.relative(projectRoot, abs),
|
|
18873
19202
|
valid: false,
|
|
18874
19203
|
errors: ["Cannot read file or parse frontmatter"]
|
|
18875
19204
|
});
|
|
@@ -18895,14 +19224,14 @@ async function validate(filePath, opts) {
|
|
|
18895
19224
|
)
|
|
18896
19225
|
);
|
|
18897
19226
|
} else {
|
|
18898
|
-
console.log(
|
|
19227
|
+
console.log(chalk24.dim(` No findings found for run "${opts.run}".`));
|
|
18899
19228
|
}
|
|
18900
19229
|
return;
|
|
18901
19230
|
}
|
|
18902
19231
|
} else {
|
|
18903
19232
|
const typesToCheck = typeFilter ? ENTITY_TYPES.filter((t) => typeFilter.has(t)) : ENTITY_TYPES;
|
|
18904
19233
|
for (const type2 of typesToCheck) {
|
|
18905
|
-
const iamuTypeDir =
|
|
19234
|
+
const iamuTypeDir = path25.join(projectRoot, "iamu", ENTITY_DIRS[type2]);
|
|
18906
19235
|
let names;
|
|
18907
19236
|
try {
|
|
18908
19237
|
names = await fs27.readdir(iamuTypeDir);
|
|
@@ -18911,20 +19240,20 @@ async function validate(filePath, opts) {
|
|
|
18911
19240
|
}
|
|
18912
19241
|
for (const name of names) {
|
|
18913
19242
|
if (!name.endsWith(".md")) continue;
|
|
18914
|
-
const abs =
|
|
19243
|
+
const abs = path25.join(iamuTypeDir, name);
|
|
18915
19244
|
try {
|
|
18916
19245
|
const raw = await fs27.readFile(abs, "utf8");
|
|
18917
19246
|
results.push(validateFile(abs, raw, projectRoot));
|
|
18918
19247
|
} catch {
|
|
18919
19248
|
results.push({
|
|
18920
|
-
path:
|
|
19249
|
+
path: path25.relative(projectRoot, abs),
|
|
18921
19250
|
valid: false,
|
|
18922
19251
|
errors: ["Cannot read file"]
|
|
18923
19252
|
});
|
|
18924
19253
|
}
|
|
18925
19254
|
}
|
|
18926
19255
|
}
|
|
18927
|
-
const ctxPath =
|
|
19256
|
+
const ctxPath = path25.join(projectRoot, "iamu", "context.yml");
|
|
18928
19257
|
try {
|
|
18929
19258
|
const raw = await fs27.readFile(ctxPath, "utf8");
|
|
18930
19259
|
results.push(validateFile(ctxPath, raw, projectRoot));
|
|
@@ -18945,19 +19274,19 @@ async function validate(filePath, opts) {
|
|
|
18945
19274
|
valid,
|
|
18946
19275
|
errors: results.filter((r) => !r.valid).flatMap(
|
|
18947
19276
|
(r) => r.errors.map((e) => ({
|
|
18948
|
-
path:
|
|
19277
|
+
path: path25.relative(projectRoot, r.path),
|
|
18949
19278
|
message: e
|
|
18950
19279
|
}))
|
|
18951
19280
|
),
|
|
18952
19281
|
warnings: results.filter((r) => r.warnings && r.warnings.length > 0).flatMap(
|
|
18953
19282
|
(r) => (r.warnings ?? []).map((w) => ({
|
|
18954
|
-
path:
|
|
19283
|
+
path: path25.relative(projectRoot, r.path),
|
|
18955
19284
|
message: w
|
|
18956
19285
|
}))
|
|
18957
19286
|
),
|
|
18958
19287
|
...opts.fix ? {
|
|
18959
19288
|
repaired: repaired.map((r) => ({
|
|
18960
|
-
path:
|
|
19289
|
+
path: path25.relative(projectRoot, r.path),
|
|
18961
19290
|
changes: r.repairs,
|
|
18962
19291
|
valid: r.valid
|
|
18963
19292
|
}))
|
|
@@ -18979,30 +19308,30 @@ async function validate(filePath, opts) {
|
|
|
18979
19308
|
}
|
|
18980
19309
|
let hasErrors = false;
|
|
18981
19310
|
for (const r of results) {
|
|
18982
|
-
const relPath =
|
|
19311
|
+
const relPath = path25.relative(projectRoot, r.path);
|
|
18983
19312
|
if (r.valid) {
|
|
18984
19313
|
if (r.warnings && r.warnings.length > 0) {
|
|
18985
|
-
console.log(` ${symbols.warning} ` +
|
|
19314
|
+
console.log(` ${symbols.warning} ` + chalk24.yellow(relPath));
|
|
18986
19315
|
for (const w of r.warnings) {
|
|
18987
|
-
console.log(
|
|
19316
|
+
console.log(chalk24.yellow(` \u2022 ${w}`));
|
|
18988
19317
|
}
|
|
18989
19318
|
} else {
|
|
18990
|
-
console.log(` ${symbols.success} ` +
|
|
19319
|
+
console.log(` ${symbols.success} ` + chalk24.dim(relPath));
|
|
18991
19320
|
}
|
|
18992
19321
|
for (const change of r.repairs ?? []) {
|
|
18993
|
-
console.log(` ${symbols.modified} ` +
|
|
19322
|
+
console.log(` ${symbols.modified} ` + chalk24.dim(change));
|
|
18994
19323
|
}
|
|
18995
19324
|
} else {
|
|
18996
19325
|
hasErrors = true;
|
|
18997
19326
|
console.log(` ${symbols.error} ` + relPath);
|
|
18998
19327
|
for (const change of r.repairs ?? []) {
|
|
18999
|
-
console.log(` ${symbols.modified} ` +
|
|
19328
|
+
console.log(` ${symbols.modified} ` + chalk24.dim(change));
|
|
19000
19329
|
}
|
|
19001
19330
|
for (const e of r.errors) {
|
|
19002
|
-
console.log(
|
|
19331
|
+
console.log(chalk24.dim(" " + e));
|
|
19003
19332
|
}
|
|
19004
19333
|
for (const w of r.warnings ?? []) {
|
|
19005
|
-
console.log(
|
|
19334
|
+
console.log(chalk24.yellow(" \u2022 " + w));
|
|
19006
19335
|
}
|
|
19007
19336
|
}
|
|
19008
19337
|
}
|
|
@@ -19015,7 +19344,7 @@ async function validate(filePath, opts) {
|
|
|
19015
19344
|
);
|
|
19016
19345
|
}
|
|
19017
19346
|
if (results.length === 0) {
|
|
19018
|
-
console.log(
|
|
19347
|
+
console.log(chalk24.dim(" No files to validate."));
|
|
19019
19348
|
}
|
|
19020
19349
|
if (hasErrors) {
|
|
19021
19350
|
process.exitCode = 1;
|
|
@@ -19053,9 +19382,9 @@ __export(update_exports, {
|
|
|
19053
19382
|
update: () => update
|
|
19054
19383
|
});
|
|
19055
19384
|
import { existsSync as existsSync11, readFileSync as readFileSync7 } from "fs";
|
|
19056
|
-
import { mkdir as mkdir6, readFile as
|
|
19385
|
+
import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile4 } from "fs/promises";
|
|
19057
19386
|
import { join as join8 } from "path";
|
|
19058
|
-
import
|
|
19387
|
+
import chalk25 from "chalk";
|
|
19059
19388
|
async function update(opts) {
|
|
19060
19389
|
const ctx = await resolveProject();
|
|
19061
19390
|
if (!ctx) return;
|
|
@@ -19082,7 +19411,7 @@ async function update(opts) {
|
|
|
19082
19411
|
const dest = join8(promptsDir, file);
|
|
19083
19412
|
let existing = "";
|
|
19084
19413
|
try {
|
|
19085
|
-
existing = await
|
|
19414
|
+
existing = await readFile6(dest, "utf-8");
|
|
19086
19415
|
} catch {
|
|
19087
19416
|
}
|
|
19088
19417
|
if (existing !== content) {
|
|
@@ -19100,13 +19429,13 @@ async function update(opts) {
|
|
|
19100
19429
|
opts?.host
|
|
19101
19430
|
);
|
|
19102
19431
|
if (error) {
|
|
19103
|
-
console.error(
|
|
19432
|
+
console.error(chalk25.red(` ${symbols.error} ${error}`));
|
|
19104
19433
|
process.exitCode = 1;
|
|
19105
19434
|
return;
|
|
19106
19435
|
}
|
|
19107
19436
|
if (targetHosts.length === 0) {
|
|
19108
19437
|
console.log(
|
|
19109
|
-
|
|
19438
|
+
chalk25.dim(
|
|
19110
19439
|
" No supported agent hosts detected. Specify with `iamu update --host <name>` or run `iamu init`."
|
|
19111
19440
|
)
|
|
19112
19441
|
);
|
|
@@ -19160,7 +19489,7 @@ __export(new_entity_exports, {
|
|
|
19160
19489
|
newEntity: () => newEntity
|
|
19161
19490
|
});
|
|
19162
19491
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
19163
|
-
import
|
|
19492
|
+
import chalk26 from "chalk";
|
|
19164
19493
|
function defaultFrontmatter(type2, id, slug, name, opts) {
|
|
19165
19494
|
const base = { id, slug };
|
|
19166
19495
|
const description = opts.description ? { description: opts.description } : {};
|
|
@@ -19286,9 +19615,9 @@ async function newEntity(type2, opts) {
|
|
|
19286
19615
|
}
|
|
19287
19616
|
console.log();
|
|
19288
19617
|
console.log(
|
|
19289
|
-
` ${symbols.success} Created ${entityType}: ${
|
|
19618
|
+
` ${symbols.success} Created ${entityType}: ${chalk26.cyan(slug)}`
|
|
19290
19619
|
);
|
|
19291
|
-
console.log(` ${
|
|
19620
|
+
console.log(` ${chalk26.dim("path:")} ${record.path}`);
|
|
19292
19621
|
console.log();
|
|
19293
19622
|
} catch (err) {
|
|
19294
19623
|
commandError(
|
|
@@ -19429,7 +19758,7 @@ async function crawlFrom(page, opts, origin, takeBlocked) {
|
|
|
19429
19758
|
const byKey = /* @__PURE__ */ new Map();
|
|
19430
19759
|
const byPlaceView = /* @__PURE__ */ new Map();
|
|
19431
19760
|
const signatureOf = (s) => exploreSignature(s.headings, s.title);
|
|
19432
|
-
function addSurface(state, place, view,
|
|
19761
|
+
function addSurface(state, place, view, path31, depth) {
|
|
19433
19762
|
const key = exploreSurfaceKey(place, view);
|
|
19434
19763
|
const surface = {
|
|
19435
19764
|
key,
|
|
@@ -19441,7 +19770,7 @@ async function crawlFrom(page, opts, origin, takeBlocked) {
|
|
|
19441
19770
|
headings: state.headings,
|
|
19442
19771
|
fields: state.fields,
|
|
19443
19772
|
depth,
|
|
19444
|
-
path:
|
|
19773
|
+
path: path31,
|
|
19445
19774
|
actions: []
|
|
19446
19775
|
};
|
|
19447
19776
|
surfaces.push(surface);
|
|
@@ -19459,9 +19788,9 @@ ${surface.signature}`, key);
|
|
|
19459
19788
|
});
|
|
19460
19789
|
await settle(page, settleMs);
|
|
19461
19790
|
}
|
|
19462
|
-
async function replay(
|
|
19463
|
-
if (!("goto" in (
|
|
19464
|
-
for (const step of
|
|
19791
|
+
async function replay(path31) {
|
|
19792
|
+
if (!("goto" in (path31[0] ?? {}))) await goto(opts.startUrl);
|
|
19793
|
+
for (const step of path31) {
|
|
19465
19794
|
if ("goto" in step) {
|
|
19466
19795
|
await goto(step.goto);
|
|
19467
19796
|
} else {
|
|
@@ -19585,8 +19914,8 @@ ${sig}`, key);
|
|
|
19585
19914
|
if (stats.surfaces >= budget.max_surfaces) {
|
|
19586
19915
|
stats.truncated = true;
|
|
19587
19916
|
} else {
|
|
19588
|
-
const
|
|
19589
|
-
addSurface(after, place, view,
|
|
19917
|
+
const path31 = !sameDoc && view === null ? [{ goto: after.url }] : [...surface.path, ...via, click];
|
|
19918
|
+
addSurface(after, place, view, path31, surface.depth + 1);
|
|
19590
19919
|
}
|
|
19591
19920
|
}
|
|
19592
19921
|
}
|
|
@@ -19787,11 +20116,11 @@ __export(explore_exports, {
|
|
|
19787
20116
|
exploreRun: () => exploreRun
|
|
19788
20117
|
});
|
|
19789
20118
|
import { promises as fs28 } from "fs";
|
|
19790
|
-
import
|
|
19791
|
-
import
|
|
20119
|
+
import path26 from "path";
|
|
20120
|
+
import chalk27 from "chalk";
|
|
19792
20121
|
function fail2(message, json2) {
|
|
19793
20122
|
if (json2) console.error(JSON.stringify({ error: message }));
|
|
19794
|
-
else console.error(
|
|
20123
|
+
else console.error(chalk27.red(` ${message}`));
|
|
19795
20124
|
process.exitCode = 1;
|
|
19796
20125
|
}
|
|
19797
20126
|
function positiveInt(raw, fallback, flag) {
|
|
@@ -19805,7 +20134,7 @@ function positiveInt(raw, fallback, flag) {
|
|
|
19805
20134
|
async function testabilityTarget2(projectRoot) {
|
|
19806
20135
|
try {
|
|
19807
20136
|
const raw = await fs28.readFile(
|
|
19808
|
-
|
|
20137
|
+
path26.join(projectRoot, "iamu", "testability.md"),
|
|
19809
20138
|
"utf8"
|
|
19810
20139
|
);
|
|
19811
20140
|
const { frontmatter } = parseFrontmatter(raw);
|
|
@@ -19894,7 +20223,7 @@ async function exploreRun(url, opts) {
|
|
|
19894
20223
|
}
|
|
19895
20224
|
const quiet = opts.json || process.env.IAMU_QUIET === "1";
|
|
19896
20225
|
if (!quiet) {
|
|
19897
|
-
console.error(
|
|
20226
|
+
console.error(chalk27.dim(` Exploring ${startUrl} (read-only)\u2026`));
|
|
19898
20227
|
}
|
|
19899
20228
|
const now = /* @__PURE__ */ new Date();
|
|
19900
20229
|
let opened = null;
|
|
@@ -19905,7 +20234,7 @@ async function exploreRun(url, opts) {
|
|
|
19905
20234
|
startUrl,
|
|
19906
20235
|
budget,
|
|
19907
20236
|
deny,
|
|
19908
|
-
log: quiet ? void 0 : (line) => console.error(
|
|
20237
|
+
log: quiet ? void 0 : (line) => console.error(chalk27.dim(line))
|
|
19909
20238
|
});
|
|
19910
20239
|
} catch (err) {
|
|
19911
20240
|
fail2(err.message.split("\n")[0], opts.json);
|
|
@@ -19925,7 +20254,7 @@ async function exploreRun(url, opts) {
|
|
|
19925
20254
|
surfaces: result.surfaces
|
|
19926
20255
|
};
|
|
19927
20256
|
const file = await writeExploreMap(ctx.projectRoot, map2);
|
|
19928
|
-
const rel =
|
|
20257
|
+
const rel = path26.relative(process.cwd(), file);
|
|
19929
20258
|
if (opts.json) {
|
|
19930
20259
|
console.log(JSON.stringify({ id: map2.id, path: rel, stats: map2.stats }));
|
|
19931
20260
|
return;
|
|
@@ -19933,17 +20262,17 @@ async function exploreRun(url, opts) {
|
|
|
19933
20262
|
const s = map2.stats;
|
|
19934
20263
|
console.log(
|
|
19935
20264
|
`
|
|
19936
|
-
${
|
|
20265
|
+
${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` : ""}`
|
|
19937
20266
|
);
|
|
19938
20267
|
if (s.truncated) {
|
|
19939
20268
|
console.log(
|
|
19940
|
-
|
|
20269
|
+
chalk27.yellow(
|
|
19941
20270
|
" Stopped by the budget before the product ran out \u2014 raise --max-surfaces / --max-actions / --max-depth to go further."
|
|
19942
20271
|
)
|
|
19943
20272
|
);
|
|
19944
20273
|
}
|
|
19945
20274
|
console.log(` Map: ${rel}`);
|
|
19946
|
-
console.log(
|
|
20275
|
+
console.log(chalk27.dim(" Next: iamu explore coverage"));
|
|
19947
20276
|
}
|
|
19948
20277
|
async function resolveMapId(projectRoot, id, offsetFromEnd = 1) {
|
|
19949
20278
|
if (id && id !== "latest") return id;
|
|
@@ -19971,7 +20300,7 @@ async function exploreList(opts) {
|
|
|
19971
20300
|
}
|
|
19972
20301
|
for (const r of rows) {
|
|
19973
20302
|
console.log(
|
|
19974
|
-
` ${r.id} ${r.surfaces} surfaces ${
|
|
20303
|
+
` ${r.id} ${r.surfaces} surfaces ${chalk27.dim(r.target_url)}`
|
|
19975
20304
|
);
|
|
19976
20305
|
}
|
|
19977
20306
|
}
|
|
@@ -20000,7 +20329,7 @@ async function exploreCoverageCommand(mapId, opts) {
|
|
|
20000
20329
|
Map ${id} (${map2.surfaces.length} surfaces) against ${cov.runs} runs, ${cov.steps} steps`
|
|
20001
20330
|
);
|
|
20002
20331
|
console.log(
|
|
20003
|
-
` ${
|
|
20332
|
+
` ${chalk27.green(`${cov.reached} reached`)} \xB7 ${chalk27.yellow(`${cov.place_only} URL reached, view unclear`)} \xB7 ${chalk27.red(`${cov.unreached} never reached`)}`
|
|
20004
20333
|
);
|
|
20005
20334
|
const section = (title, rows, color) => {
|
|
20006
20335
|
if (rows.length === 0) return;
|
|
@@ -20008,23 +20337,23 @@ async function exploreCoverageCommand(mapId, opts) {
|
|
|
20008
20337
|
${color(title)}`);
|
|
20009
20338
|
for (const r of rows) {
|
|
20010
20339
|
console.log(
|
|
20011
|
-
` ${r.key.padEnd(32)} ${r.label}${
|
|
20340
|
+
` ${r.key.padEnd(32)} ${r.label}${chalk27.dim(` (depth ${r.depth})`)}`
|
|
20012
20341
|
);
|
|
20013
20342
|
}
|
|
20014
20343
|
};
|
|
20015
20344
|
section(
|
|
20016
20345
|
"Never reached by a run",
|
|
20017
20346
|
cov.surfaces.filter((s) => s.status === "unreached"),
|
|
20018
|
-
|
|
20347
|
+
chalk27.red
|
|
20019
20348
|
);
|
|
20020
20349
|
section(
|
|
20021
20350
|
"URL reached, but no step names this view",
|
|
20022
20351
|
cov.surfaces.filter((s) => s.status === "place_only"),
|
|
20023
|
-
|
|
20352
|
+
chalk27.yellow
|
|
20024
20353
|
);
|
|
20025
20354
|
if (cov.run_only_places.length > 0) {
|
|
20026
20355
|
console.log(`
|
|
20027
|
-
${
|
|
20356
|
+
${chalk27.cyan("Walked by runs, not in the map")}`);
|
|
20028
20357
|
for (const p of cov.run_only_places) {
|
|
20029
20358
|
console.log(
|
|
20030
20359
|
` ${p.place.padEnd(32)} ${p.steps} steps, ${p.runs.length} runs`
|
|
@@ -20033,7 +20362,7 @@ async function exploreCoverageCommand(mapId, opts) {
|
|
|
20033
20362
|
}
|
|
20034
20363
|
if (cov.runs === 0) {
|
|
20035
20364
|
console.log(
|
|
20036
|
-
|
|
20365
|
+
chalk27.dim(
|
|
20037
20366
|
"\n No runs yet \u2014 every surface counts as never reached. Walk a scenario first (iamu-run)."
|
|
20038
20367
|
)
|
|
20039
20368
|
);
|
|
@@ -20069,27 +20398,27 @@ async function exploreDiffCommand(a, b, opts) {
|
|
|
20069
20398
|
console.log(`
|
|
20070
20399
|
${idA} \u2192 ${idB}`);
|
|
20071
20400
|
console.log(
|
|
20072
|
-
` ${
|
|
20401
|
+
` ${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)`
|
|
20073
20402
|
);
|
|
20074
20403
|
if (d.only_a.length > 0) {
|
|
20075
20404
|
console.log(`
|
|
20076
|
-
${
|
|
20405
|
+
${chalk27.red("Only in the first")}`);
|
|
20077
20406
|
for (const s of d.only_a) console.log(` ${s.key.padEnd(32)} ${s.label}`);
|
|
20078
20407
|
}
|
|
20079
20408
|
if (d.only_b.length > 0) {
|
|
20080
20409
|
console.log(`
|
|
20081
|
-
${
|
|
20410
|
+
${chalk27.green("Only in the second")}`);
|
|
20082
20411
|
for (const s of d.only_b) console.log(` ${s.key.padEnd(32)} ${s.label}`);
|
|
20083
20412
|
}
|
|
20084
20413
|
if (d.changed_actions.length > 0) {
|
|
20085
20414
|
console.log(
|
|
20086
20415
|
`
|
|
20087
|
-
${
|
|
20416
|
+
${chalk27.yellow(`Controls differ on ${d.changed_actions.length} shared surfaces`)}`
|
|
20088
20417
|
);
|
|
20089
20418
|
for (const c of d.changed_actions) {
|
|
20090
20419
|
console.log(` ${c.key} ${c.label}`);
|
|
20091
|
-
for (const x of c.only_a) console.log(
|
|
20092
|
-
for (const x of c.only_b) console.log(
|
|
20420
|
+
for (const x of c.only_a) console.log(chalk27.red(` - ${x}`));
|
|
20421
|
+
for (const x of c.only_b) console.log(chalk27.green(` + ${x}`));
|
|
20093
20422
|
}
|
|
20094
20423
|
}
|
|
20095
20424
|
}
|
|
@@ -20303,7 +20632,7 @@ __export(instructions_walk_exports, {
|
|
|
20303
20632
|
});
|
|
20304
20633
|
import { existsSync as existsSync12, readFileSync as readFileSync8 } from "fs";
|
|
20305
20634
|
import { join as join9 } from "path";
|
|
20306
|
-
import
|
|
20635
|
+
import chalk28 from "chalk";
|
|
20307
20636
|
function selfCommand() {
|
|
20308
20637
|
const q = (p) => /[\s"'$]/.test(p) ? JSON.stringify(p) : p;
|
|
20309
20638
|
return `${q(process.execPath)} ${q(process.argv[1] ?? "iamu")}`;
|
|
@@ -20675,40 +21004,40 @@ async function instructionsWalk(opts) {
|
|
|
20675
21004
|
return;
|
|
20676
21005
|
}
|
|
20677
21006
|
console.log();
|
|
20678
|
-
console.log(
|
|
20679
|
-
console.log(` ${
|
|
20680
|
-
console.log(` ${
|
|
20681
|
-
console.log(` ${
|
|
21007
|
+
console.log(chalk28.bold(" Walk instructions"));
|
|
21008
|
+
console.log(` ${chalk28.dim("scenario:")} ${sfm.slug}`);
|
|
21009
|
+
console.log(` ${chalk28.dim("persona:")} ${pfm.name} (${pfm.role})`);
|
|
21010
|
+
console.log(` ${chalk28.dim("outline:")} ${ofm.title}`);
|
|
20682
21011
|
if (sfm.state?.description || sfm.state?.approximation) {
|
|
20683
21012
|
console.log(
|
|
20684
|
-
` ${
|
|
21013
|
+
` ${chalk28.dim("state:")} ${sfm.state.description ? sfm.state.description : sfm.state.approximation ?? ""}`
|
|
20685
21014
|
);
|
|
20686
21015
|
}
|
|
20687
|
-
if (targetUrl) console.log(` ${
|
|
21016
|
+
if (targetUrl) console.log(` ${chalk28.dim("target:")} ${targetUrl}`);
|
|
20688
21017
|
console.log(
|
|
20689
|
-
` ${
|
|
21018
|
+
` ${chalk28.dim("access:")} ${projectAccess || personaAccess ? `${projectAccess ? "project" : ""}${projectAccess && personaAccess ? " + " : ""}${personaAccess ? "persona" : ""}` : "not recorded (walker would run as whoever is signed in)"}`
|
|
20690
21019
|
);
|
|
20691
21020
|
console.log(
|
|
20692
|
-
` ${
|
|
21021
|
+
` ${chalk28.dim("dismissed:")} ${dismissedFacts.length} findings to skip`
|
|
20693
21022
|
);
|
|
20694
21023
|
console.log(
|
|
20695
|
-
` ${
|
|
21024
|
+
` ${chalk28.dim("guidance:")} ${guidance.length} tester guidance rule${guidance.length === 1 ? "" : "s"}`
|
|
20696
21025
|
);
|
|
20697
21026
|
if (untestableBoundaries.length > 0) {
|
|
20698
21027
|
console.log(
|
|
20699
|
-
` ${
|
|
21028
|
+
` ${chalk28.dim("boundaries:")} ${untestableBoundaries.length} untestable boundaries to avoid`
|
|
20700
21029
|
);
|
|
20701
21030
|
}
|
|
20702
21031
|
if (revisit.length > 0) {
|
|
20703
21032
|
console.log(
|
|
20704
|
-
` ${
|
|
21033
|
+
` ${chalk28.dim("re-check:")} ${revisit.length} place${revisit.length === 1 ? "" : "s"} where fixes await a re-run`
|
|
20705
21034
|
);
|
|
20706
21035
|
}
|
|
20707
21036
|
console.log(
|
|
20708
|
-
` ${
|
|
21037
|
+
` ${chalk28.dim("methodology:")} ${methodology ? "loaded" : "missing (run iamu update)"}`
|
|
20709
21038
|
);
|
|
20710
21039
|
console.log();
|
|
20711
|
-
console.log(
|
|
21040
|
+
console.log(chalk28.dim(" Use --json to get the full instruction bundle."));
|
|
20712
21041
|
console.log();
|
|
20713
21042
|
}
|
|
20714
21043
|
var SCREEN;
|
|
@@ -20733,9 +21062,9 @@ __export(new_finding_exports, {
|
|
|
20733
21062
|
newFinding: () => newFinding
|
|
20734
21063
|
});
|
|
20735
21064
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
20736
|
-
import { access, readFile as
|
|
20737
|
-
import
|
|
20738
|
-
import
|
|
21065
|
+
import { access, readFile as readFile7 } from "fs/promises";
|
|
21066
|
+
import path27 from "path";
|
|
21067
|
+
import chalk29 from "chalk";
|
|
20739
21068
|
async function newFinding(opts) {
|
|
20740
21069
|
const ctx = await resolveProject(opts);
|
|
20741
21070
|
if (!ctx) return;
|
|
@@ -20801,7 +21130,7 @@ async function newFinding(opts) {
|
|
|
20801
21130
|
}
|
|
20802
21131
|
try {
|
|
20803
21132
|
await access(
|
|
20804
|
-
|
|
21133
|
+
path27.join(runDirPath, "steps", `${String(n).padStart(3, "0")}.json`)
|
|
20805
21134
|
);
|
|
20806
21135
|
} catch {
|
|
20807
21136
|
commandError(
|
|
@@ -20815,8 +21144,8 @@ async function newFinding(opts) {
|
|
|
20815
21144
|
let scenarioSlug = opts.scenario;
|
|
20816
21145
|
if (!scenarioSlug) {
|
|
20817
21146
|
try {
|
|
20818
|
-
const manifestRaw = await
|
|
20819
|
-
|
|
21147
|
+
const manifestRaw = await readFile7(
|
|
21148
|
+
path27.join(runDirPath, "walkthrough.json"),
|
|
20820
21149
|
"utf8"
|
|
20821
21150
|
);
|
|
20822
21151
|
const manifest = JSON.parse(manifestRaw);
|
|
@@ -20889,6 +21218,18 @@ async function newFinding(opts) {
|
|
|
20889
21218
|
].join("\n");
|
|
20890
21219
|
try {
|
|
20891
21220
|
const record = await writeEntity(projectRoot, "finding", frontmatter, body);
|
|
21221
|
+
sendLiveFinding(projectRoot, opts.run, {
|
|
21222
|
+
id,
|
|
21223
|
+
title: opts.title,
|
|
21224
|
+
type: opts.type,
|
|
21225
|
+
severity: opts.severity,
|
|
21226
|
+
ui_fact: uiFact,
|
|
21227
|
+
consequence,
|
|
21228
|
+
step_number: opts.step ? Number(opts.step) : void 0,
|
|
21229
|
+
task_impact: opts.taskImpact,
|
|
21230
|
+
confidence: opts.confidence
|
|
21231
|
+
}).catch(() => {
|
|
21232
|
+
});
|
|
20892
21233
|
if (opts.json) {
|
|
20893
21234
|
console.log(
|
|
20894
21235
|
JSON.stringify(
|
|
@@ -20905,10 +21246,10 @@ async function newFinding(opts) {
|
|
|
20905
21246
|
return;
|
|
20906
21247
|
}
|
|
20907
21248
|
console.log();
|
|
20908
|
-
console.log(` ${symbols.success} Created finding: ${
|
|
20909
|
-
console.log(` ${
|
|
20910
|
-
console.log(` ${
|
|
20911
|
-
for (const w of warnings) console.log(` ${
|
|
21249
|
+
console.log(` ${symbols.success} Created finding: ${chalk29.cyan(slug)}`);
|
|
21250
|
+
console.log(` ${chalk29.dim("path:")} ${record.path}`);
|
|
21251
|
+
console.log(` ${chalk29.dim("id:")} ${id}`);
|
|
21252
|
+
for (const w of warnings) console.log(` ${chalk29.yellow("!")} ${w}`);
|
|
20912
21253
|
console.log();
|
|
20913
21254
|
} catch (err) {
|
|
20914
21255
|
commandError(
|
|
@@ -20924,6 +21265,7 @@ var init_new_finding = __esm({
|
|
|
20924
21265
|
init_dist();
|
|
20925
21266
|
init_symbols();
|
|
20926
21267
|
init_context4();
|
|
21268
|
+
init_live_run_client();
|
|
20927
21269
|
}
|
|
20928
21270
|
});
|
|
20929
21271
|
|
|
@@ -20934,7 +21276,7 @@ __export(view_results_exports, {
|
|
|
20934
21276
|
promptViewResults: () => promptViewResults
|
|
20935
21277
|
});
|
|
20936
21278
|
import { isCancel as isCancel4, select as select4 } from "@clack/prompts";
|
|
20937
|
-
import
|
|
21279
|
+
import chalk30 from "chalk";
|
|
20938
21280
|
function launchCloudDashboard(config, runId) {
|
|
20939
21281
|
const cloudRunId = runId ? toCloudRunUuid(runId) : void 0;
|
|
20940
21282
|
const url = getCloudDashboardUrl(
|
|
@@ -20943,7 +21285,7 @@ function launchCloudDashboard(config, runId) {
|
|
|
20943
21285
|
cloudRunId
|
|
20944
21286
|
);
|
|
20945
21287
|
console.log();
|
|
20946
|
-
console.log(` ${symbols.success} Opening Iamu Cloud: ${
|
|
21288
|
+
console.log(` ${symbols.success} Opening Iamu Cloud: ${chalk30.cyan(url)}
|
|
20947
21289
|
`);
|
|
20948
21290
|
openBrowser(url);
|
|
20949
21291
|
}
|
|
@@ -21012,8 +21354,8 @@ __export(evaluate_exports, {
|
|
|
21012
21354
|
evaluateRecord: () => evaluateRecord
|
|
21013
21355
|
});
|
|
21014
21356
|
import { promises as fs29 } from "fs";
|
|
21015
|
-
import
|
|
21016
|
-
import
|
|
21357
|
+
import path28 from "path";
|
|
21358
|
+
import chalk31 from "chalk";
|
|
21017
21359
|
import { z as z25 } from "zod";
|
|
21018
21360
|
function formatIssues(error) {
|
|
21019
21361
|
return error.issues.map(
|
|
@@ -21043,7 +21385,7 @@ async function evaluate(runId, opts) {
|
|
|
21043
21385
|
const resolved = await resolveProjectAndRunDir(runId, opts);
|
|
21044
21386
|
if (!resolved) return;
|
|
21045
21387
|
const { projectRoot, runDirPath } = resolved;
|
|
21046
|
-
const canonicalPath =
|
|
21388
|
+
const canonicalPath = path28.join(runDirPath, "canonical.json");
|
|
21047
21389
|
let canonical;
|
|
21048
21390
|
try {
|
|
21049
21391
|
const raw = await fs29.readFile(canonicalPath, "utf8");
|
|
@@ -21102,15 +21444,15 @@ async function evaluate(runId, opts) {
|
|
|
21102
21444
|
)
|
|
21103
21445
|
};
|
|
21104
21446
|
const prompt = composeJudgePrompt(input);
|
|
21105
|
-
const promptFilePath = opts?.promptFile ??
|
|
21447
|
+
const promptFilePath = opts?.promptFile ?? path28.join(runDirPath, "judge_prompt.md");
|
|
21106
21448
|
await fs29.writeFile(promptFilePath, prompt, "utf8");
|
|
21107
21449
|
if (opts?.json) {
|
|
21108
21450
|
console.log(
|
|
21109
21451
|
JSON.stringify(
|
|
21110
21452
|
{
|
|
21111
21453
|
...input,
|
|
21112
|
-
prompt_file:
|
|
21113
|
-
prompt_file_abs:
|
|
21454
|
+
prompt_file: path28.relative(projectRoot, promptFilePath),
|
|
21455
|
+
prompt_file_abs: path28.resolve(promptFilePath),
|
|
21114
21456
|
judge_prompt: prompt
|
|
21115
21457
|
},
|
|
21116
21458
|
null,
|
|
@@ -21125,7 +21467,9 @@ async function evaluateRecord(runId, opts) {
|
|
|
21125
21467
|
const resolved = await resolveProjectAndRunDir(runId, opts);
|
|
21126
21468
|
if (!resolved) return;
|
|
21127
21469
|
const { projectRoot, runDirPath } = resolved;
|
|
21128
|
-
|
|
21470
|
+
sendLivePhase(projectRoot, runId, "judging").catch(() => {
|
|
21471
|
+
});
|
|
21472
|
+
const canonicalPath = path28.join(runDirPath, "canonical.json");
|
|
21129
21473
|
let canonical;
|
|
21130
21474
|
try {
|
|
21131
21475
|
const raw = await fs29.readFile(canonicalPath, "utf8");
|
|
@@ -21193,8 +21537,8 @@ ${formatIssues(fileResult.error)}`,
|
|
|
21193
21537
|
overall: inputVerdicts.overall
|
|
21194
21538
|
});
|
|
21195
21539
|
const reportContent = renderCanonicalMarkdown(canonicalForReport);
|
|
21196
|
-
const verdictsPath =
|
|
21197
|
-
const reportPath =
|
|
21540
|
+
const verdictsPath = path28.join(runDirPath, "verdicts.json");
|
|
21541
|
+
const reportPath = path28.join(runDirPath, "report.md");
|
|
21198
21542
|
await Promise.all([
|
|
21199
21543
|
atomicWriteFile(
|
|
21200
21544
|
verdictsPath,
|
|
@@ -21214,8 +21558,8 @@ ${formatIssues(fileResult.error)}`,
|
|
|
21214
21558
|
JSON.stringify(
|
|
21215
21559
|
{
|
|
21216
21560
|
runId,
|
|
21217
|
-
verdictsPath:
|
|
21218
|
-
reportPath:
|
|
21561
|
+
verdictsPath: path28.relative(projectRoot, verdictsPath),
|
|
21562
|
+
reportPath: path28.relative(projectRoot, reportPath),
|
|
21219
21563
|
verdictsCount: validatedVerdicts.length,
|
|
21220
21564
|
linkedCount: linked.length,
|
|
21221
21565
|
...cloudInfo ? { cloud: cloudInfo } : {}
|
|
@@ -21228,18 +21572,18 @@ ${formatIssues(fileResult.error)}`,
|
|
|
21228
21572
|
}
|
|
21229
21573
|
console.log();
|
|
21230
21574
|
console.log(
|
|
21231
|
-
` ${symbols.success} Recorded ${validatedVerdicts.length} verdicts for run ${
|
|
21575
|
+
` ${symbols.success} Recorded ${validatedVerdicts.length} verdicts for run ${chalk31.cyan(runId)}`
|
|
21232
21576
|
);
|
|
21233
21577
|
if (linked.length > 0) {
|
|
21234
21578
|
console.log(
|
|
21235
|
-
` ${
|
|
21579
|
+
` ${chalk31.dim("linked:")} ${linked.length} finding${linked.length === 1 ? "" : "s"} to the human test${linked.length === 1 ? "" : "s"} citing ${linked.length === 1 ? "it" : "them"}`
|
|
21236
21580
|
);
|
|
21237
21581
|
}
|
|
21238
21582
|
console.log(
|
|
21239
|
-
` ${
|
|
21583
|
+
` ${chalk31.dim("verdicts:")} ${path28.relative(projectRoot, verdictsPath)}`
|
|
21240
21584
|
);
|
|
21241
21585
|
console.log(
|
|
21242
|
-
` ${
|
|
21586
|
+
` ${chalk31.dim("report:")} ${path28.relative(projectRoot, reportPath)}`
|
|
21243
21587
|
);
|
|
21244
21588
|
printCloudRunInfo(cloudInfo);
|
|
21245
21589
|
await promptViewResults(projectRoot, { ...opts, runId });
|
|
@@ -21253,6 +21597,7 @@ var init_evaluate = __esm({
|
|
|
21253
21597
|
init_symbols();
|
|
21254
21598
|
init_cloud_push();
|
|
21255
21599
|
init_context4();
|
|
21600
|
+
init_live_run_client();
|
|
21256
21601
|
init_view_results();
|
|
21257
21602
|
verdictValueSchema = z25.enum(["yes", "partial", "no", "not_applicable"]);
|
|
21258
21603
|
idList = z25.array(z25.string()).optional();
|
|
@@ -21304,18 +21649,20 @@ __export(complete_exports, {
|
|
|
21304
21649
|
validateCanonicalWalkthrough: () => validateCanonicalWalkthrough
|
|
21305
21650
|
});
|
|
21306
21651
|
import { promises as fs30 } from "fs";
|
|
21307
|
-
import
|
|
21308
|
-
import
|
|
21652
|
+
import path29 from "path";
|
|
21653
|
+
import chalk32 from "chalk";
|
|
21309
21654
|
async function complete(runId, opts) {
|
|
21310
21655
|
const run = await loadRun(runId, opts);
|
|
21311
21656
|
if (!run) return;
|
|
21657
|
+
sendLivePhase(run.projectRoot, runId, "completing").catch(() => {
|
|
21658
|
+
});
|
|
21312
21659
|
if (run.manifest.status === "completed" && !opts?.force) {
|
|
21313
21660
|
await reportAlreadyCompleted(run, opts);
|
|
21314
21661
|
return;
|
|
21315
21662
|
}
|
|
21316
21663
|
if (!opts?.json) {
|
|
21317
21664
|
console.log();
|
|
21318
|
-
console.log(
|
|
21665
|
+
console.log(chalk32.bold(" Assembling canonical JSON\u2026"));
|
|
21319
21666
|
}
|
|
21320
21667
|
const provenanceAudit = auditStepProvenance(
|
|
21321
21668
|
await readStepsForRun(run.projectRoot, runId)
|
|
@@ -21329,7 +21676,7 @@ async function complete(runId, opts) {
|
|
|
21329
21676
|
let judgeReported;
|
|
21330
21677
|
try {
|
|
21331
21678
|
const verdictsRaw = await fs30.readFile(
|
|
21332
|
-
|
|
21679
|
+
path29.join(run.runDirPath, "verdicts.json"),
|
|
21333
21680
|
"utf8"
|
|
21334
21681
|
);
|
|
21335
21682
|
const parsed = JSON.parse(verdictsRaw);
|
|
@@ -21386,7 +21733,7 @@ async function loadRun(runId, opts) {
|
|
|
21386
21733
|
commandError(`Run not found: ${runId}`, opts);
|
|
21387
21734
|
return null;
|
|
21388
21735
|
}
|
|
21389
|
-
const manifestPath =
|
|
21736
|
+
const manifestPath = path29.join(runDirPath, "walkthrough.json");
|
|
21390
21737
|
let manifest;
|
|
21391
21738
|
try {
|
|
21392
21739
|
manifest = JSON.parse(
|
|
@@ -21403,7 +21750,7 @@ async function reportAlreadyCompleted(run, opts) {
|
|
|
21403
21750
|
if (opts?.json) {
|
|
21404
21751
|
try {
|
|
21405
21752
|
const raw = await fs30.readFile(
|
|
21406
|
-
|
|
21753
|
+
path29.join(run.runDirPath, "canonical.json"),
|
|
21407
21754
|
"utf8"
|
|
21408
21755
|
);
|
|
21409
21756
|
console.log(raw.trim());
|
|
@@ -21423,18 +21770,18 @@ async function reportAlreadyCompleted(run, opts) {
|
|
|
21423
21770
|
return;
|
|
21424
21771
|
}
|
|
21425
21772
|
console.log();
|
|
21426
|
-
console.log(
|
|
21427
|
-
console.log(` status ${
|
|
21773
|
+
console.log(chalk32.bold(" Run: ") + chalk32.cyan(runId));
|
|
21774
|
+
console.log(` status ${chalk32.green("completed")}`);
|
|
21428
21775
|
if (manifest.completed_at) {
|
|
21429
|
-
console.log(` completed ${
|
|
21776
|
+
console.log(` completed ${chalk32.dim(manifest.completed_at)}`);
|
|
21430
21777
|
}
|
|
21431
21778
|
const viewUrl = await pushedRunUrl(run.projectRoot, runId);
|
|
21432
21779
|
if (viewUrl) {
|
|
21433
|
-
console.log(` view ${
|
|
21780
|
+
console.log(` view ${chalk32.underline(viewUrl)}`);
|
|
21434
21781
|
}
|
|
21435
21782
|
console.log();
|
|
21436
21783
|
console.log(
|
|
21437
|
-
|
|
21784
|
+
chalk32.dim(
|
|
21438
21785
|
" Already completed \u2014 nothing to do. Use --force to reassemble the report."
|
|
21439
21786
|
)
|
|
21440
21787
|
);
|
|
@@ -21450,13 +21797,13 @@ function reportStrictProvenanceFailure(audit, opts) {
|
|
|
21450
21797
|
}
|
|
21451
21798
|
console.error();
|
|
21452
21799
|
console.error(
|
|
21453
|
-
|
|
21800
|
+
chalk32.red(` ${symbols.error} Strict provenance audit failed:`)
|
|
21454
21801
|
);
|
|
21455
21802
|
for (const w of audit.warnings) {
|
|
21456
|
-
console.error(
|
|
21803
|
+
console.error(chalk32.red(` \u2022 ${w}`));
|
|
21457
21804
|
}
|
|
21458
21805
|
console.error(
|
|
21459
|
-
|
|
21806
|
+
chalk32.dim(
|
|
21460
21807
|
" Run was flagged as synthetic / scripted. Remove --strict-provenance to complete anyway."
|
|
21461
21808
|
)
|
|
21462
21809
|
);
|
|
@@ -21497,41 +21844,41 @@ function completeJsonPayload(canonical, extras) {
|
|
|
21497
21844
|
function printCompletionSummary(run, completedAt, assembled, extras, provenanceAudit) {
|
|
21498
21845
|
const { runId, projectRoot, manifest } = run;
|
|
21499
21846
|
const { canonical } = assembled;
|
|
21500
|
-
const count = (n) => n === 0 ?
|
|
21501
|
-
console.log(
|
|
21502
|
-
console.log(` scenario ${
|
|
21503
|
-
console.log(` url ${
|
|
21847
|
+
const count = (n) => n === 0 ? chalk32.dim("0") : chalk32.cyan(String(n));
|
|
21848
|
+
console.log(chalk32.bold(" Run: ") + chalk32.cyan(runId));
|
|
21849
|
+
console.log(` scenario ${chalk32.dim(manifest.scenario_slug)}`);
|
|
21850
|
+
console.log(` url ${chalk32.dim(manifest.target_url)}`);
|
|
21504
21851
|
if (manifest.environment) {
|
|
21505
|
-
console.log(` env ${
|
|
21852
|
+
console.log(` env ${chalk32.dim(manifest.environment)}`);
|
|
21506
21853
|
}
|
|
21507
21854
|
if (manifest.build) {
|
|
21508
|
-
console.log(` build ${
|
|
21855
|
+
console.log(` build ${chalk32.dim(formatBuild(manifest.build))}`);
|
|
21509
21856
|
}
|
|
21510
21857
|
if (manifest.viewport) {
|
|
21511
|
-
console.log(` device ${
|
|
21858
|
+
console.log(` device ${chalk32.dim(formatViewport(manifest.viewport))}`);
|
|
21512
21859
|
}
|
|
21513
|
-
console.log(` status ${
|
|
21860
|
+
console.log(` status ${chalk32.green("completed")}`);
|
|
21514
21861
|
console.log(` findings ${count(canonical.findings.length)}`);
|
|
21515
21862
|
console.log(` steps ${count(canonical.steps.length)}`);
|
|
21516
|
-
console.log(` started ${
|
|
21517
|
-
console.log(` completed ${
|
|
21863
|
+
console.log(` started ${chalk32.dim(manifest.created_at)}`);
|
|
21864
|
+
console.log(` completed ${chalk32.dim(completedAt)}`);
|
|
21518
21865
|
const models = manifest.models;
|
|
21519
21866
|
if (models?.velocity_sec_per_step != null) {
|
|
21520
21867
|
console.log(
|
|
21521
|
-
` velocity ${
|
|
21868
|
+
` velocity ${chalk32.cyan(`~${models.velocity_sec_per_step}s/step`)} ${chalk32.dim(`(${models.total_duration_sec}s total)`)}`
|
|
21522
21869
|
);
|
|
21523
21870
|
}
|
|
21524
21871
|
if (models && (models.walker || models.judge || models.matcher)) {
|
|
21525
21872
|
const w = models.walker_reported ? `${models.walker} (${models.walker_reported})` : models.walker ?? "fast";
|
|
21526
21873
|
const j = models.judge_reported ? `${models.judge} (${models.judge_reported})` : models.judge ?? "thorough";
|
|
21527
|
-
console.log(` models ${
|
|
21874
|
+
console.log(` models ${chalk32.dim(`walker: ${w} \xB7 judge: ${j}`)}`);
|
|
21528
21875
|
}
|
|
21529
21876
|
console.log();
|
|
21530
21877
|
console.log(
|
|
21531
|
-
` ${
|
|
21878
|
+
` ${chalk32.dim("canonical:")} ${chalk32.dim(path29.relative(projectRoot, assembled.canonicalPath))}`
|
|
21532
21879
|
);
|
|
21533
21880
|
console.log(
|
|
21534
|
-
` ${
|
|
21881
|
+
` ${chalk32.dim("report:")} ${chalk32.dim(path29.relative(projectRoot, assembled.reportPath))}`
|
|
21535
21882
|
);
|
|
21536
21883
|
if (extras.viewportWarning) {
|
|
21537
21884
|
console.log();
|
|
@@ -21539,7 +21886,7 @@ function printCompletionSummary(run, completedAt, assembled, extras, provenanceA
|
|
|
21539
21886
|
}
|
|
21540
21887
|
if (extras.codeWarning) {
|
|
21541
21888
|
console.log();
|
|
21542
|
-
console.log(` ${
|
|
21889
|
+
console.log(` ${chalk32.yellow("!")} ${extras.codeWarning}`);
|
|
21543
21890
|
}
|
|
21544
21891
|
if (extras.revisit) printRevisit(extras.revisit);
|
|
21545
21892
|
if (assembled.verification) printVerification(assembled.verification);
|
|
@@ -21551,13 +21898,13 @@ function printProvenanceWarnings(audit) {
|
|
|
21551
21898
|
if (audit.warnings.length === 0) return;
|
|
21552
21899
|
console.log();
|
|
21553
21900
|
console.log(
|
|
21554
|
-
` ${symbols.warning} ${
|
|
21901
|
+
` ${symbols.warning} ${chalk32.yellow("Step provenance audit flagged suspicious timing:")}`
|
|
21555
21902
|
);
|
|
21556
21903
|
for (const w of audit.warnings) {
|
|
21557
|
-
console.log(` ${
|
|
21904
|
+
console.log(` ${chalk32.dim("\u2022")} ${w}`);
|
|
21558
21905
|
}
|
|
21559
21906
|
console.log(
|
|
21560
|
-
|
|
21907
|
+
chalk32.dim(
|
|
21561
21908
|
" Run appears to be programmatically batch-generated rather than an interactive walkthrough."
|
|
21562
21909
|
)
|
|
21563
21910
|
);
|
|
@@ -21589,7 +21936,7 @@ function screenshotFitsViewport(width, expected) {
|
|
|
21589
21936
|
}
|
|
21590
21937
|
async function screenshotSizeWarning(runDirPath, viewport) {
|
|
21591
21938
|
if (!viewport) return null;
|
|
21592
|
-
const dir =
|
|
21939
|
+
const dir = path29.join(runDirPath, "screenshots");
|
|
21593
21940
|
let first;
|
|
21594
21941
|
try {
|
|
21595
21942
|
first = (await fs30.readdir(dir)).filter((f) => f.toLowerCase().endsWith(".png")).sort((a, b) => a.localeCompare(b, void 0, { numeric: true }))[0];
|
|
@@ -21599,7 +21946,7 @@ async function screenshotSizeWarning(runDirPath, viewport) {
|
|
|
21599
21946
|
if (!first) return null;
|
|
21600
21947
|
let size = null;
|
|
21601
21948
|
try {
|
|
21602
|
-
const handle = await fs30.open(
|
|
21949
|
+
const handle = await fs30.open(path29.join(dir, first), "r");
|
|
21603
21950
|
try {
|
|
21604
21951
|
const head = Buffer.alloc(24);
|
|
21605
21952
|
const { bytesRead } = await handle.read(head, 0, 24, 0);
|
|
@@ -21616,7 +21963,7 @@ async function screenshotSizeWarning(runDirPath, viewport) {
|
|
|
21616
21963
|
async function readWalkerSummary(runDirPath) {
|
|
21617
21964
|
try {
|
|
21618
21965
|
const data = JSON.parse(
|
|
21619
|
-
await fs30.readFile(
|
|
21966
|
+
await fs30.readFile(path29.join(runDirPath, "summary.json"), "utf8")
|
|
21620
21967
|
);
|
|
21621
21968
|
const strings = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string" && x.trim() !== "") : void 0;
|
|
21622
21969
|
const model = typeof data.model === "string" && data.model.trim() !== "" ? data.model.trim() : void 0;
|
|
@@ -21725,7 +22072,7 @@ function validateCanonicalWalkthrough(canonical) {
|
|
|
21725
22072
|
async function applyRecordedVerdicts(canonical, runDirPath) {
|
|
21726
22073
|
try {
|
|
21727
22074
|
const recorded = JSON.parse(
|
|
21728
|
-
await fs30.readFile(
|
|
22075
|
+
await fs30.readFile(path29.join(runDirPath, "verdicts.json"), "utf8")
|
|
21729
22076
|
);
|
|
21730
22077
|
if (Array.isArray(recorded.verdicts)) {
|
|
21731
22078
|
return applyVerdicts(canonical, recorded);
|
|
@@ -21735,7 +22082,7 @@ async function applyRecordedVerdicts(canonical, runDirPath) {
|
|
|
21735
22082
|
return canonical;
|
|
21736
22083
|
}
|
|
21737
22084
|
async function persistCanonical(runDirPath, canonical) {
|
|
21738
|
-
const canonicalPath =
|
|
22085
|
+
const canonicalPath = path29.join(runDirPath, "canonical.json");
|
|
21739
22086
|
await atomicWriteFile(
|
|
21740
22087
|
canonicalPath,
|
|
21741
22088
|
`${JSON.stringify(canonical, null, 2)}
|
|
@@ -21744,7 +22091,7 @@ async function persistCanonical(runDirPath, canonical) {
|
|
|
21744
22091
|
return canonicalPath;
|
|
21745
22092
|
}
|
|
21746
22093
|
async function persistReport(runDirPath, canonical) {
|
|
21747
|
-
const reportPath =
|
|
22094
|
+
const reportPath = path29.join(runDirPath, "report.md");
|
|
21748
22095
|
await atomicWriteFile(reportPath, renderCanonicalMarkdown(canonical));
|
|
21749
22096
|
return reportPath;
|
|
21750
22097
|
}
|
|
@@ -21844,17 +22191,17 @@ function placeLabel(p) {
|
|
|
21844
22191
|
function printRevisit(r) {
|
|
21845
22192
|
const missed = r.places.filter((p) => !p.reached);
|
|
21846
22193
|
console.log();
|
|
21847
|
-
const head = ` ${
|
|
22194
|
+
const head = ` ${chalk32.bold("Re-check places:")} reached ${r.reached} of ${r.requested}`;
|
|
21848
22195
|
if (missed.length === 0) {
|
|
21849
|
-
console.log(`${head} ${
|
|
22196
|
+
console.log(`${head} ${chalk32.green("\u2713")}`);
|
|
21850
22197
|
return;
|
|
21851
22198
|
}
|
|
21852
22199
|
console.log(`${head} \u2014 not reached:`);
|
|
21853
22200
|
for (const p of missed) {
|
|
21854
|
-
console.log(` ${
|
|
22201
|
+
console.log(` ${chalk32.yellow("\u25CB")} ${placeLabel(p)}`);
|
|
21855
22202
|
}
|
|
21856
22203
|
console.log(
|
|
21857
|
-
|
|
22204
|
+
chalk32.dim(
|
|
21858
22205
|
" Fixes there stay awaiting a re-run until a walk gets there."
|
|
21859
22206
|
)
|
|
21860
22207
|
);
|
|
@@ -21862,7 +22209,7 @@ function printRevisit(r) {
|
|
|
21862
22209
|
function printVerification(verification) {
|
|
21863
22210
|
console.log();
|
|
21864
22211
|
console.log(
|
|
21865
|
-
|
|
22212
|
+
chalk32.bold(" Since this scenario's last run") + chalk32.dim(` (${verification.baseline_run_id.slice(0, 30)}\u2026)`) + chalk32.bold(":")
|
|
21866
22213
|
);
|
|
21867
22214
|
if (verification.resolved.length > 0) {
|
|
21868
22215
|
console.log(
|
|
@@ -21871,7 +22218,7 @@ function printVerification(verification) {
|
|
|
21871
22218
|
}
|
|
21872
22219
|
if (verification.not_observed.length > 0) {
|
|
21873
22220
|
console.log(
|
|
21874
|
-
` ${symbols.pending} ${verification.not_observed.length} not seen this run ${
|
|
22221
|
+
` ${symbols.pending} ${verification.not_observed.length} not seen this run ${chalk32.dim("(not evidence of a fix)")}`
|
|
21875
22222
|
);
|
|
21876
22223
|
}
|
|
21877
22224
|
if (verification.persists.length > 0) {
|
|
@@ -21900,6 +22247,7 @@ var init_complete = __esm({
|
|
|
21900
22247
|
init_cloud_push();
|
|
21901
22248
|
init_context4();
|
|
21902
22249
|
init_evaluate();
|
|
22250
|
+
init_live_run_client();
|
|
21903
22251
|
init_worktree_state();
|
|
21904
22252
|
init_start_run();
|
|
21905
22253
|
init_view_results();
|
|
@@ -21913,13 +22261,13 @@ __export(match_exports, {
|
|
|
21913
22261
|
matchRecord: () => matchRecord
|
|
21914
22262
|
});
|
|
21915
22263
|
import { promises as fs31 } from "fs";
|
|
21916
|
-
import
|
|
21917
|
-
import
|
|
22264
|
+
import path30 from "path";
|
|
22265
|
+
import chalk33 from "chalk";
|
|
21918
22266
|
async function completedManifest2(runDirPath, runId, opts) {
|
|
21919
22267
|
let manifest;
|
|
21920
22268
|
try {
|
|
21921
22269
|
manifest = JSON.parse(
|
|
21922
|
-
await fs31.readFile(
|
|
22270
|
+
await fs31.readFile(path30.join(runDirPath, "walkthrough.json"), "utf8")
|
|
21923
22271
|
);
|
|
21924
22272
|
} catch {
|
|
21925
22273
|
commandError(`Run not found: ${runId}`, opts);
|
|
@@ -21948,7 +22296,7 @@ async function match(runId, opts) {
|
|
|
21948
22296
|
);
|
|
21949
22297
|
const needed = input.current.length > 0 && (input.prior.length > 0 || (input.guidance ?? []).length > 0);
|
|
21950
22298
|
const prompt = needed ? composeMatchPrompt(input) : null;
|
|
21951
|
-
const promptFilePath = opts?.promptFile ??
|
|
22299
|
+
const promptFilePath = opts?.promptFile ?? path30.join(runDirPath, "match_prompt.md");
|
|
21952
22300
|
if (prompt) {
|
|
21953
22301
|
await fs31.writeFile(promptFilePath, prompt, "utf8");
|
|
21954
22302
|
} else {
|
|
@@ -21963,8 +22311,8 @@ async function match(runId, opts) {
|
|
|
21963
22311
|
{
|
|
21964
22312
|
...input,
|
|
21965
22313
|
needed,
|
|
21966
|
-
prompt_file: prompt ?
|
|
21967
|
-
prompt_file_abs: prompt ?
|
|
22314
|
+
prompt_file: prompt ? path30.relative(ctx.projectRoot, promptFilePath) : null,
|
|
22315
|
+
prompt_file_abs: prompt ? path30.resolve(promptFilePath) : null,
|
|
21968
22316
|
match_prompt: prompt
|
|
21969
22317
|
},
|
|
21970
22318
|
null,
|
|
@@ -21975,7 +22323,7 @@ async function match(runId, opts) {
|
|
|
21975
22323
|
}
|
|
21976
22324
|
if (!prompt) {
|
|
21977
22325
|
console.log(
|
|
21978
|
-
|
|
22326
|
+
chalk33.dim(
|
|
21979
22327
|
" No earlier findings or tester guidance for this scenario to match against \u2014 nothing to do."
|
|
21980
22328
|
)
|
|
21981
22329
|
);
|
|
@@ -21987,6 +22335,8 @@ async function matchRecord(runId, opts) {
|
|
|
21987
22335
|
const resolved = await resolveProjectAndRunDir(runId, opts);
|
|
21988
22336
|
if (!resolved) return;
|
|
21989
22337
|
const { projectRoot, runDirPath } = resolved;
|
|
22338
|
+
sendLivePhase(projectRoot, runId, "matching").catch(() => {
|
|
22339
|
+
});
|
|
21990
22340
|
const manifest = await completedManifest2(runDirPath, runId, opts);
|
|
21991
22341
|
if (!manifest) return;
|
|
21992
22342
|
let answer;
|
|
@@ -22032,17 +22382,17 @@ async function matchRecord(runId, opts) {
|
|
|
22032
22382
|
}
|
|
22033
22383
|
console.log();
|
|
22034
22384
|
console.log(
|
|
22035
|
-
` ${
|
|
22385
|
+
` ${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`
|
|
22036
22386
|
);
|
|
22037
22387
|
if (result.suppressed > 0) {
|
|
22038
22388
|
console.log(
|
|
22039
|
-
` ${
|
|
22389
|
+
` ${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)`
|
|
22040
22390
|
);
|
|
22041
22391
|
}
|
|
22042
22392
|
if (verification) printVerification(verification);
|
|
22043
22393
|
console.log();
|
|
22044
22394
|
console.log(
|
|
22045
|
-
|
|
22395
|
+
chalk33.dim(" Run `iamu sync` to push the linked findings to the cloud.")
|
|
22046
22396
|
);
|
|
22047
22397
|
console.log();
|
|
22048
22398
|
}
|
|
@@ -22053,6 +22403,7 @@ var init_match = __esm({
|
|
|
22053
22403
|
init_dist();
|
|
22054
22404
|
init_complete();
|
|
22055
22405
|
init_context4();
|
|
22406
|
+
init_live_run_client();
|
|
22056
22407
|
}
|
|
22057
22408
|
});
|
|
22058
22409
|
|
|
@@ -22063,7 +22414,7 @@ __export(prune_exports, {
|
|
|
22063
22414
|
prune: () => prune
|
|
22064
22415
|
});
|
|
22065
22416
|
import { confirm, isCancel as isCancel5 } from "@clack/prompts";
|
|
22066
|
-
import
|
|
22417
|
+
import chalk34 from "chalk";
|
|
22067
22418
|
function formatBytes(bytes) {
|
|
22068
22419
|
if (bytes <= 0) return "0 B";
|
|
22069
22420
|
if (bytes < 1024) return `${bytes} B`;
|
|
@@ -22109,7 +22460,7 @@ async function prune(opts = {}) {
|
|
|
22109
22460
|
});
|
|
22110
22461
|
if (preview.prunedRuns.length === 0) {
|
|
22111
22462
|
console.log(
|
|
22112
|
-
|
|
22463
|
+
chalk34.dim(" No runs match the pruning criteria. Nothing to prune.")
|
|
22113
22464
|
);
|
|
22114
22465
|
return preview;
|
|
22115
22466
|
}
|
|
@@ -22118,7 +22469,7 @@ async function prune(opts = {}) {
|
|
|
22118
22469
|
message: `Prune ${mode} ${preview.prunedRuns.length} run(s) and reclaim ${formatBytes(preview.totalBytesReclaimed)}?`
|
|
22119
22470
|
});
|
|
22120
22471
|
if (isCancel5(confirmed) || !confirmed) {
|
|
22121
|
-
console.log(
|
|
22472
|
+
console.log(chalk34.yellow(" Pruning cancelled."));
|
|
22122
22473
|
return;
|
|
22123
22474
|
}
|
|
22124
22475
|
}
|
|
@@ -22129,14 +22480,14 @@ async function prune(opts = {}) {
|
|
|
22129
22480
|
}
|
|
22130
22481
|
if (result.dryRun) {
|
|
22131
22482
|
console.log(
|
|
22132
|
-
|
|
22483
|
+
chalk34.cyan(
|
|
22133
22484
|
`
|
|
22134
22485
|
[DRY RUN] Would prune ${result.prunedRuns.length} of ${result.totalRunsScanned} run(s):`
|
|
22135
22486
|
)
|
|
22136
22487
|
);
|
|
22137
22488
|
} else {
|
|
22138
22489
|
console.log(
|
|
22139
|
-
|
|
22490
|
+
chalk34.bold(
|
|
22140
22491
|
`
|
|
22141
22492
|
${symbols.success} Pruned ${result.prunedRuns.length} of ${result.totalRunsScanned} run(s):`
|
|
22142
22493
|
)
|
|
@@ -22144,18 +22495,18 @@ async function prune(opts = {}) {
|
|
|
22144
22495
|
}
|
|
22145
22496
|
if (result.prunedRuns.length === 0) {
|
|
22146
22497
|
console.log(
|
|
22147
|
-
|
|
22498
|
+
chalk34.dim(" No runs matched the pruning criteria. Nothing pruned.")
|
|
22148
22499
|
);
|
|
22149
22500
|
} else {
|
|
22150
22501
|
for (const run of result.prunedRuns) {
|
|
22151
22502
|
const mode = run.fullyDeleted ? "removed" : "screenshots purged";
|
|
22152
22503
|
const count = run.screenshotsDeleted > 0 ? `${run.screenshotsDeleted} screenshots, ` : "";
|
|
22153
22504
|
console.log(
|
|
22154
|
-
` ${
|
|
22505
|
+
` ${chalk34.dim("\u2022")} ${chalk34.bold(run.runId)} ${chalk34.dim(`(${run.scenarioSlug ?? "unknown scenario"})`)}: ${chalk34.yellow(formatBytes(run.bytesReclaimed))} (${count}${mode})`
|
|
22155
22506
|
);
|
|
22156
22507
|
}
|
|
22157
22508
|
console.log(
|
|
22158
|
-
|
|
22509
|
+
chalk34.dim(
|
|
22159
22510
|
`
|
|
22160
22511
|
Total reclaimed: ${formatBytes(result.totalBytesReclaimed)} (${result.totalScreenshotsDeleted} screenshots deleted)
|
|
22161
22512
|
`
|
|
@@ -22178,7 +22529,7 @@ init_context4();
|
|
|
22178
22529
|
import { existsSync as existsSync13, readFileSync as readFileSync9 } from "fs";
|
|
22179
22530
|
import { dirname as dirname5, resolve as resolve3 } from "path";
|
|
22180
22531
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
22181
|
-
import
|
|
22532
|
+
import chalk37 from "chalk";
|
|
22182
22533
|
import { Command } from "commander";
|
|
22183
22534
|
|
|
22184
22535
|
// src/commands/register-cloud.ts
|
|
@@ -22352,9 +22703,9 @@ function registerProjectCommands(program2) {
|
|
|
22352
22703
|
"after",
|
|
22353
22704
|
"\nExamples:\n $ iamu validate --all\n $ iamu validate --all --fix --dry-run\n $ iamu validate iamu/personas/maria.md"
|
|
22354
22705
|
).action(
|
|
22355
|
-
async (
|
|
22706
|
+
async (path31, opts) => {
|
|
22356
22707
|
const { validate: validate2 } = await Promise.resolve().then(() => (init_validate(), validate_exports));
|
|
22357
|
-
await validate2(
|
|
22708
|
+
await validate2(path31, opts);
|
|
22358
22709
|
}
|
|
22359
22710
|
);
|
|
22360
22711
|
program2.command("update").helpGroup("Project:").description("Update and repair agent skills and prompts to latest version").option(
|
|
@@ -22655,23 +23006,23 @@ function registerAllCommands(program2) {
|
|
|
22655
23006
|
|
|
22656
23007
|
// src/ui/panic.ts
|
|
22657
23008
|
init_logger();
|
|
22658
|
-
import
|
|
23009
|
+
import chalk35 from "chalk";
|
|
22659
23010
|
var handlersRegistered = false;
|
|
22660
23011
|
var customSigintHandler = null;
|
|
22661
23012
|
function logFatalAndExit(title, errOrReason) {
|
|
22662
23013
|
process.stderr.write("\x1B[?25h");
|
|
22663
23014
|
if (isVerbose()) {
|
|
22664
|
-
console.error(
|
|
23015
|
+
console.error(chalk35.red(`
|
|
22665
23016
|
${title}:`));
|
|
22666
23017
|
console.error(
|
|
22667
23018
|
errOrReason instanceof Error ? errOrReason.stack || errOrReason : errOrReason
|
|
22668
23019
|
);
|
|
22669
23020
|
} else {
|
|
22670
23021
|
const msg = errOrReason instanceof Error ? errOrReason.message : String(errOrReason);
|
|
22671
|
-
console.error(
|
|
23022
|
+
console.error(chalk35.red(`
|
|
22672
23023
|
Fatal Error: ${msg}`));
|
|
22673
23024
|
console.error(
|
|
22674
|
-
|
|
23025
|
+
chalk35.dim(
|
|
22675
23026
|
" Run with --verbose or DEBUG=1 to view the full stack trace.\n"
|
|
22676
23027
|
)
|
|
22677
23028
|
);
|
|
@@ -22690,7 +23041,7 @@ function setupProcessHandlers() {
|
|
|
22690
23041
|
}
|
|
22691
23042
|
process.exit(130);
|
|
22692
23043
|
} else {
|
|
22693
|
-
console.error(
|
|
23044
|
+
console.error(chalk35.dim("\n Operation cancelled."));
|
|
22694
23045
|
process.exit(130);
|
|
22695
23046
|
}
|
|
22696
23047
|
});
|
|
@@ -22713,10 +23064,10 @@ function setupProcessHandlers() {
|
|
|
22713
23064
|
}
|
|
22714
23065
|
|
|
22715
23066
|
// src/ui/update-check.ts
|
|
22716
|
-
import { mkdir as mkdir7, readFile as
|
|
23067
|
+
import { mkdir as mkdir7, readFile as readFile8, writeFile as writeFile5 } from "fs/promises";
|
|
22717
23068
|
import { homedir as homedir4 } from "os";
|
|
22718
23069
|
import { join as join10 } from "path";
|
|
22719
|
-
import
|
|
23070
|
+
import chalk36 from "chalk";
|
|
22720
23071
|
var CACHE_FILE = join10(homedir4(), ".iamu", "update-check.json");
|
|
22721
23072
|
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
22722
23073
|
function isSemverGreater(latest, current) {
|
|
@@ -22733,7 +23084,7 @@ async function checkForUpdate(currentVersion) {
|
|
|
22733
23084
|
}
|
|
22734
23085
|
let cache = null;
|
|
22735
23086
|
try {
|
|
22736
|
-
const raw = await
|
|
23087
|
+
const raw = await readFile8(CACHE_FILE, "utf8");
|
|
22737
23088
|
cache = JSON.parse(raw);
|
|
22738
23089
|
} catch {
|
|
22739
23090
|
}
|
|
@@ -22769,7 +23120,7 @@ async function checkForUpdate(currentVersion) {
|
|
|
22769
23120
|
function printUpdateNotice(currentVersion, latestVersion) {
|
|
22770
23121
|
console.error();
|
|
22771
23122
|
console.error(
|
|
22772
|
-
` ${
|
|
23123
|
+
` ${chalk36.yellow("Update available:")} ${chalk36.dim(currentVersion)} \u2192 ${chalk36.green(latestVersion)} ${chalk36.dim("(run: npm i -g @iamu-dev/iamu)")}`
|
|
22773
23124
|
);
|
|
22774
23125
|
}
|
|
22775
23126
|
|
|
@@ -22814,7 +23165,7 @@ var program = new Command().name("iamu").description(
|
|
|
22814
23165
|
}
|
|
22815
23166
|
}
|
|
22816
23167
|
if (root.color === false || process.env.NO_COLOR) {
|
|
22817
|
-
|
|
23168
|
+
chalk37.level = 0;
|
|
22818
23169
|
}
|
|
22819
23170
|
if (root.verbose) {
|
|
22820
23171
|
process.env.IAMU_VERBOSE = "1";
|