# `/loop` driver — autonomous M2–M6 implementation You are inside a `/loop` iteration for the **mxaccess Rust port** at `c:\Users\dohertj2\Desktop\mxaccess`. Your goal each iteration: advance the project by one cohesive unit of work, verify it doesn't regress, commit it locally, and either schedule the next iteration or stop and surface. This file is re-fed to you on every iteration with no carry-over state. Read it top-to-bottom each time. Discover everything else from the project itself. --- ## Iteration protocol ### Step 0 — Triage `design/followups.md` Read `design/followups.md`. If it does not exist, create it with this skeleton: ```markdown # Followups Open work items deferred during /loop iterations. Triaged at the top of every iteration. New items are appended under `## Open`; resolved items move to `## Resolved` with a date + commit hash. ## Open (none yet) ## Resolved (none yet) ``` Then for each item under `## Open`: 1. Read the **`Resolves when:`** clause. 2. If its preconditions are met **now** (the gating commit landed, the ambiguity it flagged is now resolved, etc.) → solve it as part of this iteration's work, then move it to `## Resolved` with today's date and the resolving commit hash (the commit you make in Step 5 below). 3. If preconditions are **not** met → leave it under `## Open` and move on. If `## Open` exceeds **10 items**, STOP and surface to the user — that's a drift signal that needs human triage, not more iterations. ### Step 1 — Discover state Run in parallel (single assistant message, multiple tool calls): - `git log --oneline -20` - `cd rust && cargo test --workspace 2>&1 | grep "test result:" | grep -v "0 passed" | tail -5` — must show all-pass results. - Read `design/60-roadmap.md`, `design/dependencies.md`, `design/review.md`. If `cargo test` is **not green** at the start of the iteration: 1. Diagnose with `cargo build` and the failing test name. 2. Apply **one** targeted fix. 3. If the fix doesn't recover green: `git reset --hard HEAD`, log a followup describing the failure mode, and STOP. Never proceed past Step 1 with a red baseline. ### Step 2 — Identify the current phase and unblocked lanes From the git log + recent commits, determine which milestone is in flight: - Most recent `[M0]` / `[M1]` / `[M2]` / ... commits → that's the active phase. - If the active phase's DoD (per `design/60-roadmap.md`) is fully met, the next iteration's work is the **next** milestone. Advance the phase marker mentally. Then consult `design/dependencies.md` for the active phase's parallelism map. Identify which lanes are unblocked **right now** (their dependencies have landed in earlier commits). The summary table for fast lookup: ``` M2 wave 1: 3 agents — NTLMv2 client / DCE/RPC PDU codec / OBJREF parser M2 wave 2: 2 agents — OXID resolution / IRemUnknown::RemQueryInterface M2 wave 3: 1 agent — mxaccess-callback (the INmxSvcCallback exporter) M3: 2 agents — mxaccess-galaxy / mxaccess-nmx M4 wave 1: 1 agent — Session core + RecoveryPolicy types (sequential) M4 wave 2: 2 agents — write family / subscribe family M4 wave 3: 7 agents — examples (one each) M5: 4 agents — MS-NMF framing / MC-NBFX codec / MC-NBFS dictionary / DH+HMAC+AES M5 client: 1 agent — mxaccess-asb operations (sequential after framing) M6: 4 agents — mxaccess-compat / perf / metrics / docs ``` Pick the smallest unit that: - Is currently unblocked (dependencies landed). - Is not already covered by an open followup that's deferred. - Can be completed in one iteration's work (one commit's worth). ### Step 3 — Execute **If the active wave has multiple parallel streams** (any row above with `N agents` where `N > 1`), spawn that many `general-purpose` agents in **one single message** containing N parallel `Agent` tool calls. Each agent owns one `.cs` source file (or one logical unit) and emits one Rust module. Each agent's prompt MUST include: - Project context (one paragraph: this is the mxaccess Rust port, `src/` is the executable spec, CLAUDE.md forbids fabrication). - The exact `.cs` source path to port. - The exact Rust output module path. - Reference to existing M1 modules as the pattern to follow (`reference_handle.rs`, `envelope.rs`, `status.rs`). - Test requirements: round-trip, boundary checks, citation-bearing parity vectors against `tools/Compute-Crc.ps1` style helpers where applicable. - Hard rule: do NOT edit `lib.rs`. The driver wires up modules after agents finish. - Audit reminder: any conditional read pattern (`hasDetailStatus`-style) must mirror the .NET reference's unconditional/conditional split exactly (`design/70-risks-and-open-questions.md` Q7 — the M1 wave-1 audit defect). **If the work is sequential** (M4 Session core, M5 client integration after framing lands, any wave with `1 agent`), do it directly. Read the .cs source, port it inline, write tests inline. Do not spawn an agent for sequential single-stream work. After parallel agents return: wire up `lib.rs` (mod declarations + re-exports) and remove any stub types they replaced. ### Step 4 — Verify Run all four DoD gates: - `cargo build --workspace --all-targets` - `cargo test --workspace --no-fail-fast` - `cargo clippy --workspace --all-targets -- -D warnings` - `cargo fmt --all -- --check` For codec changes also verify the .NET parity test still passes: - `cargo test -p mxaccess-codec --test dotnet_codec_parity` If any gate fails: 1. Try **one** targeted fix. 2. If still failing → `git reset --hard HEAD`. Append a followup. STOP. ### Step 5 — Commit (local only) - `git add -A`. - Commit message format: ``` [M] : - Test count delta: NNN → MMM (+K) - Open followups touched: F, F (or "none") Co-Authored-By: Claude Opus 4.7 (1M context) ``` - **Do not push.** The user pushes manually unless they've explicitly enabled auto-push for the loop. If auto-push has been enabled (you'll know because they invoked `/loop` with that flag or said so in this iteration's pre-amble), then `git push` after the commit. ### Step 6 — Log new followups For each item this iteration **discovered but did not solve**, append to `design/followups.md` under `## Open` using this schema: ```markdown ### F **Severity:** P0 | P1 | P2 | P3 **Source:** commit **Why deferred:** **Resolves when:** **Notes:** ``` `` is the next free integer (highest existing F-number + 1, or 1 on first followup). Common follow-up sources: - An agent reported a deviation from the .NET reference that requires a separate design-decision turn. - A risk register item (`R1`–`R16` / `Q1`–`Q7`) was hit but did not block this iteration's work. - A test fixture is missing and would require a new live capture. - A dep-version bump or feature-gate decision arose that needs a workspace-level agreement. ### Step 7 — Decide next | Condition | Action | |---|---| | Milestone DoD fully satisfied (per `60-roadmap.md`) | Make a final `[Mn-done]` commit summarising the milestone, then `ScheduleWakeup` for next milestone start. | | Hit ambiguous protocol question (no evidence in `src/` / `docs/` / `captures/`) | Log followup, STOP, surface to user. | | Hit P0/P1 blocker tracked in `70-risks-and-open-questions.md` | Log followup, STOP, surface. | | 3 consecutive iterations with zero net progress (no new commit, no resolved followup) | STOP, surface to user. | | `## Open` followups list > 10 items | STOP, ask user to triage. | | M6 DoD fully satisfied | Project complete. STOP. Do not schedule. | | Otherwise | `ScheduleWakeup` with `delaySeconds` in 60–270 (cache stays warm). | When you call `ScheduleWakeup`, pass the literal sentinel `<>` as `prompt` so the runtime re-resolves these instructions. Use a one-sentence `reason` describing what the next iteration will pick up. --- ## Hard rules (do not negotiate) - **No fabricated protocol behaviour.** Every wire-byte, IID, opnum, HRESULT, byte-offset, or layout claim must cite `src/MxNativeCodec/*.cs:LINE`, `src/MxNativeClient/*.cs:LINE`, `src/MxAsbClient/*.cs:LINE`, `docs/*.md:LINE`, `analysis/frida/*.tsv`, or `captures/0NN-frida-*`. If you can't cite, you can't claim. Log a followup instead. - **No `--force`, `--no-verify`, `--no-gpg-sign`** on git commands. - **No amending pushed commits.** Always create new commits. - **No deleting or rewriting** files in `captures/`, `analysis/frida/`, `analysis/proxy/`, `analysis/decompiled-*/`, or `analysis/ghidra/exports/`. These are evidence per CLAUDE.md. - **No editing `lib.rs` from an agent.** The driver wires up modules. - **No skipping verification.** All four cargo gates green or revert. - **No pushing without authorization.** Commit locally only by default. - **Preserve unknown bytes.** Match the .NET reference round-trip for any field whose semantics are not yet decoded. Use `[u8; N]` preservation fields and document with a `:LINE` citation. - **Tests over assertions.** Do not add `assert!(true)` or `assert!()` at runtime; use `const _: () = assert!(...)` for compile-time checks. - **Conditional reads must match the .NET reference exactly** — see `design/70-risks-and-open-questions.md` Q7 (`hasDetailStatus` audit). Any field the .NET reads unconditionally must be read unconditionally in Rust. --- ## Self-check before scheduling next iteration Before calling `ScheduleWakeup`, verify each: - [ ] `cargo build --workspace --all-targets` exited 0. - [ ] `cargo test --workspace` exited 0 with all-pass results. - [ ] `cargo clippy --workspace --all-targets -- -D warnings` exited 0. - [ ] `cargo fmt --all -- --check` exited 0. - [ ] One commit landed this iteration (verify with `git log -1 --oneline`). - [ ] If any followup was deferred this iteration, `design/followups.md` has the new entry. - [ ] `delaySeconds` is in [60, 270] for cache-warm continuation, or in [1200, 3600] if waiting on a genuinely slow external process. If any item fails, do **not** schedule next iteration. Surface to the user. --- ## Useful commands reference ```powershell # State discovery cd c:\Users\dohertj2\Desktop\mxaccess git log --oneline -20 git status --short # Rust gates (run from rust/) cd rust cargo build --workspace --all-targets cargo test --workspace --no-fail-fast cargo clippy --workspace --all-targets -- -D warnings cargo fmt --all -- --check cargo test -p mxaccess-codec --test dotnet_codec_parity # Live-probe gating (M3+ only) . ..\tools\Setup-LiveProbeEnv.ps1 cargo test -p mxaccess --features live -- --ignored # .NET parity helpers dotnet build src\MxNativeCodec\MxNativeCodec.csproj pwsh -NoProfile -File tools\Compute-Crc.ps1 ``` --- ## Why this design - **Step 0 first** keeps `followups.md` from rotting. Items that became solvable get cleaned up immediately. - **Step 1's red-baseline check** prevents iterations from compounding bugs. - **Step 3's parallel-agent fan-out** is the throughput lever — `M2 wave 1` and `M5 framing` both run 3–4 agents concurrently, cutting wall-clock. - **Step 5's local-commit-only** default is reversibility. A bad iteration can be `git reset --hard HEAD~1` without affecting any remote. - **Step 7's stop conditions** are explicit and disjoint. There's no "if it feels right, stop" phrasing — every stop condition has a measurable trigger. - **Hard rules** are lifted from `CLAUDE.md` so the loop cannot drift even if a single iteration loses context.