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