Scala on Go — and the feedback loop an AI coding agent actually wants.
A coding agent is only as fast as its feedback signal. It works in discrete generate → check → fix turns, and the quality of “check” decides how many turns it burns to reach correct code. GALA’s compiler turns whole classes of bugs into an instant, precise, deterministic error at the exact edit site — no test harness, no lucky code-path coverage, no runtime surprise.
This is not a claim that GALA writes better code. It’s a claim about loop economics: where the error surfaces, how precise it is, and whether the agent has to run the program to discover it.

Human developers tolerate a loose feedback loop because they hold context in their heads. An agent doesn’t — every turn that requires running code costs more than a turn that only requires compiling it.
| Loosely-checked language | GALA (compile-time fast-fail) | |
|---|---|---|
| Where the bug shows | runtime, only on an exercised path | build time, always |
| To even reach it | write and run a test harness | just gala build |
| Precision | stack trace at the symptom | file:line at the root edit + what’s missing |
| Determinism | flaky / path-dependent | same input → same error |
| Escapes to prod | yes, if untested | no — it will not compile |
Fewer turns per fix, and no “did my test actually cover that path?” gamble. The compiler is a free, exhaustive reviewer the agent can call on every turn.
The single most common refactor an agent performs is extending a closed set —
“add a Crypto payment method.” Here a sealed type is matched on in three places.
The agent adds the variant and forgets the match sites — the realistic mistake.
GALA — compiler hands you a worklist
sealed type Payment {
case Card(Last4 string)
case Cash()
case Bank(Iban string)
case Crypto(Chain string) // agent added
}
// three match sites now incomplete
func label(p Payment) string = ...
func fee(p Payment) float64 = ...
func requiresName(p Payment) bool = ...
Go — compiles clean, ships the bug
type Payment interface{ isPayment() }
type Card struct{ Last4 string }
type Cash struct{}
type Bank struct{ Iban string }
type Crypto struct{ Chain string } // added
func label(p Payment) string {
switch v := p.(type) {
case Card: return "card ****" + v.Last4
case Cash: return "cash"
case Bank: return "bank " + v.Iban
}
return "" // Crypto silently lands here
}
Run each build. GALA fails, and names the exact site and the missing variant — one precise task per build, until green:
$ gala run main.gala
[GALA-E0002] line 13:4 non-exhaustive match: missing cases: Crypto
(hint: add the missing variant cases, or add a `case _ => ...` default)
# fix label(), rebuild → line 20:4 (fee)
# fix fee(), rebuild → line 27:4 (requiresName)
# fix all three → compiles, runs
Go compiles the same mistake with no error and no warning, and
label(Crypto{"eth"}) returns "" at runtime — forever, unless a test happens
to pass a Crypto value through label and assert the result. The agent would
have to predict the exact bug in advance. Dynamically-typed languages are worse:
the mistake hides until that line executes in production.
(The transcript above is real output from GALA — the compiler stops at the first incomplete site, so each build is a deterministic step toward green.)
Exhaustiveness is the flagship, but the same runtime → compile-time shift runs through the language. Each one is another class of bug the agent is told about for free, instead of having to discover by running code:
match — extend a closed set, get a complete
worklist of every site to update.Option[T] / Try[T] instead of nil / (T, error) — “forgot the empty
or error case” becomes a type error, not a nil panic three calls deep.any — an unresolved type is a hard error at
the edit, so the agent can’t paper over a mistake with interface{}.Codec[T] — malformed patterns and shape
mismatches fail the build, not a request handler.Every one converts a “write a test and hope” turn into a “read the compiler” turn.
Crypto case; it can’t know the fee should be 0.015. Agents
still need tests for behavior.Option, immutability, and errors