Skip to content

Commit f692da8

Browse files
tomas-samekTomáš Samek
andauthored
docs(skill-benchmark): record cell-1 run 1 (tiko+skill, specified, 13/16) + findings F2-F5 (#412)
* docs(skill-benchmark): record cell-1 run 1 (tiko+skill, specified, 13/16) + findings F2-F5 (#269) * docs(skill-benchmark): add no-skill baseline (12/16) + with-vs-without comparison (#269) --------- Co-authored-by: Tomáš Samek <jerry.samek@gmail.com>
1 parent eae552c commit f692da8

1 file changed

Lines changed: 149 additions & 0 deletions

File tree

docs/skill-benchmark/2026-06-06-results.md

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
> changes in the skill" only land once the matrix is full enough to
66
> support them — until then this file is a recording surface, not a
77
> claim.
8+
>
9+
> **2026-06-20:** first real data row landed — `tiko + skill
10+
> (auto-loaded), specified, run 1` (13/16). Run against `0.4.0-SNAPSHOT`
11+
> installed to local `.m2` (the only build carrying the post-#409
12+
> corrected bundled skill — see finding F2). Findings F2–F5 recorded
13+
> below.
814
915
## Fairness disclosure
1016

@@ -241,6 +247,88 @@ before any data was recorded against a confused methodology. The
241247
finding itself validates the harness more than a single dirty data
242248
point would.
243249

250+
### Finding F2 — Published archetype lags the corrected skill (F1 redux)
251+
252+
Recorded while preparing the `tiko + skill (auto-loaded)` cell on
253+
2026-06-20. `v0.3.0` was tagged **2026-06-18 09:02 UTC**; every
254+
bundled-skill correction merged *after* it — #407 (`Scope.REQUEST` /
255+
`@PostConstruct` fixes) at ~20:28 UTC the same evening, then #409 (full
256+
canonical sync) and #410 (the #408 anti-drift gate) on 2026-06-19. So
257+
`tiko-archetype:0.3.0` on Central — the only published version — bundles
258+
the **pre-fix, drifted** `tiko-build` skill. A clean "auto-loaded from
259+
Central" cell today would test the *wrong* skill.
260+
261+
This is structurally identical to F1: the headline auto-loaded cell is
262+
not truthfully runnable against Central until the next release ships the
263+
corrected archetype. Workaround used for run 1 (cleaner than F1's manual
264+
injection): build `0.4.0-SNAPSHOT` and `mvn install` it to the local
265+
`.m2`, then scaffold from `tiko-archetype:0.4.0-SNAPSHOT`. The installed
266+
archetype's bundled `SKILL.md` was verified as the corrected one (275
267+
lines, zero `Scope.REQUEST`) before the agent run, and the #408 gate
268+
guarantees `bundled == canonical` on `main`. Agent column records the
269+
local-`.m2` SNAPSHOT origin.
270+
271+
**Action:** the next release (0.4.0) must ship the corrected bundled
272+
skill so auto-loaded-from-Central becomes the clean headline cell with no
273+
caveat. The #408 gate makes 0.4.0's archetype clean by construction.
274+
275+
### Finding F3 — Standalone archetype apps run zero ITs (silent false green)
276+
277+
The archetype-scaffolded **standalone** app wires no
278+
`maven-failsafe-plugin`, so `mvn verify` executes **zero** `*IT` classes
279+
and still reports `BUILD SUCCESS`. CLAUDE.md and the bundled skill state
280+
failsafe is "wired in the root pom and inherited by every module" — true
281+
for tiko's *own* reactor, false for a generated standalone app, which has
282+
no such parent. The agent-under-test's first declared-ready `mvn verify`
283+
passed exit 0 while silently running none of the mandated integration
284+
test; it took an explicit correction turn to add failsafe before the IT
285+
ran at all. This is the single most consequential finding: it is a silent
286+
trap on exactly the `Done` criterion ("`mvn verify` green" + an IT that
287+
asserts a notification) that the prompt — and real users — depend on.
288+
289+
**Action:** the archetype pom should include `maven-failsafe-plugin`
290+
(and bind `integration-test`/`verify`), or the skill must explicitly call
291+
out that a standalone app needs failsafe wired before `*IT` runs. Doc
292+
half is ARCH-13 (docs describe shipped reality — for *generated* apps,
293+
not just the repo).
294+
295+
### Finding F4 — No documented test seam for FakeKafkaBroker; auto-started transport collides
296+
297+
`io.tiko.kafka.test.FakeKafkaBroker` clearly exists for in-process ITs,
298+
but nothing documents how to make it the *active* transport, and the
299+
generated `KafkaTransportBootstrap` works against the test:
300+
301+
- it hardcodes the real-client (2-arg) `KafkaBootstrapSupport`
302+
constructor and keeps its `sources()` / `sinks()` private, so the only
303+
way to drive the fake broker is to hand-rebuild a parallel
304+
`KafkaBootstrapSupport` mirroring the generated descriptors;
305+
- it auto-starts via the `TransportBootstrap` ServiceLoader SPI inside
306+
`Tiko.create()`, pointing at an unreachable localhost broker, so the IT
307+
must *also actively suppress it* — the agent stripped
308+
`META-INF/services/io.tiko.TransportBootstrap` from `target/classes`
309+
via antrun and pointed failsafe's `classesDirectory` at that stripped
310+
dir (because the packaged jar still carried the SPI registration).
311+
312+
That is a lot of framework-internal reverse-engineering for what should
313+
be a one-liner. Note this is the agent solving a *real* gap correctly —
314+
but the cost (3 of its correction turns trace here, transitively) is the
315+
finding.
316+
317+
**Action:** a documented "use the fake broker in a test" recipe, a
318+
`TikoOptions` / property to disable transport autostart under test, or a
319+
test-support helper that wires `FakeKafkaBroker` as the transport. Likely
320+
a new issue; relates to the transport/SPI work (#117/#118).
321+
322+
### Finding F5 — Kafka config key-case doc contradiction
323+
324+
The bundled skill states Kafka config keys are camelCase-exact
325+
(`bootstrapServers`); the shipped `tiko-kafka` `defaults.yaml` uses
326+
kebab-case (`bootstrap-servers`). It did not bite run 1 (the agent used
327+
defaults), but it is a live contradiction in agent-facing docs.
328+
329+
**Action:** reconcile the skill against `defaults.yaml` (ARCH-13
330+
doc-coherence). Small skill/doc fix.
331+
244332
## Per-run data (raw)
245333

246334
> **One row per run.** Aggregates are computed at the bottom, but the
@@ -251,6 +339,13 @@ point would.
251339
| cell | prompt | agent | run | tokens in | tokens out | wall (s) | first-build pass? | correction turns | rubric vector | rubric total | transcript | source |
252340
|---|---|---|---|---|---|---|---|---|---|---|---|---|
253341
| harness-smoke-test (single-Main archetype output only) | specified | no-agent (smoke test of the harness script itself) | 0 ||| 7.3 | yes | 0 | — — — — — — — — — — — — — — — — || scaffolded via `mvn archetype:generate` with prompt-verbatim coordinates 2026-06-06; ran `scripts/run-benchmark.ps1` with `MVN=W:\tools\apache-maven\bin\mvn.cmd`; bare archetype output `mvn verify` exit 0. See finding F1 above for why a real with-skill cell-1 was not attempted. | _(generated by `tiko-archetype` 0.1.0 from Maven Central; see finding F1)_ |
342+
| tiko + skill (auto-loaded, `tiko-archetype:0.4.0-SNAPSHOT` from local `.m2` — see F2) | specified | `claude-opus-4-8[1m]` @ 2026-06-20 (`.ai-skills/tiko-build/SKILL.md` auto-loaded; Claude Code clean-room subagent, no framework-repo access) | 1 | ≈128k combined¹ | ¹ | 1075 | no² | 3 | 0 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1 | 13 | local subagent JSONL³ | `W:\workspace\tiko-bench\notify-app` (local)³ |
343+
| _comment for run 1_ | | | | | | | | | | | B1=0²: first declared-ready `mvn verify` exited 0 but ran **zero** ITs (standalone archetype has no failsafe — F3); a vacuous green, so `Done` was not met first try. 3 correction turns followed: (1) add failsafe; (2) strip the auto-started Kafka transport SPI; (3) point failsafe at the SPI-stripped classes dir (F4). | |
344+
| _comment for run 1_ | | | | | | | | | | | T1=0: single Maven module — the four services are co-hosted consumers, not one module/artifact each. O1=1 (judgment): `DataSource` produced via `@Produces` ✓ (the seam O1 guards), but H2 `JdbcDataSource`, not HikariCP as the item literally names → flag for rubric **v2**: "a pooled/**managed** `DataSource` via `@Produces`" (embedded H2 makes a Hikari pool pointless). | |
345+
| _comment for run 1_ | | | | | | | | | | | H2=0: no test-isolation mechanism — `DB_CLOSE_DELAY=-1` + a fixed `mem:notify` name, no reset / isolated schema; safe only because there is exactly one test. ¹ subagent reported ≈128,409 tokens **combined** (in+out); the Task-subagent harness does not split them. ² `first-build pass? = no` per B1 above. ³ transcript + source are local paths — permalink (gist/branch) still owed per the permanence rule. | |
346+
| tiko + no skill (scrubbed: `.ai-skills` deleted, skill pointers stripped from `CLAUDE.md`/`AGENTS.md`; CLAUDE.md reference retained) | specified | `claude-opus-4-8[1m]` @ 2026-06-20 (clean-room subagent, no framework-repo access) | 1 | ≈139k combined⁴ || 1146 | no⁵ | 1⁶ | 0 1 1 0 1 1 1 1 0 1 1 1 1 1 0 1 | 12 | local subagent JSONL | `W:\workspace\tiko-bench-noskill\notify-app` (local) |
347+
| _comment for no-skill run 1_ | | | | | | | | | | | O1=0: no `@Produces` — a hand-rolled `Database` `@Component` wraps `JdbcConnectionPool` and hands repositories raw `Connection`s. Avoids the DataSource-in-repository anti-pattern but skips the `@Produces` DataSource cookbook the with-skill run followed (O1=1 there). **This is the single rubric item separating the two runs**; judgment call (the wrapper is clean, just not the prescribed factory). | |
348+
| _comment for no-skill run 1_ | | | | | | | | | | | B1=0⁵: first declared-ready `mvn verify` failed **honestly** — this cell's scaffold already had failsafe (scaffolded after the #413 fix), so the IT ran and failed on the F4 dual-transport collision; 1 correction turn (a thread-context-classloader hiding the transport SPI) to green. ⁶ correction-turns are **not** comparable to the with-skill run's 3: that cell was scaffolded *before* #413 and spent a turn adding failsafe; this one got it free. Normalized, both are ~1–2 turns on the same F4 friction. A pre-ready compile iteration to learn the (undocumented-without-skill) `@KafkaSource` contract is recorded as design discovery, not a correction turn. ⁴ ≈138,640 tokens combined; in/out not split by the harness. | |
254349

255350
### How to score the rubric vector
256351

@@ -261,6 +356,60 @@ For non-tiko cells, write `—` for the O-items (the framework doesn't
261356
have those concepts) so a reader can tell the difference between
262357
"missing concept" and "agent missed it."
263358

359+
## With-skill vs without-skill — specified, run 1
360+
361+
The load-bearing comparison. Same archetype, same locked prompt, same
362+
clean-room harness; the **only** intended variable is whether
363+
`.ai-skills/tiko-build/SKILL.md` was present (the no-skill cell is the
364+
"scrubbed" variant — CLAUDE.md's framework reference is retained).
365+
366+
| run | B1 | B2 | B3 | T1 | T2 | T3 | T4 | T5 | O1 | O2 | O3 | O4 | O5 | H1 | H2 | H3 | total |
367+
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
368+
| with-skill | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | **1** | 1 | 1 | 1 | 1 | 1 | 0 | 1 | **13** |
369+
| no-skill | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | **0** | 1 | 1 | 1 | 1 | 1 | 0 | 1 | **12** |
370+
371+
**Single rubric delta: O1** — the `@Produces` DataSource cookbook.
372+
With-skill produced the H2 `DataSource` via `@Produces`; no-skill
373+
hand-rolled a `Database` component wrapping `JdbcConnectionPool`. Every
374+
other item is identical: both nailed the event chain (O2/O3), the Kafka
375+
bridges, upserts (T2), DB-backed lookups (T3), skip-on-missing (T4),
376+
startup schema (T5), and invented-annotation hygiene (O4); both collapsed
377+
the four services into one module (T1) and shared the same H2
378+
test-isolation gap (H2).
379+
380+
**Reading it honestly** (n=1 per cell — noise is large; ≥3 runs needed
381+
before any aggregate):
382+
383+
- **The skill's marginal effect here was one rubric item.** With
384+
CLAUDE.md's reference present in *both* arms, the orchestrator-model
385+
essentials were already carried by CLAUDE.md; the SKILL.md's
386+
incremental teaching showed up only in the `@Produces` cookbook. A
387+
sharper signal would come from the **fresh-without floor** (no CLAUDE.md
388+
at all) — a distinct future cell.
389+
- **Where the skill helped but the rubric didn't capture it:** with-skill
390+
got the `@KafkaSource` / `@KafkaSink` contract straight from the skill;
391+
no-skill reverse-engineered it from compiler errors + generated sources
392+
(a pre-ready compile iteration). Both reached correct usage, so the
393+
binary rubric shows no difference — but the skill saved a discovery
394+
loop. An effort/time benefit the 0/1 vector doesn't measure.
395+
- **Where no-skill was arguably better:** it used repository **interfaces**
396+
(`ProductRepository` + an `H2…` impl, injected by interface), matching
397+
tiko's interfaces-over-impls house style, where with-skill used concrete
398+
repos; its first build was an **honest red** (IT ran and failed) where
399+
with-skill's was a **false green** (F3: IT silently didn't run); and it
400+
solved the F4 transport collision in **one** elegant turn (TCCL
401+
SPI-hiding) vs with-skill's two.
402+
- **F4 dominated both runs regardless of the skill.** Neither doc covers
403+
driving `FakeKafkaBroker`, so both agents burned their hardest correction
404+
turns reverse-engineering the transport — reinforcing #414 as the
405+
highest-value DX fix this benchmark has surfaced.
406+
407+
**Bottom line:** on tiko's home turf with the baseline CLAUDE.md present,
408+
the `tiko-build` skill moved the needle by one rubric item (the `@Produces`
409+
cookbook) and saved one discovery loop (the `@KafkaSource` contract) — a
410+
real but modest margin. The dominant friction (F4) and the structural
411+
misses (T1 multi-module, H2 isolation) were skill-independent.
412+
264413
## Aggregates
265414

266415
> Computed once the matrix has ≥ 3 runs per cell. Until then this

0 commit comments

Comments
 (0)