Skip to content

Commit 56ec3fa

Browse files
alicodingclaude
andauthored
chore: hygiene close-out -- resizable-table proper fix, golangci-lint second pass, ls-lint node_modules ignore (BACKLOG 10/11) (#53)
resizable-table.spec.ts (Standing #10, third recurrence post-hardening): structural fix, not another timeout bump. test.describe.configure({ mode: 'serial' }) makes the file's never-interleave requirement explicit; waitForStableBoundingBox polls for the handle's bounding box being IDENTICAL across two consecutive reads (a non-null box mid-reflow was always possible the old check couldn't see); the synthesized drag moved from one batched page.mouse.move(..., { steps: N }) call to discrete, individually-awaited moves (browsers coalesce rapid pointermove events within one CDP command -- real, documented browser behavior via PointerEvent.getCoalescedEvents()); two more expect.polls wait for the drag's actual DOM effect and the localStorage persist to land before the next step depends on them. A keyboard-resize alternative was checked and ruled out -- shared/ResizableTable.tsx has no keyboard path at all, building one would be a feature addition, not a test fix. Verified via 5 separate fresh playwright invocations (10/10) -- an in-process --repeat-each stress loop turned out to be a self-confounding methodology (accumulating same-worker degradation, not representative of a real CI run). golangci-lint second pass (Standing #11b, named future work in goal 0028): gocritic/prealloc/contextcheck/sqlclosecheck enabled. Triaged to zero findings on both build-tag variants -- 14 real findings fixed (1 gocritic assignOp, 13 prealloc slice-capacity hints), zero contextcheck/sqlclosecheck findings, no rule needed a scoped tweak or nolint suppression this pass. .ls-lint.yml (Standing #11c): root ignore: list gains node_modules, with a comment on the root-scoped-recursive-rule interaction that caused the original gap. Claude-Session: https://claude.ai/code/session_018pkViCNAuZp2vBv2K9AbUh Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent d6b33c0 commit 56ec3fa

7 files changed

Lines changed: 215 additions & 105 deletions

File tree

.golangci.yml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,25 @@ linters:
77
- staticcheck
88
# goal 0028, first strengthening pass (security + HTTP-client hygiene
99
# matching what the code actually does -- procexec/httpconnector/
10-
# openapispec are the real attack-surface packages). Second pass
11-
# (gocritic/prealloc/contextcheck/sqlclosecheck) is deliberately not
12-
# part of this goal -- tracked as future work in goal 0028's file.
10+
# openapispec are the real attack-surface packages).
1311
- gosec
1412
- bodyclose
1513
- noctx
1614
- revive
1715
- unparam
16+
# Second pass (docs/goals/BACKLOG.md Standing #11b, named as future
17+
# work in goal 0028): gocritic (style/perf/correctness diagnostics),
18+
# prealloc (slice-append capacity hints), contextcheck (context.Context
19+
# propagation, non-inherited-context bugs), sqlclosecheck (unclosed
20+
# *sql.Rows/*sql.Stmt). Findings triaged to zero on both build-tag
21+
# variants (default + `server`), same discipline as the first pass --
22+
# real ones fixed, a rule that genuinely misfires against this repo's
23+
# own house style gets a scoped settings tweak or a per-line `//nolint`
24+
# with a reason, never a blanket disable.
25+
- gocritic
26+
- prealloc
27+
- contextcheck
28+
- sqlclosecheck
1829
exclusions:
1930
paths:
2031
- frontend

.ls-lint.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,12 @@ ignore:
7474
- .playwright-mcp
7575
- .gitignore
7676
- .DS_Store
77+
# docs/goals/BACKLOG.md Standing #11c: a stray root-level node_modules
78+
# (created by an npm/npx invocation run from the repo root instead of
79+
# frontend/) broke root-file-naming once, 2026-08-12 -- top-level
80+
# rules apply recursively (this file's own scoping note above), so an
81+
# accidental root node_modules would otherwise get every file inside
82+
# it flagged against the .go/.* patterns above. frontend/node_modules
83+
# is already covered by the `frontend` ignore entry; this is
84+
# specifically the root-level accident case.
85+
- node_modules

docs/goals/BACKLOG.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ live-review material, interleaved during owner reviews, not a lane.**
170170
8. [x] [0013 — Canonical type system](archive/0013-canonical-type-system.md) — COMPLETE 2026-08-10 (typedfield leaf pkg; all 4 vocabularies converged incl. openapispec Phase 3; the #1 kernel investment)
171171
9. [x] [0011 — Lists maturation](archive/0011-lists-maturation.md) — DELIVERED 2026-08-12 (harvested from a parallel owner session + reconciled onto main: typed Columns/Rows against ADR-0029's canonical typedfield, system-managed audit columns w/ Expired-excluded-by-default, `list-search` node w/ go-edlib fuzzy matching, in-place legacy-List migration; CSV import + full per-run dataset snapshot named-deferred)
172172
10. [x] [0014 — Home dashboard / value mirror](archive/0014-home-dashboard.md) — delivered 2026-08-10 (Recharts, industry-decided metric semantics, editable minutes-saved, default landing)
173-
11. [ ] [0015 — Summon quick-invoke](0015-summon-quick-invoke.md) — CORE delivered 2026-08-11 (⌘K palette: commands with inline shortcuts, workflow run, tab jump/close; delegated build); PHASE 2 delivered same day (ADR-0033: the summon hotkey opens a dedicated floating Quick Panel — frameless, floats over fullscreen, Esc/blur dismiss, focus-yield; supersedes "summon opens the main window"). REMAINDER delivered 2026-08-12 (session 1), into the Quick Panel: frecency sort (frequency-only, `app/workflowFrecency.ts` off goal 0014's `HomeMetrics.mostUsed`), pending-review count (own window-local read+subscribe, `QuickPanel.tsx`), Configure entities as jumpable rows (`configure:<tab>` via new `app/useMillNavigate.ts` + `ConfigureView.initialTab`). INLINE-HOTKEY-HINT (command half) delivered 2026-08-12 (session 2): `app/HotkeyHint.tsx` (`resolveHotkeyLabel`/`useCommandBinding`/`<HotkeyHint>`), the ONE place every inline shortcut chip reads `shared/commands.ts` + `keybindingOverrides` from now (also absorbed CommandPalette's and QuickPanel's own prior independent copies); two new real, rebindable commands `tab.closeOthers` (⌘⌥W) / `tab.closeAll` (⌘⇧W) wired into `WorkTabShell.tsx`'s tab-overflow menu; proven in `e2e/hotkey-hint.spec.ts` including a rebind-in-Settings-updates-the-hint-elsewhere case. Still open, named in the goal file, not silently dropped: the ⌘K palette/Quick Panel's own inline-hotkey-per-WORKFLOW-TRIGGER-row detail (a distinct, still-unbuilt registry — a workflow's own Hotkey trigger combo, not an app-level command's); pins/favorites and the ⌘?/⌘/ multi-binding alias — see their own tech-debt lines below (Standing section).
173+
11. [ ] [0015 — Summon quick-invoke](0015-summon-quick-invoke.md) — CORE delivered 2026-08-11 (⌘K palette: commands with inline shortcuts, workflow run, tab jump/close; delegated build); PHASE 2 delivered same day (ADR-0033: the summon hotkey opens a dedicated floating Quick Panel — frameless, floats over fullscreen, Esc/blur dismiss, focus-yield; supersedes "summon opens the main window"). REMAINDER delivered 2026-08-12 (session 1), into the Quick Panel: frecency sort (frequency-only, `app/workflowFrecency.ts` off goal 0014's `HomeMetrics.mostUsed`), pending-review count (own window-local read+subscribe, `QuickPanel.tsx`), Configure entities as jumpable rows (`configure:<tab>` via new `app/useMillNavigate.ts` + `ConfigureView.initialTab`). INLINE-HOTKEY-HINT (command half) delivered 2026-08-12 (session 2): `app/HotkeyHint.tsx` (`resolveHotkeyLabel`/`useCommandBinding`/`<HotkeyHint>`), the ONE place every inline shortcut chip reads `shared/commands.ts` + `keybindingOverrides` from now (also absorbed CommandPalette's and QuickPanel's own prior independent copies); two new real, rebindable commands `tab.closeOthers` (⌘⌥W) / `tab.closeAll` (⌘⇧W) wired into `WorkTabShell.tsx`'s tab-overflow menu; proven in `e2e/hotkey-hint.spec.ts` including a rebind-in-Settings-updates-the-hint-elsewhere case. Still open, named in the goal file, not silently dropped: the ⌘K palette/Quick Panel's own inline-hotkey-per-WORKFLOW-TRIGGER-row detail (a distinct, still-unbuilt registry — a workflow's own Hotkey trigger combo, not an app-level command's). Pins/favorites and the ⌘?/⌘/ multi-binding alias — their own tech-debt lines in the Standing section — both DELIVERED 2026-08-13.
174174
12. [x] [0022 — Workflow view mode](archive/0022-workflow-view-mode.md) — delivered 2026-08-11 (row click → read-only canvas w/ Run+step-debug; Edit explicit in-place mode switch; breakpoint dot moved onto the node card, both modes; fixed a latent bug where a policy deny could hide a breakpoint's existence)
175175
13. [x] [0036 — View-mode UX hardening](archive/0036-view-mode-ux-hardening.md) — delivered 2026-08-12 (owner-found live UX gaps in goal 0022): table view's Label cell now opens VIEW mode (`WorkflowsTable.tsx`'s Link cell, matching row view's existing click-to-view) — the pencil's straight-to-Edit was the ONLY entry table view had; a "Viewing" mode chip (`CanvasMetaHeader.tsx`, Primer `Label` + `EyeIcon`) makes read-only status legible before touching anything; `NodeInspector`'s disabled `<fieldset>` now renders visibly muted (`opacity`/`cursor` on `:disabled`) — root cause investigated directly against the installed Primer build: `TextInput`/`Select` key their muted visuals off their OWN `disabled` React prop (a `data-disabled` attribute stamped on an internal wrapper `<span>`), never off the native `:disabled` CSS pseudo-class the fieldset cascade already puts on the real `<input>`/`<select>` underneath — fixed at the fieldset-ancestor CSS level (which genuinely matches `:disabled`) rather than threading a prop through NodeInspector's half-dozen nested editors.
176176
14. [x] [0020 — Workflow breakpoints](archive/0020-workflow-breakpoints.md) — delivered 2026-08-11 (ADR-0031 full scope incl. step mode + MCP debug tools; delegated build; found+fixed the ExecuteOptions.WorkflowID never-set bug that silently disabled all workflow/instance-scoped guardrail rules at runtime)
@@ -204,8 +204,8 @@ live-review material, interleaved during owner reviews, not a lane.**
204204
7. [ ] [0021 — MCP dogfood gap closure](0021-mcp-dogfood-gap-closure.md) Phase 2: orchestrator-driven live MCP probing against the locked-down-enterprise use cases (the mandate names the orchestrator as the prober — self-driveable, exploratory; produces the next ranked gap list). Phase 3 judgments that need the owner surface as they're found.
205205
8. [x] Dev-loop instance guards (tech debt, owner-hit 2026-08-12 evening: THREE concurrent `mill.dev.app` instances in the dock, real crash risk on the 16GB machine) — DELIVERED 2026-08-13, both mechanical fixes landed: (a) per-rebuild reap — `build/config.yml`'s `dev_mode.executes` gained a `type: blocking` `pkill -f "bin/mill.dev.app/Contents/MacOS/mill" || true` step right before the `primary` `wails3 task run` step (blocking steps re-run every reload cycle, confirmed directly against the vendored `github.com/atterpac/refresh` engine source — its own `Primary` case already SHOULD kill-then-restart via a process-group SIGKILL, but a live `task dev` session running during this item's own investigation was caught red-handed with two concurrent `mill.dev.app` processes, one orphaned into a foreign process group refresh's own tracking never reaped; root cause not fully pinned to one line since it's in a vendored third-party dependency, so this reap is an independent, pattern-based backstop rather than a patch to code this repo doesn't own — same shape Taskfile.yml's own start-of-session sweep already used); (b) `task dev` now refuses a second concurrent start — `internal/devguard` (a real Go package, `package main`, unit-tested: `guard_test.go` covers process-list parsing, the wails3-dev-process matcher incl. a real false-positive it caught and fixed against a differently-pathed sibling project, port-PID parsing, and message formatting) runs as the FIRST step of `Taskfile.yml`'s `dev:` task, checks for an already-running `wails3 dev` process for this exact repo, and exits non-zero naming the conflicting PID (+ any port occupancy as corroborating detail) before the destructive sweep steps can run — verified live against a genuinely running session (correctly detected + refused, naming the real PID). Manual-only registry entry added (`.claude/skills/run-mill/SKILL.md`) for what CI structurally can't prove: real per-rebuild-orphan-prevention across several live Go-triggered rebuilds, and a genuine second-terminal `task dev` invocation actually refusing to start.
206206
9. [ ] Dock-bounce on parked approvals (small, unlocked by wails beta.6's Flash() gaining macOS support via NSApp requestUserAttention — PR #44's changelog finding; Mill calls Flash nowhere today) — the attention stack (goal 0023/ADR-0032's away-user layer) gains a one-shot dock bounce when an approval parks while the user is away; kernel attention-layer surface per ADR-0035 (same class as the dock badge), NOT a new composition path. Tiny: one call site in the existing NotifyPendingApproval flow + manual-only registry entry (real dock behavior isn't CI-testable).
207-
10. [ ] resizable-table.spec.ts drag-timing flake, PROPER fix (3 confirmed recurrences POST-hardening: PR #24 original, #43's run, #44's run — the expect.poll hardening from PR #33's wave was insufficient) — the parallel-worker drag-timing race needs a structural fix: serialize the spec (test.describe.configure mode serial in its own worker), or replace the synthesized drag with keyboard-based column resize if the component supports it, or a deterministic wait on the drag handle's post-layout geometry. Not another timeout bump — three strikes means the approach changes.
208-
11. [ ] 0030 second-pass linters (gocritic/prealloc/contextcheck/sqlclosecheck — named future work in goal 0028) + `.ls-lint.yml` gains a root `node_modules` ignore (gap found 2026-08-12: a stray root node_modules broke root-file-naming; tiny, rides this or any PR).
207+
10. [x] resizable-table.spec.ts drag-timing flake, PROPER fix (3 confirmed recurrences POST-hardening: PR #24 original, #43's run, #44's run — the expect.poll hardening from PR #33's wave was insufficient) — DELIVERED 2026-08-13. A keyboard-based resize alternative was checked and ruled out (`shared/ResizableTable.tsx`'s drag handle is built entirely on pointerdown/pointermove/pointerup, no keyboard path at all — building one would be a real feature addition, not a test fix). Landed instead: `test.describe.configure({ mode: 'serial' })` makes the file's own never-interleave requirement explicit rather than an incidental side effect of global config; `waitForStableBoundingBox` replaces the old non-null-only `expect.poll` with a poll for the box being IDENTICAL across two consecutive reads (a non-null box mid-reflow was always possible the old check couldn't see); the synthesized drag itself moved from one batched `page.mouse.move(..., { steps: N })` call to discrete, individually-awaited moves (a browser can coalesce rapid pointermove events within one CDP command — a real, documented behavior via the `PointerEvent.getCoalescedEvents()` API, not Playwright-specific); and two more `expect.poll`s wait for the drag's actual DOM effect and the `localStorage` persist to land before the next step depends on them, instead of assuming the previous Playwright command's own resolution implies the page's JS listener already ran. Verified via 5 separate fresh `npx playwright test` invocations (10/10 passed) — an in-process `--repeat-each` stress loop on the same worker turned out to be a self-confounding methodology (accumulating browser/worker degradation unrelated to the fix, not representative of a real CI run) once cross-checked against genuinely fresh runs.
208+
11. [x] 0030 second-pass linters (gocritic/prealloc/contextcheck/sqlclosecheck — named future work in goal 0028) + `.ls-lint.yml` gains a root `node_modules` ignore (gap found 2026-08-12: a stray root node_modules broke root-file-naming; tiny, rides this or any PR) — DELIVERED 2026-08-13. All four enabled in `.golangci.yml`; triaged to zero findings on both build-tag variants (default + `server`) — 14 real findings fixed (1 `gocritic` assignOp in a test file, 13 `prealloc` slice-capacity hints across `seedproof_test.go` and `millmcpservice.go`'s resource-index readers), zero `contextcheck`/`sqlclosecheck` findings, zero rules needed a scoped tweak or a `//nolint` suppression this pass. `.ls-lint.yml`'s root `ignore:` list gained `node_modules` with a comment explaining the root-scoped-recursive-rule interaction.
209209

210210
**Owner-needed lane (parallel, never blocks the queue)**
211211
- [ ] [0001 — Authoring-surface overhaul](0001-authoring-surface-overhaul.md) (spacing audit + §3.8 prototype elements — live-review material, needs the owner driving; design wave 1 DELIVERED 2026-08-12 — 7 app-wide convention/bug fixes from a full-app audit screenshot pass, zero taste calls; design wave 2 DELIVERED 2026-08-13 — identity tokens: Mill's own accent scale layered over Primer, node-kind canvas colors decoupled from status semantics, one StatusStamp component replacing 7 pill families, a shared mono-font utility; design wave 3 DELIVERED 2026-08-13 — palette IA: 6 domain Kinds regrouped into 9 frontend display groups, label-shortening bug fixed, palette search added, Configure > Attributes conforms to its sibling tabs, Configure row-action icon-button consistency; both design-wave PRs now shipped, goal stays open pending the owner's live sign-off)

0 commit comments

Comments
 (0)