From 91c799f7d3754e7f7660319ce87113ef03e6f7d3 Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Tue, 27 Oct 2026 15:41:06 +0100 Subject: [PATCH] Read project config from data/ (decomp.json, compile.json, toolchain.lock.json) --- README.md | 4 ++-- deploy/rodecomp/bulk-install.mjs | 2 +- src/client/ghidra.js | 4 ++-- src/client/ops.js | 2 +- src/shared/project.js | 6 +++--- template/README.md | 4 ++-- template/{ => data}/decomp.json | 0 template/{ => data}/toolchain.lock.json | 0 test/server.test.js | 2 +- toolchain/msvc2010/Dockerfile | 2 +- tools/rodecomp/configure.sh | 2 +- tools/rodecomp/prepare-project.mjs | 8 ++++---- tools/rodecomp/remove-verification.mjs | 4 ++-- 13 files changed, 20 insertions(+), 20 deletions(-) rename template/{ => data}/decomp.json (100%) rename template/{ => data}/toolchain.lock.json (100%) diff --git a/README.md b/README.md index 002f31d..f62f964 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/deploy/rodecomp/bulk-install.mjs b/deploy/rodecomp/bulk-install.mjs index 19a86c6..89853e4 100644 --- a/deploy/rodecomp/bulk-install.mjs +++ b/deploy/rodecomp/bulk-install.mjs @@ -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 }; diff --git a/src/client/ghidra.js b/src/client/ghidra.js index 975b2e8..3660775 100644 --- a/src/client/ghidra.js +++ b/src/client/ghidra.js @@ -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)); diff --git a/src/client/ops.js b/src/client/ops.js index cae4843..4447de0 100644 --- a/src/client/ops.js +++ b/src/client/ops.js @@ -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 is required for the ${type} runner`); diff --git a/src/shared/project.js b/src/shared/project.js index 5f4ee15..a125d19 100644 --- a/src/shared/project.js +++ b/src/shared/project.js @@ -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')) : {}; } diff --git a/template/README.md b/template/README.md index 24df855..801f9db 100644 --- a/template/README.md +++ b/template/README.md @@ -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 --name `. diff --git a/template/decomp.json b/template/data/decomp.json similarity index 100% rename from template/decomp.json rename to template/data/decomp.json diff --git a/template/toolchain.lock.json b/template/data/toolchain.lock.json similarity index 100% rename from template/toolchain.lock.json rename to template/data/toolchain.lock.json diff --git a/test/server.test.js b/test/server.test.js index 60180b2..4c7bf9f 100644 --- a/test/server.test.js +++ b/test/server.test.js @@ -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); }); diff --git a/toolchain/msvc2010/Dockerfile b/toolchain/msvc2010/Dockerfile index 2d2db4c..58a37a9 100644 --- a/toolchain/msvc2010/Dockerfile +++ b/toolchain/msvc2010/Dockerfile @@ -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 diff --git a/tools/rodecomp/configure.sh b/tools/rodecomp/configure.sh index 325f8cc..84d5b1f 100644 --- a/tools/rodecomp/configure.sh +++ b/tools/rodecomp/configure.sh @@ -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" diff --git a/tools/rodecomp/prepare-project.mjs b/tools/rodecomp/prepare-project.mjs index d1794eb..376402e 100644 --- a/tools/rodecomp/prepare-project.mjs +++ b/tools/rodecomp/prepare-project.mjs @@ -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 '); -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); diff --git a/tools/rodecomp/remove-verification.mjs b/tools/rodecomp/remove-verification.mjs index d7b7937..79c523a 100644 --- a/tools/rodecomp/remove-verification.mjs +++ b/tools/rodecomp/remove-verification.mjs @@ -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'});