Skip to content

Commit 42351a8

Browse files
alicodingclaude
andcommitted
fix: list-search seed and authoring e2e drop their clipboard tail (Linux CI)
PR #11's three red shards traced to ONE cause (confirmed via CI artifacts): the new seed and the configure-lists authoring test both ended in apply-clipboard-write-text, which errors on Linux (no pbcopy/osascript) — the exact environment class the earlier triage established. Fixed by REMOVING the unneeded node (neither test needs clipboard I/O to prove list-search; the seed now ends at list-search itself, the same warn-only Process-leaf shape list-lookup's sibling seed already uses). Shard 2 was a fail-fast cancellation casualty (50/50 green — matrix fail-fast:false rides the next PR); the codeexec blip was the documented pre-existing flake class, evidenced, untouched. Takeover note: the delegated agent stopped silently mid-verification (third such instance tonight); fix verified and landed by the orchestrator directly. The recurring 'linker contention' commit-gate failures root-caused to DISK FULL, not contention — corrected in the session memory. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FYwojT8GdUbYSoggbvEFft
1 parent fb54330 commit 42351a8

3 files changed

Lines changed: 28 additions & 15 deletions

File tree

frontend/e2e/configure-lists.spec.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,18 @@ test('list-search node: configuring a real match parameter through the Inspector
109109
const panel = activePanel(page)
110110
await panel.getByLabel('Label').fill('E2E list-search config test')
111111

112+
// Deliberately no apply-clipboard-write-text terminal node -- this
113+
// test proves the list-search Inspector's own authoring/execution,
114+
// not clipboard I/O, and a clipboard apply step has no clipboard on
115+
// a headless Linux CI runner (docs/SPEC.md §1.3; the same fix
116+
// applied to the seeded "Example: Country lookup (search)" workflow
117+
// after a real CI failure, builtinworkflows_list.go). Ending at
118+
// list-search itself is an accepted, warn-only Process leaf
119+
// (ADR-0028).
112120
await panel.getByTestId('toggle-palette').click()
113121
await dragPaletteItemToCanvas(page, 'list-search')
114-
await dragPaletteItemToCanvas(page, 'apply-clipboard-write-text')
115-
await expect(panel.locator('.react-flow__node')).toHaveCount(3)
122+
await expect(panel.locator('.react-flow__node')).toHaveCount(2)
116123
await connectNodes(page, 'Trigger: manual', 'List: search')
117-
await connectNodes(page, 'List: search', 'Apply: write plain text to clipboard')
118124

119125
await clickCanvasNode(page, panel, 'List: search')
120126
const inspector = panel.getByTestId('composition-inspector')

internal/domain/composition/builtinworkflows_list.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,19 @@ func builtInListWorkflows() []Workflow {
4545
// Demonstrates a typed Object result (results/matched/first_match/
4646
// match_count/list_id) a downstream step could branch on, not just
4747
// a single scalar Attribute -- list-lookup's own seed above stays
48-
// untouched, proving the two coexist.
48+
// untouched, proving the two coexist. Deliberately ends AT
49+
// list-search itself, mirroring list-lookup's own seed above,
50+
// rather than adding a terminal apply-clipboard-write-text step:
51+
// that step has no clipboard on a headless Linux CI runner
52+
// (docs/SPEC.md §1.3) and would only be exercising clipboard I/O
53+
// this seed isn't actually about -- caught by a real CI failure
54+
// (goal 0011's own PR), not assumed. A Process leaf is an accepted,
55+
// warn-only ending (ADR-0028), the same shape several other seeds
56+
// already use.
4957
const (
5058
listSearchTriggerID = "example-list-search-trigger"
5159
listSearchCaptureID = "example-list-search-capture"
5260
listSearchStepID = "example-list-search-step"
53-
listSearchApplyID = "example-list-search-apply"
5461
)
5562
const listSearchMatchParams = `[{"column":"code","value":"attr:code","matchType":"exact"}]`
5663
listSearchNodes, err := ResolveNodeDefaults([]Node{
@@ -63,7 +70,6 @@ func builtInListWorkflows() []Workflow {
6370
"matchParams": listSearchMatchParams,
6471
"outputAttribute": "searchResult",
6572
}},
66-
{ID: listSearchApplyID, NodeTypeID: "apply-clipboard-write-text", Position: Position{X: 0, Y: 300}},
6773
})
6874
if err != nil {
6975
panic("built-in workflow references an unknown node type: " + err.Error())
@@ -88,7 +94,7 @@ func builtInListWorkflows() []Workflow {
8894
{
8995
ID: "example-list-search-workflow",
9096
Label: "Example: Country lookup (search)",
91-
Description: "Captures a typed 'code' Attribute and searches the seeded \"Example: Country codes\" List (Configure > Lists) via list-search -- an exact match on its 'code' column, writing a typed Object result ({results, matched, first_match, match_count, list_id}) into 'searchResult', then writes the captured code to the clipboard. Unlike list-lookup's plain scalar output, this demonstrates the richer typed result a downstream step (e.g. a Branch condition on searchResult.matched) could reference. Run it with code = US, CA, MX, or FR to see a match -- SU is a deliberately Expired seed row, excluded from matching by default (docs/goals/0011-lists-maturation.md).",
97+
Description: "Captures a typed 'code' Attribute and searches the seeded \"Example: Country codes\" List (Configure > Lists) via list-search -- an exact match on its 'code' column, writing a typed Object result ({results, matched, first_match, match_count, list_id}) into 'searchResult'. Unlike list-lookup's plain scalar output, this demonstrates the richer typed result a downstream step (e.g. a Branch condition on searchResult.matched) could reference. Run it with code = US, CA, MX, or FR to see a match -- SU is a deliberately Expired seed row, excluded from matching by default (docs/goals/0011-lists-maturation.md).",
9298
Nodes: listSearchNodes,
9399
Attributes: []AttributeDef{
94100
{Key: "code", Label: "Code", Type: FieldText},
@@ -97,7 +103,6 @@ func builtInListWorkflows() []Workflow {
97103
Edges: []Edge{
98104
{ID: "example-list-search-e0", Source: listSearchTriggerID, Target: listSearchCaptureID},
99105
{ID: "example-list-search-e1", Source: listSearchCaptureID, Target: listSearchStepID},
100-
{ID: "example-list-search-e2", Source: listSearchStepID, Target: listSearchApplyID},
101106
},
102107
BuiltIn: true,
103108
},

internal/services/executionsvc/listsearch_seed_test.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,14 @@ func TestSeededListSearchExample_Match_WritesTypedResult(t *testing.T) {
6161
if summary.Status != "SUCCESS" {
6262
t.Fatalf("RunWorkflow(code=US) status = %q, want SUCCESS -- error: %s", summary.Status, summary.Error)
6363
}
64-
// The seed's final step (apply-clipboard-write-text) writes the
65-
// captured code itself -- list-search's own typed result lives in
66-
// the 'searchResult' Attribute, not the string Payload/Output,
67-
// proven at the composition-unit-test layer
68-
// (listsearch_test.go) rather than re-asserted here.
64+
// The seed ends AT list-search itself (no terminal apply step --
65+
// a real Linux-CI clipboard failure caught during goal 0011's own
66+
// PR is why, see builtinworkflows_list.go), so the workflow's
67+
// final Payload/Output is still whatever capture-attribute set it
68+
// to; list-search's own typed result lives in the 'searchResult'
69+
// Attribute, not the string Payload/Output, proven at the
70+
// composition-unit-test layer (listsearch_test.go) rather than
71+
// re-asserted here.
6972
if summary.Output != "US" {
7073
t.Errorf("RunWorkflow(code=US) output = %q, want %q", summary.Output, "US")
7174
}
@@ -77,8 +80,7 @@ func TestSeededListSearchExample_NoMatch_WritesUnmatchedResult(t *testing.T) {
7780
// Unlike list-lookup's onMiss="fail" default, list-search never
7881
// fails the run on a miss -- it always writes a typed
7982
// {matched:false, results:[], ...} object and lets the workflow
80-
// continue (a Decision downstream would branch on it). The seed's
81-
// own apply-clipboard-write-text step still runs.
83+
// continue (a Decision downstream would branch on it).
8284
summary, err := exec.RunWorkflow(wfID, RunKindTest, map[string]string{"code": "ZZ"})
8385
if err != nil {
8486
t.Fatalf("RunWorkflow: %v", err)

0 commit comments

Comments
 (0)