docs(02-01): complete record-and-replay one fixture plan
Tasks completed: 2/2 - Record and replay one route through the summer CLI - Lock the one-route tide record and replay contract SUMMARY: .planning/phases/02-api-parity-harness-bootstrap/02-01-SUMMARY.md Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
---
|
||||
phase: 02-api-parity-harness-bootstrap
|
||||
plan: 01
|
||||
subsystem: testing
|
||||
tags: [tide, parity, yaml, httptest, bonfire, goccy, json-diff]
|
||||
|
||||
requires:
|
||||
- phase: 01-framework-kernel-foundation
|
||||
provides: bonfire.Command kernel and cmd/summer toolCommands()
|
||||
provides:
|
||||
- Version-1 tide Flow/Step request/response contracts
|
||||
- Validated YAML load and atomic fixture save
|
||||
- HTTP RecordFlow/ReplayFlow against an injected target
|
||||
- summer parity:record and parity:replay commands
|
||||
affects: [02-02, 02-03, 02-04, 02-05]
|
||||
|
||||
tech-stack:
|
||||
added:
|
||||
- github.com/goccy/go-yaml v1.19.2
|
||||
patterns:
|
||||
- Fixture bodies are YAML literal block scalars; JSON compares structurally with UseNumber
|
||||
- Record/replay inject http.Client, context, target URL and a body size cap
|
||||
- Bonfire string flags --spec --target --output --fixtures; errors exit through cobra
|
||||
|
||||
key-files:
|
||||
created:
|
||||
- tide/flow.go
|
||||
- tide/fixture.go
|
||||
- tide/record.go
|
||||
- tide/replay.go
|
||||
- tide/diff.go
|
||||
- tide/testdata/one-route-spec.yaml
|
||||
- tide/roundtrip_test.go
|
||||
- cmd/summer/parity.go
|
||||
- cmd/summer/parity_test.go
|
||||
modified:
|
||||
- cmd/summer/main.go
|
||||
- go.mod
|
||||
- go.sum
|
||||
|
||||
key-decisions:
|
||||
- "tide is the framework-owned parity library; it does not import Fonoteka"
|
||||
- "goccy/go-yaml v1.19.2 decodes fixtures with DisallowUnknownField; save uses a dedicated encoder so literal bodies keep nested indent"
|
||||
- "JSON diffs ignore object key order and fail on missing keys or token-type changes at $.path"
|
||||
- "Non-JSON bodies compare raw bytes and report offset plus printable escaped windows"
|
||||
- "toolchain go1.27.0 is restored after go mod tidy drops it"
|
||||
|
||||
patterns-established:
|
||||
- "Pattern: CLI tests drive bonfire.NewRoot with an injected writer and httptest.Server, never a real TTY"
|
||||
- "Pattern: SaveFlow writes a temp file, Syncs, then rename; RecordFlow errors never create the destination"
|
||||
|
||||
requirements-completed: [QA-01, QA-02, QA-03]
|
||||
|
||||
duration: 7min
|
||||
completed: 2026-09-17
|
||||
---
|
||||
|
||||
# Phase 2 Plan 1: Record and Replay One Fixture Summary
|
||||
|
||||
**A developer can record GET /sample through `summer parity:record` and replay it with `summer parity:replay` against httptest, with JSON path diffs at `$.data` and non-JSON byte-offset diffs**
|
||||
|
||||
## Performance
|
||||
|
||||
- **Duration:** 7 min
|
||||
- **Started:** 2026-09-17T10:14:10Z
|
||||
- **Completed:** 2026-09-17T10:21:51Z
|
||||
- **Tasks:** 2
|
||||
- **Files modified:** 12
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- Generic `tide` package owns version-1 Flow/Step contracts, validated YAML IO, HTTP record/replay and structural JSON/byte diffs
|
||||
- `parity:record` and `parity:replay` register on the Phase 1 bonfire kernel with string flags `--spec`, `--target`, `--output`, `--fixtures`
|
||||
- One-route testdata spec records and replays against httptest; changed JSON or bytes fail the CLI with expected/actual diagnostics
|
||||
|
||||
## Task Commits
|
||||
|
||||
Each task was committed atomically:
|
||||
|
||||
1. **Task 1: Record and replay one route through the summer CLI** - `f6e1b89` (feat)
|
||||
2. **Task 2: Make the one-route record/replay path work** - `f669d05` (feat)
|
||||
|
||||
**Plan metadata:** pending `docs(02-01)` commit
|
||||
|
||||
_Note: TDD RED was observed as compile/command discovery failure inside Task 1 and was not committed separately, per the plan's single-green-commit instruction._
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- `tide/flow.go` - Flow/Step/Request/Response types, Result, MismatchError, validation
|
||||
- `tide/fixture.go` - LoadFlow/ParseFlow/SaveFlow with unknown-field rejection and atomic sync+rename
|
||||
- `tide/record.go` - RecordFlow with injected client, context and bounded bodies
|
||||
- `tide/replay.go` - ReplayFlow against an arbitrary HTTP target
|
||||
- `tide/diff.go` - UseNumber JSON compare and non-JSON byte-offset diffs
|
||||
- `tide/testdata/one-route-spec.yaml` - version-1 GET /sample request spec
|
||||
- `tide/roundtrip_test.go` - TestParityRoundTrip library round trip and contract cases
|
||||
- `cmd/summer/parity.go` - parity:record and parity:replay commands
|
||||
- `cmd/summer/parity_test.go` - TestParityCommands through bonfire.NewRoot
|
||||
- `cmd/summer/main.go` - registers the parity commands on toolCommands()
|
||||
- `go.mod` / `go.sum` - direct github.com/goccy/go-yaml v1.19.2, toolchain go1.27.0 kept
|
||||
|
||||
## Decisions Made
|
||||
|
||||
- Named the harness library `tide` as allowed by CONTEXT.md discretion
|
||||
- Decode with goccy; encode fixtures with a small dedicated writer so `body: |-` content is indented under nested mappings (goccy BytesMarshaler dropped indent)
|
||||
- Compare JSON structurally (key sets, array lengths, scalars, json.Number token types) and ignore object key order
|
||||
- Inject `http.Client`, context and MaxBody; default cap is 8 MiB; truncation fails before SaveFlow
|
||||
- Keep the package generic: no Fonoteka route names, PHP fields, or standalone CLI
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. [Rule 2 - Missing Critical] Restored toolchain go1.27.0 after go get/tidy dropped it**
|
||||
- **Found during:** Task 1 (module resolution)
|
||||
- **Issue:** `go get github.com/goccy/go-yaml@v1.19.2` and `go mod tidy` removed the `toolchain go1.27.0` directive the plan requires
|
||||
- **Fix:** Re-inserted `toolchain go1.27.0` in go.mod after tidy
|
||||
- **Files modified:** go.mod
|
||||
- **Verification:** `grep toolchain go.mod` shows `toolchain go1.27.0`; go vet/test pass
|
||||
- **Committed in:** f6e1b89 (Task 1 commit)
|
||||
|
||||
**2. [Rule 1 - Bug] Dedicated YAML encoder for literal nested bodies**
|
||||
- **Found during:** Task 1 (GREEN of SaveFlow)
|
||||
- **Issue:** goccy BytesMarshaler parsed `|-` scalars but re-emitted content without nested indent, so LoadFlow failed with `unexpected map key`
|
||||
- **Fix:** SaveFlow writes version-1 YAML with correctly indented block scalars; LoadFlow still uses goccy with DisallowUnknownField
|
||||
- **Files modified:** tide/fixture.go
|
||||
- **Verification:** TestParityRoundTrip records YAML containing `body: |-` and reloads it
|
||||
- **Committed in:** f6e1b89 (Task 1 commit)
|
||||
|
||||
---
|
||||
|
||||
**Total deviations:** 2 auto-fixed (1 missing critical, 1 bug)
|
||||
**Impact on plan:** Required for the pinned toolchain and for round-tripping recorded JSON bodies. No scope creep.
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
- slopcheck on the updated go.mod reported goccy as OK. Pre-existing SUS findings on `golang.org/x/term` and `golang.org/x/sys` were unchanged and not newly added
|
||||
- QA-01/QA-02/QA-03 remain phase-level: this plan delivers the one-route CLI path, not the 154-route corpus, normalizer classes, or testcontainers. Frontmatter copies the plan's requirements list; they should not be treated as milestone-complete
|
||||
|
||||
## User Setup Required
|
||||
|
||||
None - no external service configuration required.
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
Ready for 02-02-PLAN.md (proxy sessions and manifest-driven record with strict diffs). Public APIs: `LoadFlow`, `SaveFlow`, `RecordFlow`, `ReplayFlow`, `Flow`, `Result`.
|
||||
|
||||
## Verification
|
||||
|
||||
- RED observed: `go test ./tide ./cmd/summer -run 'TestParityRoundTrip|TestParityCommands'` failed with undefined LoadFlow/RecordFlow and missing `parity:record` before implementation
|
||||
- GREEN: same focused tests pass; `go vet ./...` and `go test ./...` exit 0
|
||||
- slopcheck: goccy VERIFIED/OK; toolchain pin preserved
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
- [x] Key files exist on disk
|
||||
- [x] `git log --grep=02-01` returns Task 1 and Task 2 commits
|
||||
- [x] Task acceptance criteria re-run and pass
|
||||
- [x] Plan verification commands pass
|
||||
|
||||
---
|
||||
*Phase: 02-api-parity-harness-bootstrap*
|
||||
*Completed: 2026-09-17*
|
||||
Reference in New Issue
Block a user