From 2ab0a7e7adc1b00cbbe6f8c39076276b5693248f Mon Sep 17 00:00:00 2001 From: Young Joon Lee Date: Sun, 23 Aug 2026 10:26:10 +0900 Subject: [PATCH 1/2] docs(03): anchor the ERR-04 baseline to a commit, not a date The 1,138 figure was measured on a working tree that happened to contain the then-uncommitted hwped.rs. The number was right, but its provenance was accidental: 19 of the 1,138 matches live in that file, so on a tree without it the count reads 1,119 and the post-migration count lands at 1,109 - below the [1118, 1138] band the plan asserts against. Re-confirmed 1,138 on the committed tree at 34f96ee, and recorded that commit as the provenance in 03-02 and 03-04. The band itself is unchanged. - 03-04 now requires re-measuring the baseline at the start of the plan rather than only "if concurrent sessions touched src-tauri/src" - the hwp-editor track is still active, so drift is expected, not exceptional - 03-04's full-gate step drops the Phase 1/2 escape hatch for uncommitted hwped.rs/lib.rs: that work is committed and make verify is green on it, so a red gate is now this phase's to diagnose - ROADMAP success criterion 4 and requirement ERR-04 cited CONCERNS.md's stale 1,118; both now cite the measured 1,138 and name the stale figure as stale (RESEARCH Pitfall 6 had already flagged it) --- .planning/PROJECT.md | 4 ++-- .planning/REQUIREMENTS.md | 4 ++-- .planning/ROADMAP.md | 2 +- .planning/STATE.md | 2 +- .planning/phases/03-typed-ipc-error-contract/03-02-PLAN.md | 2 +- .planning/phases/03-typed-ipc-error-contract/03-04-PLAN.md | 6 +++--- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.planning/PROJECT.md b/.planning/PROJECT.md index b5c4a28b..2cc38c4f 100644 --- a/.planning/PROJECT.md +++ b/.planning/PROJECT.md @@ -69,7 +69,7 @@ real files the user owns, and nothing is lost if Maru is uninstalled. feature landing mid-refactor makes every regression ambiguous. One recorded exception: the `hwped_*` hwp-editor bridge, written by a parallel track and adopted here rather than built (STATE.md "Scope Exceptions") -- **Converting all 1,118 `Result` signatures** - CONCERNS.md rejects +- **Converting every `Result` signature** - CONCERNS.md rejects it explicitly; only the errors the frontend actually branches on move - **Retrofitting all ~20 existing path-traversal validators** - the existing checks are individually sound; promoting the canonical helper is the goal @@ -181,7 +181,7 @@ ones this milestone can actually break are listed here. | Scope drawn from CONCERNS.md Tech Debt, not from the SPECs | 18 ingested docs describe shipped behavior; inventing forward work from them would be fabrication | - Pending | | Verification gates land before the decomposition (Phase 1) | Moving 68 `useState` / 50 `useEffect` without a hook-dependency gate reproduces #260/#262/#264 | ✓ Phase 1 — 7 gates live, deliberate-break proofs red-then-green, UAT 24/24 | | Continue the module-store precedent instead of adding a state library | `errorStore`/`workspaceStore`/`editorTabsStore` already prove the pattern here | - Pending | -| Typed error contract covers only branched-on errors | Converting 1,118 signatures is cost without benefit; display-only errors read fine as strings | - Pending | +| Typed error contract covers only branched-on errors | Converting all ~1,138 signatures is cost without benefit; display-only errors read fine as strings | - Pending | | Promote `ensure_within`, do not retrofit all ~20 callers | Existing checks are individually sound; the problem is that a new author has no canonical example | ✓ Phase 2 — promoted to `crate::paths`, doc + tests as the example, zero retrofits | | Phases 4-5 get no `UI hint` annotation | They refactor UI state plumbing with pixel-identical output as the success criterion; a UI design spec would be the wrong downstream suggestion | - Pending | | 64 SPEC constraints recorded as invariants, not decisions | 0 ADRs in the set - nothing is decision-locked, so a future ADR can override any of them | - Pending | diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index a6e02211..323fda92 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -34,7 +34,7 @@ milestone with no end-user-visible surface. - [ ] **ERR-01**: A frontend caller can read a stable machine-readable `code` from any error it needs to branch on, alongside the human-readable message - [ ] **ERR-02**: Renaming an error code fails the build on both the Rust and TypeScript side instead of silently breaking a recovery path - [ ] **ERR-03**: Every existing `message.includes("")` matcher branches on the typed code instead - starting with `evidence_binder_revision_conflict` at `src/components/evidence/EvidenceBinderPane.tsx:174` -- [ ] **ERR-04**: Display-only errors are untouched - the `Result` signature count stays within a few of today's 1,118 +- [ ] **ERR-04**: Display-only errors are untouched - the `Result` signature count stays within a few of the measured baseline of 1,138 (CONCERNS.md's 1,118 is stale; re-measure before Phase 3 executes) > **Note for Phase 3 planning, from Phase 1's verification (2026-08-22).** None of the > seven `make verify` gates can catch a serde mismatch at the Rust-TypeScript IPC @@ -103,7 +103,7 @@ not compete with the structural work. Not in the current roadmap. | Feature | Reason | |---------|--------| | Any new product feature | Behavior-preserving work is only verifiable if behavior is not also changing. **Exception, 2026-08-23:** the `hwped_*` hwp-editor bridge landed from a parallel track and is adopted, not built, by this milestone - see STATE.md "Scope Exceptions" | -| Converting all 1,118 `Result` signatures | Explicitly rejected in the CONCERNS.md fix approach; cost without benefit for display-only errors | +| Converting every `Result` signature | Explicitly rejected in the CONCERNS.md fix approach; cost without benefit for display-only errors | | Retrofitting all ~20 existing path-traversal validators | The existing checks are individually sound; the problem is the absence of a canonical example, not the callers | | Changing `.maruignore` defaults | It is a user-facing file format, not a scanner constant | | Any visible UI change during decomposition | A refactor that alters output cannot be verified against the existing e2e suite | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index b9b97de5..9bbfcbae 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -117,7 +117,7 @@ Notes for planning: 1. A frontend caller can read a stable `code` and a human message from every error it branches on, without parsing the message 2. Renaming a code on the Rust side fails `make verify` on the TypeScript side, and vice versa 3. No `message.includes("")` matcher remains in `src/` for a code that moved to the contract - 4. The `Result` count in `src-tauri/src/` is essentially unchanged from today's 1,118 - display-only errors were not touched + 4. The `Result` count in `src-tauri/src/` is essentially unchanged from the measured baseline of 1,138 (CONCERNS.md's 1,118 is stale) - display-only errors were not touched **Plans**: 0/4 plans executed diff --git a/.planning/STATE.md b/.planning/STATE.md index b24fd7ba..e7188df3 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -136,7 +136,7 @@ None yet. ### Blockers/Concerns -- **Phase 3's ERR-04 count band is coupled to `hwped.rs`.** The pinned command reports 1,138 on the tree that adopts the bridge, and `hwped.rs` contributes 19 of those matches; without it the tree reads 1,119 and the post-migration count lands at 1,109, below `03-04-PLAN.md`'s `[1118, 1138]` band. Re-measure the baseline before Phase 3 executes and write the new number into `03-02-PLAN.md` and `03-04-PLAN.md` - continued hwp-editor work keeps moving it. +- **Phase 3's ERR-04 count band is coupled to `hwped.rs`.** The pinned command reports 1,138, and `hwped.rs` contributes 19 of those matches; without it the tree reads 1,119 and the post-migration count lands at 1,109, below `03-04-PLAN.md`'s `[1118, 1138]` band. The baseline is now anchored to a commit rather than a date - re-confirmed 2026-08-23 on the committed tree at 34f96ee - and `03-02`/`03-04` cite that provenance. Residual risk: the hwp-editor track is still active, so `03-04` now requires a re-measurement at the start of the plan rather than treating drift as exceptional. - `src/App.tsx` has no test of any kind. Phases 4-5 depend on Phase 1's hook-dependency gate plus the per-pane tests written during extraction; there is no existing safety net for the decomposition. - `make verify` runs on ubuntu-22.04 only and e2e runs Chromium against Vite with mocked IPC. Nothing in CI exercises WKWebView, the real PTY, IME input, or the macOS menu - macOS-affecting changes need a real-app run. diff --git a/.planning/phases/03-typed-ipc-error-contract/03-02-PLAN.md b/.planning/phases/03-typed-ipc-error-contract/03-02-PLAN.md index 3be2c448..793f5523 100644 --- a/.planning/phases/03-typed-ipc-error-contract/03-02-PLAN.md +++ b/.planning/phases/03-typed-ipc-error-contract/03-02-PLAN.md @@ -121,7 +121,7 @@ Output: the full Rust emit side of the contract; `today_apply_plan_result` adapt Per D-01/D-02: change `assert_expected_revision` (:122-132) to return `Result<(), IpcError>`, constructing `IpcError { code: DOCUMENT_CONFLICT.to_string(), message: format!("expected revision {expected}, found {actual}") }`. Flip `save_document` (:134-193) to `Result`. The two inline missing-file conflict returns (:150-152 and :185-188) construct IpcError with DOCUMENT_CONFLICT and message `format!("expected revision {expected}, file is missing")` (prefix removed, suffix verbatim). The "Cannot read document: {err}" map_err paths and every other String error path (resolve_inside_vault, assert_document_owner, assert_maru_can_write, validate_managed_write, snapshot writing, write_atomic, read_document tail-call) ride `From` UNCHANGED — do not reword them (prohibition: byte-identical text; PATTERNS explicitly sanctions non-contract paths keeping their strings via the conversion, and no non-contract code is added to the TS union). Migrate the test assertions at :738 and :1227 to the new shape in behavior above. Import from `crate::ipc_error`. - Then run the pinned ERR-04 count command — `grep -roE "Result<.*, String>" src-tauri/src --include="*.rs" | wc -l` — and record the number in the task commit message / SUMMARY for plan 03-04's guard (planning-time baseline: 1,138 measured 2026-08-23; expected after both this plan's tasks: roughly 1,128 — the 7 commands + 3 helpers flip — but the recorded measurement is what 03-04 asserts against). + Then run the pinned ERR-04 count command — `grep -roE "Result<.*, String>" src-tauri/src --include="*.rs" | wc -l` — and record the number in the task commit message / SUMMARY for plan 03-04's guard (planning-time baseline: 1,138, re-confirmed 2026-08-23 on the committed tree at 34f96ee, the merge that adopted the hwp-editor bridge - 19 of those matches live in hwped.rs, so the baseline is only valid for a tree that contains it; expected after both this plan's tasks: roughly 1,128 — the 7 commands + 3 helpers flip — but the recorded measurement is what 03-04 asserts against). cd src-tauri && cargo test --lib document && cargo clippy --lib -- -D warnings && cd .. && grep -roE "Result<.*, String>" src-tauri/src --include="*.rs" | wc -l diff --git a/.planning/phases/03-typed-ipc-error-contract/03-04-PLAN.md b/.planning/phases/03-typed-ipc-error-contract/03-04-PLAN.md index 2613d0c7..03006a57 100644 --- a/.planning/phases/03-typed-ipc-error-contract/03-04-PLAN.md +++ b/.planning/phases/03-typed-ipc-error-contract/03-04-PLAN.md @@ -17,7 +17,7 @@ estimate: must_haves: truths: - "[ERR-02] The rename drill is proven both directions: renaming a code constant fails cargo test on the Rust side, and renaming a union literal fails tsc on the TypeScript side — both observed red, then reverted to green" - - "[edge:boundary/ERR-04] The pinned count command (grep -roE over src-tauri/src for Result<*, String> signatures) reports within [1118, 1138] — planning baseline 1,138 measured 2026-08-23 minus the 10-item migration set, never above baseline, measured with the identical command before and after" + - "[edge:boundary/ERR-04] The pinned count command (grep -roE over src-tauri/src for Result<*, String> signatures) reports within [1118, 1138] — planning baseline 1,138 re-confirmed 2026-08-23 on the committed tree at 34f96ee, minus the 10-item migration set, never above baseline, measured with the identical command before and after" - "[ERR-03] The residual-matcher grep over src/ for substring matchers on the four contract codes returns zero (re-run as a phase-gate, not just at 03-03)" - "Full make verify is green with the migrated contract in place" - "D-06: the local, non-IPC matchers stay out of the contract and untouched — `clipboard.ts:30`'s \"clipboard is empty\" match and the `RibbonTable.tsx:84-86` diagram string matches are not migrated and not covered by the ERR-03 residual grep" @@ -104,9 +104,9 @@ Output: drill evidence and the final count in the SUMMARY; full verify green. - Makefile (:321 — verify target) - - ERR-04 guard: re-run the pinned command — `grep -roE "Result<.*, String>" src-tauri/src --include="*.rs" | wc -l` — and assert the result is within [1118, 1138]: the planning baseline is 1,138 (measured 2026-08-23 with this exact command; RESEARCH Pitfall 6 — CONCERNS.md's 1,118 is stale), the migration set is 10 signatures (7 commands + 3 helpers), and the count must never exceed the baseline. If the measured value differs from 03-02's recorded number, investigate before proceeding — the delta must be explainable by the migration set alone (re-measure the baseline only if concurrent sessions touched src-tauri/src since 2026-08-23, per the RESEARCH valid-until note; if so, record the new baseline and apply the same ≤20 delta rule). + - ERR-04 guard: re-run the pinned command — `grep -roE "Result<.*, String>" src-tauri/src --include="*.rs" | wc -l` — and assert the result is within [1118, 1138]: the planning baseline is 1,138 (re-confirmed 2026-08-23 with this exact command on the committed tree at 34f96ee; RESEARCH Pitfall 6 — CONCERNS.md's 1,118 is stale), the migration set is 10 signatures (7 commands + 3 helpers), and the count must never exceed the baseline. If the measured value differs from 03-02's recorded number, investigate before proceeding — the delta must be explainable by the migration set alone (**re-measure the baseline at the start of this plan, always** - 19 of the 1,138 matches live in hwped.rs and the hwp-editor track is still active, so drift is expected rather than exceptional. Record the new baseline, apply the same ≤20 delta rule, and update the band in this plan's automated check before asserting against it). - ERR-03 guard: re-run the residual-matcher grep — `grep -rnE '\.includes\("(today_conflict|task_conflict|document_conflict|evidence_binder_revision_conflict)"' src/` — and assert zero matches (the four codes are branched on only via err.code now). Also confirm `grep -rn "todayErrorCode" src/ e2e/` is empty (D-08 retirement held). - - Full gate: run `make verify` and confirm green end-to-end (typecheck, lint, test-ts, test-rust, fmt-check, clippy, build-frontend — Makefile:321). Per the Phase 1 shared-checkout lesson, if a gate fails solely inside files owned by a concurrent session (e.g. uncommitted hwped.rs/lib.rs changes from another session), verify each gate this phase owns individually and record the situation in the SUMMARY rather than diagnosing foreign files. + - Full gate: run `make verify` and confirm green end-to-end (typecheck, lint, test-ts, test-rust, fmt-check, clippy, build-frontend — Makefile:321). The Phase 1 and 2 escape hatch for uncommitted hwped.rs/lib.rs no longer applies: that work is committed as of 34f96ee and `make verify` is green end-to-end on it, so a red gate here is this phase's to diagnose. - Record the final count and both grep results in the SUMMARY. From 66e919847bc212f73bde833cdbabe48db35cf5e5 Mon Sep 17 00:00:00 2001 From: Young Joon Lee Date: Sun, 23 Aug 2026 10:36:36 +0900 Subject: [PATCH 2/2] fix(03): measure the ERR-04 baseline before the first migration, not after MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two review findings on #278, both correct. P2 — the re-measure instruction landed in the wrong plan. 03-04 runs after 03-01 and 03-02 have already flipped signatures, so "re-measure the baseline at the start of this plan" observes the post-migration count (~1,128), not a baseline. Recording that as one and shifting the band would let unintended conversions pass unnoticed. The measurement moves to where the tree is still pristine: 03-01's action now opens by running the pinned command and recording the result as the phase's pre-migration baseline B, before any file is edited (03-01 flips evidence_binder_mutate, so it cannot be taken later). 03-02 records its count against B minus 10; 03-04 asserts within [B-20, B] and derives the band from B rather than re-deriving a baseline. The literal [1118, 1138] stays as the expected values, with an explicit substitution note in the automated check. P2 — 03-CONTEXT.md still prescribed 1,118 in two places while the requirement now says 1,138. The plans consume that context as implementation guidance, so the two sources were prescribing incompatible guards. Context now cites the measured baseline, and the CONCERNS.md quotation is marked stale in place (RESEARCH Pitfall 6 had already established that). --- .../phases/03-typed-ipc-error-contract/03-01-PLAN.md | 3 ++- .../phases/03-typed-ipc-error-contract/03-02-PLAN.md | 2 +- .../phases/03-typed-ipc-error-contract/03-04-PLAN.md | 11 ++++++----- .../phases/03-typed-ipc-error-contract/03-CONTEXT.md | 11 +++++++---- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/.planning/phases/03-typed-ipc-error-contract/03-01-PLAN.md b/.planning/phases/03-typed-ipc-error-contract/03-01-PLAN.md index 0e6bc295..0bcc2928 100644 --- a/.planning/phases/03-typed-ipc-error-contract/03-01-PLAN.md +++ b/.planning/phases/03-typed-ipc-error-contract/03-01-PLAN.md @@ -105,6 +105,7 @@ Output: `src-tauri/src/ipc_error.rs`, `src/lib/ipcError.ts` + tests, the `IpcErr - TS: normalizeIpcError is idempotent — an already-normalized IpcError instance is returned by identity (same object, unchanged), so re-normalizing never produces a doubled "code: code: message" prefix (checker revision: the browser-mock path in this plan and the e2e-fixture paths in 03-03 route pre-thrown errors through the same normalizer). + ERR-04 BASELINE — do this FIRST, before editing any file. Run the pinned count command `grep -roE "Result<.*, String>" src-tauri/src --include="*.rs" | wc -l` and record the result in 03-01-SUMMARY.md as the phase's pre-migration baseline B. This plan flips `evidence_binder_mutate`, so the count stops being pristine the moment the tracer lands, and 03-04 runs far too late to establish one. The planning-time figure is 1,138 (re-confirmed on the committed tree at 34f96ee), but the measured B is what 03-02 and 03-04 assert against — do not substitute the planning-time constant if they differ. RUST — create src-tauri/src/ipc_error.rs per RESEARCH Pattern 1 and PATTERNS, with these exact decisions (Claude's-discretion items, decided here): - `#[derive(Debug, Clone, serde::Serialize)] pub struct IpcError { pub code: String, pub message: String }` — both fields are single lowercase words, so no serde rename attribute (per PATTERNS). `code` is an owned String, NOT &'static str: `impl From for IpcError` must exist so that every legacy `?`/map_err String path inside migrated commands converts without edits, and From puts the WHOLE original string into `message` with `code` set to the empty string (this keeps display-only text byte-identical — the behavior-preserving rule Phase 2 applied to ensure_within). - `impl std::fmt::Display for IpcError`: when `code` is empty, write only `message`; otherwise write code, ": ", message (hub_client/http.rs:25-35 idiom). @@ -198,5 +199,5 @@ A revision conflict in the evidence binder reaches the component as a typed `Ipc -Create `.planning/phases/03-typed-ipc-error-contract/03-01-SUMMARY.md` when done. Record: the checkpoint outcome (including the 7-command scope ratification), the exact Display/normalization semantics chosen, and any deviation from this plan. +Create `.planning/phases/03-typed-ipc-error-contract/03-01-SUMMARY.md` when done. Record: **the pre-migration ERR-04 baseline B measured before any edit** (03-02 and 03-04 assert against it), the checkpoint outcome (including the 7-command scope ratification), the exact Display/normalization semantics chosen, and any deviation from this plan. diff --git a/.planning/phases/03-typed-ipc-error-contract/03-02-PLAN.md b/.planning/phases/03-typed-ipc-error-contract/03-02-PLAN.md index 793f5523..cba53acb 100644 --- a/.planning/phases/03-typed-ipc-error-contract/03-02-PLAN.md +++ b/.planning/phases/03-typed-ipc-error-contract/03-02-PLAN.md @@ -121,7 +121,7 @@ Output: the full Rust emit side of the contract; `today_apply_plan_result` adapt Per D-01/D-02: change `assert_expected_revision` (:122-132) to return `Result<(), IpcError>`, constructing `IpcError { code: DOCUMENT_CONFLICT.to_string(), message: format!("expected revision {expected}, found {actual}") }`. Flip `save_document` (:134-193) to `Result`. The two inline missing-file conflict returns (:150-152 and :185-188) construct IpcError with DOCUMENT_CONFLICT and message `format!("expected revision {expected}, file is missing")` (prefix removed, suffix verbatim). The "Cannot read document: {err}" map_err paths and every other String error path (resolve_inside_vault, assert_document_owner, assert_maru_can_write, validate_managed_write, snapshot writing, write_atomic, read_document tail-call) ride `From` UNCHANGED — do not reword them (prohibition: byte-identical text; PATTERNS explicitly sanctions non-contract paths keeping their strings via the conversion, and no non-contract code is added to the TS union). Migrate the test assertions at :738 and :1227 to the new shape in behavior above. Import from `crate::ipc_error`. - Then run the pinned ERR-04 count command — `grep -roE "Result<.*, String>" src-tauri/src --include="*.rs" | wc -l` — and record the number in the task commit message / SUMMARY for plan 03-04's guard (planning-time baseline: 1,138, re-confirmed 2026-08-23 on the committed tree at 34f96ee, the merge that adopted the hwp-editor bridge - 19 of those matches live in hwped.rs, so the baseline is only valid for a tree that contains it; expected after both this plan's tasks: roughly 1,128 — the 7 commands + 3 helpers flip — but the recorded measurement is what 03-04 asserts against). + Then run the pinned ERR-04 count command — `grep -roE "Result<.*, String>" src-tauri/src --include="*.rs" | wc -l` — and record the number in the task commit message / SUMMARY for plan 03-04's guard (the authoritative baseline is B, the pre-migration count 03-01 measured and recorded in its SUMMARY before touching any file — not a planning-time constant. The planning-time figure was 1,138, re-confirmed 2026-08-23 on the committed tree at 34f96ee; 19 of those matches live in hwped.rs and the hwp-editor track is still active, so B may legitimately differ. Expected here: B minus 10 — the 7 commands + 3 helpers flip, with 03-01's own evidence_binder flip already inside B's delta. Record both the measured number and B minus 10 so 03-04 can check them against each other). cd src-tauri && cargo test --lib document && cargo clippy --lib -- -D warnings && cd .. && grep -roE "Result<.*, String>" src-tauri/src --include="*.rs" | wc -l diff --git a/.planning/phases/03-typed-ipc-error-contract/03-04-PLAN.md b/.planning/phases/03-typed-ipc-error-contract/03-04-PLAN.md index 03006a57..7e07cfe8 100644 --- a/.planning/phases/03-typed-ipc-error-contract/03-04-PLAN.md +++ b/.planning/phases/03-typed-ipc-error-contract/03-04-PLAN.md @@ -17,7 +17,7 @@ estimate: must_haves: truths: - "[ERR-02] The rename drill is proven both directions: renaming a code constant fails cargo test on the Rust side, and renaming a union literal fails tsc on the TypeScript side — both observed red, then reverted to green" - - "[edge:boundary/ERR-04] The pinned count command (grep -roE over src-tauri/src for Result<*, String> signatures) reports within [1118, 1138] — planning baseline 1,138 re-confirmed 2026-08-23 on the committed tree at 34f96ee, minus the 10-item migration set, never above baseline, measured with the identical command before and after" + - "[edge:boundary/ERR-04] The pinned count command (grep -roE over src-tauri/src for Result<*, String> signatures) reports within [B-20, B] where B is the pre-migration baseline 03-01 measured before any edit — expected [1118, 1138] from the planning-time 1,138 re-confirmed 2026-08-23 on the committed tree at 34f96ee, minus the 10-item migration set, never above baseline, measured with the identical command before and after" - "[ERR-03] The residual-matcher grep over src/ for substring matchers on the four contract codes returns zero (re-run as a phase-gate, not just at 03-03)" - "Full make verify is green with the migrated contract in place" - "D-06: the local, non-IPC matchers stay out of the contract and untouched — `clipboard.ts:30`'s \"clipboard is empty\" match and the `RibbonTable.tsx:84-86` diagram string matches are not migrated and not covered by the ERR-03 residual grep" @@ -104,16 +104,17 @@ Output: drill evidence and the final count in the SUMMARY; full verify green. - Makefile (:321 — verify target) - - ERR-04 guard: re-run the pinned command — `grep -roE "Result<.*, String>" src-tauri/src --include="*.rs" | wc -l` — and assert the result is within [1118, 1138]: the planning baseline is 1,138 (re-confirmed 2026-08-23 with this exact command on the committed tree at 34f96ee; RESEARCH Pitfall 6 — CONCERNS.md's 1,118 is stale), the migration set is 10 signatures (7 commands + 3 helpers), and the count must never exceed the baseline. If the measured value differs from 03-02's recorded number, investigate before proceeding — the delta must be explainable by the migration set alone (**re-measure the baseline at the start of this plan, always** - 19 of the 1,138 matches live in hwped.rs and the hwp-editor track is still active, so drift is expected rather than exceptional. Record the new baseline, apply the same ≤20 delta rule, and update the band in this plan's automated check before asserting against it). + - ERR-04 guard: re-run the pinned command — `grep -roE "Result<.*, String>" src-tauri/src --include="*.rs" | wc -l` — and assert the result is within [1118, 1138]: the baseline is B from 03-01-SUMMARY.md, expected to be 1,138 (re-confirmed 2026-08-23 with this exact command on the committed tree at 34f96ee; RESEARCH Pitfall 6 — CONCERNS.md's 1,118 is stale), the migration set is 10 signatures (7 commands + 3 helpers), and the count must never exceed the baseline. If the measured value differs from 03-02's recorded number, investigate before proceeding — the delta must be explainable by the migration set alone (**do NOT re-measure a baseline here.** This plan runs after 03-01 and 03-02 have already flipped signatures, so a measurement taken now observes the post-migration count, not a baseline; recording it as one would let unintended conversions pass. The authoritative baseline is B, measured by 03-01 before any edit and recorded in 03-01-SUMMARY.md. If B differs from the planning-time 1,138 — 19 of those matches live in hwped.rs and the hwp-editor track is still active — derive the band as [B-20, B] and substitute it into this plan's automated check before asserting). - ERR-03 guard: re-run the residual-matcher grep — `grep -rnE '\.includes\("(today_conflict|task_conflict|document_conflict|evidence_binder_revision_conflict)"' src/` — and assert zero matches (the four codes are branched on only via err.code now). Also confirm `grep -rn "todayErrorCode" src/ e2e/` is empty (D-08 retirement held). - Full gate: run `make verify` and confirm green end-to-end (typecheck, lint, test-ts, test-rust, fmt-check, clippy, build-frontend — Makefile:321). The Phase 1 and 2 escape hatch for uncommitted hwped.rs/lib.rs no longer applies: that work is committed as of 34f96ee and `make verify` is green end-to-end on it, so a red gate here is this phase's to diagnose. - Record the final count and both grep results in the SUMMARY. - COUNT=$(grep -roE "Result<.*, String>" src-tauri/src --include="*.rs" | wc -l | tr -d ' ') && [ "$COUNT" -ge 1118 ] && [ "$COUNT" -le 1138 ] && ! grep -rnE '\.includes\("(today_conflict|task_conflict|document_conflict|evidence_binder_revision_conflict)"' src/ && make verify + # Substitute B from 03-01-SUMMARY.md if it differs from 1138: LO=$((B-20)) HI=$B +COUNT=$(grep -roE "Result<.*, String>" src-tauri/src --include="*.rs" | wc -l | tr -d ' ') && [ "$COUNT" -ge 1118 ] && [ "$COUNT" -le 1138 ] && ! grep -rnE '\.includes\("(today_conflict|task_conflict|document_conflict|evidence_binder_revision_conflict)"' src/ && make verify - - The pinned count command prints a value in [1118, 1138] and the value is recorded in the SUMMARY + - The pinned count command prints a value in [B-20, B] (expected [1118, 1138]) and both the value and B are recorded in the SUMMARY - The residual-matcher grep over src/ prints nothing; the retired-parser grep over src/ and e2e/ prints nothing - `make verify` exits 0 (or the Phase 1 shared-checkout exception is documented per gate with each owned gate proven green individually) @@ -149,7 +150,7 @@ Output: drill evidence and the final count in the SUMMARY; full verify green. - Rename drill: red evidence recorded both directions, both files reverted -- ERR-04 count within [1118, 1138] via the pinned command +- ERR-04 count within [B-20, B] via the pinned command, B being 03-01's recorded pre-migration baseline (expected [1118, 1138]) - ERR-03 residual-matcher grep empty; retired-parser grep empty - `make verify` green (or the documented shared-checkout exception) diff --git a/.planning/phases/03-typed-ipc-error-contract/03-CONTEXT.md b/.planning/phases/03-typed-ipc-error-contract/03-CONTEXT.md index 99764de1..565f9f41 100644 --- a/.planning/phases/03-typed-ipc-error-contract/03-CONTEXT.md +++ b/.planning/phases/03-typed-ipc-error-contract/03-CONTEXT.md @@ -10,8 +10,9 @@ Give the errors the frontend branches on a stable machine-readable `code`, so a rename breaks the build on both sides instead of silently breaking a recovery path. Covers ERR-01..04: a typed `{ code, message }` contract over IPC for the branch-on set, a two-sided rename-fails-the-build mechanism, migration of the -existing `message.includes(...)` matchers, and zero touch to the 1,118 -display-only `Result` signatures. +existing `message.includes(...)` matchers, and zero touch to the ~1,138 +display-only `Result` signatures (measured baseline; CONCERNS.md's +1,118 is stale). @@ -95,7 +96,8 @@ display-only `Result` signatures. ### Evidence - `.planning/codebase/CONCERNS.md` §Tech Debt — "Stringly-typed IPC errors": - the 1,118 signatures, the two existing error enums + the 1,118 signatures (stale as written; the measured baseline is 1,138 — + RESEARCH Pitfall 6), the two existing error enums (`src-tauri/src/agent_host/status.rs:351`, `src-tauri/src/hub_client/http.rs:19`), and the prescribed `{ code, message }` struct + `types.ts` mirror approach @@ -136,7 +138,8 @@ display-only `Result` signatures. ## Specific Ideas -- ERR-04's guard is a count: `Result` stays within a few of 1,118 — +- ERR-04's guard is a count: `Result` stays within a few of the + pre-migration baseline 03-01 measures (planning-time figure 1,138) — the four migrated commands are the only signature changes. - The phase's own proof of ERR-02 is a deliberate rename drill: rename a code on one side, watch `make verify` go red on the other, revert (the Phase 1