From 04d62900d7644062269f2fa5feec404d08280fac Mon Sep 17 00:00:00 2001 From: root Date: Tue, 21 Jul 2026 09:53:48 +0200 Subject: [PATCH] fix(tasktree): expose L1 source provenance --- .../scripts/tasktree-native-service.ts | 51 ++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/web/hwlab-cloud-web/scripts/tasktree-native-service.ts b/web/hwlab-cloud-web/scripts/tasktree-native-service.ts index 242c8996..4c151254 100644 --- a/web/hwlab-cloud-web/scripts/tasktree-native-service.ts +++ b/web/hwlab-cloud-web/scripts/tasktree-native-service.ts @@ -1,8 +1,9 @@ -import { mkdirSync, openSync, readFileSync, rmSync } from "node:fs"; +import { mkdirSync, openSync, readFileSync, readlinkSync, realpathSync, rmSync } from "node:fs"; import { resolve } from "node:path"; const action = process.argv[2]; const root = process.cwd(); +const repoRoot = resolve(root, "../.."); const stateDir = resolve(root, ".state/tasktree-native"); const pidPath = resolve(stateDir, "supervisor.pid"); const logPath = resolve(stateDir, "supervisor.log"); @@ -34,6 +35,33 @@ function isRunning(pid: number | null): boolean { } } +function canonicalPath(path: string): string { + try { + return realpathSync(path); + } catch { + return resolve(path); + } +} + +function runningProcessCwd(pid: number | null): string | null { + if (!pid) return null; + try { + return canonicalPath(readlinkSync(`/proc/${pid}/cwd`)); + } catch { + return null; + } +} + +function gitCommit(workspace: string | null): string | null { + if (!workspace) return null; + const result = Bun.spawnSync(["git", "-C", workspace, "rev-parse", "HEAD"], { + stdout: "pipe", + stderr: "ignore" + }); + if (result.exitCode !== 0) return null; + return result.stdout.toString().trim() || null; +} + async function waitForExit(pid: number): Promise { const deadline = Date.now() + 15000; while (Date.now() < deadline) { @@ -79,7 +107,26 @@ if (action === "start") { } } else if (action === "status") { const running = isRunning(pid); - console.log(JSON.stringify({ ok: running, action, status: running ? "running" : "stopped", pid: running ? pid : null, logPath, servicesLogPath })); + const processCwd = runningProcessCwd(running ? pid : null); + const sourceWorkspace = processCwd ? canonicalPath(resolve(processCwd, "../..")) : null; + const expectedProcessCwd = canonicalPath(root); + const expectedSourceWorkspace = canonicalPath(repoRoot); + console.log(JSON.stringify({ + ok: running, + action, + status: running ? "running" : "stopped", + pid: running ? pid : null, + logPath, + servicesLogPath, + provenance: { + expectedSourceWorkspace, + sourceWorkspace, + processCwd, + commit: gitCommit(sourceWorkspace), + workspaceMatches: sourceWorkspace === expectedSourceWorkspace, + processCwdMatches: processCwd === expectedProcessCwd + } + })); process.exit(running ? 0 : 1); } else if (action === "logs") { for (const path of [logPath, servicesLogPath]) {