feat(tells 6.3): put the TELL COUNTS on the card and in the prompt

A tell-lever card named a lever and then made the agent go find its sites: it said
"extend-tell" and nothing about where or how many. atlas_features already counts the
detectors per function into .run/feat.<bin>.jsonl at atlas time, so this is a JOIN, not a
computation — one dict load per binary in the wave.

build_wave_atlas attaches 'tells' {extpair, dupselect, magic_div, sign_lh, sign_lb} to every
card that has a nonzero one — not just tell-lever cards, because a sll/sra pair site or a
repeated select is worth knowing whatever lever drew the card. Measured on a live draw: 85 of
185 cards carry counts.

api_agent._fuel renders them as a CHECKLIST rather than a hint, which is the point: the
counts come from the TARGET's own bytes, so a draft emitting fewer has provably missed sites
and should go looking before spending a turn elsewhere.

Verified: a card with {extpair 3, dupselect 2, sign_lh 1} renders all three with the zero
fields omitted; NEGATIVE CONTROL — a card with no tells renders no TELLS line at all.

Takes effect on the next draw + the next shard (api_agent is spawned per draft).
This commit is contained in:
Drew T
2026-08-25 14:35:36 -06:00
parent 98f7205a3a
commit e7353d63de
2 changed files with 64 additions and 0 deletions
+20
View File
@@ -509,6 +509,26 @@ def _fuel(t, card):
out.append( "⚠ Do NOT hunt in `sibs` for a body to read: they are drawn from the OPEN set by")
out.append( "construction, so they are stubs 100% of the time. They tell you what your work is")
out.append( "WORTH, not where an answer is.")
# 6.3 TELL COUNTS (P31 S60). Counts derived from the TARGET's own bytes by atlas_features,
# joined onto the card by build_wave_atlas. They are a CHECKLIST, not a hint: the target
# provably contains this many sites, so a draft that produces fewer has missed some.
_t = card.get('tells') or {}
_bits = []
if _t.get('extpair'):
_bits.append(f"{_t['extpair']} sign-extend pair site(s) (sll/sra, §172b EXTPAIR)")
if _t.get('dupselect'):
_bits.append(f"{_t['dupselect']} repeated two-arm select(s) (§172b SELECT)")
if _t.get('magic_div'):
_bits.append(f"{_t['magic_div']} magic-division site(s)")
if _t.get('sign_lh'):
_bits.append("signed halfword load(s) (lh, not lhu)")
if _t.get('sign_lb'):
_bits.append("signed byte load(s) (lb, not lbu)")
if _bits:
out.append("\nTELLS COUNTED IN THE TARGET (from its bytes, not a guess) — expect: "
+ "; ".join(_bits) + ".")
out.append("If your draft emits fewer of these than the count says, you have missed "
"sites — find them before spending a turn on anything else.")
if card.get('lever'):
out.append(f"\nThe atlas labels this card's lever: {card['lever']}.")
crib = LEVER_CRIB.get(card['lever'])
+44
View File
@@ -706,6 +706,50 @@ try:
except ImportError:
print('build_wave_atlas: validate_targets not importable -- VALIDITY GATE SKIPPED', file=sys.stderr)
# 6.3 TELL COUNTS ON THE CARD (P31 S60, tells-lane-s59.md). A tell-lever card named a lever and
# then made the agent go find its sites: the card said "extend-tell" and nothing about WHERE or HOW
# MANY. atlas_features already computed the per-function detector counts into .run/feat.<bin>.jsonl
# at atlas time, so this is a join, not a computation — one dict load per binary in the wave.
# Attached for EVERY card, not just tell-lever ones: a sll/sra pair site or a repeated select is
# worth knowing about whatever lever the card was drawn under.
_feat_cache = {}
def _feat_rows(binary):
if binary not in _feat_cache:
rows = {}
try:
with open(f'.run/feat.{binary}.jsonl', errors='replace') as fh:
for ln in fh:
ln = ln.strip()
if not ln.startswith('{'):
continue
try:
r = json.loads(ln)
except ValueError:
continue
try:
rows[int(str(r.get('addr')), 16)] = r
except (TypeError, ValueError):
pass
except OSError:
rows = {}
_feat_cache[binary] = rows
return _feat_cache[binary]
_n_tells = 0
for c in wave:
try:
_r = _feat_rows(c['binary']).get(int(str(c.get('addr')), 16))
except (TypeError, ValueError):
_r = None
if not _r:
continue
t = {k: _r.get(k, 0) for k in ('extpair', 'dupselect', 'magic_div', 'sign_lh', 'sign_lb')}
if any(t.values()):
c['tells'] = t
_n_tells += 1
print(f"tell counts attached to {_n_tells} of {len(wave)} card(s) "
f"(extpair/dupselect/magic_div/sign_lh/sign_lb from .run/feat.<bin>.jsonl)", file=sys.stderr)
json.dump(wave, open(a.out, 'w'), indent=1)
if a.one_per_gid:
# Only the siblings of gids that ACTUALLY made the wave are actionable this session; the rest