@kirrosh/zond 0.22.0 → 0.23.0

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.
Files changed (256) hide show
  1. package/CHANGELOG.md +648 -0
  2. package/README.md +58 -6
  3. package/package.json +9 -6
  4. package/src/cli/argv.ts +122 -0
  5. package/src/cli/commands/add-api.ts +134 -0
  6. package/src/cli/commands/api/annotate/idempotency.ts +59 -0
  7. package/src/cli/commands/api/annotate/index.ts +525 -0
  8. package/src/cli/commands/api/annotate/lifecycle.ts +74 -0
  9. package/src/cli/commands/api/annotate/overlay.ts +206 -0
  10. package/src/cli/commands/api/annotate/pagination.ts +60 -0
  11. package/src/cli/commands/api/annotate/prompts.ts +183 -0
  12. package/src/cli/commands/api/annotate/readback.ts +58 -0
  13. package/src/cli/commands/api/annotate/resources.ts +91 -0
  14. package/src/cli/commands/api/annotate/seed-bodies.ts +61 -0
  15. package/src/cli/commands/audit.ts +480 -0
  16. package/src/cli/commands/bootstrap.ts +710 -0
  17. package/src/cli/commands/catalog.ts +35 -0
  18. package/src/cli/commands/check.ts +348 -0
  19. package/src/cli/commands/checks.ts +756 -0
  20. package/src/cli/commands/ci-init.ts +43 -0
  21. package/src/cli/commands/clean.ts +212 -0
  22. package/src/cli/commands/cleanup.ts +262 -0
  23. package/src/cli/commands/completions.ts +16 -0
  24. package/src/cli/commands/coverage.ts +605 -132
  25. package/src/cli/commands/db.ts +178 -7
  26. package/src/cli/commands/describe.ts +37 -2
  27. package/src/cli/commands/discover.ts +1236 -0
  28. package/src/cli/commands/doctor.ts +607 -0
  29. package/src/cli/commands/fixtures.ts +402 -0
  30. package/src/cli/commands/generate.ts +420 -46
  31. package/src/cli/commands/init/bootstrap.ts +30 -1
  32. package/src/cli/commands/{init.ts → init/index.ts} +99 -5
  33. package/src/cli/commands/init/skills.ts +56 -3
  34. package/src/cli/commands/init/templates/agents.md +65 -61
  35. package/src/cli/commands/init/templates/skills/zond-checks.md +397 -0
  36. package/src/cli/commands/init/templates/skills/zond-triage.md +210 -0
  37. package/src/cli/commands/init/templates/skills/zond.md +592 -125
  38. package/src/cli/commands/init/templates/zond-config.yml +8 -9
  39. package/src/cli/commands/prepare-fixtures.ts +135 -0
  40. package/src/cli/commands/probe/mass-assignment.ts +503 -0
  41. package/src/cli/commands/probe/security.ts +454 -0
  42. package/src/cli/commands/probe/static.ts +255 -0
  43. package/src/cli/commands/probe/webhooks.ts +161 -0
  44. package/src/cli/commands/probe.ts +459 -0
  45. package/src/cli/commands/reference.ts +87 -0
  46. package/src/cli/commands/refresh-api.ts +169 -0
  47. package/src/cli/commands/remove-api.ts +150 -0
  48. package/src/cli/commands/report-bundle.ts +318 -0
  49. package/src/cli/commands/report.ts +241 -0
  50. package/src/cli/commands/request.ts +379 -4
  51. package/src/cli/commands/run.ts +842 -53
  52. package/src/cli/commands/session.ts +244 -0
  53. package/src/cli/commands/use.ts +18 -1
  54. package/src/cli/index.ts +20 -3
  55. package/src/cli/json-envelope.ts +112 -3
  56. package/src/cli/json-schemas.ts +263 -0
  57. package/src/cli/program.ts +198 -635
  58. package/src/cli/resolve.ts +105 -0
  59. package/src/cli/status-filter.ts +124 -0
  60. package/src/cli/util/api-context.ts +85 -0
  61. package/src/cli/version.ts +5 -0
  62. package/src/core/anti-fp/bootstrap.ts +34 -0
  63. package/src/core/anti-fp/index.ts +33 -0
  64. package/src/core/anti-fp/registry.ts +44 -0
  65. package/src/core/anti-fp/rules/baseline-echo.ts +74 -0
  66. package/src/core/anti-fp/rules/schemathesis/body_negation_becomes_valid.ts +52 -0
  67. package/src/core/anti-fp/rules/schemathesis/coverage_phase_boundary_positive.ts +38 -0
  68. package/src/core/anti-fp/rules/schemathesis/has_unverifiable_mutations.ts +35 -0
  69. package/src/core/anti-fp/rules/schemathesis/index.ts +24 -0
  70. package/src/core/anti-fp/rules/schemathesis/string_type_mutation_becomes_valid.ts +53 -0
  71. package/src/core/anti-fp/rules/subscription-gated/index.ts +11 -0
  72. package/src/core/anti-fp/rules/subscription-gated/paid-plan-403.ts +75 -0
  73. package/src/core/anti-fp/types.ts +68 -0
  74. package/src/core/checks/checks/_crud-helpers.ts +133 -0
  75. package/src/core/checks/checks/_negative_mutator.ts +133 -0
  76. package/src/core/checks/checks/_readback-helpers.ts +133 -0
  77. package/src/core/checks/checks/content_type_conformance.ts +39 -0
  78. package/src/core/checks/checks/cross_call_references.ts +134 -0
  79. package/src/core/checks/checks/ensure_resource_availability.ts +62 -0
  80. package/src/core/checks/checks/idempotency_replay.ts +246 -0
  81. package/src/core/checks/checks/ignored_auth.ts +211 -0
  82. package/src/core/checks/checks/index.ts +65 -0
  83. package/src/core/checks/checks/lifecycle_transitions.ts +273 -0
  84. package/src/core/checks/checks/missing_required_header.ts +40 -0
  85. package/src/core/checks/checks/negative_data_rejection.ts +45 -0
  86. package/src/core/checks/checks/not_a_server_error.ts +27 -0
  87. package/src/core/checks/checks/open_cors_on_sensitive.ts +131 -0
  88. package/src/core/checks/checks/pagination_invariants.ts +238 -0
  89. package/src/core/checks/checks/positive_data_acceptance.ts +36 -0
  90. package/src/core/checks/checks/rate_limit_headers_absent.ts +77 -0
  91. package/src/core/checks/checks/response_headers_conformance.ts +74 -0
  92. package/src/core/checks/checks/response_schema_conformance.ts +30 -0
  93. package/src/core/checks/checks/status_code_conformance.ts +61 -0
  94. package/src/core/checks/checks/unsupported_method.ts +63 -0
  95. package/src/core/checks/checks/use_after_free.ts +78 -0
  96. package/src/core/checks/index.ts +30 -0
  97. package/src/core/checks/mode.ts +79 -0
  98. package/src/core/checks/recommended-action.ts +64 -0
  99. package/src/core/checks/registry.ts +78 -0
  100. package/src/core/checks/runner.ts +874 -0
  101. package/src/core/checks/sarif.ts +230 -0
  102. package/src/core/checks/stateful.ts +121 -0
  103. package/src/core/checks/types.ts +189 -0
  104. package/src/core/classifier/recommended-action.ts +222 -0
  105. package/src/core/context/current.ts +22 -6
  106. package/src/core/context/session.ts +78 -0
  107. package/src/core/coverage/loader.ts +185 -0
  108. package/src/core/coverage/reasons.ts +300 -0
  109. package/src/core/diagnostics/db-analysis.ts +151 -11
  110. package/src/core/diagnostics/failure-class.ts +120 -0
  111. package/src/core/diagnostics/failure-hints.ts +212 -9
  112. package/src/core/diagnostics/spec-pointer.ts +99 -0
  113. package/src/core/diagnostics/suggested-fixes.ts +156 -0
  114. package/src/core/exporter/case-study/index.ts +270 -0
  115. package/src/core/exporter/curl.ts +40 -0
  116. package/src/core/exporter/exporter.ts +48 -0
  117. package/src/core/exporter/html-report/escape.ts +24 -0
  118. package/src/core/exporter/html-report/index.ts +479 -0
  119. package/src/core/exporter/html-report/script.ts +100 -0
  120. package/src/core/exporter/html-report/styles.ts +408 -0
  121. package/src/core/generator/chunker.ts +42 -16
  122. package/src/core/generator/coverage-phase.ts +0 -0
  123. package/src/core/generator/create-body.ts +89 -0
  124. package/src/core/generator/data-factory.ts +445 -19
  125. package/src/core/generator/describe.ts +1 -1
  126. package/src/core/generator/fixtures-builder.ts +325 -0
  127. package/src/core/generator/index.ts +7 -5
  128. package/src/core/generator/openapi-reader.ts +37 -3
  129. package/src/core/generator/path-param-disambig.ts +114 -0
  130. package/src/core/generator/resources-builder.ts +648 -0
  131. package/src/core/generator/schema-utils.ts +11 -3
  132. package/src/core/generator/serializer.ts +103 -13
  133. package/src/core/generator/suite-generator.ts +419 -111
  134. package/src/core/generator/types.ts +8 -0
  135. package/src/core/identity/identity-file.ts +129 -0
  136. package/src/core/lint/affects.ts +28 -0
  137. package/src/core/lint/config.ts +96 -0
  138. package/src/core/lint/format.ts +42 -0
  139. package/src/core/lint/index.ts +94 -0
  140. package/src/core/lint/reporter.ts +128 -0
  141. package/src/core/lint/rules/consistency.ts +158 -0
  142. package/src/core/lint/rules/heuristics.ts +97 -0
  143. package/src/core/lint/rules/strictness.ts +109 -0
  144. package/src/core/lint/types.ts +96 -0
  145. package/src/core/lint/walker.ts +248 -0
  146. package/src/core/meta/meta-store.ts +6 -73
  147. package/src/core/output/README.md +91 -0
  148. package/src/core/output/index.ts +13 -0
  149. package/src/core/output/run.ts +126 -0
  150. package/src/core/output/types.ts +129 -0
  151. package/src/core/parser/env-interpolation.ts +104 -0
  152. package/src/core/parser/filter.ts +57 -0
  153. package/src/core/parser/schema.ts +129 -4
  154. package/src/core/parser/types.ts +19 -1
  155. package/src/core/parser/variables.ts +0 -0
  156. package/src/core/parser/yaml-parser.ts +58 -12
  157. package/src/core/probe/bootstrap.ts +34 -0
  158. package/src/core/probe/dry-run-envelope.ts +57 -0
  159. package/src/core/probe/mass-assignment-probe-class.ts +198 -0
  160. package/src/core/probe/mass-assignment-probe.ts +1122 -0
  161. package/src/core/probe/mass-assignment-template.ts +212 -0
  162. package/src/core/probe/method-probe.ts +43 -76
  163. package/src/core/probe/method-shared.ts +69 -0
  164. package/src/core/probe/negative-probe.ts +183 -149
  165. package/src/core/probe/orphan-tracker.ts +188 -0
  166. package/src/core/probe/path-discovery.ts +440 -0
  167. package/src/core/probe/probe-harness.ts +120 -0
  168. package/src/core/probe/registry.ts +89 -0
  169. package/src/core/probe/runner.ts +136 -0
  170. package/src/core/probe/security-probe-class.ts +201 -0
  171. package/src/core/probe/security-probe.ts +1453 -0
  172. package/src/core/probe/shared.ts +505 -0
  173. package/src/core/probe/static-probe-class.ts +125 -0
  174. package/src/core/probe/types.ts +165 -0
  175. package/src/core/probe/verdict-aggregator.ts +33 -0
  176. package/src/core/probe/webhooks-probe.ts +284 -0
  177. package/src/core/reporter/console.ts +41 -2
  178. package/src/core/reporter/index.ts +2 -3
  179. package/src/core/reporter/json.ts +11 -1
  180. package/src/core/reporter/junit.ts +27 -12
  181. package/src/core/reporter/ndjson.ts +37 -0
  182. package/src/core/reporter/types.ts +3 -0
  183. package/src/core/runner/assertions.ts +58 -1
  184. package/src/core/runner/async-pool.ts +108 -0
  185. package/src/core/runner/auth-path.ts +8 -0
  186. package/src/core/runner/ci-context.ts +72 -0
  187. package/src/core/runner/executor.ts +264 -20
  188. package/src/core/runner/form-encode.ts +51 -0
  189. package/src/core/runner/http-client.ts +75 -2
  190. package/src/core/runner/learn-drift.ts +293 -0
  191. package/src/core/runner/preflight-vars.ts +149 -0
  192. package/src/core/runner/progress-tracker.ts +73 -0
  193. package/src/core/runner/rate-limiter.ts +89 -17
  194. package/src/core/runner/run-kind.ts +39 -0
  195. package/src/core/runner/schema-validator.ts +312 -0
  196. package/src/core/runner/send-request.ts +153 -20
  197. package/src/core/runner/types.ts +38 -0
  198. package/src/core/secrets/registry.ts +164 -0
  199. package/src/core/secrets/secrets-file.ts +115 -0
  200. package/src/core/selectors/operation-filter.ts +144 -0
  201. package/src/core/setup-api.ts +415 -16
  202. package/src/core/severity/category.ts +94 -0
  203. package/src/core/severity/index.ts +121 -0
  204. package/src/core/spec/layers.ts +154 -0
  205. package/src/core/util/format-eta.ts +21 -0
  206. package/src/core/utils.ts +5 -1
  207. package/src/core/workspace/config.ts +129 -0
  208. package/src/core/workspace/manifest.ts +283 -0
  209. package/src/core/workspace/output-rotation.ts +62 -0
  210. package/src/core/workspace/triage-path.ts +87 -0
  211. package/src/db/lint-runs.ts +47 -0
  212. package/src/db/migrate.ts +126 -0
  213. package/src/db/migrations/0001_run_kind.sql +25 -0
  214. package/src/db/migrations/sql.d.ts +4 -0
  215. package/src/db/queries/collections.ts +133 -0
  216. package/src/db/queries/coverage.ts +9 -0
  217. package/src/db/queries/dashboard.ts +59 -0
  218. package/src/db/queries/results.ts +128 -0
  219. package/src/db/queries/runs.ts +235 -0
  220. package/src/db/queries/sessions.ts +42 -0
  221. package/src/db/queries/settings.ts +28 -0
  222. package/src/db/queries/types.ts +172 -0
  223. package/src/db/queries.ts +72 -802
  224. package/src/db/schema.ts +178 -50
  225. package/src/cli/commands/export.ts +0 -144
  226. package/src/cli/commands/guide.ts +0 -127
  227. package/src/cli/commands/init/templates/skills/scenarios.md +0 -97
  228. package/src/cli/commands/probe-methods.ts +0 -108
  229. package/src/cli/commands/probe-validation.ts +0 -124
  230. package/src/cli/commands/serve.ts +0 -114
  231. package/src/cli/commands/sync.ts +0 -268
  232. package/src/cli/commands/update.ts +0 -189
  233. package/src/cli/commands/validate.ts +0 -34
  234. package/src/core/diagnostics/render-md.ts +0 -112
  235. package/src/core/exporter/postman.ts +0 -963
  236. package/src/core/generator/guide-builder.ts +0 -253
  237. package/src/core/meta/types.ts +0 -19
  238. package/src/core/parser/index.ts +0 -21
  239. package/src/core/runner/execute-run.ts +0 -132
  240. package/src/core/runner/index.ts +0 -12
  241. package/src/core/sync/spec-differ.ts +0 -38
  242. package/src/web/data/collection-state.ts +0 -362
  243. package/src/web/routes/api.ts +0 -314
  244. package/src/web/routes/dashboard.ts +0 -350
  245. package/src/web/routes/runs.ts +0 -64
  246. package/src/web/schemas.ts +0 -121
  247. package/src/web/server.ts +0 -134
  248. package/src/web/static/htmx.min.cjs +0 -1
  249. package/src/web/static/style.css +0 -1148
  250. package/src/web/views/endpoints-tab.ts +0 -174
  251. package/src/web/views/explorer-tab.ts +0 -402
  252. package/src/web/views/health-strip.ts +0 -92
  253. package/src/web/views/layout.ts +0 -48
  254. package/src/web/views/results.ts +0 -210
  255. package/src/web/views/runs-tab.ts +0 -126
  256. package/src/web/views/suites-tab.ts +0 -181
@@ -1,189 +0,0 @@
1
- import { VERSION } from "../version.ts";
2
- import { isCompiledBinary } from "../runtime.ts";
3
- import { printError, printSuccess, printWarning } from "../output.ts";
4
- import { jsonOk, jsonError, printJson } from "../json-envelope.ts";
5
-
6
- export interface UpdateOptions {
7
- json?: boolean;
8
- check?: boolean;
9
- }
10
-
11
- const REPO = "kirrosh/zond";
12
- const GITHUB_API = `https://api.github.com/repos/${REPO}/releases/latest`;
13
-
14
- interface GitHubRelease {
15
- tag_name: string;
16
- assets: { name: string; browser_download_url: string }[];
17
- }
18
-
19
- function getTarget(): { target: string; ext: string } | null {
20
- const platform = process.platform;
21
- const arch = process.arch;
22
-
23
- if (platform === "linux" && arch === "x64") return { target: "linux-x64", ext: "tar.gz" };
24
- if (platform === "darwin" && arch === "arm64") return { target: "darwin-arm64", ext: "tar.gz" };
25
- if (platform === "win32" && arch === "x64") return { target: "win-x64", ext: "zip" };
26
- return null;
27
- }
28
-
29
- async function fetchLatestRelease(): Promise<GitHubRelease> {
30
- const resp = await fetch(GITHUB_API, {
31
- headers: { "User-Agent": `zond/${VERSION}` },
32
- });
33
- if (!resp.ok) {
34
- throw new Error(`GitHub API returned ${resp.status}: ${resp.statusText}`);
35
- }
36
- return resp.json() as Promise<GitHubRelease>;
37
- }
38
-
39
- export async function updateCommand(options: UpdateOptions): Promise<number> {
40
- try {
41
- if (!isCompiledBinary()) {
42
- const msg = "Self-update is only available for standalone binaries. Install binary: curl -fsSL https://raw.githubusercontent.com/kirrosh/zond/master/install.sh | sh";
43
- if (options.json) {
44
- printJson(jsonOk("update", { action: "skip", reason: "not-standalone", installHint: "curl -fsSL https://raw.githubusercontent.com/kirrosh/zond/master/install.sh | sh" }, [msg]));
45
- } else {
46
- printWarning(msg);
47
- }
48
- return 3;
49
- }
50
-
51
- const target = getTarget();
52
- if (!target) {
53
- const msg = `Unsupported platform: ${process.platform}-${process.arch}`;
54
- if (options.json) {
55
- printJson(jsonError("update", [msg]));
56
- } else {
57
- printError(msg);
58
- }
59
- return 2;
60
- }
61
-
62
- const release = await fetchLatestRelease();
63
- const latest = release.tag_name.replace(/^v/, "");
64
-
65
- if (latest === VERSION) {
66
- const msg = `Already up to date (${VERSION})`;
67
- if (options.json) {
68
- printJson(jsonOk("update", { action: "none", currentVersion: VERSION, latestVersion: latest }));
69
- } else {
70
- console.log(msg);
71
- }
72
- return 0;
73
- }
74
-
75
- if (options.check) {
76
- const msg = `Update available: ${VERSION} → ${latest}`;
77
- if (options.json) {
78
- printJson(jsonOk("update", { action: "available", currentVersion: VERSION, latestVersion: latest }));
79
- } else {
80
- console.log(msg);
81
- }
82
- return 0;
83
- }
84
-
85
- // Find the right asset
86
- const assetName = `zond-${target.target}.${target.ext}`;
87
- const asset = release.assets.find(a => a.name === assetName);
88
- if (!asset) {
89
- const msg = `Binary not found for ${target.target} in release ${release.tag_name}`;
90
- if (options.json) {
91
- printJson(jsonError("update", [msg]));
92
- } else {
93
- printError(msg);
94
- }
95
- return 2;
96
- }
97
-
98
- console.log(`Updating zond ${VERSION} → ${latest}...`);
99
- console.log(`Downloading ${assetName}...`);
100
-
101
- // Download the archive
102
- const resp = await fetch(asset.browser_download_url, {
103
- headers: { "User-Agent": `zond/${VERSION}` },
104
- });
105
- if (!resp.ok) {
106
- throw new Error(`Download failed: ${resp.status} ${resp.statusText}`);
107
- }
108
- const archiveData = new Uint8Array(await resp.arrayBuffer());
109
-
110
- const currentBinary = process.execPath;
111
- const { join, dirname } = await import("path");
112
- const tmpDir = join(dirname(currentBinary), `.zond-update-${Date.now()}`);
113
- const { mkdir, rm, rename, chmod } = await import("fs/promises");
114
- await mkdir(tmpDir, { recursive: true });
115
-
116
- try {
117
- const archivePath = join(tmpDir, assetName);
118
- await Bun.write(archivePath, archiveData);
119
-
120
- // Extract
121
- if (target.ext === "tar.gz") {
122
- const proc = Bun.spawn(["tar", "-xzf", archivePath, "-C", tmpDir]);
123
- const exitCode = await proc.exited;
124
- if (exitCode !== 0) throw new Error(`tar extraction failed (exit ${exitCode})`);
125
- } else {
126
- // Windows zip
127
- const proc = Bun.spawn([
128
- "powershell", "-NoProfile", "-Command",
129
- `Expand-Archive -Path '${archivePath}' -DestinationPath '${tmpDir}' -Force`,
130
- ]);
131
- const exitCode = await proc.exited;
132
- if (exitCode !== 0) throw new Error(`Zip extraction failed (exit ${exitCode})`);
133
- }
134
-
135
- // Find the extracted binary
136
- const binaryName = process.platform === "win32" ? "zond.exe" : "zond";
137
- const newBinary = join(tmpDir, binaryName);
138
- const file = Bun.file(newBinary);
139
- if (!await file.exists()) {
140
- throw new Error(`Binary '${binaryName}' not found in archive`);
141
- }
142
-
143
- // Replace current binary
144
- try {
145
- if (process.platform === "win32") {
146
- // Windows: rename current to .old, move new, clean up
147
- const oldBinary = currentBinary + ".old";
148
- try { await rm(oldBinary, { force: true }); } catch {}
149
- await rename(currentBinary, oldBinary);
150
- await rename(newBinary, currentBinary);
151
- try { await rm(oldBinary, { force: true }); } catch {}
152
- } else {
153
- await rename(newBinary, currentBinary);
154
- await chmod(currentBinary, 0o755);
155
- }
156
- } catch (replaceErr: any) {
157
- if (replaceErr?.code === "EACCES" || replaceErr?.code === "EPERM") {
158
- const hint = process.platform === "win32"
159
- ? `Permission denied. Run the terminal as Administrator.`
160
- : `Permission denied writing to ${currentBinary}. Run: sudo zond update`;
161
- if (options.json) {
162
- printJson(jsonError("update", [hint]));
163
- } else {
164
- printError(hint);
165
- }
166
- return 2;
167
- }
168
- throw replaceErr;
169
- }
170
-
171
- if (options.json) {
172
- printJson(jsonOk("update", { action: "updated", previousVersion: VERSION, newVersion: latest }));
173
- } else {
174
- printSuccess(`Updated zond ${VERSION} → ${latest}`);
175
- }
176
- return 0;
177
- } finally {
178
- try { await rm(tmpDir, { recursive: true, force: true }); } catch {}
179
- }
180
- } catch (err) {
181
- const message = err instanceof Error ? err.message : String(err);
182
- if (options.json) {
183
- printJson(jsonError("update", [message]));
184
- } else {
185
- printError(message);
186
- }
187
- return 2;
188
- }
189
- }
@@ -1,34 +0,0 @@
1
- import { parse } from "../../core/parser/yaml-parser.ts";
2
- import { printError, printSuccess } from "../output.ts";
3
- import { jsonOk, jsonError, printJson } from "../json-envelope.ts";
4
-
5
- export interface ValidateOptions {
6
- path: string;
7
- json?: boolean;
8
- }
9
-
10
- export async function validateCommand(options: ValidateOptions): Promise<number> {
11
- try {
12
- const suites = await parse(options.path);
13
- const totalSteps = suites.reduce((sum, s) => sum + s.tests.length, 0);
14
- if (options.json) {
15
- printJson(jsonOk("validate", {
16
- files: suites.length,
17
- suites: suites.length,
18
- tests: totalSteps,
19
- valid: true,
20
- }));
21
- } else {
22
- printSuccess(`OK: ${suites.length} suite(s), ${totalSteps} test(s) validated successfully`);
23
- }
24
- return 0;
25
- } catch (err) {
26
- const message = err instanceof Error ? err.message : String(err);
27
- if (options.json) {
28
- printJson(jsonError("validate", [message]));
29
- } else {
30
- printError(message);
31
- }
32
- return 2;
33
- }
34
- }
@@ -1,112 +0,0 @@
1
- import type { DiagnoseResult } from "./db-analysis.ts";
2
-
3
- /**
4
- * Render a DiagnoseResult into a human-readable markdown digest.
5
- * Output is the canonical body of the `zond://run/{id}/diagnosis` MCP resource.
6
- */
7
- export function renderDiagnosisMarkdown(result: DiagnoseResult): string {
8
- const { run, summary, agent_directive, env_issue, auth_hint, cascade_skips, failures, grouped_failures } = result;
9
- const out: string[] = [];
10
-
11
- const passed = summary.passed;
12
- const total = summary.total;
13
- const env = run.environment ?? "no env";
14
- const duration = run.duration_ms !== null ? `${run.duration_ms}ms` : "unknown duration";
15
-
16
- out.push(`# Run ${run.id} — ${passed}/${total} passed`);
17
- out.push(`${run.started_at} · ${env} · ${duration}`);
18
- out.push("");
19
- out.push("## Summary");
20
- out.push(`- total: ${summary.total}`);
21
- out.push(`- passed: ${summary.passed}`);
22
- out.push(`- failed: ${summary.failed} (api_errors: ${summary.api_errors}, assertion_failures: ${summary.assertion_failures}, network_errors: ${summary.network_errors})`);
23
-
24
- if (agent_directive) {
25
- out.push("");
26
- out.push("## Agent directive");
27
- out.push(agent_directive);
28
- }
29
-
30
- if (env_issue) {
31
- out.push("");
32
- out.push("## Env issue");
33
- out.push(env_issue);
34
- }
35
-
36
- if (auth_hint) {
37
- out.push("");
38
- out.push("## Auth hint");
39
- out.push(auth_hint);
40
- }
41
-
42
- if (cascade_skips && cascade_skips.length > 0) {
43
- out.push("");
44
- out.push("## Cascade skips");
45
- for (const group of cascade_skips) {
46
- out.push(`- **${group.capture_var}** — ${group.count} test${group.count === 1 ? "" : "s"} skipped`);
47
- for (const example of group.examples) {
48
- out.push(` - ${example}`);
49
- }
50
- }
51
- }
52
-
53
- if (grouped_failures && grouped_failures.length > 0) {
54
- out.push("");
55
- out.push("## Failure groups");
56
- for (const group of grouped_failures) {
57
- out.push("");
58
- out.push(`### ${group.pattern} — ${group.count} occurrence${group.count === 1 ? "" : "s"}`);
59
- out.push(`recommended_action: \`${group.recommended_action}\``);
60
- if (group.hint) out.push(`hint: ${group.hint}`);
61
- if (group.examples.length > 0) {
62
- out.push("examples:");
63
- for (const example of group.examples) {
64
- out.push(`- ${example}`);
65
- }
66
- }
67
- }
68
- }
69
-
70
- if (failures.length > 0) {
71
- out.push("");
72
- out.push(grouped_failures && grouped_failures.length > 0 ? "## Representative failures" : "## Failures");
73
- for (const f of failures) {
74
- out.push("");
75
- out.push(`### ${f.suite_name} > ${f.test_name}`);
76
- const meta: string[] = [`failure_type: \`${f.failure_type}\``, `recommended_action: \`${f.recommended_action}\``];
77
- if (f.suite_file) meta.push(`file: \`${f.suite_file}\``);
78
- out.push(meta.join(" · "));
79
- const requestLine = `${f.request_method ?? "?"} ${f.request_url ?? "?"}`;
80
- const statusLine = f.response_status !== null ? ` → ${f.response_status}` : "";
81
- out.push(`- request: ${requestLine}${statusLine}`);
82
- if (f.error_message) out.push(`- error: ${f.error_message}`);
83
- if (f.hint) out.push(`- hint: ${f.hint}`);
84
- if (f.schema_hint) out.push(`- schema: ${f.schema_hint}`);
85
- if (f.response_headers) {
86
- const headerStr = Object.entries(f.response_headers).map(([k, v]) => `${k}: ${v}`).join(", ");
87
- out.push(`- headers: ${headerStr}`);
88
- }
89
- if (f.response_body !== undefined) {
90
- const bodyStr = typeof f.response_body === "string"
91
- ? f.response_body
92
- : JSON.stringify(f.response_body, null, 2);
93
- const fenced = bodyStr.includes("\n") || bodyStr.length > 80;
94
- if (fenced) {
95
- out.push("- response_body:");
96
- out.push(" ```");
97
- for (const line of bodyStr.split("\n")) out.push(` ${line}`);
98
- out.push(" ```");
99
- } else {
100
- out.push(`- response_body: \`${bodyStr}\``);
101
- }
102
- }
103
- }
104
- }
105
-
106
- if (failures.length === 0 && (!grouped_failures || grouped_failures.length === 0)) {
107
- out.push("");
108
- out.push("_No failures._");
109
- }
110
-
111
- return out.join("\n");
112
- }