test(voyage): add annotation roundtrip + rollback + source_annotations integration — v4.2 Step 7

Implements SC2/SC3/SC5b/SC7 + additive-field invariant for the v4.2
annotation pipeline:

Fixtures (tests/fixtures/annotation/):
  - annotation-brief.md           — brief-validator-clean fixture
  - annotation-plan.md            — plan-validator-clean (2 steps)
  - annotation-review.md          — review-validator-clean
  - annotation-plan-large.md      — 51 steps (SC3 scale fixture)

Integration tests:
  - tests/integration/annotation-roundtrip.test.mjs — 7 cases:
    SC2 byte-identical empty round-trip across brief/plan/review,
    SC3 scale (51 steps + 100 anchors) round-trip,
    SC7 parseAnchors(stripAnchors(addAnchors(...))) === [] per target.
  - tests/integration/schema-rollback.test.mjs — 4 cases:
    SC5b validator-FAIL -> revisionGuard rolls back byte-identical
    (sha256 invariant) for brief/plan/review + cross-target sweep.
    .local.bak deleted on rollback path (validator-PASS path tested
    in lib/util/revision-guard tests).
  - tests/lib/source-annotations.test.mjs — 6 cases mirroring
    tests/lib/source-findings.test.mjs additive-field pattern: each
    validator (brief/plan/review) accepts source_annotations as
    additive-optional, parser extracts as array of dicts, entries
    conform to documented shape, baseline forward-compat (artifacts
    without source_annotations still validate).

Verify: node --test tests/integration/annotation-roundtrip.test.mjs
       tests/integration/schema-rollback.test.mjs
       tests/lib/source-annotations.test.mjs -> 17 pass / 0 fail.
Full npm test: 577 pass / 0 fail / 2 skipped (Docker).

Refs plan.md Step 7 + plan-critic M4 + plan-critic B4.
This commit is contained in:
Kjell Tore Guttormsen 2026-05-09 15:13:27 +02:00
commit c412f72605
7 changed files with 1732 additions and 0 deletions

View file

@ -0,0 +1,34 @@
---
type: trekbrief
brief_version: "1.0"
task: Demo task for annotation round-trip fixture
slug: annotation-brief-demo
research_topics: 0
research_status: complete
---
# Demo brief for annotation round-trip
This fixture is used by `tests/integration/annotation-roundtrip.test.mjs`
to verify SC2 (byte-identical empty-anchor round-trip) and SC7 (per-target
isolation against `validateBrief`).
It carries no anchors. The round-trip test runs:
`stripAnchors(addAnchors(body, [])) === body`.
## Intent
Provide a minimal brief that validates against `brief-validator.mjs` so
the round-trip integration test has a real artifact to revise.
## Goal
The brief should validate cleanly (no errors, no warnings) and contain
enough body text that adding an anchor and stripping it back is a
non-trivial operation.
## Success Criteria
- File parses via `parseDocument`.
- `validateBrief` returns `valid: true`.
- `stripAnchors(addAnchors(body, []))` is byte-identical to body.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,64 @@
---
plan_version: 1.7
profile: balanced
---
# Demo plan for annotation round-trip
This fixture is used by `tests/integration/annotation-roundtrip.test.mjs`
to verify SC2 (byte-identical empty-anchor round-trip) and SC7 (per-target
isolation against `validatePlan`).
## Context
A minimal plan with two steps. Each step has a Manifest block so
`plan-validator --strict` accepts the file.
## Implementation Plan
### Step 1: Touch a sentinel file
- **Files:** `tmp/sentinel-1.txt` (new)
- **Changes:** Create the sentinel file with the literal content "step-1".
- **Reuses:** none.
- **Test first:** none — sentinel-only step.
- **Verify:** `test -f tmp/sentinel-1.txt`
- **On failure:** revert.
- **Checkpoint:** `git commit -m "chore: sentinel step 1"`
- **Manifest:**
```yaml
manifest:
expected_paths:
- tmp/sentinel-1.txt
min_file_count: 1
commit_message_pattern: "^chore: sentinel step 1"
bash_syntax_check: []
forbidden_paths: []
must_contain: []
```
### Step 2: Touch a second sentinel file
- **Files:** `tmp/sentinel-2.txt` (new)
- **Changes:** Create the sentinel file with the literal content "step-2".
- **Reuses:** none.
- **Test first:** none.
- **Verify:** `test -f tmp/sentinel-2.txt`
- **On failure:** revert.
- **Checkpoint:** `git commit -m "chore: sentinel step 2"`
- **Manifest:**
```yaml
manifest:
expected_paths:
- tmp/sentinel-2.txt
min_file_count: 1
commit_message_pattern: "^chore: sentinel step 2"
bash_syntax_check: []
forbidden_paths: []
must_contain: []
```
## Verification
- `npm test` passes.
- Both sentinel files exist.

View file

@ -0,0 +1,32 @@
---
type: trekreview
review_version: "1.0"
task: Demo review for annotation round-trip
slug: annotation-review-demo
project_dir: .claude/projects/2026-05-09-annotation-demo
brief_path: .claude/projects/2026-05-09-annotation-demo/brief.md
scope_sha_end: 0000000000000000000000000000000000000000
reviewed_files_count: 0
findings: []
---
# Demo review for annotation round-trip
This fixture is used by `tests/integration/annotation-roundtrip.test.mjs`
to verify SC2 (byte-identical empty-anchor round-trip) and SC7 (per-target
isolation against `validateReview`).
## Executive Summary
Verdict: ALLOW. No findings. This is a synthetic fixture used to exercise
the round-trip mechanics; it does not represent a real review.
## Coverage
| File | Treatment |
|------|-----------|
| _none_ | _no diff_ |
## Remediation Summary
No remediation needed. ALLOW.