Read project config from data/ (decomp.json, compile.json, toolchain.lock.json)

This commit is contained in:
ragnarok-clanker 2026-10-27 15:41:06 +01:00
commit 91c799f7d3
13 changed files with 20 additions and 20 deletions

View file

@ -65,7 +65,7 @@ attempt gets first pick on the follow-up for 6 hours.
| `src/client/` | `td` CLI, MCP server for agents, Ghidra integration |
| `ghidra_scripts/` | ExportFunctions (bootstrap), ApplySymbols, DecompileAt, DisassembleAt |
| `toolchain/msvc2010/` | Dockerfile for cl.exe under Wine (you supply the compiler files) |
| `template/` | skeleton of the decomp repo: `decomp.json`, `toolchain.lock.json`; the project's own root `AGENTS.md` is the only agent guide |
| `template/` | skeleton of the decomp repo: `data/decomp.json`, `data/toolchain.lock.json`; the project's own root `AGENTS.md` is the only agent guide |
| `deploy/` | install script, systemd unit, Caddyfile, nftables firewall |
| `deploy/forgejo/` | Forgejo git dashboard at `/git/`: installer (checksum + signature verified), config, unit |
@ -81,7 +81,7 @@ analyzeHeadless /tmp/g boot -import game.exe -scriptPath ghidra_scripts -postScr
td-server symbols import functions.csv # one stable ID per function, tasks get created
td-server symbols units units.csv # optional: start,end,src/file.cpp
td-server user add alice --role reviewer
# build the compiler image (see toolchain/msvc2010/Dockerfile), pin clSha256 in toolchain.lock.json
# build the compiler image (see toolchain/msvc2010/Dockerfile), pin clSha256 in data/toolchain.lock.json
```
New target version later: `td-server version add 1.1 game11.exe`, then

View file

@ -33,7 +33,7 @@ for (const [file, value] of Object.entries(payload.files)) {
fs.mkdirSync(path.dirname(path.join(repo, file)), { recursive: true });
fs.writeFileSync(path.join(repo, file), value.text);
}
git('add', '-A', '--', 'Source', 'CODING_RULES.md', '.clang-format', 'CMakeLists.txt', 'compile.json', 'README.md');
git('add', '-A', '--', 'Source', 'CODING_RULES.md', '.clang-format', 'CMakeLists.txt', 'data/compile.json', 'README.md');
git('-c', 'user.name=ragnarok-clanker', '-c', 'user.email=ragnarok-clanker@users.clank-together.invalid', 'commit', '-m', `${payload.message}\n\nAdministrative source import: native x86 compilation passed for 423 authored units. Source placement and submission states are migrated separately; this commit does not imply peer acceptance.\n\nPrevious head: ${payload.baseCommit}\nPayload SHA256: ${backup.payloadSha256}`);
const commit = git('rev-parse', 'HEAD');
const changes = { symbolsMoved: 0, symbolsPlacedFromAnnotations: 0, funcStatusPaths: 0, dependencyPaths: 0, regionPaths: 0 };

View file

@ -55,10 +55,10 @@ async function runHeadless(ws, args, timeoutMs) {
return r.output;
}
/** Downloads and unpacks the Ghidra release pinned in toolchain.lock.json. */
/** Downloads and unpacks the Ghidra release pinned in data/toolchain.lock.json. */
export async function installGhidra(ws) {
const lock = loadToolchainLock(ws.dir).ghidra;
if (!lock?.url || !lock?.sha256) throw new Error('toolchain.lock.json has no ghidra { url, sha256, dir } entry');
if (!lock?.url || !lock?.sha256) throw new Error('data/toolchain.lock.json has no ghidra { url, sha256, dir } entry');
const toolsDir = path.join(ws.tdDir, 'tools');
fs.mkdirSync(toolsDir, { recursive: true });
const zip = path.join(toolsDir, path.basename(new URL(lock.url).pathname));

View file

@ -99,7 +99,7 @@ function runnerConfig({ runner, vc, sdk, image, toolchain, project }) {
const type = runner ?? (os.platform() === 'win32' && vc ? 'native' : 'docker');
if (type === 'remote') return { type };
if (type === 'docker') {
if (!image) throw new Error('no docker image configured; pass --image or set it in toolchain.lock.json');
if (!image) throw new Error('no docker image configured; pass --image or set it in data/toolchain.lock.json');
return { type, image };
}
if (!vc) throw new Error(`--vc <path to the VC directory of Visual Studio 2010> is required for the ${type} runner`);

View file

@ -1,4 +1,4 @@
// Loads the decomp repo's configuration (decomp.json) and scans its sources.
// Loads the decomp repo's configuration (data/decomp.json) and scans its sources.
import fs from 'node:fs';
import path from 'node:path';
@ -27,7 +27,7 @@ const UNIT_EXT = new Set(['.c', '.cpp', '.cc', '.cxx']);
const SOURCE_EXT = new Set([...UNIT_EXT, '.h', '.hpp', '.inl']);
export function loadProject(repoDir) {
const file = path.join(repoDir, 'decomp.json');
const file = path.join(repoDir, 'data', 'decomp.json');
const cfg = fs.existsSync(file) ? JSON.parse(fs.readFileSync(file, 'utf8')) : {};
const project = { ...DEFAULT_PROJECT, ...cfg, matchPolicy: { ...DEFAULT_PROJECT.matchPolicy, ...(cfg.matchPolicy ?? {}) } };
// Optional exact per-unit command lines: { env, shapes: [[args]], units: { file: shapeIndex } }.
@ -72,7 +72,7 @@ export function addUnitsToCompileCommands(project, text, files) {
}
export function loadToolchainLock(repoDir) {
const file = path.join(repoDir, 'toolchain.lock.json');
const file = path.join(repoDir, 'data', 'toolchain.lock.json');
return fs.existsSync(file) ? JSON.parse(fs.readFileSync(file, 'utf8')) : {};
}

View file

@ -5,8 +5,8 @@ Matching decompilation, coordinated with Clank Together.
- `src/`, `include/`: decompiled C++. Every function and global carries a
stable symbol annotation (`// FUNCTION: fn_00123`); addresses live in the
coordinator's symbol database, per target version.
- `decomp.json`: compiler flags and project policy.
- `toolchain.lock.json`: pinned compiler and Ghidra versions.
- `data/decomp.json`: compiler flags and project policy.
- `data/toolchain.lock.json`: pinned compiler and Ghidra versions.
- `AGENTS.md`: how to contribute (for people and their LLM agents).
Get started: `td setup <server-url> <dir> --name <you>`.

View file

@ -119,7 +119,7 @@ test('public info, symbol snapshot, and the target is not served by default', as
test('the repository can be cloned over HTTP but not pushed to', async () => {
const dest = path.join(dataDir, 'clone');
await promisify(execFile)("git", ["clone", "-q", `${base}/repo.git`, dest]);
assert.ok(fs.existsSync(path.join(dest, 'decomp.json')));
assert.ok(fs.existsSync(path.join(dest, 'data', 'decomp.json')));
const res = await fetch(`${base}/repo.git/info/refs?service=git-receive-pack`);
assert.equal(res.status, 403);
});

View file

@ -10,7 +10,7 @@
# msvc/sdk/ Windows SDK 7.0A Include (only if the code includes windows.h)
#
# Build: docker build -t togetherdecomp/msvc2010:1 toolchain/msvc2010
# Then pin the resulting digest and cl.exe hash in the repo's toolchain.lock.json.
# Then pin the resulting digest and cl.exe hash in the repo's data/toolchain.lock.json.
FROM debian:12-slim

View file

@ -5,4 +5,4 @@ TC=/opt/toolchain/VC/Tools/MSVC/14.29.30133
SDK='/opt/toolchain/Program Files/Windows Kits/10/Include/10.0.19041.0'
export INCLUDE="Z:\\opt\\toolchain\\VC\\Tools\\MSVC\\14.29.30133\\include;Z:\\opt\\toolchain\\VC\\Tools\\MSVC\\14.29.30133\\atlmfc\\include;$(printf '%s' "$SDK" | sed 's|/|\\|g' | sed 's/^/Z:/')\\ucrt;$(printf '%s' "$SDK" | sed 's|/|\\|g' | sed 's/^/Z:/')\\shared;$(printf '%s' "$SDK" | sed 's|/|\\|g' | sed 's/^/Z:/')\\um"
cmake -S /data/repo -B /tmp/rodecomp-cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=/opt/td/cmake-toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
python3 /tools/export-compile.py /tmp/rodecomp-cmake/compile_commands.json /data/repo/compile.json --source /data/repo --compiler "$TC/bin/Hostx64/x86/cl.exe" --include "$INCLUDE"
python3 /tools/export-compile.py /tmp/rodecomp-cmake/compile_commands.json /data/repo/data/compile.json --source /data/repo --compiler "$TC/bin/Hostx64/x86/cl.exe" --include "$INCLUDE"

View file

@ -4,15 +4,15 @@ import { execFileSync } from 'node:child_process';
const repo = process.argv[2];
const compilerHash = process.argv[3];
if (!repo || !/^[a-f0-9]{64}$/.test(compilerHash ?? '')) throw new Error('usage: prepare-project.mjs <repo> <compiler-sha256>');
const file = `${repo}/decomp.json`;
const file = `${repo}/data/decomp.json`;
const p = JSON.parse(fs.readFileSync(file, 'utf8'));
p.name = 'rodecomp';
p.compileCommands = 'compile.json';
p.compileCommands = 'data/compile.json';
delete p.verification;
delete p.build;
p.matchPolicy = { autoMergeIdentical: true, approvals: 1, approvalsWithHeaderChanges: 2, maxCleanupCycles: 5, peerReviews: 3, peerMargin: 3, peerRejectMargin: 2 };
fs.writeFileSync(file, JSON.stringify(p, null, 2) + '\n');
fs.writeFileSync(`${repo}/toolchain.lock.json`, JSON.stringify({ragnarok:{family:'msvc',version:'19.29.30159',machine:'x86',image:'rodecomp/compiler:v142',clSha256:compilerHash,sdkVersion:'10.0.19041.0'}}, null, 2) + '\n');
execFileSync('git',['-c',`safe.directory=${repo}`,'add','decomp.json','compile.json','toolchain.lock.json'],{cwd:repo,stdio:'inherit'});
fs.writeFileSync(`${repo}/data/toolchain.lock.json`, JSON.stringify({ragnarok:{family:'msvc',version:'19.29.30159',machine:'x86',image:'rodecomp/compiler:v142',clSha256:compilerHash,sdkVersion:'10.0.19041.0'}}, null, 2) + '\n');
execFileSync('git',['-c',`safe.directory=${repo}`,'add','data/decomp.json','data/compile.json','data/toolchain.lock.json'],{cwd:repo,stdio:'inherit'});
execFileSync('git',['-c',`safe.directory=${repo}`,'-c','user.name=Clank Together','-c','user.email=bot@clank-together.invalid','commit','-m','Configure rodecomp v142 x86 contributor builds'],{cwd:repo,stdio:'inherit'});
console.log('Configured rodecomp with pinned compiler',compilerHash);

View file

@ -5,8 +5,8 @@ const cmake=repo+'/CMakeLists.txt';
const text=fs.readFileSync(cmake,'utf8');
if(!text.includes('add_subdirectory(Verification)'))throw Error('Expected Verification target');
fs.writeFileSync(cmake,text.replace(/^add_subdirectory\(Verification\)\r?\n?/m,''));
const file=repo+'/compile.json';const cfg=JSON.parse(fs.readFileSync(file,'utf8'));
const file=repo+'/data/compile.json';const cfg=JSON.parse(fs.readFileSync(file,'utf8'));
for(const unit of Object.keys(cfg.units))if(unit.startsWith('Verification/'))delete cfg.units[unit];
fs.writeFileSync(file,JSON.stringify(cfg,null,2)+'\n');
execFileSync('git',['-C',repo,'add','CMakeLists.txt','compile.json']);
execFileSync('git',['-C',repo,'add','CMakeLists.txt','data/compile.json']);
execFileSync('git',['-C',repo,'-c','user.name=Clank Together','-c','user.email=bot@clank-together.invalid','commit','-m','Remove build references to deleted verification sources'],{stdio:'inherit'});