@iamu-dev/iamu 0.2.0-beta.16 → 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 +16 -16
package/dist/bin.js
CHANGED
|
@@ -248,7 +248,14 @@ var init_capability = __esm({
|
|
|
248
248
|
capabilityFrontmatterSchema = entityBaseSchema.extend({
|
|
249
249
|
/** Human-readable title; corresponds to cloud `name`. */
|
|
250
250
|
title: z5.string().min(1),
|
|
251
|
-
description: z5.string().nullish()
|
|
251
|
+
description: z5.string().nullish(),
|
|
252
|
+
/**
|
|
253
|
+
* Route patterns owned by this capability (e.g. `["/billing", "/invoices"]`).
|
|
254
|
+
* Evaluated with segment-boundary Longest Prefix Match against surface places.
|
|
255
|
+
*/
|
|
256
|
+
paths: z5.array(z5.string()).default([]),
|
|
257
|
+
/** Optional visual grouping category (e.g. "Finance", "Administration"). */
|
|
258
|
+
area: z5.string().nullish()
|
|
252
259
|
});
|
|
253
260
|
}
|
|
254
261
|
});
|
|
@@ -874,6 +881,58 @@ var init_source = __esm({
|
|
|
874
881
|
}
|
|
875
882
|
});
|
|
876
883
|
|
|
884
|
+
// ../../packages/protocol/dist/schemas/frontmatter/testability.js
|
|
885
|
+
import { z as z17 } from "zod";
|
|
886
|
+
function emptyTestability(targetUrl = "http://localhost:3000") {
|
|
887
|
+
return {
|
|
888
|
+
frontmatter: {
|
|
889
|
+
schema_version: SCHEMA_VERSION,
|
|
890
|
+
status: "draft",
|
|
891
|
+
target_url: targetUrl
|
|
892
|
+
},
|
|
893
|
+
body: `# Project Testability & Environment
|
|
894
|
+
|
|
895
|
+
Target URL and execution harness for walkthroughs.
|
|
896
|
+
Audited and populated during /iamu:init.
|
|
897
|
+
|
|
898
|
+
## Target & Run Instructions
|
|
899
|
+
- Default URL: ${targetUrl}
|
|
900
|
+
|
|
901
|
+
## Reachable Surfaces
|
|
902
|
+
(Run /iamu:init to discover testable routes)
|
|
903
|
+
|
|
904
|
+
## Mocks & Data Fixtures
|
|
905
|
+
(Run /iamu:init to inspect existing harnesses)
|
|
906
|
+
|
|
907
|
+
## Untestable Boundaries
|
|
908
|
+
(None documented yet)
|
|
909
|
+
`
|
|
910
|
+
};
|
|
911
|
+
}
|
|
912
|
+
var testabilityStatusEnum, authStrategyEnum, testabilityFrontmatterSchema;
|
|
913
|
+
var init_testability = __esm({
|
|
914
|
+
"../../packages/protocol/dist/schemas/frontmatter/testability.js"() {
|
|
915
|
+
"use strict";
|
|
916
|
+
init_version();
|
|
917
|
+
testabilityStatusEnum = z17.enum(["draft", "verified"]);
|
|
918
|
+
authStrategyEnum = z17.enum([
|
|
919
|
+
"dev_switcher",
|
|
920
|
+
"interactive",
|
|
921
|
+
"test_accounts",
|
|
922
|
+
"public"
|
|
923
|
+
]);
|
|
924
|
+
testabilityFrontmatterSchema = z17.object({
|
|
925
|
+
schema_version: z17.number().int().optional(),
|
|
926
|
+
status: testabilityStatusEnum.default("draft"),
|
|
927
|
+
target_url: z17.string().url().describe("Target URL where the product is hosted or served locally."),
|
|
928
|
+
dev_command: z17.string().max(1e3).optional().describe("Dev script or startup command to boot the app locally."),
|
|
929
|
+
auth_strategy: authStrategyEnum.or(z17.string().min(1).max(100)).optional().describe("How personas authenticate in test environments."),
|
|
930
|
+
harnesses: z17.array(z17.string().min(1).max(500)).max(64).optional().describe("Mocking frameworks, seed scripts, or test harnesses present."),
|
|
931
|
+
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.")
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
});
|
|
935
|
+
|
|
877
936
|
// ../../packages/protocol/dist/schemas/frontmatter/index.js
|
|
878
937
|
var ENTITY_TYPES, entityFrontmatterSchemas, ENTITY_DIRS;
|
|
879
938
|
var init_frontmatter = __esm({
|
|
@@ -891,6 +950,7 @@ var init_frontmatter = __esm({
|
|
|
891
950
|
init_run_artifacts();
|
|
892
951
|
init_scenario();
|
|
893
952
|
init_source();
|
|
953
|
+
init_testability();
|
|
894
954
|
init_capability();
|
|
895
955
|
init_finding();
|
|
896
956
|
init_guidance();
|
|
@@ -929,7 +989,7 @@ var init_frontmatter = __esm({
|
|
|
929
989
|
});
|
|
930
990
|
|
|
931
991
|
// ../../packages/protocol/dist/device.js
|
|
932
|
-
import { z as
|
|
992
|
+
import { z as z18 } from "zod";
|
|
933
993
|
function deviceFromPersonaTags(tags) {
|
|
934
994
|
const matches = [];
|
|
935
995
|
for (const tag of tags ?? []) {
|
|
@@ -976,22 +1036,22 @@ var init_device = __esm({
|
|
|
976
1036
|
desktop: "desktop",
|
|
977
1037
|
laptop: "desktop"
|
|
978
1038
|
};
|
|
979
|
-
runViewportSchema =
|
|
980
|
-
device:
|
|
981
|
-
width:
|
|
982
|
-
height:
|
|
983
|
-
source:
|
|
1039
|
+
runViewportSchema = z18.object({
|
|
1040
|
+
device: z18.enum(DEVICE_CLASSES),
|
|
1041
|
+
width: z18.number().int().positive(),
|
|
1042
|
+
height: z18.number().int().positive(),
|
|
1043
|
+
source: z18.literal("persona-tags")
|
|
984
1044
|
});
|
|
985
1045
|
}
|
|
986
1046
|
});
|
|
987
1047
|
|
|
988
1048
|
// ../../packages/protocol/dist/types/fingerprint.js
|
|
989
|
-
import { z as
|
|
1049
|
+
import { z as z19 } from "zod";
|
|
990
1050
|
var stepActionTypeEnum, stepActionAnchorSchema, stepActionSchema, networkFingerprintEntrySchema, hex, stepFingerprintSchema;
|
|
991
1051
|
var init_fingerprint = __esm({
|
|
992
1052
|
"../../packages/protocol/dist/types/fingerprint.js"() {
|
|
993
1053
|
"use strict";
|
|
994
|
-
stepActionTypeEnum =
|
|
1054
|
+
stepActionTypeEnum = z19.enum([
|
|
995
1055
|
"click",
|
|
996
1056
|
"fill",
|
|
997
1057
|
"hover",
|
|
@@ -1001,46 +1061,46 @@ var init_fingerprint = __esm({
|
|
|
1001
1061
|
"done",
|
|
1002
1062
|
"note"
|
|
1003
1063
|
]);
|
|
1004
|
-
stepActionAnchorSchema =
|
|
1064
|
+
stepActionAnchorSchema = z19.object({
|
|
1005
1065
|
/** Max 512 chars to prevent bloating JSONB storage. */
|
|
1006
|
-
role:
|
|
1066
|
+
role: z19.string().max(512).optional(),
|
|
1007
1067
|
/** Max 512 chars to prevent bloating JSONB storage. */
|
|
1008
|
-
accessibleName:
|
|
1068
|
+
accessibleName: z19.string().max(512).optional(),
|
|
1009
1069
|
/** Max 512 chars to prevent bloating JSONB storage. */
|
|
1010
|
-
text:
|
|
1070
|
+
text: z19.string().max(512).optional()
|
|
1011
1071
|
});
|
|
1012
|
-
stepActionSchema =
|
|
1072
|
+
stepActionSchema = z19.object({
|
|
1013
1073
|
type: stepActionTypeEnum,
|
|
1014
1074
|
anchor: stepActionAnchorSchema.optional(),
|
|
1015
1075
|
/** Max 10 fallback selectors, each capped at 1024 chars. */
|
|
1016
|
-
selectorFallbacks:
|
|
1076
|
+
selectorFallbacks: z19.array(z19.string().max(1024)).max(10).optional()
|
|
1017
1077
|
});
|
|
1018
|
-
networkFingerprintEntrySchema =
|
|
1078
|
+
networkFingerprintEntrySchema = z19.object({
|
|
1019
1079
|
/** HTTP method, max 16 chars (e.g. "GET", "POST", "OPTIONS"). */
|
|
1020
|
-
method:
|
|
1080
|
+
method: z19.string().max(16),
|
|
1021
1081
|
/** Templated URL pattern, max 2048 chars. */
|
|
1022
|
-
urlPattern:
|
|
1023
|
-
status:
|
|
1082
|
+
urlPattern: z19.string().max(2048),
|
|
1083
|
+
status: z19.number().int().nonnegative()
|
|
1024
1084
|
});
|
|
1025
|
-
hex = (len) =>
|
|
1026
|
-
stepFingerprintSchema =
|
|
1085
|
+
hex = (len) => z19.string().regex(new RegExp(`^([0-9a-f]{${len}})?$`), `expected hex string of length ${len} or ""`);
|
|
1086
|
+
stepFingerprintSchema = z19.object({
|
|
1027
1087
|
/** Full page URL at time of step, max 4096 chars. */
|
|
1028
|
-
url:
|
|
1088
|
+
url: z19.string().max(4096),
|
|
1029
1089
|
action: stepActionSchema,
|
|
1030
1090
|
domHash: hex(64),
|
|
1031
1091
|
axTreeHash: hex(64),
|
|
1032
1092
|
screenshotPHash: hex(16),
|
|
1033
1093
|
/** Max 500 network entries to prevent runner abuse bloating JSONB. */
|
|
1034
|
-
networkFingerprint:
|
|
1035
|
-
consoleErrorCount:
|
|
1036
|
-
jsExceptionCount:
|
|
1037
|
-
settleDurationMs:
|
|
1094
|
+
networkFingerprint: z19.array(networkFingerprintEntrySchema).max(500),
|
|
1095
|
+
consoleErrorCount: z19.number().int().nonnegative(),
|
|
1096
|
+
jsExceptionCount: z19.number().int().nonnegative(),
|
|
1097
|
+
settleDurationMs: z19.number().int().nonnegative()
|
|
1038
1098
|
});
|
|
1039
1099
|
}
|
|
1040
1100
|
});
|
|
1041
1101
|
|
|
1042
1102
|
// ../../packages/protocol/dist/schemas/walkthrough-bundle.js
|
|
1043
|
-
import { z as
|
|
1103
|
+
import { z as z20 } from "zod";
|
|
1044
1104
|
function defaultEnvironment(targetUrl) {
|
|
1045
1105
|
try {
|
|
1046
1106
|
const origin = new URL(targetUrl).origin;
|
|
@@ -1059,147 +1119,147 @@ var init_walkthrough_bundle = __esm({
|
|
|
1059
1119
|
init_finding();
|
|
1060
1120
|
init_run_artifacts();
|
|
1061
1121
|
init_fingerprint();
|
|
1062
|
-
partNameSchema =
|
|
1122
|
+
partNameSchema = z20.string().min(1).max(128).regex(/^[a-z][a-z0-9_-]*$/, {
|
|
1063
1123
|
message: "part_name must be kebab-or-snake-case ASCII starting with a letter"
|
|
1064
1124
|
}).describe("Key of the matching multipart form field in the bundle body. Must match a binary part exactly.");
|
|
1065
|
-
artifactRefSchema =
|
|
1066
|
-
kind:
|
|
1125
|
+
artifactRefSchema = z20.object({
|
|
1126
|
+
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."),
|
|
1067
1127
|
part_name: partNameSchema,
|
|
1068
|
-
filename:
|
|
1069
|
-
content_type:
|
|
1070
|
-
bytes_hash:
|
|
1128
|
+
filename: z20.string().min(1).max(256).describe("Original filename as the client saw it. Used for logging and as a fallback display label."),
|
|
1129
|
+
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."),
|
|
1130
|
+
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.")
|
|
1071
1131
|
});
|
|
1072
|
-
stepScreenshotRefSchema =
|
|
1132
|
+
stepScreenshotRefSchema = z20.object({
|
|
1073
1133
|
part_name: partNameSchema,
|
|
1074
|
-
filename:
|
|
1075
|
-
content_type:
|
|
1134
|
+
filename: z20.string().min(1).max(256),
|
|
1135
|
+
content_type: z20.string().min(1).max(128)
|
|
1076
1136
|
});
|
|
1077
|
-
bundleStepSchema =
|
|
1078
|
-
seq:
|
|
1079
|
-
title:
|
|
1080
|
-
persona_reasoning:
|
|
1081
|
-
grounding:
|
|
1137
|
+
bundleStepSchema = z20.object({
|
|
1138
|
+
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."),
|
|
1139
|
+
title: z20.string().min(1).max(2048).describe("Short first-person heading for the step \u2014 shows in the rendered report."),
|
|
1140
|
+
persona_reasoning: z20.string().max(65536).nullable().optional().describe("First-person inner voice capture. Nullable for terse / action-only steps."),
|
|
1141
|
+
grounding: z20.string().max(65536).nullable().optional().describe("Optional citations, domain-knowledge grounding, or verification notes for this step."),
|
|
1082
1142
|
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)."),
|
|
1083
1143
|
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."),
|
|
1084
1144
|
screenshot_ref: stepScreenshotRefSchema.nullable().optional().describe("When present, identifies the multipart binary part carrying this step's screenshot bytes."),
|
|
1085
|
-
url:
|
|
1086
|
-
surface:
|
|
1145
|
+
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."),
|
|
1146
|
+
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.")
|
|
1087
1147
|
});
|
|
1088
|
-
bundleFindingSchema =
|
|
1148
|
+
bundleFindingSchema = z20.object({
|
|
1089
1149
|
slug: slugSchema,
|
|
1090
1150
|
frontmatter: findingFrontmatterSchema,
|
|
1091
|
-
body:
|
|
1092
|
-
screenshot_refs:
|
|
1151
|
+
body: z20.string().max(1048576).describe("Full markdown body of the finding file. 1 MiB cap matches the entity import envelope."),
|
|
1152
|
+
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).")
|
|
1093
1153
|
});
|
|
1094
|
-
verificationItemSchema =
|
|
1095
|
-
canonical_id:
|
|
1096
|
-
id:
|
|
1097
|
-
title:
|
|
1098
|
-
type:
|
|
1154
|
+
verificationItemSchema = z20.object({
|
|
1155
|
+
canonical_id: z20.string().max(64).optional(),
|
|
1156
|
+
id: z20.string().max(64).optional(),
|
|
1157
|
+
title: z20.string().max(1024),
|
|
1158
|
+
type: z20.string().max(32).optional()
|
|
1099
1159
|
});
|
|
1100
|
-
verificationGroup =
|
|
1101
|
-
bundleVerificationSchema =
|
|
1102
|
-
baseline_run_id:
|
|
1160
|
+
verificationGroup = z20.array(verificationItemSchema).max(500);
|
|
1161
|
+
bundleVerificationSchema = z20.object({
|
|
1162
|
+
baseline_run_id: z20.string().max(256),
|
|
1103
1163
|
resolved: verificationGroup.default([]),
|
|
1104
1164
|
persists: verificationGroup.default([]),
|
|
1105
1165
|
not_observed: verificationGroup.default([]),
|
|
1106
1166
|
uncertain: verificationGroup.default([]),
|
|
1107
1167
|
new_findings: verificationGroup.default([])
|
|
1108
1168
|
});
|
|
1109
|
-
buildMetadataSchema =
|
|
1110
|
-
label:
|
|
1111
|
-
git_sha:
|
|
1112
|
-
git_branch:
|
|
1113
|
-
base_sha:
|
|
1169
|
+
buildMetadataSchema = z20.object({
|
|
1170
|
+
label: z20.string().min(1).max(200).optional().describe("Human label for the build, from `iamu start-run --build`."),
|
|
1171
|
+
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."),
|
|
1172
|
+
git_branch: z20.string().min(1).max(255).optional(),
|
|
1173
|
+
base_sha: z20.string().regex(/^[0-9a-f]{7,64}$/i, {
|
|
1114
1174
|
message: "base_sha must be a hex commit id"
|
|
1115
1175
|
}).optional().describe("Commit the change is compared against (pull-request base)."),
|
|
1116
|
-
git_dirty:
|
|
1117
|
-
worktree_hash:
|
|
1176
|
+
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."),
|
|
1177
|
+
worktree_hash: z20.string().regex(/^[0-9a-f]{12}$/, {
|
|
1118
1178
|
message: "worktree_hash must be 12 lowercase hex characters"
|
|
1119
1179
|
}).optional().describe("Only when `git_dirty`: fingerprint of the uncommitted changes, so two runs on one commit with different edits are different builds."),
|
|
1120
|
-
ci:
|
|
1121
|
-
provider:
|
|
1122
|
-
run_url:
|
|
1180
|
+
ci: z20.object({
|
|
1181
|
+
provider: z20.string().min(1).max(64).describe("CI system that ran the walk, e.g. `github`, `azure`."),
|
|
1182
|
+
run_url: z20.string().url().max(2048)
|
|
1123
1183
|
}).optional()
|
|
1124
1184
|
});
|
|
1125
1185
|
ENVIRONMENT_MAX_LENGTH = 255;
|
|
1126
|
-
bundleManifestSchema =
|
|
1127
|
-
run_id:
|
|
1128
|
-
scenario_id:
|
|
1129
|
-
target_url:
|
|
1130
|
-
lenses:
|
|
1131
|
-
status:
|
|
1132
|
-
client_origin:
|
|
1186
|
+
bundleManifestSchema = z20.object({
|
|
1187
|
+
run_id: z20.string().uuid().describe("Client-minted UUID. Becomes `walkthroughs.id` on cloud. Idempotent key for the push endpoint."),
|
|
1188
|
+
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."),
|
|
1189
|
+
target_url: z20.string().url().max(2048),
|
|
1190
|
+
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."),
|
|
1191
|
+
status: z20.literal("completed").describe("v1 only accepts completed bundles (bundle-on-complete). In-progress runs are not pushable."),
|
|
1192
|
+
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."),
|
|
1133
1193
|
created_at: isoTimestamp,
|
|
1134
1194
|
completed_at: isoTimestamp,
|
|
1135
|
-
step_count:
|
|
1136
|
-
finding_count:
|
|
1137
|
-
report_markdown:
|
|
1138
|
-
what_worked:
|
|
1139
|
-
open_questions:
|
|
1195
|
+
step_count: z20.number().int().min(0).max(1e4),
|
|
1196
|
+
finding_count: z20.number().int().min(0).max(1e4),
|
|
1197
|
+
report_markdown: z20.string().max(1048576).describe("report.md body verbatim. Persists to walkthroughs.report_markdown so dashboard can render without regenerating."),
|
|
1198
|
+
what_worked: z20.array(z20.string().max(4096)).max(64).optional(),
|
|
1199
|
+
open_questions: z20.array(z20.string().max(4096)).max(64).optional(),
|
|
1140
1200
|
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."),
|
|
1141
1201
|
build: buildMetadataSchema.optional().describe("Build of the product under test (git SHA, branch, CI run). Absent for runs started before `start-run` recorded it."),
|
|
1142
|
-
environment:
|
|
1202
|
+
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`)."),
|
|
1143
1203
|
/** Holistic UX quality score from UX review pass. Present only when `lenses` includes "ux". */
|
|
1144
|
-
ux_quality_score:
|
|
1204
|
+
ux_quality_score: z20.number().min(1).max(5).nullish(),
|
|
1145
1205
|
/** One-line rationale naming 1-2 structural factors that determined the score. */
|
|
1146
|
-
ux_quality_rationale:
|
|
1147
|
-
verdict:
|
|
1148
|
-
humanTestId:
|
|
1149
|
-
human_test_id:
|
|
1150
|
-
question:
|
|
1151
|
-
rating:
|
|
1152
|
-
verdict:
|
|
1153
|
-
reasoning:
|
|
1154
|
-
groundingStepIds:
|
|
1155
|
-
grounding_step_ids:
|
|
1156
|
-
groundingFindingIds:
|
|
1157
|
-
grounding_finding_ids:
|
|
1206
|
+
ux_quality_rationale: z20.string().max(4096).nullish(),
|
|
1207
|
+
verdict: z20.array(z20.object({
|
|
1208
|
+
humanTestId: z20.string().optional(),
|
|
1209
|
+
human_test_id: z20.string().optional(),
|
|
1210
|
+
question: z20.string().default(""),
|
|
1211
|
+
rating: z20.enum(["yes", "no", "partial", "not_applicable"]).optional(),
|
|
1212
|
+
verdict: z20.enum(["yes", "no", "partial", "not_applicable"]).optional(),
|
|
1213
|
+
reasoning: z20.string(),
|
|
1214
|
+
groundingStepIds: z20.array(z20.string()).optional(),
|
|
1215
|
+
grounding_step_ids: z20.array(z20.string()).optional(),
|
|
1216
|
+
groundingFindingIds: z20.array(z20.string()).optional(),
|
|
1217
|
+
grounding_finding_ids: z20.array(z20.string()).optional()
|
|
1158
1218
|
}).refine((v) => Boolean(v.humanTestId || v.human_test_id) && Boolean(v.rating || v.verdict), {
|
|
1159
1219
|
message: "verdict item must include humanTestId or human_test_id, and rating or verdict"
|
|
1160
1220
|
})).optional(),
|
|
1161
|
-
judge_meta:
|
|
1162
|
-
overall:
|
|
1163
|
-
question:
|
|
1164
|
-
answer:
|
|
1165
|
-
reasoning:
|
|
1221
|
+
judge_meta: z20.object({
|
|
1222
|
+
overall: z20.object({
|
|
1223
|
+
question: z20.string(),
|
|
1224
|
+
answer: z20.string(),
|
|
1225
|
+
reasoning: z20.string()
|
|
1166
1226
|
}),
|
|
1167
|
-
provenance:
|
|
1168
|
-
judge_prompt:
|
|
1169
|
-
judge_model:
|
|
1227
|
+
provenance: z20.object({
|
|
1228
|
+
judge_prompt: z20.string().optional(),
|
|
1229
|
+
judge_model: z20.string().optional()
|
|
1170
1230
|
}).optional()
|
|
1171
1231
|
}).optional(),
|
|
1172
|
-
models:
|
|
1173
|
-
walker:
|
|
1174
|
-
matcher:
|
|
1175
|
-
judge:
|
|
1176
|
-
walker_reported:
|
|
1177
|
-
matcher_reported:
|
|
1178
|
-
judge_reported:
|
|
1179
|
-
walker_tier:
|
|
1180
|
-
matcher_tier:
|
|
1181
|
-
judge_tier:
|
|
1182
|
-
execution_mode:
|
|
1183
|
-
velocity_sec_per_step:
|
|
1184
|
-
total_duration_sec:
|
|
1232
|
+
models: z20.object({
|
|
1233
|
+
walker: z20.string().optional(),
|
|
1234
|
+
matcher: z20.string().optional(),
|
|
1235
|
+
judge: z20.string().optional(),
|
|
1236
|
+
walker_reported: z20.string().optional(),
|
|
1237
|
+
matcher_reported: z20.string().optional(),
|
|
1238
|
+
judge_reported: z20.string().optional(),
|
|
1239
|
+
walker_tier: z20.string().optional(),
|
|
1240
|
+
matcher_tier: z20.string().optional(),
|
|
1241
|
+
judge_tier: z20.string().optional(),
|
|
1242
|
+
execution_mode: z20.enum(["multi_agent", "single_agent"]).optional(),
|
|
1243
|
+
velocity_sec_per_step: z20.number().optional(),
|
|
1244
|
+
total_duration_sec: z20.number().optional()
|
|
1185
1245
|
}).optional().describe("AI model configuration and reported runtime provenance for this walkthrough.")
|
|
1186
1246
|
});
|
|
1187
|
-
walkthroughBundleSchema =
|
|
1247
|
+
walkthroughBundleSchema = z20.object({
|
|
1188
1248
|
manifest: bundleManifestSchema,
|
|
1189
|
-
steps:
|
|
1190
|
-
findings:
|
|
1191
|
-
artifacts:
|
|
1249
|
+
steps: z20.array(bundleStepSchema).max(1e4),
|
|
1250
|
+
findings: z20.array(bundleFindingSchema).max(1e4),
|
|
1251
|
+
artifacts: z20.array(artifactRefSchema).max(1e4)
|
|
1192
1252
|
}).superRefine((bundle, ctx) => {
|
|
1193
1253
|
if (bundle.manifest.step_count !== bundle.steps.length) {
|
|
1194
1254
|
ctx.addIssue({
|
|
1195
|
-
code:
|
|
1255
|
+
code: z20.ZodIssueCode.custom,
|
|
1196
1256
|
path: ["manifest", "step_count"],
|
|
1197
1257
|
message: `manifest.step_count (${bundle.manifest.step_count}) must equal steps.length (${bundle.steps.length})`
|
|
1198
1258
|
});
|
|
1199
1259
|
}
|
|
1200
1260
|
if (bundle.manifest.finding_count !== bundle.findings.length) {
|
|
1201
1261
|
ctx.addIssue({
|
|
1202
|
-
code:
|
|
1262
|
+
code: z20.ZodIssueCode.custom,
|
|
1203
1263
|
path: ["manifest", "finding_count"],
|
|
1204
1264
|
message: `manifest.finding_count (${bundle.manifest.finding_count}) must equal findings.length (${bundle.findings.length})`
|
|
1205
1265
|
});
|
|
@@ -1208,14 +1268,14 @@ var init_walkthrough_bundle = __esm({
|
|
|
1208
1268
|
const expected = Array.from({ length: bundle.steps.length }, (_, i) => i + 1);
|
|
1209
1269
|
if (seqs.join(",") !== expected.join(",")) {
|
|
1210
1270
|
ctx.addIssue({
|
|
1211
|
-
code:
|
|
1271
|
+
code: z20.ZodIssueCode.custom,
|
|
1212
1272
|
path: ["steps"],
|
|
1213
1273
|
message: `step seq values must be dense 1..${bundle.steps.length}; received [${seqs.join(",")}]`
|
|
1214
1274
|
});
|
|
1215
1275
|
}
|
|
1216
1276
|
if (bundle.steps.length === 0 && bundle.artifacts.length > 0) {
|
|
1217
1277
|
ctx.addIssue({
|
|
1218
|
-
code:
|
|
1278
|
+
code: z20.ZodIssueCode.custom,
|
|
1219
1279
|
path: ["steps"],
|
|
1220
1280
|
message: `bundle declares ${bundle.artifacts.length} artifact(s) but no steps \u2014 step records were not read`
|
|
1221
1281
|
});
|
|
@@ -1225,7 +1285,7 @@ var init_walkthrough_bundle = __esm({
|
|
|
1225
1285
|
for (const name of partNames) {
|
|
1226
1286
|
if (seen.has(name)) {
|
|
1227
1287
|
ctx.addIssue({
|
|
1228
|
-
code:
|
|
1288
|
+
code: z20.ZodIssueCode.custom,
|
|
1229
1289
|
path: ["artifacts"],
|
|
1230
1290
|
message: `duplicate artifact part_name: ${name}`
|
|
1231
1291
|
});
|
|
@@ -1237,7 +1297,7 @@ var init_walkthrough_bundle = __esm({
|
|
|
1237
1297
|
for (const [i, step] of bundle.steps.entries()) {
|
|
1238
1298
|
if (step.screenshot_ref && !artifactPartNames.has(step.screenshot_ref.part_name)) {
|
|
1239
1299
|
ctx.addIssue({
|
|
1240
|
-
code:
|
|
1300
|
+
code: z20.ZodIssueCode.custom,
|
|
1241
1301
|
path: ["steps", i, "screenshot_ref", "part_name"],
|
|
1242
1302
|
message: `step[${step.seq}].screenshot_ref.part_name "${step.screenshot_ref.part_name}" is not declared in artifacts[]`
|
|
1243
1303
|
});
|
|
@@ -1247,7 +1307,7 @@ var init_walkthrough_bundle = __esm({
|
|
|
1247
1307
|
for (const [j, ref] of (finding.screenshot_refs ?? []).entries()) {
|
|
1248
1308
|
if (!artifactPartNames.has(ref.part_name)) {
|
|
1249
1309
|
ctx.addIssue({
|
|
1250
|
-
code:
|
|
1310
|
+
code: z20.ZodIssueCode.custom,
|
|
1251
1311
|
path: ["findings", i, "screenshot_refs", j, "part_name"],
|
|
1252
1312
|
message: `finding[${finding.slug}].screenshot_refs[${j}].part_name "${ref.part_name}" is not declared in artifacts[]`
|
|
1253
1313
|
});
|
|
@@ -1257,7 +1317,7 @@ var init_walkthrough_bundle = __esm({
|
|
|
1257
1317
|
for (const [i, finding] of bundle.findings.entries()) {
|
|
1258
1318
|
if (finding.frontmatter.scenario !== bundle.manifest.scenario_id) {
|
|
1259
1319
|
ctx.addIssue({
|
|
1260
|
-
code:
|
|
1320
|
+
code: z20.ZodIssueCode.custom,
|
|
1261
1321
|
path: ["findings", i, "frontmatter", "scenario"],
|
|
1262
1322
|
message: `finding.frontmatter.scenario "${finding.frontmatter.scenario}" must match manifest.scenario_id "${bundle.manifest.scenario_id}"`
|
|
1263
1323
|
});
|
|
@@ -1266,7 +1326,7 @@ var init_walkthrough_bundle = __esm({
|
|
|
1266
1326
|
for (const [i, finding] of bundle.findings.entries()) {
|
|
1267
1327
|
if (finding.frontmatter.run !== bundle.manifest.run_id) {
|
|
1268
1328
|
ctx.addIssue({
|
|
1269
|
-
code:
|
|
1329
|
+
code: z20.ZodIssueCode.custom,
|
|
1270
1330
|
path: ["findings", i, "frontmatter", "run"],
|
|
1271
1331
|
message: `finding.frontmatter.run "${finding.frontmatter.run}" must match manifest.run_id "${bundle.manifest.run_id}"`
|
|
1272
1332
|
});
|
|
@@ -1278,30 +1338,30 @@ var init_walkthrough_bundle = __esm({
|
|
|
1278
1338
|
"updated",
|
|
1279
1339
|
"unchanged"
|
|
1280
1340
|
];
|
|
1281
|
-
walkthroughPushResponseSchema =
|
|
1282
|
-
run_id:
|
|
1283
|
-
cloud_walkthrough_id:
|
|
1284
|
-
status:
|
|
1285
|
-
step_count:
|
|
1286
|
-
finding_count:
|
|
1287
|
-
artifact_count:
|
|
1341
|
+
walkthroughPushResponseSchema = z20.object({
|
|
1342
|
+
run_id: z20.string().uuid(),
|
|
1343
|
+
cloud_walkthrough_id: z20.string().uuid(),
|
|
1344
|
+
status: z20.enum(WALKTHROUGH_PUSH_OUTCOMES),
|
|
1345
|
+
step_count: z20.number().int().min(0),
|
|
1346
|
+
finding_count: z20.number().int().min(0),
|
|
1347
|
+
artifact_count: z20.number().int().min(0)
|
|
1288
1348
|
});
|
|
1289
1349
|
WALKTHROUGH_CONFLICT_REASONS = [
|
|
1290
1350
|
"project_mismatch",
|
|
1291
1351
|
"scenario_mismatch",
|
|
1292
1352
|
"step_count_mismatch"
|
|
1293
1353
|
];
|
|
1294
|
-
walkthroughPushConflictSchema =
|
|
1295
|
-
code:
|
|
1296
|
-
reason:
|
|
1297
|
-
run_id:
|
|
1298
|
-
message:
|
|
1354
|
+
walkthroughPushConflictSchema = z20.object({
|
|
1355
|
+
code: z20.literal("walkthrough_conflict"),
|
|
1356
|
+
reason: z20.enum(WALKTHROUGH_CONFLICT_REASONS),
|
|
1357
|
+
run_id: z20.string().uuid(),
|
|
1358
|
+
message: z20.string()
|
|
1299
1359
|
});
|
|
1300
1360
|
}
|
|
1301
1361
|
});
|
|
1302
1362
|
|
|
1303
1363
|
// ../../packages/protocol/dist/types/walkthrough-canonical.js
|
|
1304
|
-
import { z as
|
|
1364
|
+
import { z as z21 } from "zod";
|
|
1305
1365
|
var CANONICAL_WALKTHROUGH_VERSION, canonicalScenarioRefSchema, canonicalTargetSchema, canonicalProvenanceSchema, canonicalStepSchema, canonicalFindingSchema, canonicalHumanTestSchema, canonicalHumanTestOverallSchema, canonicalErrorSchema, cloudMirrorStateSchema, canonicalWalkthroughSchema;
|
|
1306
1366
|
var init_walkthrough_canonical = __esm({
|
|
1307
1367
|
"../../packages/protocol/dist/types/walkthrough-canonical.js"() {
|
|
@@ -1311,106 +1371,106 @@ var init_walkthrough_canonical = __esm({
|
|
|
1311
1371
|
init_walkthrough_bundle();
|
|
1312
1372
|
init_enums();
|
|
1313
1373
|
CANONICAL_WALKTHROUGH_VERSION = "1.0.0";
|
|
1314
|
-
canonicalScenarioRefSchema =
|
|
1315
|
-
id:
|
|
1316
|
-
slug:
|
|
1317
|
-
persona_slug:
|
|
1318
|
-
outline_slug:
|
|
1319
|
-
brief:
|
|
1374
|
+
canonicalScenarioRefSchema = z21.object({
|
|
1375
|
+
id: z21.string(),
|
|
1376
|
+
slug: z21.string(),
|
|
1377
|
+
persona_slug: z21.string(),
|
|
1378
|
+
outline_slug: z21.string(),
|
|
1379
|
+
brief: z21.string()
|
|
1320
1380
|
}).passthrough();
|
|
1321
|
-
canonicalTargetSchema =
|
|
1322
|
-
url:
|
|
1381
|
+
canonicalTargetSchema = z21.object({
|
|
1382
|
+
url: z21.string(),
|
|
1323
1383
|
/** Where the product runs. "live" = real backend; "mock" = stubbed. */
|
|
1324
|
-
backend_mode:
|
|
1384
|
+
backend_mode: z21.enum(["live", "mock", "unknown"]),
|
|
1325
1385
|
/** Browser / runner used for the walk. */
|
|
1326
|
-
browser:
|
|
1386
|
+
browser: z21.string()
|
|
1327
1387
|
}).passthrough();
|
|
1328
|
-
canonicalProvenanceSchema =
|
|
1329
|
-
walker_prompt:
|
|
1330
|
-
judge_prompt:
|
|
1331
|
-
judge_mode:
|
|
1388
|
+
canonicalProvenanceSchema = z21.object({
|
|
1389
|
+
walker_prompt: z21.object({ id: z21.string(), version: z21.string() }).passthrough(),
|
|
1390
|
+
judge_prompt: z21.object({ id: z21.string(), version: z21.string() }).passthrough().optional(),
|
|
1391
|
+
judge_mode: z21.enum(["subagent", "same_agent_second_pass", "failed"]).optional(),
|
|
1332
1392
|
/** Model identifier used by the walker. Judge model (when it runs) is
|
|
1333
1393
|
* stamped inside `judge_meta.provenance.model` on the DB row. */
|
|
1334
|
-
model:
|
|
1394
|
+
model: z21.string(),
|
|
1335
1395
|
started_at: isoTimestamp,
|
|
1336
1396
|
completed_at: isoTimestamp
|
|
1337
1397
|
}).passthrough();
|
|
1338
|
-
canonicalStepSchema =
|
|
1339
|
-
id:
|
|
1340
|
-
step_number:
|
|
1341
|
-
url:
|
|
1398
|
+
canonicalStepSchema = z21.object({
|
|
1399
|
+
id: z21.string(),
|
|
1400
|
+
step_number: z21.number().int(),
|
|
1401
|
+
url: z21.string().optional(),
|
|
1342
1402
|
/** The walker's short name for the screen. */
|
|
1343
|
-
surface:
|
|
1344
|
-
screen_title:
|
|
1403
|
+
surface: z21.string().optional(),
|
|
1404
|
+
screen_title: z21.string().optional(),
|
|
1345
1405
|
/** Path reference to the screenshot file; never inline binary data. */
|
|
1346
|
-
screenshot_ref:
|
|
1347
|
-
persona_reasoning:
|
|
1348
|
-
grounding:
|
|
1349
|
-
action:
|
|
1406
|
+
screenshot_ref: z21.string().nullable().optional(),
|
|
1407
|
+
persona_reasoning: z21.string().nullable().optional(),
|
|
1408
|
+
grounding: z21.string().nullable().optional(),
|
|
1409
|
+
action: z21.string().optional()
|
|
1350
1410
|
}).passthrough();
|
|
1351
|
-
canonicalFindingSchema =
|
|
1352
|
-
id:
|
|
1411
|
+
canonicalFindingSchema = z21.object({
|
|
1412
|
+
id: z21.string(),
|
|
1353
1413
|
/** Stable across runs for pattern tracking — null until cross-run wiring lands. */
|
|
1354
|
-
canonical_id:
|
|
1414
|
+
canonical_id: z21.string().nullable(),
|
|
1355
1415
|
type: findingTypeEnum,
|
|
1356
|
-
severity:
|
|
1416
|
+
severity: z21.enum(["critical", "major", "minor", "observation"]).nullable(),
|
|
1357
1417
|
/** Depth-gate half 1: what the UI showed or did (observable without domain knowledge). */
|
|
1358
|
-
ui_fact:
|
|
1418
|
+
ui_fact: z21.string().nullable(),
|
|
1359
1419
|
/** Depth-gate half 2: what it means for the persona. Null on legacy rows (pre-migration). */
|
|
1360
|
-
consequence:
|
|
1361
|
-
recommendation:
|
|
1420
|
+
consequence: z21.string().nullable(),
|
|
1421
|
+
recommendation: z21.string().nullable(),
|
|
1362
1422
|
/** Step ids this finding cites as evidence (references `steps[].id`). */
|
|
1363
|
-
linked_step_ids:
|
|
1423
|
+
linked_step_ids: z21.array(z21.string()),
|
|
1364
1424
|
/** Parent scenario's human-test question id the finding bears on, if any. */
|
|
1365
|
-
linked_human_test_id:
|
|
1366
|
-
compliance_impact:
|
|
1367
|
-
task_impact:
|
|
1368
|
-
confidence:
|
|
1369
|
-
regulatory_weight:
|
|
1370
|
-
citations:
|
|
1425
|
+
linked_human_test_id: z21.string().nullable(),
|
|
1426
|
+
compliance_impact: z21.enum(["critical", "major", "minor", "informational"]).nullable().optional(),
|
|
1427
|
+
task_impact: z21.enum(["blocks", "impairs", "slows", "neutral", "accelerates", "enables"]).nullable().optional(),
|
|
1428
|
+
confidence: z21.enum(["high", "medium", "low"]).nullable().optional(),
|
|
1429
|
+
regulatory_weight: z21.enum(["hard_requirement", "process_model", "best_practice"]).nullable().optional(),
|
|
1430
|
+
citations: z21.array(z21.string()).optional()
|
|
1371
1431
|
}).passthrough();
|
|
1372
|
-
canonicalHumanTestSchema =
|
|
1373
|
-
id:
|
|
1374
|
-
question:
|
|
1432
|
+
canonicalHumanTestSchema = z21.object({
|
|
1433
|
+
id: z21.string(),
|
|
1434
|
+
question: z21.string(),
|
|
1375
1435
|
/** Null until judge stage writes via `record_judge_result`. */
|
|
1376
|
-
verdict:
|
|
1377
|
-
reasoning:
|
|
1378
|
-
grounding_step_ids:
|
|
1379
|
-
grounding_finding_ids:
|
|
1436
|
+
verdict: z21.enum(["yes", "partial", "no", "not_applicable"]).nullable(),
|
|
1437
|
+
reasoning: z21.string().nullable(),
|
|
1438
|
+
grounding_step_ids: z21.array(z21.string()),
|
|
1439
|
+
grounding_finding_ids: z21.array(z21.string())
|
|
1380
1440
|
}).passthrough();
|
|
1381
|
-
canonicalHumanTestOverallSchema =
|
|
1382
|
-
question:
|
|
1441
|
+
canonicalHumanTestOverallSchema = z21.object({
|
|
1442
|
+
question: z21.string(),
|
|
1383
1443
|
/** Null until judge stage answers. */
|
|
1384
|
-
answer:
|
|
1385
|
-
reasoning:
|
|
1444
|
+
answer: z21.string().nullable(),
|
|
1445
|
+
reasoning: z21.string().nullable()
|
|
1386
1446
|
}).passthrough();
|
|
1387
|
-
canonicalErrorSchema =
|
|
1388
|
-
stage:
|
|
1389
|
-
message:
|
|
1390
|
-
at:
|
|
1447
|
+
canonicalErrorSchema = z21.object({
|
|
1448
|
+
stage: z21.string(),
|
|
1449
|
+
message: z21.string(),
|
|
1450
|
+
at: z21.string()
|
|
1391
1451
|
}).passthrough();
|
|
1392
|
-
cloudMirrorStateSchema =
|
|
1452
|
+
cloudMirrorStateSchema = z21.enum([
|
|
1393
1453
|
"pushed",
|
|
1394
1454
|
"enqueued",
|
|
1395
1455
|
"local-only",
|
|
1396
1456
|
"already_pushed",
|
|
1397
1457
|
"skipped"
|
|
1398
1458
|
]);
|
|
1399
|
-
canonicalWalkthroughSchema =
|
|
1400
|
-
canonical_version:
|
|
1401
|
-
run_id:
|
|
1459
|
+
canonicalWalkthroughSchema = z21.object({
|
|
1460
|
+
canonical_version: z21.literal(CANONICAL_WALKTHROUGH_VERSION),
|
|
1461
|
+
run_id: z21.string(),
|
|
1402
1462
|
scenario: canonicalScenarioRefSchema,
|
|
1403
1463
|
target: canonicalTargetSchema,
|
|
1404
1464
|
provenance: canonicalProvenanceSchema,
|
|
1405
1465
|
build: buildMetadataSchema.optional(),
|
|
1406
1466
|
viewport: runViewportSchema.optional(),
|
|
1407
|
-
environment:
|
|
1408
|
-
models:
|
|
1409
|
-
findings:
|
|
1410
|
-
steps:
|
|
1411
|
-
human_tests:
|
|
1467
|
+
environment: z21.string().optional(),
|
|
1468
|
+
models: z21.record(z21.unknown()).optional(),
|
|
1469
|
+
findings: z21.array(canonicalFindingSchema),
|
|
1470
|
+
steps: z21.array(canonicalStepSchema),
|
|
1471
|
+
human_tests: z21.array(canonicalHumanTestSchema),
|
|
1412
1472
|
human_test_overall: canonicalHumanTestOverallSchema,
|
|
1413
|
-
errors:
|
|
1473
|
+
errors: z21.array(canonicalErrorSchema),
|
|
1414
1474
|
cloud_mirror_state: cloudMirrorStateSchema
|
|
1415
1475
|
}).passthrough();
|
|
1416
1476
|
}
|
|
@@ -1821,7 +1881,7 @@ var init_prompt_registry = __esm({
|
|
|
1821
1881
|
});
|
|
1822
1882
|
|
|
1823
1883
|
// ../../packages/protocol/dist/mcp-schemas.js
|
|
1824
|
-
import { z as
|
|
1884
|
+
import { z as z22 } from "zod";
|
|
1825
1885
|
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;
|
|
1826
1886
|
var init_mcp_schemas = __esm({
|
|
1827
1887
|
"../../packages/protocol/dist/mcp-schemas.js"() {
|
|
@@ -1833,352 +1893,352 @@ var init_mcp_schemas = __esm({
|
|
|
1833
1893
|
init_fingerprint();
|
|
1834
1894
|
AuthorityLevelSchema = authorityLevelEnum;
|
|
1835
1895
|
FindingTypeSchema = findingTypeEnum;
|
|
1836
|
-
MirrorStatusSchema =
|
|
1896
|
+
MirrorStatusSchema = z22.enum([
|
|
1837
1897
|
"synced",
|
|
1838
1898
|
"pending_retry",
|
|
1839
1899
|
"local_only",
|
|
1840
1900
|
"not_applicable"
|
|
1841
1901
|
]);
|
|
1842
|
-
FindingSummarySchema =
|
|
1843
|
-
id:
|
|
1844
|
-
slug:
|
|
1845
|
-
title:
|
|
1902
|
+
FindingSummarySchema = z22.object({
|
|
1903
|
+
id: z22.string(),
|
|
1904
|
+
slug: z22.string().nullable(),
|
|
1905
|
+
title: z22.string(),
|
|
1846
1906
|
type: FindingTypeSchema,
|
|
1847
1907
|
/** Discriminator: "canonical" for deduplicated cloud findings,
|
|
1848
1908
|
* "observation" for raw walkthrough findings (local or cloud). */
|
|
1849
|
-
kind:
|
|
1850
|
-
severity:
|
|
1851
|
-
triage_status:
|
|
1909
|
+
kind: z22.enum(["canonical", "observation"]),
|
|
1910
|
+
severity: z22.enum(["critical", "major", "minor", "observation"]).nullable().describe("Effective severity. Null when not yet assigned."),
|
|
1911
|
+
triage_status: z22.string().describe("open | addressed | dismissed"),
|
|
1852
1912
|
/** First 200 chars of the finding description. Fetch get_finding for the full text. */
|
|
1853
|
-
description:
|
|
1854
|
-
walkthrough_id:
|
|
1855
|
-
scenario_id:
|
|
1913
|
+
description: z22.string(),
|
|
1914
|
+
walkthrough_id: z22.string().nullable(),
|
|
1915
|
+
scenario_id: z22.string(),
|
|
1856
1916
|
created_at: isoTimestamp,
|
|
1857
|
-
canonical_id:
|
|
1858
|
-
cloud_mirrored:
|
|
1917
|
+
canonical_id: z22.string().nullable(),
|
|
1918
|
+
cloud_mirrored: z22.boolean()
|
|
1859
1919
|
});
|
|
1860
|
-
ScenarioSummarySchema =
|
|
1861
|
-
id:
|
|
1862
|
-
slug:
|
|
1863
|
-
outline_id:
|
|
1864
|
-
outline_slug:
|
|
1865
|
-
persona_id:
|
|
1866
|
-
persona_slug:
|
|
1920
|
+
ScenarioSummarySchema = z22.object({
|
|
1921
|
+
id: z22.string(),
|
|
1922
|
+
slug: z22.string().nullable(),
|
|
1923
|
+
outline_id: z22.string(),
|
|
1924
|
+
outline_slug: z22.string().nullable(),
|
|
1925
|
+
persona_id: z22.string(),
|
|
1926
|
+
persona_slug: z22.string().nullable(),
|
|
1867
1927
|
created_at: isoTimestamp,
|
|
1868
|
-
baseline_score:
|
|
1869
|
-
current_score:
|
|
1870
|
-
target_score:
|
|
1871
|
-
walkthrough_count:
|
|
1872
|
-
latest_walkthrough_id:
|
|
1873
|
-
cloud_mirrored:
|
|
1928
|
+
baseline_score: z22.number().nullable(),
|
|
1929
|
+
current_score: z22.number().nullable(),
|
|
1930
|
+
target_score: z22.number().nullable(),
|
|
1931
|
+
walkthrough_count: z22.number().int().nonnegative(),
|
|
1932
|
+
latest_walkthrough_id: z22.string().nullable(),
|
|
1933
|
+
cloud_mirrored: z22.boolean()
|
|
1874
1934
|
});
|
|
1875
|
-
RetrievalGapSchema =
|
|
1876
|
-
type:
|
|
1877
|
-
query:
|
|
1878
|
-
suggestion:
|
|
1935
|
+
RetrievalGapSchema = z22.object({
|
|
1936
|
+
type: z22.enum(["no_results", "low_relevance", "unverified_only"]),
|
|
1937
|
+
query: z22.string(),
|
|
1938
|
+
suggestion: z22.string()
|
|
1879
1939
|
});
|
|
1880
|
-
GetConstraintsDataSchema =
|
|
1881
|
-
domain:
|
|
1882
|
-
constraint_count:
|
|
1883
|
-
constraints:
|
|
1884
|
-
rule:
|
|
1940
|
+
GetConstraintsDataSchema = z22.object({
|
|
1941
|
+
domain: z22.string(),
|
|
1942
|
+
constraint_count: z22.number().int().nonnegative(),
|
|
1943
|
+
constraints: z22.array(z22.object({
|
|
1944
|
+
rule: z22.string(),
|
|
1885
1945
|
authority_level: AuthorityLevelSchema,
|
|
1886
|
-
source_name:
|
|
1887
|
-
source_section:
|
|
1888
|
-
source_url:
|
|
1889
|
-
source_version:
|
|
1890
|
-
source_uri:
|
|
1946
|
+
source_name: z22.string(),
|
|
1947
|
+
source_section: z22.string(),
|
|
1948
|
+
source_url: z22.string().nullable(),
|
|
1949
|
+
source_version: z22.number(),
|
|
1950
|
+
source_uri: z22.string().describe("iamu://source/<id>@v<version>")
|
|
1891
1951
|
})),
|
|
1892
|
-
gaps:
|
|
1893
|
-
context_hint_needed:
|
|
1952
|
+
gaps: z22.array(RetrievalGapSchema).optional(),
|
|
1953
|
+
context_hint_needed: z22.boolean()
|
|
1894
1954
|
});
|
|
1895
1955
|
GetConstraintsOutputSchema = mcpEnvelopeSchema(GetConstraintsDataSchema);
|
|
1896
|
-
QueryDataSchema =
|
|
1897
|
-
results:
|
|
1898
|
-
chunk_id:
|
|
1899
|
-
content:
|
|
1900
|
-
context_header:
|
|
1901
|
-
context_text:
|
|
1956
|
+
QueryDataSchema = z22.object({
|
|
1957
|
+
results: z22.array(z22.object({
|
|
1958
|
+
chunk_id: z22.string(),
|
|
1959
|
+
content: z22.string(),
|
|
1960
|
+
context_header: z22.string(),
|
|
1961
|
+
context_text: z22.string().nullable(),
|
|
1902
1962
|
authority_level: AuthorityLevelSchema,
|
|
1903
|
-
source_name:
|
|
1904
|
-
source_id:
|
|
1905
|
-
source_uri:
|
|
1906
|
-
source_version:
|
|
1907
|
-
score:
|
|
1908
|
-
verified:
|
|
1909
|
-
trust:
|
|
1963
|
+
source_name: z22.string(),
|
|
1964
|
+
source_id: z22.string(),
|
|
1965
|
+
source_uri: z22.string(),
|
|
1966
|
+
source_version: z22.number(),
|
|
1967
|
+
score: z22.number(),
|
|
1968
|
+
verified: z22.boolean(),
|
|
1969
|
+
trust: z22.enum(["hard", "soft", "unknown"])
|
|
1910
1970
|
})),
|
|
1911
|
-
result_count:
|
|
1912
|
-
query_time_ms:
|
|
1913
|
-
gaps:
|
|
1914
|
-
context_hint_needed:
|
|
1971
|
+
result_count: z22.number().int().nonnegative(),
|
|
1972
|
+
query_time_ms: z22.number().int().nonnegative().optional(),
|
|
1973
|
+
gaps: z22.array(RetrievalGapSchema).optional(),
|
|
1974
|
+
context_hint_needed: z22.boolean()
|
|
1915
1975
|
});
|
|
1916
1976
|
QueryOutputSchema = mcpEnvelopeSchema(QueryDataSchema);
|
|
1917
|
-
ListFindingsDataSchema =
|
|
1918
|
-
findings:
|
|
1919
|
-
total_returned:
|
|
1977
|
+
ListFindingsDataSchema = z22.object({
|
|
1978
|
+
findings: z22.array(FindingSummarySchema),
|
|
1979
|
+
total_returned: z22.number().int().nonnegative()
|
|
1920
1980
|
});
|
|
1921
1981
|
ListFindingsOutputSchema = mcpEnvelopeSchema(ListFindingsDataSchema);
|
|
1922
|
-
ListScenariosDataSchema =
|
|
1923
|
-
scenarios:
|
|
1982
|
+
ListScenariosDataSchema = z22.object({
|
|
1983
|
+
scenarios: z22.array(ScenarioSummarySchema)
|
|
1924
1984
|
});
|
|
1925
1985
|
ListScenariosOutputSchema = mcpEnvelopeSchema(ListScenariosDataSchema);
|
|
1926
|
-
GetProjectDataSchema =
|
|
1927
|
-
id:
|
|
1928
|
-
slug:
|
|
1929
|
-
name:
|
|
1930
|
-
cloud_linked:
|
|
1931
|
-
cloud_project_id:
|
|
1986
|
+
GetProjectDataSchema = z22.object({
|
|
1987
|
+
id: z22.string(),
|
|
1988
|
+
slug: z22.string().nullable(),
|
|
1989
|
+
name: z22.string(),
|
|
1990
|
+
cloud_linked: z22.boolean(),
|
|
1991
|
+
cloud_project_id: z22.string().nullable(),
|
|
1932
1992
|
created_at: isoTimestamp.nullable(),
|
|
1933
|
-
capabilities_count:
|
|
1934
|
-
outlines_count:
|
|
1935
|
-
scenarios_count:
|
|
1936
|
-
walkthroughs_count:
|
|
1937
|
-
personas_count:
|
|
1993
|
+
capabilities_count: z22.number().int().nonnegative(),
|
|
1994
|
+
outlines_count: z22.number().int().nonnegative(),
|
|
1995
|
+
scenarios_count: z22.number().int().nonnegative(),
|
|
1996
|
+
walkthroughs_count: z22.number().int().nonnegative(),
|
|
1997
|
+
personas_count: z22.number().int().nonnegative()
|
|
1938
1998
|
});
|
|
1939
1999
|
GetProjectOutputSchema = mcpEnvelopeSchema(GetProjectDataSchema);
|
|
1940
|
-
CreateScenarioDataSchema =
|
|
1941
|
-
scenario_id:
|
|
1942
|
-
outline_id:
|
|
1943
|
-
persona_id:
|
|
1944
|
-
was_existing:
|
|
2000
|
+
CreateScenarioDataSchema = z22.object({
|
|
2001
|
+
scenario_id: z22.string(),
|
|
2002
|
+
outline_id: z22.string(),
|
|
2003
|
+
persona_id: z22.string(),
|
|
2004
|
+
was_existing: z22.boolean(),
|
|
1945
2005
|
created_at: isoTimestamp,
|
|
1946
2006
|
brief_generated_at: isoTimestamp.nullable()
|
|
1947
2007
|
});
|
|
1948
2008
|
CreateScenarioOutputSchema = mcpEnvelopeSchema(CreateScenarioDataSchema);
|
|
1949
|
-
PrepareWalkthroughDataSchema =
|
|
1950
|
-
walkthrough_id:
|
|
1951
|
-
scenario_id:
|
|
1952
|
-
target_url:
|
|
1953
|
-
lenses:
|
|
1954
|
-
persona:
|
|
1955
|
-
id:
|
|
1956
|
-
name:
|
|
1957
|
-
slug:
|
|
2009
|
+
PrepareWalkthroughDataSchema = z22.object({
|
|
2010
|
+
walkthrough_id: z22.string(),
|
|
2011
|
+
scenario_id: z22.string(),
|
|
2012
|
+
target_url: z22.string(),
|
|
2013
|
+
lenses: z22.array(z22.string()),
|
|
2014
|
+
persona: z22.object({
|
|
2015
|
+
id: z22.string(),
|
|
2016
|
+
name: z22.string(),
|
|
2017
|
+
slug: z22.string().nullable()
|
|
1958
2018
|
}),
|
|
1959
|
-
outline:
|
|
1960
|
-
id:
|
|
1961
|
-
slug:
|
|
1962
|
-
title:
|
|
2019
|
+
outline: z22.object({
|
|
2020
|
+
id: z22.string(),
|
|
2021
|
+
slug: z22.string().nullable(),
|
|
2022
|
+
title: z22.string()
|
|
1963
2023
|
}),
|
|
1964
|
-
mode:
|
|
1965
|
-
cloud_mirrored:
|
|
2024
|
+
mode: z22.enum(["local", "cloud"]),
|
|
2025
|
+
cloud_mirrored: z22.boolean(),
|
|
1966
2026
|
mirror_status: MirrorStatusSchema,
|
|
1967
|
-
run_dir:
|
|
2027
|
+
run_dir: z22.string().nullable(),
|
|
1968
2028
|
/** Persona-specific first-person brief — markdown body of the scenario file. */
|
|
1969
|
-
brief:
|
|
2029
|
+
brief: z22.string(),
|
|
1970
2030
|
/** Full composed walking prompt: persona + outline + lenses +
|
|
1971
2031
|
* evaluation philosophy. This is the text the walker should adopt
|
|
1972
2032
|
* before driving the browser; `brief` alone lacks the philosophy
|
|
1973
2033
|
* + lens guidance. */
|
|
1974
|
-
prompt_text:
|
|
2034
|
+
prompt_text: z22.string(),
|
|
1975
2035
|
/** Withheld during walker stage (always empty here). Populated by
|
|
1976
2036
|
* `get_judge_input` once the walk completes. */
|
|
1977
|
-
human_tests:
|
|
2037
|
+
human_tests: z22.array(z22.string())
|
|
1978
2038
|
});
|
|
1979
2039
|
PrepareWalkthroughOutputSchema = mcpEnvelopeSchema(PrepareWalkthroughDataSchema);
|
|
1980
|
-
PersonaSummarySchema =
|
|
1981
|
-
id:
|
|
1982
|
-
slug:
|
|
1983
|
-
name:
|
|
1984
|
-
role:
|
|
2040
|
+
PersonaSummarySchema = z22.object({
|
|
2041
|
+
id: z22.string(),
|
|
2042
|
+
slug: z22.string(),
|
|
2043
|
+
name: z22.string(),
|
|
2044
|
+
role: z22.string(),
|
|
1985
2045
|
/** First 200 chars of context/background. */
|
|
1986
|
-
context_preview:
|
|
1987
|
-
status:
|
|
2046
|
+
context_preview: z22.string().nullable(),
|
|
2047
|
+
status: z22.enum(["active", "archived"]),
|
|
1988
2048
|
created_at: isoTimestamp,
|
|
1989
|
-
cloud_mirrored:
|
|
2049
|
+
cloud_mirrored: z22.boolean()
|
|
1990
2050
|
});
|
|
1991
|
-
OutlineSummarySchema =
|
|
1992
|
-
id:
|
|
1993
|
-
slug:
|
|
1994
|
-
name:
|
|
1995
|
-
description:
|
|
1996
|
-
primary_capability_id:
|
|
1997
|
-
primary_capability_slug:
|
|
2051
|
+
OutlineSummarySchema = z22.object({
|
|
2052
|
+
id: z22.string(),
|
|
2053
|
+
slug: z22.string(),
|
|
2054
|
+
name: z22.string(),
|
|
2055
|
+
description: z22.string().nullable(),
|
|
2056
|
+
primary_capability_id: z22.string().nullable(),
|
|
2057
|
+
primary_capability_slug: z22.string().nullable(),
|
|
1998
2058
|
/** Capability slugs (denormalized for agent display). */
|
|
1999
|
-
additional_capabilities:
|
|
2000
|
-
task_criticality:
|
|
2059
|
+
additional_capabilities: z22.array(z22.string()),
|
|
2060
|
+
task_criticality: z22.string().nullable(),
|
|
2001
2061
|
created_at: isoTimestamp,
|
|
2002
|
-
cloud_mirrored:
|
|
2062
|
+
cloud_mirrored: z22.boolean()
|
|
2003
2063
|
});
|
|
2004
|
-
CapabilitySummarySchema =
|
|
2005
|
-
id:
|
|
2006
|
-
slug:
|
|
2007
|
-
name:
|
|
2008
|
-
description:
|
|
2064
|
+
CapabilitySummarySchema = z22.object({
|
|
2065
|
+
id: z22.string(),
|
|
2066
|
+
slug: z22.string(),
|
|
2067
|
+
name: z22.string(),
|
|
2068
|
+
description: z22.string().nullable(),
|
|
2009
2069
|
/** Number of outlines with this capability as primary. Cloud-only;
|
|
2010
2070
|
* null in local mode (filesystem walk would be too expensive). */
|
|
2011
|
-
outline_count:
|
|
2071
|
+
outline_count: z22.number().int().nonnegative().nullable(),
|
|
2012
2072
|
created_at: isoTimestamp,
|
|
2013
|
-
cloud_mirrored:
|
|
2073
|
+
cloud_mirrored: z22.boolean()
|
|
2014
2074
|
});
|
|
2015
|
-
ListPersonasDataSchema =
|
|
2016
|
-
personas:
|
|
2075
|
+
ListPersonasDataSchema = z22.object({
|
|
2076
|
+
personas: z22.array(PersonaSummarySchema)
|
|
2017
2077
|
});
|
|
2018
2078
|
ListPersonasOutputSchema = mcpEnvelopeSchema(ListPersonasDataSchema);
|
|
2019
|
-
ListOutlinesDataSchema =
|
|
2020
|
-
outlines:
|
|
2079
|
+
ListOutlinesDataSchema = z22.object({
|
|
2080
|
+
outlines: z22.array(OutlineSummarySchema)
|
|
2021
2081
|
});
|
|
2022
2082
|
ListOutlinesOutputSchema = mcpEnvelopeSchema(ListOutlinesDataSchema);
|
|
2023
|
-
ListCapabilitiesDataSchema =
|
|
2024
|
-
capabilities:
|
|
2083
|
+
ListCapabilitiesDataSchema = z22.object({
|
|
2084
|
+
capabilities: z22.array(CapabilitySummarySchema)
|
|
2025
2085
|
});
|
|
2026
2086
|
ListCapabilitiesOutputSchema = mcpEnvelopeSchema(ListCapabilitiesDataSchema);
|
|
2027
|
-
GetPersonaDataSchema =
|
|
2028
|
-
id:
|
|
2029
|
-
slug:
|
|
2030
|
-
name:
|
|
2031
|
-
role:
|
|
2032
|
-
context:
|
|
2033
|
-
disposition:
|
|
2034
|
-
brief:
|
|
2035
|
-
status:
|
|
2036
|
-
body:
|
|
2087
|
+
GetPersonaDataSchema = z22.object({
|
|
2088
|
+
id: z22.string(),
|
|
2089
|
+
slug: z22.string(),
|
|
2090
|
+
name: z22.string(),
|
|
2091
|
+
role: z22.string(),
|
|
2092
|
+
context: z22.string().nullable(),
|
|
2093
|
+
disposition: z22.string().nullable(),
|
|
2094
|
+
brief: z22.string().nullable(),
|
|
2095
|
+
status: z22.enum(["active", "archived"]),
|
|
2096
|
+
body: z22.string(),
|
|
2037
2097
|
created_at: isoTimestamp,
|
|
2038
2098
|
updated_at: isoTimestamp.nullable(),
|
|
2039
|
-
cloud_mirrored:
|
|
2040
|
-
resource_uri:
|
|
2099
|
+
cloud_mirrored: z22.boolean(),
|
|
2100
|
+
resource_uri: z22.string()
|
|
2041
2101
|
});
|
|
2042
2102
|
GetPersonaOutputSchema = mcpEnvelopeSchema(GetPersonaDataSchema);
|
|
2043
|
-
GetOutlineDataSchema =
|
|
2044
|
-
id:
|
|
2045
|
-
slug:
|
|
2046
|
-
name:
|
|
2047
|
-
description:
|
|
2048
|
-
narrative:
|
|
2049
|
-
primary_capability_id:
|
|
2050
|
-
primary_capability_slug:
|
|
2051
|
-
additional_capabilities:
|
|
2052
|
-
human_tests:
|
|
2053
|
-
tension:
|
|
2054
|
-
situation_roles:
|
|
2055
|
-
task_criticality:
|
|
2056
|
-
complexity_level:
|
|
2103
|
+
GetOutlineDataSchema = z22.object({
|
|
2104
|
+
id: z22.string(),
|
|
2105
|
+
slug: z22.string(),
|
|
2106
|
+
name: z22.string(),
|
|
2107
|
+
description: z22.string().nullable(),
|
|
2108
|
+
narrative: z22.string(),
|
|
2109
|
+
primary_capability_id: z22.string().nullable(),
|
|
2110
|
+
primary_capability_slug: z22.string().nullable(),
|
|
2111
|
+
additional_capabilities: z22.array(z22.string()),
|
|
2112
|
+
human_tests: z22.array(z22.object({ id: z22.string(), question: z22.string() })),
|
|
2113
|
+
tension: z22.string().nullable(),
|
|
2114
|
+
situation_roles: z22.array(z22.object({ role: z22.string(), stake: z22.string() })).nullable(),
|
|
2115
|
+
task_criticality: z22.string().nullable(),
|
|
2116
|
+
complexity_level: z22.string().nullable(),
|
|
2057
2117
|
created_at: isoTimestamp,
|
|
2058
2118
|
updated_at: isoTimestamp.nullable(),
|
|
2059
|
-
cloud_mirrored:
|
|
2060
|
-
resource_uri:
|
|
2119
|
+
cloud_mirrored: z22.boolean(),
|
|
2120
|
+
resource_uri: z22.string()
|
|
2061
2121
|
});
|
|
2062
2122
|
GetOutlineOutputSchema = mcpEnvelopeSchema(GetOutlineDataSchema);
|
|
2063
|
-
GetFindingDataSchema =
|
|
2064
|
-
id:
|
|
2065
|
-
slug:
|
|
2066
|
-
title:
|
|
2123
|
+
GetFindingDataSchema = z22.object({
|
|
2124
|
+
id: z22.string(),
|
|
2125
|
+
slug: z22.string().nullable(),
|
|
2126
|
+
title: z22.string().nullable(),
|
|
2067
2127
|
type: FindingTypeSchema,
|
|
2068
|
-
severity:
|
|
2069
|
-
kind:
|
|
2070
|
-
ui_fact:
|
|
2071
|
-
consequence:
|
|
2072
|
-
description:
|
|
2073
|
-
citations:
|
|
2074
|
-
walkthrough_id:
|
|
2075
|
-
scenario_id:
|
|
2076
|
-
persona_id:
|
|
2077
|
-
run:
|
|
2078
|
-
triage_status:
|
|
2079
|
-
triage_note:
|
|
2080
|
-
fix_status:
|
|
2081
|
-
lens:
|
|
2082
|
-
compliance_impact:
|
|
2083
|
-
task_impact:
|
|
2084
|
-
confidence:
|
|
2085
|
-
regulatory_weight:
|
|
2086
|
-
human_test_id:
|
|
2087
|
-
walkthrough_step_id:
|
|
2088
|
-
canonical_id:
|
|
2128
|
+
severity: z22.enum(["critical", "major", "minor", "observation"]).nullable(),
|
|
2129
|
+
kind: z22.enum(["canonical", "observation"]),
|
|
2130
|
+
ui_fact: z22.string().nullable(),
|
|
2131
|
+
consequence: z22.string().nullable(),
|
|
2132
|
+
description: z22.string().nullable(),
|
|
2133
|
+
citations: z22.array(z22.string()),
|
|
2134
|
+
walkthrough_id: z22.string().nullable(),
|
|
2135
|
+
scenario_id: z22.string(),
|
|
2136
|
+
persona_id: z22.string().nullable(),
|
|
2137
|
+
run: z22.string().nullable(),
|
|
2138
|
+
triage_status: z22.string(),
|
|
2139
|
+
triage_note: z22.string().nullable(),
|
|
2140
|
+
fix_status: z22.string(),
|
|
2141
|
+
lens: z22.string().nullable(),
|
|
2142
|
+
compliance_impact: z22.string().nullable(),
|
|
2143
|
+
task_impact: z22.string().nullable(),
|
|
2144
|
+
confidence: z22.string().nullable(),
|
|
2145
|
+
regulatory_weight: z22.string().nullable(),
|
|
2146
|
+
human_test_id: z22.string().nullable(),
|
|
2147
|
+
walkthrough_step_id: z22.string().nullable(),
|
|
2148
|
+
canonical_id: z22.string().nullable(),
|
|
2089
2149
|
recorded_at: isoTimestamp.nullable(),
|
|
2090
2150
|
updated_at: isoTimestamp.nullable(),
|
|
2091
|
-
cloud_mirrored:
|
|
2151
|
+
cloud_mirrored: z22.boolean(),
|
|
2092
2152
|
mirror_status: MirrorStatusSchema,
|
|
2093
|
-
resource_uri:
|
|
2153
|
+
resource_uri: z22.string()
|
|
2094
2154
|
});
|
|
2095
2155
|
GetFindingOutputSchema = mcpEnvelopeSchema(GetFindingDataSchema);
|
|
2096
|
-
CreatePersonaDataSchema =
|
|
2097
|
-
persona_id:
|
|
2098
|
-
slug:
|
|
2099
|
-
was_existing:
|
|
2156
|
+
CreatePersonaDataSchema = z22.object({
|
|
2157
|
+
persona_id: z22.string(),
|
|
2158
|
+
slug: z22.string(),
|
|
2159
|
+
was_existing: z22.boolean(),
|
|
2100
2160
|
created_at: isoTimestamp,
|
|
2101
2161
|
brief_generated_at: isoTimestamp.nullable()
|
|
2102
2162
|
});
|
|
2103
2163
|
CreatePersonaOutputSchema = mcpEnvelopeSchema(CreatePersonaDataSchema);
|
|
2104
|
-
CreateOutlineDataSchema =
|
|
2105
|
-
outline_id:
|
|
2106
|
-
slug:
|
|
2107
|
-
primary_capability_id:
|
|
2108
|
-
primary_capability_slug:
|
|
2109
|
-
was_existing:
|
|
2164
|
+
CreateOutlineDataSchema = z22.object({
|
|
2165
|
+
outline_id: z22.string(),
|
|
2166
|
+
slug: z22.string(),
|
|
2167
|
+
primary_capability_id: z22.string().nullable(),
|
|
2168
|
+
primary_capability_slug: z22.string().nullable(),
|
|
2169
|
+
was_existing: z22.boolean(),
|
|
2110
2170
|
created_at: isoTimestamp
|
|
2111
2171
|
});
|
|
2112
2172
|
CreateOutlineOutputSchema = mcpEnvelopeSchema(CreateOutlineDataSchema);
|
|
2113
|
-
CreateCapabilityDataSchema =
|
|
2114
|
-
capability_id:
|
|
2115
|
-
slug:
|
|
2116
|
-
was_existing:
|
|
2173
|
+
CreateCapabilityDataSchema = z22.object({
|
|
2174
|
+
capability_id: z22.string(),
|
|
2175
|
+
slug: z22.string(),
|
|
2176
|
+
was_existing: z22.boolean(),
|
|
2117
2177
|
created_at: isoTimestamp
|
|
2118
2178
|
});
|
|
2119
2179
|
CreateCapabilityOutputSchema = mcpEnvelopeSchema(CreateCapabilityDataSchema);
|
|
2120
|
-
RecordStepDataSchema =
|
|
2121
|
-
step_id:
|
|
2122
|
-
step_index:
|
|
2123
|
-
walkthrough_id:
|
|
2124
|
-
persona_reasoning:
|
|
2180
|
+
RecordStepDataSchema = z22.object({
|
|
2181
|
+
step_id: z22.string(),
|
|
2182
|
+
step_index: z22.number().int().nonnegative(),
|
|
2183
|
+
walkthrough_id: z22.string(),
|
|
2184
|
+
persona_reasoning: z22.string(),
|
|
2125
2185
|
recorded_at: isoTimestamp,
|
|
2126
2186
|
/** Set when a screenshot_path was provided. */
|
|
2127
|
-
screenshot_uri:
|
|
2187
|
+
screenshot_uri: z22.string().nullable(),
|
|
2128
2188
|
/** Capture failure modes (per-field) — see fingerprint shape in
|
|
2129
2189
|
* `./types/fingerprint.ts`. Optional; null
|
|
2130
2190
|
* when fingerprint capture didn't run. */
|
|
2131
|
-
fingerprint: stepFingerprintSchema.or(
|
|
2132
|
-
dom_hash:
|
|
2133
|
-
ax_hash:
|
|
2134
|
-
screenshot_hash:
|
|
2135
|
-
url_template:
|
|
2191
|
+
fingerprint: stepFingerprintSchema.or(z22.object({
|
|
2192
|
+
dom_hash: z22.string().nullable(),
|
|
2193
|
+
ax_hash: z22.string().nullable(),
|
|
2194
|
+
screenshot_hash: z22.string().nullable(),
|
|
2195
|
+
url_template: z22.string().nullable()
|
|
2136
2196
|
})).nullable()
|
|
2137
2197
|
});
|
|
2138
2198
|
RecordStepOutputSchema = mcpEnvelopeSchema(RecordStepDataSchema);
|
|
2139
|
-
RecordFindingDataSchema =
|
|
2140
|
-
finding_id:
|
|
2141
|
-
slug:
|
|
2199
|
+
RecordFindingDataSchema = z22.object({
|
|
2200
|
+
finding_id: z22.string(),
|
|
2201
|
+
slug: z22.string().nullable(),
|
|
2142
2202
|
type: FindingTypeSchema,
|
|
2143
|
-
severity:
|
|
2144
|
-
kind:
|
|
2145
|
-
ui_fact:
|
|
2146
|
-
consequence:
|
|
2147
|
-
citations:
|
|
2148
|
-
scenario_id:
|
|
2149
|
-
walkthrough_id:
|
|
2150
|
-
persona_id:
|
|
2151
|
-
triage_status:
|
|
2152
|
-
fix_status:
|
|
2153
|
-
lens:
|
|
2203
|
+
severity: z22.enum(["critical", "major", "minor", "observation"]).nullable(),
|
|
2204
|
+
kind: z22.literal("observation"),
|
|
2205
|
+
ui_fact: z22.string(),
|
|
2206
|
+
consequence: z22.string(),
|
|
2207
|
+
citations: z22.array(z22.string()),
|
|
2208
|
+
scenario_id: z22.string(),
|
|
2209
|
+
walkthrough_id: z22.string(),
|
|
2210
|
+
persona_id: z22.string().nullable(),
|
|
2211
|
+
triage_status: z22.literal("open"),
|
|
2212
|
+
fix_status: z22.literal("open"),
|
|
2213
|
+
lens: z22.string().nullable(),
|
|
2154
2214
|
recorded_at: isoTimestamp,
|
|
2155
|
-
resource_uri:
|
|
2215
|
+
resource_uri: z22.string()
|
|
2156
2216
|
});
|
|
2157
2217
|
RecordFindingOutputSchema = mcpEnvelopeSchema(RecordFindingDataSchema);
|
|
2158
2218
|
CompleteWalkthroughDataSchema = canonicalWalkthroughSchema;
|
|
2159
2219
|
CompleteWalkthroughOutputSchema = mcpEnvelopeSchema(CompleteWalkthroughDataSchema);
|
|
2160
|
-
GetJudgeInputDataSchema =
|
|
2161
|
-
walkthrough_id:
|
|
2162
|
-
judge_prompt:
|
|
2163
|
-
id:
|
|
2164
|
-
version:
|
|
2165
|
-
text:
|
|
2220
|
+
GetJudgeInputDataSchema = z22.object({
|
|
2221
|
+
walkthrough_id: z22.string(),
|
|
2222
|
+
judge_prompt: z22.object({
|
|
2223
|
+
id: z22.string(),
|
|
2224
|
+
version: z22.string(),
|
|
2225
|
+
text: z22.string()
|
|
2166
2226
|
}),
|
|
2167
|
-
scenario:
|
|
2168
|
-
outline_context:
|
|
2169
|
-
steps:
|
|
2170
|
-
findings:
|
|
2171
|
-
human_tests:
|
|
2172
|
-
id:
|
|
2173
|
-
question:
|
|
2227
|
+
scenario: z22.object({}).passthrough(),
|
|
2228
|
+
outline_context: z22.object({}).passthrough(),
|
|
2229
|
+
steps: z22.array(z22.unknown()),
|
|
2230
|
+
findings: z22.array(z22.unknown()),
|
|
2231
|
+
human_tests: z22.array(z22.object({
|
|
2232
|
+
id: z22.string(),
|
|
2233
|
+
question: z22.string()
|
|
2174
2234
|
}))
|
|
2175
2235
|
});
|
|
2176
2236
|
GetJudgeInputOutputSchema = mcpEnvelopeSchema(GetJudgeInputDataSchema);
|
|
2177
|
-
RecordJudgeResultDataSchema =
|
|
2178
|
-
walkthrough_id:
|
|
2237
|
+
RecordJudgeResultDataSchema = z22.object({
|
|
2238
|
+
walkthrough_id: z22.string(),
|
|
2179
2239
|
persisted_at: isoTimestamp,
|
|
2180
|
-
canonical_path:
|
|
2181
|
-
report_path:
|
|
2240
|
+
canonical_path: z22.string(),
|
|
2241
|
+
report_path: z22.string()
|
|
2182
2242
|
});
|
|
2183
2243
|
RecordJudgeResultOutputSchema = mcpEnvelopeSchema(RecordJudgeResultDataSchema);
|
|
2184
2244
|
}
|
|
@@ -2351,6 +2411,9 @@ function configPath(projectRoot) {
|
|
|
2351
2411
|
function contextPath(projectRoot) {
|
|
2352
2412
|
return path2.join(iamuDir(projectRoot), "context.yml");
|
|
2353
2413
|
}
|
|
2414
|
+
function testabilityPath(projectRoot) {
|
|
2415
|
+
return path2.join(iamuDir(projectRoot), "testability.md");
|
|
2416
|
+
}
|
|
2354
2417
|
function entityDirPath(projectRoot, type2) {
|
|
2355
2418
|
return path2.join(iamuDir(projectRoot), ENTITY_DIRS[type2]);
|
|
2356
2419
|
}
|
|
@@ -5294,6 +5357,37 @@ var init_context2 = __esm({
|
|
|
5294
5357
|
}
|
|
5295
5358
|
});
|
|
5296
5359
|
|
|
5360
|
+
// ../../packages/local-store/dist/testability.js
|
|
5361
|
+
import { promises as fs5 } from "fs";
|
|
5362
|
+
async function readTestability(projectRoot) {
|
|
5363
|
+
const p = testabilityPath(projectRoot);
|
|
5364
|
+
let raw;
|
|
5365
|
+
try {
|
|
5366
|
+
raw = await fs5.readFile(p, "utf8");
|
|
5367
|
+
} catch (err) {
|
|
5368
|
+
if (err.code === "ENOENT")
|
|
5369
|
+
return null;
|
|
5370
|
+
throw err;
|
|
5371
|
+
}
|
|
5372
|
+
const parsed = parseFrontmatter(raw);
|
|
5373
|
+
const result = testabilityFrontmatterSchema.safeParse(parsed.frontmatter);
|
|
5374
|
+
if (!result.success) {
|
|
5375
|
+
throw new Error(`testability: invalid frontmatter in ${p}: ${result.error.issues.map((i) => `${i.path.join(".") || "root"}: ${i.message}`).join("; ")}`);
|
|
5376
|
+
}
|
|
5377
|
+
return {
|
|
5378
|
+
frontmatter: result.data,
|
|
5379
|
+
body: parsed.body
|
|
5380
|
+
};
|
|
5381
|
+
}
|
|
5382
|
+
var init_testability2 = __esm({
|
|
5383
|
+
"../../packages/local-store/dist/testability.js"() {
|
|
5384
|
+
"use strict";
|
|
5385
|
+
init_dist();
|
|
5386
|
+
init_markdown();
|
|
5387
|
+
init_paths();
|
|
5388
|
+
}
|
|
5389
|
+
});
|
|
5390
|
+
|
|
5297
5391
|
// ../../packages/local-store/dist/hash.js
|
|
5298
5392
|
import { createHash } from "crypto";
|
|
5299
5393
|
function hashNormalizedContent(raw) {
|
|
@@ -5327,7 +5421,7 @@ var init_server_reason = __esm({
|
|
|
5327
5421
|
|
|
5328
5422
|
// ../../packages/local-store/dist/file-lock.js
|
|
5329
5423
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
5330
|
-
import { promises as
|
|
5424
|
+
import { promises as fs6 } from "fs";
|
|
5331
5425
|
import os from "os";
|
|
5332
5426
|
import path4 from "path";
|
|
5333
5427
|
function takeoverFilePathFor(lockPath) {
|
|
@@ -5364,7 +5458,7 @@ function pidIsDead(rec) {
|
|
|
5364
5458
|
async function isStale(lockPath, rec, staleMs, now) {
|
|
5365
5459
|
if (rec === null) {
|
|
5366
5460
|
try {
|
|
5367
|
-
const stat3 = await
|
|
5461
|
+
const stat3 = await fs6.stat(lockPath);
|
|
5368
5462
|
if (stat3.size === 0) {
|
|
5369
5463
|
const mtime = stat3.birthtimeMs && stat3.birthtimeMs > 0 ? stat3.birthtimeMs : stat3.mtimeMs;
|
|
5370
5464
|
if (now - mtime <= staleMs) {
|
|
@@ -5389,7 +5483,7 @@ async function tryCreateMarker(markerPath, token) {
|
|
|
5389
5483
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5390
5484
|
};
|
|
5391
5485
|
try {
|
|
5392
|
-
const handle = await
|
|
5486
|
+
const handle = await fs6.open(markerPath, "wx", 420);
|
|
5393
5487
|
try {
|
|
5394
5488
|
await handle.writeFile(JSON.stringify(record));
|
|
5395
5489
|
await handle.sync();
|
|
@@ -5408,7 +5502,7 @@ async function tryCreateLock(lockPath, token) {
|
|
|
5408
5502
|
}
|
|
5409
5503
|
async function readRecord(markerPath) {
|
|
5410
5504
|
try {
|
|
5411
|
-
return parseLockRecord(await
|
|
5505
|
+
return parseLockRecord(await fs6.readFile(markerPath, "utf8"));
|
|
5412
5506
|
} catch {
|
|
5413
5507
|
return null;
|
|
5414
5508
|
}
|
|
@@ -5418,7 +5512,7 @@ async function tryTakeover(lockPath, token, expected, opts) {
|
|
|
5418
5512
|
if (!await tryCreateMarker(takeoverPath, token)) {
|
|
5419
5513
|
const holder = await readRecord(takeoverPath);
|
|
5420
5514
|
if (await isStale(takeoverPath, holder, opts.staleMs, opts.now())) {
|
|
5421
|
-
await
|
|
5515
|
+
await fs6.unlink(takeoverPath).catch(() => {
|
|
5422
5516
|
});
|
|
5423
5517
|
}
|
|
5424
5518
|
return null;
|
|
@@ -5427,7 +5521,7 @@ async function tryTakeover(lockPath, token, expected, opts) {
|
|
|
5427
5521
|
const current = await readRecord(lockPath);
|
|
5428
5522
|
let present = true;
|
|
5429
5523
|
try {
|
|
5430
|
-
await
|
|
5524
|
+
await fs6.access(lockPath);
|
|
5431
5525
|
} catch {
|
|
5432
5526
|
present = false;
|
|
5433
5527
|
}
|
|
@@ -5438,11 +5532,11 @@ async function tryTakeover(lockPath, token, expected, opts) {
|
|
|
5438
5532
|
return null;
|
|
5439
5533
|
if (!await isStale(lockPath, current, opts.staleMs, opts.now()))
|
|
5440
5534
|
return null;
|
|
5441
|
-
await
|
|
5535
|
+
await fs6.unlink(lockPath).catch(() => {
|
|
5442
5536
|
});
|
|
5443
5537
|
return await tryCreateLock(lockPath, token);
|
|
5444
5538
|
} finally {
|
|
5445
|
-
await
|
|
5539
|
+
await fs6.unlink(takeoverPath).catch(() => {
|
|
5446
5540
|
});
|
|
5447
5541
|
}
|
|
5448
5542
|
}
|
|
@@ -5459,13 +5553,13 @@ async function acquireLockFile(lockPath, opts) {
|
|
|
5459
5553
|
const token = randomUUID3();
|
|
5460
5554
|
const deadline = opts.now() + opts.timeoutMs;
|
|
5461
5555
|
let lastHolderPid;
|
|
5462
|
-
await
|
|
5556
|
+
await fs6.mkdir(path4.dirname(lockPath), { recursive: true });
|
|
5463
5557
|
for (; ; ) {
|
|
5464
5558
|
if (await tryCreateLock(lockPath, token))
|
|
5465
5559
|
return token;
|
|
5466
5560
|
let raw = null;
|
|
5467
5561
|
try {
|
|
5468
|
-
raw = await
|
|
5562
|
+
raw = await fs6.readFile(lockPath, "utf8");
|
|
5469
5563
|
} catch (err) {
|
|
5470
5564
|
if (err.code === "ENOENT")
|
|
5471
5565
|
continue;
|
|
@@ -5492,13 +5586,13 @@ async function acquireLockFile(lockPath, opts) {
|
|
|
5492
5586
|
}
|
|
5493
5587
|
async function releaseLockFile(lockPath, token) {
|
|
5494
5588
|
try {
|
|
5495
|
-
const rec = parseLockRecord(await
|
|
5589
|
+
const rec = parseLockRecord(await fs6.readFile(lockPath, "utf8"));
|
|
5496
5590
|
if (rec?.token !== token)
|
|
5497
5591
|
return;
|
|
5498
|
-
const recheck = parseLockRecord(await
|
|
5592
|
+
const recheck = parseLockRecord(await fs6.readFile(lockPath, "utf8"));
|
|
5499
5593
|
if (recheck?.token !== token)
|
|
5500
5594
|
return;
|
|
5501
|
-
await
|
|
5595
|
+
await fs6.unlink(lockPath);
|
|
5502
5596
|
} catch {
|
|
5503
5597
|
}
|
|
5504
5598
|
}
|
|
@@ -5567,10 +5661,10 @@ var init_file_lock = __esm({
|
|
|
5567
5661
|
});
|
|
5568
5662
|
|
|
5569
5663
|
// ../../packages/local-store/dist/sync-tracking.js
|
|
5570
|
-
import { promises as
|
|
5664
|
+
import { promises as fs7 } from "fs";
|
|
5571
5665
|
async function readLastPush(projectRoot) {
|
|
5572
5666
|
try {
|
|
5573
|
-
const raw = await
|
|
5667
|
+
const raw = await fs7.readFile(lastPushPath(projectRoot), "utf8");
|
|
5574
5668
|
const parsed = JSON.parse(raw);
|
|
5575
5669
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
5576
5670
|
return parsed;
|
|
@@ -5617,7 +5711,7 @@ async function forgetLastPush(projectRoot, entityId) {
|
|
|
5617
5711
|
}
|
|
5618
5712
|
async function readCloudBase(projectRoot) {
|
|
5619
5713
|
try {
|
|
5620
|
-
const raw = await
|
|
5714
|
+
const raw = await fs7.readFile(cloudBasePath(projectRoot), "utf8");
|
|
5621
5715
|
const parsed = JSON.parse(raw);
|
|
5622
5716
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
5623
5717
|
return parsed;
|
|
@@ -5718,7 +5812,7 @@ function isRetryQueueEntry(value) {
|
|
|
5718
5812
|
async function readRetryQueueDetailed(projectRoot) {
|
|
5719
5813
|
let raw;
|
|
5720
5814
|
try {
|
|
5721
|
-
raw = await
|
|
5815
|
+
raw = await fs7.readFile(retryQueuePath(projectRoot), "utf8");
|
|
5722
5816
|
} catch (err) {
|
|
5723
5817
|
if (err.code === "ENOENT") {
|
|
5724
5818
|
return { entries: [], warnings: [], corruptedLines: [] };
|
|
@@ -5774,7 +5868,7 @@ function canonicalJsonString(val) {
|
|
|
5774
5868
|
async function readQueueAndPreserveCorrupted(projectRoot) {
|
|
5775
5869
|
const { entries, corruptedLines } = await readRetryQueueDetailed(projectRoot);
|
|
5776
5870
|
if (corruptedLines && corruptedLines.length > 0) {
|
|
5777
|
-
await
|
|
5871
|
+
await fs7.appendFile(retryQueueCorruptedPath(projectRoot), corruptedLines.map((l) => `${l}
|
|
5778
5872
|
`).join(""), "utf8");
|
|
5779
5873
|
}
|
|
5780
5874
|
return entries;
|
|
@@ -5824,7 +5918,7 @@ var init_sync_tracking = __esm({
|
|
|
5824
5918
|
});
|
|
5825
5919
|
|
|
5826
5920
|
// ../../packages/local-store/dist/entity.js
|
|
5827
|
-
import { promises as
|
|
5921
|
+
import { promises as fs8 } from "fs";
|
|
5828
5922
|
import path5 from "path";
|
|
5829
5923
|
async function resolveEntityPath(projectRoot, type2, slugOrUuid) {
|
|
5830
5924
|
const isSlug = slugSchema.safeParse(slugOrUuid).success;
|
|
@@ -5833,7 +5927,7 @@ async function resolveEntityPath(projectRoot, type2, slugOrUuid) {
|
|
|
5833
5927
|
return null;
|
|
5834
5928
|
const direct = entityFilePath(projectRoot, type2, slugOrUuid);
|
|
5835
5929
|
try {
|
|
5836
|
-
await
|
|
5930
|
+
await fs8.access(direct);
|
|
5837
5931
|
return direct;
|
|
5838
5932
|
} catch {
|
|
5839
5933
|
}
|
|
@@ -5842,7 +5936,7 @@ async function resolveEntityPath(projectRoot, type2, slugOrUuid) {
|
|
|
5842
5936
|
const dir = entityDirPath(projectRoot, type2);
|
|
5843
5937
|
let entries;
|
|
5844
5938
|
try {
|
|
5845
|
-
entries = await
|
|
5939
|
+
entries = await fs8.readdir(dir);
|
|
5846
5940
|
} catch {
|
|
5847
5941
|
return null;
|
|
5848
5942
|
}
|
|
@@ -5851,7 +5945,7 @@ async function resolveEntityPath(projectRoot, type2, slugOrUuid) {
|
|
|
5851
5945
|
continue;
|
|
5852
5946
|
const abs = path5.join(dir, name);
|
|
5853
5947
|
try {
|
|
5854
|
-
const raw = await
|
|
5948
|
+
const raw = await fs8.readFile(abs, "utf8");
|
|
5855
5949
|
const { frontmatter } = parseFrontmatter(raw);
|
|
5856
5950
|
if (typeof frontmatter.id === "string" && frontmatter.id.toLowerCase() === slugOrUuid.toLowerCase()) {
|
|
5857
5951
|
return abs;
|
|
@@ -5868,7 +5962,7 @@ async function readEntity(projectRoot, type2, slugOrUuid) {
|
|
|
5868
5962
|
const abs = await resolveEntityPath(projectRoot, type2, slugOrUuid);
|
|
5869
5963
|
if (!abs)
|
|
5870
5964
|
return null;
|
|
5871
|
-
const raw = await
|
|
5965
|
+
const raw = await fs8.readFile(abs, "utf8");
|
|
5872
5966
|
const { frontmatter, body } = parseFrontmatter(raw);
|
|
5873
5967
|
const schema2 = entityFrontmatterSchemas[type2];
|
|
5874
5968
|
const parsed = schema2.parse(frontmatter);
|
|
@@ -5896,7 +5990,7 @@ async function writeEntity(projectRoot, type2, frontmatter, body) {
|
|
|
5896
5990
|
}
|
|
5897
5991
|
async function entityExists(projectRoot, type2, slug) {
|
|
5898
5992
|
try {
|
|
5899
|
-
await
|
|
5993
|
+
await fs8.access(entityFilePath(projectRoot, type2, slug));
|
|
5900
5994
|
return true;
|
|
5901
5995
|
} catch {
|
|
5902
5996
|
return false;
|
|
@@ -5906,7 +6000,7 @@ async function listEntities(projectRoot, type2) {
|
|
|
5906
6000
|
const dir = entityDirPath(projectRoot, type2);
|
|
5907
6001
|
let names;
|
|
5908
6002
|
try {
|
|
5909
|
-
names = await
|
|
6003
|
+
names = await fs8.readdir(dir);
|
|
5910
6004
|
} catch (err) {
|
|
5911
6005
|
if (err.code === "ENOENT") {
|
|
5912
6006
|
return { entities: [], warnings: [] };
|
|
@@ -5921,7 +6015,7 @@ async function listEntities(projectRoot, type2) {
|
|
|
5921
6015
|
continue;
|
|
5922
6016
|
const abs = path5.join(dir, name);
|
|
5923
6017
|
try {
|
|
5924
|
-
const raw = await
|
|
6018
|
+
const raw = await fs8.readFile(abs, "utf8");
|
|
5925
6019
|
const { frontmatter, body } = parseFrontmatter(raw);
|
|
5926
6020
|
const parsed = schema2.parse(frontmatter);
|
|
5927
6021
|
entities.push({
|
|
@@ -6036,14 +6130,14 @@ var init_guidance2 = __esm({
|
|
|
6036
6130
|
});
|
|
6037
6131
|
|
|
6038
6132
|
// ../../packages/local-store/dist/finding-match.js
|
|
6039
|
-
import { promises as
|
|
6133
|
+
import { promises as fs9 } from "fs";
|
|
6040
6134
|
import path6 from "path";
|
|
6041
|
-
import { z as
|
|
6135
|
+
import { z as z23 } from "zod";
|
|
6042
6136
|
async function readScenarioFindings(projectRoot, scenarioSlug) {
|
|
6043
6137
|
const dir = entityDirPath(projectRoot, "finding");
|
|
6044
6138
|
let names;
|
|
6045
6139
|
try {
|
|
6046
|
-
names = await
|
|
6140
|
+
names = await fs9.readdir(dir);
|
|
6047
6141
|
} catch {
|
|
6048
6142
|
return [];
|
|
6049
6143
|
}
|
|
@@ -6053,7 +6147,7 @@ async function readScenarioFindings(projectRoot, scenarioSlug) {
|
|
|
6053
6147
|
continue;
|
|
6054
6148
|
const file = path6.join(dir, name);
|
|
6055
6149
|
try {
|
|
6056
|
-
const { frontmatter } = parseFrontmatter(await
|
|
6150
|
+
const { frontmatter } = parseFrontmatter(await fs9.readFile(file, "utf8"));
|
|
6057
6151
|
const fm = frontmatter;
|
|
6058
6152
|
if (fm.scenario === scenarioSlug)
|
|
6059
6153
|
out.push({ file, frontmatter: fm });
|
|
@@ -6093,7 +6187,7 @@ async function suppressionRules(projectRoot, outlineSlug) {
|
|
|
6093
6187
|
}
|
|
6094
6188
|
async function scenarioOutline(projectRoot, scenarioSlug) {
|
|
6095
6189
|
try {
|
|
6096
|
-
const raw = await
|
|
6190
|
+
const raw = await fs9.readFile(path6.join(entityDirPath(projectRoot, "scenario"), `${scenarioSlug}.md`), "utf8");
|
|
6097
6191
|
const outline = parseFrontmatter(raw).frontmatter.outline;
|
|
6098
6192
|
return typeof outline === "string" ? outline : null;
|
|
6099
6193
|
} catch {
|
|
@@ -6206,7 +6300,7 @@ async function recordMatches(projectRoot, runId, scenarioSlug, answer) {
|
|
|
6206
6300
|
const target = byId.get(m.finding_id);
|
|
6207
6301
|
if (!target)
|
|
6208
6302
|
continue;
|
|
6209
|
-
const raw = await
|
|
6303
|
+
const raw = await fs9.readFile(target, "utf8");
|
|
6210
6304
|
const updated = setFrontmatterScalar(raw, "canonical_id", m.canonical_id);
|
|
6211
6305
|
if (updated !== raw)
|
|
6212
6306
|
await atomicWriteFile(target, updated);
|
|
@@ -6216,7 +6310,7 @@ async function recordMatches(projectRoot, runId, scenarioSlug, answer) {
|
|
|
6216
6310
|
const target = byId.get(s.finding_id);
|
|
6217
6311
|
if (!target)
|
|
6218
6312
|
continue;
|
|
6219
|
-
const raw = await
|
|
6313
|
+
const raw = await fs9.readFile(target, "utf8");
|
|
6220
6314
|
const updated = setFrontmatterScalar(raw, "suppressed_by_guidance", s.guidance_id);
|
|
6221
6315
|
if (updated !== raw)
|
|
6222
6316
|
await atomicWriteFile(target, updated);
|
|
@@ -6234,7 +6328,7 @@ async function setCanonicalFixStatus(projectRoot, scenarioSlug, canonicalId, sta
|
|
|
6234
6328
|
for (const f of await readScenarioFindings(projectRoot, scenarioSlug)) {
|
|
6235
6329
|
if (f.frontmatter.canonical_id !== canonicalId)
|
|
6236
6330
|
continue;
|
|
6237
|
-
const raw = await
|
|
6331
|
+
const raw = await fs9.readFile(f.file, "utf8");
|
|
6238
6332
|
const updated = setFrontmatterScalar(raw, "fix_status", status2);
|
|
6239
6333
|
if (updated !== raw)
|
|
6240
6334
|
await atomicWriteFile(f.file, updated);
|
|
@@ -6242,7 +6336,7 @@ async function setCanonicalFixStatus(projectRoot, scenarioSlug, canonicalId, sta
|
|
|
6242
6336
|
}
|
|
6243
6337
|
async function readMatches(projectRoot, runId) {
|
|
6244
6338
|
try {
|
|
6245
|
-
const raw = await
|
|
6339
|
+
const raw = await fs9.readFile(path6.join(runDir(projectRoot, runId), MATCHES_FILE), "utf8");
|
|
6246
6340
|
const parsed = matchesFileSchema.safeParse(JSON.parse(raw));
|
|
6247
6341
|
return parsed.success ? parsed.data : null;
|
|
6248
6342
|
} catch {
|
|
@@ -6259,32 +6353,32 @@ var init_finding_match = __esm({
|
|
|
6259
6353
|
init_paths();
|
|
6260
6354
|
init_walkthrough_canonical2();
|
|
6261
6355
|
MATCHES_FILE = "matches.json";
|
|
6262
|
-
matchesFileSchema =
|
|
6263
|
-
matches:
|
|
6264
|
-
finding_id:
|
|
6265
|
-
canonical_id:
|
|
6266
|
-
reasoning:
|
|
6356
|
+
matchesFileSchema = z23.object({
|
|
6357
|
+
matches: z23.array(z23.object({
|
|
6358
|
+
finding_id: z23.string().min(1),
|
|
6359
|
+
canonical_id: z23.string().min(1).nullable(),
|
|
6360
|
+
reasoning: z23.string().default("")
|
|
6267
6361
|
})),
|
|
6268
|
-
rechecked_fixed:
|
|
6269
|
-
canonical_id:
|
|
6270
|
-
step_ids:
|
|
6271
|
-
reasoning:
|
|
6362
|
+
rechecked_fixed: z23.array(z23.object({
|
|
6363
|
+
canonical_id: z23.string().min(1),
|
|
6364
|
+
step_ids: z23.array(z23.string().min(1)).min(1),
|
|
6365
|
+
reasoning: z23.string().default("")
|
|
6272
6366
|
})).default([]),
|
|
6273
6367
|
/**
|
|
6274
6368
|
* Findings of this run that an active `not_relevant` tester guidance
|
|
6275
6369
|
* rule covers. Kept, flagged: `suppressed_by_guidance` on the file.
|
|
6276
6370
|
*/
|
|
6277
|
-
suppressed:
|
|
6278
|
-
finding_id:
|
|
6279
|
-
guidance_id:
|
|
6280
|
-
reasoning:
|
|
6371
|
+
suppressed: z23.array(z23.object({
|
|
6372
|
+
finding_id: z23.string().min(1),
|
|
6373
|
+
guidance_id: z23.string().min(1),
|
|
6374
|
+
reasoning: z23.string().default("")
|
|
6281
6375
|
})).default([])
|
|
6282
6376
|
});
|
|
6283
6377
|
}
|
|
6284
6378
|
});
|
|
6285
6379
|
|
|
6286
6380
|
// ../../packages/local-store/dist/runs.js
|
|
6287
|
-
import { promises as
|
|
6381
|
+
import { promises as fs10 } from "fs";
|
|
6288
6382
|
import path7 from "path";
|
|
6289
6383
|
async function openRun(projectRoot, scenarioSlug, options = {}) {
|
|
6290
6384
|
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
@@ -6293,9 +6387,9 @@ async function openRun(projectRoot, scenarioSlug, options = {}) {
|
|
|
6293
6387
|
const stepsDir = path7.join(absPath, "steps");
|
|
6294
6388
|
const fingerprintsDir = path7.join(absPath, "fingerprints");
|
|
6295
6389
|
const screenshotsDir = path7.join(absPath, "screenshots");
|
|
6296
|
-
await
|
|
6297
|
-
await
|
|
6298
|
-
await
|
|
6390
|
+
await fs10.mkdir(stepsDir, { recursive: true });
|
|
6391
|
+
await fs10.mkdir(fingerprintsDir, { recursive: true });
|
|
6392
|
+
await fs10.mkdir(screenshotsDir, { recursive: true });
|
|
6299
6393
|
return {
|
|
6300
6394
|
runId,
|
|
6301
6395
|
absPath,
|
|
@@ -6310,14 +6404,14 @@ function padStepNumber(n) {
|
|
|
6310
6404
|
}
|
|
6311
6405
|
async function writeStep(runDirAbs, step) {
|
|
6312
6406
|
const stepsDir = path7.join(runDirAbs, "steps");
|
|
6313
|
-
await
|
|
6407
|
+
await fs10.mkdir(stepsDir, { recursive: true });
|
|
6314
6408
|
const filename = `${padStepNumber(step.step_number)}.json`;
|
|
6315
6409
|
await atomicWriteFile(path7.join(stepsDir, filename), JSON.stringify(step, null, 2) + "\n");
|
|
6316
6410
|
}
|
|
6317
6411
|
async function listRuns(projectRoot) {
|
|
6318
6412
|
const dir = runsDir(projectRoot);
|
|
6319
6413
|
try {
|
|
6320
|
-
const entries = await
|
|
6414
|
+
const entries = await fs10.readdir(dir, { withFileTypes: true });
|
|
6321
6415
|
return entries.filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name).sort();
|
|
6322
6416
|
} catch (err) {
|
|
6323
6417
|
if (err.code === "ENOENT")
|
|
@@ -6329,7 +6423,7 @@ async function listIncompleteRuns(projectRoot) {
|
|
|
6329
6423
|
const incomplete = [];
|
|
6330
6424
|
for (const runId of await listRuns(projectRoot)) {
|
|
6331
6425
|
try {
|
|
6332
|
-
const manifest = JSON.parse(await
|
|
6426
|
+
const manifest = JSON.parse(await fs10.readFile(path7.join(runsDir(projectRoot), runId, "walkthrough.json"), "utf8"));
|
|
6333
6427
|
if (manifest.status !== "completed")
|
|
6334
6428
|
incomplete.push(runId);
|
|
6335
6429
|
} catch {
|
|
@@ -6347,7 +6441,7 @@ var init_runs = __esm({
|
|
|
6347
6441
|
});
|
|
6348
6442
|
|
|
6349
6443
|
// ../../packages/local-store/dist/fix-state.js
|
|
6350
|
-
import { promises as
|
|
6444
|
+
import { promises as fs11 } from "fs";
|
|
6351
6445
|
import path8 from "path";
|
|
6352
6446
|
function toMillis(iso) {
|
|
6353
6447
|
if (!iso)
|
|
@@ -6453,7 +6547,7 @@ function summarizeRerun(findings2, runs, states) {
|
|
|
6453
6547
|
}
|
|
6454
6548
|
async function readJson(file) {
|
|
6455
6549
|
try {
|
|
6456
|
-
return JSON.parse(await
|
|
6550
|
+
return JSON.parse(await fs11.readFile(file, "utf8"));
|
|
6457
6551
|
} catch {
|
|
6458
6552
|
return null;
|
|
6459
6553
|
}
|
|
@@ -7026,19 +7120,19 @@ var init_journey_diff = __esm({
|
|
|
7026
7120
|
|
|
7027
7121
|
// ../../packages/local-store/dist/walkthrough-canonical.js
|
|
7028
7122
|
import { createHash as createHash2, randomUUID as randomUUID5 } from "crypto";
|
|
7029
|
-
import { promises as
|
|
7123
|
+
import { promises as fs12 } from "fs";
|
|
7030
7124
|
import path9 from "path";
|
|
7031
7125
|
async function readStepsForRun(projectRoot, runId) {
|
|
7032
7126
|
const runDirPath = runDir(projectRoot, runId);
|
|
7033
7127
|
const stepsDir = path9.join(runDirPath, "steps");
|
|
7034
7128
|
try {
|
|
7035
|
-
const names = await
|
|
7129
|
+
const names = await fs12.readdir(stepsDir);
|
|
7036
7130
|
const jsonFiles = names.filter((n) => n.endsWith(".json")).sort();
|
|
7037
7131
|
if (jsonFiles.length > 0) {
|
|
7038
7132
|
const out2 = [];
|
|
7039
7133
|
for (const name of jsonFiles) {
|
|
7040
7134
|
try {
|
|
7041
|
-
const raw2 = await
|
|
7135
|
+
const raw2 = await fs12.readFile(path9.join(stepsDir, name), "utf8");
|
|
7042
7136
|
const parsed = JSON.parse(raw2);
|
|
7043
7137
|
if (parsed.step_number == null) {
|
|
7044
7138
|
const numFromName = Number.parseInt(name.replace(/\.json$/, ""), 10);
|
|
@@ -7055,7 +7149,7 @@ async function readStepsForRun(projectRoot, runId) {
|
|
|
7055
7149
|
const stepsPath = path9.join(runDirPath, "steps.jsonl");
|
|
7056
7150
|
let raw;
|
|
7057
7151
|
try {
|
|
7058
|
-
raw = await
|
|
7152
|
+
raw = await fs12.readFile(stepsPath, "utf8");
|
|
7059
7153
|
} catch (err) {
|
|
7060
7154
|
if (err.code === "ENOENT")
|
|
7061
7155
|
return [];
|
|
@@ -7080,7 +7174,7 @@ async function readFindingsForRun(projectRoot, runId) {
|
|
|
7080
7174
|
const findingsDir = entityDirPath(projectRoot, "finding");
|
|
7081
7175
|
let names;
|
|
7082
7176
|
try {
|
|
7083
|
-
names = await
|
|
7177
|
+
names = await fs12.readdir(findingsDir);
|
|
7084
7178
|
} catch (err) {
|
|
7085
7179
|
if (err.code === "ENOENT")
|
|
7086
7180
|
return [];
|
|
@@ -7091,7 +7185,7 @@ async function readFindingsForRun(projectRoot, runId) {
|
|
|
7091
7185
|
if (!name.endsWith(".md") || name.startsWith("."))
|
|
7092
7186
|
continue;
|
|
7093
7187
|
const filePath = path9.join(findingsDir, name);
|
|
7094
|
-
const raw = await
|
|
7188
|
+
const raw = await fs12.readFile(filePath, "utf8");
|
|
7095
7189
|
try {
|
|
7096
7190
|
const { frontmatter, body } = parseFrontmatter(raw);
|
|
7097
7191
|
const fm = frontmatter;
|
|
@@ -7122,7 +7216,7 @@ async function resolveCanonicalIds(projectRoot, scenarioSlug, currentRunId, curr
|
|
|
7122
7216
|
const findingsDir = entityDirPath(projectRoot, "finding");
|
|
7123
7217
|
let allNames;
|
|
7124
7218
|
try {
|
|
7125
|
-
allNames = await
|
|
7219
|
+
allNames = await fs12.readdir(findingsDir);
|
|
7126
7220
|
} catch {
|
|
7127
7221
|
allNames = [];
|
|
7128
7222
|
}
|
|
@@ -7130,7 +7224,7 @@ async function resolveCanonicalIds(projectRoot, scenarioSlug, currentRunId, curr
|
|
|
7130
7224
|
if (!name.endsWith(".md") || name.startsWith("."))
|
|
7131
7225
|
continue;
|
|
7132
7226
|
try {
|
|
7133
|
-
const raw = await
|
|
7227
|
+
const raw = await fs12.readFile(path9.join(findingsDir, name), "utf8");
|
|
7134
7228
|
const { frontmatter } = parseFrontmatter(raw);
|
|
7135
7229
|
const fm = frontmatter;
|
|
7136
7230
|
if (!fm.scenario || fm.scenario !== scenarioSlug)
|
|
@@ -7158,7 +7252,7 @@ async function resolveCanonicalIds(projectRoot, scenarioSlug, currentRunId, curr
|
|
|
7158
7252
|
continue;
|
|
7159
7253
|
const candidatePath = path9.join(findingsDir, name);
|
|
7160
7254
|
try {
|
|
7161
|
-
const candidateRaw = await
|
|
7255
|
+
const candidateRaw = await fs12.readFile(candidatePath, "utf8");
|
|
7162
7256
|
const { frontmatter: cFm } = parseFrontmatter(candidateRaw);
|
|
7163
7257
|
if (cFm.id === f.frontmatter.id) {
|
|
7164
7258
|
targetPath = candidatePath;
|
|
@@ -7169,7 +7263,7 @@ async function resolveCanonicalIds(projectRoot, scenarioSlug, currentRunId, curr
|
|
|
7169
7263
|
}
|
|
7170
7264
|
if (targetPath) {
|
|
7171
7265
|
await withFileLock(targetPath, async () => {
|
|
7172
|
-
const raw = await
|
|
7266
|
+
const raw = await fs12.readFile(targetPath, "utf8");
|
|
7173
7267
|
const updated = raw.replace(/^(---\n[\s\S]*?)(---\n)/m, `$1canonical_id: ${canonicalId}
|
|
7174
7268
|
$2`);
|
|
7175
7269
|
if (updated !== raw) {
|
|
@@ -7305,7 +7399,7 @@ async function compareWithBaseline(projectRoot, scenarioSlug, currentRunId, curr
|
|
|
7305
7399
|
continue;
|
|
7306
7400
|
try {
|
|
7307
7401
|
const mPath = path9.join(runDir(projectRoot, rid), "walkthrough.json");
|
|
7308
|
-
const raw = await
|
|
7402
|
+
const raw = await fs12.readFile(mPath, "utf8");
|
|
7309
7403
|
const m = JSON.parse(raw);
|
|
7310
7404
|
if (m.scenario_slug === scenarioSlug && m.status === "completed") {
|
|
7311
7405
|
baselineRunId = rid;
|
|
@@ -7388,7 +7482,7 @@ async function updateFixStatus(projectRoot, slug, status2) {
|
|
|
7388
7482
|
const findingsDir = entityDirPath(projectRoot, "finding");
|
|
7389
7483
|
const filePath = path9.join(findingsDir, `${slug}.md`);
|
|
7390
7484
|
await withFileLock(filePath, async () => {
|
|
7391
|
-
const raw = await
|
|
7485
|
+
const raw = await fs12.readFile(filePath, "utf8");
|
|
7392
7486
|
const updated = raw.replace(/^(fix_status:\s*).*$/m, `$1${status2}`);
|
|
7393
7487
|
if (updated !== raw) {
|
|
7394
7488
|
await atomicWriteFile(filePath, updated);
|
|
@@ -7404,7 +7498,7 @@ fix_status: ${status2}`);
|
|
|
7404
7498
|
async function listRunsInternal(projectRoot) {
|
|
7405
7499
|
const dir = path9.join(projectRoot, "iamu", ".runs");
|
|
7406
7500
|
try {
|
|
7407
|
-
const names = await
|
|
7501
|
+
const names = await fs12.readdir(dir);
|
|
7408
7502
|
return names.filter((n) => !n.startsWith(".")).sort();
|
|
7409
7503
|
} catch {
|
|
7410
7504
|
return [];
|
|
@@ -7586,7 +7680,7 @@ __export(walkthrough_mirror_exports, {
|
|
|
7586
7680
|
walkthroughBundleSchema: () => walkthroughBundleSchema
|
|
7587
7681
|
});
|
|
7588
7682
|
import { createHash as createHash3 } from "crypto";
|
|
7589
|
-
import { promises as
|
|
7683
|
+
import { promises as fs13 } from "fs";
|
|
7590
7684
|
import path10 from "path";
|
|
7591
7685
|
function toCloudRunUuid(runId) {
|
|
7592
7686
|
if (UUID_RE.test(runId))
|
|
@@ -7639,7 +7733,7 @@ function buildPushUrl(cloudApiUrl, cloudProjectId) {
|
|
|
7639
7733
|
async function readLocalManifest(projectRoot, runId) {
|
|
7640
7734
|
const p = path10.join(runDir(projectRoot, runId), "walkthrough.json");
|
|
7641
7735
|
try {
|
|
7642
|
-
const raw = await
|
|
7736
|
+
const raw = await fs13.readFile(p, "utf8");
|
|
7643
7737
|
return JSON.parse(raw);
|
|
7644
7738
|
} catch {
|
|
7645
7739
|
return null;
|
|
@@ -7648,7 +7742,7 @@ async function readLocalManifest(projectRoot, runId) {
|
|
|
7648
7742
|
async function readLocalReport(projectRoot, runId) {
|
|
7649
7743
|
const p = path10.join(runDir(projectRoot, runId), "report.md");
|
|
7650
7744
|
try {
|
|
7651
|
-
return await
|
|
7745
|
+
return await fs13.readFile(p, "utf8");
|
|
7652
7746
|
} catch (err) {
|
|
7653
7747
|
if (err.code === "ENOENT")
|
|
7654
7748
|
return "";
|
|
@@ -7659,7 +7753,7 @@ async function readScreenshotBytes(projectRoot, runId) {
|
|
|
7659
7753
|
const dir = path10.join(runDir(projectRoot, runId), SCREENSHOTS_DIR);
|
|
7660
7754
|
let names;
|
|
7661
7755
|
try {
|
|
7662
|
-
names = await
|
|
7756
|
+
names = await fs13.readdir(dir);
|
|
7663
7757
|
} catch (err) {
|
|
7664
7758
|
if (err.code === "ENOENT")
|
|
7665
7759
|
return /* @__PURE__ */ new Map();
|
|
@@ -7675,7 +7769,7 @@ async function readScreenshotBytes(projectRoot, runId) {
|
|
|
7675
7769
|
const contentType = EXT_TO_CONTENT_TYPE[ext === ".jpeg" ? ".jpeg" : ext];
|
|
7676
7770
|
if (!contentType)
|
|
7677
7771
|
continue;
|
|
7678
|
-
const bytes = await
|
|
7772
|
+
const bytes = await fs13.readFile(path10.join(dir, name));
|
|
7679
7773
|
out.set(seq2, { bytes, filename: name, contentType });
|
|
7680
7774
|
}
|
|
7681
7775
|
return out;
|
|
@@ -7683,7 +7777,7 @@ async function readScreenshotBytes(projectRoot, runId) {
|
|
|
7683
7777
|
async function readVerdictsJson(projectRoot, runId) {
|
|
7684
7778
|
const filePath = path10.join(runDir(projectRoot, runId), "verdicts.json");
|
|
7685
7779
|
try {
|
|
7686
|
-
const raw = await
|
|
7780
|
+
const raw = await fs13.readFile(filePath, "utf-8");
|
|
7687
7781
|
return JSON.parse(raw);
|
|
7688
7782
|
} catch {
|
|
7689
7783
|
return null;
|
|
@@ -7694,7 +7788,7 @@ async function readProvenance(projectRoot, runId, verdicts) {
|
|
|
7694
7788
|
return verdicts.provenance;
|
|
7695
7789
|
const filePath = path10.join(runDir(projectRoot, runId), "canonical.json");
|
|
7696
7790
|
try {
|
|
7697
|
-
const raw = await
|
|
7791
|
+
const raw = await fs13.readFile(filePath, "utf-8");
|
|
7698
7792
|
const data = JSON.parse(raw);
|
|
7699
7793
|
return data.provenance ?? null;
|
|
7700
7794
|
} catch {
|
|
@@ -7703,7 +7797,7 @@ async function readProvenance(projectRoot, runId, verdicts) {
|
|
|
7703
7797
|
}
|
|
7704
7798
|
async function readCanonicalExtras(projectRoot, runId) {
|
|
7705
7799
|
try {
|
|
7706
|
-
const data = JSON.parse(await
|
|
7800
|
+
const data = JSON.parse(await fs13.readFile(path10.join(runDir(projectRoot, runId), "canonical.json"), "utf-8"));
|
|
7707
7801
|
const strings = (v) => Array.isArray(v) && v.every((x) => typeof x === "string") ? v : void 0;
|
|
7708
7802
|
const verification = bundleVerificationSchema.safeParse(data.verification);
|
|
7709
7803
|
return {
|
|
@@ -8442,7 +8536,7 @@ var init_refs = __esm({
|
|
|
8442
8536
|
});
|
|
8443
8537
|
|
|
8444
8538
|
// ../../packages/local-store/dist/sync/types.js
|
|
8445
|
-
import { z as
|
|
8539
|
+
import { z as z24 } from "zod";
|
|
8446
8540
|
function toRef(d) {
|
|
8447
8541
|
return { type: d.type, id: d.id, label: d.label };
|
|
8448
8542
|
}
|
|
@@ -8507,17 +8601,17 @@ var init_types = __esm({
|
|
|
8507
8601
|
DEFAULT_TIMEOUT_MS4 = 3e4;
|
|
8508
8602
|
MAX_BATCH_BYTES = 6 * 1024 * 1024;
|
|
8509
8603
|
BASE_HASH_BYTES = 96;
|
|
8510
|
-
importConflictSchema =
|
|
8511
|
-
type:
|
|
8512
|
-
id:
|
|
8513
|
-
base_hash:
|
|
8514
|
-
cloud_hash:
|
|
8515
|
-
cloud_updated_at:
|
|
8516
|
-
cloud_changed_by:
|
|
8604
|
+
importConflictSchema = z24.object({
|
|
8605
|
+
type: z24.string(),
|
|
8606
|
+
id: z24.string(),
|
|
8607
|
+
base_hash: z24.string().nullish(),
|
|
8608
|
+
cloud_hash: z24.string(),
|
|
8609
|
+
cloud_updated_at: z24.string().nullish(),
|
|
8610
|
+
cloud_changed_by: z24.string().nullish()
|
|
8517
8611
|
});
|
|
8518
|
-
importResponseSchema =
|
|
8519
|
-
imported:
|
|
8520
|
-
conflicts:
|
|
8612
|
+
importResponseSchema = z24.object({
|
|
8613
|
+
imported: z24.number().int().min(0),
|
|
8614
|
+
conflicts: z24.array(importConflictSchema).optional()
|
|
8521
8615
|
});
|
|
8522
8616
|
}
|
|
8523
8617
|
});
|
|
@@ -8768,7 +8862,7 @@ var init_push = __esm({
|
|
|
8768
8862
|
});
|
|
8769
8863
|
|
|
8770
8864
|
// ../../packages/local-store/dist/sync/context.js
|
|
8771
|
-
import { promises as
|
|
8865
|
+
import { promises as fs14 } from "fs";
|
|
8772
8866
|
async function syncContext(target) {
|
|
8773
8867
|
const { projectRoot } = target;
|
|
8774
8868
|
const summary = zeroContext();
|
|
@@ -8776,7 +8870,7 @@ async function syncContext(target) {
|
|
|
8776
8870
|
const conflicts = [];
|
|
8777
8871
|
let raw;
|
|
8778
8872
|
try {
|
|
8779
|
-
raw = await
|
|
8873
|
+
raw = await fs14.readFile(contextPath(projectRoot), "utf8");
|
|
8780
8874
|
} catch (err) {
|
|
8781
8875
|
if (err.code === "ENOENT")
|
|
8782
8876
|
return { summary, errors, conflicts };
|
|
@@ -8986,7 +9080,7 @@ var init_git_branches = __esm({
|
|
|
8986
9080
|
});
|
|
8987
9081
|
|
|
8988
9082
|
// ../../packages/local-store/dist/deletions.js
|
|
8989
|
-
import { promises as
|
|
9083
|
+
import { promises as fs15 } from "fs";
|
|
8990
9084
|
import path12 from "path";
|
|
8991
9085
|
function describeDeletionCount(type2, n) {
|
|
8992
9086
|
const nouns = {
|
|
@@ -9014,7 +9108,7 @@ function summarizeDeletions(items) {
|
|
|
9014
9108
|
}
|
|
9015
9109
|
async function readPushedEntities(projectRoot) {
|
|
9016
9110
|
try {
|
|
9017
|
-
const raw = await
|
|
9111
|
+
const raw = await fs15.readFile(pushedEntitiesPath(projectRoot), "utf8");
|
|
9018
9112
|
const parsed = JSON.parse(raw);
|
|
9019
9113
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
9020
9114
|
return {};
|
|
@@ -9053,7 +9147,7 @@ async function rememberPushedEntities(projectRoot, known) {
|
|
|
9053
9147
|
}
|
|
9054
9148
|
async function readLenient(projectRoot, relPath) {
|
|
9055
9149
|
try {
|
|
9056
|
-
const raw = await
|
|
9150
|
+
const raw = await fs15.readFile(path12.join(projectRoot, relPath), "utf8");
|
|
9057
9151
|
const fm = parseFrontmatter(raw).frontmatter;
|
|
9058
9152
|
if (typeof fm.id !== "string" || fm.id.length === 0)
|
|
9059
9153
|
return null;
|
|
@@ -9479,7 +9573,7 @@ var init_deletions2 = __esm({
|
|
|
9479
9573
|
});
|
|
9480
9574
|
|
|
9481
9575
|
// ../../packages/local-store/dist/sync/scan.js
|
|
9482
|
-
import { promises as
|
|
9576
|
+
import { promises as fs16 } from "fs";
|
|
9483
9577
|
function blockedRef(refs, blocked) {
|
|
9484
9578
|
if (!refs)
|
|
9485
9579
|
return null;
|
|
@@ -9575,7 +9669,7 @@ async function scanPending(projectRoot) {
|
|
|
9575
9669
|
continue;
|
|
9576
9670
|
let bytes;
|
|
9577
9671
|
try {
|
|
9578
|
-
bytes = await
|
|
9672
|
+
bytes = await fs16.readFile(entity.absPath, "utf8");
|
|
9579
9673
|
} catch {
|
|
9580
9674
|
continue;
|
|
9581
9675
|
}
|
|
@@ -9636,7 +9730,7 @@ var init_scan = __esm({
|
|
|
9636
9730
|
});
|
|
9637
9731
|
|
|
9638
9732
|
// ../../packages/local-store/dist/sync/walkthroughs.js
|
|
9639
|
-
import { promises as
|
|
9733
|
+
import { promises as fs17 } from "fs";
|
|
9640
9734
|
import nodePath from "path";
|
|
9641
9735
|
async function syncWalkthroughs(projectRoot, deps, unpushableScenarios = /* @__PURE__ */ new Set()) {
|
|
9642
9736
|
const summary = zeroWalkthroughs();
|
|
@@ -9664,7 +9758,7 @@ async function syncWalkthroughs(projectRoot, deps, unpushableScenarios = /* @__P
|
|
|
9664
9758
|
const manifestPath = nodePath.join(runDir(projectRoot, runId), "walkthrough.json");
|
|
9665
9759
|
let manifestRaw;
|
|
9666
9760
|
try {
|
|
9667
|
-
manifestRaw = await
|
|
9761
|
+
manifestRaw = await fs17.readFile(manifestPath, "utf8");
|
|
9668
9762
|
} catch {
|
|
9669
9763
|
continue;
|
|
9670
9764
|
}
|
|
@@ -10003,7 +10097,7 @@ var init_disconnect = __esm({
|
|
|
10003
10097
|
});
|
|
10004
10098
|
|
|
10005
10099
|
// ../../packages/local-store/dist/status.js
|
|
10006
|
-
import { promises as
|
|
10100
|
+
import { promises as fs18 } from "fs";
|
|
10007
10101
|
import path13 from "path";
|
|
10008
10102
|
async function countType(projectRoot, type2) {
|
|
10009
10103
|
const result = await listEntities(projectRoot, type2);
|
|
@@ -10014,7 +10108,7 @@ async function countType(projectRoot, type2) {
|
|
|
10014
10108
|
if (typeof id !== "string" || typeof slug !== "string")
|
|
10015
10109
|
continue;
|
|
10016
10110
|
try {
|
|
10017
|
-
const raw = await
|
|
10111
|
+
const raw = await fs18.readFile(entity.absPath, "utf8");
|
|
10018
10112
|
contentHashes.set(id, hashNormalizedContent(raw));
|
|
10019
10113
|
} catch {
|
|
10020
10114
|
}
|
|
@@ -10108,7 +10202,7 @@ async function countContext(projectRoot, opts = {
|
|
|
10108
10202
|
return base;
|
|
10109
10203
|
let pending = true;
|
|
10110
10204
|
try {
|
|
10111
|
-
const bytes = await
|
|
10205
|
+
const bytes = await fs18.readFile(contextPath(projectRoot), "utf8");
|
|
10112
10206
|
const hash = hashNormalizedContent(bytes);
|
|
10113
10207
|
pending = opts.lastPush["context:root"] !== hash;
|
|
10114
10208
|
} catch {
|
|
@@ -10130,7 +10224,7 @@ async function countWalkthroughs(projectRoot, opts = { cloudLinked: false, lastP
|
|
|
10130
10224
|
const manifestPath = path13.join(projectRoot, "iamu", ".runs", runId, "walkthrough.json");
|
|
10131
10225
|
let completed = false;
|
|
10132
10226
|
try {
|
|
10133
|
-
const raw = await
|
|
10227
|
+
const raw = await fs18.readFile(manifestPath, "utf8");
|
|
10134
10228
|
const manifest = JSON.parse(raw);
|
|
10135
10229
|
completed = manifest.status === "completed";
|
|
10136
10230
|
} catch {
|
|
@@ -10150,7 +10244,7 @@ async function getProjectStatus(projectRoot, opts = {}) {
|
|
|
10150
10244
|
const config = await readConfig(projectRoot);
|
|
10151
10245
|
const iamuPath = iamuDir(projectRoot);
|
|
10152
10246
|
try {
|
|
10153
|
-
await
|
|
10247
|
+
await fs18.access(iamuPath);
|
|
10154
10248
|
} catch {
|
|
10155
10249
|
throw new Error(`status: iamu/ directory missing at ${iamuPath}`);
|
|
10156
10250
|
}
|
|
@@ -10332,13 +10426,13 @@ var init_status = __esm({
|
|
|
10332
10426
|
});
|
|
10333
10427
|
|
|
10334
10428
|
// ../../packages/local-store/dist/prune.js
|
|
10335
|
-
import { promises as
|
|
10429
|
+
import { promises as fs19 } from "fs";
|
|
10336
10430
|
import path14 from "path";
|
|
10337
10431
|
async function getDirectoryStats(dirPath) {
|
|
10338
10432
|
let bytes = 0;
|
|
10339
10433
|
let count = 0;
|
|
10340
10434
|
try {
|
|
10341
|
-
const entries = await
|
|
10435
|
+
const entries = await fs19.readdir(dirPath, { withFileTypes: true });
|
|
10342
10436
|
for (const entry of entries) {
|
|
10343
10437
|
const fullPath = path14.join(dirPath, entry.name);
|
|
10344
10438
|
if (entry.isDirectory()) {
|
|
@@ -10347,7 +10441,7 @@ async function getDirectoryStats(dirPath) {
|
|
|
10347
10441
|
count += sub.count;
|
|
10348
10442
|
} else if (entry.isFile()) {
|
|
10349
10443
|
try {
|
|
10350
|
-
const s = await
|
|
10444
|
+
const s = await fs19.stat(fullPath);
|
|
10351
10445
|
bytes += s.size;
|
|
10352
10446
|
count += 1;
|
|
10353
10447
|
} catch {
|
|
@@ -10363,12 +10457,12 @@ async function getScreenshotsStats(screenshotsDir) {
|
|
|
10363
10457
|
let count = 0;
|
|
10364
10458
|
const paths = [];
|
|
10365
10459
|
try {
|
|
10366
|
-
const entries = await
|
|
10460
|
+
const entries = await fs19.readdir(screenshotsDir, { withFileTypes: true });
|
|
10367
10461
|
for (const entry of entries) {
|
|
10368
10462
|
if (entry.isFile() && (entry.name.endsWith(".png") || entry.name.endsWith(".jpg") || entry.name.endsWith(".jpeg") || entry.name.endsWith(".webp"))) {
|
|
10369
10463
|
const fullPath = path14.join(screenshotsDir, entry.name);
|
|
10370
10464
|
try {
|
|
10371
|
-
const s = await
|
|
10465
|
+
const s = await fs19.stat(fullPath);
|
|
10372
10466
|
bytes += s.size;
|
|
10373
10467
|
count += 1;
|
|
10374
10468
|
paths.push(fullPath);
|
|
@@ -10389,7 +10483,7 @@ async function pruneRuns(projectRoot, opts = {}) {
|
|
|
10389
10483
|
let scenarioSlug;
|
|
10390
10484
|
try {
|
|
10391
10485
|
const manifestPath = path14.join(dirPath, "walkthrough.json");
|
|
10392
|
-
const raw = await
|
|
10486
|
+
const raw = await fs19.readFile(manifestPath, "utf-8");
|
|
10393
10487
|
const parsed = JSON.parse(raw);
|
|
10394
10488
|
if (parsed.scenario_slug)
|
|
10395
10489
|
scenarioSlug = parsed.scenario_slug;
|
|
@@ -10401,7 +10495,7 @@ async function pruneRuns(projectRoot, opts = {}) {
|
|
|
10401
10495
|
}
|
|
10402
10496
|
if (!timestamp2 || Number.isNaN(timestamp2.getTime())) {
|
|
10403
10497
|
try {
|
|
10404
|
-
const st = await
|
|
10498
|
+
const st = await fs19.stat(dirPath);
|
|
10405
10499
|
timestamp2 = st.mtime;
|
|
10406
10500
|
} catch {
|
|
10407
10501
|
timestamp2 = /* @__PURE__ */ new Date();
|
|
@@ -10441,7 +10535,7 @@ async function pruneRuns(projectRoot, opts = {}) {
|
|
|
10441
10535
|
if (opts.screenshotsOnly) {
|
|
10442
10536
|
if (!opts.dryRun) {
|
|
10443
10537
|
for (const shotPath of shotStats.paths) {
|
|
10444
|
-
await
|
|
10538
|
+
await fs19.unlink(shotPath).catch(() => {
|
|
10445
10539
|
});
|
|
10446
10540
|
}
|
|
10447
10541
|
}
|
|
@@ -10458,7 +10552,7 @@ async function pruneRuns(projectRoot, opts = {}) {
|
|
|
10458
10552
|
} else {
|
|
10459
10553
|
const dirStats = await getDirectoryStats(c.dirPath);
|
|
10460
10554
|
if (!opts.dryRun) {
|
|
10461
|
-
await
|
|
10555
|
+
await fs19.rm(c.dirPath, { recursive: true, force: true });
|
|
10462
10556
|
}
|
|
10463
10557
|
prunedRuns.push({
|
|
10464
10558
|
runId: c.runId,
|
|
@@ -10490,7 +10584,7 @@ var init_prune = __esm({
|
|
|
10490
10584
|
|
|
10491
10585
|
// ../../packages/local-store/dist/explore-map.js
|
|
10492
10586
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
10493
|
-
import { promises as
|
|
10587
|
+
import { promises as fs20 } from "fs";
|
|
10494
10588
|
import path15 from "path";
|
|
10495
10589
|
function templateToken(token) {
|
|
10496
10590
|
if (token === "")
|
|
@@ -10586,13 +10680,13 @@ function mapPath(projectRoot, id) {
|
|
|
10586
10680
|
}
|
|
10587
10681
|
async function writeExploreMap(projectRoot, map2) {
|
|
10588
10682
|
const file = mapPath(projectRoot, map2.id);
|
|
10589
|
-
await
|
|
10683
|
+
await fs20.mkdir(path15.dirname(file), { recursive: true });
|
|
10590
10684
|
await atomicWriteFile(file, `${JSON.stringify(map2, null, 2)}
|
|
10591
10685
|
`);
|
|
10592
10686
|
return file;
|
|
10593
10687
|
}
|
|
10594
10688
|
async function readExploreMap(projectRoot, id) {
|
|
10595
|
-
const raw = await
|
|
10689
|
+
const raw = await fs20.readFile(mapPath(projectRoot, id), "utf8");
|
|
10596
10690
|
const map2 = JSON.parse(raw);
|
|
10597
10691
|
if (map2?.schema !== EXPLORE_MAP_SCHEMA || !Array.isArray(map2.surfaces)) {
|
|
10598
10692
|
throw new Error(`Unreadable explore map: ${id}`);
|
|
@@ -10601,7 +10695,7 @@ async function readExploreMap(projectRoot, id) {
|
|
|
10601
10695
|
}
|
|
10602
10696
|
async function listExploreMaps(projectRoot) {
|
|
10603
10697
|
try {
|
|
10604
|
-
const entries = await
|
|
10698
|
+
const entries = await fs20.readdir(exploreDir(projectRoot), {
|
|
10605
10699
|
withFileTypes: true
|
|
10606
10700
|
});
|
|
10607
10701
|
return entries.filter((e) => e.isDirectory() && isValidExploreId(e.name)).map((e) => e.name).sort();
|
|
@@ -10699,6 +10793,127 @@ async function readAllRunSteps(projectRoot) {
|
|
|
10699
10793
|
}
|
|
10700
10794
|
return out;
|
|
10701
10795
|
}
|
|
10796
|
+
function matchSurfaceCapabilities(place, capabilities) {
|
|
10797
|
+
const normPlace = place.length > 1 ? place.replace(/\/+$/, "") : place;
|
|
10798
|
+
const matchedCaps = /* @__PURE__ */ new Map();
|
|
10799
|
+
for (const cap of capabilities) {
|
|
10800
|
+
if (!cap.paths || cap.paths.length === 0)
|
|
10801
|
+
continue;
|
|
10802
|
+
for (const rawPath of cap.paths) {
|
|
10803
|
+
if (!rawPath)
|
|
10804
|
+
continue;
|
|
10805
|
+
const cleanPath = rawPath.length > 1 ? rawPath.replace(/\/+$/, "") : rawPath;
|
|
10806
|
+
let isMatch = false;
|
|
10807
|
+
if (cleanPath === "/") {
|
|
10808
|
+
isMatch = normPlace === "/" || normPlace.startsWith("/?") || normPlace.startsWith("/#");
|
|
10809
|
+
} else {
|
|
10810
|
+
isMatch = normPlace === cleanPath || normPlace.startsWith(`${cleanPath}/`) || normPlace.startsWith(`${cleanPath}?`) || normPlace.startsWith(`${cleanPath}#`);
|
|
10811
|
+
}
|
|
10812
|
+
if (isMatch) {
|
|
10813
|
+
const prevLen = matchedCaps.get(cap.slug) ?? -1;
|
|
10814
|
+
if (cleanPath.length > prevLen) {
|
|
10815
|
+
matchedCaps.set(cap.slug, cleanPath.length);
|
|
10816
|
+
}
|
|
10817
|
+
}
|
|
10818
|
+
}
|
|
10819
|
+
}
|
|
10820
|
+
if (matchedCaps.size > 0) {
|
|
10821
|
+
return Array.from(matchedCaps.entries()).sort((a, b) => b[1] - a[1]).map(([slug]) => slug);
|
|
10822
|
+
}
|
|
10823
|
+
const firstSegment = normPlace.replace(/^\/+/, "").split(/[/\\?#]/)[0];
|
|
10824
|
+
if (firstSegment) {
|
|
10825
|
+
const slugMatches = [];
|
|
10826
|
+
for (const c of capabilities) {
|
|
10827
|
+
if (c.slug === firstSegment || c.slug.toLowerCase() === firstSegment.toLowerCase()) {
|
|
10828
|
+
slugMatches.push(c.slug);
|
|
10829
|
+
}
|
|
10830
|
+
}
|
|
10831
|
+
if (slugMatches.length > 0)
|
|
10832
|
+
return slugMatches;
|
|
10833
|
+
}
|
|
10834
|
+
return [];
|
|
10835
|
+
}
|
|
10836
|
+
function summarizeCapabilityCoverage(surfaces, capabilities, outlines = []) {
|
|
10837
|
+
const capMap = /* @__PURE__ */ new Map();
|
|
10838
|
+
for (const c of capabilities) {
|
|
10839
|
+
capMap.set(c.slug, []);
|
|
10840
|
+
}
|
|
10841
|
+
const unassigned = [];
|
|
10842
|
+
for (const s of surfaces) {
|
|
10843
|
+
const matchedSlugs = matchSurfaceCapabilities(s.place, capabilities);
|
|
10844
|
+
if (matchedSlugs.length > 0) {
|
|
10845
|
+
for (const slug of matchedSlugs) {
|
|
10846
|
+
capMap.get(slug)?.push(s);
|
|
10847
|
+
}
|
|
10848
|
+
} else {
|
|
10849
|
+
unassigned.push(s);
|
|
10850
|
+
}
|
|
10851
|
+
}
|
|
10852
|
+
const primaryCounts = /* @__PURE__ */ new Map();
|
|
10853
|
+
const secondaryCounts = /* @__PURE__ */ new Map();
|
|
10854
|
+
for (const o of outlines) {
|
|
10855
|
+
if (o.primary_capability) {
|
|
10856
|
+
primaryCounts.set(o.primary_capability, (primaryCounts.get(o.primary_capability) ?? 0) + 1);
|
|
10857
|
+
}
|
|
10858
|
+
if (Array.isArray(o.additional_capabilities)) {
|
|
10859
|
+
for (const add of o.additional_capabilities) {
|
|
10860
|
+
if (add) {
|
|
10861
|
+
secondaryCounts.set(add, (secondaryCounts.get(add) ?? 0) + 1);
|
|
10862
|
+
}
|
|
10863
|
+
}
|
|
10864
|
+
}
|
|
10865
|
+
}
|
|
10866
|
+
const summaries = capabilities.map((c) => {
|
|
10867
|
+
const owned = capMap.get(c.slug) ?? [];
|
|
10868
|
+
const reached = owned.filter((s) => s.status === "reached").length;
|
|
10869
|
+
const unreached = owned.length - reached;
|
|
10870
|
+
const coverage_pct = owned.length > 0 ? Math.round(reached / owned.length * 100) : 0;
|
|
10871
|
+
const primary = primaryCounts.get(c.slug) ?? 0;
|
|
10872
|
+
const secondary = secondaryCounts.get(c.slug) ?? 0;
|
|
10873
|
+
return {
|
|
10874
|
+
slug: c.slug,
|
|
10875
|
+
title: c.title,
|
|
10876
|
+
area: c.area ?? null,
|
|
10877
|
+
total_surfaces: owned.length,
|
|
10878
|
+
reached_surfaces: reached,
|
|
10879
|
+
unreached_surfaces: unreached,
|
|
10880
|
+
coverage_pct,
|
|
10881
|
+
primary_scenarios: primary,
|
|
10882
|
+
secondary_scenarios: secondary,
|
|
10883
|
+
surfaces: owned
|
|
10884
|
+
};
|
|
10885
|
+
});
|
|
10886
|
+
summaries.sort((a, b) => {
|
|
10887
|
+
const aUntested = a.primary_scenarios === 0 && a.unreached_surfaces > 0;
|
|
10888
|
+
const bUntested = b.primary_scenarios === 0 && b.unreached_surfaces > 0;
|
|
10889
|
+
if (aUntested !== bUntested)
|
|
10890
|
+
return aUntested ? -1 : 1;
|
|
10891
|
+
if (a.coverage_pct !== b.coverage_pct)
|
|
10892
|
+
return a.coverage_pct - b.coverage_pct;
|
|
10893
|
+
return a.slug.localeCompare(b.slug);
|
|
10894
|
+
});
|
|
10895
|
+
return {
|
|
10896
|
+
capabilities: summaries,
|
|
10897
|
+
unassigned_surfaces: unassigned
|
|
10898
|
+
};
|
|
10899
|
+
}
|
|
10900
|
+
async function readCapabilityCoverage(projectRoot, coverage) {
|
|
10901
|
+
const [capsResult, outlinesResult] = await Promise.all([
|
|
10902
|
+
listEntities(projectRoot, "capability"),
|
|
10903
|
+
listEntities(projectRoot, "outline")
|
|
10904
|
+
]);
|
|
10905
|
+
const caps = capsResult.entities.map((e) => ({
|
|
10906
|
+
slug: e.frontmatter.slug,
|
|
10907
|
+
title: e.frontmatter.title,
|
|
10908
|
+
area: e.frontmatter.area ?? null,
|
|
10909
|
+
paths: e.frontmatter.paths ?? []
|
|
10910
|
+
}));
|
|
10911
|
+
const outlines = outlinesResult.entities.map((e) => ({
|
|
10912
|
+
primary_capability: e.frontmatter.primary_capability,
|
|
10913
|
+
additional_capabilities: e.frontmatter.additional_capabilities ?? []
|
|
10914
|
+
}));
|
|
10915
|
+
return summarizeCapabilityCoverage(coverage.surfaces, caps, outlines);
|
|
10916
|
+
}
|
|
10702
10917
|
function actionSignature(a) {
|
|
10703
10918
|
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;
|
|
10704
10919
|
return `${a.role} "${a.name}" \u2192 ${where}`;
|
|
@@ -10743,6 +10958,7 @@ var init_explore_map = __esm({
|
|
|
10743
10958
|
"../../packages/local-store/dist/explore-map.js"() {
|
|
10744
10959
|
"use strict";
|
|
10745
10960
|
init_atomic();
|
|
10961
|
+
init_entity();
|
|
10746
10962
|
init_paths();
|
|
10747
10963
|
init_revisit();
|
|
10748
10964
|
init_runs();
|
|
@@ -10755,7 +10971,7 @@ var init_explore_map = __esm({
|
|
|
10755
10971
|
});
|
|
10756
10972
|
|
|
10757
10973
|
// ../../packages/local-store/dist/human-test-link.js
|
|
10758
|
-
import { promises as
|
|
10974
|
+
import { promises as fs21 } from "fs";
|
|
10759
10975
|
import path16 from "path";
|
|
10760
10976
|
function humanTestLinks(verdicts) {
|
|
10761
10977
|
const best = /* @__PURE__ */ new Map();
|
|
@@ -10779,7 +10995,7 @@ async function linkFindingsToHumanTests(projectRoot, runId, verdicts) {
|
|
|
10779
10995
|
const dir = entityDirPath(projectRoot, "finding");
|
|
10780
10996
|
let names;
|
|
10781
10997
|
try {
|
|
10782
|
-
names = await
|
|
10998
|
+
names = await fs21.readdir(dir);
|
|
10783
10999
|
} catch {
|
|
10784
11000
|
return [];
|
|
10785
11001
|
}
|
|
@@ -10791,7 +11007,7 @@ async function linkFindingsToHumanTests(projectRoot, runId, verdicts) {
|
|
|
10791
11007
|
let raw;
|
|
10792
11008
|
let fm;
|
|
10793
11009
|
try {
|
|
10794
|
-
raw = await
|
|
11010
|
+
raw = await fs21.readFile(file, "utf8");
|
|
10795
11011
|
fm = parseFrontmatter(raw).frontmatter;
|
|
10796
11012
|
} catch {
|
|
10797
11013
|
continue;
|
|
@@ -11022,14 +11238,14 @@ var init_cloud_client = __esm({
|
|
|
11022
11238
|
});
|
|
11023
11239
|
|
|
11024
11240
|
// ../../packages/local-store/dist/last-pull.js
|
|
11025
|
-
import { promises as
|
|
11241
|
+
import { promises as fs22 } from "fs";
|
|
11026
11242
|
import path17 from "path";
|
|
11027
11243
|
function lastPullPath(projectRoot) {
|
|
11028
11244
|
return path17.join(cacheDir(projectRoot), "last-pull.json");
|
|
11029
11245
|
}
|
|
11030
11246
|
async function readLastPull(projectRoot) {
|
|
11031
11247
|
try {
|
|
11032
|
-
const raw = await
|
|
11248
|
+
const raw = await fs22.readFile(lastPullPath(projectRoot), "utf8");
|
|
11033
11249
|
const parsed = JSON.parse(raw);
|
|
11034
11250
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
11035
11251
|
return parsed;
|
|
@@ -11315,7 +11531,7 @@ var init_frontmatter2 = __esm({
|
|
|
11315
11531
|
});
|
|
11316
11532
|
|
|
11317
11533
|
// ../../packages/local-store/dist/pull/write.js
|
|
11318
|
-
import { promises as
|
|
11534
|
+
import { promises as fs23 } from "fs";
|
|
11319
11535
|
async function loadLocalIndex(projectRoot, type2) {
|
|
11320
11536
|
const byId = /* @__PURE__ */ new Map();
|
|
11321
11537
|
const bySlug = /* @__PURE__ */ new Map();
|
|
@@ -11344,7 +11560,7 @@ async function classifyExisting(projectRoot, type2, cloudId, localSlug, targetSl
|
|
|
11344
11560
|
if (localSlug !== targetSlug)
|
|
11345
11561
|
return "untracked";
|
|
11346
11562
|
const lastSynced = localIndex.lastPushById[cloudId];
|
|
11347
|
-
const bytes = await
|
|
11563
|
+
const bytes = await fs23.readFile(entityFilePath(projectRoot, type2, localSlug), "utf8");
|
|
11348
11564
|
return lastSynced && hashNormalizedContent(bytes) === lastSynced ? "fast_forward" : "diverged";
|
|
11349
11565
|
}
|
|
11350
11566
|
async function writeOrSkip(projectRoot, type2, cloudId, slug, frontmatter, body, localIndex, mode, cloudVersion) {
|
|
@@ -11405,13 +11621,13 @@ async function writeOrSkip(projectRoot, type2, cloudId, slug, frontmatter, body,
|
|
|
11405
11621
|
}
|
|
11406
11622
|
if (existingSlugForId && existingSlugForId !== slug) {
|
|
11407
11623
|
try {
|
|
11408
|
-
await
|
|
11624
|
+
await fs23.unlink(entityFilePath(projectRoot, type2, existingSlugForId));
|
|
11409
11625
|
localIndex.bySlug.delete(existingSlugForId);
|
|
11410
11626
|
} catch {
|
|
11411
11627
|
}
|
|
11412
11628
|
}
|
|
11413
11629
|
await writeEntity(projectRoot, type2, frontmatter, text);
|
|
11414
|
-
const bytes = await
|
|
11630
|
+
const bytes = await fs23.readFile(entityFilePath(projectRoot, type2, slug), "utf8");
|
|
11415
11631
|
const hash = hashNormalizedContent(bytes);
|
|
11416
11632
|
localIndex.byId.set(cloudId, slug);
|
|
11417
11633
|
localIndex.bySlug.set(slug, cloudId);
|
|
@@ -11465,7 +11681,7 @@ var init_write = __esm({
|
|
|
11465
11681
|
});
|
|
11466
11682
|
|
|
11467
11683
|
// ../../packages/local-store/dist/pull/entities.js
|
|
11468
|
-
import { promises as
|
|
11684
|
+
import { promises as fs24 } from "fs";
|
|
11469
11685
|
function buildContextFrontmatter(payload) {
|
|
11470
11686
|
const cloudCtx = payload.context ?? {};
|
|
11471
11687
|
const glossary = (payload.glossary ?? []).map((g) => ({
|
|
@@ -11520,7 +11736,7 @@ async function pullContext(projectRoot, cloud, projectId, mode, result) {
|
|
|
11520
11736
|
const frontmatter = buildContextFrontmatter(payload);
|
|
11521
11737
|
let hasLocal = false;
|
|
11522
11738
|
try {
|
|
11523
|
-
await
|
|
11739
|
+
await fs24.access(contextPath(projectRoot));
|
|
11524
11740
|
hasLocal = true;
|
|
11525
11741
|
} catch {
|
|
11526
11742
|
hasLocal = false;
|
|
@@ -11550,7 +11766,7 @@ async function pullContext(projectRoot, cloud, projectId, mode, result) {
|
|
|
11550
11766
|
frontmatter,
|
|
11551
11767
|
notes_body: existingNotes
|
|
11552
11768
|
});
|
|
11553
|
-
const bytes = await
|
|
11769
|
+
const bytes = await fs24.readFile(contextPath(projectRoot), "utf8");
|
|
11554
11770
|
const hash = hashNormalizedContent(bytes);
|
|
11555
11771
|
await recordLastPull(projectRoot, "context:root", hash);
|
|
11556
11772
|
await recordLastPush(projectRoot, "context:root", hash);
|
|
@@ -12070,6 +12286,7 @@ var init_dist2 = __esm({
|
|
|
12070
12286
|
init_bootstrap();
|
|
12071
12287
|
init_config2();
|
|
12072
12288
|
init_context2();
|
|
12289
|
+
init_testability2();
|
|
12073
12290
|
init_connect();
|
|
12074
12291
|
init_disconnect();
|
|
12075
12292
|
init_status();
|
|
@@ -12967,10 +13184,10 @@ import { existsSync as existsSync4 } from "fs";
|
|
|
12967
13184
|
import { dirname as dirname2, resolve } from "path";
|
|
12968
13185
|
import { fileURLToPath } from "url";
|
|
12969
13186
|
function getTemplatesRoot() {
|
|
12970
|
-
const
|
|
12971
|
-
const inThisDir = resolve(
|
|
13187
|
+
const thisDir = dirname2(fileURLToPath(import.meta.url));
|
|
13188
|
+
const inThisDir = resolve(thisDir, "templates");
|
|
12972
13189
|
if (existsSync4(inThisDir)) return inThisDir;
|
|
12973
|
-
const inParent = resolve(
|
|
13190
|
+
const inParent = resolve(thisDir, "..", "templates");
|
|
12974
13191
|
if (existsSync4(inParent)) return inParent;
|
|
12975
13192
|
return inThisDir;
|
|
12976
13193
|
}
|
|
@@ -12993,11 +13210,24 @@ import { dirname as dirname3, join as join4, resolve as resolve2 } from "path";
|
|
|
12993
13210
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
12994
13211
|
import chalk6 from "chalk";
|
|
12995
13212
|
function getVersion() {
|
|
13213
|
+
if ("0.2.0-beta.17") {
|
|
13214
|
+
return "0.2.0-beta.17";
|
|
13215
|
+
}
|
|
12996
13216
|
try {
|
|
12997
|
-
const
|
|
12998
|
-
const
|
|
12999
|
-
|
|
13000
|
-
|
|
13217
|
+
const thisDir = dirname3(fileURLToPath2(import.meta.url));
|
|
13218
|
+
for (const rel of [".", "..", "../.."]) {
|
|
13219
|
+
const pkgPath = resolve2(thisDir, rel, "package.json");
|
|
13220
|
+
if (existsSync5(pkgPath)) {
|
|
13221
|
+
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
13222
|
+
if (pkg.name === "@iamu-dev/iamu" && pkg.version) {
|
|
13223
|
+
return pkg.version;
|
|
13224
|
+
}
|
|
13225
|
+
if (pkg.version && pkg.version !== "0.0.0") {
|
|
13226
|
+
return pkg.version;
|
|
13227
|
+
}
|
|
13228
|
+
}
|
|
13229
|
+
}
|
|
13230
|
+
return "0.0.0";
|
|
13001
13231
|
} catch {
|
|
13002
13232
|
return "0.0.0";
|
|
13003
13233
|
}
|
|
@@ -14887,17 +15117,12 @@ __export(start_run_exports, {
|
|
|
14887
15117
|
startRun: () => startRun,
|
|
14888
15118
|
testabilityTarget: () => testabilityTarget
|
|
14889
15119
|
});
|
|
14890
|
-
import fs24 from "fs/promises";
|
|
14891
15120
|
import path20 from "path";
|
|
14892
15121
|
import chalk12 from "chalk";
|
|
14893
15122
|
async function testabilityTarget(projectRoot) {
|
|
14894
15123
|
try {
|
|
14895
|
-
const
|
|
14896
|
-
|
|
14897
|
-
"utf8"
|
|
14898
|
-
);
|
|
14899
|
-
const { frontmatter } = parseFrontmatter(raw);
|
|
14900
|
-
return typeof frontmatter.target_url === "string" && frontmatter.target_url.trim().length > 0 ? frontmatter.target_url.trim() : null;
|
|
15124
|
+
const doc = await readTestability(projectRoot);
|
|
15125
|
+
return doc?.frontmatter.target_url ?? null;
|
|
14901
15126
|
} catch {
|
|
14902
15127
|
return null;
|
|
14903
15128
|
}
|
|
@@ -15525,7 +15750,7 @@ var init_fatal = __esm({
|
|
|
15525
15750
|
|
|
15526
15751
|
// src/sync-mcp/tools.ts
|
|
15527
15752
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
15528
|
-
import { z as
|
|
15753
|
+
import { z as z25 } from "zod";
|
|
15529
15754
|
function getProjectRoot() {
|
|
15530
15755
|
const root = findProjectRoot(process.cwd());
|
|
15531
15756
|
if (!root)
|
|
@@ -15766,7 +15991,7 @@ function createSyncServer() {
|
|
|
15766
15991
|
server.tool(
|
|
15767
15992
|
"iamu_requests_claim",
|
|
15768
15993
|
"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.",
|
|
15769
|
-
{ id:
|
|
15994
|
+
{ id: z25.string().uuid().describe("Request id from iamu_requests") },
|
|
15770
15995
|
async ({ id }) => {
|
|
15771
15996
|
try {
|
|
15772
15997
|
const linked = await resolveLinkedCloudClient();
|
|
@@ -16426,11 +16651,14 @@ var init_serve = __esm({
|
|
|
16426
16651
|
// src/commands/init.ts
|
|
16427
16652
|
var init_exports = {};
|
|
16428
16653
|
__export(init_exports, {
|
|
16654
|
+
createDraftTestabilityContent: () => createDraftTestabilityContent,
|
|
16655
|
+
detectTargetPort: () => detectTargetPort,
|
|
16656
|
+
detectTargetUrl: () => detectTargetUrl,
|
|
16429
16657
|
init: () => init,
|
|
16430
16658
|
setupCommand: () => setupCommand
|
|
16431
16659
|
});
|
|
16432
16660
|
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
|
|
16433
|
-
import { mkdir as mkdir4, writeFile as writeFile3 } from "fs/promises";
|
|
16661
|
+
import { mkdir as mkdir4, readdir, writeFile as writeFile3 } from "fs/promises";
|
|
16434
16662
|
import { basename as basename2, join as join5 } from "path";
|
|
16435
16663
|
import { isCancel as isCancel3, multiselect, select as select3 } from "@clack/prompts";
|
|
16436
16664
|
import chalk18 from "chalk";
|
|
@@ -16458,6 +16686,81 @@ function setupCommand(projectRoot, hosts) {
|
|
|
16458
16686
|
if (hosts.every((h) => h.value === "claude")) return "/iamu:init";
|
|
16459
16687
|
return "/iamu-setup (Claude Code: /iamu:init)";
|
|
16460
16688
|
}
|
|
16689
|
+
function detectTargetPort(projectRoot) {
|
|
16690
|
+
if (process.env.PORT) {
|
|
16691
|
+
const p = Number.parseInt(process.env.PORT, 10);
|
|
16692
|
+
if (!Number.isNaN(p) && p > 0 && p <= 65535) return p;
|
|
16693
|
+
}
|
|
16694
|
+
for (const envFile of [".env.local", ".env.development", ".env"]) {
|
|
16695
|
+
const fullPath = join5(projectRoot, envFile);
|
|
16696
|
+
if (existsSync7(fullPath)) {
|
|
16697
|
+
try {
|
|
16698
|
+
const content = readFileSync5(fullPath, "utf-8");
|
|
16699
|
+
for (const line of content.split("\n")) {
|
|
16700
|
+
const trimmed = line.trim();
|
|
16701
|
+
if (trimmed.startsWith("#") || !trimmed.includes("=")) continue;
|
|
16702
|
+
const [key, ...rest] = trimmed.split("=");
|
|
16703
|
+
const k = key.trim();
|
|
16704
|
+
const val = rest.join("=").trim().replace(/^["']|["']$/g, "");
|
|
16705
|
+
if (k === "PORT" || k === "VITE_PORT") {
|
|
16706
|
+
const p = Number.parseInt(val, 10);
|
|
16707
|
+
if (!Number.isNaN(p) && p > 0 && p <= 65535) return p;
|
|
16708
|
+
}
|
|
16709
|
+
if (k === "NEXT_PUBLIC_APP_URL" || k === "APP_URL") {
|
|
16710
|
+
try {
|
|
16711
|
+
const url = new URL(val);
|
|
16712
|
+
if (url.port) return Number.parseInt(url.port, 10);
|
|
16713
|
+
} catch {
|
|
16714
|
+
}
|
|
16715
|
+
}
|
|
16716
|
+
}
|
|
16717
|
+
} catch {
|
|
16718
|
+
}
|
|
16719
|
+
}
|
|
16720
|
+
}
|
|
16721
|
+
const pkgPath = join5(projectRoot, "package.json");
|
|
16722
|
+
if (existsSync7(pkgPath)) {
|
|
16723
|
+
try {
|
|
16724
|
+
const pkg = JSON.parse(readFileSync5(pkgPath, "utf-8"));
|
|
16725
|
+
const scripts = pkg.scripts || {};
|
|
16726
|
+
for (const script of Object.values(scripts)) {
|
|
16727
|
+
if (typeof script !== "string") continue;
|
|
16728
|
+
const portMatch = script.match(/(?:-p|--port(?:=|\s+))(\d+)/);
|
|
16729
|
+
if (portMatch) {
|
|
16730
|
+
const p = Number.parseInt(portMatch[1], 10);
|
|
16731
|
+
if (!Number.isNaN(p) && p > 0 && p <= 65535) return p;
|
|
16732
|
+
}
|
|
16733
|
+
}
|
|
16734
|
+
const allDeps = {
|
|
16735
|
+
...pkg.dependencies || {},
|
|
16736
|
+
...pkg.devDependencies || {}
|
|
16737
|
+
};
|
|
16738
|
+
if ("astro" in allDeps) return 4321;
|
|
16739
|
+
if ("vite" in allDeps) return 5173;
|
|
16740
|
+
} catch {
|
|
16741
|
+
}
|
|
16742
|
+
}
|
|
16743
|
+
for (const f of ["astro.config.mjs", "astro.config.ts", "astro.config.js"]) {
|
|
16744
|
+
if (existsSync7(join5(projectRoot, f))) return 4321;
|
|
16745
|
+
}
|
|
16746
|
+
for (const f of [
|
|
16747
|
+
"vite.config.ts",
|
|
16748
|
+
"vite.config.js",
|
|
16749
|
+
"vite.config.mjs",
|
|
16750
|
+
"vite.config.cjs"
|
|
16751
|
+
]) {
|
|
16752
|
+
if (existsSync7(join5(projectRoot, f))) return 5173;
|
|
16753
|
+
}
|
|
16754
|
+
return void 0;
|
|
16755
|
+
}
|
|
16756
|
+
function detectTargetUrl(projectRoot) {
|
|
16757
|
+
const port = detectTargetPort(projectRoot);
|
|
16758
|
+
return port ? `http://localhost:${port}` : "http://localhost:3000";
|
|
16759
|
+
}
|
|
16760
|
+
function createDraftTestabilityContent(targetUrl = "http://localhost:3000") {
|
|
16761
|
+
const doc = emptyTestability(targetUrl);
|
|
16762
|
+
return serializeFrontmatter(doc.frontmatter, doc.body);
|
|
16763
|
+
}
|
|
16461
16764
|
async function init(opts) {
|
|
16462
16765
|
const options = typeof opts === "string" ? { name: opts } : opts ?? {};
|
|
16463
16766
|
const projectRoot = process.cwd();
|
|
@@ -16475,12 +16778,86 @@ async function init(opts) {
|
|
|
16475
16778
|
console.log();
|
|
16476
16779
|
}
|
|
16477
16780
|
let freshInit = false;
|
|
16781
|
+
const backfilled = [];
|
|
16478
16782
|
if (existsSync7(join5(iamuDir2, "config.json"))) {
|
|
16479
|
-
const
|
|
16480
|
-
if (!
|
|
16481
|
-
|
|
16482
|
-
|
|
16783
|
+
const testabilityPath2 = join5(iamuDir2, "testability.md");
|
|
16784
|
+
if (!existsSync7(testabilityPath2)) {
|
|
16785
|
+
const targetUrl = detectTargetUrl(projectRoot);
|
|
16786
|
+
await writeFile3(
|
|
16787
|
+
testabilityPath2,
|
|
16788
|
+
createDraftTestabilityContent(targetUrl)
|
|
16483
16789
|
);
|
|
16790
|
+
backfilled.push("testability.md");
|
|
16791
|
+
}
|
|
16792
|
+
const contextPath2 = join5(iamuDir2, "context.yml");
|
|
16793
|
+
if (!existsSync7(contextPath2)) {
|
|
16794
|
+
await writeFile3(
|
|
16795
|
+
contextPath2,
|
|
16796
|
+
serializeFrontmatter(
|
|
16797
|
+
{ status: "draft", schema_version: 1, name: projectName },
|
|
16798
|
+
""
|
|
16799
|
+
)
|
|
16800
|
+
);
|
|
16801
|
+
backfilled.push("context.yml");
|
|
16802
|
+
}
|
|
16803
|
+
const gitignorePath = join5(iamuDir2, ".gitignore");
|
|
16804
|
+
if (!existsSync7(gitignorePath)) {
|
|
16805
|
+
await writeFile3(gitignorePath, GITIGNORE_CONTENT);
|
|
16806
|
+
backfilled.push(".gitignore");
|
|
16807
|
+
}
|
|
16808
|
+
const cacheDirPath = join5(iamuDir2, ".cache");
|
|
16809
|
+
if (!existsSync7(cacheDirPath)) {
|
|
16810
|
+
await mkdir4(cacheDirPath, { recursive: true });
|
|
16811
|
+
backfilled.push(".cache/");
|
|
16812
|
+
}
|
|
16813
|
+
const runsDirPath = join5(iamuDir2, ".runs");
|
|
16814
|
+
if (!existsSync7(runsDirPath)) {
|
|
16815
|
+
await mkdir4(runsDirPath, { recursive: true });
|
|
16816
|
+
}
|
|
16817
|
+
for (const type2 of ENTITY_TYPES) {
|
|
16818
|
+
const sub = join5(iamuDir2, ENTITY_DIRS[type2]);
|
|
16819
|
+
if (!existsSync7(sub)) {
|
|
16820
|
+
await mkdir4(sub, { recursive: true });
|
|
16821
|
+
}
|
|
16822
|
+
const keep = join5(sub, ".gitkeep");
|
|
16823
|
+
if (!existsSync7(keep)) {
|
|
16824
|
+
try {
|
|
16825
|
+
const files = await readdir(sub);
|
|
16826
|
+
if (files.length === 0) {
|
|
16827
|
+
await writeFile3(keep, "");
|
|
16828
|
+
}
|
|
16829
|
+
} catch {
|
|
16830
|
+
await writeFile3(keep, "");
|
|
16831
|
+
}
|
|
16832
|
+
}
|
|
16833
|
+
}
|
|
16834
|
+
const promptTemplates2 = loadPromptTemplates();
|
|
16835
|
+
const promptsDir2 = join5(iamuDir2, ".prompts");
|
|
16836
|
+
const missingPrompts = [];
|
|
16837
|
+
if (!existsSync7(promptsDir2)) {
|
|
16838
|
+
missingPrompts.push(".prompts/");
|
|
16839
|
+
} else {
|
|
16840
|
+
for (const [name] of promptTemplates2) {
|
|
16841
|
+
if (!existsSync7(join5(promptsDir2, name))) {
|
|
16842
|
+
missingPrompts.push(name);
|
|
16843
|
+
}
|
|
16844
|
+
}
|
|
16845
|
+
}
|
|
16846
|
+
if (missingPrompts.length > 0) {
|
|
16847
|
+
if (missingPrompts.includes(".prompts/")) {
|
|
16848
|
+
backfilled.push(".prompts/");
|
|
16849
|
+
} else {
|
|
16850
|
+
backfilled.push(...missingPrompts.map((p) => `.prompts/${p}`));
|
|
16851
|
+
}
|
|
16852
|
+
}
|
|
16853
|
+
if (!options.json) {
|
|
16854
|
+
if (backfilled.length > 0) {
|
|
16855
|
+
console.log(
|
|
16856
|
+
` ${symbols.success} Scaffolding verified (backfilled missing ${backfilled.join(", ")})`
|
|
16857
|
+
);
|
|
16858
|
+
} else {
|
|
16859
|
+
console.log(` ${symbols.success} Scaffolding up to date`);
|
|
16860
|
+
}
|
|
16484
16861
|
}
|
|
16485
16862
|
} else {
|
|
16486
16863
|
freshInit = true;
|
|
@@ -16496,33 +16873,12 @@ async function init(opts) {
|
|
|
16496
16873
|
""
|
|
16497
16874
|
)
|
|
16498
16875
|
);
|
|
16499
|
-
const
|
|
16500
|
-
if (!existsSync7(
|
|
16876
|
+
const testabilityPath2 = join5(iamuDir2, "testability.md");
|
|
16877
|
+
if (!existsSync7(testabilityPath2)) {
|
|
16878
|
+
const targetUrl = detectTargetUrl(projectRoot);
|
|
16501
16879
|
await writeFile3(
|
|
16502
|
-
|
|
16503
|
-
|
|
16504
|
-
{
|
|
16505
|
-
status: "draft",
|
|
16506
|
-
target_url: "http://localhost:3000"
|
|
16507
|
-
},
|
|
16508
|
-
`# Project Testability & Environment
|
|
16509
|
-
|
|
16510
|
-
Target URL and execution harness for walkthroughs.
|
|
16511
|
-
Audited and populated during /iamu:init.
|
|
16512
|
-
|
|
16513
|
-
## Target & Run Instructions
|
|
16514
|
-
- Default URL: http://localhost:3000
|
|
16515
|
-
|
|
16516
|
-
## Reachable Surfaces
|
|
16517
|
-
(Run /iamu:init to discover testable routes)
|
|
16518
|
-
|
|
16519
|
-
## Mocks & Data Fixtures
|
|
16520
|
-
(Run /iamu:init to inspect existing harnesses)
|
|
16521
|
-
|
|
16522
|
-
## Untestable Boundaries
|
|
16523
|
-
(None documented yet)
|
|
16524
|
-
`
|
|
16525
|
-
)
|
|
16880
|
+
testabilityPath2,
|
|
16881
|
+
createDraftTestabilityContent(targetUrl)
|
|
16526
16882
|
);
|
|
16527
16883
|
}
|
|
16528
16884
|
}
|
|
@@ -16532,7 +16888,13 @@ Audited and populated during /iamu:init.
|
|
|
16532
16888
|
for (const [name, content] of promptTemplates) {
|
|
16533
16889
|
await writeFile3(join5(promptsDir, name), content);
|
|
16534
16890
|
}
|
|
16535
|
-
const
|
|
16891
|
+
const detectedInstalled = detectInstalledHosts(projectRoot);
|
|
16892
|
+
const detectedWorkspace = detectHosts(projectRoot);
|
|
16893
|
+
const detectedMap = /* @__PURE__ */ new Map();
|
|
16894
|
+
for (const h of [...detectedInstalled, ...detectedWorkspace]) {
|
|
16895
|
+
detectedMap.set(h.value, h);
|
|
16896
|
+
}
|
|
16897
|
+
const detected = Array.from(detectedMap.values());
|
|
16536
16898
|
if (!options.json && detected.length > 0) {
|
|
16537
16899
|
console.log(
|
|
16538
16900
|
chalk18.dim(" Detected: ") + detected.map((h) => h.name).join(", ") + chalk18.dim(" (pre-selected)")
|
|
@@ -16641,6 +17003,7 @@ Audited and populated during /iamu:init.
|
|
|
16641
17003
|
projectName,
|
|
16642
17004
|
projectRoot,
|
|
16643
17005
|
fresh: freshInit,
|
|
17006
|
+
backfilled,
|
|
16644
17007
|
tools: selectedHosts.map((h) => h.name),
|
|
16645
17008
|
skillsCount: totalSkills,
|
|
16646
17009
|
commandsCount: totalCommands,
|
|
@@ -16742,6 +17105,7 @@ var init_init = __esm({
|
|
|
16742
17105
|
"src/commands/init.ts"() {
|
|
16743
17106
|
"use strict";
|
|
16744
17107
|
init_dist2();
|
|
17108
|
+
init_dist();
|
|
16745
17109
|
init_claude_plugin();
|
|
16746
17110
|
init_registry();
|
|
16747
17111
|
init_cloud_url();
|
|
@@ -16809,6 +17173,25 @@ async function status(opts) {
|
|
|
16809
17173
|
const incompleteRuns = await listIncompleteRuns(projectRoot);
|
|
16810
17174
|
const { rerun } = await computeFixStates(projectRoot);
|
|
16811
17175
|
const staleSkills = await findStaleSkills(projectRoot);
|
|
17176
|
+
let exploreSummary = null;
|
|
17177
|
+
try {
|
|
17178
|
+
const maps = await listExploreMaps(projectRoot);
|
|
17179
|
+
if (maps.length > 0) {
|
|
17180
|
+
const latestMapId = maps.at(-1);
|
|
17181
|
+
const map2 = await readExploreMap(projectRoot, latestMapId);
|
|
17182
|
+
if (map2) {
|
|
17183
|
+
const steps = await readAllRunSteps(projectRoot);
|
|
17184
|
+
const cov = exploreCoverage(map2, steps);
|
|
17185
|
+
exploreSummary = {
|
|
17186
|
+
map_id: latestMapId,
|
|
17187
|
+
total_surfaces: cov.surfaces.length,
|
|
17188
|
+
reached_surfaces: cov.reached,
|
|
17189
|
+
unreached_surfaces: cov.unreached
|
|
17190
|
+
};
|
|
17191
|
+
}
|
|
17192
|
+
}
|
|
17193
|
+
} catch {
|
|
17194
|
+
}
|
|
16812
17195
|
if (opts.json) {
|
|
16813
17196
|
console.log(
|
|
16814
17197
|
JSON.stringify(
|
|
@@ -16832,6 +17215,7 @@ async function status(opts) {
|
|
|
16832
17215
|
last: runs.at(-1) ?? null,
|
|
16833
17216
|
incomplete: incompleteRuns
|
|
16834
17217
|
},
|
|
17218
|
+
explore: exploreSummary,
|
|
16835
17219
|
rerun: rerun.map((r) => ({
|
|
16836
17220
|
...r,
|
|
16837
17221
|
command: rerunCommand(projectRoot, r.scenario)
|
|
@@ -16919,6 +17303,11 @@ async function status(opts) {
|
|
|
16919
17303
|
)
|
|
16920
17304
|
);
|
|
16921
17305
|
}
|
|
17306
|
+
if (exploreSummary) {
|
|
17307
|
+
console.log(
|
|
17308
|
+
` ${padRight("product map", 14)} ${chalk19.cyan(String(exploreSummary.total_surfaces))} surfaces (${chalk19.green(`${exploreSummary.reached_surfaces} reached`)} \xB7 ${chalk19.yellow(`${exploreSummary.unreached_surfaces} unreached`)})`
|
|
17309
|
+
);
|
|
17310
|
+
}
|
|
16922
17311
|
if (projectStatus.requests && projectStatus.requests.open > 0) {
|
|
16923
17312
|
console.log(
|
|
16924
17313
|
chalk19.cyan(
|
|
@@ -17221,7 +17610,7 @@ var init_browse_driver = __esm({
|
|
|
17221
17610
|
});
|
|
17222
17611
|
|
|
17223
17612
|
// src/commands/step-numbering.ts
|
|
17224
|
-
import { open, readdir, unlink } from "fs/promises";
|
|
17613
|
+
import { open, readdir as readdir2, unlink } from "fs/promises";
|
|
17225
17614
|
import path22 from "path";
|
|
17226
17615
|
function stepFileName(stepNumber2) {
|
|
17227
17616
|
return `${String(stepNumber2).padStart(3, "0")}.json`;
|
|
@@ -17230,7 +17619,7 @@ function stepLimitMessage(maxSteps, runId) {
|
|
|
17230
17619
|
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>.`;
|
|
17231
17620
|
}
|
|
17232
17621
|
async function peekNextStepNumber(stepsDir) {
|
|
17233
|
-
const files = await
|
|
17622
|
+
const files = await readdir2(stepsDir).catch(() => []);
|
|
17234
17623
|
let max = 0;
|
|
17235
17624
|
for (const f of files) {
|
|
17236
17625
|
const m = /^(\d+)\.json$/.exec(f);
|
|
@@ -18299,7 +18688,7 @@ async function checkTargetHealth(targetUrl) {
|
|
|
18299
18688
|
const res = await fetch(targetUrl, {
|
|
18300
18689
|
method: "GET",
|
|
18301
18690
|
redirect: "manual",
|
|
18302
|
-
signal: AbortSignal.timeout(
|
|
18691
|
+
signal: AbortSignal.timeout(1e3)
|
|
18303
18692
|
});
|
|
18304
18693
|
if ([301, 302, 303, 307, 308].includes(res.status)) {
|
|
18305
18694
|
const location = res.headers.get("location") || "";
|
|
@@ -18413,21 +18802,20 @@ async function checkProjectHarnesses(projectRoot) {
|
|
|
18413
18802
|
}
|
|
18414
18803
|
async function checkProjectTestabilityContract(projectRoot) {
|
|
18415
18804
|
const checks = [];
|
|
18416
|
-
const testabilityPath = join7(projectRoot, "iamu", "testability.md");
|
|
18417
|
-
if (!existsSync10(testabilityPath)) {
|
|
18418
|
-
checks.push({
|
|
18419
|
-
category: "target",
|
|
18420
|
-
name: "Testability Contract (testability.md)",
|
|
18421
|
-
status: "warn",
|
|
18422
|
-
message: "iamu/testability.md not found",
|
|
18423
|
-
remedy: "Run `/iamu:init` to audit your codebase and record testable routes, auth strategies, and mock harnesses."
|
|
18424
|
-
});
|
|
18425
|
-
return { checks };
|
|
18426
|
-
}
|
|
18427
18805
|
try {
|
|
18428
|
-
const
|
|
18429
|
-
|
|
18430
|
-
|
|
18806
|
+
const doc = await readTestability(projectRoot);
|
|
18807
|
+
if (!doc) {
|
|
18808
|
+
checks.push({
|
|
18809
|
+
category: "target",
|
|
18810
|
+
name: "Testability Contract (testability.md)",
|
|
18811
|
+
status: "warn",
|
|
18812
|
+
message: "iamu/testability.md not found",
|
|
18813
|
+
remedy: "Run `/iamu:init` to audit your codebase and record testable routes, auth strategies, and mock harnesses."
|
|
18814
|
+
});
|
|
18815
|
+
return { checks };
|
|
18816
|
+
}
|
|
18817
|
+
const { frontmatter } = doc;
|
|
18818
|
+
const targetUrl = frontmatter.target_url;
|
|
18431
18819
|
const details = [];
|
|
18432
18820
|
if (targetUrl) details.push(`Target: ${targetUrl}`);
|
|
18433
18821
|
if (frontmatter.dev_command) {
|
|
@@ -19424,6 +19812,19 @@ async function update(opts) {
|
|
|
19424
19812
|
console.log(` ${symbols.success} ${promptsUpdated} prompts updated`);
|
|
19425
19813
|
}
|
|
19426
19814
|
}
|
|
19815
|
+
if (existsSync11(iamuDir2)) {
|
|
19816
|
+
const testabilityPath2 = join8(iamuDir2, "testability.md");
|
|
19817
|
+
if (!existsSync11(testabilityPath2)) {
|
|
19818
|
+
const targetUrl = detectTargetUrl(projectRoot);
|
|
19819
|
+
await writeFile4(
|
|
19820
|
+
testabilityPath2,
|
|
19821
|
+
createDraftTestabilityContent(targetUrl)
|
|
19822
|
+
);
|
|
19823
|
+
console.log(
|
|
19824
|
+
` ${symbols.success} Repaired testability contract: created iamu/testability.md (draft)`
|
|
19825
|
+
);
|
|
19826
|
+
}
|
|
19827
|
+
}
|
|
19427
19828
|
const { hosts: targetHosts, error } = resolveTargetHosts(
|
|
19428
19829
|
projectRoot,
|
|
19429
19830
|
opts?.host
|
|
@@ -19479,6 +19880,7 @@ var init_update = __esm({
|
|
|
19479
19880
|
init_mcp_config();
|
|
19480
19881
|
init_context4();
|
|
19481
19882
|
init_skills();
|
|
19883
|
+
init_init();
|
|
19482
19884
|
init_templates();
|
|
19483
19885
|
}
|
|
19484
19886
|
});
|
|
@@ -19504,11 +19906,13 @@ function defaultFrontmatter(type2, id, slug, name, opts) {
|
|
|
19504
19906
|
};
|
|
19505
19907
|
case "outline": {
|
|
19506
19908
|
const tests = Array.isArray(opts.humanTest) ? opts.humanTest : opts.humanTest ? [opts.humanTest] : [];
|
|
19909
|
+
const additionalCaps = Array.isArray(opts.additionalCapabilities) ? opts.additionalCapabilities : typeof opts.additionalCapabilities === "string" ? opts.additionalCapabilities.split(",").map((s) => s.trim()).filter(Boolean) : [];
|
|
19507
19910
|
return {
|
|
19508
19911
|
...base,
|
|
19509
19912
|
title: name,
|
|
19510
19913
|
...description,
|
|
19511
19914
|
...opts.capability ? { primary_capability: opts.capability } : {},
|
|
19915
|
+
...additionalCaps.length > 0 ? { additional_capabilities: additionalCaps } : {},
|
|
19512
19916
|
...opts.tension ? { tension: opts.tension } : {},
|
|
19513
19917
|
...opts.narrative ? { narrative: opts.narrative } : {},
|
|
19514
19918
|
...tests.length > 0 ? {
|
|
@@ -19519,8 +19923,16 @@ function defaultFrontmatter(type2, id, slug, name, opts) {
|
|
|
19519
19923
|
} : {}
|
|
19520
19924
|
};
|
|
19521
19925
|
}
|
|
19522
|
-
case "capability":
|
|
19523
|
-
|
|
19926
|
+
case "capability": {
|
|
19927
|
+
const capPaths = Array.isArray(opts.paths) ? opts.paths : typeof opts.paths === "string" ? opts.paths.split(",").map((s) => s.trim()).filter(Boolean) : [];
|
|
19928
|
+
return {
|
|
19929
|
+
...base,
|
|
19930
|
+
title: name,
|
|
19931
|
+
...description,
|
|
19932
|
+
...capPaths.length > 0 ? { paths: capPaths } : {},
|
|
19933
|
+
...opts.area ? { area: opts.area.trim() } : {}
|
|
19934
|
+
};
|
|
19935
|
+
}
|
|
19524
19936
|
case "source":
|
|
19525
19937
|
return {
|
|
19526
19938
|
...base,
|
|
@@ -20115,7 +20527,6 @@ __export(explore_exports, {
|
|
|
20115
20527
|
exploreList: () => exploreList,
|
|
20116
20528
|
exploreRun: () => exploreRun
|
|
20117
20529
|
});
|
|
20118
|
-
import { promises as fs28 } from "fs";
|
|
20119
20530
|
import path26 from "path";
|
|
20120
20531
|
import chalk27 from "chalk";
|
|
20121
20532
|
function fail2(message, json2) {
|
|
@@ -20133,12 +20544,8 @@ function positiveInt(raw, fallback, flag) {
|
|
|
20133
20544
|
}
|
|
20134
20545
|
async function testabilityTarget2(projectRoot) {
|
|
20135
20546
|
try {
|
|
20136
|
-
const
|
|
20137
|
-
|
|
20138
|
-
"utf8"
|
|
20139
|
-
);
|
|
20140
|
-
const { frontmatter } = parseFrontmatter(raw);
|
|
20141
|
-
return typeof frontmatter.target_url === "string" ? frontmatter.target_url : null;
|
|
20547
|
+
const doc = await readTestability(projectRoot);
|
|
20548
|
+
return doc?.frontmatter.target_url ?? null;
|
|
20142
20549
|
} catch {
|
|
20143
20550
|
return null;
|
|
20144
20551
|
}
|
|
@@ -20320,8 +20727,17 @@ async function exploreCoverageCommand(mapId, opts) {
|
|
|
20320
20727
|
return;
|
|
20321
20728
|
}
|
|
20322
20729
|
const cov = exploreCoverage(map2, await readAllRunSteps(ctx.projectRoot));
|
|
20730
|
+
const capReport = await readCapabilityCoverage(ctx.projectRoot, cov);
|
|
20323
20731
|
if (opts.json) {
|
|
20324
|
-
console.log(
|
|
20732
|
+
console.log(
|
|
20733
|
+
JSON.stringify({
|
|
20734
|
+
...cov,
|
|
20735
|
+
...capReport.capabilities.length > 0 ? {
|
|
20736
|
+
capabilities: capReport.capabilities,
|
|
20737
|
+
unassigned_surfaces: capReport.unassigned_surfaces
|
|
20738
|
+
} : {}
|
|
20739
|
+
})
|
|
20740
|
+
);
|
|
20325
20741
|
return;
|
|
20326
20742
|
}
|
|
20327
20743
|
console.log(
|
|
@@ -20331,26 +20747,122 @@ async function exploreCoverageCommand(mapId, opts) {
|
|
|
20331
20747
|
console.log(
|
|
20332
20748
|
` ${chalk27.green(`${cov.reached} reached`)} \xB7 ${chalk27.yellow(`${cov.place_only} URL reached, view unclear`)} \xB7 ${chalk27.red(`${cov.unreached} never reached`)}`
|
|
20333
20749
|
);
|
|
20334
|
-
|
|
20335
|
-
|
|
20336
|
-
console.log(
|
|
20337
|
-
|
|
20338
|
-
|
|
20750
|
+
if (capReport.capabilities.length > 0) {
|
|
20751
|
+
console.log(chalk27.bold("\n CAPABILITY COVERAGE"));
|
|
20752
|
+
console.log(
|
|
20753
|
+
chalk27.dim(
|
|
20754
|
+
" \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"
|
|
20755
|
+
)
|
|
20756
|
+
);
|
|
20757
|
+
console.log(
|
|
20758
|
+
chalk27.dim(
|
|
20759
|
+
` ${"Capability".padEnd(24)} ${"Surfaces".padStart(8)} ${"Coverage".padStart(8)} ${"Scenarios (1\xB0 / 2\xB0)"}`
|
|
20760
|
+
)
|
|
20761
|
+
);
|
|
20762
|
+
console.log(
|
|
20763
|
+
chalk27.dim(
|
|
20764
|
+
" \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"
|
|
20765
|
+
)
|
|
20766
|
+
);
|
|
20767
|
+
for (const cap of capReport.capabilities) {
|
|
20768
|
+
const title = cap.slug.padEnd(24);
|
|
20769
|
+
const surfaces = `${cap.reached_surfaces}/${cap.total_surfaces}`.padStart(
|
|
20770
|
+
8
|
|
20771
|
+
);
|
|
20772
|
+
const covStr = `${cap.coverage_pct}%`.padStart(8);
|
|
20773
|
+
const scenarios = `${cap.primary_scenarios} / ${cap.secondary_scenarios}`;
|
|
20774
|
+
const untestedFlag = cap.primary_scenarios === 0 && cap.unreached_surfaces > 0 ? chalk27.yellow(" (untested)") : "";
|
|
20775
|
+
const covColored = cap.coverage_pct === 100 ? chalk27.green(covStr) : cap.coverage_pct === 0 ? chalk27.red(covStr) : chalk27.yellow(covStr);
|
|
20339
20776
|
console.log(
|
|
20340
|
-
`
|
|
20777
|
+
` ${title} ${surfaces} ${covColored} ${scenarios}${untestedFlag}`
|
|
20341
20778
|
);
|
|
20342
20779
|
}
|
|
20343
|
-
|
|
20344
|
-
|
|
20345
|
-
|
|
20346
|
-
|
|
20347
|
-
|
|
20348
|
-
|
|
20349
|
-
|
|
20350
|
-
|
|
20351
|
-
|
|
20352
|
-
|
|
20353
|
-
|
|
20780
|
+
if (capReport.unassigned_surfaces.length > 0) {
|
|
20781
|
+
const unassigned = capReport.unassigned_surfaces;
|
|
20782
|
+
const reached = unassigned.filter((s) => s.status === "reached").length;
|
|
20783
|
+
const pct = Math.round(reached / unassigned.length * 100);
|
|
20784
|
+
console.log(
|
|
20785
|
+
chalk27.dim(
|
|
20786
|
+
` ${"(Unassigned)".padEnd(24)} ${`${reached}/${unassigned.length}`.padStart(8)} ${`${pct}%`.padStart(8)} -`
|
|
20787
|
+
)
|
|
20788
|
+
);
|
|
20789
|
+
}
|
|
20790
|
+
console.log(
|
|
20791
|
+
chalk27.dim(
|
|
20792
|
+
" \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"
|
|
20793
|
+
)
|
|
20794
|
+
);
|
|
20795
|
+
const hasGaps = capReport.capabilities.some((c) => c.unreached_surfaces > 0) || capReport.unassigned_surfaces.some((s) => s.status !== "reached");
|
|
20796
|
+
if (hasGaps) {
|
|
20797
|
+
console.log(chalk27.red("\n UNREACHED SURFACES (Gaps)"));
|
|
20798
|
+
for (const cap of capReport.capabilities) {
|
|
20799
|
+
const gaps = cap.surfaces.filter((s) => s.status !== "reached");
|
|
20800
|
+
if (gaps.length === 0) continue;
|
|
20801
|
+
console.log(` ${chalk27.bold(cap.slug)}:`);
|
|
20802
|
+
for (const s of gaps) {
|
|
20803
|
+
console.log(
|
|
20804
|
+
` ${chalk27.red("\u25CB")} ${s.key.padEnd(32)} ${s.label}${chalk27.dim(` (depth ${s.depth})`)}`
|
|
20805
|
+
);
|
|
20806
|
+
}
|
|
20807
|
+
}
|
|
20808
|
+
const unassignedGaps = capReport.unassigned_surfaces.filter(
|
|
20809
|
+
(s) => s.status !== "reached"
|
|
20810
|
+
);
|
|
20811
|
+
if (unassignedGaps.length > 0) {
|
|
20812
|
+
console.log(chalk27.dim(" (Unassigned):"));
|
|
20813
|
+
for (const s of unassignedGaps) {
|
|
20814
|
+
console.log(
|
|
20815
|
+
` ${chalk27.dim("\u25CB")} ${s.key.padEnd(32)} ${s.label}${chalk27.dim(` (depth ${s.depth})`)}`
|
|
20816
|
+
);
|
|
20817
|
+
}
|
|
20818
|
+
}
|
|
20819
|
+
}
|
|
20820
|
+
if (opts.all) {
|
|
20821
|
+
console.log(chalk27.green("\n REACHED SURFACES"));
|
|
20822
|
+
for (const cap of capReport.capabilities) {
|
|
20823
|
+
const reached = cap.surfaces.filter((s) => s.status === "reached");
|
|
20824
|
+
if (reached.length === 0) continue;
|
|
20825
|
+
console.log(` ${chalk27.bold(cap.slug)}:`);
|
|
20826
|
+
for (const s of reached) {
|
|
20827
|
+
console.log(
|
|
20828
|
+
` ${chalk27.green("\u2713")} ${s.key.padEnd(32)} ${s.label}${chalk27.dim(` (depth ${s.depth})`)}`
|
|
20829
|
+
);
|
|
20830
|
+
}
|
|
20831
|
+
}
|
|
20832
|
+
const unassignedReached = capReport.unassigned_surfaces.filter(
|
|
20833
|
+
(s) => s.status === "reached"
|
|
20834
|
+
);
|
|
20835
|
+
if (unassignedReached.length > 0) {
|
|
20836
|
+
console.log(chalk27.dim(" (Unassigned):"));
|
|
20837
|
+
for (const s of unassignedReached) {
|
|
20838
|
+
console.log(
|
|
20839
|
+
` ${chalk27.green("\u2713")} ${s.key.padEnd(32)} ${s.label}${chalk27.dim(` (depth ${s.depth})`)}`
|
|
20840
|
+
);
|
|
20841
|
+
}
|
|
20842
|
+
}
|
|
20843
|
+
}
|
|
20844
|
+
} else {
|
|
20845
|
+
const section = (title, rows, color) => {
|
|
20846
|
+
if (rows.length === 0) return;
|
|
20847
|
+
console.log(`
|
|
20848
|
+
${color(title)}`);
|
|
20849
|
+
for (const r of rows) {
|
|
20850
|
+
console.log(
|
|
20851
|
+
` ${r.key.padEnd(32)} ${r.label}${chalk27.dim(` (depth ${r.depth})`)}`
|
|
20852
|
+
);
|
|
20853
|
+
}
|
|
20854
|
+
};
|
|
20855
|
+
section(
|
|
20856
|
+
"Never reached by a run",
|
|
20857
|
+
cov.surfaces.filter((s) => s.status === "unreached"),
|
|
20858
|
+
chalk27.red
|
|
20859
|
+
);
|
|
20860
|
+
section(
|
|
20861
|
+
"URL reached, but no step names this view",
|
|
20862
|
+
cov.surfaces.filter((s) => s.status === "place_only"),
|
|
20863
|
+
chalk27.yellow
|
|
20864
|
+
);
|
|
20865
|
+
}
|
|
20354
20866
|
if (cov.run_only_places.length > 0) {
|
|
20355
20867
|
console.log(`
|
|
20356
20868
|
${chalk27.cyan("Walked by runs, not in the map")}`);
|
|
@@ -20910,17 +21422,13 @@ async function instructionsWalk(opts) {
|
|
|
20910
21422
|
}
|
|
20911
21423
|
const untestableBoundaries = [];
|
|
20912
21424
|
try {
|
|
20913
|
-
const
|
|
20914
|
-
if (
|
|
20915
|
-
|
|
20916
|
-
|
|
20917
|
-
if (!targetUrl && typeof frontmatter.target_url === "string" && frontmatter.target_url.trim().length > 0) {
|
|
20918
|
-
targetUrl = frontmatter.target_url.trim();
|
|
21425
|
+
const doc = await readTestability(projectRoot);
|
|
21426
|
+
if (doc) {
|
|
21427
|
+
if (!targetUrl && doc.frontmatter.target_url) {
|
|
21428
|
+
targetUrl = doc.frontmatter.target_url;
|
|
20919
21429
|
}
|
|
20920
|
-
const fromFm =
|
|
20921
|
-
|
|
20922
|
-
) ? frontmatter.untestable_boundaries.filter(Boolean) : [];
|
|
20923
|
-
const fromBody = extractUntestableBoundaries(body);
|
|
21430
|
+
const fromFm = doc.frontmatter.untestable_boundaries ?? [];
|
|
21431
|
+
const fromBody = extractUntestableBoundaries(doc.body);
|
|
20924
21432
|
untestableBoundaries.push(
|
|
20925
21433
|
...Array.from(/* @__PURE__ */ new Set([...fromFm, ...fromBody]))
|
|
20926
21434
|
);
|
|
@@ -21277,7 +21785,7 @@ var summary_exports = {};
|
|
|
21277
21785
|
__export(summary_exports, {
|
|
21278
21786
|
summaryCommand: () => summaryCommand
|
|
21279
21787
|
});
|
|
21280
|
-
import { promises as
|
|
21788
|
+
import { promises as fs28 } from "fs";
|
|
21281
21789
|
import path28 from "path";
|
|
21282
21790
|
import chalk30 from "chalk";
|
|
21283
21791
|
async function summaryCommand(runIdArg, opts) {
|
|
@@ -21304,7 +21812,7 @@ async function summaryCommand(runIdArg, opts) {
|
|
|
21304
21812
|
}
|
|
21305
21813
|
raw = Buffer.concat(chunks).toString("utf8");
|
|
21306
21814
|
} else {
|
|
21307
|
-
raw = await
|
|
21815
|
+
raw = await fs28.readFile(path28.resolve(projectRoot, opts.file), "utf8");
|
|
21308
21816
|
}
|
|
21309
21817
|
const parsed = JSON.parse(raw);
|
|
21310
21818
|
if (Array.isArray(parsed.what_worked)) {
|
|
@@ -21472,10 +21980,10 @@ __export(evaluate_exports, {
|
|
|
21472
21980
|
evaluate: () => evaluate,
|
|
21473
21981
|
evaluateRecord: () => evaluateRecord
|
|
21474
21982
|
});
|
|
21475
|
-
import { promises as
|
|
21983
|
+
import { promises as fs29 } from "fs";
|
|
21476
21984
|
import path29 from "path";
|
|
21477
21985
|
import chalk32 from "chalk";
|
|
21478
|
-
import { z as
|
|
21986
|
+
import { z as z26 } from "zod";
|
|
21479
21987
|
function formatIssues(error) {
|
|
21480
21988
|
return error.issues.map(
|
|
21481
21989
|
(i) => `${i.path.length > 0 ? i.path.join(".") : "(root)"}: ${i.message}`
|
|
@@ -21507,7 +22015,7 @@ async function evaluate(runId, opts) {
|
|
|
21507
22015
|
const canonicalPath = path29.join(runDirPath, "canonical.json");
|
|
21508
22016
|
let canonical;
|
|
21509
22017
|
try {
|
|
21510
|
-
const raw = await
|
|
22018
|
+
const raw = await fs29.readFile(canonicalPath, "utf8");
|
|
21511
22019
|
canonical = JSON.parse(raw);
|
|
21512
22020
|
} catch {
|
|
21513
22021
|
commandError(
|
|
@@ -21564,7 +22072,7 @@ async function evaluate(runId, opts) {
|
|
|
21564
22072
|
};
|
|
21565
22073
|
const prompt = composeJudgePrompt(input);
|
|
21566
22074
|
const promptFilePath = opts?.promptFile ?? path29.join(runDirPath, "judge_prompt.md");
|
|
21567
|
-
await
|
|
22075
|
+
await fs29.writeFile(promptFilePath, prompt, "utf8");
|
|
21568
22076
|
if (opts?.json) {
|
|
21569
22077
|
console.log(
|
|
21570
22078
|
JSON.stringify(
|
|
@@ -21591,7 +22099,7 @@ async function evaluateRecord(runId, opts) {
|
|
|
21591
22099
|
const canonicalPath = path29.join(runDirPath, "canonical.json");
|
|
21592
22100
|
let canonical;
|
|
21593
22101
|
try {
|
|
21594
|
-
const raw = await
|
|
22102
|
+
const raw = await fs29.readFile(canonicalPath, "utf8");
|
|
21595
22103
|
canonical = JSON.parse(raw);
|
|
21596
22104
|
} catch {
|
|
21597
22105
|
commandError(`No canonical.json for run: ${runId}`, opts);
|
|
@@ -21613,7 +22121,7 @@ async function evaluateRecord(runId, opts) {
|
|
|
21613
22121
|
}
|
|
21614
22122
|
raw = Buffer.concat(chunks).toString("utf8");
|
|
21615
22123
|
} else {
|
|
21616
|
-
raw = await
|
|
22124
|
+
raw = await fs29.readFile(opts.file, "utf8");
|
|
21617
22125
|
}
|
|
21618
22126
|
parsedFile = JSON.parse(raw);
|
|
21619
22127
|
} catch (err) {
|
|
@@ -21736,28 +22244,28 @@ var init_evaluate = __esm({
|
|
|
21736
22244
|
init_context4();
|
|
21737
22245
|
init_live_run_client();
|
|
21738
22246
|
init_view_results();
|
|
21739
|
-
verdictValueSchema =
|
|
21740
|
-
idList =
|
|
21741
|
-
verdictEntrySchema =
|
|
21742
|
-
human_test_id:
|
|
21743
|
-
id:
|
|
22247
|
+
verdictValueSchema = z26.enum(["yes", "partial", "no", "not_applicable"]);
|
|
22248
|
+
idList = z26.array(z26.string()).optional();
|
|
22249
|
+
verdictEntrySchema = z26.object({
|
|
22250
|
+
human_test_id: z26.string().min(1).optional(),
|
|
22251
|
+
id: z26.string().min(1).optional(),
|
|
21744
22252
|
verdict: verdictValueSchema,
|
|
21745
|
-
reasoning:
|
|
22253
|
+
reasoning: z26.string(),
|
|
21746
22254
|
grounding_step_ids: idList,
|
|
21747
22255
|
grounding_finding_ids: idList
|
|
21748
22256
|
}).refine((v) => Boolean(v.human_test_id ?? v.id), {
|
|
21749
22257
|
message: "must carry human_test_id (or id)",
|
|
21750
22258
|
path: ["human_test_id"]
|
|
21751
22259
|
});
|
|
21752
|
-
verdictsFileSchema =
|
|
21753
|
-
verdicts:
|
|
21754
|
-
human_tests:
|
|
21755
|
-
overall:
|
|
21756
|
-
provenance:
|
|
21757
|
-
judge_mode:
|
|
21758
|
-
prompt_id:
|
|
21759
|
-
prompt_version:
|
|
21760
|
-
model:
|
|
22260
|
+
verdictsFileSchema = z26.object({
|
|
22261
|
+
verdicts: z26.array(verdictEntrySchema).optional(),
|
|
22262
|
+
human_tests: z26.array(verdictEntrySchema).optional(),
|
|
22263
|
+
overall: z26.object({ answer: z26.string(), reasoning: z26.string() }).passthrough().optional(),
|
|
22264
|
+
provenance: z26.object({
|
|
22265
|
+
judge_mode: z26.string().optional(),
|
|
22266
|
+
prompt_id: z26.string().optional(),
|
|
22267
|
+
prompt_version: z26.string().optional(),
|
|
22268
|
+
model: z26.string().optional()
|
|
21761
22269
|
}).passthrough().optional()
|
|
21762
22270
|
});
|
|
21763
22271
|
}
|
|
@@ -21785,7 +22293,7 @@ __export(complete_exports, {
|
|
|
21785
22293
|
screenshotSizeWarning: () => screenshotSizeWarning,
|
|
21786
22294
|
validateCanonicalWalkthrough: () => validateCanonicalWalkthrough
|
|
21787
22295
|
});
|
|
21788
|
-
import { promises as
|
|
22296
|
+
import { promises as fs30 } from "fs";
|
|
21789
22297
|
import path30 from "path";
|
|
21790
22298
|
import chalk33 from "chalk";
|
|
21791
22299
|
async function complete(runId, opts) {
|
|
@@ -21812,7 +22320,7 @@ async function complete(runId, opts) {
|
|
|
21812
22320
|
const walkerSummary = await readWalkerSummary(run.runDirPath);
|
|
21813
22321
|
let judgeReported;
|
|
21814
22322
|
try {
|
|
21815
|
-
const verdictsRaw = await
|
|
22323
|
+
const verdictsRaw = await fs30.readFile(
|
|
21816
22324
|
path30.join(run.runDirPath, "verdicts.json"),
|
|
21817
22325
|
"utf8"
|
|
21818
22326
|
);
|
|
@@ -21865,7 +22373,7 @@ async function loadRun(runId, opts) {
|
|
|
21865
22373
|
if (!resolved) return null;
|
|
21866
22374
|
const { projectRoot, runDirPath } = resolved;
|
|
21867
22375
|
try {
|
|
21868
|
-
await
|
|
22376
|
+
await fs30.access(runDirPath);
|
|
21869
22377
|
} catch {
|
|
21870
22378
|
commandError(`Run not found: ${runId}`, opts);
|
|
21871
22379
|
return null;
|
|
@@ -21874,7 +22382,7 @@ async function loadRun(runId, opts) {
|
|
|
21874
22382
|
let manifest;
|
|
21875
22383
|
try {
|
|
21876
22384
|
manifest = JSON.parse(
|
|
21877
|
-
await
|
|
22385
|
+
await fs30.readFile(manifestPath, "utf8")
|
|
21878
22386
|
);
|
|
21879
22387
|
} catch {
|
|
21880
22388
|
commandError(`No walkthrough.json found for run: ${runId}`, opts);
|
|
@@ -21886,7 +22394,7 @@ async function reportAlreadyCompleted(run, opts) {
|
|
|
21886
22394
|
const { runId, manifest } = run;
|
|
21887
22395
|
if (opts?.json) {
|
|
21888
22396
|
try {
|
|
21889
|
-
const raw = await
|
|
22397
|
+
const raw = await fs30.readFile(
|
|
21890
22398
|
path30.join(run.runDirPath, "canonical.json"),
|
|
21891
22399
|
"utf8"
|
|
21892
22400
|
);
|
|
@@ -22076,14 +22584,14 @@ async function screenshotSizeWarning(runDirPath, viewport) {
|
|
|
22076
22584
|
const dir = path30.join(runDirPath, "screenshots");
|
|
22077
22585
|
let first;
|
|
22078
22586
|
try {
|
|
22079
|
-
first = (await
|
|
22587
|
+
first = (await fs30.readdir(dir)).filter((f) => f.toLowerCase().endsWith(".png")).sort((a, b) => a.localeCompare(b, void 0, { numeric: true }))[0];
|
|
22080
22588
|
} catch {
|
|
22081
22589
|
return null;
|
|
22082
22590
|
}
|
|
22083
22591
|
if (!first) return null;
|
|
22084
22592
|
let size = null;
|
|
22085
22593
|
try {
|
|
22086
|
-
const handle = await
|
|
22594
|
+
const handle = await fs30.open(path30.join(dir, first), "r");
|
|
22087
22595
|
try {
|
|
22088
22596
|
const head = Buffer.alloc(24);
|
|
22089
22597
|
const { bytesRead } = await handle.read(head, 0, 24, 0);
|
|
@@ -22100,7 +22608,7 @@ async function screenshotSizeWarning(runDirPath, viewport) {
|
|
|
22100
22608
|
async function readWalkerSummary(runDirPath) {
|
|
22101
22609
|
try {
|
|
22102
22610
|
const data = JSON.parse(
|
|
22103
|
-
await
|
|
22611
|
+
await fs30.readFile(path30.join(runDirPath, "summary.json"), "utf8")
|
|
22104
22612
|
);
|
|
22105
22613
|
const strings = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string" && x.trim() !== "") : void 0;
|
|
22106
22614
|
const model = typeof data.model === "string" && data.model.trim() !== "" ? data.model.trim() : void 0;
|
|
@@ -22209,7 +22717,7 @@ function validateCanonicalWalkthrough(canonical) {
|
|
|
22209
22717
|
async function applyRecordedVerdicts(canonical, runDirPath) {
|
|
22210
22718
|
try {
|
|
22211
22719
|
const recorded = JSON.parse(
|
|
22212
|
-
await
|
|
22720
|
+
await fs30.readFile(path30.join(runDirPath, "verdicts.json"), "utf8")
|
|
22213
22721
|
);
|
|
22214
22722
|
if (Array.isArray(recorded.verdicts)) {
|
|
22215
22723
|
return applyVerdicts(canonical, recorded);
|
|
@@ -22397,14 +22905,14 @@ __export(match_exports, {
|
|
|
22397
22905
|
match: () => match,
|
|
22398
22906
|
matchRecord: () => matchRecord
|
|
22399
22907
|
});
|
|
22400
|
-
import { promises as
|
|
22908
|
+
import { promises as fs31 } from "fs";
|
|
22401
22909
|
import path31 from "path";
|
|
22402
22910
|
import chalk34 from "chalk";
|
|
22403
22911
|
async function completedManifest2(runDirPath, runId, opts) {
|
|
22404
22912
|
let manifest;
|
|
22405
22913
|
try {
|
|
22406
22914
|
manifest = JSON.parse(
|
|
22407
|
-
await
|
|
22915
|
+
await fs31.readFile(path31.join(runDirPath, "walkthrough.json"), "utf8")
|
|
22408
22916
|
);
|
|
22409
22917
|
} catch {
|
|
22410
22918
|
commandError(`Run not found: ${runId}`, opts);
|
|
@@ -22435,10 +22943,10 @@ async function match(runId, opts) {
|
|
|
22435
22943
|
const prompt = needed ? composeMatchPrompt(input) : null;
|
|
22436
22944
|
const promptFilePath = opts?.promptFile ?? path31.join(runDirPath, "match_prompt.md");
|
|
22437
22945
|
if (prompt) {
|
|
22438
|
-
await
|
|
22946
|
+
await fs31.writeFile(promptFilePath, prompt, "utf8");
|
|
22439
22947
|
} else {
|
|
22440
22948
|
try {
|
|
22441
|
-
await
|
|
22949
|
+
await fs31.unlink(promptFilePath);
|
|
22442
22950
|
} catch {
|
|
22443
22951
|
}
|
|
22444
22952
|
}
|
|
@@ -22492,7 +23000,7 @@ async function matchRecord(runId, opts) {
|
|
|
22492
23000
|
}
|
|
22493
23001
|
raw = Buffer.concat(chunks).toString("utf8");
|
|
22494
23002
|
} else {
|
|
22495
|
-
raw = await
|
|
23003
|
+
raw = await fs31.readFile(opts.file, "utf8");
|
|
22496
23004
|
}
|
|
22497
23005
|
answer = JSON.parse(raw);
|
|
22498
23006
|
} catch (err) {
|
|
@@ -22682,9 +23190,8 @@ var init_prune2 = __esm({
|
|
|
22682
23190
|
|
|
22683
23191
|
// src/bin.ts
|
|
22684
23192
|
init_context4();
|
|
22685
|
-
import { existsSync as existsSync13
|
|
22686
|
-
import {
|
|
22687
|
-
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
23193
|
+
import { existsSync as existsSync13 } from "fs";
|
|
23194
|
+
import { resolve as resolve3 } from "path";
|
|
22688
23195
|
import chalk38 from "chalk";
|
|
22689
23196
|
import { Command } from "commander";
|
|
22690
23197
|
|
|
@@ -22880,6 +23387,12 @@ function registerProjectCommands(program2) {
|
|
|
22880
23387
|
"--description <text>",
|
|
22881
23388
|
"One-line description (capability, outline)"
|
|
22882
23389
|
).option("--capability <slug>", "Primary capability slug (outline only)").option(
|
|
23390
|
+
"--additional-capabilities <slugs>",
|
|
23391
|
+
"Secondary capability slugs, comma-separated (outline only)"
|
|
23392
|
+
).option(
|
|
23393
|
+
"--paths <paths>",
|
|
23394
|
+
"Route patterns owned by this capability, comma-separated (capability only)"
|
|
23395
|
+
).option("--area <name>", "Visual grouping category (capability only)").option(
|
|
22883
23396
|
"--tension <text>",
|
|
22884
23397
|
"Structural tension driving this situation (outline only)"
|
|
22885
23398
|
).option(
|
|
@@ -22941,10 +23454,12 @@ Examples:
|
|
|
22941
23454
|
);
|
|
22942
23455
|
explore.command("coverage [map]").description(
|
|
22943
23456
|
"Surfaces of a map (default: latest) that no run reached, and places runs reached that the map lacks"
|
|
22944
|
-
).option("--json", "Output as JSON").
|
|
22945
|
-
|
|
22946
|
-
|
|
22947
|
-
|
|
23457
|
+
).option("--json", "Output as JSON").option("--all", "List all surfaces, including reached ones").action(
|
|
23458
|
+
async (map2, opts) => {
|
|
23459
|
+
const { exploreCoverageCommand: exploreCoverageCommand2 } = await Promise.resolve().then(() => (init_explore(), explore_exports));
|
|
23460
|
+
await exploreCoverageCommand2(map2, opts);
|
|
23461
|
+
}
|
|
23462
|
+
);
|
|
22948
23463
|
explore.command("diff [a] [b]").description("Compare two maps (default: the two latest)").option("--json", "Output as JSON").action(
|
|
22949
23464
|
async (a, b, opts) => {
|
|
22950
23465
|
const { exploreDiffCommand: exploreDiffCommand2 } = await Promise.resolve().then(() => (init_explore(), explore_exports));
|
|
@@ -23185,6 +23700,9 @@ function registerAllCommands(program2) {
|
|
|
23185
23700
|
registerCloudCommands(program2);
|
|
23186
23701
|
}
|
|
23187
23702
|
|
|
23703
|
+
// src/bin.ts
|
|
23704
|
+
init_skills();
|
|
23705
|
+
|
|
23188
23706
|
// src/ui/panic.ts
|
|
23189
23707
|
init_logger();
|
|
23190
23708
|
import chalk36 from "chalk";
|
|
@@ -23307,15 +23825,7 @@ function printUpdateNotice(currentVersion, latestVersion) {
|
|
|
23307
23825
|
|
|
23308
23826
|
// src/bin.ts
|
|
23309
23827
|
setupProcessHandlers();
|
|
23310
|
-
var
|
|
23311
|
-
var version = "0.0.0";
|
|
23312
|
-
try {
|
|
23313
|
-
const pkg = JSON.parse(
|
|
23314
|
-
readFileSync9(resolve3(thisDir, "..", "package.json"), "utf-8")
|
|
23315
|
-
);
|
|
23316
|
-
version = pkg.version ?? "0.0.0";
|
|
23317
|
-
} catch {
|
|
23318
|
-
}
|
|
23828
|
+
var version = getVersion();
|
|
23319
23829
|
var program = new Command().name("iamu").description(
|
|
23320
23830
|
"Scenario-driven development \u2014 test your product as realistic personas"
|
|
23321
23831
|
).version(version).option(
|