Skip to content

feat: t27_find -- intent to ranked corpus specs, or an honest miss - #14

Merged
gHashTag merged 1 commit into
masterfrom
claude/exciting-gauss-9cbc6e
Oct 18, 2026
Merged

gHashTag merged 1 commit into
masterfrom
claude/exciting-gauss-9cbc6e

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

What

New tool t27_find: an intent in plain words ("clocked counter") returns ranked, existing corpus specs, or an honest miss. This is the first missing step of the validated-code contract (epic gHashTag/t27#10066): look up first, generate last.

All the logic is a t27 spec, specs/t27mcp/find.t27, in gHashTag/t27#10194 (13/13 tests, 0 vacuous, 5 negative controls, dupe_scan --like clean; evidence is in that PR). Here are only the generated artifacts and glue.

Reply shape: {intent, miss, matched, skipped:{unhealthy,untested}, note, hits:[{path, ..., next:'t27_spec path:"..." source:true'}]}. A relevant spec that is not health/ok + has/tests is counted in skipped, never returned. Below the threshold the answer is miss:true with no hits (not the nearest neighbour).

Files

file kind lines / bytes
wasm/find.wasm generated (t27c gen-c + zig cc, reactor, wasm32-wasi) 2765 bytes
wasm/find_table.mjs generated (t27c gen-js) 64 lines
wasm/BUILD rebuild commands, test counts, negative controls, hashes +28
find.mjs glue: load wasm, write row strings into memory, call verdict / rank_key, sort 26
server.mjs glue: import + t27_find tool entry +8
smoke.mjs glue: one hit check, one miss check +6
package.json files list 1 line changed

Hand-written added lines: 40 (limit: 40 per file, 80 per PR). No logic in JS: every decision is verdict / rank_key from the spec.

sha256

82b64bde50ec3ec42729b1d88b7b41525372c5fbcf39f02876bdb98a7e063e3a  wasm/find.wasm
51043849996d40633099f1f2b6d9960f6eccea2b7e8f21031265965c5656ff1d  wasm/find_table.mjs

Built on the Railway lab with t27c 0.5.2 and zig 0.16.0; smoke.mjs passes.

Before / after: 10 lookup questions

Same driver CLI (t27_specs, t27_grep, t27_spec) for both arms; the "after" arm also lists t27_find. Haiku subagents, at most 8 calls, one run per cell. Ground truth was fixed before running. 7 questions have a spec in the corpus, 3 have none (correct answer: NONE). "Seen at" is the call number whose output first showed a ground-truth path.

# question calls b / a seen at b / a tokens b / a answer b / a
1 SHA-256 implementation 7 / 4 - / - 75320 / 67523 diskbloom/.../duplicate_rules.t27 / NONE
2 topological sort 6 / 4 3 / 2 67764 / 57339 NONE / NONE
3 heap sort 3 / 3 2 / 2 62989 / 57336 heap_sort / heap_sort
4 priority queue 5 / 6 2 / 2 63422 / 61157 NONE / NONE
5 UART loopback circuit 5 / 5 2 / 2 65683 / 63265 uart_loopback_core / uart_loopback_core
6 ternary ripple adder 4 / 4 2 / 2 68064 / 63938 ripple_adder / ripple_adder
7 merge sort 4 / 4 2 / 2 60647 / 58794 merge_sort / merge_sort
8 LFSR pseudo-random generator 5 / 7 - / - 67655 / 65706 NONE / NONE
9 I2C master controller 8 / 8 - / - 66810 / 62028 NONE / NONE
10 gray code counter 7 / 7 - / - 61379 / 60792 NONE / NONE
total 54 / 52 659,733 / 617,878 7 / 7 correct

Honest reading: no measurable improvement on this set. Strict correctness is 7/10 in both arms; the call counts (54 vs 52) and tokens (-6%) are within what one run per cell cannot separate from noise. Tokens include roughly 50k of fixed overhead per agent. t27_specs with a path substring already finds the common names in 2 calls.

Findings:

  • Q1 (SHA-256) was an honest t27_find miss, not a hit. The measured build dropped digits as noise, so SHA-256 matched shaping, sha512, blog-share; the agent rejected them and answered NONE. The "numbers are content words" fix in the spec removes those weak hits (SHA-256 is now a miss, sha256 hits), but SHA-256 with a hyphen still does not hit, and SHA-256 implementation is a miss too. That fix came after the measurement and changes none of the 10 rows above. In the "before" arm the agent did find a real SHA-256 (duplicate_rules.t27) that no name search reaches; my ground truth did not list it, so it is scored wrong here although it is arguably right.
  • Q2 and Q4: the corpus has the spec, both arms refused it. specs/tri/graph/topological_sort.t27 and specs/tri/collections/priority_queue.t27 are health/ok + has/tests, but their tests assert only != undefined. The agents read the source and said NONE. has/tests is a manifest tag, not a receipt. This is the case t27_validate (next tool in the plan) is for, and t27_find says so in its note.
  • "implementation" as a filler word (Q1) is a candidate stop word; I did not tune it, so as not to contaminate the measurement.

Not in this PR

  • Auto-merge is not enabled; left for the owner.
  • Follow-ups: t27_validate; t27_find tuning (filler words, hyphenated numbers); drop the duplicated find/has in the JS filterSpecs.

Refs gHashTag/t27#10066. Spec PR: gHashTag/t27#10194.

🤖 Generated with Claude Code

@tri-claw

tri-claw Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Summary by t27-bees

This PR adds t27_find, a tool that ranks corpus specs against a plain-word intent using a t27 spec compiled to WASM. The glue code (find.mjs) loads the module, writes each manifest row into linear memory, calls verdict/rank_key, and returns the top hits. All decision logic lives in specs/t27mcp/find.t27; the JS is pure plumbing.

Worth a look

  • find.mjs:11–12 — W.memory.grow(1) is called once at module load; base is captured after the grow. If find() were ever called concurrently (not expected in MCP), simultaneous put() calls would overwrite each other’s slots. Sequential use is safe.
  • find.mjs:12 — A new TextEncoder() is created per put() call (4 per row). Trivial overhead, but a single shared encoder would be cleaner.
  • find.mjs:18–19 — On V_EMPTY the function returns immediately without scanning remaining rows. skipped stays zero. Intent is by design (empty intent → no searchable words), but callers see no skipped breakdown for that case.
  • find.mjs:24 — Math.trunc(limit) || S.LIMIT treats limit: 0 as “use default” (since 0 is falsy). Explicit zero becomes 5; likely intentional (minimum 1 enforced by Math.max(..., 1)), but surprising if a caller passes 0 expecting “no results”.
  • wasm/find_table.mjs — The generated file notes that verdict, rank_key, and all helper fns were not emitted (“backend lowers declarations, not bodies”). The WASM exports are the sole runtime implementation; the JS constants (STOPS, ALT_FROM, etc.) are correctly provided for any client-side reference.

Read: 7 files, +133 -1, the whole diff. Head 26d28eb. Model: openai-compatible/nvidia/nemotron-3-ultra-550b-a55b. Commands: @t27-bees review | summary | help | pause | resume. Free for every repository.

The ranking is specs/t27mcp/find.t27 (gHashTag/t27, epic gHashTag/t27#10066),
compiled to wasm; find.mjs only writes one manifest row at a time into the
instance memory and sorts by the key it returns.

- wasm/find.wasm, wasm/find_table.mjs: generated, sha256 in wasm/BUILD
- find.mjs: glue (26 lines); server.mjs: the tool entry (8 lines)
- smoke.mjs: a hit and a miss against the live manifest

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@gHashTag
gHashTag force-pushed the claude/exciting-gauss-9cbc6e branch from 328a540 to 26d28eb Compare October 18, 2026 04:25
@gHashTag
gHashTag merged commit 9a0d111 into master Oct 18, 2026
2 checks passed
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