Goal 0011 design section (research delivered; build gated on wt-lists decision) - #10
Merged
Conversation
go-edlib adopted for fuzzy (with the industry-default-is-exact framing correction); fixed-by-construction output shape; rows without CreatedBy (§3.2.4's verdict); snapshot-per-execution reframed from correctness gap to audit evidence (DBOS checkpointing already guarantees replay stability — Temporal-precedent-confirmed); storage stays settings-store with a named SQLite trigger. Flags the gating owner decision: wt-lists' near-complete parallel implementation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FYwojT8GdUbYSoggbvEFft
alicoding
enabled auto-merge
August 12, 2026 01:56
alicoding
added a commit
that referenced
this pull request
Aug 12, 2026
… self-cancel Owner-mandated framework, researched to the converged standard and found to need NAMING, not building: Scrum 2020's DoD (a formal artifact commitment) + Kanban University's ready-for-delivery pull criteria are the industry vocabulary for gates this repo already runs — consolidated into ONE always-loaded rule (.claude/rules/delivery-discipline.md) instead of four documents. Estimation deliberately excluded (negotiates team capacity a solo+agent loop doesn't have); peer review already settled by ADR-0034. Build-health becomes a ritual, not a wonder: gh pr checks --watch after opening a goal PR; gh run list -b main -L 1 at goal pickup. Tech debt: same queue, same DoR/DoD, never a shadow register. Plus the real config bug the research found: cancel-in-progress applied to main's post-merge runs too, so two quick merges cancelled the earlier one's verification (observed live: merges #1/#10) — now conditional per GitHub's own documented pattern; PR runs still supersede, main runs always complete. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FYwojT8GdUbYSoggbvEFft
5 tasks
alicoding
added a commit
that referenced
this pull request
Aug 13, 2026
… 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>
alicoding
added a commit
that referenced
this pull request
Aug 13, 2026
… 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>
alicoding
added a commit
that referenced
this pull request
Aug 13, 2026
… second pass, ls-lint node_modules ignore (BACKLOG 10/11) 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. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018pkViCNAuZp2vBv2K9AbUh
alicoding
added a commit
that referenced
this pull request
Aug 15, 2026
New capability: CompositionService.ExportWorkflow/ImportWorkflow (compositionservice_export.go) plus a real Composition UI affordance (Export IconButton per workflow row, an Import button + hidden file input near New workflow) -- not backend-only, per explicit direction that this needs to be visibly checkable in the running app, not just git history. Design decision the goal itself required in writing: exportedWorkflow deliberately omits the workflow's own ID and BuiltIn flag from the wire shape. ImportWorkflow always mints a brand-new workflow via the existing CreateWorkflow (same validation bar as a hand-composed one -- ResolveNodeDefaults, ValidateGraph, no import-specific leniency), matching ADR-0013's Duplicate precedent (copying an entity means a new identity, never resurrecting the old one) -- so importing the same file twice, or into a different Mill instance, can never silently collide with or overwrite an existing workflow. Node/Edge IDs inside the graph ARE preserved as-is (relative references, not global identity). Stable/deterministic by construction, not extra bookkeeping: every exported field is already-stored data, never regenerated on save (confirmed by reading idgen.go directly), and Go's encoding/json guarantees deterministic struct-field and sorted-map-key ordering. Two exports of an unchanged workflow are therefore byte-identical -- proven by a real test (TestExportWorkflow_IsDeterministic), not just asserted -- which is the concrete answer to n8n's own documented git-diff-noise problem researched earlier this session. Two files crossed the 500-line limit adding this (CompositionView.tsx, composition.spec.ts) -- split along real seams, not truncated: TestRunDialog extracted to its own file (self-contained, zero shared state with its parent beyond props, same pattern this repo already uses); the three new e2e tests moved to composition-export-import.spec.ts with their own workflowRow helper, matching the existing convention of 5 other spec files each keeping their own copy rather than a shared helpers file that doesn't otherwise exist here. Verified: 11 new Go tests (round-trip, new-ID-never-reused, two independent imports from the same file, determinism, ID/BuiltIn omitted from the wire shape, unknown-ID/invalid-JSON/empty-label/ invalid-graph-shape rejection, Attributes application) plus the full existing suite, all passing with -race. Full frontend check suite (tsc, eslint, boundaries, vitest) clean. Both e2e spec files run twice in a row per .claude/rules/testing.md's explicit discipline for tests creating persisted entities -- 17/17 both times, confirming cleanup actually works, not just once. Regenerated bindings also carry two small doc-comment-only updates trailing from task #3's Go comment edits (configureservice.ts, models.ts) -- no functional change. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FYwojT8GdUbYSoggbvEFft
alicoding
added a commit
that referenced
this pull request
Aug 15, 2026
…y (task #12) Mill as MCP server for the first time -- §3.1 named three possible MCP roles (server, client, host) back when only client was ever built (§3.6, wrapping external tools as workflow nodes); this closes the server role, already locked as fine ("fits §1.1 cleanly with zero tension") since no LLM/agent loop runs inside Mill here -- an external agent's own host connects and reads, the same shape as httpconnector being an HTTP client. Does not touch or reopen the still-disputed MCP-host question. internal/adapters/mcpserving wraps modelcontextprotocol/go-sdk's server role (the same SDK Mill already depends on for the client role) behind a thin New()/Serve() pair -- new role, not a new dependency. millmcpservice.go registers two URIs per entity type: a plain index resource (mill://workflows, mill://requests, mill://lists, mill://mcpservers) listing every current ID/Label/Description, and a ResourceTemplate (mill://workflows/{id}, etc.) whose read returns the full definition by calling the SAME Export* methods tasks #10/#11 just built for the UI's own Export buttons -- one read-model, reused, not a second one built for this. Secrets stay excluded by the same construction Export* already guarantees, verified independently through this new code path rather than assumed inherited: a real test connects a genuine MCP client over real HTTP, sets a real secret on a real HTTPRequest, reads it back through mill://requests/{id}, and asserts the secret never appears in the wire response. Binds 127.0.0.1:8090 by default (MILL_MCP_ADDR overrides), loopback-only deliberately -- a new unauthenticated local listener, same conservative- default reasoning as the LAN-exposure question elsewhere in this repo. Runs in both desktop and server-mode builds (no build tag); confirmed the second listener doesn't conflict with server mode's existing :8080 via a real Playwright smoke run. A bind failure is logged, not fatal. Explicitly NOT built here, named directly rather than silently dropped: the write side (create/import via MCP Tools). §8's guardrail policy is still OPEN, and programmatic writes are a materially different risk than read-only exposure -- tracked as its own task (#13), not folded into this one. Verified: two new Go tests connect a genuine MCP client (the SDK's own client role, not a mock, not a direct call into the handler functions) over real HTTP -- resources/list returns the real registered set, resources/read against a just-created real workflow returns its real node data, an unknown ID returns a real resource-not-found error, and the secret-exclusion test above. Full existing suite passes with -race. go vet, golangci-lint (0 issues after fixing two real errcheck findings on deferred session.Close() -- fixed using this repo's own existing defer func() { _ = x.Close() }() convention, not suppressed), ls_lint, check-loc.sh all clean. Documented in docs/SPEC.md §3.6. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FYwojT8GdUbYSoggbvEFft
alicoding
added a commit
that referenced
this pull request
Aug 15, 2026
… self-cancel Owner-mandated framework, researched to the converged standard and found to need NAMING, not building: Scrum 2020's DoD (a formal artifact commitment) + Kanban University's ready-for-delivery pull criteria are the industry vocabulary for gates this repo already runs — consolidated into ONE always-loaded rule (.claude/rules/delivery-discipline.md) instead of four documents. Estimation deliberately excluded (negotiates team capacity a solo+agent loop doesn't have); peer review already settled by ADR-0034. Build-health becomes a ritual, not a wonder: gh pr checks --watch after opening a goal PR; gh run list -b main -L 1 at goal pickup. Tech debt: same queue, same DoR/DoD, never a shadow register. Plus the real config bug the research found: cancel-in-progress applied to main's post-merge runs too, so two quick merges cancelled the earlier one's verification (observed live: merges #1/#10) — now conditional per GitHub's own documented pattern; PR runs still supersede, main runs always complete. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FYwojT8GdUbYSoggbvEFft
alicoding
added a commit
that referenced
this pull request
Aug 15, 2026
… 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Records the Lists-maturation research verdicts into the goal file. The build is gated on an owner decision: the wt-lists worktree holds a near-complete parallel implementation — rebase-and-land vs rebuild-from-research is theirs to call.
🤖 Generated with Claude Code
https://claude.ai/code/session_01FYwojT8GdUbYSoggbvEFft