@iamu-dev/iamu 0.2.0-beta.4 → 0.2.0-beta.6
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 +238 -23
- package/dist/commands/start-run.d.ts +52 -0
- package/dist/index.js +238 -23
- package/dist/templates/skills/iamu-findings.md +27 -29
- package/dist/templates/skills/iamu-new.md +42 -43
- package/dist/templates/skills/iamu-propose.md +34 -18
- package/dist/templates/skills/iamu-run.md +99 -43
- package/dist/templates/skills/iamu-status.md +21 -14
- package/package.json +2 -2
package/dist/bin.js
CHANGED
|
@@ -200,17 +200,24 @@ function defaultConfig(params) {
|
|
|
200
200
|
cloud_api_url: null
|
|
201
201
|
};
|
|
202
202
|
}
|
|
203
|
-
var baseProjectFields, localOnlyConfig, cloudLinkedConfig, projectConfigSchema;
|
|
203
|
+
var modelTierSchema, projectModelsConfigSchema, baseProjectFields, localOnlyConfig, cloudLinkedConfig, projectConfigSchema;
|
|
204
204
|
var init_config = __esm({
|
|
205
205
|
"../../packages/protocol/dist/schemas/frontmatter/config.js"() {
|
|
206
206
|
"use strict";
|
|
207
207
|
init_common();
|
|
208
208
|
init_version();
|
|
209
|
+
modelTierSchema = z4.string().min(1).max(128).describe("Model role tier ('fast', 'thorough', 'inherit') or a specific model identifier.");
|
|
210
|
+
projectModelsConfigSchema = z4.object({
|
|
211
|
+
walker: modelTierSchema.optional(),
|
|
212
|
+
matcher: modelTierSchema.optional(),
|
|
213
|
+
judge: modelTierSchema.optional()
|
|
214
|
+
}).strict();
|
|
209
215
|
baseProjectFields = {
|
|
210
216
|
schema_version: z4.literal(SCHEMA_VERSION),
|
|
211
217
|
id: uuidSchema,
|
|
212
218
|
project_slug: slugSchema,
|
|
213
|
-
project_name: z4.string().min(1)
|
|
219
|
+
project_name: z4.string().min(1),
|
|
220
|
+
models: projectModelsConfigSchema.optional()
|
|
214
221
|
};
|
|
215
222
|
localOnlyConfig = z4.object({
|
|
216
223
|
...baseProjectFields,
|
|
@@ -1154,7 +1161,21 @@ var init_walkthrough_bundle = __esm({
|
|
|
1154
1161
|
judge_prompt: z19.string().optional(),
|
|
1155
1162
|
judge_model: z19.string().optional()
|
|
1156
1163
|
}).optional()
|
|
1157
|
-
}).optional()
|
|
1164
|
+
}).optional(),
|
|
1165
|
+
models: z19.object({
|
|
1166
|
+
walker: z19.string().optional(),
|
|
1167
|
+
matcher: z19.string().optional(),
|
|
1168
|
+
judge: z19.string().optional(),
|
|
1169
|
+
walker_reported: z19.string().optional(),
|
|
1170
|
+
matcher_reported: z19.string().optional(),
|
|
1171
|
+
judge_reported: z19.string().optional(),
|
|
1172
|
+
walker_tier: z19.string().optional(),
|
|
1173
|
+
matcher_tier: z19.string().optional(),
|
|
1174
|
+
judge_tier: z19.string().optional(),
|
|
1175
|
+
execution_mode: z19.enum(["multi_agent", "single_agent"]).optional(),
|
|
1176
|
+
velocity_sec_per_step: z19.number().optional(),
|
|
1177
|
+
total_duration_sec: z19.number().optional()
|
|
1178
|
+
}).optional().describe("AI model configuration and reported runtime provenance for this walkthrough.")
|
|
1158
1179
|
});
|
|
1159
1180
|
walkthroughBundleSchema = z19.object({
|
|
1160
1181
|
manifest: bundleManifestSchema,
|
|
@@ -1377,6 +1398,7 @@ var init_walkthrough_canonical = __esm({
|
|
|
1377
1398
|
build: buildMetadataSchema.optional(),
|
|
1378
1399
|
viewport: runViewportSchema.optional(),
|
|
1379
1400
|
environment: z20.string().optional(),
|
|
1401
|
+
models: z20.record(z20.unknown()).optional(),
|
|
1380
1402
|
findings: z20.array(canonicalFindingSchema),
|
|
1381
1403
|
steps: z20.array(canonicalStepSchema),
|
|
1382
1404
|
human_tests: z20.array(canonicalHumanTestSchema),
|
|
@@ -7248,6 +7270,7 @@ async function buildCanonical(projectRoot, manifest, completedAt, inputs) {
|
|
|
7248
7270
|
...manifest.build ? { build: manifest.build } : {},
|
|
7249
7271
|
...manifest.viewport ? { viewport: manifest.viewport } : {},
|
|
7250
7272
|
...manifest.environment ? { environment: manifest.environment } : {},
|
|
7273
|
+
...manifest.models ? { models: manifest.models } : {},
|
|
7251
7274
|
findings: canonicalFindings,
|
|
7252
7275
|
steps: canonicalSteps,
|
|
7253
7276
|
human_tests: humanTests,
|
|
@@ -7408,6 +7431,20 @@ function renderCanonicalMarkdown(canonical) {
|
|
|
7408
7431
|
lines.push(`- Viewport: ${canonical.viewport.device} (${canonical.viewport.width}\xD7${canonical.viewport.height})`);
|
|
7409
7432
|
}
|
|
7410
7433
|
lines.push(`- Started: ${canonical.provenance.started_at}`, `- Completed: ${canonical.provenance.completed_at}`, `- Walker prompt: ${canonical.provenance.walker_prompt.id}@${canonical.provenance.walker_prompt.version}`, `- Findings: ${canonical.findings.length}`, `- Steps: ${canonical.steps.length}`);
|
|
7434
|
+
const models = canonical.models;
|
|
7435
|
+
if (models) {
|
|
7436
|
+
const parts = [
|
|
7437
|
+
models.walker ? `Walker: ${models.walker}${models.walker_reported ? ` (${models.walker_reported})` : ""}` : "",
|
|
7438
|
+
models.judge ? `Judge: ${models.judge}${models.judge_reported ? ` (${models.judge_reported})` : ""}` : "",
|
|
7439
|
+
models.matcher ? `Matcher: ${models.matcher}` : ""
|
|
7440
|
+
].filter(Boolean);
|
|
7441
|
+
if (parts.length > 0) {
|
|
7442
|
+
lines.push(`- Models: ${parts.join(" \xB7 ")}`);
|
|
7443
|
+
}
|
|
7444
|
+
if (typeof models.velocity_sec_per_step === "number") {
|
|
7445
|
+
lines.push(`- Velocity: ~${models.velocity_sec_per_step}s/step (${models.total_duration_sec}s total)`);
|
|
7446
|
+
}
|
|
7447
|
+
}
|
|
7411
7448
|
const what = canonical.what_worked;
|
|
7412
7449
|
if (what && what.length > 0) {
|
|
7413
7450
|
lines.push("", "## What worked");
|
|
@@ -7777,6 +7814,7 @@ async function assembleWalkthroughBundle(projectRoot, runId) {
|
|
|
7777
7814
|
report_markdown: report3,
|
|
7778
7815
|
verdict: verdictArray,
|
|
7779
7816
|
judge_meta: judgeMeta,
|
|
7817
|
+
...manifest.models ? { models: manifest.models } : {},
|
|
7780
7818
|
...buildFields(manifest),
|
|
7781
7819
|
...await readCanonicalExtras(projectRoot, runId)
|
|
7782
7820
|
},
|
|
@@ -14434,6 +14472,18 @@ async function startRun(scenarioSlug, opts) {
|
|
|
14434
14472
|
}
|
|
14435
14473
|
const build = detectBuild({ cwd: projectRoot, label: opts.build });
|
|
14436
14474
|
const environment = resolveEnvironment(opts.env, start2.url);
|
|
14475
|
+
const cfg = await readConfig(projectRoot).catch(() => null);
|
|
14476
|
+
const walker = opts.walker ?? process.env.IAMU_WALKER_MODEL ?? cfg?.models?.walker ?? "fast";
|
|
14477
|
+
const judge = opts.judge ?? process.env.IAMU_JUDGE_MODEL ?? cfg?.models?.judge ?? "thorough";
|
|
14478
|
+
const matcher = opts.matcher ?? process.env.IAMU_MATCHER_MODEL ?? cfg?.models?.matcher ?? "thorough";
|
|
14479
|
+
const models = {
|
|
14480
|
+
walker,
|
|
14481
|
+
judge,
|
|
14482
|
+
matcher,
|
|
14483
|
+
walker_tier: ["fast", "thorough", "inherit"].includes(walker) ? walker : "custom",
|
|
14484
|
+
judge_tier: ["fast", "thorough", "inherit"].includes(judge) ? judge : "custom",
|
|
14485
|
+
matcher_tier: ["fast", "thorough", "inherit"].includes(matcher) ? matcher : "custom"
|
|
14486
|
+
};
|
|
14437
14487
|
let revisit = [];
|
|
14438
14488
|
try {
|
|
14439
14489
|
revisit = await computeRevisitPlaces(projectRoot, scenarioSlug, start2.url);
|
|
@@ -14451,6 +14501,7 @@ async function startRun(scenarioSlug, opts) {
|
|
|
14451
14501
|
status: "running",
|
|
14452
14502
|
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14453
14503
|
completed_at: null,
|
|
14504
|
+
models,
|
|
14454
14505
|
...build ? { build } : {},
|
|
14455
14506
|
...environment ? { environment } : {},
|
|
14456
14507
|
...revisit.length > 0 ? { revisit } : {},
|
|
@@ -14472,6 +14523,7 @@ async function startRun(scenarioSlug, opts) {
|
|
|
14472
14523
|
...targetWarning ? { target_warning: targetWarning } : {},
|
|
14473
14524
|
persona_slug: fm.persona,
|
|
14474
14525
|
outline_slug: fm.outline,
|
|
14526
|
+
models,
|
|
14475
14527
|
build: build ?? null,
|
|
14476
14528
|
environment: environment ?? null,
|
|
14477
14529
|
revisit,
|
|
@@ -14490,6 +14542,9 @@ async function startRun(scenarioSlug, opts) {
|
|
|
14490
14542
|
console.log(` ${chalk11.dim("persona:")} ${fm.persona}`);
|
|
14491
14543
|
console.log(` ${chalk11.dim("outline:")} ${fm.outline}`);
|
|
14492
14544
|
console.log(` ${chalk11.dim("target:")} ${start2.url}`);
|
|
14545
|
+
console.log(
|
|
14546
|
+
` ${chalk11.dim("models:")} walker: ${chalk11.cyan(walker)} \xB7 judge: ${chalk11.cyan(judge)} \xB7 matcher: ${chalk11.cyan(matcher)}`
|
|
14547
|
+
);
|
|
14493
14548
|
if (targetWarning) {
|
|
14494
14549
|
console.log(` ${symbols.warning} ${chalk11.yellow(targetWarning)}`);
|
|
14495
14550
|
}
|
|
@@ -16673,6 +16728,7 @@ __export(browse_exports, {
|
|
|
16673
16728
|
readBrowseState: () => readBrowseState,
|
|
16674
16729
|
shouldDisableSandbox: () => shouldDisableSandbox,
|
|
16675
16730
|
start: () => start,
|
|
16731
|
+
waitForVisualStability: () => waitForVisualStability,
|
|
16676
16732
|
withPage: () => withPage
|
|
16677
16733
|
});
|
|
16678
16734
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
@@ -16879,6 +16935,45 @@ async function stop(opts, driver) {
|
|
|
16879
16935
|
}
|
|
16880
16936
|
report2(opts, { stopped: true }, [` ${chalk20.green("\u2713")} Browser stopped`]);
|
|
16881
16937
|
}
|
|
16938
|
+
async function waitForVisualStability(page, maxWaitMs = 300) {
|
|
16939
|
+
let timer;
|
|
16940
|
+
try {
|
|
16941
|
+
const nodeTimeout = new Promise((resolve4) => {
|
|
16942
|
+
timer = setTimeout(resolve4, maxWaitMs + 100);
|
|
16943
|
+
});
|
|
16944
|
+
const browserWait = page.evaluate((maxWait) => {
|
|
16945
|
+
return new Promise((resolve4) => {
|
|
16946
|
+
const timeout = setTimeout(resolve4, maxWait);
|
|
16947
|
+
const done = () => {
|
|
16948
|
+
clearTimeout(timeout);
|
|
16949
|
+
resolve4();
|
|
16950
|
+
};
|
|
16951
|
+
const g = globalThis;
|
|
16952
|
+
if (typeof g.requestAnimationFrame !== "function") {
|
|
16953
|
+
done();
|
|
16954
|
+
return;
|
|
16955
|
+
}
|
|
16956
|
+
g.requestAnimationFrame(() => {
|
|
16957
|
+
g.requestAnimationFrame?.(() => {
|
|
16958
|
+
const animations = g.document?.getAnimations ? g.document.getAnimations().filter((a) => a.playState === "running" && a.finished) : [];
|
|
16959
|
+
if (animations.length === 0) {
|
|
16960
|
+
done();
|
|
16961
|
+
return;
|
|
16962
|
+
}
|
|
16963
|
+
Promise.allSettled(
|
|
16964
|
+
animations.map((a) => a.finished)
|
|
16965
|
+
).finally(done);
|
|
16966
|
+
});
|
|
16967
|
+
});
|
|
16968
|
+
});
|
|
16969
|
+
}, maxWaitMs).catch(() => {
|
|
16970
|
+
});
|
|
16971
|
+
await Promise.race([browserWait, nodeTimeout]);
|
|
16972
|
+
} catch {
|
|
16973
|
+
} finally {
|
|
16974
|
+
if (timer) clearTimeout(timer);
|
|
16975
|
+
}
|
|
16976
|
+
}
|
|
16882
16977
|
async function withPage(opts, driver, fn, target) {
|
|
16883
16978
|
const state = readBrowseState();
|
|
16884
16979
|
if (!state) {
|
|
@@ -16898,9 +16993,9 @@ async function withPage(opts, driver, fn, target) {
|
|
|
16898
16993
|
await fn(page);
|
|
16899
16994
|
await page.waitForLoadState("domcontentloaded").catch(() => {
|
|
16900
16995
|
});
|
|
16901
|
-
await page.waitForTimeout(400);
|
|
16902
16996
|
let screenshot = null;
|
|
16903
16997
|
if (opts.shot) {
|
|
16998
|
+
await waitForVisualStability(page);
|
|
16904
16999
|
screenshot = path22.resolve(opts.shot);
|
|
16905
17000
|
mkdirSync(path22.dirname(screenshot), { recursive: true });
|
|
16906
17001
|
await page.screenshot({ path: screenshot, fullPage: Boolean(opts.full) });
|
|
@@ -17001,6 +17096,35 @@ function printStep(opts, record, projectRoot) {
|
|
|
17001
17096
|
}
|
|
17002
17097
|
}
|
|
17003
17098
|
async function browseStep(args, opts, driver) {
|
|
17099
|
+
if (opts.stepFile) {
|
|
17100
|
+
try {
|
|
17101
|
+
let raw;
|
|
17102
|
+
if (opts.stepFile === "-") {
|
|
17103
|
+
raw = readFileSync6(0, "utf8");
|
|
17104
|
+
} else {
|
|
17105
|
+
raw = readFileSync6(opts.stepFile, "utf8");
|
|
17106
|
+
}
|
|
17107
|
+
const data = JSON.parse(raw);
|
|
17108
|
+
if (data.run && typeof data.run === "string") opts.run = data.run;
|
|
17109
|
+
if (data.action && typeof data.action === "string")
|
|
17110
|
+
opts.action = data.action;
|
|
17111
|
+
if (data.note && typeof data.note === "string") opts.note = data.note;
|
|
17112
|
+
if (data.surface && typeof data.surface === "string")
|
|
17113
|
+
opts.surface = data.surface;
|
|
17114
|
+
if (args.length === 0 && data.cmd) {
|
|
17115
|
+
if (Array.isArray(data.cmd)) {
|
|
17116
|
+
args = data.cmd.map(String);
|
|
17117
|
+
} else if (typeof data.cmd === "string") {
|
|
17118
|
+
args = data.cmd.trim().split(/\s+/);
|
|
17119
|
+
}
|
|
17120
|
+
}
|
|
17121
|
+
} catch (err) {
|
|
17122
|
+
return fail(
|
|
17123
|
+
`Failed to read step payload from ${opts.stepFile}: ${err.message}`,
|
|
17124
|
+
opts
|
|
17125
|
+
);
|
|
17126
|
+
}
|
|
17127
|
+
}
|
|
17004
17128
|
if (!opts.run)
|
|
17005
17129
|
return fail("--run <run-id> is required for browse step.", opts);
|
|
17006
17130
|
if (!opts.action) {
|
|
@@ -18858,7 +18982,7 @@ function composeWalkerPrompt(p) {
|
|
|
18858
18982
|
`Screenshots to: ${rd}/screenshots/step-N.png \u2014 absolute paths.`,
|
|
18859
18983
|
`Record findings with: ${iamu} new-finding --scenario ${p.scenarioSlug} --run ${p.runId} --step <N> --title "..." --type <helps|hinders|missing|irrelevant|incorrect> --severity <critical|major|minor|observation> --ui-fact "..." --consequence "..." --task-impact <blocks|impairs|slows|neutral|accelerates|enables> --confidence <high|medium|low> --json \u2014 then add the body (description + "## Recommendation") below the frontmatter of the file it returns.`,
|
|
18860
18984
|
"`--step <N>` is the step whose screenshot shows the problem (or strength): it is the evidence people see next to the finding, so record that step and its screenshot first, and pick the screenshot where the thing is actually visible.",
|
|
18861
|
-
`Before you finish, write ${rd}/summary.json: {"what_worked": [...], "open_questions": [...]} \u2014 one sentence each, in the persona's language.`,
|
|
18985
|
+
`Before you finish, write ${rd}/summary.json: {"what_worked": [...], "open_questions": [...], "model": "<your model identifier if known, e.g. claude-3-5-haiku, gemini-3.8-flash, or unspecified>"} \u2014 one sentence each, in the persona's language.`,
|
|
18862
18986
|
"",
|
|
18863
18987
|
"Do not read the product's source code, other iamu/ entity files, or earlier runs: you know only what the persona knows.",
|
|
18864
18988
|
"",
|
|
@@ -19457,8 +19581,21 @@ async function evaluate(runId, opts) {
|
|
|
19457
19581
|
)
|
|
19458
19582
|
};
|
|
19459
19583
|
const prompt = composeJudgePrompt(input);
|
|
19584
|
+
const promptFilePath = opts?.promptFile ?? path25.join(runDirPath, "judge_prompt.md");
|
|
19585
|
+
await fs25.writeFile(promptFilePath, prompt, "utf8");
|
|
19460
19586
|
if (opts?.json) {
|
|
19461
|
-
console.log(
|
|
19587
|
+
console.log(
|
|
19588
|
+
JSON.stringify(
|
|
19589
|
+
{
|
|
19590
|
+
...input,
|
|
19591
|
+
prompt_file: path25.relative(projectRoot, promptFilePath),
|
|
19592
|
+
prompt_file_abs: path25.resolve(promptFilePath),
|
|
19593
|
+
judge_prompt: prompt
|
|
19594
|
+
},
|
|
19595
|
+
null,
|
|
19596
|
+
2
|
|
19597
|
+
)
|
|
19598
|
+
);
|
|
19462
19599
|
return;
|
|
19463
19600
|
}
|
|
19464
19601
|
console.log(prompt);
|
|
@@ -19550,7 +19687,7 @@ ${formatIssues(fileResult.error)}`,
|
|
|
19550
19687
|
runId,
|
|
19551
19688
|
validatedVerdicts
|
|
19552
19689
|
);
|
|
19553
|
-
const cloudInfo = await pushRunToCloud(projectRoot, runId);
|
|
19690
|
+
const cloudInfo = opts?.push === false ? void 0 : await pushRunToCloud(projectRoot, runId);
|
|
19554
19691
|
if (opts?.json) {
|
|
19555
19692
|
console.log(
|
|
19556
19693
|
JSON.stringify(
|
|
@@ -19667,6 +19804,36 @@ async function complete(runId, opts) {
|
|
|
19667
19804
|
return;
|
|
19668
19805
|
}
|
|
19669
19806
|
const completedAt = pickCompletedAt(run.manifest);
|
|
19807
|
+
const walkerSummary = await readWalkerSummary(run.runDirPath);
|
|
19808
|
+
let judgeReported;
|
|
19809
|
+
try {
|
|
19810
|
+
const verdictsRaw = await fs26.readFile(
|
|
19811
|
+
path26.join(run.runDirPath, "verdicts.json"),
|
|
19812
|
+
"utf8"
|
|
19813
|
+
);
|
|
19814
|
+
const parsed = JSON.parse(verdictsRaw);
|
|
19815
|
+
if (parsed.provenance?.model) {
|
|
19816
|
+
judgeReported = parsed.provenance.model;
|
|
19817
|
+
}
|
|
19818
|
+
} catch {
|
|
19819
|
+
}
|
|
19820
|
+
const stepCount = provenanceAudit.step_count;
|
|
19821
|
+
const durationSec = provenanceAudit.duration_seconds ?? (run.manifest.created_at && Date.parse(completedAt) > Date.parse(run.manifest.created_at) ? Math.round(
|
|
19822
|
+
(Date.parse(completedAt) - Date.parse(run.manifest.created_at)) / 1e3 * 10
|
|
19823
|
+
) / 10 : null);
|
|
19824
|
+
const velocitySec = provenanceAudit.avg_step_interval_seconds ?? (durationSec != null && stepCount > 1 ? Math.round(durationSec / (stepCount - 1) * 10) / 10 : null);
|
|
19825
|
+
const existingModels = run.manifest.models ?? {};
|
|
19826
|
+
const updatedModels = {
|
|
19827
|
+
...existingModels,
|
|
19828
|
+
...walkerSummary.model ? { walker_reported: walkerSummary.model } : {},
|
|
19829
|
+
...judgeReported ? { judge_reported: judgeReported } : {},
|
|
19830
|
+
...durationSec != null ? { total_duration_sec: durationSec } : {},
|
|
19831
|
+
...velocitySec != null ? { velocity_sec_per_step: velocitySec } : {}
|
|
19832
|
+
};
|
|
19833
|
+
run.manifest = {
|
|
19834
|
+
...run.manifest,
|
|
19835
|
+
models: updatedModels
|
|
19836
|
+
};
|
|
19670
19837
|
const assembled = await assembleRun(
|
|
19671
19838
|
run.projectRoot,
|
|
19672
19839
|
runId,
|
|
@@ -19794,7 +19961,7 @@ async function collectCompletionExtras(run, opts) {
|
|
|
19794
19961
|
parseRunViewport(manifest.viewport)
|
|
19795
19962
|
);
|
|
19796
19963
|
const codeWarning = opts?.force ? null : codeChangedWarning(manifest.build, detectWorktreeState(projectRoot));
|
|
19797
|
-
const cloudInfo = await pushRunToCloud(projectRoot, runId);
|
|
19964
|
+
const cloudInfo = opts?.push === false ? void 0 : await pushRunToCloud(projectRoot, runId);
|
|
19798
19965
|
return { revisit, viewportWarning, codeWarning, cloudInfo };
|
|
19799
19966
|
}
|
|
19800
19967
|
function completeJsonPayload(canonical, extras) {
|
|
@@ -19827,6 +19994,17 @@ function printCompletionSummary(run, completedAt, assembled, extras, provenanceA
|
|
|
19827
19994
|
console.log(` steps ${count(canonical.steps.length)}`);
|
|
19828
19995
|
console.log(` started ${chalk30.dim(manifest.created_at)}`);
|
|
19829
19996
|
console.log(` completed ${chalk30.dim(completedAt)}`);
|
|
19997
|
+
const models = manifest.models;
|
|
19998
|
+
if (models?.velocity_sec_per_step != null) {
|
|
19999
|
+
console.log(
|
|
20000
|
+
` velocity ${chalk30.cyan(`~${models.velocity_sec_per_step}s/step`)} ${chalk30.dim(`(${models.total_duration_sec}s total)`)}`
|
|
20001
|
+
);
|
|
20002
|
+
}
|
|
20003
|
+
if (models && (models.walker || models.judge || models.matcher)) {
|
|
20004
|
+
const w = models.walker_reported ? `${models.walker} (${models.walker_reported})` : models.walker ?? "fast";
|
|
20005
|
+
const j = models.judge_reported ? `${models.judge} (${models.judge_reported})` : models.judge ?? "thorough";
|
|
20006
|
+
console.log(` models ${chalk30.dim(`walker: ${w} \xB7 judge: ${j}`)}`);
|
|
20007
|
+
}
|
|
19830
20008
|
console.log();
|
|
19831
20009
|
console.log(
|
|
19832
20010
|
` ${chalk30.dim("canonical:")} ${chalk30.dim(path26.relative(projectRoot, assembled.canonicalPath))}`
|
|
@@ -19920,9 +20098,11 @@ async function readWalkerSummary(runDirPath) {
|
|
|
19920
20098
|
await fs26.readFile(path26.join(runDirPath, "summary.json"), "utf8")
|
|
19921
20099
|
);
|
|
19922
20100
|
const strings = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string" && x.trim() !== "") : void 0;
|
|
20101
|
+
const model = typeof data.model === "string" && data.model.trim() !== "" ? data.model.trim() : void 0;
|
|
19923
20102
|
return {
|
|
19924
20103
|
what_worked: strings(data.what_worked),
|
|
19925
|
-
open_questions: strings(data.open_questions)
|
|
20104
|
+
open_questions: strings(data.open_questions),
|
|
20105
|
+
model
|
|
19926
20106
|
};
|
|
19927
20107
|
} catch {
|
|
19928
20108
|
return {};
|
|
@@ -20247,9 +20427,28 @@ async function match(runId, opts) {
|
|
|
20247
20427
|
);
|
|
20248
20428
|
const needed = input.current.length > 0 && (input.prior.length > 0 || (input.guidance ?? []).length > 0);
|
|
20249
20429
|
const prompt = needed ? composeMatchPrompt(input) : null;
|
|
20430
|
+
const promptFilePath = opts?.promptFile ?? path27.join(runDirPath, "match_prompt.md");
|
|
20431
|
+
if (prompt) {
|
|
20432
|
+
await fs27.writeFile(promptFilePath, prompt, "utf8");
|
|
20433
|
+
} else {
|
|
20434
|
+
try {
|
|
20435
|
+
await fs27.unlink(promptFilePath);
|
|
20436
|
+
} catch {
|
|
20437
|
+
}
|
|
20438
|
+
}
|
|
20250
20439
|
if (opts?.json) {
|
|
20251
20440
|
console.log(
|
|
20252
|
-
JSON.stringify(
|
|
20441
|
+
JSON.stringify(
|
|
20442
|
+
{
|
|
20443
|
+
...input,
|
|
20444
|
+
needed,
|
|
20445
|
+
prompt_file: prompt ? path27.relative(ctx.projectRoot, promptFilePath) : null,
|
|
20446
|
+
prompt_file_abs: prompt ? path27.resolve(promptFilePath) : null,
|
|
20447
|
+
match_prompt: prompt
|
|
20448
|
+
},
|
|
20449
|
+
null,
|
|
20450
|
+
2
|
|
20451
|
+
)
|
|
20253
20452
|
);
|
|
20254
20453
|
return;
|
|
20255
20454
|
}
|
|
@@ -20693,6 +20892,15 @@ function registerWalkthroughCommands(program2) {
|
|
|
20693
20892
|
).option(
|
|
20694
20893
|
"--env <name>",
|
|
20695
20894
|
"Environment the product runs in (default: the target URL's origin)"
|
|
20895
|
+
).option(
|
|
20896
|
+
"--walker <tierOrModel>",
|
|
20897
|
+
"Model tier ('fast', 'thorough', 'inherit') or model ID for driving browser navigation (default: fast)"
|
|
20898
|
+
).option(
|
|
20899
|
+
"--judge <tierOrModel>",
|
|
20900
|
+
"Model tier ('fast', 'thorough', 'inherit') or model ID for human test evaluation (default: thorough)"
|
|
20901
|
+
).option(
|
|
20902
|
+
"--matcher <tierOrModel>",
|
|
20903
|
+
"Model tier ('fast', 'thorough', 'inherit') or model ID for finding matching (default: thorough)"
|
|
20696
20904
|
).option(
|
|
20697
20905
|
"--check",
|
|
20698
20906
|
"Enforce target URL reachability (fail fast if server is offline)"
|
|
@@ -20723,7 +20931,10 @@ function registerWalkthroughCommands(program2) {
|
|
|
20723
20931
|
).option(
|
|
20724
20932
|
"--run <run-id>",
|
|
20725
20933
|
"Run ID to size browser (start) or record step into (step)"
|
|
20726
|
-
).option("--action <text>", "Action description (step only)").option("--note <text>", "Persona inner monologue / reasoning (step only)").option("--surface <name>", "Screen or surface name (step only)").option(
|
|
20934
|
+
).option("--action <text>", "Action description (step only)").option("--note <text>", "Persona inner monologue / reasoning (step only)").option("--surface <name>", "Screen or surface name (step only)").option(
|
|
20935
|
+
"--step-file <path>",
|
|
20936
|
+
"Read step payload (action, note, cmd) from a JSON file or '-' for stdin (step only)"
|
|
20937
|
+
).option("--width <px>", "Window width (start)").option("--height <px>", "Window height (start)").option("--headless", "Run without a window (start)").option(
|
|
20727
20938
|
"--port <port>",
|
|
20728
20939
|
"CDP port (start), default 9333",
|
|
20729
20940
|
(value) => parsePortOption(value)
|
|
@@ -20799,9 +21010,9 @@ function registerWalkthroughCommands(program2) {
|
|
|
20799
21010
|
).option("-y, --yes", "Skip interactive prompts").option("--no-prompt", "Skip interactive prompt to view results").option("--view", "Open results in browser immediately without prompt").option(
|
|
20800
21011
|
"--strict-provenance",
|
|
20801
21012
|
"Fail if steps show synthetic or programmatic timing anomalies"
|
|
20802
|
-
).addHelpText(
|
|
21013
|
+
).option("--no-push", "Skip pushing the run to Iamu Cloud").addHelpText(
|
|
20803
21014
|
"after",
|
|
20804
|
-
"\nExamples:\n $ iamu complete <run-id>\n $ iamu complete <run-id> --view\n $ iamu complete <run-id> --no-prompt\n $ iamu complete <run-id> --json\n $ iamu complete <run-id> --strict-provenance"
|
|
21015
|
+
"\nExamples:\n $ iamu complete <run-id>\n $ iamu complete <run-id> --view\n $ iamu complete <run-id> --no-prompt\n $ iamu complete <run-id> --no-push\n $ iamu complete <run-id> --json\n $ iamu complete <run-id> --strict-provenance"
|
|
20805
21016
|
).action(
|
|
20806
21017
|
async (runId, opts) => {
|
|
20807
21018
|
const { complete: complete2 } = await Promise.resolve().then(() => (init_complete(), complete_exports));
|
|
@@ -20810,23 +21021,27 @@ function registerWalkthroughCommands(program2) {
|
|
|
20810
21021
|
);
|
|
20811
21022
|
program2.command("match <run-id>").helpGroup("Walkthrough:").description(
|
|
20812
21023
|
"Compose the prompt that links this run's findings to earlier ones"
|
|
20813
|
-
).option("--json", "Output the match input bundle as JSON").
|
|
20814
|
-
|
|
20815
|
-
|
|
20816
|
-
|
|
21024
|
+
).option("--json", "Output the match input bundle as JSON").option("--prompt-file <path>", "Write the generated prompt to a file").action(
|
|
21025
|
+
async (runId, opts) => {
|
|
21026
|
+
const { match: match2 } = await Promise.resolve().then(() => (init_match(), match_exports));
|
|
21027
|
+
await match2(runId, opts);
|
|
21028
|
+
}
|
|
21029
|
+
);
|
|
20817
21030
|
program2.command("match-record <run-id>").helpGroup("Walkthrough:").description(
|
|
20818
21031
|
"Record finding matches and re-derive the run's since-last-run delta"
|
|
20819
21032
|
).requiredOption("--file <path>", "Path to matches JSON file").option("--json", "Output match results as JSON").action(async (runId, opts) => {
|
|
20820
21033
|
const { matchRecord: matchRecord2 } = await Promise.resolve().then(() => (init_match(), match_exports));
|
|
20821
21034
|
await matchRecord2(runId, opts);
|
|
20822
21035
|
});
|
|
20823
|
-
program2.command("evaluate <run-id>").helpGroup("Walkthrough:").description("Compose evaluation prompt for human-test questions").option("--json", "Output evaluation input bundle as JSON").
|
|
20824
|
-
|
|
20825
|
-
|
|
20826
|
-
|
|
20827
|
-
|
|
21036
|
+
program2.command("evaluate <run-id>").helpGroup("Walkthrough:").description("Compose evaluation prompt for human-test questions").option("--json", "Output evaluation input bundle as JSON").option("--prompt-file <path>", "Write the generated prompt to a file").action(
|
|
21037
|
+
async (runId, opts) => {
|
|
21038
|
+
const { evaluate: evaluate2 } = await Promise.resolve().then(() => (init_evaluate(), evaluate_exports));
|
|
21039
|
+
await evaluate2(runId, opts);
|
|
21040
|
+
}
|
|
21041
|
+
);
|
|
21042
|
+
program2.command("evaluate-record <run-id>").helpGroup("Walkthrough:").description("Record evaluation verdicts into the run's verdicts.json").requiredOption("--file <path>", "Path to verdicts JSON file").option("--json", "Output summary as JSON").option("-y, --yes", "Skip interactive prompts").option("--no-prompt", "Skip interactive prompt to view results").option("--no-push", "Skip pushing the updated run to Iamu Cloud").option("--view", "Open results in browser immediately without prompt").addHelpText(
|
|
20828
21043
|
"after",
|
|
20829
|
-
"\nExamples:\n $ iamu evaluate-record <run-id> --file verdicts.json\n $ iamu evaluate-record <run-id> --file verdicts.json --no-prompt\n $ iamu evaluate-record <run-id> --file verdicts.json --json"
|
|
21044
|
+
"\nExamples:\n $ iamu evaluate-record <run-id> --file verdicts.json\n $ iamu evaluate-record <run-id> --file verdicts.json --no-prompt\n $ iamu evaluate-record <run-id> --file verdicts.json --no-push\n $ iamu evaluate-record <run-id> --file verdicts.json --json"
|
|
20830
21045
|
).action(
|
|
20831
21046
|
async (runId, opts) => {
|
|
20832
21047
|
const { evaluateRecord: evaluateRecord2 } = await Promise.resolve().then(() => (init_evaluate(), evaluate_exports));
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type BuildMetadata, type RunViewport, type ScenarioFrontmatter } from "@iamu-dev/protocol";
|
|
2
|
+
/**
|
|
3
|
+
* The URL a run starts at: `--target` (or the scenario's `target_url`)
|
|
4
|
+
* as the base, with the scenario's `entry_path` resolved against it.
|
|
5
|
+
* Returns an error message instead when there is nothing usable.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveStartUrl(target: string | undefined, scenario: Pick<ScenarioFrontmatter, "target_url" | "entry_path">): {
|
|
8
|
+
url: string;
|
|
9
|
+
} | {
|
|
10
|
+
error: string;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Fast preflight probe to check if the target URL answers HTTP requests.
|
|
14
|
+
* Times out quickly (default: 1000ms) to avoid stalling walkthrough initialization.
|
|
15
|
+
*/
|
|
16
|
+
export declare function checkTargetReachable(url: string, timeoutMs?: number): Promise<{
|
|
17
|
+
reachable: boolean;
|
|
18
|
+
error?: string;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* The build as one line: label, branch, commit and CI provider. A dirty
|
|
22
|
+
* tree shows next to the commit, so a re-run after an uncommitted fix
|
|
23
|
+
* visibly walks a different build.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* formatBuild({ git_sha: "90e2444…", git_dirty: true, worktree_hash: "3fa9c1d2e4b5" });
|
|
28
|
+
* // "90e2444 + uncommitted changes (3fa9c1…)"
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function formatBuild(build: BuildMetadata): string;
|
|
32
|
+
/**
|
|
33
|
+
* A run viewport as one line.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* formatViewport({ device: "desktop", width: 1280, height: 800, source: "persona-tags" });
|
|
38
|
+
* // "desktop 1280×800 (from persona tags)"
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function formatViewport(v: RunViewport): string;
|
|
42
|
+
export interface StartRunOptions {
|
|
43
|
+
target?: string;
|
|
44
|
+
build?: string;
|
|
45
|
+
env?: string;
|
|
46
|
+
json?: boolean;
|
|
47
|
+
check?: boolean;
|
|
48
|
+
walker?: string;
|
|
49
|
+
judge?: string;
|
|
50
|
+
matcher?: string;
|
|
51
|
+
}
|
|
52
|
+
export declare function startRun(scenarioSlug: string, opts: StartRunOptions): Promise<void>;
|