#3715 fixed this class for the analysis scripts, which only read. Three tracker writers still have it, and one of them is the write path the whole system funnels through.
set-status.mjs:103 const CAREER_OPS = dirname(fileURLToPath(import.meta.url)); // the CODE root
set-status.mjs:263 const APPS_FILE = resolveTrackerPath(CAREER_OPS);
getCareerOpsRoot() — the only thing that honours CAREER_OPS_ROOT, CAREER_OPS_DATA_DIR and the .career-ops-data marker — is never called.
Measured
Tracker at a configured data root, cwd elsewhere:
$ CAREER_OPS_ROOT=<root> node set-status.mjs 1 Interview --json
{"error":"No tracker found at <CHECKOUT>/applications.md","code":"no-tracker"}
It names a file the user never configured, while their real tracker sits untouched.
Why this one is the sharp case
So on any configured data root, the single supported way to change an application's status does not work — and outcome.mjs, which shells out to it, fails the same way.
The full census
Every resolveTrackerPath() caller in the repo, by what it is handed:
OK (data root) 16 scripts
BUG (code root) set-status.mjs, mark-pdf-ready.mjs, outcome.mjs
Note for a fix
set-status.mjs and outcome.mjs need two roots, not a substitution. set-status reads templates/states.yml, which ships with the code and is absent from a user's data root — moving everything to the data root would break every status validation. outcome.mjs shells out to sibling scripts and uses its own directory as their cwd.
PR to follow.
#3715 fixed this class for the analysis scripts, which only read. Three tracker writers still have it, and one of them is the write path the whole system funnels through.
getCareerOpsRoot()— the only thing that honoursCAREER_OPS_ROOT,CAREER_OPS_DATA_DIRand the.career-ops-datamarker — is never called.Measured
Tracker at a configured data root, cwd elsewhere:
It names a file the user never configured, while their real tracker sits untouched.
Why this one is the sharp case
AGENTS.mdcalls it "the canonical (locked, validated, atomic) write path"/api/statusonto itSo on any configured data root, the single supported way to change an application's status does not work — and
outcome.mjs, which shells out to it, fails the same way.The full census
Every
resolveTrackerPath()caller in the repo, by what it is handed:Note for a fix
set-status.mjsandoutcome.mjsneed two roots, not a substitution.set-statusreadstemplates/states.yml, which ships with the code and is absent from a user's data root — moving everything to the data root would break every status validation.outcome.mjsshells out to sibling scripts and uses its own directory as their cwd.PR to follow.