@iamu-dev/iamu 0.2.0-beta.15 → 0.2.0-beta.17
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 +1237 -727
- package/dist/commands/explore.d.ts +1 -0
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/new-entity.d.ts +6 -0
- package/dist/index.js +1227 -711
- package/dist/templates/skills/iamu-findings.md +15 -2
- package/dist/templates/skills/iamu-new.md +7 -2
- package/dist/templates/skills/iamu-propose.md +19 -3
- package/dist/templates/skills/iamu-run.md +49 -3
- package/dist/templates/skills/iamu-status.md +9 -0
- package/package.json +18 -18
package/dist/index.js
CHANGED
|
@@ -247,7 +247,14 @@ var init_capability = __esm({
|
|
|
247
247
|
capabilityFrontmatterSchema = entityBaseSchema.extend({
|
|
248
248
|
/** Human-readable title; corresponds to cloud `name`. */
|
|
249
249
|
title: z5.string().min(1),
|
|
250
|
-
description: z5.string().nullish()
|
|
250
|
+
description: z5.string().nullish(),
|
|
251
|
+
/**
|
|
252
|
+
* Route patterns owned by this capability (e.g. `["/billing", "/invoices"]`).
|
|
253
|
+
* Evaluated with segment-boundary Longest Prefix Match against surface places.
|
|
254
|
+
*/
|
|
255
|
+
paths: z5.array(z5.string()).default([]),
|
|
256
|
+
/** Optional visual grouping category (e.g. "Finance", "Administration"). */
|
|
257
|
+
area: z5.string().nullish()
|
|
251
258
|
});
|
|
252
259
|
}
|
|
253
260
|
});
|
|
@@ -873,6 +880,58 @@ var init_source = __esm({
|
|
|
873
880
|
}
|
|
874
881
|
});
|
|
875
882
|
|
|
883
|
+
// ../../packages/protocol/dist/schemas/frontmatter/testability.js
|
|
884
|
+
import { z as z17 } from "zod";
|
|
885
|
+
function emptyTestability(targetUrl = "http://localhost:3000") {
|
|
886
|
+
return {
|
|
887
|
+
frontmatter: {
|
|
888
|
+
schema_version: SCHEMA_VERSION,
|
|
889
|
+
status: "draft",
|
|
890
|
+
target_url: targetUrl
|
|
891
|
+
},
|
|
892
|
+
body: `# Project Testability & Environment
|
|
893
|
+
|
|
894
|
+
Target URL and execution harness for walkthroughs.
|
|
895
|
+
Audited and populated during /iamu:init.
|
|
896
|
+
|
|
897
|
+
## Target & Run Instructions
|
|
898
|
+
- Default URL: ${targetUrl}
|
|
899
|
+
|
|
900
|
+
## Reachable Surfaces
|
|
901
|
+
(Run /iamu:init to discover testable routes)
|
|
902
|
+
|
|
903
|
+
## Mocks & Data Fixtures
|
|
904
|
+
(Run /iamu:init to inspect existing harnesses)
|
|
905
|
+
|
|
906
|
+
## Untestable Boundaries
|
|
907
|
+
(None documented yet)
|
|
908
|
+
`
|
|
909
|
+
};
|
|
910
|
+
}
|
|
911
|
+
var testabilityStatusEnum, authStrategyEnum, testabilityFrontmatterSchema;
|
|
912
|
+
var init_testability = __esm({
|
|
913
|
+
"../../packages/protocol/dist/schemas/frontmatter/testability.js"() {
|
|
914
|
+
"use strict";
|
|
915
|
+
init_version();
|
|
916
|
+
testabilityStatusEnum = z17.enum(["draft", "verified"]);
|
|
917
|
+
authStrategyEnum = z17.enum([
|
|
918
|
+
"dev_switcher",
|
|
919
|
+
"interactive",
|
|
920
|
+
"test_accounts",
|
|
921
|
+
"public"
|
|
922
|
+
]);
|
|
923
|
+
testabilityFrontmatterSchema = z17.object({
|
|
924
|
+
schema_version: z17.number().int().optional(),
|
|
925
|
+
status: testabilityStatusEnum.default("draft"),
|
|
926
|
+
target_url: z17.string().url().describe("Target URL where the product is hosted or served locally."),
|
|
927
|
+
dev_command: z17.string().max(1e3).optional().describe("Dev script or startup command to boot the app locally."),
|
|
928
|
+
auth_strategy: authStrategyEnum.or(z17.string().min(1).max(100)).optional().describe("How personas authenticate in test environments."),
|
|
929
|
+
harnesses: z17.array(z17.string().min(1).max(500)).max(64).optional().describe("Mocking frameworks, seed scripts, or test harnesses present."),
|
|
930
|
+
untestable_boundaries: z17.array(z17.string().min(1).max(1024)).max(128).optional().describe("External services, third-party APIs, or surfaces forbidden to autonomous walkers.")
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
});
|
|
934
|
+
|
|
876
935
|
// ../../packages/protocol/dist/schemas/frontmatter/index.js
|
|
877
936
|
var ENTITY_TYPES, entityFrontmatterSchemas, ENTITY_DIRS;
|
|
878
937
|
var init_frontmatter = __esm({
|
|
@@ -890,6 +949,7 @@ var init_frontmatter = __esm({
|
|
|
890
949
|
init_run_artifacts();
|
|
891
950
|
init_scenario();
|
|
892
951
|
init_source();
|
|
952
|
+
init_testability();
|
|
893
953
|
init_capability();
|
|
894
954
|
init_finding();
|
|
895
955
|
init_guidance();
|
|
@@ -928,7 +988,7 @@ var init_frontmatter = __esm({
|
|
|
928
988
|
});
|
|
929
989
|
|
|
930
990
|
// ../../packages/protocol/dist/device.js
|
|
931
|
-
import { z as
|
|
991
|
+
import { z as z18 } from "zod";
|
|
932
992
|
function deviceFromPersonaTags(tags) {
|
|
933
993
|
const matches = [];
|
|
934
994
|
for (const tag of tags ?? []) {
|
|
@@ -975,22 +1035,22 @@ var init_device = __esm({
|
|
|
975
1035
|
desktop: "desktop",
|
|
976
1036
|
laptop: "desktop"
|
|
977
1037
|
};
|
|
978
|
-
runViewportSchema =
|
|
979
|
-
device:
|
|
980
|
-
width:
|
|
981
|
-
height:
|
|
982
|
-
source:
|
|
1038
|
+
runViewportSchema = z18.object({
|
|
1039
|
+
device: z18.enum(DEVICE_CLASSES),
|
|
1040
|
+
width: z18.number().int().positive(),
|
|
1041
|
+
height: z18.number().int().positive(),
|
|
1042
|
+
source: z18.literal("persona-tags")
|
|
983
1043
|
});
|
|
984
1044
|
}
|
|
985
1045
|
});
|
|
986
1046
|
|
|
987
1047
|
// ../../packages/protocol/dist/types/fingerprint.js
|
|
988
|
-
import { z as
|
|
1048
|
+
import { z as z19 } from "zod";
|
|
989
1049
|
var stepActionTypeEnum, stepActionAnchorSchema, stepActionSchema, networkFingerprintEntrySchema, hex, stepFingerprintSchema;
|
|
990
1050
|
var init_fingerprint = __esm({
|
|
991
1051
|
"../../packages/protocol/dist/types/fingerprint.js"() {
|
|
992
1052
|
"use strict";
|
|
993
|
-
stepActionTypeEnum =
|
|
1053
|
+
stepActionTypeEnum = z19.enum([
|
|
994
1054
|
"click",
|
|
995
1055
|
"fill",
|
|
996
1056
|
"hover",
|
|
@@ -1000,46 +1060,46 @@ var init_fingerprint = __esm({
|
|
|
1000
1060
|
"done",
|
|
1001
1061
|
"note"
|
|
1002
1062
|
]);
|
|
1003
|
-
stepActionAnchorSchema =
|
|
1063
|
+
stepActionAnchorSchema = z19.object({
|
|
1004
1064
|
/** Max 512 chars to prevent bloating JSONB storage. */
|
|
1005
|
-
role:
|
|
1065
|
+
role: z19.string().max(512).optional(),
|
|
1006
1066
|
/** Max 512 chars to prevent bloating JSONB storage. */
|
|
1007
|
-
accessibleName:
|
|
1067
|
+
accessibleName: z19.string().max(512).optional(),
|
|
1008
1068
|
/** Max 512 chars to prevent bloating JSONB storage. */
|
|
1009
|
-
text:
|
|
1069
|
+
text: z19.string().max(512).optional()
|
|
1010
1070
|
});
|
|
1011
|
-
stepActionSchema =
|
|
1071
|
+
stepActionSchema = z19.object({
|
|
1012
1072
|
type: stepActionTypeEnum,
|
|
1013
1073
|
anchor: stepActionAnchorSchema.optional(),
|
|
1014
1074
|
/** Max 10 fallback selectors, each capped at 1024 chars. */
|
|
1015
|
-
selectorFallbacks:
|
|
1075
|
+
selectorFallbacks: z19.array(z19.string().max(1024)).max(10).optional()
|
|
1016
1076
|
});
|
|
1017
|
-
networkFingerprintEntrySchema =
|
|
1077
|
+
networkFingerprintEntrySchema = z19.object({
|
|
1018
1078
|
/** HTTP method, max 16 chars (e.g. "GET", "POST", "OPTIONS"). */
|
|
1019
|
-
method:
|
|
1079
|
+
method: z19.string().max(16),
|
|
1020
1080
|
/** Templated URL pattern, max 2048 chars. */
|
|
1021
|
-
urlPattern:
|
|
1022
|
-
status:
|
|
1081
|
+
urlPattern: z19.string().max(2048),
|
|
1082
|
+
status: z19.number().int().nonnegative()
|
|
1023
1083
|
});
|
|
1024
|
-
hex = (len) =>
|
|
1025
|
-
stepFingerprintSchema =
|
|
1084
|
+
hex = (len) => z19.string().regex(new RegExp(`^([0-9a-f]{${len}})?$`), `expected hex string of length ${len} or ""`);
|
|
1085
|
+
stepFingerprintSchema = z19.object({
|
|
1026
1086
|
/** Full page URL at time of step, max 4096 chars. */
|
|
1027
|
-
url:
|
|
1087
|
+
url: z19.string().max(4096),
|
|
1028
1088
|
action: stepActionSchema,
|
|
1029
1089
|
domHash: hex(64),
|
|
1030
1090
|
axTreeHash: hex(64),
|
|
1031
1091
|
screenshotPHash: hex(16),
|
|
1032
1092
|
/** Max 500 network entries to prevent runner abuse bloating JSONB. */
|
|
1033
|
-
networkFingerprint:
|
|
1034
|
-
consoleErrorCount:
|
|
1035
|
-
jsExceptionCount:
|
|
1036
|
-
settleDurationMs:
|
|
1093
|
+
networkFingerprint: z19.array(networkFingerprintEntrySchema).max(500),
|
|
1094
|
+
consoleErrorCount: z19.number().int().nonnegative(),
|
|
1095
|
+
jsExceptionCount: z19.number().int().nonnegative(),
|
|
1096
|
+
settleDurationMs: z19.number().int().nonnegative()
|
|
1037
1097
|
});
|
|
1038
1098
|
}
|
|
1039
1099
|
});
|
|
1040
1100
|
|
|
1041
1101
|
// ../../packages/protocol/dist/schemas/walkthrough-bundle.js
|
|
1042
|
-
import { z as
|
|
1102
|
+
import { z as z20 } from "zod";
|
|
1043
1103
|
function defaultEnvironment(targetUrl) {
|
|
1044
1104
|
try {
|
|
1045
1105
|
const origin = new URL(targetUrl).origin;
|
|
@@ -1058,147 +1118,147 @@ var init_walkthrough_bundle = __esm({
|
|
|
1058
1118
|
init_finding();
|
|
1059
1119
|
init_run_artifacts();
|
|
1060
1120
|
init_fingerprint();
|
|
1061
|
-
partNameSchema =
|
|
1121
|
+
partNameSchema = z20.string().min(1).max(128).regex(/^[a-z][a-z0-9_-]*$/, {
|
|
1062
1122
|
message: "part_name must be kebab-or-snake-case ASCII starting with a letter"
|
|
1063
1123
|
}).describe("Key of the matching multipart form field in the bundle body. Must match a binary part exactly.");
|
|
1064
|
-
artifactRefSchema =
|
|
1065
|
-
kind:
|
|
1124
|
+
artifactRefSchema = z20.object({
|
|
1125
|
+
kind: z20.enum(["screenshot", "report", "other"]).describe("Artifact family. 'screenshot' streams to files/walkthroughs/<run_id>/step-<seq>.<ext>; 'report' / 'other' reserved for future kinds."),
|
|
1066
1126
|
part_name: partNameSchema,
|
|
1067
|
-
filename:
|
|
1068
|
-
content_type:
|
|
1069
|
-
bytes_hash:
|
|
1127
|
+
filename: z20.string().min(1).max(256).describe("Original filename as the client saw it. Used for logging and as a fallback display label."),
|
|
1128
|
+
content_type: z20.string().min(1).max(128).describe("MIME type. Screenshots MUST use one of image/png | image/jpeg | image/webp \u2014 the cloud handler enforces that subset separately."),
|
|
1129
|
+
bytes_hash: z20.string().length(64).regex(/^[0-9a-f]+$/).optional().describe("Lowercase hex sha256 of the binary bytes. Optional in v1; client populates when available so cloud can detect transport corruption.")
|
|
1070
1130
|
});
|
|
1071
|
-
stepScreenshotRefSchema =
|
|
1131
|
+
stepScreenshotRefSchema = z20.object({
|
|
1072
1132
|
part_name: partNameSchema,
|
|
1073
|
-
filename:
|
|
1074
|
-
content_type:
|
|
1133
|
+
filename: z20.string().min(1).max(256),
|
|
1134
|
+
content_type: z20.string().min(1).max(128)
|
|
1075
1135
|
});
|
|
1076
|
-
bundleStepSchema =
|
|
1077
|
-
seq:
|
|
1078
|
-
title:
|
|
1079
|
-
persona_reasoning:
|
|
1080
|
-
grounding:
|
|
1136
|
+
bundleStepSchema = z20.object({
|
|
1137
|
+
seq: z20.number().int().min(1).describe("1-based step sequence. Persisted to `walkthrough_steps.bundle_order` so render order survives DB insert-order drift."),
|
|
1138
|
+
title: z20.string().min(1).max(2048).describe("Short first-person heading for the step \u2014 shows in the rendered report."),
|
|
1139
|
+
persona_reasoning: z20.string().max(65536).nullable().optional().describe("First-person inner voice capture. Nullable for terse / action-only steps."),
|
|
1140
|
+
grounding: z20.string().max(65536).nullable().optional().describe("Optional citations, domain-knowledge grounding, or verification notes for this step."),
|
|
1081
1141
|
created_at: isoTimestamp.describe("Client-side ISO timestamp. Trusted as-is by the cloud (runner writes cloud-side already trust the runner's clock \u2014 same invariant)."),
|
|
1082
1142
|
fingerprint: stepFingerprintSchema.nullable().optional().describe("Full StepFingerprint object (dom/ax/screenshot hashes + network + console signals). Passed through verbatim to walkthrough_steps.fingerprint; runtime shape validated by the fingerprint package on write."),
|
|
1083
1143
|
screenshot_ref: stepScreenshotRefSchema.nullable().optional().describe("When present, identifies the multipart binary part carrying this step's screenshot bytes."),
|
|
1084
|
-
url:
|
|
1085
|
-
surface:
|
|
1144
|
+
url: z20.string().min(1).max(STEP_URL_MAX_LENGTH).nullable().optional().describe("The page the persona was on when the step ended. Absent for runs recorded before steps carried a URL."),
|
|
1145
|
+
surface: z20.string().min(1).max(STEP_SURFACE_MAX_LENGTH).nullable().optional().describe("The walker's short name for the screen (e.g. 'search results'). Optional.")
|
|
1086
1146
|
});
|
|
1087
|
-
bundleFindingSchema =
|
|
1147
|
+
bundleFindingSchema = z20.object({
|
|
1088
1148
|
slug: slugSchema,
|
|
1089
1149
|
frontmatter: findingFrontmatterSchema,
|
|
1090
|
-
body:
|
|
1091
|
-
screenshot_refs:
|
|
1150
|
+
body: z20.string().max(1048576).describe("Full markdown body of the finding file. 1 MiB cap matches the entity import envelope."),
|
|
1151
|
+
screenshot_refs: z20.array(stepScreenshotRefSchema).max(32).optional().describe("Optional per-finding screenshot parts (distinct from step screenshots \u2014 e.g. annotated evidence shots attached to the finding write-up).")
|
|
1092
1152
|
});
|
|
1093
|
-
verificationItemSchema =
|
|
1094
|
-
canonical_id:
|
|
1095
|
-
id:
|
|
1096
|
-
title:
|
|
1097
|
-
type:
|
|
1153
|
+
verificationItemSchema = z20.object({
|
|
1154
|
+
canonical_id: z20.string().max(64).optional(),
|
|
1155
|
+
id: z20.string().max(64).optional(),
|
|
1156
|
+
title: z20.string().max(1024),
|
|
1157
|
+
type: z20.string().max(32).optional()
|
|
1098
1158
|
});
|
|
1099
|
-
verificationGroup =
|
|
1100
|
-
bundleVerificationSchema =
|
|
1101
|
-
baseline_run_id:
|
|
1159
|
+
verificationGroup = z20.array(verificationItemSchema).max(500);
|
|
1160
|
+
bundleVerificationSchema = z20.object({
|
|
1161
|
+
baseline_run_id: z20.string().max(256),
|
|
1102
1162
|
resolved: verificationGroup.default([]),
|
|
1103
1163
|
persists: verificationGroup.default([]),
|
|
1104
1164
|
not_observed: verificationGroup.default([]),
|
|
1105
1165
|
uncertain: verificationGroup.default([]),
|
|
1106
1166
|
new_findings: verificationGroup.default([])
|
|
1107
1167
|
});
|
|
1108
|
-
buildMetadataSchema =
|
|
1109
|
-
label:
|
|
1110
|
-
git_sha:
|
|
1111
|
-
git_branch:
|
|
1112
|
-
base_sha:
|
|
1168
|
+
buildMetadataSchema = z20.object({
|
|
1169
|
+
label: z20.string().min(1).max(200).optional().describe("Human label for the build, from `iamu start-run --build`."),
|
|
1170
|
+
git_sha: z20.string().regex(/^[0-9a-f]{7,64}$/i, { message: "git_sha must be a hex commit id" }).optional().describe("Commit of the product under test."),
|
|
1171
|
+
git_branch: z20.string().min(1).max(255).optional(),
|
|
1172
|
+
base_sha: z20.string().regex(/^[0-9a-f]{7,64}$/i, {
|
|
1113
1173
|
message: "base_sha must be a hex commit id"
|
|
1114
1174
|
}).optional().describe("Commit the change is compared against (pull-request base)."),
|
|
1115
|
-
git_dirty:
|
|
1116
|
-
worktree_hash:
|
|
1175
|
+
git_dirty: z20.boolean().optional().describe("True when the working tree had changes outside `iamu/` (tracked edits vs HEAD, staged or not, or untracked non-ignored files). Absent outside git."),
|
|
1176
|
+
worktree_hash: z20.string().regex(/^[0-9a-f]{12}$/, {
|
|
1117
1177
|
message: "worktree_hash must be 12 lowercase hex characters"
|
|
1118
1178
|
}).optional().describe("Only when `git_dirty`: fingerprint of the uncommitted changes, so two runs on one commit with different edits are different builds."),
|
|
1119
|
-
ci:
|
|
1120
|
-
provider:
|
|
1121
|
-
run_url:
|
|
1179
|
+
ci: z20.object({
|
|
1180
|
+
provider: z20.string().min(1).max(64).describe("CI system that ran the walk, e.g. `github`, `azure`."),
|
|
1181
|
+
run_url: z20.string().url().max(2048)
|
|
1122
1182
|
}).optional()
|
|
1123
1183
|
});
|
|
1124
1184
|
ENVIRONMENT_MAX_LENGTH = 255;
|
|
1125
|
-
bundleManifestSchema =
|
|
1126
|
-
run_id:
|
|
1127
|
-
scenario_id:
|
|
1128
|
-
target_url:
|
|
1129
|
-
lenses:
|
|
1130
|
-
status:
|
|
1131
|
-
client_origin:
|
|
1185
|
+
bundleManifestSchema = z20.object({
|
|
1186
|
+
run_id: z20.string().uuid().describe("Client-minted UUID. Becomes `walkthroughs.id` on cloud. Idempotent key for the push endpoint."),
|
|
1187
|
+
scenario_id: z20.string().min(1).describe("Scenario reference \u2014 slug in local-only mode, UUID in cloud-linked mode. Cloud handler resolves to the tenant's scenarios.id."),
|
|
1188
|
+
target_url: z20.string().url().max(2048),
|
|
1189
|
+
lenses: z20.array(z20.string().min(1).max(64)).min(1).max(16).describe("Analysis lenses enabled for this run. Defaults to ['persona'] in most flows."),
|
|
1190
|
+
status: z20.literal("completed").describe("v1 only accepts completed bundles (bundle-on-complete). In-progress runs are not pushable."),
|
|
1191
|
+
client_origin: z20.literal("local").describe("Discriminator written to walkthroughs.client_origin. Reserved for `local` in this endpoint; runner-origin rows take a different code path."),
|
|
1132
1192
|
created_at: isoTimestamp,
|
|
1133
1193
|
completed_at: isoTimestamp,
|
|
1134
|
-
step_count:
|
|
1135
|
-
finding_count:
|
|
1136
|
-
report_markdown:
|
|
1137
|
-
what_worked:
|
|
1138
|
-
open_questions:
|
|
1194
|
+
step_count: z20.number().int().min(0).max(1e4),
|
|
1195
|
+
finding_count: z20.number().int().min(0).max(1e4),
|
|
1196
|
+
report_markdown: z20.string().max(1048576).describe("report.md body verbatim. Persists to walkthroughs.report_markdown so dashboard can render without regenerating."),
|
|
1197
|
+
what_worked: z20.array(z20.string().max(4096)).max(64).optional(),
|
|
1198
|
+
open_questions: z20.array(z20.string().max(4096)).max(64).optional(),
|
|
1139
1199
|
verification: bundleVerificationSchema.optional().describe("Since-last-run delta from canonical.json \u2014 which earlier findings persist, were re-checked fixed, were not seen, and which are new. Persists to walkthroughs.verification."),
|
|
1140
1200
|
build: buildMetadataSchema.optional().describe("Build of the product under test (git SHA, branch, CI run). Absent for runs started before `start-run` recorded it."),
|
|
1141
|
-
environment:
|
|
1201
|
+
environment: z20.string().min(1).max(ENVIRONMENT_MAX_LENGTH).optional().describe("Where the product ran: `--env <name>` or, by default, the target URL's origin (e.g. `http://localhost:3000`)."),
|
|
1142
1202
|
/** Holistic UX quality score from UX review pass. Present only when `lenses` includes "ux". */
|
|
1143
|
-
ux_quality_score:
|
|
1203
|
+
ux_quality_score: z20.number().min(1).max(5).nullish(),
|
|
1144
1204
|
/** One-line rationale naming 1-2 structural factors that determined the score. */
|
|
1145
|
-
ux_quality_rationale:
|
|
1146
|
-
verdict:
|
|
1147
|
-
humanTestId:
|
|
1148
|
-
human_test_id:
|
|
1149
|
-
question:
|
|
1150
|
-
rating:
|
|
1151
|
-
verdict:
|
|
1152
|
-
reasoning:
|
|
1153
|
-
groundingStepIds:
|
|
1154
|
-
grounding_step_ids:
|
|
1155
|
-
groundingFindingIds:
|
|
1156
|
-
grounding_finding_ids:
|
|
1205
|
+
ux_quality_rationale: z20.string().max(4096).nullish(),
|
|
1206
|
+
verdict: z20.array(z20.object({
|
|
1207
|
+
humanTestId: z20.string().optional(),
|
|
1208
|
+
human_test_id: z20.string().optional(),
|
|
1209
|
+
question: z20.string().default(""),
|
|
1210
|
+
rating: z20.enum(["yes", "no", "partial", "not_applicable"]).optional(),
|
|
1211
|
+
verdict: z20.enum(["yes", "no", "partial", "not_applicable"]).optional(),
|
|
1212
|
+
reasoning: z20.string(),
|
|
1213
|
+
groundingStepIds: z20.array(z20.string()).optional(),
|
|
1214
|
+
grounding_step_ids: z20.array(z20.string()).optional(),
|
|
1215
|
+
groundingFindingIds: z20.array(z20.string()).optional(),
|
|
1216
|
+
grounding_finding_ids: z20.array(z20.string()).optional()
|
|
1157
1217
|
}).refine((v) => Boolean(v.humanTestId || v.human_test_id) && Boolean(v.rating || v.verdict), {
|
|
1158
1218
|
message: "verdict item must include humanTestId or human_test_id, and rating or verdict"
|
|
1159
1219
|
})).optional(),
|
|
1160
|
-
judge_meta:
|
|
1161
|
-
overall:
|
|
1162
|
-
question:
|
|
1163
|
-
answer:
|
|
1164
|
-
reasoning:
|
|
1220
|
+
judge_meta: z20.object({
|
|
1221
|
+
overall: z20.object({
|
|
1222
|
+
question: z20.string(),
|
|
1223
|
+
answer: z20.string(),
|
|
1224
|
+
reasoning: z20.string()
|
|
1165
1225
|
}),
|
|
1166
|
-
provenance:
|
|
1167
|
-
judge_prompt:
|
|
1168
|
-
judge_model:
|
|
1226
|
+
provenance: z20.object({
|
|
1227
|
+
judge_prompt: z20.string().optional(),
|
|
1228
|
+
judge_model: z20.string().optional()
|
|
1169
1229
|
}).optional()
|
|
1170
1230
|
}).optional(),
|
|
1171
|
-
models:
|
|
1172
|
-
walker:
|
|
1173
|
-
matcher:
|
|
1174
|
-
judge:
|
|
1175
|
-
walker_reported:
|
|
1176
|
-
matcher_reported:
|
|
1177
|
-
judge_reported:
|
|
1178
|
-
walker_tier:
|
|
1179
|
-
matcher_tier:
|
|
1180
|
-
judge_tier:
|
|
1181
|
-
execution_mode:
|
|
1182
|
-
velocity_sec_per_step:
|
|
1183
|
-
total_duration_sec:
|
|
1231
|
+
models: z20.object({
|
|
1232
|
+
walker: z20.string().optional(),
|
|
1233
|
+
matcher: z20.string().optional(),
|
|
1234
|
+
judge: z20.string().optional(),
|
|
1235
|
+
walker_reported: z20.string().optional(),
|
|
1236
|
+
matcher_reported: z20.string().optional(),
|
|
1237
|
+
judge_reported: z20.string().optional(),
|
|
1238
|
+
walker_tier: z20.string().optional(),
|
|
1239
|
+
matcher_tier: z20.string().optional(),
|
|
1240
|
+
judge_tier: z20.string().optional(),
|
|
1241
|
+
execution_mode: z20.enum(["multi_agent", "single_agent"]).optional(),
|
|
1242
|
+
velocity_sec_per_step: z20.number().optional(),
|
|
1243
|
+
total_duration_sec: z20.number().optional()
|
|
1184
1244
|
}).optional().describe("AI model configuration and reported runtime provenance for this walkthrough.")
|
|
1185
1245
|
});
|
|
1186
|
-
walkthroughBundleSchema =
|
|
1246
|
+
walkthroughBundleSchema = z20.object({
|
|
1187
1247
|
manifest: bundleManifestSchema,
|
|
1188
|
-
steps:
|
|
1189
|
-
findings:
|
|
1190
|
-
artifacts:
|
|
1248
|
+
steps: z20.array(bundleStepSchema).max(1e4),
|
|
1249
|
+
findings: z20.array(bundleFindingSchema).max(1e4),
|
|
1250
|
+
artifacts: z20.array(artifactRefSchema).max(1e4)
|
|
1191
1251
|
}).superRefine((bundle, ctx) => {
|
|
1192
1252
|
if (bundle.manifest.step_count !== bundle.steps.length) {
|
|
1193
1253
|
ctx.addIssue({
|
|
1194
|
-
code:
|
|
1254
|
+
code: z20.ZodIssueCode.custom,
|
|
1195
1255
|
path: ["manifest", "step_count"],
|
|
1196
1256
|
message: `manifest.step_count (${bundle.manifest.step_count}) must equal steps.length (${bundle.steps.length})`
|
|
1197
1257
|
});
|
|
1198
1258
|
}
|
|
1199
1259
|
if (bundle.manifest.finding_count !== bundle.findings.length) {
|
|
1200
1260
|
ctx.addIssue({
|
|
1201
|
-
code:
|
|
1261
|
+
code: z20.ZodIssueCode.custom,
|
|
1202
1262
|
path: ["manifest", "finding_count"],
|
|
1203
1263
|
message: `manifest.finding_count (${bundle.manifest.finding_count}) must equal findings.length (${bundle.findings.length})`
|
|
1204
1264
|
});
|
|
@@ -1207,14 +1267,14 @@ var init_walkthrough_bundle = __esm({
|
|
|
1207
1267
|
const expected = Array.from({ length: bundle.steps.length }, (_, i) => i + 1);
|
|
1208
1268
|
if (seqs.join(",") !== expected.join(",")) {
|
|
1209
1269
|
ctx.addIssue({
|
|
1210
|
-
code:
|
|
1270
|
+
code: z20.ZodIssueCode.custom,
|
|
1211
1271
|
path: ["steps"],
|
|
1212
1272
|
message: `step seq values must be dense 1..${bundle.steps.length}; received [${seqs.join(",")}]`
|
|
1213
1273
|
});
|
|
1214
1274
|
}
|
|
1215
1275
|
if (bundle.steps.length === 0 && bundle.artifacts.length > 0) {
|
|
1216
1276
|
ctx.addIssue({
|
|
1217
|
-
code:
|
|
1277
|
+
code: z20.ZodIssueCode.custom,
|
|
1218
1278
|
path: ["steps"],
|
|
1219
1279
|
message: `bundle declares ${bundle.artifacts.length} artifact(s) but no steps \u2014 step records were not read`
|
|
1220
1280
|
});
|
|
@@ -1224,7 +1284,7 @@ var init_walkthrough_bundle = __esm({
|
|
|
1224
1284
|
for (const name of partNames) {
|
|
1225
1285
|
if (seen.has(name)) {
|
|
1226
1286
|
ctx.addIssue({
|
|
1227
|
-
code:
|
|
1287
|
+
code: z20.ZodIssueCode.custom,
|
|
1228
1288
|
path: ["artifacts"],
|
|
1229
1289
|
message: `duplicate artifact part_name: ${name}`
|
|
1230
1290
|
});
|
|
@@ -1236,7 +1296,7 @@ var init_walkthrough_bundle = __esm({
|
|
|
1236
1296
|
for (const [i, step] of bundle.steps.entries()) {
|
|
1237
1297
|
if (step.screenshot_ref && !artifactPartNames.has(step.screenshot_ref.part_name)) {
|
|
1238
1298
|
ctx.addIssue({
|
|
1239
|
-
code:
|
|
1299
|
+
code: z20.ZodIssueCode.custom,
|
|
1240
1300
|
path: ["steps", i, "screenshot_ref", "part_name"],
|
|
1241
1301
|
message: `step[${step.seq}].screenshot_ref.part_name "${step.screenshot_ref.part_name}" is not declared in artifacts[]`
|
|
1242
1302
|
});
|
|
@@ -1246,7 +1306,7 @@ var init_walkthrough_bundle = __esm({
|
|
|
1246
1306
|
for (const [j, ref] of (finding.screenshot_refs ?? []).entries()) {
|
|
1247
1307
|
if (!artifactPartNames.has(ref.part_name)) {
|
|
1248
1308
|
ctx.addIssue({
|
|
1249
|
-
code:
|
|
1309
|
+
code: z20.ZodIssueCode.custom,
|
|
1250
1310
|
path: ["findings", i, "screenshot_refs", j, "part_name"],
|
|
1251
1311
|
message: `finding[${finding.slug}].screenshot_refs[${j}].part_name "${ref.part_name}" is not declared in artifacts[]`
|
|
1252
1312
|
});
|
|
@@ -1256,7 +1316,7 @@ var init_walkthrough_bundle = __esm({
|
|
|
1256
1316
|
for (const [i, finding] of bundle.findings.entries()) {
|
|
1257
1317
|
if (finding.frontmatter.scenario !== bundle.manifest.scenario_id) {
|
|
1258
1318
|
ctx.addIssue({
|
|
1259
|
-
code:
|
|
1319
|
+
code: z20.ZodIssueCode.custom,
|
|
1260
1320
|
path: ["findings", i, "frontmatter", "scenario"],
|
|
1261
1321
|
message: `finding.frontmatter.scenario "${finding.frontmatter.scenario}" must match manifest.scenario_id "${bundle.manifest.scenario_id}"`
|
|
1262
1322
|
});
|
|
@@ -1265,7 +1325,7 @@ var init_walkthrough_bundle = __esm({
|
|
|
1265
1325
|
for (const [i, finding] of bundle.findings.entries()) {
|
|
1266
1326
|
if (finding.frontmatter.run !== bundle.manifest.run_id) {
|
|
1267
1327
|
ctx.addIssue({
|
|
1268
|
-
code:
|
|
1328
|
+
code: z20.ZodIssueCode.custom,
|
|
1269
1329
|
path: ["findings", i, "frontmatter", "run"],
|
|
1270
1330
|
message: `finding.frontmatter.run "${finding.frontmatter.run}" must match manifest.run_id "${bundle.manifest.run_id}"`
|
|
1271
1331
|
});
|
|
@@ -1277,30 +1337,30 @@ var init_walkthrough_bundle = __esm({
|
|
|
1277
1337
|
"updated",
|
|
1278
1338
|
"unchanged"
|
|
1279
1339
|
];
|
|
1280
|
-
walkthroughPushResponseSchema =
|
|
1281
|
-
run_id:
|
|
1282
|
-
cloud_walkthrough_id:
|
|
1283
|
-
status:
|
|
1284
|
-
step_count:
|
|
1285
|
-
finding_count:
|
|
1286
|
-
artifact_count:
|
|
1340
|
+
walkthroughPushResponseSchema = z20.object({
|
|
1341
|
+
run_id: z20.string().uuid(),
|
|
1342
|
+
cloud_walkthrough_id: z20.string().uuid(),
|
|
1343
|
+
status: z20.enum(WALKTHROUGH_PUSH_OUTCOMES),
|
|
1344
|
+
step_count: z20.number().int().min(0),
|
|
1345
|
+
finding_count: z20.number().int().min(0),
|
|
1346
|
+
artifact_count: z20.number().int().min(0)
|
|
1287
1347
|
});
|
|
1288
1348
|
WALKTHROUGH_CONFLICT_REASONS = [
|
|
1289
1349
|
"project_mismatch",
|
|
1290
1350
|
"scenario_mismatch",
|
|
1291
1351
|
"step_count_mismatch"
|
|
1292
1352
|
];
|
|
1293
|
-
walkthroughPushConflictSchema =
|
|
1294
|
-
code:
|
|
1295
|
-
reason:
|
|
1296
|
-
run_id:
|
|
1297
|
-
message:
|
|
1353
|
+
walkthroughPushConflictSchema = z20.object({
|
|
1354
|
+
code: z20.literal("walkthrough_conflict"),
|
|
1355
|
+
reason: z20.enum(WALKTHROUGH_CONFLICT_REASONS),
|
|
1356
|
+
run_id: z20.string().uuid(),
|
|
1357
|
+
message: z20.string()
|
|
1298
1358
|
});
|
|
1299
1359
|
}
|
|
1300
1360
|
});
|
|
1301
1361
|
|
|
1302
1362
|
// ../../packages/protocol/dist/types/walkthrough-canonical.js
|
|
1303
|
-
import { z as
|
|
1363
|
+
import { z as z21 } from "zod";
|
|
1304
1364
|
var CANONICAL_WALKTHROUGH_VERSION, canonicalScenarioRefSchema, canonicalTargetSchema, canonicalProvenanceSchema, canonicalStepSchema, canonicalFindingSchema, canonicalHumanTestSchema, canonicalHumanTestOverallSchema, canonicalErrorSchema, cloudMirrorStateSchema, canonicalWalkthroughSchema;
|
|
1305
1365
|
var init_walkthrough_canonical = __esm({
|
|
1306
1366
|
"../../packages/protocol/dist/types/walkthrough-canonical.js"() {
|
|
@@ -1310,106 +1370,106 @@ var init_walkthrough_canonical = __esm({
|
|
|
1310
1370
|
init_walkthrough_bundle();
|
|
1311
1371
|
init_enums();
|
|
1312
1372
|
CANONICAL_WALKTHROUGH_VERSION = "1.0.0";
|
|
1313
|
-
canonicalScenarioRefSchema =
|
|
1314
|
-
id:
|
|
1315
|
-
slug:
|
|
1316
|
-
persona_slug:
|
|
1317
|
-
outline_slug:
|
|
1318
|
-
brief:
|
|
1373
|
+
canonicalScenarioRefSchema = z21.object({
|
|
1374
|
+
id: z21.string(),
|
|
1375
|
+
slug: z21.string(),
|
|
1376
|
+
persona_slug: z21.string(),
|
|
1377
|
+
outline_slug: z21.string(),
|
|
1378
|
+
brief: z21.string()
|
|
1319
1379
|
}).passthrough();
|
|
1320
|
-
canonicalTargetSchema =
|
|
1321
|
-
url:
|
|
1380
|
+
canonicalTargetSchema = z21.object({
|
|
1381
|
+
url: z21.string(),
|
|
1322
1382
|
/** Where the product runs. "live" = real backend; "mock" = stubbed. */
|
|
1323
|
-
backend_mode:
|
|
1383
|
+
backend_mode: z21.enum(["live", "mock", "unknown"]),
|
|
1324
1384
|
/** Browser / runner used for the walk. */
|
|
1325
|
-
browser:
|
|
1385
|
+
browser: z21.string()
|
|
1326
1386
|
}).passthrough();
|
|
1327
|
-
canonicalProvenanceSchema =
|
|
1328
|
-
walker_prompt:
|
|
1329
|
-
judge_prompt:
|
|
1330
|
-
judge_mode:
|
|
1387
|
+
canonicalProvenanceSchema = z21.object({
|
|
1388
|
+
walker_prompt: z21.object({ id: z21.string(), version: z21.string() }).passthrough(),
|
|
1389
|
+
judge_prompt: z21.object({ id: z21.string(), version: z21.string() }).passthrough().optional(),
|
|
1390
|
+
judge_mode: z21.enum(["subagent", "same_agent_second_pass", "failed"]).optional(),
|
|
1331
1391
|
/** Model identifier used by the walker. Judge model (when it runs) is
|
|
1332
1392
|
* stamped inside `judge_meta.provenance.model` on the DB row. */
|
|
1333
|
-
model:
|
|
1393
|
+
model: z21.string(),
|
|
1334
1394
|
started_at: isoTimestamp,
|
|
1335
1395
|
completed_at: isoTimestamp
|
|
1336
1396
|
}).passthrough();
|
|
1337
|
-
canonicalStepSchema =
|
|
1338
|
-
id:
|
|
1339
|
-
step_number:
|
|
1340
|
-
url:
|
|
1397
|
+
canonicalStepSchema = z21.object({
|
|
1398
|
+
id: z21.string(),
|
|
1399
|
+
step_number: z21.number().int(),
|
|
1400
|
+
url: z21.string().optional(),
|
|
1341
1401
|
/** The walker's short name for the screen. */
|
|
1342
|
-
surface:
|
|
1343
|
-
screen_title:
|
|
1402
|
+
surface: z21.string().optional(),
|
|
1403
|
+
screen_title: z21.string().optional(),
|
|
1344
1404
|
/** Path reference to the screenshot file; never inline binary data. */
|
|
1345
|
-
screenshot_ref:
|
|
1346
|
-
persona_reasoning:
|
|
1347
|
-
grounding:
|
|
1348
|
-
action:
|
|
1405
|
+
screenshot_ref: z21.string().nullable().optional(),
|
|
1406
|
+
persona_reasoning: z21.string().nullable().optional(),
|
|
1407
|
+
grounding: z21.string().nullable().optional(),
|
|
1408
|
+
action: z21.string().optional()
|
|
1349
1409
|
}).passthrough();
|
|
1350
|
-
canonicalFindingSchema =
|
|
1351
|
-
id:
|
|
1410
|
+
canonicalFindingSchema = z21.object({
|
|
1411
|
+
id: z21.string(),
|
|
1352
1412
|
/** Stable across runs for pattern tracking — null until cross-run wiring lands. */
|
|
1353
|
-
canonical_id:
|
|
1413
|
+
canonical_id: z21.string().nullable(),
|
|
1354
1414
|
type: findingTypeEnum,
|
|
1355
|
-
severity:
|
|
1415
|
+
severity: z21.enum(["critical", "major", "minor", "observation"]).nullable(),
|
|
1356
1416
|
/** Depth-gate half 1: what the UI showed or did (observable without domain knowledge). */
|
|
1357
|
-
ui_fact:
|
|
1417
|
+
ui_fact: z21.string().nullable(),
|
|
1358
1418
|
/** Depth-gate half 2: what it means for the persona. Null on legacy rows (pre-migration). */
|
|
1359
|
-
consequence:
|
|
1360
|
-
recommendation:
|
|
1419
|
+
consequence: z21.string().nullable(),
|
|
1420
|
+
recommendation: z21.string().nullable(),
|
|
1361
1421
|
/** Step ids this finding cites as evidence (references `steps[].id`). */
|
|
1362
|
-
linked_step_ids:
|
|
1422
|
+
linked_step_ids: z21.array(z21.string()),
|
|
1363
1423
|
/** Parent scenario's human-test question id the finding bears on, if any. */
|
|
1364
|
-
linked_human_test_id:
|
|
1365
|
-
compliance_impact:
|
|
1366
|
-
task_impact:
|
|
1367
|
-
confidence:
|
|
1368
|
-
regulatory_weight:
|
|
1369
|
-
citations:
|
|
1424
|
+
linked_human_test_id: z21.string().nullable(),
|
|
1425
|
+
compliance_impact: z21.enum(["critical", "major", "minor", "informational"]).nullable().optional(),
|
|
1426
|
+
task_impact: z21.enum(["blocks", "impairs", "slows", "neutral", "accelerates", "enables"]).nullable().optional(),
|
|
1427
|
+
confidence: z21.enum(["high", "medium", "low"]).nullable().optional(),
|
|
1428
|
+
regulatory_weight: z21.enum(["hard_requirement", "process_model", "best_practice"]).nullable().optional(),
|
|
1429
|
+
citations: z21.array(z21.string()).optional()
|
|
1370
1430
|
}).passthrough();
|
|
1371
|
-
canonicalHumanTestSchema =
|
|
1372
|
-
id:
|
|
1373
|
-
question:
|
|
1431
|
+
canonicalHumanTestSchema = z21.object({
|
|
1432
|
+
id: z21.string(),
|
|
1433
|
+
question: z21.string(),
|
|
1374
1434
|
/** Null until judge stage writes via `record_judge_result`. */
|
|
1375
|
-
verdict:
|
|
1376
|
-
reasoning:
|
|
1377
|
-
grounding_step_ids:
|
|
1378
|
-
grounding_finding_ids:
|
|
1435
|
+
verdict: z21.enum(["yes", "partial", "no", "not_applicable"]).nullable(),
|
|
1436
|
+
reasoning: z21.string().nullable(),
|
|
1437
|
+
grounding_step_ids: z21.array(z21.string()),
|
|
1438
|
+
grounding_finding_ids: z21.array(z21.string())
|
|
1379
1439
|
}).passthrough();
|
|
1380
|
-
canonicalHumanTestOverallSchema =
|
|
1381
|
-
question:
|
|
1440
|
+
canonicalHumanTestOverallSchema = z21.object({
|
|
1441
|
+
question: z21.string(),
|
|
1382
1442
|
/** Null until judge stage answers. */
|
|
1383
|
-
answer:
|
|
1384
|
-
reasoning:
|
|
1443
|
+
answer: z21.string().nullable(),
|
|
1444
|
+
reasoning: z21.string().nullable()
|
|
1385
1445
|
}).passthrough();
|
|
1386
|
-
canonicalErrorSchema =
|
|
1387
|
-
stage:
|
|
1388
|
-
message:
|
|
1389
|
-
at:
|
|
1446
|
+
canonicalErrorSchema = z21.object({
|
|
1447
|
+
stage: z21.string(),
|
|
1448
|
+
message: z21.string(),
|
|
1449
|
+
at: z21.string()
|
|
1390
1450
|
}).passthrough();
|
|
1391
|
-
cloudMirrorStateSchema =
|
|
1451
|
+
cloudMirrorStateSchema = z21.enum([
|
|
1392
1452
|
"pushed",
|
|
1393
1453
|
"enqueued",
|
|
1394
1454
|
"local-only",
|
|
1395
1455
|
"already_pushed",
|
|
1396
1456
|
"skipped"
|
|
1397
1457
|
]);
|
|
1398
|
-
canonicalWalkthroughSchema =
|
|
1399
|
-
canonical_version:
|
|
1400
|
-
run_id:
|
|
1458
|
+
canonicalWalkthroughSchema = z21.object({
|
|
1459
|
+
canonical_version: z21.literal(CANONICAL_WALKTHROUGH_VERSION),
|
|
1460
|
+
run_id: z21.string(),
|
|
1401
1461
|
scenario: canonicalScenarioRefSchema,
|
|
1402
1462
|
target: canonicalTargetSchema,
|
|
1403
1463
|
provenance: canonicalProvenanceSchema,
|
|
1404
1464
|
build: buildMetadataSchema.optional(),
|
|
1405
1465
|
viewport: runViewportSchema.optional(),
|
|
1406
|
-
environment:
|
|
1407
|
-
models:
|
|
1408
|
-
findings:
|
|
1409
|
-
steps:
|
|
1410
|
-
human_tests:
|
|
1466
|
+
environment: z21.string().optional(),
|
|
1467
|
+
models: z21.record(z21.unknown()).optional(),
|
|
1468
|
+
findings: z21.array(canonicalFindingSchema),
|
|
1469
|
+
steps: z21.array(canonicalStepSchema),
|
|
1470
|
+
human_tests: z21.array(canonicalHumanTestSchema),
|
|
1411
1471
|
human_test_overall: canonicalHumanTestOverallSchema,
|
|
1412
|
-
errors:
|
|
1472
|
+
errors: z21.array(canonicalErrorSchema),
|
|
1413
1473
|
cloud_mirror_state: cloudMirrorStateSchema
|
|
1414
1474
|
}).passthrough();
|
|
1415
1475
|
}
|
|
@@ -1820,7 +1880,7 @@ var init_prompt_registry = __esm({
|
|
|
1820
1880
|
});
|
|
1821
1881
|
|
|
1822
1882
|
// ../../packages/protocol/dist/mcp-schemas.js
|
|
1823
|
-
import { z as
|
|
1883
|
+
import { z as z22 } from "zod";
|
|
1824
1884
|
var AuthorityLevelSchema, FindingTypeSchema, MirrorStatusSchema, FindingSummarySchema, ScenarioSummarySchema, RetrievalGapSchema, GetConstraintsDataSchema, GetConstraintsOutputSchema, QueryDataSchema, QueryOutputSchema, ListFindingsDataSchema, ListFindingsOutputSchema, ListScenariosDataSchema, ListScenariosOutputSchema, GetProjectDataSchema, GetProjectOutputSchema, CreateScenarioDataSchema, CreateScenarioOutputSchema, PrepareWalkthroughDataSchema, PrepareWalkthroughOutputSchema, PersonaSummarySchema, OutlineSummarySchema, CapabilitySummarySchema, ListPersonasDataSchema, ListPersonasOutputSchema, ListOutlinesDataSchema, ListOutlinesOutputSchema, ListCapabilitiesDataSchema, ListCapabilitiesOutputSchema, GetPersonaDataSchema, GetPersonaOutputSchema, GetOutlineDataSchema, GetOutlineOutputSchema, GetFindingDataSchema, GetFindingOutputSchema, CreatePersonaDataSchema, CreatePersonaOutputSchema, CreateOutlineDataSchema, CreateOutlineOutputSchema, CreateCapabilityDataSchema, CreateCapabilityOutputSchema, RecordStepDataSchema, RecordStepOutputSchema, RecordFindingDataSchema, RecordFindingOutputSchema, CompleteWalkthroughDataSchema, CompleteWalkthroughOutputSchema, GetJudgeInputDataSchema, GetJudgeInputOutputSchema, RecordJudgeResultDataSchema, RecordJudgeResultOutputSchema;
|
|
1825
1885
|
var init_mcp_schemas = __esm({
|
|
1826
1886
|
"../../packages/protocol/dist/mcp-schemas.js"() {
|
|
@@ -1832,352 +1892,352 @@ var init_mcp_schemas = __esm({
|
|
|
1832
1892
|
init_fingerprint();
|
|
1833
1893
|
AuthorityLevelSchema = authorityLevelEnum;
|
|
1834
1894
|
FindingTypeSchema = findingTypeEnum;
|
|
1835
|
-
MirrorStatusSchema =
|
|
1895
|
+
MirrorStatusSchema = z22.enum([
|
|
1836
1896
|
"synced",
|
|
1837
1897
|
"pending_retry",
|
|
1838
1898
|
"local_only",
|
|
1839
1899
|
"not_applicable"
|
|
1840
1900
|
]);
|
|
1841
|
-
FindingSummarySchema =
|
|
1842
|
-
id:
|
|
1843
|
-
slug:
|
|
1844
|
-
title:
|
|
1901
|
+
FindingSummarySchema = z22.object({
|
|
1902
|
+
id: z22.string(),
|
|
1903
|
+
slug: z22.string().nullable(),
|
|
1904
|
+
title: z22.string(),
|
|
1845
1905
|
type: FindingTypeSchema,
|
|
1846
1906
|
/** Discriminator: "canonical" for deduplicated cloud findings,
|
|
1847
1907
|
* "observation" for raw walkthrough findings (local or cloud). */
|
|
1848
|
-
kind:
|
|
1849
|
-
severity:
|
|
1850
|
-
triage_status:
|
|
1908
|
+
kind: z22.enum(["canonical", "observation"]),
|
|
1909
|
+
severity: z22.enum(["critical", "major", "minor", "observation"]).nullable().describe("Effective severity. Null when not yet assigned."),
|
|
1910
|
+
triage_status: z22.string().describe("open | addressed | dismissed"),
|
|
1851
1911
|
/** First 200 chars of the finding description. Fetch get_finding for the full text. */
|
|
1852
|
-
description:
|
|
1853
|
-
walkthrough_id:
|
|
1854
|
-
scenario_id:
|
|
1912
|
+
description: z22.string(),
|
|
1913
|
+
walkthrough_id: z22.string().nullable(),
|
|
1914
|
+
scenario_id: z22.string(),
|
|
1855
1915
|
created_at: isoTimestamp,
|
|
1856
|
-
canonical_id:
|
|
1857
|
-
cloud_mirrored:
|
|
1916
|
+
canonical_id: z22.string().nullable(),
|
|
1917
|
+
cloud_mirrored: z22.boolean()
|
|
1858
1918
|
});
|
|
1859
|
-
ScenarioSummarySchema =
|
|
1860
|
-
id:
|
|
1861
|
-
slug:
|
|
1862
|
-
outline_id:
|
|
1863
|
-
outline_slug:
|
|
1864
|
-
persona_id:
|
|
1865
|
-
persona_slug:
|
|
1919
|
+
ScenarioSummarySchema = z22.object({
|
|
1920
|
+
id: z22.string(),
|
|
1921
|
+
slug: z22.string().nullable(),
|
|
1922
|
+
outline_id: z22.string(),
|
|
1923
|
+
outline_slug: z22.string().nullable(),
|
|
1924
|
+
persona_id: z22.string(),
|
|
1925
|
+
persona_slug: z22.string().nullable(),
|
|
1866
1926
|
created_at: isoTimestamp,
|
|
1867
|
-
baseline_score:
|
|
1868
|
-
current_score:
|
|
1869
|
-
target_score:
|
|
1870
|
-
walkthrough_count:
|
|
1871
|
-
latest_walkthrough_id:
|
|
1872
|
-
cloud_mirrored:
|
|
1927
|
+
baseline_score: z22.number().nullable(),
|
|
1928
|
+
current_score: z22.number().nullable(),
|
|
1929
|
+
target_score: z22.number().nullable(),
|
|
1930
|
+
walkthrough_count: z22.number().int().nonnegative(),
|
|
1931
|
+
latest_walkthrough_id: z22.string().nullable(),
|
|
1932
|
+
cloud_mirrored: z22.boolean()
|
|
1873
1933
|
});
|
|
1874
|
-
RetrievalGapSchema =
|
|
1875
|
-
type:
|
|
1876
|
-
query:
|
|
1877
|
-
suggestion:
|
|
1934
|
+
RetrievalGapSchema = z22.object({
|
|
1935
|
+
type: z22.enum(["no_results", "low_relevance", "unverified_only"]),
|
|
1936
|
+
query: z22.string(),
|
|
1937
|
+
suggestion: z22.string()
|
|
1878
1938
|
});
|
|
1879
|
-
GetConstraintsDataSchema =
|
|
1880
|
-
domain:
|
|
1881
|
-
constraint_count:
|
|
1882
|
-
constraints:
|
|
1883
|
-
rule:
|
|
1939
|
+
GetConstraintsDataSchema = z22.object({
|
|
1940
|
+
domain: z22.string(),
|
|
1941
|
+
constraint_count: z22.number().int().nonnegative(),
|
|
1942
|
+
constraints: z22.array(z22.object({
|
|
1943
|
+
rule: z22.string(),
|
|
1884
1944
|
authority_level: AuthorityLevelSchema,
|
|
1885
|
-
source_name:
|
|
1886
|
-
source_section:
|
|
1887
|
-
source_url:
|
|
1888
|
-
source_version:
|
|
1889
|
-
source_uri:
|
|
1945
|
+
source_name: z22.string(),
|
|
1946
|
+
source_section: z22.string(),
|
|
1947
|
+
source_url: z22.string().nullable(),
|
|
1948
|
+
source_version: z22.number(),
|
|
1949
|
+
source_uri: z22.string().describe("iamu://source/<id>@v<version>")
|
|
1890
1950
|
})),
|
|
1891
|
-
gaps:
|
|
1892
|
-
context_hint_needed:
|
|
1951
|
+
gaps: z22.array(RetrievalGapSchema).optional(),
|
|
1952
|
+
context_hint_needed: z22.boolean()
|
|
1893
1953
|
});
|
|
1894
1954
|
GetConstraintsOutputSchema = mcpEnvelopeSchema(GetConstraintsDataSchema);
|
|
1895
|
-
QueryDataSchema =
|
|
1896
|
-
results:
|
|
1897
|
-
chunk_id:
|
|
1898
|
-
content:
|
|
1899
|
-
context_header:
|
|
1900
|
-
context_text:
|
|
1955
|
+
QueryDataSchema = z22.object({
|
|
1956
|
+
results: z22.array(z22.object({
|
|
1957
|
+
chunk_id: z22.string(),
|
|
1958
|
+
content: z22.string(),
|
|
1959
|
+
context_header: z22.string(),
|
|
1960
|
+
context_text: z22.string().nullable(),
|
|
1901
1961
|
authority_level: AuthorityLevelSchema,
|
|
1902
|
-
source_name:
|
|
1903
|
-
source_id:
|
|
1904
|
-
source_uri:
|
|
1905
|
-
source_version:
|
|
1906
|
-
score:
|
|
1907
|
-
verified:
|
|
1908
|
-
trust:
|
|
1962
|
+
source_name: z22.string(),
|
|
1963
|
+
source_id: z22.string(),
|
|
1964
|
+
source_uri: z22.string(),
|
|
1965
|
+
source_version: z22.number(),
|
|
1966
|
+
score: z22.number(),
|
|
1967
|
+
verified: z22.boolean(),
|
|
1968
|
+
trust: z22.enum(["hard", "soft", "unknown"])
|
|
1909
1969
|
})),
|
|
1910
|
-
result_count:
|
|
1911
|
-
query_time_ms:
|
|
1912
|
-
gaps:
|
|
1913
|
-
context_hint_needed:
|
|
1970
|
+
result_count: z22.number().int().nonnegative(),
|
|
1971
|
+
query_time_ms: z22.number().int().nonnegative().optional(),
|
|
1972
|
+
gaps: z22.array(RetrievalGapSchema).optional(),
|
|
1973
|
+
context_hint_needed: z22.boolean()
|
|
1914
1974
|
});
|
|
1915
1975
|
QueryOutputSchema = mcpEnvelopeSchema(QueryDataSchema);
|
|
1916
|
-
ListFindingsDataSchema =
|
|
1917
|
-
findings:
|
|
1918
|
-
total_returned:
|
|
1976
|
+
ListFindingsDataSchema = z22.object({
|
|
1977
|
+
findings: z22.array(FindingSummarySchema),
|
|
1978
|
+
total_returned: z22.number().int().nonnegative()
|
|
1919
1979
|
});
|
|
1920
1980
|
ListFindingsOutputSchema = mcpEnvelopeSchema(ListFindingsDataSchema);
|
|
1921
|
-
ListScenariosDataSchema =
|
|
1922
|
-
scenarios:
|
|
1981
|
+
ListScenariosDataSchema = z22.object({
|
|
1982
|
+
scenarios: z22.array(ScenarioSummarySchema)
|
|
1923
1983
|
});
|
|
1924
1984
|
ListScenariosOutputSchema = mcpEnvelopeSchema(ListScenariosDataSchema);
|
|
1925
|
-
GetProjectDataSchema =
|
|
1926
|
-
id:
|
|
1927
|
-
slug:
|
|
1928
|
-
name:
|
|
1929
|
-
cloud_linked:
|
|
1930
|
-
cloud_project_id:
|
|
1985
|
+
GetProjectDataSchema = z22.object({
|
|
1986
|
+
id: z22.string(),
|
|
1987
|
+
slug: z22.string().nullable(),
|
|
1988
|
+
name: z22.string(),
|
|
1989
|
+
cloud_linked: z22.boolean(),
|
|
1990
|
+
cloud_project_id: z22.string().nullable(),
|
|
1931
1991
|
created_at: isoTimestamp.nullable(),
|
|
1932
|
-
capabilities_count:
|
|
1933
|
-
outlines_count:
|
|
1934
|
-
scenarios_count:
|
|
1935
|
-
walkthroughs_count:
|
|
1936
|
-
personas_count:
|
|
1992
|
+
capabilities_count: z22.number().int().nonnegative(),
|
|
1993
|
+
outlines_count: z22.number().int().nonnegative(),
|
|
1994
|
+
scenarios_count: z22.number().int().nonnegative(),
|
|
1995
|
+
walkthroughs_count: z22.number().int().nonnegative(),
|
|
1996
|
+
personas_count: z22.number().int().nonnegative()
|
|
1937
1997
|
});
|
|
1938
1998
|
GetProjectOutputSchema = mcpEnvelopeSchema(GetProjectDataSchema);
|
|
1939
|
-
CreateScenarioDataSchema =
|
|
1940
|
-
scenario_id:
|
|
1941
|
-
outline_id:
|
|
1942
|
-
persona_id:
|
|
1943
|
-
was_existing:
|
|
1999
|
+
CreateScenarioDataSchema = z22.object({
|
|
2000
|
+
scenario_id: z22.string(),
|
|
2001
|
+
outline_id: z22.string(),
|
|
2002
|
+
persona_id: z22.string(),
|
|
2003
|
+
was_existing: z22.boolean(),
|
|
1944
2004
|
created_at: isoTimestamp,
|
|
1945
2005
|
brief_generated_at: isoTimestamp.nullable()
|
|
1946
2006
|
});
|
|
1947
2007
|
CreateScenarioOutputSchema = mcpEnvelopeSchema(CreateScenarioDataSchema);
|
|
1948
|
-
PrepareWalkthroughDataSchema =
|
|
1949
|
-
walkthrough_id:
|
|
1950
|
-
scenario_id:
|
|
1951
|
-
target_url:
|
|
1952
|
-
lenses:
|
|
1953
|
-
persona:
|
|
1954
|
-
id:
|
|
1955
|
-
name:
|
|
1956
|
-
slug:
|
|
2008
|
+
PrepareWalkthroughDataSchema = z22.object({
|
|
2009
|
+
walkthrough_id: z22.string(),
|
|
2010
|
+
scenario_id: z22.string(),
|
|
2011
|
+
target_url: z22.string(),
|
|
2012
|
+
lenses: z22.array(z22.string()),
|
|
2013
|
+
persona: z22.object({
|
|
2014
|
+
id: z22.string(),
|
|
2015
|
+
name: z22.string(),
|
|
2016
|
+
slug: z22.string().nullable()
|
|
1957
2017
|
}),
|
|
1958
|
-
outline:
|
|
1959
|
-
id:
|
|
1960
|
-
slug:
|
|
1961
|
-
title:
|
|
2018
|
+
outline: z22.object({
|
|
2019
|
+
id: z22.string(),
|
|
2020
|
+
slug: z22.string().nullable(),
|
|
2021
|
+
title: z22.string()
|
|
1962
2022
|
}),
|
|
1963
|
-
mode:
|
|
1964
|
-
cloud_mirrored:
|
|
2023
|
+
mode: z22.enum(["local", "cloud"]),
|
|
2024
|
+
cloud_mirrored: z22.boolean(),
|
|
1965
2025
|
mirror_status: MirrorStatusSchema,
|
|
1966
|
-
run_dir:
|
|
2026
|
+
run_dir: z22.string().nullable(),
|
|
1967
2027
|
/** Persona-specific first-person brief — markdown body of the scenario file. */
|
|
1968
|
-
brief:
|
|
2028
|
+
brief: z22.string(),
|
|
1969
2029
|
/** Full composed walking prompt: persona + outline + lenses +
|
|
1970
2030
|
* evaluation philosophy. This is the text the walker should adopt
|
|
1971
2031
|
* before driving the browser; `brief` alone lacks the philosophy
|
|
1972
2032
|
* + lens guidance. */
|
|
1973
|
-
prompt_text:
|
|
2033
|
+
prompt_text: z22.string(),
|
|
1974
2034
|
/** Withheld during walker stage (always empty here). Populated by
|
|
1975
2035
|
* `get_judge_input` once the walk completes. */
|
|
1976
|
-
human_tests:
|
|
2036
|
+
human_tests: z22.array(z22.string())
|
|
1977
2037
|
});
|
|
1978
2038
|
PrepareWalkthroughOutputSchema = mcpEnvelopeSchema(PrepareWalkthroughDataSchema);
|
|
1979
|
-
PersonaSummarySchema =
|
|
1980
|
-
id:
|
|
1981
|
-
slug:
|
|
1982
|
-
name:
|
|
1983
|
-
role:
|
|
2039
|
+
PersonaSummarySchema = z22.object({
|
|
2040
|
+
id: z22.string(),
|
|
2041
|
+
slug: z22.string(),
|
|
2042
|
+
name: z22.string(),
|
|
2043
|
+
role: z22.string(),
|
|
1984
2044
|
/** First 200 chars of context/background. */
|
|
1985
|
-
context_preview:
|
|
1986
|
-
status:
|
|
2045
|
+
context_preview: z22.string().nullable(),
|
|
2046
|
+
status: z22.enum(["active", "archived"]),
|
|
1987
2047
|
created_at: isoTimestamp,
|
|
1988
|
-
cloud_mirrored:
|
|
2048
|
+
cloud_mirrored: z22.boolean()
|
|
1989
2049
|
});
|
|
1990
|
-
OutlineSummarySchema =
|
|
1991
|
-
id:
|
|
1992
|
-
slug:
|
|
1993
|
-
name:
|
|
1994
|
-
description:
|
|
1995
|
-
primary_capability_id:
|
|
1996
|
-
primary_capability_slug:
|
|
2050
|
+
OutlineSummarySchema = z22.object({
|
|
2051
|
+
id: z22.string(),
|
|
2052
|
+
slug: z22.string(),
|
|
2053
|
+
name: z22.string(),
|
|
2054
|
+
description: z22.string().nullable(),
|
|
2055
|
+
primary_capability_id: z22.string().nullable(),
|
|
2056
|
+
primary_capability_slug: z22.string().nullable(),
|
|
1997
2057
|
/** Capability slugs (denormalized for agent display). */
|
|
1998
|
-
additional_capabilities:
|
|
1999
|
-
task_criticality:
|
|
2058
|
+
additional_capabilities: z22.array(z22.string()),
|
|
2059
|
+
task_criticality: z22.string().nullable(),
|
|
2000
2060
|
created_at: isoTimestamp,
|
|
2001
|
-
cloud_mirrored:
|
|
2061
|
+
cloud_mirrored: z22.boolean()
|
|
2002
2062
|
});
|
|
2003
|
-
CapabilitySummarySchema =
|
|
2004
|
-
id:
|
|
2005
|
-
slug:
|
|
2006
|
-
name:
|
|
2007
|
-
description:
|
|
2063
|
+
CapabilitySummarySchema = z22.object({
|
|
2064
|
+
id: z22.string(),
|
|
2065
|
+
slug: z22.string(),
|
|
2066
|
+
name: z22.string(),
|
|
2067
|
+
description: z22.string().nullable(),
|
|
2008
2068
|
/** Number of outlines with this capability as primary. Cloud-only;
|
|
2009
2069
|
* null in local mode (filesystem walk would be too expensive). */
|
|
2010
|
-
outline_count:
|
|
2070
|
+
outline_count: z22.number().int().nonnegative().nullable(),
|
|
2011
2071
|
created_at: isoTimestamp,
|
|
2012
|
-
cloud_mirrored:
|
|
2072
|
+
cloud_mirrored: z22.boolean()
|
|
2013
2073
|
});
|
|
2014
|
-
ListPersonasDataSchema =
|
|
2015
|
-
personas:
|
|
2074
|
+
ListPersonasDataSchema = z22.object({
|
|
2075
|
+
personas: z22.array(PersonaSummarySchema)
|
|
2016
2076
|
});
|
|
2017
2077
|
ListPersonasOutputSchema = mcpEnvelopeSchema(ListPersonasDataSchema);
|
|
2018
|
-
ListOutlinesDataSchema =
|
|
2019
|
-
outlines:
|
|
2078
|
+
ListOutlinesDataSchema = z22.object({
|
|
2079
|
+
outlines: z22.array(OutlineSummarySchema)
|
|
2020
2080
|
});
|
|
2021
2081
|
ListOutlinesOutputSchema = mcpEnvelopeSchema(ListOutlinesDataSchema);
|
|
2022
|
-
ListCapabilitiesDataSchema =
|
|
2023
|
-
capabilities:
|
|
2082
|
+
ListCapabilitiesDataSchema = z22.object({
|
|
2083
|
+
capabilities: z22.array(CapabilitySummarySchema)
|
|
2024
2084
|
});
|
|
2025
2085
|
ListCapabilitiesOutputSchema = mcpEnvelopeSchema(ListCapabilitiesDataSchema);
|
|
2026
|
-
GetPersonaDataSchema =
|
|
2027
|
-
id:
|
|
2028
|
-
slug:
|
|
2029
|
-
name:
|
|
2030
|
-
role:
|
|
2031
|
-
context:
|
|
2032
|
-
disposition:
|
|
2033
|
-
brief:
|
|
2034
|
-
status:
|
|
2035
|
-
body:
|
|
2086
|
+
GetPersonaDataSchema = z22.object({
|
|
2087
|
+
id: z22.string(),
|
|
2088
|
+
slug: z22.string(),
|
|
2089
|
+
name: z22.string(),
|
|
2090
|
+
role: z22.string(),
|
|
2091
|
+
context: z22.string().nullable(),
|
|
2092
|
+
disposition: z22.string().nullable(),
|
|
2093
|
+
brief: z22.string().nullable(),
|
|
2094
|
+
status: z22.enum(["active", "archived"]),
|
|
2095
|
+
body: z22.string(),
|
|
2036
2096
|
created_at: isoTimestamp,
|
|
2037
2097
|
updated_at: isoTimestamp.nullable(),
|
|
2038
|
-
cloud_mirrored:
|
|
2039
|
-
resource_uri:
|
|
2098
|
+
cloud_mirrored: z22.boolean(),
|
|
2099
|
+
resource_uri: z22.string()
|
|
2040
2100
|
});
|
|
2041
2101
|
GetPersonaOutputSchema = mcpEnvelopeSchema(GetPersonaDataSchema);
|
|
2042
|
-
GetOutlineDataSchema =
|
|
2043
|
-
id:
|
|
2044
|
-
slug:
|
|
2045
|
-
name:
|
|
2046
|
-
description:
|
|
2047
|
-
narrative:
|
|
2048
|
-
primary_capability_id:
|
|
2049
|
-
primary_capability_slug:
|
|
2050
|
-
additional_capabilities:
|
|
2051
|
-
human_tests:
|
|
2052
|
-
tension:
|
|
2053
|
-
situation_roles:
|
|
2054
|
-
task_criticality:
|
|
2055
|
-
complexity_level:
|
|
2102
|
+
GetOutlineDataSchema = z22.object({
|
|
2103
|
+
id: z22.string(),
|
|
2104
|
+
slug: z22.string(),
|
|
2105
|
+
name: z22.string(),
|
|
2106
|
+
description: z22.string().nullable(),
|
|
2107
|
+
narrative: z22.string(),
|
|
2108
|
+
primary_capability_id: z22.string().nullable(),
|
|
2109
|
+
primary_capability_slug: z22.string().nullable(),
|
|
2110
|
+
additional_capabilities: z22.array(z22.string()),
|
|
2111
|
+
human_tests: z22.array(z22.object({ id: z22.string(), question: z22.string() })),
|
|
2112
|
+
tension: z22.string().nullable(),
|
|
2113
|
+
situation_roles: z22.array(z22.object({ role: z22.string(), stake: z22.string() })).nullable(),
|
|
2114
|
+
task_criticality: z22.string().nullable(),
|
|
2115
|
+
complexity_level: z22.string().nullable(),
|
|
2056
2116
|
created_at: isoTimestamp,
|
|
2057
2117
|
updated_at: isoTimestamp.nullable(),
|
|
2058
|
-
cloud_mirrored:
|
|
2059
|
-
resource_uri:
|
|
2118
|
+
cloud_mirrored: z22.boolean(),
|
|
2119
|
+
resource_uri: z22.string()
|
|
2060
2120
|
});
|
|
2061
2121
|
GetOutlineOutputSchema = mcpEnvelopeSchema(GetOutlineDataSchema);
|
|
2062
|
-
GetFindingDataSchema =
|
|
2063
|
-
id:
|
|
2064
|
-
slug:
|
|
2065
|
-
title:
|
|
2122
|
+
GetFindingDataSchema = z22.object({
|
|
2123
|
+
id: z22.string(),
|
|
2124
|
+
slug: z22.string().nullable(),
|
|
2125
|
+
title: z22.string().nullable(),
|
|
2066
2126
|
type: FindingTypeSchema,
|
|
2067
|
-
severity:
|
|
2068
|
-
kind:
|
|
2069
|
-
ui_fact:
|
|
2070
|
-
consequence:
|
|
2071
|
-
description:
|
|
2072
|
-
citations:
|
|
2073
|
-
walkthrough_id:
|
|
2074
|
-
scenario_id:
|
|
2075
|
-
persona_id:
|
|
2076
|
-
run:
|
|
2077
|
-
triage_status:
|
|
2078
|
-
triage_note:
|
|
2079
|
-
fix_status:
|
|
2080
|
-
lens:
|
|
2081
|
-
compliance_impact:
|
|
2082
|
-
task_impact:
|
|
2083
|
-
confidence:
|
|
2084
|
-
regulatory_weight:
|
|
2085
|
-
human_test_id:
|
|
2086
|
-
walkthrough_step_id:
|
|
2087
|
-
canonical_id:
|
|
2127
|
+
severity: z22.enum(["critical", "major", "minor", "observation"]).nullable(),
|
|
2128
|
+
kind: z22.enum(["canonical", "observation"]),
|
|
2129
|
+
ui_fact: z22.string().nullable(),
|
|
2130
|
+
consequence: z22.string().nullable(),
|
|
2131
|
+
description: z22.string().nullable(),
|
|
2132
|
+
citations: z22.array(z22.string()),
|
|
2133
|
+
walkthrough_id: z22.string().nullable(),
|
|
2134
|
+
scenario_id: z22.string(),
|
|
2135
|
+
persona_id: z22.string().nullable(),
|
|
2136
|
+
run: z22.string().nullable(),
|
|
2137
|
+
triage_status: z22.string(),
|
|
2138
|
+
triage_note: z22.string().nullable(),
|
|
2139
|
+
fix_status: z22.string(),
|
|
2140
|
+
lens: z22.string().nullable(),
|
|
2141
|
+
compliance_impact: z22.string().nullable(),
|
|
2142
|
+
task_impact: z22.string().nullable(),
|
|
2143
|
+
confidence: z22.string().nullable(),
|
|
2144
|
+
regulatory_weight: z22.string().nullable(),
|
|
2145
|
+
human_test_id: z22.string().nullable(),
|
|
2146
|
+
walkthrough_step_id: z22.string().nullable(),
|
|
2147
|
+
canonical_id: z22.string().nullable(),
|
|
2088
2148
|
recorded_at: isoTimestamp.nullable(),
|
|
2089
2149
|
updated_at: isoTimestamp.nullable(),
|
|
2090
|
-
cloud_mirrored:
|
|
2150
|
+
cloud_mirrored: z22.boolean(),
|
|
2091
2151
|
mirror_status: MirrorStatusSchema,
|
|
2092
|
-
resource_uri:
|
|
2152
|
+
resource_uri: z22.string()
|
|
2093
2153
|
});
|
|
2094
2154
|
GetFindingOutputSchema = mcpEnvelopeSchema(GetFindingDataSchema);
|
|
2095
|
-
CreatePersonaDataSchema =
|
|
2096
|
-
persona_id:
|
|
2097
|
-
slug:
|
|
2098
|
-
was_existing:
|
|
2155
|
+
CreatePersonaDataSchema = z22.object({
|
|
2156
|
+
persona_id: z22.string(),
|
|
2157
|
+
slug: z22.string(),
|
|
2158
|
+
was_existing: z22.boolean(),
|
|
2099
2159
|
created_at: isoTimestamp,
|
|
2100
2160
|
brief_generated_at: isoTimestamp.nullable()
|
|
2101
2161
|
});
|
|
2102
2162
|
CreatePersonaOutputSchema = mcpEnvelopeSchema(CreatePersonaDataSchema);
|
|
2103
|
-
CreateOutlineDataSchema =
|
|
2104
|
-
outline_id:
|
|
2105
|
-
slug:
|
|
2106
|
-
primary_capability_id:
|
|
2107
|
-
primary_capability_slug:
|
|
2108
|
-
was_existing:
|
|
2163
|
+
CreateOutlineDataSchema = z22.object({
|
|
2164
|
+
outline_id: z22.string(),
|
|
2165
|
+
slug: z22.string(),
|
|
2166
|
+
primary_capability_id: z22.string().nullable(),
|
|
2167
|
+
primary_capability_slug: z22.string().nullable(),
|
|
2168
|
+
was_existing: z22.boolean(),
|
|
2109
2169
|
created_at: isoTimestamp
|
|
2110
2170
|
});
|
|
2111
2171
|
CreateOutlineOutputSchema = mcpEnvelopeSchema(CreateOutlineDataSchema);
|
|
2112
|
-
CreateCapabilityDataSchema =
|
|
2113
|
-
capability_id:
|
|
2114
|
-
slug:
|
|
2115
|
-
was_existing:
|
|
2172
|
+
CreateCapabilityDataSchema = z22.object({
|
|
2173
|
+
capability_id: z22.string(),
|
|
2174
|
+
slug: z22.string(),
|
|
2175
|
+
was_existing: z22.boolean(),
|
|
2116
2176
|
created_at: isoTimestamp
|
|
2117
2177
|
});
|
|
2118
2178
|
CreateCapabilityOutputSchema = mcpEnvelopeSchema(CreateCapabilityDataSchema);
|
|
2119
|
-
RecordStepDataSchema =
|
|
2120
|
-
step_id:
|
|
2121
|
-
step_index:
|
|
2122
|
-
walkthrough_id:
|
|
2123
|
-
persona_reasoning:
|
|
2179
|
+
RecordStepDataSchema = z22.object({
|
|
2180
|
+
step_id: z22.string(),
|
|
2181
|
+
step_index: z22.number().int().nonnegative(),
|
|
2182
|
+
walkthrough_id: z22.string(),
|
|
2183
|
+
persona_reasoning: z22.string(),
|
|
2124
2184
|
recorded_at: isoTimestamp,
|
|
2125
2185
|
/** Set when a screenshot_path was provided. */
|
|
2126
|
-
screenshot_uri:
|
|
2186
|
+
screenshot_uri: z22.string().nullable(),
|
|
2127
2187
|
/** Capture failure modes (per-field) — see fingerprint shape in
|
|
2128
2188
|
* `./types/fingerprint.ts`. Optional; null
|
|
2129
2189
|
* when fingerprint capture didn't run. */
|
|
2130
|
-
fingerprint: stepFingerprintSchema.or(
|
|
2131
|
-
dom_hash:
|
|
2132
|
-
ax_hash:
|
|
2133
|
-
screenshot_hash:
|
|
2134
|
-
url_template:
|
|
2190
|
+
fingerprint: stepFingerprintSchema.or(z22.object({
|
|
2191
|
+
dom_hash: z22.string().nullable(),
|
|
2192
|
+
ax_hash: z22.string().nullable(),
|
|
2193
|
+
screenshot_hash: z22.string().nullable(),
|
|
2194
|
+
url_template: z22.string().nullable()
|
|
2135
2195
|
})).nullable()
|
|
2136
2196
|
});
|
|
2137
2197
|
RecordStepOutputSchema = mcpEnvelopeSchema(RecordStepDataSchema);
|
|
2138
|
-
RecordFindingDataSchema =
|
|
2139
|
-
finding_id:
|
|
2140
|
-
slug:
|
|
2198
|
+
RecordFindingDataSchema = z22.object({
|
|
2199
|
+
finding_id: z22.string(),
|
|
2200
|
+
slug: z22.string().nullable(),
|
|
2141
2201
|
type: FindingTypeSchema,
|
|
2142
|
-
severity:
|
|
2143
|
-
kind:
|
|
2144
|
-
ui_fact:
|
|
2145
|
-
consequence:
|
|
2146
|
-
citations:
|
|
2147
|
-
scenario_id:
|
|
2148
|
-
walkthrough_id:
|
|
2149
|
-
persona_id:
|
|
2150
|
-
triage_status:
|
|
2151
|
-
fix_status:
|
|
2152
|
-
lens:
|
|
2202
|
+
severity: z22.enum(["critical", "major", "minor", "observation"]).nullable(),
|
|
2203
|
+
kind: z22.literal("observation"),
|
|
2204
|
+
ui_fact: z22.string(),
|
|
2205
|
+
consequence: z22.string(),
|
|
2206
|
+
citations: z22.array(z22.string()),
|
|
2207
|
+
scenario_id: z22.string(),
|
|
2208
|
+
walkthrough_id: z22.string(),
|
|
2209
|
+
persona_id: z22.string().nullable(),
|
|
2210
|
+
triage_status: z22.literal("open"),
|
|
2211
|
+
fix_status: z22.literal("open"),
|
|
2212
|
+
lens: z22.string().nullable(),
|
|
2153
2213
|
recorded_at: isoTimestamp,
|
|
2154
|
-
resource_uri:
|
|
2214
|
+
resource_uri: z22.string()
|
|
2155
2215
|
});
|
|
2156
2216
|
RecordFindingOutputSchema = mcpEnvelopeSchema(RecordFindingDataSchema);
|
|
2157
2217
|
CompleteWalkthroughDataSchema = canonicalWalkthroughSchema;
|
|
2158
2218
|
CompleteWalkthroughOutputSchema = mcpEnvelopeSchema(CompleteWalkthroughDataSchema);
|
|
2159
|
-
GetJudgeInputDataSchema =
|
|
2160
|
-
walkthrough_id:
|
|
2161
|
-
judge_prompt:
|
|
2162
|
-
id:
|
|
2163
|
-
version:
|
|
2164
|
-
text:
|
|
2219
|
+
GetJudgeInputDataSchema = z22.object({
|
|
2220
|
+
walkthrough_id: z22.string(),
|
|
2221
|
+
judge_prompt: z22.object({
|
|
2222
|
+
id: z22.string(),
|
|
2223
|
+
version: z22.string(),
|
|
2224
|
+
text: z22.string()
|
|
2165
2225
|
}),
|
|
2166
|
-
scenario:
|
|
2167
|
-
outline_context:
|
|
2168
|
-
steps:
|
|
2169
|
-
findings:
|
|
2170
|
-
human_tests:
|
|
2171
|
-
id:
|
|
2172
|
-
question:
|
|
2226
|
+
scenario: z22.object({}).passthrough(),
|
|
2227
|
+
outline_context: z22.object({}).passthrough(),
|
|
2228
|
+
steps: z22.array(z22.unknown()),
|
|
2229
|
+
findings: z22.array(z22.unknown()),
|
|
2230
|
+
human_tests: z22.array(z22.object({
|
|
2231
|
+
id: z22.string(),
|
|
2232
|
+
question: z22.string()
|
|
2173
2233
|
}))
|
|
2174
2234
|
});
|
|
2175
2235
|
GetJudgeInputOutputSchema = mcpEnvelopeSchema(GetJudgeInputDataSchema);
|
|
2176
|
-
RecordJudgeResultDataSchema =
|
|
2177
|
-
walkthrough_id:
|
|
2236
|
+
RecordJudgeResultDataSchema = z22.object({
|
|
2237
|
+
walkthrough_id: z22.string(),
|
|
2178
2238
|
persisted_at: isoTimestamp,
|
|
2179
|
-
canonical_path:
|
|
2180
|
-
report_path:
|
|
2239
|
+
canonical_path: z22.string(),
|
|
2240
|
+
report_path: z22.string()
|
|
2181
2241
|
});
|
|
2182
2242
|
RecordJudgeResultOutputSchema = mcpEnvelopeSchema(RecordJudgeResultDataSchema);
|
|
2183
2243
|
}
|
|
@@ -2350,6 +2410,9 @@ function configPath(projectRoot) {
|
|
|
2350
2410
|
function contextPath(projectRoot) {
|
|
2351
2411
|
return path2.join(iamuDir(projectRoot), "context.yml");
|
|
2352
2412
|
}
|
|
2413
|
+
function testabilityPath(projectRoot) {
|
|
2414
|
+
return path2.join(iamuDir(projectRoot), "testability.md");
|
|
2415
|
+
}
|
|
2353
2416
|
function entityDirPath(projectRoot, type2) {
|
|
2354
2417
|
return path2.join(iamuDir(projectRoot), ENTITY_DIRS[type2]);
|
|
2355
2418
|
}
|
|
@@ -5293,6 +5356,37 @@ var init_context2 = __esm({
|
|
|
5293
5356
|
}
|
|
5294
5357
|
});
|
|
5295
5358
|
|
|
5359
|
+
// ../../packages/local-store/dist/testability.js
|
|
5360
|
+
import { promises as fs5 } from "fs";
|
|
5361
|
+
async function readTestability(projectRoot) {
|
|
5362
|
+
const p = testabilityPath(projectRoot);
|
|
5363
|
+
let raw;
|
|
5364
|
+
try {
|
|
5365
|
+
raw = await fs5.readFile(p, "utf8");
|
|
5366
|
+
} catch (err) {
|
|
5367
|
+
if (err.code === "ENOENT")
|
|
5368
|
+
return null;
|
|
5369
|
+
throw err;
|
|
5370
|
+
}
|
|
5371
|
+
const parsed = parseFrontmatter(raw);
|
|
5372
|
+
const result = testabilityFrontmatterSchema.safeParse(parsed.frontmatter);
|
|
5373
|
+
if (!result.success) {
|
|
5374
|
+
throw new Error(`testability: invalid frontmatter in ${p}: ${result.error.issues.map((i) => `${i.path.join(".") || "root"}: ${i.message}`).join("; ")}`);
|
|
5375
|
+
}
|
|
5376
|
+
return {
|
|
5377
|
+
frontmatter: result.data,
|
|
5378
|
+
body: parsed.body
|
|
5379
|
+
};
|
|
5380
|
+
}
|
|
5381
|
+
var init_testability2 = __esm({
|
|
5382
|
+
"../../packages/local-store/dist/testability.js"() {
|
|
5383
|
+
"use strict";
|
|
5384
|
+
init_dist();
|
|
5385
|
+
init_markdown();
|
|
5386
|
+
init_paths();
|
|
5387
|
+
}
|
|
5388
|
+
});
|
|
5389
|
+
|
|
5296
5390
|
// ../../packages/local-store/dist/hash.js
|
|
5297
5391
|
import { createHash } from "crypto";
|
|
5298
5392
|
function hashNormalizedContent(raw) {
|
|
@@ -5326,7 +5420,7 @@ var init_server_reason = __esm({
|
|
|
5326
5420
|
|
|
5327
5421
|
// ../../packages/local-store/dist/file-lock.js
|
|
5328
5422
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
5329
|
-
import { promises as
|
|
5423
|
+
import { promises as fs6 } from "fs";
|
|
5330
5424
|
import os from "os";
|
|
5331
5425
|
import path4 from "path";
|
|
5332
5426
|
function takeoverFilePathFor(lockPath) {
|
|
@@ -5363,7 +5457,7 @@ function pidIsDead(rec) {
|
|
|
5363
5457
|
async function isStale(lockPath, rec, staleMs, now) {
|
|
5364
5458
|
if (rec === null) {
|
|
5365
5459
|
try {
|
|
5366
|
-
const stat3 = await
|
|
5460
|
+
const stat3 = await fs6.stat(lockPath);
|
|
5367
5461
|
if (stat3.size === 0) {
|
|
5368
5462
|
const mtime = stat3.birthtimeMs && stat3.birthtimeMs > 0 ? stat3.birthtimeMs : stat3.mtimeMs;
|
|
5369
5463
|
if (now - mtime <= staleMs) {
|
|
@@ -5388,7 +5482,7 @@ async function tryCreateMarker(markerPath, token) {
|
|
|
5388
5482
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5389
5483
|
};
|
|
5390
5484
|
try {
|
|
5391
|
-
const handle = await
|
|
5485
|
+
const handle = await fs6.open(markerPath, "wx", 420);
|
|
5392
5486
|
try {
|
|
5393
5487
|
await handle.writeFile(JSON.stringify(record));
|
|
5394
5488
|
await handle.sync();
|
|
@@ -5407,7 +5501,7 @@ async function tryCreateLock(lockPath, token) {
|
|
|
5407
5501
|
}
|
|
5408
5502
|
async function readRecord(markerPath) {
|
|
5409
5503
|
try {
|
|
5410
|
-
return parseLockRecord(await
|
|
5504
|
+
return parseLockRecord(await fs6.readFile(markerPath, "utf8"));
|
|
5411
5505
|
} catch {
|
|
5412
5506
|
return null;
|
|
5413
5507
|
}
|
|
@@ -5417,7 +5511,7 @@ async function tryTakeover(lockPath, token, expected, opts) {
|
|
|
5417
5511
|
if (!await tryCreateMarker(takeoverPath, token)) {
|
|
5418
5512
|
const holder = await readRecord(takeoverPath);
|
|
5419
5513
|
if (await isStale(takeoverPath, holder, opts.staleMs, opts.now())) {
|
|
5420
|
-
await
|
|
5514
|
+
await fs6.unlink(takeoverPath).catch(() => {
|
|
5421
5515
|
});
|
|
5422
5516
|
}
|
|
5423
5517
|
return null;
|
|
@@ -5426,7 +5520,7 @@ async function tryTakeover(lockPath, token, expected, opts) {
|
|
|
5426
5520
|
const current = await readRecord(lockPath);
|
|
5427
5521
|
let present = true;
|
|
5428
5522
|
try {
|
|
5429
|
-
await
|
|
5523
|
+
await fs6.access(lockPath);
|
|
5430
5524
|
} catch {
|
|
5431
5525
|
present = false;
|
|
5432
5526
|
}
|
|
@@ -5437,11 +5531,11 @@ async function tryTakeover(lockPath, token, expected, opts) {
|
|
|
5437
5531
|
return null;
|
|
5438
5532
|
if (!await isStale(lockPath, current, opts.staleMs, opts.now()))
|
|
5439
5533
|
return null;
|
|
5440
|
-
await
|
|
5534
|
+
await fs6.unlink(lockPath).catch(() => {
|
|
5441
5535
|
});
|
|
5442
5536
|
return await tryCreateLock(lockPath, token);
|
|
5443
5537
|
} finally {
|
|
5444
|
-
await
|
|
5538
|
+
await fs6.unlink(takeoverPath).catch(() => {
|
|
5445
5539
|
});
|
|
5446
5540
|
}
|
|
5447
5541
|
}
|
|
@@ -5458,13 +5552,13 @@ async function acquireLockFile(lockPath, opts) {
|
|
|
5458
5552
|
const token = randomUUID3();
|
|
5459
5553
|
const deadline = opts.now() + opts.timeoutMs;
|
|
5460
5554
|
let lastHolderPid;
|
|
5461
|
-
await
|
|
5555
|
+
await fs6.mkdir(path4.dirname(lockPath), { recursive: true });
|
|
5462
5556
|
for (; ; ) {
|
|
5463
5557
|
if (await tryCreateLock(lockPath, token))
|
|
5464
5558
|
return token;
|
|
5465
5559
|
let raw = null;
|
|
5466
5560
|
try {
|
|
5467
|
-
raw = await
|
|
5561
|
+
raw = await fs6.readFile(lockPath, "utf8");
|
|
5468
5562
|
} catch (err) {
|
|
5469
5563
|
if (err.code === "ENOENT")
|
|
5470
5564
|
continue;
|
|
@@ -5491,13 +5585,13 @@ async function acquireLockFile(lockPath, opts) {
|
|
|
5491
5585
|
}
|
|
5492
5586
|
async function releaseLockFile(lockPath, token) {
|
|
5493
5587
|
try {
|
|
5494
|
-
const rec = parseLockRecord(await
|
|
5588
|
+
const rec = parseLockRecord(await fs6.readFile(lockPath, "utf8"));
|
|
5495
5589
|
if (rec?.token !== token)
|
|
5496
5590
|
return;
|
|
5497
|
-
const recheck = parseLockRecord(await
|
|
5591
|
+
const recheck = parseLockRecord(await fs6.readFile(lockPath, "utf8"));
|
|
5498
5592
|
if (recheck?.token !== token)
|
|
5499
5593
|
return;
|
|
5500
|
-
await
|
|
5594
|
+
await fs6.unlink(lockPath);
|
|
5501
5595
|
} catch {
|
|
5502
5596
|
}
|
|
5503
5597
|
}
|
|
@@ -5566,10 +5660,10 @@ var init_file_lock = __esm({
|
|
|
5566
5660
|
});
|
|
5567
5661
|
|
|
5568
5662
|
// ../../packages/local-store/dist/sync-tracking.js
|
|
5569
|
-
import { promises as
|
|
5663
|
+
import { promises as fs7 } from "fs";
|
|
5570
5664
|
async function readLastPush(projectRoot) {
|
|
5571
5665
|
try {
|
|
5572
|
-
const raw = await
|
|
5666
|
+
const raw = await fs7.readFile(lastPushPath(projectRoot), "utf8");
|
|
5573
5667
|
const parsed = JSON.parse(raw);
|
|
5574
5668
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
5575
5669
|
return parsed;
|
|
@@ -5616,7 +5710,7 @@ async function forgetLastPush(projectRoot, entityId) {
|
|
|
5616
5710
|
}
|
|
5617
5711
|
async function readCloudBase(projectRoot) {
|
|
5618
5712
|
try {
|
|
5619
|
-
const raw = await
|
|
5713
|
+
const raw = await fs7.readFile(cloudBasePath(projectRoot), "utf8");
|
|
5620
5714
|
const parsed = JSON.parse(raw);
|
|
5621
5715
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
5622
5716
|
return parsed;
|
|
@@ -5717,7 +5811,7 @@ function isRetryQueueEntry(value) {
|
|
|
5717
5811
|
async function readRetryQueueDetailed(projectRoot) {
|
|
5718
5812
|
let raw;
|
|
5719
5813
|
try {
|
|
5720
|
-
raw = await
|
|
5814
|
+
raw = await fs7.readFile(retryQueuePath(projectRoot), "utf8");
|
|
5721
5815
|
} catch (err) {
|
|
5722
5816
|
if (err.code === "ENOENT") {
|
|
5723
5817
|
return { entries: [], warnings: [], corruptedLines: [] };
|
|
@@ -5773,7 +5867,7 @@ function canonicalJsonString(val) {
|
|
|
5773
5867
|
async function readQueueAndPreserveCorrupted(projectRoot) {
|
|
5774
5868
|
const { entries, corruptedLines } = await readRetryQueueDetailed(projectRoot);
|
|
5775
5869
|
if (corruptedLines && corruptedLines.length > 0) {
|
|
5776
|
-
await
|
|
5870
|
+
await fs7.appendFile(retryQueueCorruptedPath(projectRoot), corruptedLines.map((l) => `${l}
|
|
5777
5871
|
`).join(""), "utf8");
|
|
5778
5872
|
}
|
|
5779
5873
|
return entries;
|
|
@@ -5823,7 +5917,7 @@ var init_sync_tracking = __esm({
|
|
|
5823
5917
|
});
|
|
5824
5918
|
|
|
5825
5919
|
// ../../packages/local-store/dist/entity.js
|
|
5826
|
-
import { promises as
|
|
5920
|
+
import { promises as fs8 } from "fs";
|
|
5827
5921
|
import path5 from "path";
|
|
5828
5922
|
async function resolveEntityPath(projectRoot, type2, slugOrUuid) {
|
|
5829
5923
|
const isSlug = slugSchema.safeParse(slugOrUuid).success;
|
|
@@ -5832,7 +5926,7 @@ async function resolveEntityPath(projectRoot, type2, slugOrUuid) {
|
|
|
5832
5926
|
return null;
|
|
5833
5927
|
const direct = entityFilePath(projectRoot, type2, slugOrUuid);
|
|
5834
5928
|
try {
|
|
5835
|
-
await
|
|
5929
|
+
await fs8.access(direct);
|
|
5836
5930
|
return direct;
|
|
5837
5931
|
} catch {
|
|
5838
5932
|
}
|
|
@@ -5841,7 +5935,7 @@ async function resolveEntityPath(projectRoot, type2, slugOrUuid) {
|
|
|
5841
5935
|
const dir = entityDirPath(projectRoot, type2);
|
|
5842
5936
|
let entries;
|
|
5843
5937
|
try {
|
|
5844
|
-
entries = await
|
|
5938
|
+
entries = await fs8.readdir(dir);
|
|
5845
5939
|
} catch {
|
|
5846
5940
|
return null;
|
|
5847
5941
|
}
|
|
@@ -5850,7 +5944,7 @@ async function resolveEntityPath(projectRoot, type2, slugOrUuid) {
|
|
|
5850
5944
|
continue;
|
|
5851
5945
|
const abs = path5.join(dir, name);
|
|
5852
5946
|
try {
|
|
5853
|
-
const raw = await
|
|
5947
|
+
const raw = await fs8.readFile(abs, "utf8");
|
|
5854
5948
|
const { frontmatter } = parseFrontmatter(raw);
|
|
5855
5949
|
if (typeof frontmatter.id === "string" && frontmatter.id.toLowerCase() === slugOrUuid.toLowerCase()) {
|
|
5856
5950
|
return abs;
|
|
@@ -5867,7 +5961,7 @@ async function readEntity(projectRoot, type2, slugOrUuid) {
|
|
|
5867
5961
|
const abs = await resolveEntityPath(projectRoot, type2, slugOrUuid);
|
|
5868
5962
|
if (!abs)
|
|
5869
5963
|
return null;
|
|
5870
|
-
const raw = await
|
|
5964
|
+
const raw = await fs8.readFile(abs, "utf8");
|
|
5871
5965
|
const { frontmatter, body } = parseFrontmatter(raw);
|
|
5872
5966
|
const schema2 = entityFrontmatterSchemas[type2];
|
|
5873
5967
|
const parsed = schema2.parse(frontmatter);
|
|
@@ -5895,7 +5989,7 @@ async function writeEntity(projectRoot, type2, frontmatter, body) {
|
|
|
5895
5989
|
}
|
|
5896
5990
|
async function entityExists(projectRoot, type2, slug) {
|
|
5897
5991
|
try {
|
|
5898
|
-
await
|
|
5992
|
+
await fs8.access(entityFilePath(projectRoot, type2, slug));
|
|
5899
5993
|
return true;
|
|
5900
5994
|
} catch {
|
|
5901
5995
|
return false;
|
|
@@ -5905,7 +5999,7 @@ async function listEntities(projectRoot, type2) {
|
|
|
5905
5999
|
const dir = entityDirPath(projectRoot, type2);
|
|
5906
6000
|
let names;
|
|
5907
6001
|
try {
|
|
5908
|
-
names = await
|
|
6002
|
+
names = await fs8.readdir(dir);
|
|
5909
6003
|
} catch (err) {
|
|
5910
6004
|
if (err.code === "ENOENT") {
|
|
5911
6005
|
return { entities: [], warnings: [] };
|
|
@@ -5920,7 +6014,7 @@ async function listEntities(projectRoot, type2) {
|
|
|
5920
6014
|
continue;
|
|
5921
6015
|
const abs = path5.join(dir, name);
|
|
5922
6016
|
try {
|
|
5923
|
-
const raw = await
|
|
6017
|
+
const raw = await fs8.readFile(abs, "utf8");
|
|
5924
6018
|
const { frontmatter, body } = parseFrontmatter(raw);
|
|
5925
6019
|
const parsed = schema2.parse(frontmatter);
|
|
5926
6020
|
entities.push({
|
|
@@ -6035,14 +6129,14 @@ var init_guidance2 = __esm({
|
|
|
6035
6129
|
});
|
|
6036
6130
|
|
|
6037
6131
|
// ../../packages/local-store/dist/finding-match.js
|
|
6038
|
-
import { promises as
|
|
6132
|
+
import { promises as fs9 } from "fs";
|
|
6039
6133
|
import path6 from "path";
|
|
6040
|
-
import { z as
|
|
6134
|
+
import { z as z23 } from "zod";
|
|
6041
6135
|
async function readScenarioFindings(projectRoot, scenarioSlug) {
|
|
6042
6136
|
const dir = entityDirPath(projectRoot, "finding");
|
|
6043
6137
|
let names;
|
|
6044
6138
|
try {
|
|
6045
|
-
names = await
|
|
6139
|
+
names = await fs9.readdir(dir);
|
|
6046
6140
|
} catch {
|
|
6047
6141
|
return [];
|
|
6048
6142
|
}
|
|
@@ -6052,7 +6146,7 @@ async function readScenarioFindings(projectRoot, scenarioSlug) {
|
|
|
6052
6146
|
continue;
|
|
6053
6147
|
const file = path6.join(dir, name);
|
|
6054
6148
|
try {
|
|
6055
|
-
const { frontmatter } = parseFrontmatter(await
|
|
6149
|
+
const { frontmatter } = parseFrontmatter(await fs9.readFile(file, "utf8"));
|
|
6056
6150
|
const fm = frontmatter;
|
|
6057
6151
|
if (fm.scenario === scenarioSlug)
|
|
6058
6152
|
out.push({ file, frontmatter: fm });
|
|
@@ -6092,7 +6186,7 @@ async function suppressionRules(projectRoot, outlineSlug) {
|
|
|
6092
6186
|
}
|
|
6093
6187
|
async function scenarioOutline(projectRoot, scenarioSlug) {
|
|
6094
6188
|
try {
|
|
6095
|
-
const raw = await
|
|
6189
|
+
const raw = await fs9.readFile(path6.join(entityDirPath(projectRoot, "scenario"), `${scenarioSlug}.md`), "utf8");
|
|
6096
6190
|
const outline = parseFrontmatter(raw).frontmatter.outline;
|
|
6097
6191
|
return typeof outline === "string" ? outline : null;
|
|
6098
6192
|
} catch {
|
|
@@ -6205,7 +6299,7 @@ async function recordMatches(projectRoot, runId, scenarioSlug, answer) {
|
|
|
6205
6299
|
const target = byId.get(m.finding_id);
|
|
6206
6300
|
if (!target)
|
|
6207
6301
|
continue;
|
|
6208
|
-
const raw = await
|
|
6302
|
+
const raw = await fs9.readFile(target, "utf8");
|
|
6209
6303
|
const updated = setFrontmatterScalar(raw, "canonical_id", m.canonical_id);
|
|
6210
6304
|
if (updated !== raw)
|
|
6211
6305
|
await atomicWriteFile(target, updated);
|
|
@@ -6215,7 +6309,7 @@ async function recordMatches(projectRoot, runId, scenarioSlug, answer) {
|
|
|
6215
6309
|
const target = byId.get(s.finding_id);
|
|
6216
6310
|
if (!target)
|
|
6217
6311
|
continue;
|
|
6218
|
-
const raw = await
|
|
6312
|
+
const raw = await fs9.readFile(target, "utf8");
|
|
6219
6313
|
const updated = setFrontmatterScalar(raw, "suppressed_by_guidance", s.guidance_id);
|
|
6220
6314
|
if (updated !== raw)
|
|
6221
6315
|
await atomicWriteFile(target, updated);
|
|
@@ -6233,7 +6327,7 @@ async function setCanonicalFixStatus(projectRoot, scenarioSlug, canonicalId, sta
|
|
|
6233
6327
|
for (const f of await readScenarioFindings(projectRoot, scenarioSlug)) {
|
|
6234
6328
|
if (f.frontmatter.canonical_id !== canonicalId)
|
|
6235
6329
|
continue;
|
|
6236
|
-
const raw = await
|
|
6330
|
+
const raw = await fs9.readFile(f.file, "utf8");
|
|
6237
6331
|
const updated = setFrontmatterScalar(raw, "fix_status", status2);
|
|
6238
6332
|
if (updated !== raw)
|
|
6239
6333
|
await atomicWriteFile(f.file, updated);
|
|
@@ -6241,7 +6335,7 @@ async function setCanonicalFixStatus(projectRoot, scenarioSlug, canonicalId, sta
|
|
|
6241
6335
|
}
|
|
6242
6336
|
async function readMatches(projectRoot, runId) {
|
|
6243
6337
|
try {
|
|
6244
|
-
const raw = await
|
|
6338
|
+
const raw = await fs9.readFile(path6.join(runDir(projectRoot, runId), MATCHES_FILE), "utf8");
|
|
6245
6339
|
const parsed = matchesFileSchema.safeParse(JSON.parse(raw));
|
|
6246
6340
|
return parsed.success ? parsed.data : null;
|
|
6247
6341
|
} catch {
|
|
@@ -6258,32 +6352,32 @@ var init_finding_match = __esm({
|
|
|
6258
6352
|
init_paths();
|
|
6259
6353
|
init_walkthrough_canonical2();
|
|
6260
6354
|
MATCHES_FILE = "matches.json";
|
|
6261
|
-
matchesFileSchema =
|
|
6262
|
-
matches:
|
|
6263
|
-
finding_id:
|
|
6264
|
-
canonical_id:
|
|
6265
|
-
reasoning:
|
|
6355
|
+
matchesFileSchema = z23.object({
|
|
6356
|
+
matches: z23.array(z23.object({
|
|
6357
|
+
finding_id: z23.string().min(1),
|
|
6358
|
+
canonical_id: z23.string().min(1).nullable(),
|
|
6359
|
+
reasoning: z23.string().default("")
|
|
6266
6360
|
})),
|
|
6267
|
-
rechecked_fixed:
|
|
6268
|
-
canonical_id:
|
|
6269
|
-
step_ids:
|
|
6270
|
-
reasoning:
|
|
6361
|
+
rechecked_fixed: z23.array(z23.object({
|
|
6362
|
+
canonical_id: z23.string().min(1),
|
|
6363
|
+
step_ids: z23.array(z23.string().min(1)).min(1),
|
|
6364
|
+
reasoning: z23.string().default("")
|
|
6271
6365
|
})).default([]),
|
|
6272
6366
|
/**
|
|
6273
6367
|
* Findings of this run that an active `not_relevant` tester guidance
|
|
6274
6368
|
* rule covers. Kept, flagged: `suppressed_by_guidance` on the file.
|
|
6275
6369
|
*/
|
|
6276
|
-
suppressed:
|
|
6277
|
-
finding_id:
|
|
6278
|
-
guidance_id:
|
|
6279
|
-
reasoning:
|
|
6370
|
+
suppressed: z23.array(z23.object({
|
|
6371
|
+
finding_id: z23.string().min(1),
|
|
6372
|
+
guidance_id: z23.string().min(1),
|
|
6373
|
+
reasoning: z23.string().default("")
|
|
6280
6374
|
})).default([])
|
|
6281
6375
|
});
|
|
6282
6376
|
}
|
|
6283
6377
|
});
|
|
6284
6378
|
|
|
6285
6379
|
// ../../packages/local-store/dist/runs.js
|
|
6286
|
-
import { promises as
|
|
6380
|
+
import { promises as fs10 } from "fs";
|
|
6287
6381
|
import path7 from "path";
|
|
6288
6382
|
async function openRun(projectRoot, scenarioSlug, options = {}) {
|
|
6289
6383
|
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
@@ -6292,9 +6386,9 @@ async function openRun(projectRoot, scenarioSlug, options = {}) {
|
|
|
6292
6386
|
const stepsDir = path7.join(absPath, "steps");
|
|
6293
6387
|
const fingerprintsDir = path7.join(absPath, "fingerprints");
|
|
6294
6388
|
const screenshotsDir = path7.join(absPath, "screenshots");
|
|
6295
|
-
await
|
|
6296
|
-
await
|
|
6297
|
-
await
|
|
6389
|
+
await fs10.mkdir(stepsDir, { recursive: true });
|
|
6390
|
+
await fs10.mkdir(fingerprintsDir, { recursive: true });
|
|
6391
|
+
await fs10.mkdir(screenshotsDir, { recursive: true });
|
|
6298
6392
|
return {
|
|
6299
6393
|
runId,
|
|
6300
6394
|
absPath,
|
|
@@ -6309,14 +6403,14 @@ function padStepNumber(n) {
|
|
|
6309
6403
|
}
|
|
6310
6404
|
async function writeStep(runDirAbs, step) {
|
|
6311
6405
|
const stepsDir = path7.join(runDirAbs, "steps");
|
|
6312
|
-
await
|
|
6406
|
+
await fs10.mkdir(stepsDir, { recursive: true });
|
|
6313
6407
|
const filename = `${padStepNumber(step.step_number)}.json`;
|
|
6314
6408
|
await atomicWriteFile(path7.join(stepsDir, filename), JSON.stringify(step, null, 2) + "\n");
|
|
6315
6409
|
}
|
|
6316
6410
|
async function listRuns(projectRoot) {
|
|
6317
6411
|
const dir = runsDir(projectRoot);
|
|
6318
6412
|
try {
|
|
6319
|
-
const entries = await
|
|
6413
|
+
const entries = await fs10.readdir(dir, { withFileTypes: true });
|
|
6320
6414
|
return entries.filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name).sort();
|
|
6321
6415
|
} catch (err) {
|
|
6322
6416
|
if (err.code === "ENOENT")
|
|
@@ -6328,7 +6422,7 @@ async function listIncompleteRuns(projectRoot) {
|
|
|
6328
6422
|
const incomplete = [];
|
|
6329
6423
|
for (const runId of await listRuns(projectRoot)) {
|
|
6330
6424
|
try {
|
|
6331
|
-
const manifest = JSON.parse(await
|
|
6425
|
+
const manifest = JSON.parse(await fs10.readFile(path7.join(runsDir(projectRoot), runId, "walkthrough.json"), "utf8"));
|
|
6332
6426
|
if (manifest.status !== "completed")
|
|
6333
6427
|
incomplete.push(runId);
|
|
6334
6428
|
} catch {
|
|
@@ -6346,7 +6440,7 @@ var init_runs = __esm({
|
|
|
6346
6440
|
});
|
|
6347
6441
|
|
|
6348
6442
|
// ../../packages/local-store/dist/fix-state.js
|
|
6349
|
-
import { promises as
|
|
6443
|
+
import { promises as fs11 } from "fs";
|
|
6350
6444
|
import path8 from "path";
|
|
6351
6445
|
function toMillis(iso) {
|
|
6352
6446
|
if (!iso)
|
|
@@ -6452,7 +6546,7 @@ function summarizeRerun(findings2, runs, states) {
|
|
|
6452
6546
|
}
|
|
6453
6547
|
async function readJson(file) {
|
|
6454
6548
|
try {
|
|
6455
|
-
return JSON.parse(await
|
|
6549
|
+
return JSON.parse(await fs11.readFile(file, "utf8"));
|
|
6456
6550
|
} catch {
|
|
6457
6551
|
return null;
|
|
6458
6552
|
}
|
|
@@ -7025,19 +7119,19 @@ var init_journey_diff = __esm({
|
|
|
7025
7119
|
|
|
7026
7120
|
// ../../packages/local-store/dist/walkthrough-canonical.js
|
|
7027
7121
|
import { createHash as createHash2, randomUUID as randomUUID5 } from "crypto";
|
|
7028
|
-
import { promises as
|
|
7122
|
+
import { promises as fs12 } from "fs";
|
|
7029
7123
|
import path9 from "path";
|
|
7030
7124
|
async function readStepsForRun(projectRoot, runId) {
|
|
7031
7125
|
const runDirPath = runDir(projectRoot, runId);
|
|
7032
7126
|
const stepsDir = path9.join(runDirPath, "steps");
|
|
7033
7127
|
try {
|
|
7034
|
-
const names = await
|
|
7128
|
+
const names = await fs12.readdir(stepsDir);
|
|
7035
7129
|
const jsonFiles = names.filter((n) => n.endsWith(".json")).sort();
|
|
7036
7130
|
if (jsonFiles.length > 0) {
|
|
7037
7131
|
const out2 = [];
|
|
7038
7132
|
for (const name of jsonFiles) {
|
|
7039
7133
|
try {
|
|
7040
|
-
const raw2 = await
|
|
7134
|
+
const raw2 = await fs12.readFile(path9.join(stepsDir, name), "utf8");
|
|
7041
7135
|
const parsed = JSON.parse(raw2);
|
|
7042
7136
|
if (parsed.step_number == null) {
|
|
7043
7137
|
const numFromName = Number.parseInt(name.replace(/\.json$/, ""), 10);
|
|
@@ -7054,7 +7148,7 @@ async function readStepsForRun(projectRoot, runId) {
|
|
|
7054
7148
|
const stepsPath = path9.join(runDirPath, "steps.jsonl");
|
|
7055
7149
|
let raw;
|
|
7056
7150
|
try {
|
|
7057
|
-
raw = await
|
|
7151
|
+
raw = await fs12.readFile(stepsPath, "utf8");
|
|
7058
7152
|
} catch (err) {
|
|
7059
7153
|
if (err.code === "ENOENT")
|
|
7060
7154
|
return [];
|
|
@@ -7079,7 +7173,7 @@ async function readFindingsForRun(projectRoot, runId) {
|
|
|
7079
7173
|
const findingsDir = entityDirPath(projectRoot, "finding");
|
|
7080
7174
|
let names;
|
|
7081
7175
|
try {
|
|
7082
|
-
names = await
|
|
7176
|
+
names = await fs12.readdir(findingsDir);
|
|
7083
7177
|
} catch (err) {
|
|
7084
7178
|
if (err.code === "ENOENT")
|
|
7085
7179
|
return [];
|
|
@@ -7090,7 +7184,7 @@ async function readFindingsForRun(projectRoot, runId) {
|
|
|
7090
7184
|
if (!name.endsWith(".md") || name.startsWith("."))
|
|
7091
7185
|
continue;
|
|
7092
7186
|
const filePath = path9.join(findingsDir, name);
|
|
7093
|
-
const raw = await
|
|
7187
|
+
const raw = await fs12.readFile(filePath, "utf8");
|
|
7094
7188
|
try {
|
|
7095
7189
|
const { frontmatter, body } = parseFrontmatter(raw);
|
|
7096
7190
|
const fm = frontmatter;
|
|
@@ -7121,7 +7215,7 @@ async function resolveCanonicalIds(projectRoot, scenarioSlug, currentRunId, curr
|
|
|
7121
7215
|
const findingsDir = entityDirPath(projectRoot, "finding");
|
|
7122
7216
|
let allNames;
|
|
7123
7217
|
try {
|
|
7124
|
-
allNames = await
|
|
7218
|
+
allNames = await fs12.readdir(findingsDir);
|
|
7125
7219
|
} catch {
|
|
7126
7220
|
allNames = [];
|
|
7127
7221
|
}
|
|
@@ -7129,7 +7223,7 @@ async function resolveCanonicalIds(projectRoot, scenarioSlug, currentRunId, curr
|
|
|
7129
7223
|
if (!name.endsWith(".md") || name.startsWith("."))
|
|
7130
7224
|
continue;
|
|
7131
7225
|
try {
|
|
7132
|
-
const raw = await
|
|
7226
|
+
const raw = await fs12.readFile(path9.join(findingsDir, name), "utf8");
|
|
7133
7227
|
const { frontmatter } = parseFrontmatter(raw);
|
|
7134
7228
|
const fm = frontmatter;
|
|
7135
7229
|
if (!fm.scenario || fm.scenario !== scenarioSlug)
|
|
@@ -7157,7 +7251,7 @@ async function resolveCanonicalIds(projectRoot, scenarioSlug, currentRunId, curr
|
|
|
7157
7251
|
continue;
|
|
7158
7252
|
const candidatePath = path9.join(findingsDir, name);
|
|
7159
7253
|
try {
|
|
7160
|
-
const candidateRaw = await
|
|
7254
|
+
const candidateRaw = await fs12.readFile(candidatePath, "utf8");
|
|
7161
7255
|
const { frontmatter: cFm } = parseFrontmatter(candidateRaw);
|
|
7162
7256
|
if (cFm.id === f.frontmatter.id) {
|
|
7163
7257
|
targetPath = candidatePath;
|
|
@@ -7168,7 +7262,7 @@ async function resolveCanonicalIds(projectRoot, scenarioSlug, currentRunId, curr
|
|
|
7168
7262
|
}
|
|
7169
7263
|
if (targetPath) {
|
|
7170
7264
|
await withFileLock(targetPath, async () => {
|
|
7171
|
-
const raw = await
|
|
7265
|
+
const raw = await fs12.readFile(targetPath, "utf8");
|
|
7172
7266
|
const updated = raw.replace(/^(---\n[\s\S]*?)(---\n)/m, `$1canonical_id: ${canonicalId}
|
|
7173
7267
|
$2`);
|
|
7174
7268
|
if (updated !== raw) {
|
|
@@ -7304,7 +7398,7 @@ async function compareWithBaseline(projectRoot, scenarioSlug, currentRunId, curr
|
|
|
7304
7398
|
continue;
|
|
7305
7399
|
try {
|
|
7306
7400
|
const mPath = path9.join(runDir(projectRoot, rid), "walkthrough.json");
|
|
7307
|
-
const raw = await
|
|
7401
|
+
const raw = await fs12.readFile(mPath, "utf8");
|
|
7308
7402
|
const m = JSON.parse(raw);
|
|
7309
7403
|
if (m.scenario_slug === scenarioSlug && m.status === "completed") {
|
|
7310
7404
|
baselineRunId = rid;
|
|
@@ -7387,7 +7481,7 @@ async function updateFixStatus(projectRoot, slug, status2) {
|
|
|
7387
7481
|
const findingsDir = entityDirPath(projectRoot, "finding");
|
|
7388
7482
|
const filePath = path9.join(findingsDir, `${slug}.md`);
|
|
7389
7483
|
await withFileLock(filePath, async () => {
|
|
7390
|
-
const raw = await
|
|
7484
|
+
const raw = await fs12.readFile(filePath, "utf8");
|
|
7391
7485
|
const updated = raw.replace(/^(fix_status:\s*).*$/m, `$1${status2}`);
|
|
7392
7486
|
if (updated !== raw) {
|
|
7393
7487
|
await atomicWriteFile(filePath, updated);
|
|
@@ -7403,7 +7497,7 @@ fix_status: ${status2}`);
|
|
|
7403
7497
|
async function listRunsInternal(projectRoot) {
|
|
7404
7498
|
const dir = path9.join(projectRoot, "iamu", ".runs");
|
|
7405
7499
|
try {
|
|
7406
|
-
const names = await
|
|
7500
|
+
const names = await fs12.readdir(dir);
|
|
7407
7501
|
return names.filter((n) => !n.startsWith(".")).sort();
|
|
7408
7502
|
} catch {
|
|
7409
7503
|
return [];
|
|
@@ -7585,7 +7679,7 @@ __export(walkthrough_mirror_exports, {
|
|
|
7585
7679
|
walkthroughBundleSchema: () => walkthroughBundleSchema
|
|
7586
7680
|
});
|
|
7587
7681
|
import { createHash as createHash3 } from "crypto";
|
|
7588
|
-
import { promises as
|
|
7682
|
+
import { promises as fs13 } from "fs";
|
|
7589
7683
|
import path10 from "path";
|
|
7590
7684
|
function toCloudRunUuid(runId) {
|
|
7591
7685
|
if (UUID_RE.test(runId))
|
|
@@ -7638,7 +7732,7 @@ function buildPushUrl(cloudApiUrl, cloudProjectId) {
|
|
|
7638
7732
|
async function readLocalManifest(projectRoot, runId) {
|
|
7639
7733
|
const p = path10.join(runDir(projectRoot, runId), "walkthrough.json");
|
|
7640
7734
|
try {
|
|
7641
|
-
const raw = await
|
|
7735
|
+
const raw = await fs13.readFile(p, "utf8");
|
|
7642
7736
|
return JSON.parse(raw);
|
|
7643
7737
|
} catch {
|
|
7644
7738
|
return null;
|
|
@@ -7647,7 +7741,7 @@ async function readLocalManifest(projectRoot, runId) {
|
|
|
7647
7741
|
async function readLocalReport(projectRoot, runId) {
|
|
7648
7742
|
const p = path10.join(runDir(projectRoot, runId), "report.md");
|
|
7649
7743
|
try {
|
|
7650
|
-
return await
|
|
7744
|
+
return await fs13.readFile(p, "utf8");
|
|
7651
7745
|
} catch (err) {
|
|
7652
7746
|
if (err.code === "ENOENT")
|
|
7653
7747
|
return "";
|
|
@@ -7658,7 +7752,7 @@ async function readScreenshotBytes(projectRoot, runId) {
|
|
|
7658
7752
|
const dir = path10.join(runDir(projectRoot, runId), SCREENSHOTS_DIR);
|
|
7659
7753
|
let names;
|
|
7660
7754
|
try {
|
|
7661
|
-
names = await
|
|
7755
|
+
names = await fs13.readdir(dir);
|
|
7662
7756
|
} catch (err) {
|
|
7663
7757
|
if (err.code === "ENOENT")
|
|
7664
7758
|
return /* @__PURE__ */ new Map();
|
|
@@ -7674,7 +7768,7 @@ async function readScreenshotBytes(projectRoot, runId) {
|
|
|
7674
7768
|
const contentType = EXT_TO_CONTENT_TYPE[ext === ".jpeg" ? ".jpeg" : ext];
|
|
7675
7769
|
if (!contentType)
|
|
7676
7770
|
continue;
|
|
7677
|
-
const bytes = await
|
|
7771
|
+
const bytes = await fs13.readFile(path10.join(dir, name));
|
|
7678
7772
|
out.set(seq2, { bytes, filename: name, contentType });
|
|
7679
7773
|
}
|
|
7680
7774
|
return out;
|
|
@@ -7682,7 +7776,7 @@ async function readScreenshotBytes(projectRoot, runId) {
|
|
|
7682
7776
|
async function readVerdictsJson(projectRoot, runId) {
|
|
7683
7777
|
const filePath = path10.join(runDir(projectRoot, runId), "verdicts.json");
|
|
7684
7778
|
try {
|
|
7685
|
-
const raw = await
|
|
7779
|
+
const raw = await fs13.readFile(filePath, "utf-8");
|
|
7686
7780
|
return JSON.parse(raw);
|
|
7687
7781
|
} catch {
|
|
7688
7782
|
return null;
|
|
@@ -7693,7 +7787,7 @@ async function readProvenance(projectRoot, runId, verdicts) {
|
|
|
7693
7787
|
return verdicts.provenance;
|
|
7694
7788
|
const filePath = path10.join(runDir(projectRoot, runId), "canonical.json");
|
|
7695
7789
|
try {
|
|
7696
|
-
const raw = await
|
|
7790
|
+
const raw = await fs13.readFile(filePath, "utf-8");
|
|
7697
7791
|
const data = JSON.parse(raw);
|
|
7698
7792
|
return data.provenance ?? null;
|
|
7699
7793
|
} catch {
|
|
@@ -7702,7 +7796,7 @@ async function readProvenance(projectRoot, runId, verdicts) {
|
|
|
7702
7796
|
}
|
|
7703
7797
|
async function readCanonicalExtras(projectRoot, runId) {
|
|
7704
7798
|
try {
|
|
7705
|
-
const data = JSON.parse(await
|
|
7799
|
+
const data = JSON.parse(await fs13.readFile(path10.join(runDir(projectRoot, runId), "canonical.json"), "utf-8"));
|
|
7706
7800
|
const strings = (v) => Array.isArray(v) && v.every((x) => typeof x === "string") ? v : void 0;
|
|
7707
7801
|
const verification = bundleVerificationSchema.safeParse(data.verification);
|
|
7708
7802
|
return {
|
|
@@ -8441,7 +8535,7 @@ var init_refs = __esm({
|
|
|
8441
8535
|
});
|
|
8442
8536
|
|
|
8443
8537
|
// ../../packages/local-store/dist/sync/types.js
|
|
8444
|
-
import { z as
|
|
8538
|
+
import { z as z24 } from "zod";
|
|
8445
8539
|
function toRef(d) {
|
|
8446
8540
|
return { type: d.type, id: d.id, label: d.label };
|
|
8447
8541
|
}
|
|
@@ -8506,17 +8600,17 @@ var init_types = __esm({
|
|
|
8506
8600
|
DEFAULT_TIMEOUT_MS4 = 3e4;
|
|
8507
8601
|
MAX_BATCH_BYTES = 6 * 1024 * 1024;
|
|
8508
8602
|
BASE_HASH_BYTES = 96;
|
|
8509
|
-
importConflictSchema =
|
|
8510
|
-
type:
|
|
8511
|
-
id:
|
|
8512
|
-
base_hash:
|
|
8513
|
-
cloud_hash:
|
|
8514
|
-
cloud_updated_at:
|
|
8515
|
-
cloud_changed_by:
|
|
8603
|
+
importConflictSchema = z24.object({
|
|
8604
|
+
type: z24.string(),
|
|
8605
|
+
id: z24.string(),
|
|
8606
|
+
base_hash: z24.string().nullish(),
|
|
8607
|
+
cloud_hash: z24.string(),
|
|
8608
|
+
cloud_updated_at: z24.string().nullish(),
|
|
8609
|
+
cloud_changed_by: z24.string().nullish()
|
|
8516
8610
|
});
|
|
8517
|
-
importResponseSchema =
|
|
8518
|
-
imported:
|
|
8519
|
-
conflicts:
|
|
8611
|
+
importResponseSchema = z24.object({
|
|
8612
|
+
imported: z24.number().int().min(0),
|
|
8613
|
+
conflicts: z24.array(importConflictSchema).optional()
|
|
8520
8614
|
});
|
|
8521
8615
|
}
|
|
8522
8616
|
});
|
|
@@ -8767,7 +8861,7 @@ var init_push = __esm({
|
|
|
8767
8861
|
});
|
|
8768
8862
|
|
|
8769
8863
|
// ../../packages/local-store/dist/sync/context.js
|
|
8770
|
-
import { promises as
|
|
8864
|
+
import { promises as fs14 } from "fs";
|
|
8771
8865
|
async function syncContext(target) {
|
|
8772
8866
|
const { projectRoot } = target;
|
|
8773
8867
|
const summary = zeroContext();
|
|
@@ -8775,7 +8869,7 @@ async function syncContext(target) {
|
|
|
8775
8869
|
const conflicts = [];
|
|
8776
8870
|
let raw;
|
|
8777
8871
|
try {
|
|
8778
|
-
raw = await
|
|
8872
|
+
raw = await fs14.readFile(contextPath(projectRoot), "utf8");
|
|
8779
8873
|
} catch (err) {
|
|
8780
8874
|
if (err.code === "ENOENT")
|
|
8781
8875
|
return { summary, errors, conflicts };
|
|
@@ -8985,7 +9079,7 @@ var init_git_branches = __esm({
|
|
|
8985
9079
|
});
|
|
8986
9080
|
|
|
8987
9081
|
// ../../packages/local-store/dist/deletions.js
|
|
8988
|
-
import { promises as
|
|
9082
|
+
import { promises as fs15 } from "fs";
|
|
8989
9083
|
import path12 from "path";
|
|
8990
9084
|
function describeDeletionCount(type2, n) {
|
|
8991
9085
|
const nouns = {
|
|
@@ -9013,7 +9107,7 @@ function summarizeDeletions(items) {
|
|
|
9013
9107
|
}
|
|
9014
9108
|
async function readPushedEntities(projectRoot) {
|
|
9015
9109
|
try {
|
|
9016
|
-
const raw = await
|
|
9110
|
+
const raw = await fs15.readFile(pushedEntitiesPath(projectRoot), "utf8");
|
|
9017
9111
|
const parsed = JSON.parse(raw);
|
|
9018
9112
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
9019
9113
|
return {};
|
|
@@ -9052,7 +9146,7 @@ async function rememberPushedEntities(projectRoot, known) {
|
|
|
9052
9146
|
}
|
|
9053
9147
|
async function readLenient(projectRoot, relPath) {
|
|
9054
9148
|
try {
|
|
9055
|
-
const raw = await
|
|
9149
|
+
const raw = await fs15.readFile(path12.join(projectRoot, relPath), "utf8");
|
|
9056
9150
|
const fm = parseFrontmatter(raw).frontmatter;
|
|
9057
9151
|
if (typeof fm.id !== "string" || fm.id.length === 0)
|
|
9058
9152
|
return null;
|
|
@@ -9478,7 +9572,7 @@ var init_deletions2 = __esm({
|
|
|
9478
9572
|
});
|
|
9479
9573
|
|
|
9480
9574
|
// ../../packages/local-store/dist/sync/scan.js
|
|
9481
|
-
import { promises as
|
|
9575
|
+
import { promises as fs16 } from "fs";
|
|
9482
9576
|
function blockedRef(refs, blocked) {
|
|
9483
9577
|
if (!refs)
|
|
9484
9578
|
return null;
|
|
@@ -9574,7 +9668,7 @@ async function scanPending(projectRoot) {
|
|
|
9574
9668
|
continue;
|
|
9575
9669
|
let bytes;
|
|
9576
9670
|
try {
|
|
9577
|
-
bytes = await
|
|
9671
|
+
bytes = await fs16.readFile(entity.absPath, "utf8");
|
|
9578
9672
|
} catch {
|
|
9579
9673
|
continue;
|
|
9580
9674
|
}
|
|
@@ -9635,7 +9729,7 @@ var init_scan = __esm({
|
|
|
9635
9729
|
});
|
|
9636
9730
|
|
|
9637
9731
|
// ../../packages/local-store/dist/sync/walkthroughs.js
|
|
9638
|
-
import { promises as
|
|
9732
|
+
import { promises as fs17 } from "fs";
|
|
9639
9733
|
import nodePath from "path";
|
|
9640
9734
|
async function syncWalkthroughs(projectRoot, deps, unpushableScenarios = /* @__PURE__ */ new Set()) {
|
|
9641
9735
|
const summary = zeroWalkthroughs();
|
|
@@ -9663,7 +9757,7 @@ async function syncWalkthroughs(projectRoot, deps, unpushableScenarios = /* @__P
|
|
|
9663
9757
|
const manifestPath = nodePath.join(runDir(projectRoot, runId), "walkthrough.json");
|
|
9664
9758
|
let manifestRaw;
|
|
9665
9759
|
try {
|
|
9666
|
-
manifestRaw = await
|
|
9760
|
+
manifestRaw = await fs17.readFile(manifestPath, "utf8");
|
|
9667
9761
|
} catch {
|
|
9668
9762
|
continue;
|
|
9669
9763
|
}
|
|
@@ -10002,7 +10096,7 @@ var init_disconnect = __esm({
|
|
|
10002
10096
|
});
|
|
10003
10097
|
|
|
10004
10098
|
// ../../packages/local-store/dist/status.js
|
|
10005
|
-
import { promises as
|
|
10099
|
+
import { promises as fs18 } from "fs";
|
|
10006
10100
|
import path13 from "path";
|
|
10007
10101
|
async function countType(projectRoot, type2) {
|
|
10008
10102
|
const result = await listEntities(projectRoot, type2);
|
|
@@ -10013,7 +10107,7 @@ async function countType(projectRoot, type2) {
|
|
|
10013
10107
|
if (typeof id !== "string" || typeof slug !== "string")
|
|
10014
10108
|
continue;
|
|
10015
10109
|
try {
|
|
10016
|
-
const raw = await
|
|
10110
|
+
const raw = await fs18.readFile(entity.absPath, "utf8");
|
|
10017
10111
|
contentHashes.set(id, hashNormalizedContent(raw));
|
|
10018
10112
|
} catch {
|
|
10019
10113
|
}
|
|
@@ -10107,7 +10201,7 @@ async function countContext(projectRoot, opts = {
|
|
|
10107
10201
|
return base;
|
|
10108
10202
|
let pending = true;
|
|
10109
10203
|
try {
|
|
10110
|
-
const bytes = await
|
|
10204
|
+
const bytes = await fs18.readFile(contextPath(projectRoot), "utf8");
|
|
10111
10205
|
const hash = hashNormalizedContent(bytes);
|
|
10112
10206
|
pending = opts.lastPush["context:root"] !== hash;
|
|
10113
10207
|
} catch {
|
|
@@ -10129,7 +10223,7 @@ async function countWalkthroughs(projectRoot, opts = { cloudLinked: false, lastP
|
|
|
10129
10223
|
const manifestPath = path13.join(projectRoot, "iamu", ".runs", runId, "walkthrough.json");
|
|
10130
10224
|
let completed = false;
|
|
10131
10225
|
try {
|
|
10132
|
-
const raw = await
|
|
10226
|
+
const raw = await fs18.readFile(manifestPath, "utf8");
|
|
10133
10227
|
const manifest = JSON.parse(raw);
|
|
10134
10228
|
completed = manifest.status === "completed";
|
|
10135
10229
|
} catch {
|
|
@@ -10149,7 +10243,7 @@ async function getProjectStatus(projectRoot, opts = {}) {
|
|
|
10149
10243
|
const config = await readConfig(projectRoot);
|
|
10150
10244
|
const iamuPath = iamuDir(projectRoot);
|
|
10151
10245
|
try {
|
|
10152
|
-
await
|
|
10246
|
+
await fs18.access(iamuPath);
|
|
10153
10247
|
} catch {
|
|
10154
10248
|
throw new Error(`status: iamu/ directory missing at ${iamuPath}`);
|
|
10155
10249
|
}
|
|
@@ -10331,13 +10425,13 @@ var init_status = __esm({
|
|
|
10331
10425
|
});
|
|
10332
10426
|
|
|
10333
10427
|
// ../../packages/local-store/dist/prune.js
|
|
10334
|
-
import { promises as
|
|
10428
|
+
import { promises as fs19 } from "fs";
|
|
10335
10429
|
import path14 from "path";
|
|
10336
10430
|
async function getDirectoryStats(dirPath) {
|
|
10337
10431
|
let bytes = 0;
|
|
10338
10432
|
let count = 0;
|
|
10339
10433
|
try {
|
|
10340
|
-
const entries = await
|
|
10434
|
+
const entries = await fs19.readdir(dirPath, { withFileTypes: true });
|
|
10341
10435
|
for (const entry of entries) {
|
|
10342
10436
|
const fullPath = path14.join(dirPath, entry.name);
|
|
10343
10437
|
if (entry.isDirectory()) {
|
|
@@ -10346,7 +10440,7 @@ async function getDirectoryStats(dirPath) {
|
|
|
10346
10440
|
count += sub.count;
|
|
10347
10441
|
} else if (entry.isFile()) {
|
|
10348
10442
|
try {
|
|
10349
|
-
const s = await
|
|
10443
|
+
const s = await fs19.stat(fullPath);
|
|
10350
10444
|
bytes += s.size;
|
|
10351
10445
|
count += 1;
|
|
10352
10446
|
} catch {
|
|
@@ -10362,12 +10456,12 @@ async function getScreenshotsStats(screenshotsDir) {
|
|
|
10362
10456
|
let count = 0;
|
|
10363
10457
|
const paths = [];
|
|
10364
10458
|
try {
|
|
10365
|
-
const entries = await
|
|
10459
|
+
const entries = await fs19.readdir(screenshotsDir, { withFileTypes: true });
|
|
10366
10460
|
for (const entry of entries) {
|
|
10367
10461
|
if (entry.isFile() && (entry.name.endsWith(".png") || entry.name.endsWith(".jpg") || entry.name.endsWith(".jpeg") || entry.name.endsWith(".webp"))) {
|
|
10368
10462
|
const fullPath = path14.join(screenshotsDir, entry.name);
|
|
10369
10463
|
try {
|
|
10370
|
-
const s = await
|
|
10464
|
+
const s = await fs19.stat(fullPath);
|
|
10371
10465
|
bytes += s.size;
|
|
10372
10466
|
count += 1;
|
|
10373
10467
|
paths.push(fullPath);
|
|
@@ -10388,7 +10482,7 @@ async function pruneRuns(projectRoot, opts = {}) {
|
|
|
10388
10482
|
let scenarioSlug;
|
|
10389
10483
|
try {
|
|
10390
10484
|
const manifestPath = path14.join(dirPath, "walkthrough.json");
|
|
10391
|
-
const raw = await
|
|
10485
|
+
const raw = await fs19.readFile(manifestPath, "utf-8");
|
|
10392
10486
|
const parsed = JSON.parse(raw);
|
|
10393
10487
|
if (parsed.scenario_slug)
|
|
10394
10488
|
scenarioSlug = parsed.scenario_slug;
|
|
@@ -10400,7 +10494,7 @@ async function pruneRuns(projectRoot, opts = {}) {
|
|
|
10400
10494
|
}
|
|
10401
10495
|
if (!timestamp2 || Number.isNaN(timestamp2.getTime())) {
|
|
10402
10496
|
try {
|
|
10403
|
-
const st = await
|
|
10497
|
+
const st = await fs19.stat(dirPath);
|
|
10404
10498
|
timestamp2 = st.mtime;
|
|
10405
10499
|
} catch {
|
|
10406
10500
|
timestamp2 = /* @__PURE__ */ new Date();
|
|
@@ -10440,7 +10534,7 @@ async function pruneRuns(projectRoot, opts = {}) {
|
|
|
10440
10534
|
if (opts.screenshotsOnly) {
|
|
10441
10535
|
if (!opts.dryRun) {
|
|
10442
10536
|
for (const shotPath of shotStats.paths) {
|
|
10443
|
-
await
|
|
10537
|
+
await fs19.unlink(shotPath).catch(() => {
|
|
10444
10538
|
});
|
|
10445
10539
|
}
|
|
10446
10540
|
}
|
|
@@ -10457,7 +10551,7 @@ async function pruneRuns(projectRoot, opts = {}) {
|
|
|
10457
10551
|
} else {
|
|
10458
10552
|
const dirStats = await getDirectoryStats(c.dirPath);
|
|
10459
10553
|
if (!opts.dryRun) {
|
|
10460
|
-
await
|
|
10554
|
+
await fs19.rm(c.dirPath, { recursive: true, force: true });
|
|
10461
10555
|
}
|
|
10462
10556
|
prunedRuns.push({
|
|
10463
10557
|
runId: c.runId,
|
|
@@ -10489,7 +10583,7 @@ var init_prune = __esm({
|
|
|
10489
10583
|
|
|
10490
10584
|
// ../../packages/local-store/dist/explore-map.js
|
|
10491
10585
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
10492
|
-
import { promises as
|
|
10586
|
+
import { promises as fs20 } from "fs";
|
|
10493
10587
|
import path15 from "path";
|
|
10494
10588
|
function templateToken(token) {
|
|
10495
10589
|
if (token === "")
|
|
@@ -10585,13 +10679,13 @@ function mapPath(projectRoot, id) {
|
|
|
10585
10679
|
}
|
|
10586
10680
|
async function writeExploreMap(projectRoot, map2) {
|
|
10587
10681
|
const file = mapPath(projectRoot, map2.id);
|
|
10588
|
-
await
|
|
10682
|
+
await fs20.mkdir(path15.dirname(file), { recursive: true });
|
|
10589
10683
|
await atomicWriteFile(file, `${JSON.stringify(map2, null, 2)}
|
|
10590
10684
|
`);
|
|
10591
10685
|
return file;
|
|
10592
10686
|
}
|
|
10593
10687
|
async function readExploreMap(projectRoot, id) {
|
|
10594
|
-
const raw = await
|
|
10688
|
+
const raw = await fs20.readFile(mapPath(projectRoot, id), "utf8");
|
|
10595
10689
|
const map2 = JSON.parse(raw);
|
|
10596
10690
|
if (map2?.schema !== EXPLORE_MAP_SCHEMA || !Array.isArray(map2.surfaces)) {
|
|
10597
10691
|
throw new Error(`Unreadable explore map: ${id}`);
|
|
@@ -10600,7 +10694,7 @@ async function readExploreMap(projectRoot, id) {
|
|
|
10600
10694
|
}
|
|
10601
10695
|
async function listExploreMaps(projectRoot) {
|
|
10602
10696
|
try {
|
|
10603
|
-
const entries = await
|
|
10697
|
+
const entries = await fs20.readdir(exploreDir(projectRoot), {
|
|
10604
10698
|
withFileTypes: true
|
|
10605
10699
|
});
|
|
10606
10700
|
return entries.filter((e) => e.isDirectory() && isValidExploreId(e.name)).map((e) => e.name).sort();
|
|
@@ -10698,6 +10792,127 @@ async function readAllRunSteps(projectRoot) {
|
|
|
10698
10792
|
}
|
|
10699
10793
|
return out;
|
|
10700
10794
|
}
|
|
10795
|
+
function matchSurfaceCapabilities(place, capabilities) {
|
|
10796
|
+
const normPlace = place.length > 1 ? place.replace(/\/+$/, "") : place;
|
|
10797
|
+
const matchedCaps = /* @__PURE__ */ new Map();
|
|
10798
|
+
for (const cap of capabilities) {
|
|
10799
|
+
if (!cap.paths || cap.paths.length === 0)
|
|
10800
|
+
continue;
|
|
10801
|
+
for (const rawPath of cap.paths) {
|
|
10802
|
+
if (!rawPath)
|
|
10803
|
+
continue;
|
|
10804
|
+
const cleanPath = rawPath.length > 1 ? rawPath.replace(/\/+$/, "") : rawPath;
|
|
10805
|
+
let isMatch = false;
|
|
10806
|
+
if (cleanPath === "/") {
|
|
10807
|
+
isMatch = normPlace === "/" || normPlace.startsWith("/?") || normPlace.startsWith("/#");
|
|
10808
|
+
} else {
|
|
10809
|
+
isMatch = normPlace === cleanPath || normPlace.startsWith(`${cleanPath}/`) || normPlace.startsWith(`${cleanPath}?`) || normPlace.startsWith(`${cleanPath}#`);
|
|
10810
|
+
}
|
|
10811
|
+
if (isMatch) {
|
|
10812
|
+
const prevLen = matchedCaps.get(cap.slug) ?? -1;
|
|
10813
|
+
if (cleanPath.length > prevLen) {
|
|
10814
|
+
matchedCaps.set(cap.slug, cleanPath.length);
|
|
10815
|
+
}
|
|
10816
|
+
}
|
|
10817
|
+
}
|
|
10818
|
+
}
|
|
10819
|
+
if (matchedCaps.size > 0) {
|
|
10820
|
+
return Array.from(matchedCaps.entries()).sort((a, b) => b[1] - a[1]).map(([slug]) => slug);
|
|
10821
|
+
}
|
|
10822
|
+
const firstSegment = normPlace.replace(/^\/+/, "").split(/[/\\?#]/)[0];
|
|
10823
|
+
if (firstSegment) {
|
|
10824
|
+
const slugMatches = [];
|
|
10825
|
+
for (const c of capabilities) {
|
|
10826
|
+
if (c.slug === firstSegment || c.slug.toLowerCase() === firstSegment.toLowerCase()) {
|
|
10827
|
+
slugMatches.push(c.slug);
|
|
10828
|
+
}
|
|
10829
|
+
}
|
|
10830
|
+
if (slugMatches.length > 0)
|
|
10831
|
+
return slugMatches;
|
|
10832
|
+
}
|
|
10833
|
+
return [];
|
|
10834
|
+
}
|
|
10835
|
+
function summarizeCapabilityCoverage(surfaces, capabilities, outlines = []) {
|
|
10836
|
+
const capMap = /* @__PURE__ */ new Map();
|
|
10837
|
+
for (const c of capabilities) {
|
|
10838
|
+
capMap.set(c.slug, []);
|
|
10839
|
+
}
|
|
10840
|
+
const unassigned = [];
|
|
10841
|
+
for (const s of surfaces) {
|
|
10842
|
+
const matchedSlugs = matchSurfaceCapabilities(s.place, capabilities);
|
|
10843
|
+
if (matchedSlugs.length > 0) {
|
|
10844
|
+
for (const slug of matchedSlugs) {
|
|
10845
|
+
capMap.get(slug)?.push(s);
|
|
10846
|
+
}
|
|
10847
|
+
} else {
|
|
10848
|
+
unassigned.push(s);
|
|
10849
|
+
}
|
|
10850
|
+
}
|
|
10851
|
+
const primaryCounts = /* @__PURE__ */ new Map();
|
|
10852
|
+
const secondaryCounts = /* @__PURE__ */ new Map();
|
|
10853
|
+
for (const o of outlines) {
|
|
10854
|
+
if (o.primary_capability) {
|
|
10855
|
+
primaryCounts.set(o.primary_capability, (primaryCounts.get(o.primary_capability) ?? 0) + 1);
|
|
10856
|
+
}
|
|
10857
|
+
if (Array.isArray(o.additional_capabilities)) {
|
|
10858
|
+
for (const add of o.additional_capabilities) {
|
|
10859
|
+
if (add) {
|
|
10860
|
+
secondaryCounts.set(add, (secondaryCounts.get(add) ?? 0) + 1);
|
|
10861
|
+
}
|
|
10862
|
+
}
|
|
10863
|
+
}
|
|
10864
|
+
}
|
|
10865
|
+
const summaries = capabilities.map((c) => {
|
|
10866
|
+
const owned = capMap.get(c.slug) ?? [];
|
|
10867
|
+
const reached = owned.filter((s) => s.status === "reached").length;
|
|
10868
|
+
const unreached = owned.length - reached;
|
|
10869
|
+
const coverage_pct = owned.length > 0 ? Math.round(reached / owned.length * 100) : 0;
|
|
10870
|
+
const primary = primaryCounts.get(c.slug) ?? 0;
|
|
10871
|
+
const secondary = secondaryCounts.get(c.slug) ?? 0;
|
|
10872
|
+
return {
|
|
10873
|
+
slug: c.slug,
|
|
10874
|
+
title: c.title,
|
|
10875
|
+
area: c.area ?? null,
|
|
10876
|
+
total_surfaces: owned.length,
|
|
10877
|
+
reached_surfaces: reached,
|
|
10878
|
+
unreached_surfaces: unreached,
|
|
10879
|
+
coverage_pct,
|
|
10880
|
+
primary_scenarios: primary,
|
|
10881
|
+
secondary_scenarios: secondary,
|
|
10882
|
+
surfaces: owned
|
|
10883
|
+
};
|
|
10884
|
+
});
|
|
10885
|
+
summaries.sort((a, b) => {
|
|
10886
|
+
const aUntested = a.primary_scenarios === 0 && a.unreached_surfaces > 0;
|
|
10887
|
+
const bUntested = b.primary_scenarios === 0 && b.unreached_surfaces > 0;
|
|
10888
|
+
if (aUntested !== bUntested)
|
|
10889
|
+
return aUntested ? -1 : 1;
|
|
10890
|
+
if (a.coverage_pct !== b.coverage_pct)
|
|
10891
|
+
return a.coverage_pct - b.coverage_pct;
|
|
10892
|
+
return a.slug.localeCompare(b.slug);
|
|
10893
|
+
});
|
|
10894
|
+
return {
|
|
10895
|
+
capabilities: summaries,
|
|
10896
|
+
unassigned_surfaces: unassigned
|
|
10897
|
+
};
|
|
10898
|
+
}
|
|
10899
|
+
async function readCapabilityCoverage(projectRoot, coverage) {
|
|
10900
|
+
const [capsResult, outlinesResult] = await Promise.all([
|
|
10901
|
+
listEntities(projectRoot, "capability"),
|
|
10902
|
+
listEntities(projectRoot, "outline")
|
|
10903
|
+
]);
|
|
10904
|
+
const caps = capsResult.entities.map((e) => ({
|
|
10905
|
+
slug: e.frontmatter.slug,
|
|
10906
|
+
title: e.frontmatter.title,
|
|
10907
|
+
area: e.frontmatter.area ?? null,
|
|
10908
|
+
paths: e.frontmatter.paths ?? []
|
|
10909
|
+
}));
|
|
10910
|
+
const outlines = outlinesResult.entities.map((e) => ({
|
|
10911
|
+
primary_capability: e.frontmatter.primary_capability,
|
|
10912
|
+
additional_capabilities: e.frontmatter.additional_capabilities ?? []
|
|
10913
|
+
}));
|
|
10914
|
+
return summarizeCapabilityCoverage(coverage.surfaces, caps, outlines);
|
|
10915
|
+
}
|
|
10701
10916
|
function actionSignature(a) {
|
|
10702
10917
|
const where = a.outcome.kind === "surface" ? a.outcome.surface : a.outcome.kind === "skipped" ? `skipped:${a.outcome.reason}` : a.outcome.kind === "external" ? `external:${a.outcome.url}` : a.outcome.kind;
|
|
10703
10918
|
return `${a.role} "${a.name}" \u2192 ${where}`;
|
|
@@ -10742,6 +10957,7 @@ var init_explore_map = __esm({
|
|
|
10742
10957
|
"../../packages/local-store/dist/explore-map.js"() {
|
|
10743
10958
|
"use strict";
|
|
10744
10959
|
init_atomic();
|
|
10960
|
+
init_entity();
|
|
10745
10961
|
init_paths();
|
|
10746
10962
|
init_revisit();
|
|
10747
10963
|
init_runs();
|
|
@@ -10754,7 +10970,7 @@ var init_explore_map = __esm({
|
|
|
10754
10970
|
});
|
|
10755
10971
|
|
|
10756
10972
|
// ../../packages/local-store/dist/human-test-link.js
|
|
10757
|
-
import { promises as
|
|
10973
|
+
import { promises as fs21 } from "fs";
|
|
10758
10974
|
import path16 from "path";
|
|
10759
10975
|
function humanTestLinks(verdicts) {
|
|
10760
10976
|
const best = /* @__PURE__ */ new Map();
|
|
@@ -10778,7 +10994,7 @@ async function linkFindingsToHumanTests(projectRoot, runId, verdicts) {
|
|
|
10778
10994
|
const dir = entityDirPath(projectRoot, "finding");
|
|
10779
10995
|
let names;
|
|
10780
10996
|
try {
|
|
10781
|
-
names = await
|
|
10997
|
+
names = await fs21.readdir(dir);
|
|
10782
10998
|
} catch {
|
|
10783
10999
|
return [];
|
|
10784
11000
|
}
|
|
@@ -10790,7 +11006,7 @@ async function linkFindingsToHumanTests(projectRoot, runId, verdicts) {
|
|
|
10790
11006
|
let raw;
|
|
10791
11007
|
let fm;
|
|
10792
11008
|
try {
|
|
10793
|
-
raw = await
|
|
11009
|
+
raw = await fs21.readFile(file, "utf8");
|
|
10794
11010
|
fm = parseFrontmatter(raw).frontmatter;
|
|
10795
11011
|
} catch {
|
|
10796
11012
|
continue;
|
|
@@ -11021,14 +11237,14 @@ var init_cloud_client = __esm({
|
|
|
11021
11237
|
});
|
|
11022
11238
|
|
|
11023
11239
|
// ../../packages/local-store/dist/last-pull.js
|
|
11024
|
-
import { promises as
|
|
11240
|
+
import { promises as fs22 } from "fs";
|
|
11025
11241
|
import path17 from "path";
|
|
11026
11242
|
function lastPullPath(projectRoot) {
|
|
11027
11243
|
return path17.join(cacheDir(projectRoot), "last-pull.json");
|
|
11028
11244
|
}
|
|
11029
11245
|
async function readLastPull(projectRoot) {
|
|
11030
11246
|
try {
|
|
11031
|
-
const raw = await
|
|
11247
|
+
const raw = await fs22.readFile(lastPullPath(projectRoot), "utf8");
|
|
11032
11248
|
const parsed = JSON.parse(raw);
|
|
11033
11249
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
11034
11250
|
return parsed;
|
|
@@ -11314,7 +11530,7 @@ var init_frontmatter2 = __esm({
|
|
|
11314
11530
|
});
|
|
11315
11531
|
|
|
11316
11532
|
// ../../packages/local-store/dist/pull/write.js
|
|
11317
|
-
import { promises as
|
|
11533
|
+
import { promises as fs23 } from "fs";
|
|
11318
11534
|
async function loadLocalIndex(projectRoot, type2) {
|
|
11319
11535
|
const byId = /* @__PURE__ */ new Map();
|
|
11320
11536
|
const bySlug = /* @__PURE__ */ new Map();
|
|
@@ -11343,7 +11559,7 @@ async function classifyExisting(projectRoot, type2, cloudId, localSlug, targetSl
|
|
|
11343
11559
|
if (localSlug !== targetSlug)
|
|
11344
11560
|
return "untracked";
|
|
11345
11561
|
const lastSynced = localIndex.lastPushById[cloudId];
|
|
11346
|
-
const bytes = await
|
|
11562
|
+
const bytes = await fs23.readFile(entityFilePath(projectRoot, type2, localSlug), "utf8");
|
|
11347
11563
|
return lastSynced && hashNormalizedContent(bytes) === lastSynced ? "fast_forward" : "diverged";
|
|
11348
11564
|
}
|
|
11349
11565
|
async function writeOrSkip(projectRoot, type2, cloudId, slug, frontmatter, body, localIndex, mode, cloudVersion) {
|
|
@@ -11404,13 +11620,13 @@ async function writeOrSkip(projectRoot, type2, cloudId, slug, frontmatter, body,
|
|
|
11404
11620
|
}
|
|
11405
11621
|
if (existingSlugForId && existingSlugForId !== slug) {
|
|
11406
11622
|
try {
|
|
11407
|
-
await
|
|
11623
|
+
await fs23.unlink(entityFilePath(projectRoot, type2, existingSlugForId));
|
|
11408
11624
|
localIndex.bySlug.delete(existingSlugForId);
|
|
11409
11625
|
} catch {
|
|
11410
11626
|
}
|
|
11411
11627
|
}
|
|
11412
11628
|
await writeEntity(projectRoot, type2, frontmatter, text);
|
|
11413
|
-
const bytes = await
|
|
11629
|
+
const bytes = await fs23.readFile(entityFilePath(projectRoot, type2, slug), "utf8");
|
|
11414
11630
|
const hash = hashNormalizedContent(bytes);
|
|
11415
11631
|
localIndex.byId.set(cloudId, slug);
|
|
11416
11632
|
localIndex.bySlug.set(slug, cloudId);
|
|
@@ -11464,7 +11680,7 @@ var init_write = __esm({
|
|
|
11464
11680
|
});
|
|
11465
11681
|
|
|
11466
11682
|
// ../../packages/local-store/dist/pull/entities.js
|
|
11467
|
-
import { promises as
|
|
11683
|
+
import { promises as fs24 } from "fs";
|
|
11468
11684
|
function buildContextFrontmatter(payload) {
|
|
11469
11685
|
const cloudCtx = payload.context ?? {};
|
|
11470
11686
|
const glossary = (payload.glossary ?? []).map((g) => ({
|
|
@@ -11519,7 +11735,7 @@ async function pullContext(projectRoot, cloud, projectId, mode, result) {
|
|
|
11519
11735
|
const frontmatter = buildContextFrontmatter(payload);
|
|
11520
11736
|
let hasLocal = false;
|
|
11521
11737
|
try {
|
|
11522
|
-
await
|
|
11738
|
+
await fs24.access(contextPath(projectRoot));
|
|
11523
11739
|
hasLocal = true;
|
|
11524
11740
|
} catch {
|
|
11525
11741
|
hasLocal = false;
|
|
@@ -11549,7 +11765,7 @@ async function pullContext(projectRoot, cloud, projectId, mode, result) {
|
|
|
11549
11765
|
frontmatter,
|
|
11550
11766
|
notes_body: existingNotes
|
|
11551
11767
|
});
|
|
11552
|
-
const bytes = await
|
|
11768
|
+
const bytes = await fs24.readFile(contextPath(projectRoot), "utf8");
|
|
11553
11769
|
const hash = hashNormalizedContent(bytes);
|
|
11554
11770
|
await recordLastPull(projectRoot, "context:root", hash);
|
|
11555
11771
|
await recordLastPush(projectRoot, "context:root", hash);
|
|
@@ -12069,6 +12285,7 @@ var init_dist2 = __esm({
|
|
|
12069
12285
|
init_bootstrap();
|
|
12070
12286
|
init_config2();
|
|
12071
12287
|
init_context2();
|
|
12288
|
+
init_testability2();
|
|
12072
12289
|
init_connect();
|
|
12073
12290
|
init_disconnect();
|
|
12074
12291
|
init_status();
|
|
@@ -12972,11 +13189,24 @@ import { dirname as dirname3, join as join4, resolve as resolve2 } from "path";
|
|
|
12972
13189
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
12973
13190
|
import chalk6 from "chalk";
|
|
12974
13191
|
function getVersion() {
|
|
13192
|
+
if ("0.2.0-beta.17") {
|
|
13193
|
+
return "0.2.0-beta.17";
|
|
13194
|
+
}
|
|
12975
13195
|
try {
|
|
12976
13196
|
const thisDir = dirname3(fileURLToPath2(import.meta.url));
|
|
12977
|
-
const
|
|
12978
|
-
|
|
12979
|
-
|
|
13197
|
+
for (const rel of [".", "..", "../.."]) {
|
|
13198
|
+
const pkgPath = resolve2(thisDir, rel, "package.json");
|
|
13199
|
+
if (existsSync5(pkgPath)) {
|
|
13200
|
+
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
13201
|
+
if (pkg.name === "@iamu-dev/iamu" && pkg.version) {
|
|
13202
|
+
return pkg.version;
|
|
13203
|
+
}
|
|
13204
|
+
if (pkg.version && pkg.version !== "0.0.0") {
|
|
13205
|
+
return pkg.version;
|
|
13206
|
+
}
|
|
13207
|
+
}
|
|
13208
|
+
}
|
|
13209
|
+
return "0.0.0";
|
|
12980
13210
|
} catch {
|
|
12981
13211
|
return "0.0.0";
|
|
12982
13212
|
}
|
|
@@ -14866,17 +15096,12 @@ __export(start_run_exports, {
|
|
|
14866
15096
|
startRun: () => startRun,
|
|
14867
15097
|
testabilityTarget: () => testabilityTarget
|
|
14868
15098
|
});
|
|
14869
|
-
import fs24 from "fs/promises";
|
|
14870
15099
|
import path20 from "path";
|
|
14871
15100
|
import chalk12 from "chalk";
|
|
14872
15101
|
async function testabilityTarget(projectRoot) {
|
|
14873
15102
|
try {
|
|
14874
|
-
const
|
|
14875
|
-
|
|
14876
|
-
"utf8"
|
|
14877
|
-
);
|
|
14878
|
-
const { frontmatter } = parseFrontmatter(raw);
|
|
14879
|
-
return typeof frontmatter.target_url === "string" && frontmatter.target_url.trim().length > 0 ? frontmatter.target_url.trim() : null;
|
|
15103
|
+
const doc = await readTestability(projectRoot);
|
|
15104
|
+
return doc?.frontmatter.target_url ?? null;
|
|
14880
15105
|
} catch {
|
|
14881
15106
|
return null;
|
|
14882
15107
|
}
|
|
@@ -15504,7 +15729,7 @@ var init_fatal = __esm({
|
|
|
15504
15729
|
|
|
15505
15730
|
// src/sync-mcp/tools.ts
|
|
15506
15731
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
15507
|
-
import { z as
|
|
15732
|
+
import { z as z25 } from "zod";
|
|
15508
15733
|
function getProjectRoot() {
|
|
15509
15734
|
const root = findProjectRoot(process.cwd());
|
|
15510
15735
|
if (!root)
|
|
@@ -15745,7 +15970,7 @@ function createSyncServer() {
|
|
|
15745
15970
|
server.tool(
|
|
15746
15971
|
"iamu_requests_claim",
|
|
15747
15972
|
"Claim one work request before working on it. Takes an exclusive lease (2h, renewable by re-claiming) so no teammate's agent does the same work. Returns the full payload: the finding's ui_fact and consequence with its local finding ids, or the scenario and target URL, plus `next` \u2014 the skill step to run. Fails with lease_held when someone else is on it.",
|
|
15748
|
-
{ id:
|
|
15973
|
+
{ id: z25.string().uuid().describe("Request id from iamu_requests") },
|
|
15749
15974
|
async ({ id }) => {
|
|
15750
15975
|
try {
|
|
15751
15976
|
const linked = await resolveLinkedCloudClient();
|
|
@@ -16405,11 +16630,14 @@ var init_serve = __esm({
|
|
|
16405
16630
|
// src/commands/init.ts
|
|
16406
16631
|
var init_exports = {};
|
|
16407
16632
|
__export(init_exports, {
|
|
16633
|
+
createDraftTestabilityContent: () => createDraftTestabilityContent,
|
|
16634
|
+
detectTargetPort: () => detectTargetPort,
|
|
16635
|
+
detectTargetUrl: () => detectTargetUrl,
|
|
16408
16636
|
init: () => init,
|
|
16409
16637
|
setupCommand: () => setupCommand
|
|
16410
16638
|
});
|
|
16411
16639
|
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
|
|
16412
|
-
import { mkdir as mkdir4, writeFile as writeFile3 } from "fs/promises";
|
|
16640
|
+
import { mkdir as mkdir4, readdir, writeFile as writeFile3 } from "fs/promises";
|
|
16413
16641
|
import { basename as basename2, join as join5 } from "path";
|
|
16414
16642
|
import { isCancel as isCancel3, multiselect, select as select3 } from "@clack/prompts";
|
|
16415
16643
|
import chalk18 from "chalk";
|
|
@@ -16437,6 +16665,81 @@ function setupCommand(projectRoot, hosts) {
|
|
|
16437
16665
|
if (hosts.every((h) => h.value === "claude")) return "/iamu:init";
|
|
16438
16666
|
return "/iamu-setup (Claude Code: /iamu:init)";
|
|
16439
16667
|
}
|
|
16668
|
+
function detectTargetPort(projectRoot) {
|
|
16669
|
+
if (process.env.PORT) {
|
|
16670
|
+
const p = Number.parseInt(process.env.PORT, 10);
|
|
16671
|
+
if (!Number.isNaN(p) && p > 0 && p <= 65535) return p;
|
|
16672
|
+
}
|
|
16673
|
+
for (const envFile of [".env.local", ".env.development", ".env"]) {
|
|
16674
|
+
const fullPath = join5(projectRoot, envFile);
|
|
16675
|
+
if (existsSync7(fullPath)) {
|
|
16676
|
+
try {
|
|
16677
|
+
const content = readFileSync5(fullPath, "utf-8");
|
|
16678
|
+
for (const line of content.split("\n")) {
|
|
16679
|
+
const trimmed = line.trim();
|
|
16680
|
+
if (trimmed.startsWith("#") || !trimmed.includes("=")) continue;
|
|
16681
|
+
const [key, ...rest] = trimmed.split("=");
|
|
16682
|
+
const k = key.trim();
|
|
16683
|
+
const val = rest.join("=").trim().replace(/^["']|["']$/g, "");
|
|
16684
|
+
if (k === "PORT" || k === "VITE_PORT") {
|
|
16685
|
+
const p = Number.parseInt(val, 10);
|
|
16686
|
+
if (!Number.isNaN(p) && p > 0 && p <= 65535) return p;
|
|
16687
|
+
}
|
|
16688
|
+
if (k === "NEXT_PUBLIC_APP_URL" || k === "APP_URL") {
|
|
16689
|
+
try {
|
|
16690
|
+
const url = new URL(val);
|
|
16691
|
+
if (url.port) return Number.parseInt(url.port, 10);
|
|
16692
|
+
} catch {
|
|
16693
|
+
}
|
|
16694
|
+
}
|
|
16695
|
+
}
|
|
16696
|
+
} catch {
|
|
16697
|
+
}
|
|
16698
|
+
}
|
|
16699
|
+
}
|
|
16700
|
+
const pkgPath = join5(projectRoot, "package.json");
|
|
16701
|
+
if (existsSync7(pkgPath)) {
|
|
16702
|
+
try {
|
|
16703
|
+
const pkg = JSON.parse(readFileSync5(pkgPath, "utf-8"));
|
|
16704
|
+
const scripts = pkg.scripts || {};
|
|
16705
|
+
for (const script of Object.values(scripts)) {
|
|
16706
|
+
if (typeof script !== "string") continue;
|
|
16707
|
+
const portMatch = script.match(/(?:-p|--port(?:=|\s+))(\d+)/);
|
|
16708
|
+
if (portMatch) {
|
|
16709
|
+
const p = Number.parseInt(portMatch[1], 10);
|
|
16710
|
+
if (!Number.isNaN(p) && p > 0 && p <= 65535) return p;
|
|
16711
|
+
}
|
|
16712
|
+
}
|
|
16713
|
+
const allDeps = {
|
|
16714
|
+
...pkg.dependencies || {},
|
|
16715
|
+
...pkg.devDependencies || {}
|
|
16716
|
+
};
|
|
16717
|
+
if ("astro" in allDeps) return 4321;
|
|
16718
|
+
if ("vite" in allDeps) return 5173;
|
|
16719
|
+
} catch {
|
|
16720
|
+
}
|
|
16721
|
+
}
|
|
16722
|
+
for (const f of ["astro.config.mjs", "astro.config.ts", "astro.config.js"]) {
|
|
16723
|
+
if (existsSync7(join5(projectRoot, f))) return 4321;
|
|
16724
|
+
}
|
|
16725
|
+
for (const f of [
|
|
16726
|
+
"vite.config.ts",
|
|
16727
|
+
"vite.config.js",
|
|
16728
|
+
"vite.config.mjs",
|
|
16729
|
+
"vite.config.cjs"
|
|
16730
|
+
]) {
|
|
16731
|
+
if (existsSync7(join5(projectRoot, f))) return 5173;
|
|
16732
|
+
}
|
|
16733
|
+
return void 0;
|
|
16734
|
+
}
|
|
16735
|
+
function detectTargetUrl(projectRoot) {
|
|
16736
|
+
const port = detectTargetPort(projectRoot);
|
|
16737
|
+
return port ? `http://localhost:${port}` : "http://localhost:3000";
|
|
16738
|
+
}
|
|
16739
|
+
function createDraftTestabilityContent(targetUrl = "http://localhost:3000") {
|
|
16740
|
+
const doc = emptyTestability(targetUrl);
|
|
16741
|
+
return serializeFrontmatter(doc.frontmatter, doc.body);
|
|
16742
|
+
}
|
|
16440
16743
|
async function init(opts) {
|
|
16441
16744
|
const options = typeof opts === "string" ? { name: opts } : opts ?? {};
|
|
16442
16745
|
const projectRoot = process.cwd();
|
|
@@ -16454,12 +16757,86 @@ async function init(opts) {
|
|
|
16454
16757
|
console.log();
|
|
16455
16758
|
}
|
|
16456
16759
|
let freshInit = false;
|
|
16760
|
+
const backfilled = [];
|
|
16457
16761
|
if (existsSync7(join5(iamuDir2, "config.json"))) {
|
|
16458
|
-
const
|
|
16459
|
-
if (!
|
|
16460
|
-
|
|
16461
|
-
|
|
16762
|
+
const testabilityPath2 = join5(iamuDir2, "testability.md");
|
|
16763
|
+
if (!existsSync7(testabilityPath2)) {
|
|
16764
|
+
const targetUrl = detectTargetUrl(projectRoot);
|
|
16765
|
+
await writeFile3(
|
|
16766
|
+
testabilityPath2,
|
|
16767
|
+
createDraftTestabilityContent(targetUrl)
|
|
16768
|
+
);
|
|
16769
|
+
backfilled.push("testability.md");
|
|
16770
|
+
}
|
|
16771
|
+
const contextPath2 = join5(iamuDir2, "context.yml");
|
|
16772
|
+
if (!existsSync7(contextPath2)) {
|
|
16773
|
+
await writeFile3(
|
|
16774
|
+
contextPath2,
|
|
16775
|
+
serializeFrontmatter(
|
|
16776
|
+
{ status: "draft", schema_version: 1, name: projectName },
|
|
16777
|
+
""
|
|
16778
|
+
)
|
|
16462
16779
|
);
|
|
16780
|
+
backfilled.push("context.yml");
|
|
16781
|
+
}
|
|
16782
|
+
const gitignorePath = join5(iamuDir2, ".gitignore");
|
|
16783
|
+
if (!existsSync7(gitignorePath)) {
|
|
16784
|
+
await writeFile3(gitignorePath, GITIGNORE_CONTENT);
|
|
16785
|
+
backfilled.push(".gitignore");
|
|
16786
|
+
}
|
|
16787
|
+
const cacheDirPath = join5(iamuDir2, ".cache");
|
|
16788
|
+
if (!existsSync7(cacheDirPath)) {
|
|
16789
|
+
await mkdir4(cacheDirPath, { recursive: true });
|
|
16790
|
+
backfilled.push(".cache/");
|
|
16791
|
+
}
|
|
16792
|
+
const runsDirPath = join5(iamuDir2, ".runs");
|
|
16793
|
+
if (!existsSync7(runsDirPath)) {
|
|
16794
|
+
await mkdir4(runsDirPath, { recursive: true });
|
|
16795
|
+
}
|
|
16796
|
+
for (const type2 of ENTITY_TYPES) {
|
|
16797
|
+
const sub = join5(iamuDir2, ENTITY_DIRS[type2]);
|
|
16798
|
+
if (!existsSync7(sub)) {
|
|
16799
|
+
await mkdir4(sub, { recursive: true });
|
|
16800
|
+
}
|
|
16801
|
+
const keep = join5(sub, ".gitkeep");
|
|
16802
|
+
if (!existsSync7(keep)) {
|
|
16803
|
+
try {
|
|
16804
|
+
const files = await readdir(sub);
|
|
16805
|
+
if (files.length === 0) {
|
|
16806
|
+
await writeFile3(keep, "");
|
|
16807
|
+
}
|
|
16808
|
+
} catch {
|
|
16809
|
+
await writeFile3(keep, "");
|
|
16810
|
+
}
|
|
16811
|
+
}
|
|
16812
|
+
}
|
|
16813
|
+
const promptTemplates2 = loadPromptTemplates();
|
|
16814
|
+
const promptsDir2 = join5(iamuDir2, ".prompts");
|
|
16815
|
+
const missingPrompts = [];
|
|
16816
|
+
if (!existsSync7(promptsDir2)) {
|
|
16817
|
+
missingPrompts.push(".prompts/");
|
|
16818
|
+
} else {
|
|
16819
|
+
for (const [name] of promptTemplates2) {
|
|
16820
|
+
if (!existsSync7(join5(promptsDir2, name))) {
|
|
16821
|
+
missingPrompts.push(name);
|
|
16822
|
+
}
|
|
16823
|
+
}
|
|
16824
|
+
}
|
|
16825
|
+
if (missingPrompts.length > 0) {
|
|
16826
|
+
if (missingPrompts.includes(".prompts/")) {
|
|
16827
|
+
backfilled.push(".prompts/");
|
|
16828
|
+
} else {
|
|
16829
|
+
backfilled.push(...missingPrompts.map((p) => `.prompts/${p}`));
|
|
16830
|
+
}
|
|
16831
|
+
}
|
|
16832
|
+
if (!options.json) {
|
|
16833
|
+
if (backfilled.length > 0) {
|
|
16834
|
+
console.log(
|
|
16835
|
+
` ${symbols.success} Scaffolding verified (backfilled missing ${backfilled.join(", ")})`
|
|
16836
|
+
);
|
|
16837
|
+
} else {
|
|
16838
|
+
console.log(` ${symbols.success} Scaffolding up to date`);
|
|
16839
|
+
}
|
|
16463
16840
|
}
|
|
16464
16841
|
} else {
|
|
16465
16842
|
freshInit = true;
|
|
@@ -16475,33 +16852,12 @@ async function init(opts) {
|
|
|
16475
16852
|
""
|
|
16476
16853
|
)
|
|
16477
16854
|
);
|
|
16478
|
-
const
|
|
16479
|
-
if (!existsSync7(
|
|
16855
|
+
const testabilityPath2 = join5(iamuDir2, "testability.md");
|
|
16856
|
+
if (!existsSync7(testabilityPath2)) {
|
|
16857
|
+
const targetUrl = detectTargetUrl(projectRoot);
|
|
16480
16858
|
await writeFile3(
|
|
16481
|
-
|
|
16482
|
-
|
|
16483
|
-
{
|
|
16484
|
-
status: "draft",
|
|
16485
|
-
target_url: "http://localhost:3000"
|
|
16486
|
-
},
|
|
16487
|
-
`# Project Testability & Environment
|
|
16488
|
-
|
|
16489
|
-
Target URL and execution harness for walkthroughs.
|
|
16490
|
-
Audited and populated during /iamu:init.
|
|
16491
|
-
|
|
16492
|
-
## Target & Run Instructions
|
|
16493
|
-
- Default URL: http://localhost:3000
|
|
16494
|
-
|
|
16495
|
-
## Reachable Surfaces
|
|
16496
|
-
(Run /iamu:init to discover testable routes)
|
|
16497
|
-
|
|
16498
|
-
## Mocks & Data Fixtures
|
|
16499
|
-
(Run /iamu:init to inspect existing harnesses)
|
|
16500
|
-
|
|
16501
|
-
## Untestable Boundaries
|
|
16502
|
-
(None documented yet)
|
|
16503
|
-
`
|
|
16504
|
-
)
|
|
16859
|
+
testabilityPath2,
|
|
16860
|
+
createDraftTestabilityContent(targetUrl)
|
|
16505
16861
|
);
|
|
16506
16862
|
}
|
|
16507
16863
|
}
|
|
@@ -16511,7 +16867,13 @@ Audited and populated during /iamu:init.
|
|
|
16511
16867
|
for (const [name, content] of promptTemplates) {
|
|
16512
16868
|
await writeFile3(join5(promptsDir, name), content);
|
|
16513
16869
|
}
|
|
16514
|
-
const
|
|
16870
|
+
const detectedInstalled = detectInstalledHosts(projectRoot);
|
|
16871
|
+
const detectedWorkspace = detectHosts(projectRoot);
|
|
16872
|
+
const detectedMap = /* @__PURE__ */ new Map();
|
|
16873
|
+
for (const h of [...detectedInstalled, ...detectedWorkspace]) {
|
|
16874
|
+
detectedMap.set(h.value, h);
|
|
16875
|
+
}
|
|
16876
|
+
const detected = Array.from(detectedMap.values());
|
|
16515
16877
|
if (!options.json && detected.length > 0) {
|
|
16516
16878
|
console.log(
|
|
16517
16879
|
chalk18.dim(" Detected: ") + detected.map((h) => h.name).join(", ") + chalk18.dim(" (pre-selected)")
|
|
@@ -16620,6 +16982,7 @@ Audited and populated during /iamu:init.
|
|
|
16620
16982
|
projectName,
|
|
16621
16983
|
projectRoot,
|
|
16622
16984
|
fresh: freshInit,
|
|
16985
|
+
backfilled,
|
|
16623
16986
|
tools: selectedHosts.map((h) => h.name),
|
|
16624
16987
|
skillsCount: totalSkills,
|
|
16625
16988
|
commandsCount: totalCommands,
|
|
@@ -16721,6 +17084,7 @@ var init_init = __esm({
|
|
|
16721
17084
|
"src/commands/init.ts"() {
|
|
16722
17085
|
"use strict";
|
|
16723
17086
|
init_dist2();
|
|
17087
|
+
init_dist();
|
|
16724
17088
|
init_claude_plugin();
|
|
16725
17089
|
init_registry();
|
|
16726
17090
|
init_cloud_url();
|
|
@@ -16788,6 +17152,25 @@ async function status(opts) {
|
|
|
16788
17152
|
const incompleteRuns = await listIncompleteRuns(projectRoot);
|
|
16789
17153
|
const { rerun } = await computeFixStates(projectRoot);
|
|
16790
17154
|
const staleSkills = await findStaleSkills(projectRoot);
|
|
17155
|
+
let exploreSummary = null;
|
|
17156
|
+
try {
|
|
17157
|
+
const maps = await listExploreMaps(projectRoot);
|
|
17158
|
+
if (maps.length > 0) {
|
|
17159
|
+
const latestMapId = maps.at(-1);
|
|
17160
|
+
const map2 = await readExploreMap(projectRoot, latestMapId);
|
|
17161
|
+
if (map2) {
|
|
17162
|
+
const steps = await readAllRunSteps(projectRoot);
|
|
17163
|
+
const cov = exploreCoverage(map2, steps);
|
|
17164
|
+
exploreSummary = {
|
|
17165
|
+
map_id: latestMapId,
|
|
17166
|
+
total_surfaces: cov.surfaces.length,
|
|
17167
|
+
reached_surfaces: cov.reached,
|
|
17168
|
+
unreached_surfaces: cov.unreached
|
|
17169
|
+
};
|
|
17170
|
+
}
|
|
17171
|
+
}
|
|
17172
|
+
} catch {
|
|
17173
|
+
}
|
|
16791
17174
|
if (opts.json) {
|
|
16792
17175
|
console.log(
|
|
16793
17176
|
JSON.stringify(
|
|
@@ -16811,6 +17194,7 @@ async function status(opts) {
|
|
|
16811
17194
|
last: runs.at(-1) ?? null,
|
|
16812
17195
|
incomplete: incompleteRuns
|
|
16813
17196
|
},
|
|
17197
|
+
explore: exploreSummary,
|
|
16814
17198
|
rerun: rerun.map((r) => ({
|
|
16815
17199
|
...r,
|
|
16816
17200
|
command: rerunCommand(projectRoot, r.scenario)
|
|
@@ -16898,6 +17282,11 @@ async function status(opts) {
|
|
|
16898
17282
|
)
|
|
16899
17283
|
);
|
|
16900
17284
|
}
|
|
17285
|
+
if (exploreSummary) {
|
|
17286
|
+
console.log(
|
|
17287
|
+
` ${padRight("product map", 14)} ${chalk19.cyan(String(exploreSummary.total_surfaces))} surfaces (${chalk19.green(`${exploreSummary.reached_surfaces} reached`)} \xB7 ${chalk19.yellow(`${exploreSummary.unreached_surfaces} unreached`)})`
|
|
17288
|
+
);
|
|
17289
|
+
}
|
|
16901
17290
|
if (projectStatus.requests && projectStatus.requests.open > 0) {
|
|
16902
17291
|
console.log(
|
|
16903
17292
|
chalk19.cyan(
|
|
@@ -17200,7 +17589,7 @@ var init_browse_driver = __esm({
|
|
|
17200
17589
|
});
|
|
17201
17590
|
|
|
17202
17591
|
// src/commands/step-numbering.ts
|
|
17203
|
-
import { open, readdir, unlink } from "fs/promises";
|
|
17592
|
+
import { open, readdir as readdir2, unlink } from "fs/promises";
|
|
17204
17593
|
import path22 from "path";
|
|
17205
17594
|
function stepFileName(stepNumber2) {
|
|
17206
17595
|
return `${String(stepNumber2).padStart(3, "0")}.json`;
|
|
@@ -17209,7 +17598,7 @@ function stepLimitMessage(maxSteps, runId) {
|
|
|
17209
17598
|
return `Step limit of ${maxSteps} reached for run "${runId}". To prevent runaway agent loops, step aborted. Complete the walk with \`iamu complete\` or increase the limit with --max-steps <n>.`;
|
|
17210
17599
|
}
|
|
17211
17600
|
async function peekNextStepNumber(stepsDir) {
|
|
17212
|
-
const files = await
|
|
17601
|
+
const files = await readdir2(stepsDir).catch(() => []);
|
|
17213
17602
|
let max = 0;
|
|
17214
17603
|
for (const f of files) {
|
|
17215
17604
|
const m = /^(\d+)\.json$/.exec(f);
|
|
@@ -18278,7 +18667,7 @@ async function checkTargetHealth(targetUrl) {
|
|
|
18278
18667
|
const res = await fetch(targetUrl, {
|
|
18279
18668
|
method: "GET",
|
|
18280
18669
|
redirect: "manual",
|
|
18281
|
-
signal: AbortSignal.timeout(
|
|
18670
|
+
signal: AbortSignal.timeout(1e3)
|
|
18282
18671
|
});
|
|
18283
18672
|
if ([301, 302, 303, 307, 308].includes(res.status)) {
|
|
18284
18673
|
const location = res.headers.get("location") || "";
|
|
@@ -18392,21 +18781,20 @@ async function checkProjectHarnesses(projectRoot) {
|
|
|
18392
18781
|
}
|
|
18393
18782
|
async function checkProjectTestabilityContract(projectRoot) {
|
|
18394
18783
|
const checks = [];
|
|
18395
|
-
const testabilityPath = join7(projectRoot, "iamu", "testability.md");
|
|
18396
|
-
if (!existsSync10(testabilityPath)) {
|
|
18397
|
-
checks.push({
|
|
18398
|
-
category: "target",
|
|
18399
|
-
name: "Testability Contract (testability.md)",
|
|
18400
|
-
status: "warn",
|
|
18401
|
-
message: "iamu/testability.md not found",
|
|
18402
|
-
remedy: "Run `/iamu:init` to audit your codebase and record testable routes, auth strategies, and mock harnesses."
|
|
18403
|
-
});
|
|
18404
|
-
return { checks };
|
|
18405
|
-
}
|
|
18406
18784
|
try {
|
|
18407
|
-
const
|
|
18408
|
-
|
|
18409
|
-
|
|
18785
|
+
const doc = await readTestability(projectRoot);
|
|
18786
|
+
if (!doc) {
|
|
18787
|
+
checks.push({
|
|
18788
|
+
category: "target",
|
|
18789
|
+
name: "Testability Contract (testability.md)",
|
|
18790
|
+
status: "warn",
|
|
18791
|
+
message: "iamu/testability.md not found",
|
|
18792
|
+
remedy: "Run `/iamu:init` to audit your codebase and record testable routes, auth strategies, and mock harnesses."
|
|
18793
|
+
});
|
|
18794
|
+
return { checks };
|
|
18795
|
+
}
|
|
18796
|
+
const { frontmatter } = doc;
|
|
18797
|
+
const targetUrl = frontmatter.target_url;
|
|
18410
18798
|
const details = [];
|
|
18411
18799
|
if (targetUrl) details.push(`Target: ${targetUrl}`);
|
|
18412
18800
|
if (frontmatter.dev_command) {
|
|
@@ -19403,6 +19791,19 @@ async function update(opts) {
|
|
|
19403
19791
|
console.log(` ${symbols.success} ${promptsUpdated} prompts updated`);
|
|
19404
19792
|
}
|
|
19405
19793
|
}
|
|
19794
|
+
if (existsSync11(iamuDir2)) {
|
|
19795
|
+
const testabilityPath2 = join8(iamuDir2, "testability.md");
|
|
19796
|
+
if (!existsSync11(testabilityPath2)) {
|
|
19797
|
+
const targetUrl = detectTargetUrl(projectRoot);
|
|
19798
|
+
await writeFile4(
|
|
19799
|
+
testabilityPath2,
|
|
19800
|
+
createDraftTestabilityContent(targetUrl)
|
|
19801
|
+
);
|
|
19802
|
+
console.log(
|
|
19803
|
+
` ${symbols.success} Repaired testability contract: created iamu/testability.md (draft)`
|
|
19804
|
+
);
|
|
19805
|
+
}
|
|
19806
|
+
}
|
|
19406
19807
|
const { hosts: targetHosts, error } = resolveTargetHosts(
|
|
19407
19808
|
projectRoot,
|
|
19408
19809
|
opts?.host
|
|
@@ -19458,6 +19859,7 @@ var init_update = __esm({
|
|
|
19458
19859
|
init_mcp_config();
|
|
19459
19860
|
init_context4();
|
|
19460
19861
|
init_skills();
|
|
19862
|
+
init_init();
|
|
19461
19863
|
init_templates();
|
|
19462
19864
|
}
|
|
19463
19865
|
});
|
|
@@ -19483,11 +19885,13 @@ function defaultFrontmatter(type2, id, slug, name, opts) {
|
|
|
19483
19885
|
};
|
|
19484
19886
|
case "outline": {
|
|
19485
19887
|
const tests = Array.isArray(opts.humanTest) ? opts.humanTest : opts.humanTest ? [opts.humanTest] : [];
|
|
19888
|
+
const additionalCaps = Array.isArray(opts.additionalCapabilities) ? opts.additionalCapabilities : typeof opts.additionalCapabilities === "string" ? opts.additionalCapabilities.split(",").map((s) => s.trim()).filter(Boolean) : [];
|
|
19486
19889
|
return {
|
|
19487
19890
|
...base,
|
|
19488
19891
|
title: name,
|
|
19489
19892
|
...description,
|
|
19490
19893
|
...opts.capability ? { primary_capability: opts.capability } : {},
|
|
19894
|
+
...additionalCaps.length > 0 ? { additional_capabilities: additionalCaps } : {},
|
|
19491
19895
|
...opts.tension ? { tension: opts.tension } : {},
|
|
19492
19896
|
...opts.narrative ? { narrative: opts.narrative } : {},
|
|
19493
19897
|
...tests.length > 0 ? {
|
|
@@ -19498,8 +19902,16 @@ function defaultFrontmatter(type2, id, slug, name, opts) {
|
|
|
19498
19902
|
} : {}
|
|
19499
19903
|
};
|
|
19500
19904
|
}
|
|
19501
|
-
case "capability":
|
|
19502
|
-
|
|
19905
|
+
case "capability": {
|
|
19906
|
+
const capPaths = Array.isArray(opts.paths) ? opts.paths : typeof opts.paths === "string" ? opts.paths.split(",").map((s) => s.trim()).filter(Boolean) : [];
|
|
19907
|
+
return {
|
|
19908
|
+
...base,
|
|
19909
|
+
title: name,
|
|
19910
|
+
...description,
|
|
19911
|
+
...capPaths.length > 0 ? { paths: capPaths } : {},
|
|
19912
|
+
...opts.area ? { area: opts.area.trim() } : {}
|
|
19913
|
+
};
|
|
19914
|
+
}
|
|
19503
19915
|
case "source":
|
|
19504
19916
|
return {
|
|
19505
19917
|
...base,
|
|
@@ -20094,7 +20506,6 @@ __export(explore_exports, {
|
|
|
20094
20506
|
exploreList: () => exploreList,
|
|
20095
20507
|
exploreRun: () => exploreRun
|
|
20096
20508
|
});
|
|
20097
|
-
import { promises as fs28 } from "fs";
|
|
20098
20509
|
import path26 from "path";
|
|
20099
20510
|
import chalk27 from "chalk";
|
|
20100
20511
|
function fail2(message, json2) {
|
|
@@ -20112,12 +20523,8 @@ function positiveInt(raw, fallback, flag) {
|
|
|
20112
20523
|
}
|
|
20113
20524
|
async function testabilityTarget2(projectRoot) {
|
|
20114
20525
|
try {
|
|
20115
|
-
const
|
|
20116
|
-
|
|
20117
|
-
"utf8"
|
|
20118
|
-
);
|
|
20119
|
-
const { frontmatter } = parseFrontmatter(raw);
|
|
20120
|
-
return typeof frontmatter.target_url === "string" ? frontmatter.target_url : null;
|
|
20526
|
+
const doc = await readTestability(projectRoot);
|
|
20527
|
+
return doc?.frontmatter.target_url ?? null;
|
|
20121
20528
|
} catch {
|
|
20122
20529
|
return null;
|
|
20123
20530
|
}
|
|
@@ -20299,8 +20706,17 @@ async function exploreCoverageCommand(mapId, opts) {
|
|
|
20299
20706
|
return;
|
|
20300
20707
|
}
|
|
20301
20708
|
const cov = exploreCoverage(map2, await readAllRunSteps(ctx.projectRoot));
|
|
20709
|
+
const capReport = await readCapabilityCoverage(ctx.projectRoot, cov);
|
|
20302
20710
|
if (opts.json) {
|
|
20303
|
-
console.log(
|
|
20711
|
+
console.log(
|
|
20712
|
+
JSON.stringify({
|
|
20713
|
+
...cov,
|
|
20714
|
+
...capReport.capabilities.length > 0 ? {
|
|
20715
|
+
capabilities: capReport.capabilities,
|
|
20716
|
+
unassigned_surfaces: capReport.unassigned_surfaces
|
|
20717
|
+
} : {}
|
|
20718
|
+
})
|
|
20719
|
+
);
|
|
20304
20720
|
return;
|
|
20305
20721
|
}
|
|
20306
20722
|
console.log(
|
|
@@ -20310,26 +20726,122 @@ async function exploreCoverageCommand(mapId, opts) {
|
|
|
20310
20726
|
console.log(
|
|
20311
20727
|
` ${chalk27.green(`${cov.reached} reached`)} \xB7 ${chalk27.yellow(`${cov.place_only} URL reached, view unclear`)} \xB7 ${chalk27.red(`${cov.unreached} never reached`)}`
|
|
20312
20728
|
);
|
|
20313
|
-
|
|
20314
|
-
|
|
20315
|
-
console.log(
|
|
20316
|
-
|
|
20317
|
-
|
|
20729
|
+
if (capReport.capabilities.length > 0) {
|
|
20730
|
+
console.log(chalk27.bold("\n CAPABILITY COVERAGE"));
|
|
20731
|
+
console.log(
|
|
20732
|
+
chalk27.dim(
|
|
20733
|
+
" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
|
20734
|
+
)
|
|
20735
|
+
);
|
|
20736
|
+
console.log(
|
|
20737
|
+
chalk27.dim(
|
|
20738
|
+
` ${"Capability".padEnd(24)} ${"Surfaces".padStart(8)} ${"Coverage".padStart(8)} ${"Scenarios (1\xB0 / 2\xB0)"}`
|
|
20739
|
+
)
|
|
20740
|
+
);
|
|
20741
|
+
console.log(
|
|
20742
|
+
chalk27.dim(
|
|
20743
|
+
" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
|
20744
|
+
)
|
|
20745
|
+
);
|
|
20746
|
+
for (const cap of capReport.capabilities) {
|
|
20747
|
+
const title = cap.slug.padEnd(24);
|
|
20748
|
+
const surfaces = `${cap.reached_surfaces}/${cap.total_surfaces}`.padStart(
|
|
20749
|
+
8
|
|
20750
|
+
);
|
|
20751
|
+
const covStr = `${cap.coverage_pct}%`.padStart(8);
|
|
20752
|
+
const scenarios = `${cap.primary_scenarios} / ${cap.secondary_scenarios}`;
|
|
20753
|
+
const untestedFlag = cap.primary_scenarios === 0 && cap.unreached_surfaces > 0 ? chalk27.yellow(" (untested)") : "";
|
|
20754
|
+
const covColored = cap.coverage_pct === 100 ? chalk27.green(covStr) : cap.coverage_pct === 0 ? chalk27.red(covStr) : chalk27.yellow(covStr);
|
|
20318
20755
|
console.log(
|
|
20319
|
-
`
|
|
20756
|
+
` ${title} ${surfaces} ${covColored} ${scenarios}${untestedFlag}`
|
|
20320
20757
|
);
|
|
20321
20758
|
}
|
|
20322
|
-
|
|
20323
|
-
|
|
20324
|
-
|
|
20325
|
-
|
|
20326
|
-
|
|
20327
|
-
|
|
20328
|
-
|
|
20329
|
-
|
|
20330
|
-
|
|
20331
|
-
|
|
20332
|
-
|
|
20759
|
+
if (capReport.unassigned_surfaces.length > 0) {
|
|
20760
|
+
const unassigned = capReport.unassigned_surfaces;
|
|
20761
|
+
const reached = unassigned.filter((s) => s.status === "reached").length;
|
|
20762
|
+
const pct = Math.round(reached / unassigned.length * 100);
|
|
20763
|
+
console.log(
|
|
20764
|
+
chalk27.dim(
|
|
20765
|
+
` ${"(Unassigned)".padEnd(24)} ${`${reached}/${unassigned.length}`.padStart(8)} ${`${pct}%`.padStart(8)} -`
|
|
20766
|
+
)
|
|
20767
|
+
);
|
|
20768
|
+
}
|
|
20769
|
+
console.log(
|
|
20770
|
+
chalk27.dim(
|
|
20771
|
+
" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
|
20772
|
+
)
|
|
20773
|
+
);
|
|
20774
|
+
const hasGaps = capReport.capabilities.some((c) => c.unreached_surfaces > 0) || capReport.unassigned_surfaces.some((s) => s.status !== "reached");
|
|
20775
|
+
if (hasGaps) {
|
|
20776
|
+
console.log(chalk27.red("\n UNREACHED SURFACES (Gaps)"));
|
|
20777
|
+
for (const cap of capReport.capabilities) {
|
|
20778
|
+
const gaps = cap.surfaces.filter((s) => s.status !== "reached");
|
|
20779
|
+
if (gaps.length === 0) continue;
|
|
20780
|
+
console.log(` ${chalk27.bold(cap.slug)}:`);
|
|
20781
|
+
for (const s of gaps) {
|
|
20782
|
+
console.log(
|
|
20783
|
+
` ${chalk27.red("\u25CB")} ${s.key.padEnd(32)} ${s.label}${chalk27.dim(` (depth ${s.depth})`)}`
|
|
20784
|
+
);
|
|
20785
|
+
}
|
|
20786
|
+
}
|
|
20787
|
+
const unassignedGaps = capReport.unassigned_surfaces.filter(
|
|
20788
|
+
(s) => s.status !== "reached"
|
|
20789
|
+
);
|
|
20790
|
+
if (unassignedGaps.length > 0) {
|
|
20791
|
+
console.log(chalk27.dim(" (Unassigned):"));
|
|
20792
|
+
for (const s of unassignedGaps) {
|
|
20793
|
+
console.log(
|
|
20794
|
+
` ${chalk27.dim("\u25CB")} ${s.key.padEnd(32)} ${s.label}${chalk27.dim(` (depth ${s.depth})`)}`
|
|
20795
|
+
);
|
|
20796
|
+
}
|
|
20797
|
+
}
|
|
20798
|
+
}
|
|
20799
|
+
if (opts.all) {
|
|
20800
|
+
console.log(chalk27.green("\n REACHED SURFACES"));
|
|
20801
|
+
for (const cap of capReport.capabilities) {
|
|
20802
|
+
const reached = cap.surfaces.filter((s) => s.status === "reached");
|
|
20803
|
+
if (reached.length === 0) continue;
|
|
20804
|
+
console.log(` ${chalk27.bold(cap.slug)}:`);
|
|
20805
|
+
for (const s of reached) {
|
|
20806
|
+
console.log(
|
|
20807
|
+
` ${chalk27.green("\u2713")} ${s.key.padEnd(32)} ${s.label}${chalk27.dim(` (depth ${s.depth})`)}`
|
|
20808
|
+
);
|
|
20809
|
+
}
|
|
20810
|
+
}
|
|
20811
|
+
const unassignedReached = capReport.unassigned_surfaces.filter(
|
|
20812
|
+
(s) => s.status === "reached"
|
|
20813
|
+
);
|
|
20814
|
+
if (unassignedReached.length > 0) {
|
|
20815
|
+
console.log(chalk27.dim(" (Unassigned):"));
|
|
20816
|
+
for (const s of unassignedReached) {
|
|
20817
|
+
console.log(
|
|
20818
|
+
` ${chalk27.green("\u2713")} ${s.key.padEnd(32)} ${s.label}${chalk27.dim(` (depth ${s.depth})`)}`
|
|
20819
|
+
);
|
|
20820
|
+
}
|
|
20821
|
+
}
|
|
20822
|
+
}
|
|
20823
|
+
} else {
|
|
20824
|
+
const section = (title, rows, color) => {
|
|
20825
|
+
if (rows.length === 0) return;
|
|
20826
|
+
console.log(`
|
|
20827
|
+
${color(title)}`);
|
|
20828
|
+
for (const r of rows) {
|
|
20829
|
+
console.log(
|
|
20830
|
+
` ${r.key.padEnd(32)} ${r.label}${chalk27.dim(` (depth ${r.depth})`)}`
|
|
20831
|
+
);
|
|
20832
|
+
}
|
|
20833
|
+
};
|
|
20834
|
+
section(
|
|
20835
|
+
"Never reached by a run",
|
|
20836
|
+
cov.surfaces.filter((s) => s.status === "unreached"),
|
|
20837
|
+
chalk27.red
|
|
20838
|
+
);
|
|
20839
|
+
section(
|
|
20840
|
+
"URL reached, but no step names this view",
|
|
20841
|
+
cov.surfaces.filter((s) => s.status === "place_only"),
|
|
20842
|
+
chalk27.yellow
|
|
20843
|
+
);
|
|
20844
|
+
}
|
|
20333
20845
|
if (cov.run_only_places.length > 0) {
|
|
20334
20846
|
console.log(`
|
|
20335
20847
|
${chalk27.cyan("Walked by runs, not in the map")}`);
|
|
@@ -20889,17 +21401,13 @@ async function instructionsWalk(opts) {
|
|
|
20889
21401
|
}
|
|
20890
21402
|
const untestableBoundaries = [];
|
|
20891
21403
|
try {
|
|
20892
|
-
const
|
|
20893
|
-
if (
|
|
20894
|
-
|
|
20895
|
-
|
|
20896
|
-
if (!targetUrl && typeof frontmatter.target_url === "string" && frontmatter.target_url.trim().length > 0) {
|
|
20897
|
-
targetUrl = frontmatter.target_url.trim();
|
|
21404
|
+
const doc = await readTestability(projectRoot);
|
|
21405
|
+
if (doc) {
|
|
21406
|
+
if (!targetUrl && doc.frontmatter.target_url) {
|
|
21407
|
+
targetUrl = doc.frontmatter.target_url;
|
|
20898
21408
|
}
|
|
20899
|
-
const fromFm =
|
|
20900
|
-
|
|
20901
|
-
) ? frontmatter.untestable_boundaries.filter(Boolean) : [];
|
|
20902
|
-
const fromBody = extractUntestableBoundaries(body);
|
|
21409
|
+
const fromFm = doc.frontmatter.untestable_boundaries ?? [];
|
|
21410
|
+
const fromBody = extractUntestableBoundaries(doc.body);
|
|
20903
21411
|
untestableBoundaries.push(
|
|
20904
21412
|
...Array.from(/* @__PURE__ */ new Set([...fromFm, ...fromBody]))
|
|
20905
21413
|
);
|
|
@@ -21256,7 +21764,7 @@ var summary_exports = {};
|
|
|
21256
21764
|
__export(summary_exports, {
|
|
21257
21765
|
summaryCommand: () => summaryCommand
|
|
21258
21766
|
});
|
|
21259
|
-
import { promises as
|
|
21767
|
+
import { promises as fs28 } from "fs";
|
|
21260
21768
|
import path28 from "path";
|
|
21261
21769
|
import chalk30 from "chalk";
|
|
21262
21770
|
async function summaryCommand(runIdArg, opts) {
|
|
@@ -21283,7 +21791,7 @@ async function summaryCommand(runIdArg, opts) {
|
|
|
21283
21791
|
}
|
|
21284
21792
|
raw = Buffer.concat(chunks).toString("utf8");
|
|
21285
21793
|
} else {
|
|
21286
|
-
raw = await
|
|
21794
|
+
raw = await fs28.readFile(path28.resolve(projectRoot, opts.file), "utf8");
|
|
21287
21795
|
}
|
|
21288
21796
|
const parsed = JSON.parse(raw);
|
|
21289
21797
|
if (Array.isArray(parsed.what_worked)) {
|
|
@@ -21451,10 +21959,10 @@ __export(evaluate_exports, {
|
|
|
21451
21959
|
evaluate: () => evaluate,
|
|
21452
21960
|
evaluateRecord: () => evaluateRecord
|
|
21453
21961
|
});
|
|
21454
|
-
import { promises as
|
|
21962
|
+
import { promises as fs29 } from "fs";
|
|
21455
21963
|
import path29 from "path";
|
|
21456
21964
|
import chalk32 from "chalk";
|
|
21457
|
-
import { z as
|
|
21965
|
+
import { z as z26 } from "zod";
|
|
21458
21966
|
function formatIssues(error) {
|
|
21459
21967
|
return error.issues.map(
|
|
21460
21968
|
(i) => `${i.path.length > 0 ? i.path.join(".") : "(root)"}: ${i.message}`
|
|
@@ -21486,7 +21994,7 @@ async function evaluate(runId, opts) {
|
|
|
21486
21994
|
const canonicalPath = path29.join(runDirPath, "canonical.json");
|
|
21487
21995
|
let canonical;
|
|
21488
21996
|
try {
|
|
21489
|
-
const raw = await
|
|
21997
|
+
const raw = await fs29.readFile(canonicalPath, "utf8");
|
|
21490
21998
|
canonical = JSON.parse(raw);
|
|
21491
21999
|
} catch {
|
|
21492
22000
|
commandError(
|
|
@@ -21543,7 +22051,7 @@ async function evaluate(runId, opts) {
|
|
|
21543
22051
|
};
|
|
21544
22052
|
const prompt = composeJudgePrompt(input);
|
|
21545
22053
|
const promptFilePath = opts?.promptFile ?? path29.join(runDirPath, "judge_prompt.md");
|
|
21546
|
-
await
|
|
22054
|
+
await fs29.writeFile(promptFilePath, prompt, "utf8");
|
|
21547
22055
|
if (opts?.json) {
|
|
21548
22056
|
console.log(
|
|
21549
22057
|
JSON.stringify(
|
|
@@ -21570,7 +22078,7 @@ async function evaluateRecord(runId, opts) {
|
|
|
21570
22078
|
const canonicalPath = path29.join(runDirPath, "canonical.json");
|
|
21571
22079
|
let canonical;
|
|
21572
22080
|
try {
|
|
21573
|
-
const raw = await
|
|
22081
|
+
const raw = await fs29.readFile(canonicalPath, "utf8");
|
|
21574
22082
|
canonical = JSON.parse(raw);
|
|
21575
22083
|
} catch {
|
|
21576
22084
|
commandError(`No canonical.json for run: ${runId}`, opts);
|
|
@@ -21592,7 +22100,7 @@ async function evaluateRecord(runId, opts) {
|
|
|
21592
22100
|
}
|
|
21593
22101
|
raw = Buffer.concat(chunks).toString("utf8");
|
|
21594
22102
|
} else {
|
|
21595
|
-
raw = await
|
|
22103
|
+
raw = await fs29.readFile(opts.file, "utf8");
|
|
21596
22104
|
}
|
|
21597
22105
|
parsedFile = JSON.parse(raw);
|
|
21598
22106
|
} catch (err) {
|
|
@@ -21715,28 +22223,28 @@ var init_evaluate = __esm({
|
|
|
21715
22223
|
init_context4();
|
|
21716
22224
|
init_live_run_client();
|
|
21717
22225
|
init_view_results();
|
|
21718
|
-
verdictValueSchema =
|
|
21719
|
-
idList =
|
|
21720
|
-
verdictEntrySchema =
|
|
21721
|
-
human_test_id:
|
|
21722
|
-
id:
|
|
22226
|
+
verdictValueSchema = z26.enum(["yes", "partial", "no", "not_applicable"]);
|
|
22227
|
+
idList = z26.array(z26.string()).optional();
|
|
22228
|
+
verdictEntrySchema = z26.object({
|
|
22229
|
+
human_test_id: z26.string().min(1).optional(),
|
|
22230
|
+
id: z26.string().min(1).optional(),
|
|
21723
22231
|
verdict: verdictValueSchema,
|
|
21724
|
-
reasoning:
|
|
22232
|
+
reasoning: z26.string(),
|
|
21725
22233
|
grounding_step_ids: idList,
|
|
21726
22234
|
grounding_finding_ids: idList
|
|
21727
22235
|
}).refine((v) => Boolean(v.human_test_id ?? v.id), {
|
|
21728
22236
|
message: "must carry human_test_id (or id)",
|
|
21729
22237
|
path: ["human_test_id"]
|
|
21730
22238
|
});
|
|
21731
|
-
verdictsFileSchema =
|
|
21732
|
-
verdicts:
|
|
21733
|
-
human_tests:
|
|
21734
|
-
overall:
|
|
21735
|
-
provenance:
|
|
21736
|
-
judge_mode:
|
|
21737
|
-
prompt_id:
|
|
21738
|
-
prompt_version:
|
|
21739
|
-
model:
|
|
22239
|
+
verdictsFileSchema = z26.object({
|
|
22240
|
+
verdicts: z26.array(verdictEntrySchema).optional(),
|
|
22241
|
+
human_tests: z26.array(verdictEntrySchema).optional(),
|
|
22242
|
+
overall: z26.object({ answer: z26.string(), reasoning: z26.string() }).passthrough().optional(),
|
|
22243
|
+
provenance: z26.object({
|
|
22244
|
+
judge_mode: z26.string().optional(),
|
|
22245
|
+
prompt_id: z26.string().optional(),
|
|
22246
|
+
prompt_version: z26.string().optional(),
|
|
22247
|
+
model: z26.string().optional()
|
|
21740
22248
|
}).passthrough().optional()
|
|
21741
22249
|
});
|
|
21742
22250
|
}
|
|
@@ -21764,7 +22272,7 @@ __export(complete_exports, {
|
|
|
21764
22272
|
screenshotSizeWarning: () => screenshotSizeWarning,
|
|
21765
22273
|
validateCanonicalWalkthrough: () => validateCanonicalWalkthrough
|
|
21766
22274
|
});
|
|
21767
|
-
import { promises as
|
|
22275
|
+
import { promises as fs30 } from "fs";
|
|
21768
22276
|
import path30 from "path";
|
|
21769
22277
|
import chalk33 from "chalk";
|
|
21770
22278
|
async function complete(runId, opts) {
|
|
@@ -21791,7 +22299,7 @@ async function complete(runId, opts) {
|
|
|
21791
22299
|
const walkerSummary = await readWalkerSummary(run.runDirPath);
|
|
21792
22300
|
let judgeReported;
|
|
21793
22301
|
try {
|
|
21794
|
-
const verdictsRaw = await
|
|
22302
|
+
const verdictsRaw = await fs30.readFile(
|
|
21795
22303
|
path30.join(run.runDirPath, "verdicts.json"),
|
|
21796
22304
|
"utf8"
|
|
21797
22305
|
);
|
|
@@ -21844,7 +22352,7 @@ async function loadRun(runId, opts) {
|
|
|
21844
22352
|
if (!resolved) return null;
|
|
21845
22353
|
const { projectRoot, runDirPath } = resolved;
|
|
21846
22354
|
try {
|
|
21847
|
-
await
|
|
22355
|
+
await fs30.access(runDirPath);
|
|
21848
22356
|
} catch {
|
|
21849
22357
|
commandError(`Run not found: ${runId}`, opts);
|
|
21850
22358
|
return null;
|
|
@@ -21853,7 +22361,7 @@ async function loadRun(runId, opts) {
|
|
|
21853
22361
|
let manifest;
|
|
21854
22362
|
try {
|
|
21855
22363
|
manifest = JSON.parse(
|
|
21856
|
-
await
|
|
22364
|
+
await fs30.readFile(manifestPath, "utf8")
|
|
21857
22365
|
);
|
|
21858
22366
|
} catch {
|
|
21859
22367
|
commandError(`No walkthrough.json found for run: ${runId}`, opts);
|
|
@@ -21865,7 +22373,7 @@ async function reportAlreadyCompleted(run, opts) {
|
|
|
21865
22373
|
const { runId, manifest } = run;
|
|
21866
22374
|
if (opts?.json) {
|
|
21867
22375
|
try {
|
|
21868
|
-
const raw = await
|
|
22376
|
+
const raw = await fs30.readFile(
|
|
21869
22377
|
path30.join(run.runDirPath, "canonical.json"),
|
|
21870
22378
|
"utf8"
|
|
21871
22379
|
);
|
|
@@ -22055,14 +22563,14 @@ async function screenshotSizeWarning(runDirPath, viewport) {
|
|
|
22055
22563
|
const dir = path30.join(runDirPath, "screenshots");
|
|
22056
22564
|
let first;
|
|
22057
22565
|
try {
|
|
22058
|
-
first = (await
|
|
22566
|
+
first = (await fs30.readdir(dir)).filter((f) => f.toLowerCase().endsWith(".png")).sort((a, b) => a.localeCompare(b, void 0, { numeric: true }))[0];
|
|
22059
22567
|
} catch {
|
|
22060
22568
|
return null;
|
|
22061
22569
|
}
|
|
22062
22570
|
if (!first) return null;
|
|
22063
22571
|
let size = null;
|
|
22064
22572
|
try {
|
|
22065
|
-
const handle = await
|
|
22573
|
+
const handle = await fs30.open(path30.join(dir, first), "r");
|
|
22066
22574
|
try {
|
|
22067
22575
|
const head = Buffer.alloc(24);
|
|
22068
22576
|
const { bytesRead } = await handle.read(head, 0, 24, 0);
|
|
@@ -22079,7 +22587,7 @@ async function screenshotSizeWarning(runDirPath, viewport) {
|
|
|
22079
22587
|
async function readWalkerSummary(runDirPath) {
|
|
22080
22588
|
try {
|
|
22081
22589
|
const data = JSON.parse(
|
|
22082
|
-
await
|
|
22590
|
+
await fs30.readFile(path30.join(runDirPath, "summary.json"), "utf8")
|
|
22083
22591
|
);
|
|
22084
22592
|
const strings = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string" && x.trim() !== "") : void 0;
|
|
22085
22593
|
const model = typeof data.model === "string" && data.model.trim() !== "" ? data.model.trim() : void 0;
|
|
@@ -22188,7 +22696,7 @@ function validateCanonicalWalkthrough(canonical) {
|
|
|
22188
22696
|
async function applyRecordedVerdicts(canonical, runDirPath) {
|
|
22189
22697
|
try {
|
|
22190
22698
|
const recorded = JSON.parse(
|
|
22191
|
-
await
|
|
22699
|
+
await fs30.readFile(path30.join(runDirPath, "verdicts.json"), "utf8")
|
|
22192
22700
|
);
|
|
22193
22701
|
if (Array.isArray(recorded.verdicts)) {
|
|
22194
22702
|
return applyVerdicts(canonical, recorded);
|
|
@@ -22376,14 +22884,14 @@ __export(match_exports, {
|
|
|
22376
22884
|
match: () => match,
|
|
22377
22885
|
matchRecord: () => matchRecord
|
|
22378
22886
|
});
|
|
22379
|
-
import { promises as
|
|
22887
|
+
import { promises as fs31 } from "fs";
|
|
22380
22888
|
import path31 from "path";
|
|
22381
22889
|
import chalk34 from "chalk";
|
|
22382
22890
|
async function completedManifest2(runDirPath, runId, opts) {
|
|
22383
22891
|
let manifest;
|
|
22384
22892
|
try {
|
|
22385
22893
|
manifest = JSON.parse(
|
|
22386
|
-
await
|
|
22894
|
+
await fs31.readFile(path31.join(runDirPath, "walkthrough.json"), "utf8")
|
|
22387
22895
|
);
|
|
22388
22896
|
} catch {
|
|
22389
22897
|
commandError(`Run not found: ${runId}`, opts);
|
|
@@ -22414,10 +22922,10 @@ async function match(runId, opts) {
|
|
|
22414
22922
|
const prompt = needed ? composeMatchPrompt(input) : null;
|
|
22415
22923
|
const promptFilePath = opts?.promptFile ?? path31.join(runDirPath, "match_prompt.md");
|
|
22416
22924
|
if (prompt) {
|
|
22417
|
-
await
|
|
22925
|
+
await fs31.writeFile(promptFilePath, prompt, "utf8");
|
|
22418
22926
|
} else {
|
|
22419
22927
|
try {
|
|
22420
|
-
await
|
|
22928
|
+
await fs31.unlink(promptFilePath);
|
|
22421
22929
|
} catch {
|
|
22422
22930
|
}
|
|
22423
22931
|
}
|
|
@@ -22471,7 +22979,7 @@ async function matchRecord(runId, opts) {
|
|
|
22471
22979
|
}
|
|
22472
22980
|
raw = Buffer.concat(chunks).toString("utf8");
|
|
22473
22981
|
} else {
|
|
22474
|
-
raw = await
|
|
22982
|
+
raw = await fs31.readFile(opts.file, "utf8");
|
|
22475
22983
|
}
|
|
22476
22984
|
answer = JSON.parse(raw);
|
|
22477
22985
|
} catch (err) {
|
|
@@ -22851,6 +23359,12 @@ function registerProjectCommands(program) {
|
|
|
22851
23359
|
"--description <text>",
|
|
22852
23360
|
"One-line description (capability, outline)"
|
|
22853
23361
|
).option("--capability <slug>", "Primary capability slug (outline only)").option(
|
|
23362
|
+
"--additional-capabilities <slugs>",
|
|
23363
|
+
"Secondary capability slugs, comma-separated (outline only)"
|
|
23364
|
+
).option(
|
|
23365
|
+
"--paths <paths>",
|
|
23366
|
+
"Route patterns owned by this capability, comma-separated (capability only)"
|
|
23367
|
+
).option("--area <name>", "Visual grouping category (capability only)").option(
|
|
22854
23368
|
"--tension <text>",
|
|
22855
23369
|
"Structural tension driving this situation (outline only)"
|
|
22856
23370
|
).option(
|
|
@@ -22912,10 +23426,12 @@ Examples:
|
|
|
22912
23426
|
);
|
|
22913
23427
|
explore.command("coverage [map]").description(
|
|
22914
23428
|
"Surfaces of a map (default: latest) that no run reached, and places runs reached that the map lacks"
|
|
22915
|
-
).option("--json", "Output as JSON").
|
|
22916
|
-
|
|
22917
|
-
|
|
22918
|
-
|
|
23429
|
+
).option("--json", "Output as JSON").option("--all", "List all surfaces, including reached ones").action(
|
|
23430
|
+
async (map2, opts) => {
|
|
23431
|
+
const { exploreCoverageCommand: exploreCoverageCommand2 } = await Promise.resolve().then(() => (init_explore(), explore_exports));
|
|
23432
|
+
await exploreCoverageCommand2(map2, opts);
|
|
23433
|
+
}
|
|
23434
|
+
);
|
|
22919
23435
|
explore.command("diff [a] [b]").description("Compare two maps (default: the two latest)").option("--json", "Output as JSON").action(
|
|
22920
23436
|
async (a, b, opts) => {
|
|
22921
23437
|
const { exploreDiffCommand: exploreDiffCommand2 } = await Promise.resolve().then(() => (init_explore(), explore_exports));
|