A patch release with one theme: the workflow stops paying for work it does not need and stops hiding work it failed to do. /rank no longer drags your whole job history through the conversation on every run, the portal CLIs now refuse bad input instead of silently returning the wrong thing, and forks get a clean CI and a complete /setup. Seventeen entries, fourteen of them fixes, most of them reported and fixed by contributors within a day of each other.
Highlights
/rank is bounded and keeps its state on disk (#395, #424, #425, #390)
A bare /rank used to score the entire backlog in one go and read the whole of seen_jobs.json into the conversation twice per run - a cost that grew for the life of a workspace and was paid regardless of batch size (one reporter measured a 188 KB state file). --limit <N> now bounds each run to ten jobs by default, independently of --top, and reports what it deferred. tools/rank_state.py owns the state traffic: candidates selects and projects only the fields a scoring agent needs, sweep runs the expiry pass on disk, and apply writes results back atomically. Scoring policy is unchanged, and every existing write-back rule (legacy location migration, null deadlines never erasing a stored one, verbatim strengths and gaps) is pinned by tests. /rank also now flags postings whose stored posted_date is more than 30 days old.
Portal CLIs fail loudly instead of lying (#426, #429, #371, #416, #418, #421)
The sharpest fix of the release: the unknown-flag guard in the four bunli-based CLIs only inspected --long flags, so an undefined short flag was silently discarded and the search ran unfiltered - search -q "sygeplejerske" on jobnet returned 18,210 ads with exit 0 where the correct flag returns 669. Both dash forms are now checked. The detail commands of jobbank, jobdanmark and jobnet accept full posting URLs as the contract always said they should, linkedin-search rejects fractional numeric flags instead of truncating them, and a one-CLI-at-a-time audit closed three crashes where a single null field from a portal API killed the whole run (a jobbank feed date, a jobnet publication date, a jobdanmark autocomplete item).
Forks get a clean CI and a complete /setup (#405, #433, #396)
The python-tests job ran the upstream-only placeholder-integrity tests on every personalised fork and failed permanently; they now skip when GITHUB_REPOSITORY is a fork and still run locally and upstream. /setup now fills the contact blocks inside 05-cv-templates.md and 06-cover-letter-templates.md - the two templates /apply compiles from - which a full run previously left as [YOUR_NAME] and [YOUR_EMAIL]; /reset restores them. And settings.json no longer pre-approves bun run on arbitrary files: the allowlist is one path-scoped entry per shipped portal CLI.
Salary data tools stop failing silently (#414, and the salary_lookup.py null fix)
convert_salary_excel.py could mistake a source-citation line above a real header for the header itself and drop every company's salary data with exit 0; header detection now requires cross-cell corroboration and warns when a sheet yields no salary columns. salary_lookup.py no longer crashes on a null metadata or categories field.
Fork maintainers: what to reconcile
Pull this tag rather than raw master, then check three things:
/rankbehaviour changed. A bare run now scores at most 10 jobs and reports the rest as deferred; pass a larger--limitif you relied on scoring everything in one go. State moves throughtools/rank_state.py; if you customisedrank.md's Step 1 or Step 4, re-read the new versions before merging your changes over them..claude/settings.jsonchanged twice. The blanketBash(bun run:*)entry is gone in favour of one path-scoped line per shipped CLI, and twopython tools/rank_state.pylines were added. A fork with its own portal skills needs its own path-scopedbun runline per skill (and the matchingtools/security_guards.pyentry), or/scrapewill prompt once per run./setupand/resetcover two more files. If you already personalised05-cv-templates.mdand06-cover-letter-templates.mdby hand, nothing changes; if you have not, re-run/setup --sectionfor the contact blocks or edit them directly.
No framework_version marker changed in this release: the methodology files under job-application-assistant/ are as they were in 1.7.0.
Also in this release
- A CHANGELOG structure guard runs on every PR (duplicate or unknown headings, orphan entries, conflict markers).
/scrapepersists each posting's publication date (#391), which/ranknow consumes.linkedin-search detailaccepts LinkedIn job URLs with trailing slashes, regional subdomains and tracking parameters (#411).- The
documents/interview/**ignore rule no longer claims interview prep is written there;/interviewhas always saved underdocuments/applications/, which was already ignored (#336).
Thanks to everyone who reported and fixed this cycle - ayobamiseun for the null-deref audit across all six CLIs, Na-bra for the salary and flag-guard fixes, InstinctEx for the /rank work and the numbers behind it, iAbhiNaV2005 for the URL normalisation, markvandeven for the fork-CI diagnosis, and shahidbeig-a11y for carrying it.