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>
7.5 KiB
Sprint 111 Plan: Iteration Session Context
Context
Sprints 1-110 established Whetstone as a deterministic open-loop generator: schema → struct, spec → taskitems, source → transpiled output. The output is fully determined by the input, with no environmental state involved.
Sprint 111 begins a new capability tier: closed-loop iteration. Real
development is not open-loop. It involves running code, observing what breaks,
forming a hypothesis, patching, and repeating until a goal is met. This sprint
introduces the foundational primitive for that loop: the IterationSession.
An IterationSession is a structured record of one attempt to achieve a
convergence goal (all tests pass, build succeeds, environment is ready). It
tracks: the goal, each attempt taken, each observation made, and the current
distance from the goal. Every subsequent sprint in this epoch builds on it.
Goals
- Define the
IterationSessionschema with goal, attempt history, and state - Define
AttemptRecordandObservationRecordas structured sub-types - Define
GapModelto measure distance from the convergence goal - Implement a state machine: pending → active → converged / escalated / failed
- Persist sessions to sidecar files alongside annotated ASTs
Steps
Step 1339: IterationSession core schema (12 tests)
Create editor/src/IterationSession.h.
Fields: session_id, goal (string), goal_type (enum: build_success,
tests_pass, environment_ready, custom), status (enum: pending, active,
converged, escalated, failed), created_at, updated_at, attempts[],
max_attempts (default 10).
Tests (12): constructable with defaults, goal stored, goal_type round-trips, status defaults to pending, session_id is non-empty on construction, attempt list starts empty, max_attempts enforced, JSON serialization, JSON deserialization, unknown status survives passthrough, deterministic serialization order, schema version field present.
Step 1340: AttemptRecord schema (10 tests)
Create editor/src/AttemptRecord.h.
Fields: attempt_id, session_id, action_type (enum: build, test, patch,
probe, escalate), action_description, started_at, completed_at,
outcome (enum: success, failure, partial, error), observation_id.
Tests (10): constructable, action_type round-trips, outcome defaults to error, duration computable from timestamps, JSON round-trip, unknown action_type passthrough, attempt_id non-empty, links to session_id, links to observation_id, deterministic serialization.
Step 1341: ObservationRecord schema (10 tests)
Create editor/src/ObservationRecord.h.
Fields: observation_id, source (enum: build_output, test_output,
process_stdout, process_stderr, file_read, env_probe), raw_text,
exit_code, duration_ms, structured_data (JSON blob for parsed output),
truncated (bool — raw_text may be capped at 16KB).
Tests (10): constructable, source enum round-trips, exit_code defaults to -1, truncated flag set when raw_text exceeds limit, structured_data round-trips, JSON serialization, deserialization, unknown source passthrough, observation_id non-empty, deterministic output.
Step 1342: GapModel — distance from convergence goal (10 tests)
Create editor/src/GapModel.h.
Fields: metric_type (enum: error_count, test_failure_count, missing_deps,
custom), current_value, target_value, delta, converged (bool —
true when current_value == target_value), trend (enum: improving,
stagnant, worsening — derived from last two values).
Tests (10): converged true when delta is zero, trend improving when delta decreasing, trend worsening when delta increasing, stagnant after two equal values, JSON round-trip, negative delta flagged as worsening, custom metric type passthrough, deterministic output, delta auto-computed, schema constructable.
Step 1343: Session state machine transitions (10 tests)
Add SessionStateMachine to IterationSession.h (or small companion header).
Valid transitions:
- pending → active (on first attempt recorded)
- active → converged (on gap.converged == true)
- active → escalated (on max_attempts reached without convergence)
- active → failed (on attempt with outcome=error and no recovery path)
- Any terminal state is immutable.
Tests (10): pending→active on first attempt, active→converged when gap closes, active→escalated at max_attempts, active→failed on terminal error, illegal transition rejected, terminal states immutable, state serialized, state deserialized, history preserved through transitions, deterministic transition log.
Step 1344: Session persistence to sidecar file (10 tests)
Add SessionStore to a new editor/src/SessionStore.h.
Sidecar path convention: .whetstone/sessions/<session_id>.json relative
to workspace root. SessionStore::save(session) writes atomically (write
to .tmp then rename). SessionStore::load(session_id) reads and
deserializes. SessionStore::list() returns all session IDs in the store.
Tests (10): save creates file, load round-trips session, list returns saved ids, overwrite preserves new state, missing session returns nullopt, atomic write (partial write does not corrupt), path derivation from workspace root, concurrent save does not corrupt (file lock), deterministic file layout, sidecar dir created on first save.
Step 1345: whetstone_start_iteration_session MCP tool (8 tests)
Create editor/src/mcp/RegisterIterationSessionTools.h.
Input: { "goal": string, "goal_type": string, "max_attempts": int? }
Output: { "session_id": string, "status": "pending" }
Persists session to SessionStore immediately on creation.
Tests (8): tool registered, schema validates, session_id returned, status is pending, session persisted to disk, missing goal_type defaults to "custom", max_attempts defaults to 10, deterministic output shape.
Step 1346: whetstone_record_attempt MCP tool (8 tests)
Input: { "session_id": string, "action_type": string, "action_description": string, "observation": { ... } }
Output: { "attempt_id": string, "session_status": string, "gap": { ... }? }
Appends AttemptRecord + ObservationRecord to session. Returns updated session status after state machine step.
Tests (8): tool registered, attempt appended, session_status updated, unknown session_id returns error, illegal transition returns error, gap field present when gap model updated, deterministic output, session persisted after record.
Step 1347: whetstone_get_session_state MCP tool (8 tests)
Input: { "session_id": string }
Output: full session JSON with attempts[], gap, and current status.
Tests (8): tool registered, full session returned, attempts included, gap included when present, terminal sessions readable, missing session returns structured error, deterministic serialization, attempt count correct.
Step 1348: Sprint 111 integration summary + regression (8 tests)
Create editor/src/Sprint111IntegrationSummary.h.
Tests (8): all new headers constructable, tools registered in initialize response, session round-trip end-to-end (start → record × 2 → converge → read), state machine covers all transitions, sidecar created on disk, no header exceeds 600 lines, deterministic snapshots, full prior regression passes.
Architecture Gate
- Max 600 lines per header — split
IterationSessionExtended.hif needed - No runtime dependencies beyond nlohmann-json and std::filesystem
- Session IDs use UUIDv4 (reuse existing UUID utility if present, else add one)
- All MCP tool outputs are stable and machine-readable
- Sidecar format is versioned (
"schema_version": 1)