Files
whetstone_DSL/sprint112_plan.md
Bill 84bdad8e9e Add Sprints 111-117: closed-loop iteration epoch
Sprint 111: IterationSession context primitive
Sprint 112: EnvironmentSnapshot and diff
Sprint 113: Build output feedback loop
Sprint 114: Test failure feedback loop
Sprint 115: Requirements derivation from AST
Sprint 116: FeedbackLoopOrchestrator (wires 111-115)
Sprint 117: HiveMind integration (iteration steps as distributed jobs)

These sprints begin Epoch 3 — closed-loop determinism.
Sprints 1-110 made code generation open-loop deterministic.
Sprints 111+ make the full dev workflow (sense→act→observe→repeat)
structurally deterministic, with HiveMind as the execution layer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-21 13:27:32 -07:00

169 lines
7.2 KiB
Markdown

# Sprint 112 Plan: Environment Snapshot and Diff
## Context
Before iterating on a failing environment, you must read it deterministically.
"Environment" means the intersection of: installed packages, active config files,
running processes, and file system state that your project depends on. Without a
structured snapshot, the iteration session has no baseline to compare against and
no way to tell whether a change actually helped.
Sprint 112 adds `EnvironmentSnapshot` — a structured, serializable record of the
environment at a point in time — and `EnvironmentDiff` — the delta between two
snapshots. These are the observability primitives that the build, test, and setup
feedback loops in later sprints will use.
---
## Goals
1. Define `EnvironmentSnapshot` schema covering deps, configs, processes, and paths
2. Implement probes that read each domain from the actual system
3. Define `EnvironmentDiff` as a typed delta between two snapshots
4. Expose snapshot and diff as MCP tools
5. Produce a setup verification report (what is present vs what is needed)
---
## Steps
### Step 1349: `EnvironmentSnapshot` core schema (12 tests)
Create `editor/src/EnvironmentSnapshot.h`.
Fields: `snapshot_id`, `captured_at`, `workspace_root`, `platform`
(os, arch, shell), `packages[]` (name, version, source: apt/pip/npm/cargo/etc.),
`config_files[]` (path, hash, key_values[] for known formats),
`processes[]` (name, pid, port, status), `env_vars[]` (key, value — filtered
to relevant set, never secrets).
Tests (12): constructable with defaults, snapshot_id non-empty, platform fields
populated, packages list starts empty, config list starts empty, process list
starts empty, env_vars list starts empty, JSON serialization, JSON deserialization,
unknown package source passthrough, schema version present, deterministic output.
### Step 1350: Package state probe (10 tests)
Create `editor/src/PackageProbe.h`.
Probes installed packages from available managers on the current platform.
Strategy: try each manager (dpkg-query, pip list, npm list -g, cargo --list)
via subprocess, parse stdout into PackageRecord rows, tag with source.
Failures are non-fatal — missing manager produces empty list for that source.
Tests (10): probe runs without crashing, result is parseable, known-installed
package appears in results, unknown package absent, source tag correct,
failed probe returns empty not error, deterministic sort order, version field
populated, JSON round-trip, timeout respected (default 5s).
### Step 1351: Config file probe (10 tests)
Create `editor/src/ConfigFileProbe.h`.
Scans workspace for known config files: `.env`, `*.yaml`, `*.toml`, `*.json`
(at workspace root depth only — no deep recursion). Reads content, computes
SHA-256 hash, extracts key_values for .env and simple YAML/TOML maps.
Sensitive keys (PASSWORD, SECRET, KEY, TOKEN) are redacted to `"[REDACTED]"`.
Tests (10): .env file parsed into key_values, sensitive keys redacted,
hash computed and stable, yaml keys extracted, toml keys extracted,
json keys extracted (top-level only), missing file produces absent entry,
hash changes on content change, deterministic key ordering, depth limit
respected.
### Step 1352: Process state probe (10 tests)
Create `editor/src/ProcessProbe.h`.
Lists running processes filtered to a known-relevant set (configurable list of
process name substrings). Uses `/proc` on Linux, `ps` subprocess on macOS.
Captures name, pid, and listening ports (from `ss -tlnp` or `netstat`).
Tests (10): probe runs without crashing, result parseable, known process
appears when running, absent process not in list, port captured when listening,
no port when not listening, deterministic sort, name filter respected,
JSON round-trip, timeout respected.
### Step 1353: `EnvironmentDiff` schema and computation (10 tests)
Create `editor/src/EnvironmentDiff.h`.
Compares two `EnvironmentSnapshot` instances. Fields: `added_packages[]`,
`removed_packages[]`, `changed_packages[]` (name + old_version + new_version),
`added_configs[]`, `removed_configs[]`, `changed_configs[]` (path + old_hash
+ new_hash), `added_processes[]`, `removed_processes[]`, `unchanged` (bool —
true when all diff lists are empty).
Tests (10): empty diff on identical snapshots, unchanged true on identical,
added package detected, removed package detected, changed package detected,
added config detected, changed config hash detected, process added detected,
JSON round-trip, deterministic diff ordering.
### Step 1354: Snapshot persistence (sidecar integration) (8 tests)
Extend `SessionStore.h` (or add `SnapshotStore.h`) to persist
`EnvironmentSnapshot` alongside iteration sessions.
Convention: `.whetstone/snapshots/<snapshot_id>.json`
Tests (8): save creates file, load round-trips, list returns ids, overwrite
preserves new data, missing snapshot returns nullopt, atomic write, path
derivation correct, sidecar dir created on first save.
### Step 1355: Setup verification report (8 tests)
Create `editor/src/SetupVerificationReport.h`.
Given a `RequiredEnvironment` spec (a list of expected packages, config files,
and processes) and a current `EnvironmentSnapshot`, produces a structured report:
`satisfied[]`, `missing[]`, `version_mismatch[]`, `ready` (bool — true when
missing and version_mismatch are both empty).
Tests (8): ready true when all present, missing package detected, version
mismatch detected, correct version passes, empty required produces ready=true,
JSON round-trip, deterministic output, report serializable.
### Step 1356: `whetstone_snapshot_environment` MCP tool (8 tests)
Input: `{ "workspace": string, "process_filter": string[]? }`
Output: full `EnvironmentSnapshot` JSON + `snapshot_id`.
Runs all three probes (packages, configs, processes) and persists result.
Tests (8): tool registered, snapshot_id returned, packages field present,
configs field present, processes field present, snapshot persisted to disk,
invalid workspace returns structured error, deterministic output shape.
### Step 1357: `whetstone_diff_environments` MCP tool (8 tests)
Input: `{ "before_id": string, "after_id": string }`
Output: `EnvironmentDiff` JSON + `unchanged` bool.
Loads both snapshots from store, computes diff, returns result.
Tests (8): tool registered, unchanged true on same snapshot, added package
appears in diff, removed package appears, changed package appears, missing
snapshot_id returns error, diff persisted to session if session_id provided,
deterministic output.
### Step 1358: Sprint 112 integration summary + regression (8 tests)
Create `editor/src/Sprint112IntegrationSummary.h`.
End-to-end test: capture snapshot → mutate environment (add a dummy config
file) → capture second snapshot → diff → verify change detected.
Tests (8): headers constructable, tools registered, end-to-end diff detects
change, verification report correct, sidecar files created, no header exceeds
600 lines, deterministic snapshots, full prior regression passes.
---
## Architecture Gate
- Probes are non-fatal: subprocess failure returns empty list, not panic
- No new dependencies — subprocess via std::system or popen, parsing in C++
- Sensitive data never stored in snapshots (redaction in ConfigFileProbe)
- Max 600 lines per header
- All MCP outputs stable and machine-readable