Skip to content

fix(parse): classify every spawn candidate as InvokeSpawn (calque#189 follow-up) - #192

Merged
scttfrdmn merged 1 commit into
mainfrom
fix/calque-189-followup-classify-candidates
Aug 15, 2026
Merged

fix(parse): classify every spawn candidate as InvokeSpawn (calque#189 follow-up)#192
scttfrdmn merged 1 commit into
mainfrom
fix/calque-189-followup-classify-candidates

Conversation

@scttfrdmn

Copy link
Copy Markdown
Contributor

Summary

This is a follow-up to #190 (calque#189), prompted by a direct question: "why not synthesize a test that exercises what the AI-Almanac script is doing under controlled and understood conditions?" I hadn't — I'd only tested SpawnCallSites in isolation. Writing the actual end-to-end pipeline test surfaced a real second bug.

Why the original PR missed this

The original fix touched two layers (SpawnCallSites for call-site resolution) but I only unit-tested that layer in isolation, plus one subprocess-level test confirming the JSON wire shape. I never assembled the real pipeline (Parse → ResolveSpawnCallables → SpawnCallSitesReport → BuildSpawnManifests) end-to-end — which is exactly what spawnRunFromScript (cmd/calque/spawnrun.go) actually does. The defect lived in the gap between two already-individually-tested layers, invisible to either one's own unit tests.

What this PR adds

  • The classification fix itself (internal/parse/parse.go).
  • TestInvocationKindsClassifiesSpawnCandidatesNotEmptyTarget — pure unit test on invocationKinds.
  • cmd/calque/spawn_dict_dispatch_e2e_test.go's TestSpawnDictDispatchEndToEndProducesRealShards — a real end-to-end test wiring the full pipeline together against the spawn_dict_dispatch.py fixture, asserting a real, non-empty shard comes out the other end. Verified this test actually fails without the fix (reverted parse.go locally, confirmed both assertions fail with the exact "zero callables" symptom, then restored the fix).

Also found, filed separately (not fixed here)

calque#191: spawn-run only ever binds a spawned callable's FIRST positional arg regardless of its real arity (found via the same end-to-end test — bundle's job_id/config args showed only job_id bound in the built shard's payload). This is a distinct, pre-existing limitation in spawnshard.go's own binding protocol, out of scope for #189's target-resolution fix — calque#187's arity guard doesn't cover spawn-run's separate driver at all.

Test plan

  • go build ./... && go vet ./... && gofmt -l . && go test -count=1 ./... — all pass
  • golangci-lint run ./... — 0 issues
  • ruff check . — all checks passed
  • Confirmed TestSpawnDictDispatchEndToEndProducesRealShards fails without this fix (manually reverted parse.go, re-ran, confirmed the exact "0 callables / 0 shards" failure), passes with it

…pty target (calque#189 follow-up)

calque#189's SpawnCallSites candidate expansion made a dict-subscript
.spawn() call site visible, but invocationKinds' consider() call for the
"spawn" case was still keyed on the empty ic.Target -- the candidate
callable's own ir.Function.Invoke never became InvokeSpawn, so
ResolveSpawnCallables found zero callables and BuildSpawnManifests
produced zero shards. The exact failure #189 was filed to prevent, one
layer deeper.

Found by writing a synthesized end-to-end test
(cmd/calque/spawn_dict_dispatch_e2e_test.go) that wires
Parse->ResolveSpawnCallables->SpawnCallSitesReport->BuildSpawnManifests
together against the real fixture, instead of only asserting on
SpawnCallSites in isolation -- confirmed the test fails without this fix
and passes with it. The defect lived in the gap between two
already-individually-tested layers.

Also filed calque#191 (not fixed here): spawn-run only ever binds a
spawned callable's FIRST positional arg regardless of its real arity --
a distinct, pre-existing limitation this investigation surfaced but is
out of scope for #189's own target-resolution fix.
@scttfrdmn
scttfrdmn merged commit 5e218d1 into main Aug 15, 2026
7 checks passed
@scttfrdmn
scttfrdmn deleted the fix/calque-189-followup-classify-candidates branch August 15, 2026 22:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant