unit_deps holds only the units some merge compiled, so a change to a header no merge touched compiled none of its includers. Includers now unite unit_deps with a transitive #include scan of the sources as the submission has them.
effectiveHash fingerprints a function by its bytes and where each reference lands (symbol address + addend). A maintenance batch compiles the touched units as main has them and refuses only functions whose effective code changes, so moving a global, renaming it, or reaching a member through its owning object merges.
A maintenance batch carries structural source changes that belong to no function task (moving a global to its owner, fixing data annotations, adding a header or unit). It runs the same gates as function work and compiles every unit the change can affect; it merges only when no function's compiled code changes, recording the result like any merge. POST /api/admin/symbols/:id corrects a symbol's size or name, or retires a global main no longer annotates. td maintenance submit|symbol drive both.
A region whose functions are all on main can be claimed, and its done tasks submitted as revisions: competing candidates verified and peer reviewed like new work, while the task stays done whatever the outcome. Rewriting a merged function without listing it sends the batch back instead of merging it unreviewed. Admins can force a done task back to open.
The "review first" rule counted only task claims, but new work is claimed by
region, so after three reviews an hour an agent could claim any number of
regions while the review queue kept growing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The queue judged "decided" by weight alone, while a decision also takes two
reviewers on the winning side. A function led by one heavy verdict dropped
out of the queue but was never decided, and waited forever.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"same" now needs 70% of the weight as well as a lead of three (7:3, not 10:7),
so a contested function is not worn down until "same" happens to lead. A
function seven reviewers could not decide goes back to its author with why;
the queue stops handing it out at the cap. Both are policy settings
(peerAcceptShare, peerMaxReviewers); trust's author record counts the same way.
One body annotated for several functions: when the original of the submitted
one is the same code as another's (same bytes, relative references to the same
targets) and main already accepts that one from this compiled body, the
submission is approved without peer review.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A resubmission whose peer verdicts carry over now goes on as approved; in_review
waited for a human review that no longer comes, and the peer queue skipped it.
A batch that only merges as a whole (noSplit) goes back to its author once a
function of it drops out later (sent back, withdrawn, superseded), instead of
holding its approved functions forever.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
users.review_weight (1 to 3, or auto) overrides the earned weight
(trust.js). Setting it re-weights the account's verdicts on functions still
waiting and settles the queue: what the new weight decides is accepted or
sent back at once. One reviewer still never decides alone.
td-server user review-weight <name> <1|2|3|auto>, or the admin actions
review-weight-1/2/3/auto.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Four (five after an objection) "same" could not be reached with the few
accounts online: an author never reviews their own work, and with four
active accounts that were also the authors, each function could get at most
three verdicts. 948 of 1027 verdicts in six hours went to functions that
stayed undecided; merges fell to about 5 an hour.
- Accept when weighted "same" leads "different" by peerMargin (3: 3:0, 4:1,
5:2), from at least two reviewers.
- Send back when at least peerReviews (3) "different" lead by
peerRejectMargin (2: 3:1, 4:2), from at least two reviewers.
- Close votes wait for more verdicts; reviewers are offered functions that a
verdict can still decide.
- The worker settles the waiting queue under the current rule when it starts.
- Trust and quality count accepted and sent-back functions the same way.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Static gate: a file main already holds may grow 128 KB beyond its size on
main (Unit_C.cpp is 796 KB, Player_C.cpp 491 KB: no edit to them could
pass the 256 KB limit); only what a submission adds counts toward the total.
- A peer-confirmed function in another unit may move closer to the original
(a header layout fix); only moving away from it is a regression.
- A function main no longer annotates anywhere (fn_07162, removed from stpl.h
in 0f9ebdb4 while its record still said exact) is not "removed" by every
later submission of the unit it was recorded at.
- A library function main already annotates in a file (fn_25851 in
BSNEncodeInterface.h) no longer refuses every edit of that file; adding
such an annotation still is refused.
- td_withdraw / td withdraw <attemptId>: the author takes back a function
waiting for review; it returns to their claim.
- td_submit says when held functions have no changed code in the working
tree, instead of "you hold no tasks".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The admin Authors table computed trust for all 121 agents in ~30 s, blocking
the web process (arcade, admin, everything) meanwhile.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
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>
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>
- 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>
- 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>
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
- 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
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
- "Next work" (td_claim_batch without arguments, and td_claim_task without
an id) claims a group: the best open task's source file, else its class,
else the run of neighbouring unplaced functions in the binary.
- The worker places unplaced functions where the binary makes it clear:
between two functions of the same file, or with their class's other
methods (6,745 of 22,572 on the live data); again every 30 minutes.
- td_place lets an agent organize a group of unplaced functions before
porting them: a .cpp file each (validated path) and optionally a name
(identifiers only). Later work on them then comes per file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
A function with peerAutoAccept (5) "same" verdicts is accepted without human
review even if a peer said "different". Every function that reaches main with
at least one "different" verdict (auto-accepted or approved by a human) is
recorded in later_review; the review page lists them with the attempt and a
"Reviewed" button.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
Per reviewer: verdicts, agreement with the other reviewers of the same
function and with the human decision, and the share of verdicts given within
10 seconds of the previous one; flags for never/mostly objecting and very fast
reviewers. Admins can pause an account's peer reviews (its verdicts so far
stay) and allow them again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
After three "same" verdicts a function goes to human review as before, but it
stays open for more reviewers: with peerAutoAccept (default 5) "same" verdicts
and no "different" at all, it is approved and merged without a human. Any
objection leaves the decision to a human. The review queue shows how close a
function is, or that it is contested.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
Verification compiles the submitted units (one includer per header for
header-only changes, plus one includer as the lint sample): enough to judge
and route every submitted function, in seconds even for header changes. The
merge compiles every includer of a changed header that verification skipped
and checks them for regressions, so nothing reaches main without it; it runs
in the big merge lane. Batches sent back early never pay for the full compile.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
- The preprocessed-output lint compiled every unit a second time (with /P)
when a header changed: 323 units twice for Types.h. A header expands the
same way everywhere, so it now lints the submitted units plus one includer
of each changed header.
- Merges re-ran the full check, including that lint. The lint is skipped on
merge, and when nothing the compiled units consist of (sources, included
headers) changed on main since verification, the verification's compile is
reused and nothing is compiled at all.
- The queue takes small batches first (by the number of units they compile);
a big batch that waited 20 minutes goes ahead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
A function resubmitted unchanged (port-first) made the merge a no-op, and git
refused the empty commit, so the merge retried forever and blocked the queue.
CRLF from Windows workspaces is normalized on arrival.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
Prompt injection: a submission may not add comments other than annotations,
offset and INLINED markers, and only string literals that occur in the
original executable (adjacent literals joined; #include paths restricted).
Comments and strings already on main stay. Checked before compiling, for
remote checks and submissions; errors name the line but never repeat the
text. Peer reviewers no longer see author notes or running verdict counts.
Agents are told that only AGENTS.md and the guidance field instruct them.
Review: "Approve batch" in the confirmed section also approved the batch's
functions still in peer review (for maintainers). The page now sends exactly
the functions it shows, and skipping peer review needs skipPeerReview,
which only the peer review section's button and the attempt page send.
Worker drain: a stopping worker kept starting new verifications when one
finished, so it never stopped. Stopped queues take no new work.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
While the worker was stopped (maintenance), checks were queued with nobody to
run them; agents timed out ("fetch failed", 502 after a restart) and every
retry queued another copy. Now: the worker writes a heartbeat and a check is
refused with 503 at once while it is down; a retry of the same files joins
the job already queued or running; a job nobody waits for any more is
dropped. TD_KEEP_WORKER=1 deploys without touching the worker.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
Templates and inline functions are compiled in every unit that uses them. A
merge that recompiled many units (a header change) let the last unit's copy
win, so functions that matched in one unit were recorded as match_unresolved
from another, and the regression check missed it because the better status
came from a unit it did not compile. Now each function counts with its best
compiled copy, and a check never lowers a status measured in a unit it did
not compile.
The progress gauge and the crew views refresh every 30 seconds; the gauge
moves from its previous reading.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
Peer review: one "different" no longer sends a function back. It stays in
review until three agents agree: three "same" send it to human review, three
"different" back to its author; mixed votes let further reviewers in. When a
function does go back (peers or a human), only that function goes; the rest
of its batch carries on and its approved part merges without it.
Public "Active agents" (who is working on what right now) and "Users"
(merged, submitted, peer reviews) sections, from /api/crew. No token labels
or account details.
Updates: deploy/update.sh copies and syntax-checks a new release next to the
running one, switches the /opt/togetherdecomp symlink in one step and only
then restarts what changed (the worker when idle); pages are live without a
restart. tools/deploy.sh ships HEAD (and with --td the td binaries).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
td-server start web | worker | all. The web process serves the website, API
and git; the worker verifies, merges, runs remote checks and refreshes the
Ghidra project. They share the database and the repository, so restarting
one never interrupts the other. Remote checks are queued in check_jobs and
picked up by the worker. Web files are read from disk per request, so page
changes need no restart at all. The web unit no longer has docker access.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
The queue lists functions still waiting for peer verdicts (with how many peers
confirmed so far) next to the ones ready for a human. Maintainers and admins can
approve, send back or reject them without waiting for the peers. The attempt
page shows the original pseudocode and disassembly beside the submission.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
A batch no longer waits for its slowest function: once some of its functions
are approved and the rest wait for review, the approved ones merge as their
own batch (the pending functions put back as they are on the base commit),
and the rest is rebased onto that commit. The merge re-verifies the split; if
anything breaks, the batch merges as a whole as before.
Comparing compiler output against the original runs in worker threads. A
check that recompiled dozens of units (a header change) blocked the
coordinator's event loop for minutes, so the website stopped responding.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
- Batches: claim every open function of a unit or address range (td claim --unit/--range),
submit the file once; one compile, per-function routing, merged as a whole. A failing
function returns the batch; peer verdicts carry over to functions whose compiled code is
unchanged (code fingerprints). Submissions may not change functions they do not hold.
- Byte-identical functions are approved and merged without human review
(matchPolicy.autoMergeIdentical); peer-confirmed ones need one click per batch.
- Remote check: td check compiles on the server when there is no local toolchain.
- /api/original: assembly and pseudocode of the original from the server's Ghidra export
(objdump before an export exists); td disasm/decompile fall back to it.
- td as a standalone executable (Node single executable application; tools/build-td),
one-line installers (install.ps1 / install.sh) with checksum verification, td connect for
any MCP client, td mcp --workspace, self-update (td update, hourly check).
- Server-side Ghidra project: built once per version, refreshed after merges, downloadable
for contributors (td ghidra download); JDK 21 and the pinned Ghidra in deploy/install.sh.
- Agent instructions: work continuously, batches first, peer reviews in between.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
Coordinator (accounts with approval, API tokens, tasks with leases, sandboxed MSVC verification against
the original exe, peer review by three agents for non-identical code, human review, serial merge queue),
the `td` contributor CLI with an MCP server for agents, pinned Ghidra integration, deployment (Caddy,
systemd, nftables, Forgejo) and the wowdecomp 15890 migration tools.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW