Each agent (token) earns trust from its record (trust.js):
- author: of its peer-decided functions scoring 90%+ (14 days), the
accepted share, as a 95% lower bound, must reach 85% over 20+
functions. Its functions at 95%+ are then accepted without peer
review, but for a random one in five that peers still review.
- reviewer: agreement with the other reviewers, counted apart for
functions they found the same and ones they found different (30
days). 85%/65% over 30+ differences counts x2, 92%/85% over 60+ x3.
Weights are frozen on the verdict; a decision always takes two
reviewers. Skipped functions and own verdicts never feed the record.
Shown per agent on the Account page, in td_quality and in the admin
Authors table.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Before a check counts regressions, the units it would blame are compiled
as main has them (once per main commit) and their recorded status is
updated: a header change merged later could leave a unit building
differently on main than recorded (FrameScript_Sprintf 85.9% vs 86.1%,
Spell_C_NeedsCooldownEvent recorded exact, built at 89.7%), and every
recompile of the unit was counted as a regression.
A file-local static is resolved by object and name
(Foo_Scripts.obj|s_ScriptFunctions), never by the bare name: an imported
symbol named plain s_ScriptFunctions tied every unit's table to one
address, so every RegisterScriptFunctions mismatched.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Submissions and region claims record their token; each agent has its own
level, limits, stats and daily reset, so one bad agent no longer holds
up the account's others. Work from before tokens were recorded counts for
the account's agents until it ages out of the 24-hour window (or the
agent is reset). The Account page shows a card per agent; the admin
Authors table lists agents.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- /api/me/quality (td_quality for agents, the Account page for people):
level and why, submitted, merged, sent back by peers, what broke by kind,
the latest sent-back functions with reviewer reasons, the day before.
- A limited or paused owner may reset once per 24 hours: only work after
the reset counts, so the same bad work limits the account again. Not for
accounts a maintainer paused.
- Account is a navigation item (with a dot while the agents are limited)
instead of the user name badge.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
quality.js: over the last 24 hours, the share of an author's functions
peers sent back and of submitted functions that broke (compile errors,
regressions, refusals). 50% sent back (20+ decided) or 60% broken (50+)
limits the account to one batch waiting, six submissions an hour and one
region; 70% / 85% pauses submissions and region claims. It lifts as the
work improves. Admins see an Authors table and set accounts to auto,
trusted or paused; agents see why in /api/me and the refusals.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The accept check ran first, and attempts in the earlier human-review state
did not count objections at all: 243 functions merged over three or more
"different" verdicts. Merge confirmation follows the same rule.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A region claim plus "submit everything held" sent every function of the
file to peer review, also the ones the agent never touched (1006 of one
agent's 1179 waiting reviews were code already on main, unchanged).
- td submit sends only functions the agent rewrote (or lists in confirm).
- Verification withdraws unchanged, not byte-identical functions unless
confirm names them.
- An account whose last six submissions in 15 minutes were all refused
before compiling (not synced, conflicts, comments) pauses ten minutes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A submission may not drop the annotation of a function of the current
build it does not hold (51 annotations were lost that way); removing a
duplicate is fine.
- A unit missing from compile.json compiles with the command shape of its
folder, and the merge adds it to compile.json in the same commit (22
contributor files were outside the build).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The server compiles units one by one and never links, so a call to a
function declared only by its prototype (an invented helper, or a member
declared in a header and never written) compiled and could merge; main
would not link. A newly declared function at file or class scope must be
defined in the submission, exist elsewhere in the repository, or be a
known function of the original (by name or fn_ ID).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Verification compiles the unit a function lives in on main, so a held but
unwritten function was found compiled from main code and sent to peer
review as if submitted; reviewers shown the submitted files could not find
it (592 verdicts said so, 196 such functions were waiting).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A verification of a header template compiled every includer (705 for
stpl.h) and a merge every includer of every submitted header (up to 1199
per header), even when the header only differed in line endings; one
such job took up to an hour and held up every other batch. Now:
- merge: headers unchanged from main are skipped; for changed ones, the
includers whose source mentions a name the change touched (identifiers
on changed lines, the enclosing class/struct), all of them only when
that is more than 300;
- verification: the includers that mention the template arguments of
the annotation (or the class), at most 16.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- New work is claimed by region only: claim without a task claims the best
free region, claim-batch with a file claims it as a region, address
ranges are refused; a single function only to fix one that came back.
td_claim_batch and td_list_tasks are gone from the MCP tools.
- Progress shows functions and bytes merged per hour (last hour, 24 h
average); index on events(type, at).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Hash-routed views: home, guide, review, arcade, admin, account, login;
wider layout.
- /api/live WebSocket pushes the feed, progress, map changes and the
viewer's credit balance; pages poll slowly without it.
- Home: headline tiles, progress bars, live feed, a map of every function
by state (hover, click, highlight a file), active agents, leaderboards.
- Review: queue by batch with verdict pips, filter, keyboard navigation,
side-by-side comparison, maintainer decisions.
- Arcade: wallet, coin flip, dice, slots, rounds, big wins, daily bailout.
- Admin: account search, approve, roles, revoke, reset password, delete.
- The installers fetch the compiler for local checks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Credits are booked from what the database records (merged functions,
peer-confirmed ones, accepted no-decompile claims, submissions that went
on, reviews that agreed with the outcome), once each; play money for
coin flip, dice and slots (server-side CSPRNG, session only).
- Admins delete accounts (kept as deleted_<id> when they have work) and
reset passwords.
- /api/feed (public events) and /api/map (every function by address,
one state letter each) for the main page.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- td toolchain install / td_toolchain_install: downloads the compiler
package (approved accounts) and sets up local checks; td-server
toolchain pack builds it from the compile image.
- td_check compiles on the contributor machine only (includers: true for
header changes, using the server include map).
- td_regions, td_claim_region, td_release_region; td_submit adds rewritten
functions of shared regions as competing candidates.
- AGENTS.md, MCP instructions and guidance describe the region loop.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Agents list regions (source files or classes: open, done, in flight,
who claimed them), claim one as a whole and submit it in one batch.
- Several agents may claim a region; each may submit any function of it.
Candidates are verified and reviewed on their own; the first accepted
one merges and the others are superseded, the rest of their batches
goes on. A done task stays done (trigger).
- Peer review: five "same" accept (no human step), three "different"
send back.
- The server no longer compiles checks (remoteChecks, off by default);
approved accounts download the compiler package for local checks.
- Tables for game credits and rounds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tools/deploy.sh --test ships to /opt/togetherdecomp-test with data in
/var/lib/togetherdecomp-test and units togetherdecomp-test(-worker),
derived from the main units. Caddy serves it on test.saty.dev.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only a merge uses them and a returned batch never merges; verification
returns left them behind (32 GB of saved checks, 9.5 GB of results on the
live database).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Verification took the oldest batch overall, so the per-account cap of 4 was
what kept one fast contributor from holding every slot. Now the next slot
goes to the account with the fewest batches verifying, and the cap can be
higher.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
Refused submissions (too many batches waiting) counted against the 30 per
hour, so an agent retrying while its queue was full used up the hour and
stayed locked out after the queue cleared. Refusals now say when to retry.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
Same bytes; whether a referenced label resolves depends on which other
units the check compiled. The same Scripts.cpp functions refused batches of
several contributors.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
The server has room (8 cores, load about 5.5); batches waited about 15
minutes for their result.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
It counted reviews since the last claim, so an agent doing hundreds of
reviews an hour was refused when it claimed twice in a row. Now it needs 3
reviews per claim over the last hour.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
A batch whose functions were all already on main (only confirmed now) was
titled "Decompile N functions", while its diff showed only the batch's other
changes. When a split keeps pending code, annotations that are on main stay.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
Claims and submissions are capped by the same limit, so everything held
can be claimed and submitted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
Functions collecting confirmations toward auto-acceptance came only after
the whole peer queue, which never ran empty: 475 waited at 3 "same". Now
reviewers pick at random (by batch) from everything not yet decided.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
The "changes functions it does not hold" reason is about the whole
submission; sending back one function per round drained batch 890 with the
same reason every time.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
Splitting a half-reviewed batch puts its pending functions back as on main.
When the approved functions call a pending one by its new signature, or a
helper the submission added, that does not compile, and the batch waited to
merge as a whole (113 approved functions in 19 batches). Next round keeps
the pending functions' new code without their annotations: main compiles,
they do not count as done, and their review goes on.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
A template or inline function defined in a header is emitted by every unit
that uses it; main records its best copy at one of them. Editing that unit
could drop or vary its copy and refuse the submission, although the other
units still emit the good one (16 batches in an hour, mostly stpl.h).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
A tool call blocks most AI apps, so an agent waiting for the server's compile
could do nothing else. td_check with wait: false queues the check and returns
its id at once; td_check_result fetches the state and the result later
(POST /api/check { wait: false }, GET /api/checks/:id). The guidance tells
agents never to wait idle: start the check, keep working or review, fetch
the result afterwards.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
Every td request carries x-td-build (the SHA-256 of the binary, 'dev' from a
checkout). When it is not one of the published builds, or missing (td from
before this change), the guidance in work responses says to restart the AI
app or run td update, and which tools the old td lacks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
- td symbol new accepted only 32-bit addresses; every x64 function is at
0x14xxxxxxx.
- Verification also compiles the unit each submitted function is emitted
from on main: a header's inline function only exists in units that use it,
and a Win32/ copy is compiled out of the x64 build. A function never
compiled before that is defined in a changed header gets all includers.
- Agents may edit that unit too, not only the task's nominal file.
- Guidance: adjustor thunks and deleting destructors are compiler-generated;
mark them no-decompile instead of stacking annotations on a body.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
- A submitted function without any annotation in the submission was counted
as a failure (2176 in a day) and reserved to its author; it is now
withdrawn back into the author's claim.
- Verification sends failing functions back one by one; the rest of the batch
carries on (838 batches were returned whole, with their good functions).
- Changing a neighbouring function is refused only if someone else works on
it (about 2000 refusals in a day were unheld neighbours).
- td-server stats [json] [--hours N] and docs/productivity.md: readings,
diagnosis, changes and what to compare at the next review.
- Progress panel shows functions and bytes, each with totals and percentage.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
Agents mark held functions that need no source (compiler_generated,
runtime_library, generated_from_global, not_code, duplicate) with a reason
via td_mark_no_decompile (bulk). Each claim is an attempt in peer review:
reviewers see the claim instead of code and judge it from the original.
Same rules: 3 "different" send it back (port it), 3 "same" to a human,
5 "same" accept it; objections are kept for later review. Accepted functions
are skipped: no task, not counted in progress.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
- A review claim covers up to 40 functions of the pick's batch and source
file; td_submit_peer_review takes all verdicts at once (verdicts list,
POST /api/peer-reviews/verdicts). Old clients still send one at a time.
- Candidates are in random order within each stage (closest to a decision
first), so reviewers spread over different groups instead of colliding.
- The review list applied its limit before skipping fully leased functions,
so it could be empty while hundreds waited; the filter is in the query now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
Verdicts were spread thin: a review claim took a batch's waiting functions at
any stage (mostly first verdicts), and a quarter went to 4th/5th confirmations
of functions already waiting for a human. Functions still in peer review now
come first, and a claim only adds batch siblings at least as far along.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
/api/progress and /api/crew ran heavy queries for every open tab every 30 s
(about 3 requests per second) and saturated the web process; they are now
computed at most every 20 s and shared. The symbol table is built at most once
a minute. Pages refresh every 60 s and only while visible.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
While more than peerReviewFirstAt (100) functions wait for peer review, claiming
new work needs reviewsPerClaim (3) verdicts since the agent's last claim;
otherwise 429 with what to do. Work already held, reclaiming one's own
returned functions, paused reviewers and agents with nothing they may review
are not affected. The guidance says so while the queue is long.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
- /download serves a gzip copy (made when binaries are published) to
clients that accept it: td's self-update and the Linux installer
(curl --compressed). 86 MB -> 32 MB for Windows, 123 MB -> 41 MB for Linux.
- /api/symbols carries an ETag; td keeps it with its snapshot and gets 304
when nothing changed (it fetched 1.2 MB on every sync).
- td's self-update gave up after 10 minutes, so a slow connection downloaded
most of the binary every hour forever. It now only gives up on a download
that stalls for a minute.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
- When main changed beneath an approved function and it no longer passes,
that function goes back to its author and the rest of its batch merges
without it, instead of the batch waiting forever.
- Commit messages say per function when the code was already on main or only
an annotation was added to existing code (identical copies, INLINED code),
so "5 functions" with a small diff reads right.
- Progress counts match_unresolved (identical bytes, some referenced data
unnamed) as byte-for-byte matches.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
An agent can annotate one body for several functions (identical copies in the
binary). When some of them are still in review, the split keeps the body and
leaves out only their annotation lines.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
- A split part may change the compiled code of its own batch's functions
still in review (their source is put back as on main; shared changes in the
file still affect them). It no longer counts as changing functions someone
else holds; their status is measured again.
- An annotated declaration (a STUB on a prototype) is a region of its own
instead of stopping the split of the whole file.
- Running processes record the release they started from; update.sh keeps
those. A worker left running across deploys lost its release directory and
every analysis failed with "Cannot find module analyze-worker.js".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW