@kirrosh/zond 0.26.1 → 0.27.1
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/CHANGELOG.md +65 -0
- package/README.md +39 -22
- package/bin/zond.mjs +23 -0
- package/package.json +36 -23
- package/scripts/npm/postinstall.mjs +76 -0
- package/src/CLAUDE.md +0 -112
- package/src/bun-types.d.ts +0 -5
- package/src/cli/argv.ts +0 -122
- package/src/cli/commands/add-api.ts +0 -146
- package/src/cli/commands/api/annotate/idempotency.ts +0 -59
- package/src/cli/commands/api/annotate/index.ts +0 -880
- package/src/cli/commands/api/annotate/lifecycle.ts +0 -74
- package/src/cli/commands/api/annotate/overlay.ts +0 -206
- package/src/cli/commands/api/annotate/pagination.ts +0 -64
- package/src/cli/commands/api/annotate/prompts.ts +0 -220
- package/src/cli/commands/api/annotate/readback.ts +0 -58
- package/src/cli/commands/api/annotate/resources.ts +0 -91
- package/src/cli/commands/api/annotate/seed-bodies.ts +0 -61
- package/src/cli/commands/audit.ts +0 -786
- package/src/cli/commands/catalog.ts +0 -97
- package/src/cli/commands/check.ts +0 -361
- package/src/cli/commands/checks.ts +0 -1072
- package/src/cli/commands/ci-init.ts +0 -223
- package/src/cli/commands/clean.ts +0 -212
- package/src/cli/commands/cleanup.ts +0 -236
- package/src/cli/commands/completions.ts +0 -192
- package/src/cli/commands/coverage.ts +0 -872
- package/src/cli/commands/db.ts +0 -611
- package/src/cli/commands/describe.ts +0 -120
- package/src/cli/commands/discover.ts +0 -1356
- package/src/cli/commands/doctor.ts +0 -661
- package/src/cli/commands/fixtures.ts +0 -402
- package/src/cli/commands/generate.ts +0 -577
- package/src/cli/commands/init/agents-md.ts +0 -61
- package/src/cli/commands/init/bootstrap.ts +0 -111
- package/src/cli/commands/init/index.ts +0 -244
- package/src/cli/commands/init/skills.ts +0 -141
- package/src/cli/commands/init/templates/agents.md +0 -86
- package/src/cli/commands/init/templates/markdown.d.ts +0 -4
- package/src/cli/commands/init/templates/skills/warm-up-target.md +0 -122
- package/src/cli/commands/init/templates/skills/zond-checks.md +0 -621
- package/src/cli/commands/init/templates/skills/zond-seed.md +0 -114
- package/src/cli/commands/init/templates/skills/zond-triage.md +0 -272
- package/src/cli/commands/init/templates/skills/zond.md +0 -861
- package/src/cli/commands/init/templates/zond-config.yml +0 -14
- package/src/cli/commands/prepare-fixtures.ts +0 -97
- package/src/cli/commands/probe/_seed-bodies.ts +0 -52
- package/src/cli/commands/probe/mass-assignment.ts +0 -594
- package/src/cli/commands/probe/security.ts +0 -537
- package/src/cli/commands/probe/static.ts +0 -255
- package/src/cli/commands/probe/webhooks.ts +0 -163
- package/src/cli/commands/probe.ts +0 -535
- package/src/cli/commands/reference.ts +0 -87
- package/src/cli/commands/refresh-api.ts +0 -227
- package/src/cli/commands/remove-api.ts +0 -150
- package/src/cli/commands/report-bundle.ts +0 -310
- package/src/cli/commands/report.ts +0 -241
- package/src/cli/commands/request.ts +0 -548
- package/src/cli/commands/run.ts +0 -1162
- package/src/cli/commands/schema-from-runs.ts +0 -128
- package/src/cli/commands/secrets.ts +0 -133
- package/src/cli/commands/session.ts +0 -244
- package/src/cli/commands/use.ts +0 -74
- package/src/cli/index.ts +0 -55
- package/src/cli/json-envelope.ts +0 -108
- package/src/cli/json-schemas.ts +0 -314
- package/src/cli/output.ts +0 -40
- package/src/cli/program.ts +0 -219
- package/src/cli/resolve.ts +0 -105
- package/src/cli/runtime.ts +0 -7
- package/src/cli/safe-live.ts +0 -24
- package/src/cli/status-filter.ts +0 -114
- package/src/cli/util/api-context.ts +0 -85
- package/src/cli/version.ts +0 -8
- package/src/core/audit/persist.ts +0 -183
- package/src/core/checks/budget.ts +0 -59
- package/src/core/checks/checks/_crud-helpers.ts +0 -133
- package/src/core/checks/checks/_negative_mutator.ts +0 -133
- package/src/core/checks/checks/_readback-helpers.ts +0 -133
- package/src/core/checks/checks/content_type_conformance.ts +0 -39
- package/src/core/checks/checks/cross_call_references.ts +0 -147
- package/src/core/checks/checks/cursor_boundary_fuzzing.ts +0 -219
- package/src/core/checks/checks/ensure_resource_availability.ts +0 -62
- package/src/core/checks/checks/idempotency_replay.ts +0 -242
- package/src/core/checks/checks/ignored_auth.ts +0 -254
- package/src/core/checks/checks/index.ts +0 -68
- package/src/core/checks/checks/lifecycle_transitions.ts +0 -416
- package/src/core/checks/checks/missing_required_header.ts +0 -40
- package/src/core/checks/checks/negative_data_rejection.ts +0 -148
- package/src/core/checks/checks/not_a_server_error.ts +0 -35
- package/src/core/checks/checks/open_cors_on_sensitive.ts +0 -160
- package/src/core/checks/checks/pagination_invariants.ts +0 -419
- package/src/core/checks/checks/positive_data_acceptance.ts +0 -33
- package/src/core/checks/checks/rate_limit_headers_absent.ts +0 -77
- package/src/core/checks/checks/response_headers_conformance.ts +0 -74
- package/src/core/checks/checks/response_schema_conformance.ts +0 -30
- package/src/core/checks/checks/status_code_conformance.ts +0 -132
- package/src/core/checks/checks/unsupported_method.ts +0 -63
- package/src/core/checks/checks/use_after_free.ts +0 -78
- package/src/core/checks/index.ts +0 -30
- package/src/core/checks/mode.ts +0 -82
- package/src/core/checks/recommended-action.ts +0 -68
- package/src/core/checks/registry.ts +0 -78
- package/src/core/checks/runner.ts +0 -1461
- package/src/core/checks/sarif.ts +0 -230
- package/src/core/checks/spec-findings.ts +0 -308
- package/src/core/checks/stateful.ts +0 -121
- package/src/core/checks/types.ts +0 -305
- package/src/core/checks/zond-extensions.ts +0 -73
- package/src/core/classifier/recommended-action.ts +0 -251
- package/src/core/context/current.ts +0 -51
- package/src/core/context/session.ts +0 -78
- package/src/core/coverage/loader.ts +0 -216
- package/src/core/coverage/reasons.ts +0 -300
- package/src/core/diagnostics/db-analysis.ts +0 -666
- package/src/core/diagnostics/failure-class.ts +0 -140
- package/src/core/diagnostics/failure-hints.ts +0 -112
- package/src/core/diagnostics/spec-pointer.ts +0 -99
- package/src/core/diagnostics/suggested-fixes.ts +0 -155
- package/src/core/exporter/case-study/index.ts +0 -270
- package/src/core/exporter/curl.ts +0 -40
- package/src/core/exporter/exporter.ts +0 -48
- package/src/core/exporter/html-report/escape.ts +0 -24
- package/src/core/exporter/html-report/index.ts +0 -479
- package/src/core/exporter/html-report/script.ts +0 -100
- package/src/core/exporter/html-report/styles.ts +0 -408
- package/src/core/generator/catalog-builder.ts +0 -179
- package/src/core/generator/chunker.ts +0 -78
- package/src/core/generator/coverage-phase.ts +0 -0
- package/src/core/generator/coverage-scanner.ts +0 -87
- package/src/core/generator/data-factory.ts +0 -759
- package/src/core/generator/describe.ts +0 -302
- package/src/core/generator/endpoint-warnings.ts +0 -52
- package/src/core/generator/fixtures-builder.ts +0 -332
- package/src/core/generator/index.ts +0 -14
- package/src/core/generator/openapi-reader.ts +0 -297
- package/src/core/generator/path-param-disambig.ts +0 -140
- package/src/core/generator/resources-builder.ts +0 -898
- package/src/core/generator/schema-utils.ts +0 -112
- package/src/core/generator/serializer.ts +0 -343
- package/src/core/generator/suite-generator.ts +0 -1301
- package/src/core/generator/types.ts +0 -63
- package/src/core/identity/identity-file.ts +0 -0
- package/src/core/lint/affects.ts +0 -28
- package/src/core/lint/config.ts +0 -96
- package/src/core/lint/format.ts +0 -42
- package/src/core/lint/index.ts +0 -94
- package/src/core/lint/reporter.ts +0 -128
- package/src/core/lint/rules/consistency.ts +0 -158
- package/src/core/lint/rules/heuristics.ts +0 -97
- package/src/core/lint/rules/strictness.ts +0 -109
- package/src/core/lint/types.ts +0 -96
- package/src/core/lint/walker.ts +0 -248
- package/src/core/meta/meta-store.ts +0 -11
- package/src/core/output/README.md +0 -73
- package/src/core/output/index.ts +0 -13
- package/src/core/output/run.ts +0 -91
- package/src/core/output/types.ts +0 -122
- package/src/core/parser/dynamic-values.ts +0 -160
- package/src/core/parser/env-interpolation.ts +0 -104
- package/src/core/parser/filter.ts +0 -97
- package/src/core/parser/schema.ts +0 -359
- package/src/core/parser/types.ts +0 -117
- package/src/core/parser/variables.ts +0 -0
- package/src/core/parser/yaml-parser.ts +0 -181
- package/src/core/probe/bootstrap.ts +0 -34
- package/src/core/probe/dry-run-envelope.ts +0 -61
- package/src/core/probe/mass-assignment/classify.ts +0 -175
- package/src/core/probe/mass-assignment/cleanup.ts +0 -52
- package/src/core/probe/mass-assignment/digest.ts +0 -114
- package/src/core/probe/mass-assignment/orchestrator.ts +0 -459
- package/src/core/probe/mass-assignment/regression.ts +0 -141
- package/src/core/probe/mass-assignment/suspects.ts +0 -92
- package/src/core/probe/mass-assignment/types.ts +0 -135
- package/src/core/probe/mass-assignment-probe-class.ts +0 -198
- package/src/core/probe/mass-assignment-probe.ts +0 -27
- package/src/core/probe/mass-assignment-template.ts +0 -240
- package/src/core/probe/method-probe.ts +0 -164
- package/src/core/probe/method-shared.ts +0 -69
- package/src/core/probe/negative-probe.ts +0 -691
- package/src/core/probe/orphan-tracker.ts +0 -188
- package/src/core/probe/path-discovery.ts +0 -439
- package/src/core/probe/probe-harness.ts +0 -119
- package/src/core/probe/registry.ts +0 -89
- package/src/core/probe/runner.ts +0 -136
- package/src/core/probe/security/baseline.ts +0 -174
- package/src/core/probe/security/classify.ts +0 -341
- package/src/core/probe/security/cleanup.ts +0 -125
- package/src/core/probe/security/detectors.ts +0 -71
- package/src/core/probe/security/digest.ts +0 -104
- package/src/core/probe/security/orchestrator.ts +0 -398
- package/src/core/probe/security/regression.ts +0 -103
- package/src/core/probe/security/types.ts +0 -151
- package/src/core/probe/security-probe-class.ts +0 -207
- package/src/core/probe/security-probe.ts +0 -32
- package/src/core/probe/shared.ts +0 -531
- package/src/core/probe/static-probe-class.ts +0 -125
- package/src/core/probe/types.ts +0 -165
- package/src/core/probe/verdict-aggregator.ts +0 -33
- package/src/core/probe/webhooks-probe.ts +0 -282
- package/src/core/reporter/console.ts +0 -240
- package/src/core/reporter/index.ts +0 -22
- package/src/core/reporter/json.ts +0 -22
- package/src/core/reporter/junit.ts +0 -93
- package/src/core/reporter/ndjson.ts +0 -37
- package/src/core/reporter/types.ts +0 -15
- package/src/core/runner/assertions.ts +0 -383
- package/src/core/runner/async-pool.ts +0 -108
- package/src/core/runner/auth-path.ts +0 -8
- package/src/core/runner/ci-context.ts +0 -72
- package/src/core/runner/executor.ts +0 -652
- package/src/core/runner/expr-eval.ts +0 -41
- package/src/core/runner/form-encode.ts +0 -41
- package/src/core/runner/http-client.ts +0 -224
- package/src/core/runner/learn-drift.ts +0 -293
- package/src/core/runner/preflight-vars.ts +0 -153
- package/src/core/runner/progress-tracker.ts +0 -73
- package/src/core/runner/rate-limiter.ts +0 -185
- package/src/core/runner/run-kind.ts +0 -45
- package/src/core/runner/schema-validator.ts +0 -308
- package/src/core/runner/send-request.ts +0 -232
- package/src/core/runner/transforms.ts +0 -65
- package/src/core/runner/types.ts +0 -94
- package/src/core/secrets/registry.ts +0 -164
- package/src/core/secrets/secrets-file.ts +0 -115
- package/src/core/selectors/operation-filter.ts +0 -144
- package/src/core/setup-api.ts +0 -590
- package/src/core/severity/category.ts +0 -94
- package/src/core/severity/index.ts +0 -58
- package/src/core/spec/infer-schema.ts +0 -102
- package/src/core/spec/layers.ts +0 -154
- package/src/core/spec/merge-specs.ts +0 -156
- package/src/core/spec/schema-from-runs.ts +0 -117
- package/src/core/spec/schema-overlay.ts +0 -130
- package/src/core/util/ajv.ts +0 -13
- package/src/core/util/format-eta.ts +0 -21
- package/src/core/util/headers.ts +0 -9
- package/src/core/util/url.ts +0 -24
- package/src/core/utils.ts +0 -13
- package/src/core/workspace/config.ts +0 -129
- package/src/core/workspace/fixture-gap-report.ts +0 -84
- package/src/core/workspace/fixture-gaps.ts +0 -71
- package/src/core/workspace/manifest.ts +0 -283
- package/src/core/workspace/output-rotation.ts +0 -62
- package/src/core/workspace/root.ts +0 -96
- package/src/core/workspace/triage-path.ts +0 -87
- package/src/db/lint-runs.ts +0 -47
- package/src/db/migrate.ts +0 -128
- package/src/db/migrations/0001_run_kind.sql +0 -25
- package/src/db/migrations/0002_run_kind_request.sql +0 -59
- package/src/db/migrations/sql.d.ts +0 -4
- package/src/db/queries/collections.ts +0 -133
- package/src/db/queries/coverage.ts +0 -9
- package/src/db/queries/dashboard.ts +0 -59
- package/src/db/queries/results.ts +0 -216
- package/src/db/queries/runs.ts +0 -289
- package/src/db/queries/sessions.ts +0 -42
- package/src/db/queries/settings.ts +0 -28
- package/src/db/queries/types.ts +0 -172
- package/src/db/queries.ts +0 -75
- package/src/db/schema.ts +0 -298
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,71 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.27.1] — 2026-07-09
|
|
8
|
+
|
|
9
|
+
m-27 Bucket E (agentic discoverability): metadata release — no engine changes.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- **Claude Code plugin / self-serve marketplace (ARV-395):**
|
|
13
|
+
`.claude-plugin/{plugin,marketplace}.json` — install skills via
|
|
14
|
+
`/plugin marketplace add kirrosh/zond`; skills mirrored to root
|
|
15
|
+
`skills/<name>/SKILL.md` (synced from init templates, drift-checked in
|
|
16
|
+
`bun run check`), also picked up by SkillsMP / `npx skills add kirrosh/zond`.
|
|
17
|
+
- **Agent discovery files (ARV-394):** `llms.txt` (machine index of docs) and
|
|
18
|
+
`context7.json` (Context7 config with agent rules) at the repo root.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
- **Agentic metadata (ARV-393, ARV-400):** canonical tagline in npm
|
|
22
|
+
`description`, task-shaped `keywords`, `repository`/`homepage`/`bugs` links;
|
|
23
|
+
agent-first README top (what → when → install → minimal example).
|
|
24
|
+
|
|
25
|
+
## [0.27.0] — 2026-07-09
|
|
26
|
+
|
|
27
|
+
m-27 start-distribution: every install channel works on a clean machine,
|
|
28
|
+
one-run release pipeline, cold-start onboarding pass. Engine untouched.
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
- **npm channel for node-only users (ARV-386):** the published package is a
|
|
32
|
+
thin node launcher (`bin/zond.mjs`) + `postinstall` that downloads the
|
|
33
|
+
platform binary from the matching GitHub release and verifies its sha256
|
|
34
|
+
against `checksums.txt` (`ZOND_DOWNLOAD_BASE` override for mirrors/E2E).
|
|
35
|
+
Zero runtime deps, no `src/` TS execution, no bun required.
|
|
36
|
+
- **Full platform matrix (ARV-388):** releases now ship `darwin-x64` and
|
|
37
|
+
`linux-arm64` on top of `darwin-arm64`/`linux-x64`/`win-x64`, cross-compiled
|
|
38
|
+
via `bun build --compile --target`. `install.sh` fails with a clear message
|
|
39
|
+
+ releases link instead of a raw 404; `install.ps1` falls back ARM64 → x64
|
|
40
|
+
with an emulation note.
|
|
41
|
+
- **One-run release pipeline (ARV-389):** tag push cross-compiles all 5
|
|
42
|
+
targets, adhoc-codesigns darwin, emits `checksums.txt`, attaches everything
|
|
43
|
+
to the GH release and publishes npm — documented in `docs/ci.md`. A brew
|
|
44
|
+
formula generator (`scripts/release/generate-brew-formula.mjs`) is in-repo
|
|
45
|
+
but the channel is deferred until first users (ARV-387); its pipeline step
|
|
46
|
+
self-skips while `TAP_GITHUB_TOKEN` is unset.
|
|
47
|
+
- **`zond audit --safe` (ARV-390):** explicit alias of the default safe mode
|
|
48
|
+
(docs and skills always said `--safe`, but the flag didn't exist — a
|
|
49
|
+
stranger's first command died on `unknown option`). Conflicts with `--live`.
|
|
50
|
+
- **Strict-TLS opt-in (ARV-367):** runtime HTTP keeps lax TLS by default
|
|
51
|
+
(internal/dev targets behind corp CAs); `ZOND_STRICT_TLS=1` turns
|
|
52
|
+
certificate verification on for public-API audits. Documented as a TLS
|
|
53
|
+
policy section in ZOND.md + the zond-checks skill.
|
|
54
|
+
- **Raw-apiKey hint (ARV-367):** `doctor` warns when a securityScheme is
|
|
55
|
+
`apiKey` in the `Authorization` header — set `auth_token` to the RAW key,
|
|
56
|
+
no `Bearer ` prefix.
|
|
57
|
+
|
|
58
|
+
### Fixed
|
|
59
|
+
- **Serializer dropped OPTIONS/HEAD/TRACE method keys (ARV-390):** emitted
|
|
60
|
+
probe-methods suites failed the runner's own validation and were skipped
|
|
61
|
+
with a scary warning on a stranger's first run. Empty `json: {}` bodies no
|
|
62
|
+
longer degrade to a bare `json:` (null). Round-trip regression tests added.
|
|
63
|
+
- **Cold-start dead-ends (ARV-390):** `init` next-steps now end at
|
|
64
|
+
`zond audit --api <name> --safe`; `doctor`'s all-set output points at the
|
|
65
|
+
same next action instead of stopping silently.
|
|
66
|
+
|
|
67
|
+
### Docs
|
|
68
|
+
- **README distribution pass (ARV-391):** install matrix (curl/npm/win/manual),
|
|
69
|
+
safe-by-default trust note above the fold, animated SVG terminal demo
|
|
70
|
+
(`docs/demo.svg`), one-liner positioning for strangers.
|
|
71
|
+
|
|
7
72
|
## [0.26.1] — 2026-07-09
|
|
8
73
|
|
|
9
74
|
Follow-up from the v0.26.0 petstore verify audit (report-zond findings).
|
package/README.md
CHANGED
|
@@ -1,19 +1,47 @@
|
|
|
1
1
|
# zond
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
API hygiene scanner for small teams and their coding agents — test REST API endpoints against the OpenAPI spec, catch contract drift, track coverage.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Use it when you need to:** test REST API endpoints from an OpenAPI spec,
|
|
6
|
+
verify an API contract after a deploy, debug a failing HTTP request with
|
|
7
|
+
stored run history, or raise endpoint coverage. Works standalone or through
|
|
8
|
+
a coding agent (Claude Code, Cursor) — say "test my API" and the agent
|
|
9
|
+
drives zond for you.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
curl -fsSL https://raw.githubusercontent.com/kirrosh/zond/master/install.sh | sh # or: npm i -g @kirrosh/zond
|
|
13
|
+
zond init && zond add api my-api --spec ./openapi.json
|
|
14
|
+
zond audit --api my-api --safe # read-only pass: spec lint → probes → tests → coverage → HTML report
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
> **Safe by default.** The first run (`zond audit --safe`) sends read-only
|
|
18
|
+
> GET traffic — no writes, no deletes, nothing destructive. Mutating
|
|
19
|
+
> probes require an explicit `--live` opt-in, meant for throwaway/sandbox
|
|
20
|
+
> accounts only. Running zond against your API won't break it.
|
|
21
|
+
|
|
22
|
+

|
|
6
23
|
|
|
7
24
|
Zond reads your OpenAPI spec and gives your AI agent everything it needs to test your API: a focused CLI, safety guardrails, coverage tracking, and run history. You don't need to learn anything new — just describe what you want and the agent runs `zond` commands.
|
|
8
25
|
|
|
9
|
-
##
|
|
26
|
+
## Install
|
|
10
27
|
|
|
11
|
-
|
|
28
|
+
| Channel | Command |
|
|
29
|
+
|---|---|
|
|
30
|
+
| **curl** (macOS/Linux) | `curl -fsSL https://raw.githubusercontent.com/kirrosh/zond/master/install.sh \| sh` |
|
|
31
|
+
| **npm** (needs Node 20+) | `npm install -g @kirrosh/zond` |
|
|
32
|
+
| **Windows** | `iwr https://raw.githubusercontent.com/kirrosh/zond/master/install.ps1 \| iex` |
|
|
33
|
+
| **Manual** | grab a binary from [releases](https://github.com/kirrosh/zond/releases/latest) (darwin arm64/x64, linux x64/arm64, win x64) |
|
|
34
|
+
| **Claude Code plugin** | `/plugin marketplace add kirrosh/zond` then `/plugin install zond@zond` — the agent skills without `zond init` |
|
|
35
|
+
| **Agent skills** ([skills.sh](https://www.skills.sh)) | `npx skills add kirrosh/zond` |
|
|
12
36
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
37
|
+
The plugin/skills channels ship the [five zond skills](skills/) (audit
|
|
38
|
+
pipeline, depth checks, fixture seeding, triage, target warm-up); the zond
|
|
39
|
+
binary itself still comes from any of the channels above.
|
|
40
|
+
|
|
41
|
+
Every channel ships the same self-contained binary — no Bun or Node
|
|
42
|
+
required at runtime (npm uses Node only as a thin launcher).
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
17
45
|
|
|
18
46
|
Bootstrap a workspace, register your first API, then fill its fixtures:
|
|
19
47
|
|
|
@@ -56,21 +84,13 @@ upstream spec changes.
|
|
|
56
84
|
|
|
57
85
|
Then say to your agent: _"Safely cover the API from openapi.json with tests."_
|
|
58
86
|
|
|
59
|
-
Want the whole pipeline at once? `zond audit --api my-api` runs
|
|
87
|
+
Want the whole pipeline at once? `zond audit --api my-api --safe` runs
|
|
60
88
|
prepare-fixtures → generate → probes → run → coverage → HTML report in a
|
|
61
|
-
single shot.
|
|
62
|
-
|
|
63
|
-
<details>
|
|
64
|
-
<summary>Other installation methods (npx)</summary>
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
npx -y @kirrosh/zond --version
|
|
68
|
-
```
|
|
89
|
+
single read-only shot (safe is the default even without the flag). Add
|
|
90
|
+
`--live` for the mutating stages once you're pointed at a sandbox.
|
|
69
91
|
|
|
70
92
|
See [ZOND.md](ZOND.md) for the full CLI reference.
|
|
71
93
|
|
|
72
|
-
</details>
|
|
73
|
-
|
|
74
94
|
## What Happens
|
|
75
95
|
|
|
76
96
|
1. **Point** — you give the agent an OpenAPI spec
|
|
@@ -117,9 +137,6 @@ curl -fsSL https://raw.githubusercontent.com/kirrosh/zond/master/install.sh | sh
|
|
|
117
137
|
|
|
118
138
|
# npm
|
|
119
139
|
npm install -g @kirrosh/zond@latest
|
|
120
|
-
|
|
121
|
-
# bun
|
|
122
|
-
bun install -g @kirrosh/zond@latest
|
|
123
140
|
```
|
|
124
141
|
|
|
125
142
|
## Shell completions
|
package/bin/zond.mjs
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Thin launcher: exec the platform binary fetched by scripts/npm/postinstall.mjs.
|
|
3
|
+
import { spawnSync } from 'node:child_process'
|
|
4
|
+
import { existsSync } from 'node:fs'
|
|
5
|
+
import { dirname, join } from 'node:path'
|
|
6
|
+
import { fileURLToPath } from 'node:url'
|
|
7
|
+
|
|
8
|
+
const bin = join(
|
|
9
|
+
dirname(fileURLToPath(import.meta.url)),
|
|
10
|
+
process.platform === 'win32' ? 'zond-bin.exe' : 'zond-bin',
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
if (!existsSync(bin)) {
|
|
14
|
+
console.error(
|
|
15
|
+
'zond binary is missing — the postinstall download likely failed.\n' +
|
|
16
|
+
'Re-run: npm rebuild @kirrosh/zond\n' +
|
|
17
|
+
'Or install another way: https://github.com/kirrosh/zond#install',
|
|
18
|
+
)
|
|
19
|
+
process.exit(1)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const result = spawnSync(bin, process.argv.slice(2), { stdio: 'inherit' })
|
|
23
|
+
process.exit(result.status ?? 1)
|
package/package.json
CHANGED
|
@@ -1,60 +1,73 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kirrosh/zond",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "API
|
|
3
|
+
"version": "0.27.1",
|
|
4
|
+
"description": "API hygiene scanner for small teams and their coding agents — test REST API endpoints against the OpenAPI spec, catch contract drift, track coverage.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"module": "index.ts",
|
|
7
6
|
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/kirrosh/zond.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/kirrosh/zond#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/kirrosh/zond/issues"
|
|
14
|
+
},
|
|
8
15
|
"keywords": [
|
|
9
|
-
"api",
|
|
10
|
-
"
|
|
16
|
+
"api-testing",
|
|
17
|
+
"rest-api",
|
|
11
18
|
"openapi",
|
|
12
|
-
"
|
|
19
|
+
"contract-testing",
|
|
20
|
+
"contract-drift",
|
|
21
|
+
"schema-validation",
|
|
22
|
+
"api-coverage",
|
|
23
|
+
"api-hygiene",
|
|
24
|
+
"coding-agents",
|
|
25
|
+
"ai-agents",
|
|
26
|
+
"claude-code",
|
|
27
|
+
"sarif",
|
|
13
28
|
"cli",
|
|
14
|
-
"rest",
|
|
15
29
|
"http"
|
|
16
30
|
],
|
|
17
31
|
"files": [
|
|
18
|
-
"
|
|
32
|
+
"bin/zond.mjs",
|
|
33
|
+
"scripts/npm/postinstall.mjs",
|
|
19
34
|
"README.md",
|
|
20
35
|
"LICENSE",
|
|
21
36
|
"CHANGELOG.md"
|
|
22
37
|
],
|
|
23
38
|
"bin": {
|
|
24
|
-
"zond": "
|
|
39
|
+
"zond": "bin/zond.mjs"
|
|
25
40
|
},
|
|
26
41
|
"scripts": {
|
|
27
42
|
"zond": "bun run src/cli/index.ts",
|
|
43
|
+
"postinstall": "node scripts/npm/postinstall.mjs",
|
|
28
44
|
"backlog": "bunx backlog",
|
|
29
45
|
"board": "bunx backlog board",
|
|
30
46
|
"test": "bun run test:unit && bun run test:mocked",
|
|
31
47
|
"test:unit": "bun test tests/",
|
|
32
48
|
"test:mocked": "bun run scripts/run-mocked-tests.ts",
|
|
33
|
-
"check": "tsc --noEmit --project tsconfig.json",
|
|
49
|
+
"check": "tsc --noEmit --project tsconfig.json && bun run scripts/sync-plugin-skills.ts --check",
|
|
34
50
|
"schemas": "bun run scripts/emit-json-schemas.ts",
|
|
35
51
|
"schemas:check": "bun run scripts/emit-json-schemas.ts --check",
|
|
36
52
|
"lint:dead": "knip --reporter compact",
|
|
37
|
-
"build": "bun build --compile src/cli/index.ts --outfile dist/zond && bun run scripts/codesign-darwin.ts ./dist/zond"
|
|
53
|
+
"build": "bun build --compile src/cli/index.ts --outfile dist/zond && bun run scripts/codesign-darwin.ts ./dist/zond",
|
|
54
|
+
"sync:plugin": "bun run scripts/sync-plugin-skills.ts"
|
|
38
55
|
},
|
|
39
56
|
"devDependencies": {
|
|
40
|
-
"@types/bun": "latest",
|
|
41
|
-
"ajv-draft-04": "^1.0.0",
|
|
42
|
-
"backlog.md": "^1.44.0",
|
|
43
|
-
"knip": "^6.7.0"
|
|
44
|
-
},
|
|
45
|
-
"engines": {
|
|
46
|
-
"bun": ">=1.1.0"
|
|
47
|
-
},
|
|
48
|
-
"peerDependencies": {
|
|
49
|
-
"typescript": "^5"
|
|
50
|
-
},
|
|
51
|
-
"dependencies": {
|
|
52
57
|
"@readme/openapi-parser": "^5.5.0",
|
|
58
|
+
"@types/bun": "latest",
|
|
53
59
|
"ajv": "^8.20.0",
|
|
60
|
+
"ajv-draft-04": "^1.0.0",
|
|
54
61
|
"ajv-formats": "^3.0.1",
|
|
62
|
+
"backlog.md": "^1.44.0",
|
|
55
63
|
"commander": "^14.0.0",
|
|
64
|
+
"knip": "^6.7.0",
|
|
56
65
|
"openapi-types": "^12.1.3",
|
|
66
|
+
"typescript": "^5",
|
|
57
67
|
"yaml": "^2.8.3",
|
|
58
68
|
"zod": "^4.3.6"
|
|
69
|
+
},
|
|
70
|
+
"engines": {
|
|
71
|
+
"node": ">=20"
|
|
59
72
|
}
|
|
60
73
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// npm postinstall: download the platform binary from the GitHub release
|
|
3
|
+
// matching this package version, verify its sha256, drop it next to the
|
|
4
|
+
// bin launcher. Pure node stdlib — the published package has zero deps.
|
|
5
|
+
import { createHash } from 'node:crypto'
|
|
6
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
7
|
+
import { dirname, join } from 'node:path'
|
|
8
|
+
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
9
|
+
|
|
10
|
+
const REPO = 'kirrosh/zond'
|
|
11
|
+
const PKG_DIR = join(dirname(fileURLToPath(import.meta.url)), '..', '..')
|
|
12
|
+
|
|
13
|
+
export function resolveTarget(platform = process.platform, arch = process.arch) {
|
|
14
|
+
const os = { darwin: 'darwin', linux: 'linux', win32: 'win' }[platform]
|
|
15
|
+
const cpu = { x64: 'x64', arm64: 'arm64' }[arch]
|
|
16
|
+
if (!os || !cpu || (os === 'win' && cpu !== 'x64')) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
`Unsupported platform: ${platform}-${arch}. Prebuilt binaries: https://github.com/${REPO}/releases`,
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
return `${os}-${cpu}`
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function sha256(buf) {
|
|
25
|
+
return createHash('sha256').update(buf).digest('hex')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function expectedChecksum(checksumsText, artifact) {
|
|
29
|
+
for (const line of checksumsText.split('\n')) {
|
|
30
|
+
const [hash, name] = line.trim().split(/\s+/)
|
|
31
|
+
if (name === artifact) return hash
|
|
32
|
+
}
|
|
33
|
+
throw new Error(`No entry for ${artifact} in checksums.txt`)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function download(url) {
|
|
37
|
+
const res = await fetch(url)
|
|
38
|
+
if (!res.ok) throw new Error(`Download failed (${res.status}): ${url}`)
|
|
39
|
+
return Buffer.from(await res.arrayBuffer())
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function main() {
|
|
43
|
+
if (process.env.ZOND_SKIP_DOWNLOAD) return
|
|
44
|
+
// Dev checkout (src/ is not shipped in the npm package) — nothing to download.
|
|
45
|
+
if (existsSync(join(PKG_DIR, 'src'))) return
|
|
46
|
+
|
|
47
|
+
const { version } = JSON.parse(readFileSync(join(PKG_DIR, 'package.json'), 'utf8'))
|
|
48
|
+
const target = resolveTarget()
|
|
49
|
+
const artifact = target === 'win-x64' ? `zond-${target}.exe` : `zond-${target}`
|
|
50
|
+
// ZOND_DOWNLOAD_BASE: mirror / clean-machine E2E override.
|
|
51
|
+
const base =
|
|
52
|
+
process.env.ZOND_DOWNLOAD_BASE || `https://github.com/${REPO}/releases/download/v${version}`
|
|
53
|
+
const [binary, checksums] = await Promise.all([
|
|
54
|
+
download(`${base}/${artifact}`),
|
|
55
|
+
download(`${base}/checksums.txt`),
|
|
56
|
+
])
|
|
57
|
+
|
|
58
|
+
const expected = expectedChecksum(checksums.toString('utf8'), artifact)
|
|
59
|
+
const actual = sha256(binary)
|
|
60
|
+
if (actual !== expected) {
|
|
61
|
+
throw new Error(`Checksum mismatch for ${artifact}: expected ${expected}, got ${actual}`)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const dest = join(PKG_DIR, 'bin', target === 'win-x64' ? 'zond-bin.exe' : 'zond-bin')
|
|
65
|
+
mkdirSync(dirname(dest), { recursive: true })
|
|
66
|
+
writeFileSync(dest, binary)
|
|
67
|
+
chmodSync(dest, 0o755)
|
|
68
|
+
console.log(`zond ${version} (${target}) ready`)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
72
|
+
main().catch((err) => {
|
|
73
|
+
console.error(`zond postinstall failed: ${err.message}`)
|
|
74
|
+
process.exit(1)
|
|
75
|
+
})
|
|
76
|
+
}
|
package/src/CLAUDE.md
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
# src/ — architecture map
|
|
2
|
-
|
|
3
|
-
Этот файл — точка входа в **код** zond. Workspace-контракт (`.api-fixtures.yaml` vs `.env.yaml`) — в [`../AGENTS.md`](../AGENTS.md), пользовательский CLI-референс — в [`../ZOND.md`](../ZOND.md).
|
|
4
|
-
|
|
5
|
-
zond — API hygiene scanner. **Dumb-tool**: умеет дёргать API, собирать evidence, проверять конформность спеки. Не зовёт LLM, не делает решения — это работа агента, который скармливает zond'у YAML и читает обратно отчёты.
|
|
6
|
-
|
|
7
|
-
### Litmus-тест: что кладём в zond, а что оставляем агенту
|
|
8
|
-
|
|
9
|
-
m-24 срезал эвристический слой (discovery/seed/cascade, severity-калибраторы, anti-FP-гейты, annotate-auto). Чтобы он не наползал обратно по одному «разумному» фиксу за раз — **каждое изменение zond проходит один тест: детерминировано ли оно?** Один и тот же вход → один и тот же выход, без догадок про намерение / вину / серьёзность / «баг ли это на самом деле».
|
|
10
|
-
|
|
11
|
-
- ✅ **В zond** (детерминированное, быстрое, скучное): слать запросы, валидировать схемы, считать диффы, эмитить evidence + closed-enum хинты, **корректно ограничивать scope чека** (какие case-kinds / методы он оценивает), плюс plumbing/скорость/артефакты. zond — удобный работающий быстрый инструмент.
|
|
12
|
-
- ❌ **Агенту** (суждение): severity, приоритет, атрибуция вины (spec vs backend), «это false-positive?», «это эксплуатируемо?», выдумывание фикстур, многопроходный discovery. Сложное решает умный агент, читая сырой evidence.
|
|
13
|
-
|
|
14
|
-
Практическое следствие для «zond что-то пропустил/зашумил» из аудита: **чини scope чека детерминированно** (напр. ARV-340 — чек смотрел не те case-kinds) — но **не добавляй suppression/down-rank «это FP»** (это ровно тот anti-FP-гейт, что убрал ARV-337; FP отсекает агент в триаже). `recommended_action` — самая размытая из выживших поверхностей: это тонкий routing-хинт, держи его тупым, не выращивай в мини-классификатор.
|
|
15
|
-
|
|
16
|
-
**Evidence-over-inference (ARV-376):** статические инференсеры по форме URL (какой `/list` владеет `{id}`, какой ресурс за `{code}`) имеют бесконечный хвост идиосинкразий спеков. **Не** закрывай хвост растущими хардкод-списками маркеров/глаголов (`LIST_VERB_SUFFIXES`, `ACCESSOR_MARKER_SEGS`, версии) — это ровно тот creep «по одному разумному за раз». Правило: **новый маркер/глагол добавляется только под реальный спек, который его упражняет**, никогда «на всякий случай» (так был убран спекулятивный `bycode`). А когда вывод неуверенный — не тупик (`miss-no-list`), а **`item.candidates`**: правдоподобные эндпоинты, ранжированные по структурной близости, БЕЗ выбора значения. Граф — детерминизм zond'а; выбор — суждение агента. Выравнивание двух слоёв, где один уже что-то делает (напр. version-strip, ARV-381), — это консистентность, не новое знание, и ок.
|
|
17
|
-
|
|
18
|
-
## Top-level layout
|
|
19
|
-
|
|
20
|
-
| Каталог | Назначение |
|
|
21
|
-
|---|---|
|
|
22
|
-
| `cli/` | CLI surface: парсинг argv, регистрация команд, форматирование вывода. |
|
|
23
|
-
| `core/` | Бизнес-логика: probes, checks, generators, runner, reporters. **Никакой зависимости от commander/process.argv** — это переиспользуемое ядро. |
|
|
24
|
-
| `db/` | SQLite-слой: schema, migrations, queries для истории runs/results. |
|
|
25
|
-
|
|
26
|
-
**Правило**: `cli/commands/<cmd>.ts` парсит флаги и зовёт функции из `core/`. Бизнес-логика в `cli/` — code-smell (см. ARV-257 про `bootstrap.ts`/`discover.ts`, которые лежат в `cli/commands/` но не регистрируют команды).
|
|
27
|
-
|
|
28
|
-
## cli/
|
|
29
|
-
|
|
30
|
-
| Файл | Что |
|
|
31
|
-
|---|---|
|
|
32
|
-
| `index.ts` | Entry point бинаря. |
|
|
33
|
-
| `program.ts` | Commander root: регистрирует все top-level команды. |
|
|
34
|
-
| `argv.ts`, `resolve.ts` | Аргумент-парсинг и `--api` chain resolution (per-command > global > `ZOND_API` > `.zond/current-api`). |
|
|
35
|
-
| `runtime.ts` | Глобальный runtime context (`api`, workspace paths, http auditor). |
|
|
36
|
-
| `output.ts`, `json-envelope.ts`, `json-schemas.ts` | Forматирование результатов: текстовый/JSON envelope + Ajv-валидация envelope-схем. |
|
|
37
|
-
| `status-filter.ts` | Общий парсер `--status` фильтров. |
|
|
38
|
-
| `commands/` | Один файл на команду; `commands/init/`, `commands/api/`, `commands/probe/` — кластеры с subcommands. |
|
|
39
|
-
|
|
40
|
-
Контракт команды: парсит флаги, валидирует через зависимости из `core/`, эмиттит результат через `output.ts` (envelope) или streaming-репортер.
|
|
41
|
-
|
|
42
|
-
## core/ — подсистемы
|
|
43
|
-
|
|
44
|
-
| Подкаталог | Роль |
|
|
45
|
-
|---|---|
|
|
46
|
-
| `parser/`, `spec/` | Парсинг OpenAPI, dereferenced spec.json, extraction схем. |
|
|
47
|
-
| `generator/` | Синтез тестовых YAML-сьютов из spec: `suite-generator.ts`, `data-factory.ts`, `resources-builder.ts`. |
|
|
48
|
-
| `runner/` | HTTP-исполнение: `executor.ts`, retry, assertions, schema validation. |
|
|
49
|
-
| `checks/` | Schemathesis-style depth checks (status_code_conformance, response_schema_conformance, idempotency, …). Орк — `checks/runner.ts`. Один файл = один check class. |
|
|
50
|
-
| `probe/` | Активные security/mass-assignment probes. Сейчас два монолита (`security-probe.ts`, `mass-assignment-probe.ts`) — кандидаты на split (ARV-295, ARV-296). |
|
|
51
|
-
| `lint/` | Static spec-lint (`check spec`). Не путать с `checks/` — это разные команды и разные envelope'ы. |
|
|
52
|
-
| `diagnostics/` | Triage финдингов: классификация ошибок, hints, `recommended_action` mapping. |
|
|
53
|
-
| `severity/` | Per-finding severity calibration (ARV-283–288 актуализирует). |
|
|
54
|
-
| `anti-fp/` | Anti-false-positive guard'ы; registry-pattern частично (см. ARV-259). |
|
|
55
|
-
| `coverage/` | Покрытие endpoint'ов: test-runs + audit-runs, dual-metric. |
|
|
56
|
-
| `reporter/` | Форматирование `Run`/`Check`/`Probe` результатов в текст/JSON/NDJSON/SARIF/JUnit/HTML. |
|
|
57
|
-
| `exporter/` | HTML-отчёты, case studies. |
|
|
58
|
-
| `audit/` | Высокоуровневая `audit` команда — wraps checks + probe + report для CI-smoke. |
|
|
59
|
-
| `workspace/` | Layout API-папки: `apis/<name>/{spec,catalog,resources,fixtures,env,secrets}`. |
|
|
60
|
-
| `context/`, `identity/`, `secrets/` | Загрузка контекста запуска, identity tokens, секреты. |
|
|
61
|
-
| `util/`, `utils.ts` | Общие хелперы. URL/headers/schema-валидация частично дублируются с `probe/shared.ts` — кандидат на консолидацию (ARV-297). |
|
|
62
|
-
| `selectors/`, `meta/`, `classifier/` | Endpoint-classification и meta-аттрибуты для дискавери и группировки. |
|
|
63
|
-
| `setup-api.ts` | Регистрация нового API в workspace (used by `add api`/`refresh-api`). |
|
|
64
|
-
|
|
65
|
-
## db/
|
|
66
|
-
|
|
67
|
-
SQLite на bun. `migrations/` — versioned migrations, `schema.ts` — текущий schema, `queries/` — типизированные SQL. Используется reporter'ами и `coverage` для исторических runs. Retention (ARV-266): `zond db stats` — счётчики строк per `run_kind`; `zond db prune` — opt-in удаление (per-kind defaults: check/probe/request/fixture старше 7d, `regular` — forever; `--older-than 30d` для uniform-cutoff), VACUUM после delete.
|
|
68
|
-
|
|
69
|
-
## Data-flow по фазам
|
|
70
|
-
|
|
71
|
-
zond работает по 5 фазам — это ментальная модель CLI и skills:
|
|
72
|
-
|
|
73
|
-
```
|
|
74
|
-
Setup ──► Generate ──► Run ──► Analyze ──► Report
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
| Фаза | Команды | Что происходит | Артефакты |
|
|
78
|
-
|---|---|---|---|
|
|
79
|
-
| **Setup** | `init`, `add api`, `refresh-api`, `use`, `doctor`, `prepare-fixtures` | Регистрируем API, тянем spec, заполняем `.env.yaml`. | `apis/<name>/{spec.json, .api-catalog.yaml, .api-resources.yaml, .api-fixtures.yaml, .env.yaml}` |
|
|
80
|
-
| **Generate** | `generate`, `api annotate`, `prepare-fixtures` | Синтез тестовых YAML из spec + аннотации (seed-bodies, idempotency, pagination, lifecycle). | `apis/<name>/tests/*.yaml`, annotations |
|
|
81
|
-
| **Run** | `run`, `session`, `request`, `audit`, `checks run`, `probe <class>` | Дергаем API: тесты, depth-checks, probes. Пишем runs/results в SQLite. | `runs/` (DB), HTTP-аудит |
|
|
82
|
-
| **Analyze** | `coverage`, `db {runs,run,collections,diagnose,compare}`, `check spec`, `describe`, `catalog` | Триаж результатов, coverage-гэпы, lint спеки. Финдинги через `recommended_action`. | Envelope JSON, finding-streams |
|
|
83
|
-
| **Report** | `report`, `report-bundle`, `--report {json,ndjson,sarif,junit,html,markdown}` | Конвертация runs/findings в shareable форматы. | NDJSON-stream, SARIF, HTML, JUnit |
|
|
84
|
-
|
|
85
|
-
Полная картина с iron-rules и pre-flight checklist'ами — в skill-документах (`src/cli/commands/init/templates/skills/*.md`), которые ставятся через `zond init`.
|
|
86
|
-
|
|
87
|
-
## Extension points
|
|
88
|
-
|
|
89
|
-
Когда добавляешь новую функциональность — это **типичные точки расширения**:
|
|
90
|
-
|
|
91
|
-
| Хочу добавить | Куда |
|
|
92
|
-
|---|---|
|
|
93
|
-
| Новый depth-check (schemathesis-style) | `core/checks/checks/<name>.ts` + регистрация в `core/checks/runner.ts`. |
|
|
94
|
-
| Новый probe-class (security/mass-assignment-like) | `core/probe/<class>/` подмодуль; subcommand в `cli/commands/probe/`. Не клади всё в один монолит — см. ARV-295/ARV-296. |
|
|
95
|
-
| Новый reporter format | `core/reporter/<format>.ts`; зарегистрировать в `cli/output.ts` или per-command `--report`. |
|
|
96
|
-
| Новый CLI флаг с envelope-выводом | `cli/commands/<cmd>.ts` + Ajv-схема в `cli/json-schemas.ts`. Envelope shape — единый, не плоди вариации. |
|
|
97
|
-
| Анти-FP guard для check/probe | `core/anti-fp/rules/<rule>.ts` (registry-pattern в развитии — ARV-259). |
|
|
98
|
-
| Новая diagnostic-hint | `core/diagnostics/` — closed-enum `recommended_action`, не магические строки. |
|
|
99
|
-
| Новая DB-сущность | `src/db/migrations/<NNNN>-<name>.sql` + tiped query в `db/queries/`. |
|
|
100
|
-
|
|
101
|
-
## Workspace contract (ссылка)
|
|
102
|
-
|
|
103
|
-
Артефакты в `apis/<name>/` (`spec.json` / `.api-catalog.yaml` / `.api-resources.yaml` / **`.api-fixtures.yaml` manifest** / **`.env.yaml` values**) — описаны в [`../AGENTS.md`](../AGENTS.md). Главное правило: **manifest — source of truth о списке переменных, env — только values**.
|
|
104
|
-
|
|
105
|
-
## Conventions
|
|
106
|
-
|
|
107
|
-
- TypeScript strict mode, `bun run check` = `tsc --noEmit` без warnings (`noUnusedLocals`/`noUnusedParameters` включены).
|
|
108
|
-
- Тесты — `bun test` (unit + integration), `bun run test:mocked` (HTTP-mocked).
|
|
109
|
-
- Сборка — `bun run build` → single-file `dist/zond` бинарь.
|
|
110
|
-
- Никаких `console.log` в `core/` — выводи через `cli/output.ts` или reporter slot.
|
|
111
|
-
- Никаких SDK Anthropic/Ollama/прочих LLM-провайдеров внутри zond — это dumb-tool (см. `feedback_zond_no_llm_calls`).
|
|
112
|
-
- Финдинги — через closed-enum `recommended_action`, агент триажит по enum, не по тексту message.
|
package/src/bun-types.d.ts
DELETED
package/src/cli/argv.ts
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pre-commander argv handling and shared argument parsers used across the
|
|
3
|
-
* commander tree. Pulled out of program.ts (TASK-190, m-11) so program.ts
|
|
4
|
-
* shrinks toward "just command registration" and these helpers can be
|
|
5
|
-
* unit-tested in isolation.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { InvalidArgumentError } from "commander";
|
|
9
|
-
import type { ReporterName } from "../core/reporter/types.ts";
|
|
10
|
-
|
|
11
|
-
// ── MSYS path preprocessing ──
|
|
12
|
-
//
|
|
13
|
-
// Git Bash on Windows converts API paths like "/users" → "C:/Program Files/Git/users".
|
|
14
|
-
// We reverse that for flags whose values are API paths, not filesystem paths.
|
|
15
|
-
|
|
16
|
-
const MSYS_PREFIX_RE = /^[A-Z]:[\\/](?:Program Files[\\/]Git|msys64|usr)[\\/]/i;
|
|
17
|
-
|
|
18
|
-
const API_PATH_FLAGS = new Set(["--path", "--json-path"]);
|
|
19
|
-
|
|
20
|
-
function stripMsysPath(value: string): string {
|
|
21
|
-
if (!MSYS_PREFIX_RE.test(value)) return value;
|
|
22
|
-
return value.replace(MSYS_PREFIX_RE, "/");
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Pre-process argv before commander sees it: undo Git Bash's MSYS path conversion
|
|
27
|
-
* for `--path` and `--json-path` values (both `--path X` and `--path=X` forms).
|
|
28
|
-
*/
|
|
29
|
-
export function preprocessArgv(argv: string[]): string[] {
|
|
30
|
-
const out = [...argv];
|
|
31
|
-
for (let i = 0; i < out.length; i++) {
|
|
32
|
-
const arg = out[i]!;
|
|
33
|
-
|
|
34
|
-
// --flag=value form
|
|
35
|
-
const eqIdx = arg.indexOf("=");
|
|
36
|
-
if (arg.startsWith("--") && eqIdx !== -1) {
|
|
37
|
-
const flag = arg.slice(0, eqIdx);
|
|
38
|
-
if (API_PATH_FLAGS.has(flag)) {
|
|
39
|
-
out[i] = `${flag}=${stripMsysPath(arg.slice(eqIdx + 1))}`;
|
|
40
|
-
}
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// --flag value form
|
|
45
|
-
if (API_PATH_FLAGS.has(arg)) {
|
|
46
|
-
const next = out[i + 1];
|
|
47
|
-
if (next !== undefined && !next.startsWith("-")) {
|
|
48
|
-
out[i + 1] = stripMsysPath(next);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return out;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// ── Argument parsers ──
|
|
56
|
-
|
|
57
|
-
export function parsePositiveInt(name: string): (raw: string) => number {
|
|
58
|
-
return (raw: string) => {
|
|
59
|
-
const n = Number.parseInt(raw, 10);
|
|
60
|
-
if (Number.isNaN(n) || n <= 0) {
|
|
61
|
-
throw new InvalidArgumentError(`Invalid ${name} value: ${raw}`);
|
|
62
|
-
}
|
|
63
|
-
return n;
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/** `--rate-limit` accepts a positive integer (req/sec cap) or the literal
|
|
68
|
-
* string `auto` (no static cap; throttle adaptively from ratelimit-* headers). */
|
|
69
|
-
export function parseRateLimit(raw: string): number | "auto" {
|
|
70
|
-
if (raw.toLowerCase() === "auto") return "auto";
|
|
71
|
-
const n = Number.parseInt(raw, 10);
|
|
72
|
-
if (Number.isNaN(n) || n <= 0) {
|
|
73
|
-
throw new InvalidArgumentError(`Invalid --rate-limit value: ${raw} (expected a positive integer or "auto")`);
|
|
74
|
-
}
|
|
75
|
-
return n;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function parseNonNegativeInt(name: string): (raw: string) => number {
|
|
79
|
-
return (raw: string) => {
|
|
80
|
-
const n = Number.parseInt(raw, 10);
|
|
81
|
-
if (Number.isNaN(n) || n < 0 || String(n) !== raw.trim()) {
|
|
82
|
-
throw new InvalidArgumentError(`Invalid ${name} value: ${raw} (expected a non-negative integer)`);
|
|
83
|
-
}
|
|
84
|
-
return n;
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export function parseInteger(name: string): (raw: string) => number {
|
|
89
|
-
return (raw: string) => {
|
|
90
|
-
const n = Number.parseInt(raw, 10);
|
|
91
|
-
if (Number.isNaN(n)) {
|
|
92
|
-
throw new InvalidArgumentError(`Invalid ${name} value: ${raw}`);
|
|
93
|
-
}
|
|
94
|
-
return n;
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export function parsePercentage(raw: string): number {
|
|
99
|
-
const n = Number.parseInt(raw, 10);
|
|
100
|
-
if (Number.isNaN(n) || n < 0 || n > 100) {
|
|
101
|
-
throw new InvalidArgumentError(`Invalid --fail-on-coverage value: ${raw} (must be 0–100)`);
|
|
102
|
-
}
|
|
103
|
-
return n;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export const collect = (val: string, prev: string[]): string[] => [...prev, val];
|
|
107
|
-
|
|
108
|
-
const VALID_REPORTERS = new Set<string>(["console", "json", "junit"]);
|
|
109
|
-
|
|
110
|
-
export function parseReporter(raw: string): ReporterName {
|
|
111
|
-
if (!VALID_REPORTERS.has(raw)) {
|
|
112
|
-
throw new InvalidArgumentError(`Unknown reporter: ${raw}. Available: console, json, junit`);
|
|
113
|
-
}
|
|
114
|
-
return raw as ReporterName;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/** Helper: split repeatable values like ["a,b", "c"] → ["a", "b", "c"] */
|
|
118
|
-
export function flatSplit(values: string[] | undefined): string[] | undefined {
|
|
119
|
-
if (!values || values.length === 0) return undefined;
|
|
120
|
-
const out = values.flatMap((v) => v.split(",")).filter(Boolean);
|
|
121
|
-
return out.length > 0 ? out : undefined;
|
|
122
|
-
}
|