diff --git a/openspec/changes/add-validation-findings-report/.openspec.yaml b/openspec/changes/add-validation-findings-report/.openspec.yaml new file mode 100644 index 0000000000..d160e09cf5 --- /dev/null +++ b/openspec/changes/add-validation-findings-report/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-08-21 diff --git a/openspec/changes/add-validation-findings-report/design.md b/openspec/changes/add-validation-findings-report/design.md new file mode 100644 index 0000000000..457c330625 --- /dev/null +++ b/openspec/changes/add-validation-findings-report/design.md @@ -0,0 +1,188 @@ +## Context + +See `proposal.md` for motivation and measured output size. Bulk validation currently has one documented JSON contract: top-level `version: "1.0"`, a complete `items` array for the requested scope, `summary`, and `root`. Human bulk output lists every item before totals. + +The preserved feasibility candidate proves that completed validation results can be projected while retaining totals, severities, scope, and exit status. It is not the proposed contract: the candidate reused `items` under top-level version `1.0`, which could let a consumer interpret a subset as the complete scope. + +Live main currently has no top-level validation advisory collection outside the item results. Two open PRs affect the rebase gate rather than this proposal's current schema. #1710 adds `INFO` issues inside item records, which the whole-record projection naturally retains. #1698 proposes a top-level `overlaps` advisory collection; if it lands before implementation, the proposal artifacts must be updated to name `overlaps` explicitly and define its JSON field and human section before code is written. + +## Goals / Non-Goals + +**Goals:** + +- Reduce human and agent-facing output when a bulk validation scope is dominated by clean items. +- Preserve the current complete report as the default and as explicit `full` mode. +- Give JSON findings an exact discriminator and a document that is intentionally distinct from full v1. +- Preserve complete item records, item order, issue detail and severity, requested scope, summary totals, root selection, and exit status. +- Reject ambiguous report requests before prompts, root selection, progress UI, or validation work. + +**Non-Goals:** + +- Improving validation runtime or skipping validation work for valid requests. +- Changing validation rules, strict-mode semantics, concurrency, full-report ordering, or exit codes. +- Adding summary-only output, alternate serializers, TOON, a general output framework, project defaults, or new dependencies. +- Changing omitted-`--report` targeted, interactive, or mixed-flag behavior. +- Automatically copying unknown future top-level report fields into the findings document. + +## Decisions + +### 1. Use one bulk report selector; keep serialization orthogonal + +`--report` accepts `full` and `findings`. Omitting it preserves every existing command flow. Explicit `--report full` and `--report findings` are bulk-report selectors: both require an explicit, unambiguous bulk scope and neither is accepted with an item name. In particular, `openspec validate --report full` is intentionally rejected rather than treated as a targeted alias. + +This keeps report content separate from serialization: `--report findings` selects the findings contract, while `--json` serializes that contract. Help text is `Select bulk report content: full|findings; combine with --json for JSON`. + +The existing CLI has command-specific projections (`--deltas-only`, `--requirements`, and `--no-scenarios`) but no generic `--only`, `--report`, or `--format` vocabulary. `--findings-only` and `--only findings` read like in-place filters on the existing JSON document. `--report findings` makes the separately versioned document intentional and avoids adding more booleans if another report contract is justified later. + +### 2. Resolve active scope combinations and reject archive ambiguity + +For an explicit report request, the canonical scope is resolved as follows: + +| Input flags | Canonical scope | +|---|---| +| `--changes` | `changes` | +| `--specs` | `specs` | +| `--changes --specs` | `all` | +| `--all`, including `--all` plus either active subset | `all` | +| `--archived` | `archived` | + +`--archived` combined with any active scope flag is rejected. An item name combined with any explicit report option is rejected, whether or not a bulk flag is also present. An explicit report option without a bulk scope and an unsupported report value are also rejected. Omitted `--report` retains current precedence and behavior, including existing mixed-flag behavior; this proposal does not retroactively tighten old invocations. + +### 3. Fail invalid report requests before doing work + +Report mode and scope are normalized before root resolution or validation. Invalid human requests write a targeted error to stderr, write nothing to stdout, render no prompt or spinner, perform no validation, and exit 1. + +With `--json`, every invalid report request writes exactly one JSON document to stdout, writes no human text to either stream, performs no root resolution or validation, and exits 1: + +```json +{ + "status": [ + { + "severity": "error", + "code": "invalid_validation_report_request", + "message": "The requested validation report and scope cannot be combined.", + "fix": "Use --report full|findings with one active bulk scope or --archived, without an item name." + } + ] +} +``` + +The `code` is stable. The message may identify the specific conflict while retaining that code and one-status-entry shape. + +### 4. Use a distinct item-findings JSON document + +`--json --report findings` returns: + +```json +{ + "report": { + "kind": "validation-findings", + "version": "1.0", + "scope": "archived", + "returnedItems": 19, + "totalItems": 895 + }, + "itemFindings": [ + { + "id": "example-change", + "type": "change", + "valid": false, + "issues": [ + { + "level": "ERROR", + "path": "tasks.md", + "message": "4 incomplete tasks (15/19 completed)" + } + ], + "durationMs": 3 + } + ], + "summary": { + "totals": { "items": 895, "passed": 876, "failed": 19 }, + "byType": { + "change": { "items": 895, "passed": 876, "failed": 19 } + } + }, + "root": { + "path": "", + "source": "nearest" + } +} +``` + +The typed projection is exactly the full result's item records filtered by `item.issues.length > 0`. It preserves full-report order and returns each selected record whole rather than rebuilding a fixed field list, so current fields and future additive item fields survive. `report.returnedItems` equals `itemFindings.length`; `report.totalItems` equals `summary.totals.items`. `ERROR`, `WARNING`, and `INFO` all count as item findings, regardless of whether the item's `valid` field is true. + +The findings document has no top-level `items` or top-level `version`, and it carries the exact `report.kind: "validation-findings"` discriminator and exact JSON-string `report.version: "1.0"`. Contract tests assert the version value and its string type. Tests also assert that the document does not conform to the documented full-v1 contract, which requires top-level `version: "1.0"` and a complete `items` array. No claim is made about how arbitrary permissive parsers behave. + +Live main has no additional top-level advisory collection to include. The implementation does not generically spread unknown full-result fields. At the rebase gate, each then-current top-level section must be inventoried and either explicitly named in the findings contract or deliberately excluded with maintainer review. If #1698 has landed, `overlaps` must remain a separate top-level advisory collection; it is not renamed to `itemFindings` and does not affect `returnedItems`. + +JSON findings emit exactly one document on stdout and no stderr text. + +### 5. Define human findings sections and order each stream independently + +Human findings preserve stream ownership, but stdout and stderr may be buffered or interleaved by the caller. The contract therefore defines ordering independently within each stream and makes no relative-order promise between a stdout section and a stderr section. + +Within stdout, sections appear in this order: + +1. `Scope:` line. +2. If `itemFindings` is empty, `No item findings.`; otherwise there is no item row or item block on stdout. +3. `Totals:` for the complete scope. +4. The existing first-failure `Details:` command for active scopes when one is currently provided; findings mode does not invent a details line for archived scope. + +Within stderr, sections appear in this order: + +1. Item-finding blocks in full-report item order. Each block prints its item heading once, followed by every issue in issue order with its original `ERROR`, `WARNING`, or `INFO` label, path, and message. All three severities use stderr. +2. Any advisory section explicitly named at the implementation rebase gate. If #1698 lands, the `overlaps` section follows item-finding blocks on stderr and remains distinct from item findings. + +Clean item rows are omitted. `No item findings.` says nothing about separately rendered advisories. Tests capture and assert each stream independently rather than asserting a merged stdout/stderr sequence. A valid findings request may retain existing progress behavior, which is outside this final-report per-stream ordering contract; the invalid-request path never renders progress UI. + +### 6. Use one typed projector for active and archived results + +Active and archived validation currently assemble similar result/summary envelopes on separate paths. Implementation defines one typed findings projection over the shared full-result contract and routes both paths through it. This prevents scope, ordering, whole-record preservation, and returned/total count rules from drifting. Human and JSON renderers consume that same projection; they do not independently filter. + +### 7. Keep verdict, root, and platform behavior unchanged + +For valid requests, findings mode validates the same requested items as full mode. `summary` is the full-scope summary and exit status is identical for the same scope and strictness. Warning- and info-only records remain visible even when they do not fail a non-strict run. + +The report uses the same resolved repo or store root and native path values as full validation. No path construction or rewriting is introduced. The `--report` flag is registered on every currently supported completion surface: Bash, Zsh, Fish, and PowerShell. Only Zsh and Fish suggest the fixed `full` and `findings` values because only those existing generators consume registry value metadata. Bash and PowerShell remain unchanged beyond flag registration. This proposal does not add a completion capability or broaden the set of generators; any additional shell or agent completion surface requires separate justification. + +## Alternatives Considered + +### Reuse full-v1 `items` with only issue-bearing records + +Rejected. Projection metadata does not undo the documented meaning of the complete `items` collection; a consumer can silently undercount clean items. + +### Introduce projected `items` in a new full JSON version + +Rejected for this contribution. A v2 union can be safe, but it creates a broader protocol migration for a narrow projection. A separate discriminator and `itemFindings` collection avoid changing full v1. + +### Human-only compact output + +Rejected as the recommendation. It is the smallest surface, but leaves the structured agent/log use case unsolved. + +### Use `--findings-only` or `--only findings` + +Rejected. Both frame the behavior as filtering the existing output shape. The report selector makes the distinct JSON contract intentional and composes with `--json` as content plus serialization. + +### Document external filtering only + +Safe and still supported. Callers can filter full JSON through `jq` or PowerShell, but the complete document still crosses the CLI boundary and each integration must recreate scope, summary, and exit-code discipline. + +### Add summary mode or a general output framework + +Rejected. Summary-only output omits actionable item findings. Alternate serializers, preferences, and frameworks expand maintenance and compatibility risk without evidence they are required. + +## Risks / Trade-offs + +- **A second JSON report contract is durable API surface.** Mitigation: one exact discriminator/version, one item projector, and reuse of full item records, summary, and root. +- **Output savings depend on corpus shape.** The measured matrix ranged from 4.9% on an issue-dense synthetic human case to 95.7% on the real 895-change archive. The 6,740-byte figure belongs to the feasibility candidate, not this exact envelope. Mitigation: claim output reduction only and remeasure the implemented envelope. +- **Item findings can be confused with top-level advisories.** Mitigation: `itemFindings`, `No item findings.`, separate advisory sections, and counts that cover item records only. +- **Unknown top-level fields could be dropped.** Mitigation: a required rebase inventory and explicit named-section decisions; no unbounded generic preservation promise. +- **Active and archived paths could drift.** Mitigation: one typed projector and shared contract tests. + +## Migration Plan + +- Ship as an additive option with no persisted configuration. +- Existing invocations and documented full-v1 parsers continue using the unchanged full report. +- New callers opt in and parse `report.kind: "validation-findings"` plus `itemFindings`. +- A rollback removes the option without migrating data or restoring files. diff --git a/openspec/changes/add-validation-findings-report/proposal.md b/openspec/changes/add-validation-findings-report/proposal.md new file mode 100644 index 0000000000..cc82f807d0 --- /dev/null +++ b/openspec/changes/add-validation-findings-report/proposal.md @@ -0,0 +1,29 @@ +## Why + +Bulk validation currently prints one result for every item in scope, including clean items. That complete report is useful for audit and automation, but it can dominate agent context and CI logs in large, mostly-clean repositories. In one real 895-change archive, the complete JSON report was 157,396 bytes while a feasibility candidate's projected-v1 envelope was 6,740 bytes (95.7% smaller) with all 19 failures and the same exit status. The proposed envelope is different and may have a slightly different byte count; savings vary with issue density. This is evidence about output volume, not validation runtime. + +## What Changes + +- Add an opt-in `--report ` mode to explicit bulk validation scopes: `--all`, `--changes`, `--specs`, and `--archived`. +- Keep the current human and JSON output unchanged when `--report` is omitted or set to `full`. +- In findings mode, project complete item records whose `issues.length > 0` into `itemFindings`, preserving full-report order, every issue severity, and all current or future additive item fields. +- Give JSON findings an exact `report.kind: "validation-findings"` discriminator and exact JSON-string `report.version: "1.0"`. It does not reuse the full-v1 `items` field or claim conformance with that document. +- Keep top-level advisories distinct from item findings and explicitly name any such sections that exist after the required implementation rebase. +- Require an explicit, non-conflicting bulk scope for either report value. Invalid JSON/report combinations return one stable structured diagnostic before root selection, prompts, spinners, or validation. + +## Capabilities + +### New Capabilities + +_None._ + +### Modified Capabilities + +- `cli-validate`: Add a compatibility-safe, opt-in findings report for bulk human and JSON validation output. + +## Impact + +- **Public CLI:** one additive report option on bulk `openspec validate`; no default behavior change. +- **JSON consumers:** the existing full-v1 complete-`items` document remains unchanged. Consumers choosing findings mode parse a separately identified schema with `itemFindings`. +- **Documentation and completions:** document the two report modes, their scope rules, and the findings JSON envelope; register `--report` on the existing Bash, Zsh, Fish, and PowerShell completion surfaces, with fixed `full`/`findings` value suggestions only in Zsh and Fish. +- **Implementation follow-up:** validation command output, CLI option registration, completions, and focused tests. No new dependency or project-level preference is proposed. diff --git a/openspec/changes/add-validation-findings-report/specs/cli-validate/spec.md b/openspec/changes/add-validation-findings-report/specs/cli-validate/spec.md new file mode 100644 index 0000000000..4be2e2984d --- /dev/null +++ b/openspec/changes/add-validation-findings-report/specs/cli-validate/spec.md @@ -0,0 +1,166 @@ +## ADDED Requirements + +### Requirement: Bulk validation SHALL provide an opt-in item-findings report + +The `validate` command SHALL support `--report full` and `--report findings` for explicit, unambiguous bulk scopes. Omitting `--report` SHALL retain current targeted, interactive, bulk, human, and JSON behavior. Findings mode SHALL return whole issue-bearing item records separately from top-level advisories while preserving full item order, complete requested-scope totals, root selection, issue severities, strict-mode semantics, and exit status. + +#### Scenario: Default and explicit bulk full output remain compatible + +- **WHEN** a user runs bulk validation without `--report` or with `--report full` +- **THEN** human output SHALL retain the current complete item listing and totals +- **AND** JSON output SHALL retain the documented full-v1 top-level `version: "1.0"` and complete `items` collection +- **AND** the two bulk invocations SHALL have equivalent observable output and exit status for the same scope + +#### Scenario: Explicit report values select a bulk report + +- **WHEN** a user supplies `--report full` or `--report findings` with exactly one resolvable bulk scope and no item name +- **THEN** validation SHALL run that bulk report without prompting for a scope + +#### Scenario: Explicit report values do not alias targeted or interactive flows + +- **WHEN** a user supplies an explicit report value with an item name or without a bulk scope +- **THEN** validation SHALL reject the request rather than treating explicit `full` as a targeted or interactive alias + +#### Scenario: A changes-only report retains changes scope + +- **WHEN** a findings report request uses `--changes` alone +- **THEN** `report.scope` SHALL be `changes` + +#### Scenario: A specs-only report retains specs scope + +- **WHEN** a findings report request uses `--specs` alone +- **THEN** `report.scope` SHALL be `specs` + +#### Scenario: Combined active scopes normalize to all + +- **WHEN** a findings report request uses `--changes --specs`, `--all`, or `--all` with either active subset flag +- **THEN** the complete active scope SHALL be validated and `report.scope` SHALL be `all` + +#### Scenario: Archived and active scopes cannot be combined for a report + +- **WHEN** a user supplies `--archived` with `--all`, `--changes`, or `--specs` and an explicit report value +- **THEN** validation SHALL reject the request rather than choosing one scope by precedence +- **AND** SHALL NOT validate either scope + +#### Scenario: Invalid human report requests fail before work + +- **WHEN** a non-JSON request has an item/report conflict, archived/active conflict, missing bulk scope, or unsupported report value +- **THEN** validation SHALL write a targeted diagnostic to stderr and nothing to stdout +- **AND** SHALL exit with code 1 +- **AND** SHALL NOT resolve a root, prompt, render a spinner, or validate any item + +#### Scenario: Invalid JSON report requests return one stable diagnostic + +- **WHEN** a JSON request has an item/report conflict, archived/active conflict, missing bulk scope, or unsupported report value +- **THEN** stdout SHALL contain exactly one JSON document with exactly one `status` entry +- **AND** that entry SHALL have `severity: "error"` and stable `code: "invalid_validation_report_request"` +- **AND** it SHALL include a targeted `message` and corrective `fix` +- **AND** no human text SHALL be written to stdout or stderr +- **AND** validation SHALL exit with code 1 without resolving a root, prompting, rendering a spinner, or validating any item + +#### Scenario: Findings JSON uses an exact distinct contract + +- **WHEN** validation runs with `--json --report findings` +- **THEN** stdout SHALL contain exactly one parseable JSON document and stderr SHALL be empty +- **AND** `report.kind` SHALL equal `validation-findings` +- **AND** `report.version` SHALL be the JSON string `"1.0"` +- **AND** `report` SHALL include canonical `scope`, `returnedItems`, and `totalItems` +- **AND** `summary` SHALL contain totals for the complete requested scope +- **AND** `root` SHALL retain the current resolved-root envelope + +#### Scenario: Findings JSON is not the documented full-v1 document + +- **WHEN** validation runs with `--json --report findings` +- **THEN** the document SHALL NOT contain a top-level `items` field +- **AND** SHALL NOT contain the full-v1 top-level `version` field +- **AND** contract tests SHALL reject it against the documented full-v1 shape requiring top-level `version: "1.0"` and complete `items` +- **AND** compatibility assertions SHALL be limited to documented full-v1 conformance, leaving undocumented permissive parser behavior outside this contract + +#### Scenario: Item findings project whole issue-bearing records + +- **GIVEN** the corresponding full result has item records in a defined order +- **WHEN** findings JSON is produced +- **THEN** `itemFindings` SHALL equal those full item records filtered by `issues.length > 0` +- **AND** record order and issue order SHALL match the full result +- **AND** each selected record SHALL preserve every current field and future additive field from that full item record +- **AND** clean item records SHALL be omitted + +#### Scenario: Every item issue severity counts as an item finding + +- **GIVEN** separate item records containing only `ERROR`, only `WARNING`, or only `INFO` issues +- **WHEN** findings mode is produced +- **THEN** all three records SHALL appear in `itemFindings` +- **AND** every issue SHALL retain its original severity, path, and message +- **AND** `valid` and exit behavior SHALL remain whatever full mode reports under the same strictness + +#### Scenario: Item counts exclude top-level advisories + +- **WHEN** findings JSON is produced +- **THEN** `report.returnedItems` SHALL equal `itemFindings.length` +- **AND** `report.totalItems` SHALL equal `summary.totals.items` +- **AND** separately named top-level advisory records SHALL NOT increase either item count + +#### Scenario: Zero item findings in a non-empty scope remain auditable + +- **GIVEN** the requested bulk scope contains one or more items and none has an issue +- **WHEN** validation runs with `--json --report findings` +- **THEN** `itemFindings` SHALL be an empty array and `report.returnedItems` SHALL be `0` +- **AND** `report.totalItems`, `report.scope`, `summary`, and `root` SHALL still identify the complete validated scope +- **AND** the successful exit status SHALL match full mode for the same scope + +#### Scenario: Empty JSON scope is explicit and successful + +- **GIVEN** the selected bulk scope contains no items +- **WHEN** validation runs with `--json --report findings` +- **THEN** `itemFindings` SHALL be empty, item counts and summary totals SHALL be zero, and scope and root SHALL remain explicit +- **AND** validation SHALL preserve the current successful empty-scope exit status + +#### Scenario: Human findings use independently ordered streams + +- **GIVEN** a bulk scope with issue-bearing and clean item records +- **WHEN** validation runs with `--report findings` and without `--json` +- **THEN** within stdout the final report SHALL emit `Scope:` first, followed by complete-scope `Totals:`, followed by any existing active-scope first-failure `Details:` command +- **AND** within stderr the final report SHALL emit item-finding blocks in full item order, with each item heading followed by all issues in issue order +- **AND** `ERROR`, `WARNING`, and `INFO` labels, paths, and messages SHALL all be emitted to stderr +- **AND** clean item rows SHALL be omitted +- **AND** within stderr any explicitly named advisory section SHALL be emitted after item-finding blocks +- **AND** archived scope SHALL NOT gain a new details command +- **AND** no relative ordering between stdout and stderr sections SHALL be required + +#### Scenario: Human output distinguishes no item findings from advisories + +- **GIVEN** no item record has an issue +- **WHEN** validation runs with `--report findings` and without `--json` +- **THEN** within stdout `No item findings.` SHALL be emitted after `Scope:` and before `Totals:` +- **AND** any explicitly named advisory section SHALL still be emitted separately to stderr +- **AND** `No item findings.` SHALL NOT assert that no top-level advisory exists +- **AND** no relative ordering between that stderr advisory and stdout sections SHALL be required + +#### Scenario: Human empty scope is explicit and successful + +- **GIVEN** the selected bulk scope contains no items +- **WHEN** validation runs with `--report findings` and without `--json` +- **THEN** within stdout the report SHALL contain zero-item `Scope:`, `No item findings.`, and zero `Totals:` in that order +- **AND** validation SHALL preserve the current successful empty-scope exit status + +#### Scenario: Full and findings verdicts remain equal + +- **GIVEN** the same bulk scope, root, inputs, and strictness +- **WHEN** full mode and findings mode run +- **THEN** both modes SHALL validate the same items +- **AND** SHALL produce the same complete summary totals and exit status +- **AND** store and archived scopes SHALL inspect exactly the items their corresponding full invocations inspect + +#### Scenario: Completion support follows existing shell capabilities + +- **WHEN** completion output is generated for the currently supported Bash, Zsh, Fish, and PowerShell surfaces +- **THEN** the `--report` flag SHALL be registered on all four surfaces +- **AND** Zsh and Fish SHALL suggest the fixed values `full` and `findings` +- **AND** Bash and PowerShell SHALL remain unchanged beyond registering the flag and SHALL NOT be required to suggest fixed values +- **AND** this change SHALL NOT add another completion generator or completion capability + +#### Scenario: Findings output is cross-platform + +- **WHEN** the same findings validation scenario runs on Windows, macOS, and Linux +- **THEN** report selection, projection, totals, severities, streams, and exit status SHALL be equivalent +- **AND** paths in item records or the root envelope SHALL retain the platform-native form used by full validation diff --git a/openspec/changes/add-validation-findings-report/tasks.md b/openspec/changes/add-validation-findings-report/tasks.md new file mode 100644 index 0000000000..8e5ce7d020 --- /dev/null +++ b/openspec/changes/add-validation-findings-report/tasks.md @@ -0,0 +1,33 @@ +## 1. Request and scope contract + +- [ ] 1.1 Add `--report ` to bulk `validate` help and registration, leave omitted-report behavior unchanged, and verify explicit `--report full` and `--report findings` require a bulk scope without an item name +- [ ] 1.2 Implement one typed request normalizer before root resolution that maps `--changes` to `changes`, `--specs` to `specs`, `--changes --specs` and `--all` plus active subsets to `all`, and `--archived` to `archived`; verify archived+active, item+report, missing-scope, and unsupported-value requests are rejected before validation +- [ ] 1.3 Emit invalid human requests only to stderr and invalid JSON requests as one stdout document with one `status` entry and stable code `invalid_validation_report_request`; verify exit 1, empty opposite streams, and absence of root resolution, prompts, spinners, and validator calls +- [ ] 1.4 Register the `--report` flag on the existing Bash, Zsh, Fish, and PowerShell completion outputs; add fixed `full`/`findings` value suggestions only to Zsh and Fish, leave Bash and PowerShell unchanged beyond flag registration, and verify no completion capability or generator is added + +## 2. Shared item projection and renderers + +- [ ] 2.1 Define one typed projector used by active and archived validation that derives `itemFindings` with `full.items.filter(item => item.issues.length > 0)`, preserving full item order, issue order, and whole item records including additive fields; verify both paths use it rather than filtering independently +- [ ] 2.2 Produce the exact findings JSON contract with `report.kind: "validation-findings"`, JSON-string `report.version: "1.0"`, scope/item counts, `itemFindings`, complete `summary`, and `root`; omit full-v1 top-level `items` and `version` +- [ ] 2.3 Implement human findings with independently ordered streams: stdout `Scope:` -> optional `No item findings.` -> `Totals:` -> existing active `Details:`; stderr item blocks/all severities -> explicitly named advisories; add tests that capture each stream independently and make no merged stdout/stderr ordering assertion +- [ ] 2.4 Preserve full-scope validation work, totals, root, strictness, and exit status in findings mode, and verify ERROR-, WARNING-, INFO-only, no-item-finding, empty-scope, failure, active, archived, and selected-store cases + +## 3. Rebase and compatibility gate + +- [ ] 3.1 Rebase before implementation, inventory the then-current typed full-result top-level sections, and update proposal/design/spec/tasks to name every additional section included in findings mode rather than generically copying unknown fields +- [ ] 3.2 If #1698 has landed, add `overlaps` as an explicitly named top-level advisory JSON field and human stderr section that does not affect item counts; if #1710 has landed, verify INFO-bearing full item records appear unchanged in `itemFindings` +- [ ] 3.3 Add human-byte and normalized-JSON compatibility tests proving omitted `--report` and explicit bulk `--report full` preserve current output for active, spec, archived, empty, and selected-store scopes while ignoring expected timing-field variation between runs +- [ ] 3.4 Add contract tests proving `report.version` is exactly the JSON string `"1.0"` and findings output does not conform to the documented full-v1 shape requiring top-level `version: "1.0"` and complete `items`; do not assert failure behavior for arbitrary undocumented parsers + +## 4. Documentation and release tracking + +- [ ] 4.1 Document report-versus-serialization semantics, canonical/invalid scope combinations, independent within-stream human section ordering, the exact findings JSON and invalid-request JSON documents, item/advisory distinction, exit codes, and the unchanged full-v1 contract +- [ ] 4.2 Document external `jq` and PowerShell filtering as compatible alternatives for existing releases and explain that findings mode reduces emitted output but does not claim faster validation +- [ ] 4.3 Add the appropriate release changeset with the implementation PR and verify release tracking passes; do not add a changeset to the proposal-only PR + +## 5. Verification + +- [ ] 5.1 Run focused validate command, archived validation, completion, store-root, structured-error, and CLI end-to-end tests and verify all pass +- [ ] 5.2 Run build, full tests, TypeScript checks, lint, and `git diff --check`, and verify all repository checks pass +- [ ] 5.3 Run `openspec validate add-validation-findings-report --strict` and reconcile implementation and documentation against every scenario before marking the change complete +- [ ] 5.4 Re-run the bounded real-corpus measurement against the implemented `itemFindings` envelope, verify default/full compatibility and complete item findings/totals/exit status, and report the new bytes separately from the 6,740-byte feasibility candidate without a runtime claim