### Original error
```shell
❯ RUST_BACKTRACE=1 hk run pre-commit
thread 'main' (49584) panicked at src/settings.rs:90:30:
Failed to load configuration: Failed to read config file: /Users/jonathan/development/inko-tantivy/hk.pkl
Caused by:
Eval error: field not found: checkFail
Location:
src/config.rs:389:18
stack backtrace:
0: __rustc::rust_begin_unwind
1: core::panicking::panic_fmt
2: core::result::unwrap_failed
3: hk::settings::<impl hk::settings::generated::settings::Settings>::get
4: hk::cli::run::{{closure}}
5: tokio::runtime::park::CachedParkThread::block_on
6: tokio::runtime::runtime::Runtime::block_on
7: hk::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
```
---
### Summary
- Arc-wrap `Lambda` captures so cloning a Lambda is O(1)
- Seed `Null` into `eval_scope` for nullable-no-default base class
properties so `outer.optProp` resolves to `Null` instead of erroring
- Treat `;` as whitespace so Pkl's semicolon property separator is
accepted
---
### Details
#### `outer.before` — field not found
hk's `helpers.pkl` `TestMaker` class uses this pattern:
```pkl
class TestMaker {
before: String?
local function makeTest(...): Config.StepTest = new Config.StepTest {
before = outer.before
...
}
}
```
When `outer.before` was evaluated and `before` had no default value and
was not set on the `TestMaker` instance, `outer` (a snapshot of the
scope before evaluating the object body) didn't contain `before` at all,
causing a "field not found: before" error.
Fix: in `eval_amended_object`, after building `eval_scope` from
`base_scope + current_scope`, iterate over the base entries and insert
`Null` for any nullable-no-default property absent from `eval_scope`.
Since `eval_scope` becomes `outer` in the child `eval_entries` call,
`outer.before` now resolves to `Null`.
#### O(2^n) Lambda capture cloning
`TestMaker` defines five local functions in sequence: `makeTest`,
`checkPass`, `checkFail`, `fixPass`, `fixFail`. Each is a deferred
lambda that captures `child_scope.flatten()` at evaluation time, which
includes all previously-defined lambdas. With `Lambda` captures stored
as a bare `IndexMap`, cloning a `Lambda` deep-copied its entire capture
map — causing each successive lambda's clone cost to double, resulting
in O(2^n) total work when `scope.flatten()` was called across 128 hk
builtins.
Fix: change `Value::Lambda`'s captures from `IndexMap<String, Value>` to
`Arc<IndexMap<String, Value>>`. Clone is now O(1).
#### Semicolons as property separators
Pkl allows `;` as a separator between properties in object bodies (e.g.,
`new { file = "package.json"; contains = "..." }`). The lexer was
rejecting them as unexpected characters.
Fix: skip `;` alongside whitespace in `skip_whitespace_and_comments`.
(`checkFail` was missing because its function definition used a dotted
return type `Config.StepTest`, fixed in the previous commit. After that
fix, the error became `field not found: before`.)
---
### Test plan
- [x] All 266 existing tests continue to pass
- [x] `HK_PKL_BACKEND=pklr hk run check` succeeds in
[inko-tantivy](https://github.com/jhult/inko-tantivy)