ff12f16545ee37da68090c7e2c1f74e7fa30c1b6
8
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
34299bce54 |
fix: follow-up review corrections, BIS rejection, and a gitignore miss
Second-pass review of this session's work by another agent. It corrected several
real mistakes of mine and finished F06 gaps I had left open. Reviewed, verified
and committed as-is.
THE MISS THAT MATTERS
`job_scout/state/applications.json` — the authoritative application registry
introduced by F02 — was never actually tracked. `job_scout/state/*` in
.gitignore silently excluded it, so my checkpoint commit
|
||
|
|
b8c5141279 |
fix(F18-F19): get evidence onto page one earlier, measured not asserted
F18 - page-one weighting - Across four compiled packages the first employment entry began at 45-55% of page one. A reader reaching the middle of the page had seen a profile and a skills block, and no evidence. - The old skills rule counted `\skillline` MACROS, which does not control density: six categories with long value lists wrap to twelve or more rendered lines. Replaced with a rendered-line budget verified in the compiled PDF, plus the rule that a skills line repeating what three bullets below already prove is spending the first screen to say it twice. - Employer chronology stays reverse-chronological; the ordering freedom is WITHIN a position, where the bullet closest to the target role leads. - New helper `page_metrics.py` measures page-one geometry from the PDF via pdftotext -bbox. F19 - education and phrasing - Degree + focus + institution crammed into one cell with a right-aligned date produced visible word spacing and mid-word breaks in SBB, NVIDIA and Aker BP. Split the entry, as RUAG_AI_Engineer_C5I already did. Template carries the rule. - Grades and thesis stay only where concretely relevant. claims.json grade_output_rule already keeps grades off by default; the M.Eng. thesis earns its place on condition-monitoring or sensor-data roles and otherwise does not. Validated by measurement rather than assertion - page_metrics.py first reproduced the review's own figures (NVIDIA 55.4%, SBB 50.6%, RUAG 50.3%). That is what makes the after-figure meaningful. - The NVIDIA CV was rebuilt FROM A COPY with the guidance applied: experience moved 55.4% -> 44.0% of page one, page-one text lines 47 -> 39, still two pages, zero overfull boxes, validator PASS. - The submitted package itself was not modified. F17 classifies archives as evidence, not as drafts. The percentage is a diagnostic, not a target: no pixel goal and no rule that page two must be filled. All 19 review findings are now complete. 37/37 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qej5SBvhcbGXHwLqNWiskM |
||
|
|
eecdbdade6 |
fix(F17): a PDF in a folder is not proof the package can be rebuilt
Build sweep run this session: 48 sources, 46 built, 2 failed. Infineon_AI_Engineer's cover letter fails on font expansion (the font is not scalable); cv_template.tex fails on unfilled placeholders, which is expected for the academic legacy path. Overfull boxes: Microsoft ISE 25.33pt, Isovalent 0.88pt. All historical, all left alone. New: resume_builder/helpers/package_manifest.py records, per application package, what a rebuild would ACTUALLY do - sources, class-file hashes, PDFs present, and the reasons a rebuild would not reproduce the submitted document. It is descriptive; nothing in it authorises rewriting a submitted file. What it found across 21 packages: - 17 are DATE-DEPENDENT. The cover letters use oday, so recompiling a historical package silently restamps it with today's date. - 1 has an INCOMPLETE SOURCE DISTRIBUTION: output/NATO_AI_ENGINEER ships no resume.cls. It builds on this machine only because a copy exists elsewhere, and the shipped PDF hid that. Not repaired by copying the newest class in - the repo carries THREE different resume.cls variants (13/7/1 copies) and older macros differ, so that "fix" could silently change a historical document. - 1 has no PDF at all, so nothing is reviewable without a build. Classification: 7 application packages were in no reuse category. Added to historical_revalidate, and the register now records the default explicitly - anything unlisted is treated as revalidate-before-reuse. Being recent is not the same as being verified; none of the seven was re-read for this. Prevention rather than repair: oday removed from the cover-letter template so new packages stop adding to the pile. A test now fails if it comes back, if the manifest goes stale, or if a package is left unclassified. Also: scan_document gained a template mode. A placeholder in a TEMPLATE is what makes it a template; the defect is one surviving into a generated document. 37/37 tests pass; counter-proof still catches all 9. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qej5SBvhcbGXHwLqNWiskM |
||
|
|
c7e8d4e058 |
fix(F15-F16): stop losing dates, contacts and whole daily reports
F15 - dates and metadata kept their meaning - The Taleo parser stored an application DEADLINE in `posted`, so a role closing on 30 September looked as though it had been published then - backwards for a freshness signal. It now populates `deadline`, and `posted` stays empty because that board genuinely publishes none. - The Prospective adapter read unit, Lohnklasse and a named contact, folded them into `description` for scoring, and `_process_company` then discarded `description` - losing exactly the fields that decide level, pay and whether a cold submit is necessary. They are now carried as fields through to the report and the JSON dump, alongside `date_provenance`. - Named contacts now appear in report rows. Channel is the rationed variable since 2026-09-05, so a published, reachable name is the difference between a cold submit being a choice and being the only option. F16 - writes stopped destroying delivered work - Every run of a day wrote `<date>.md`/`.json`, so a restricted run replaced the full daily report. This is not hypothetical: it happened twice in this session and both times the 37-company run had to be repeated by hand. Restricted runs now write `<date>.only-kdocy.md` and say so. - `save_seen()` ran in a `finally:` BEFORE the report was written. A failed report write therefore left roles marked seen, so a `--new-only` retry would hide precisely the hits that were never delivered. Seen-state is now committed only after report and dump are on disk - and never by a restricted run, which did not look at the whole board. - Atomic writes used a fixed `.tmp` name; two writers could share it and os.replace the wrong content into place. Unique temp names now. 34/34 tests pass; validated on a live 37-company run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qej5SBvhcbGXHwLqNWiskM |
||
|
|
ce8619b8e3 |
fix(F14): call keyword relevance what it is, and teach it German
The scout presented a keyword count as "Strong fit" / "Medium fit". It is neither: it measures how many profile keywords a posting echoes, and knows nothing about his evidence, the hard requirements, the level, the language or the commute. - Buckets renamed to keyword relevance, with "NOT a fit judgement" in the heading, and score_job documents the limit with the review's own example: "Senior AI Engineer, Generative AI / LLM / RAG" scores 12 against "Senior Data Engineer" at 3, while the second is much closer to what he can evidence. - German job vocabulary added. Every German-language posting used to score near zero regardless of fit, which is the real reason RUAG, SBB, BKW, PostFinance and Kdo Cy all needed a _score_floor. The floor was a workaround; the missing terms were the defect. "Senior Dateningenieur" 1 -> 3, level with its English twin. - Platform/DevOps vocabulary was simply absent: devsecops, platform engineer, platform automation, infrastructure as code, observability, site reliability. The Kdo Cy "ICT-System Engineer (DevSecOps / Platform Automation)" scored ZERO before this - a posting whose requirement lines match his canonical evidence almost line for line. It now scores 10. - Noise is unaffected: "Office Manager:in Administration" still scores 0. Floors were left in place so this diff stays attributable; they can likely be reduced now that the vocabulary exists. 34/34 tests pass; validated on a live 37-company run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qej5SBvhcbGXHwLqNWiskM |
||
|
|
3519b2ffe7 |
fix(F08-F10): machine-checkable evidence, honest templates, demoted GPA
F08 - evidence metadata - Only 1 of 26 claims carried structured source/last_verified/ownership, which is why recency and reference checks could not run. Added an evidence_schema block and an evidence block on all 26 claims. - 8 dates were recovered from each claim's OWN recorded text; the other 18 are written as the literal "unrecorded". Nothing was inferred. "unrecorded" means nobody wrote it down, NOT that the claim is unevidenced - most carry evidence in their free-text scope. - Coverage is reported as an advisory warning, never a gate: failing on it would push a future session to invent dates to clear the run. F09 - templates - resume_template.tex asserted "12+ years of production software experience". It does not hold: canonical employment starts 2014-11 (~11y10m) and the VISIBLE chronology starts 2015-05 (~11y4m) because Capgemini is omitted. Now "over ten years", with the arithmetic and the no-date-math rule inline. - cv_template.tex still carries page targets, rendered-line budgets and 2L/3L variants the project dropped. Banner-marked as the ACADEMIC legacy path so it is not reached for whenever a posting says "CV". F10 - US GPA - The modified Bavarian formula converts FOREIGN grades INTO the German system. Inverting it to produce a US GPA is not a recognised method, and the TUM source calls even its forward calculator orientation only. - Fields renamed to final_grade_us_4pt_orientation_only with that caveat. The German grades remain the canonical facts. If a recipient publishes its own conversion, use theirs and record which was used. Validator PASS (1 advisory), 31/31 tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qej5SBvhcbGXHwLqNWiskM |
||
|
|
fc5f3e49ba |
fix: review findings F03-F06 — quotas, rule hierarchy and a validator that checks
F03 — application records
- Quota already removed with F02's tracker; verified uncapped and that
"interview reached" survives a later withdrawal.
- Aker BP: application date confirmed 2026-07-29 by the user, settling the
one-day conflict. Its Adjacent-despite-79 classification is kept, NOT
reclassified: the user does not remember the rationale and judged it
immaterial on a closed role, and silently reclassifying to make the
arithmetic tidy is the exact objection the review raised. Recorded as an
explicit override reason with a rubric version instead.
F04 — rule hierarchy
- Three levels stated in AGENTS.md and CLAUDE.md: immutable evidence rules,
standing user preferences, market/employer presentation.
- Deliverables separated from QA. The .tex stays the artefact of record; you
still compile, into the application's own output/ folder, because the user
cannot approve what he cannot open.
- `resume_reference.md` said "Capgemini/Bundeswehr: include only when directly
relevant", contradicting the standing never-include rule. Split and fixed.
F05 — a green validator now means something
- Per-claim `forbidden` wording is enforced. 14 of 26 claims carried such a
list and NONE of it was checked, which is why "owned the full ML lifecycle"
passed. Matching tolerates inserted adjectives: the real regression read
"Built a decentralized Data Mesh" and one word defeated the literal list.
- Added identity (e-mail/phone), employer-date, placeholder and
document-exclusion checks. Capgemini's omission rule now has a canonical
home in claims.json instead of living only in memory and config.md.
- Registered Groovy and Snowflake as forbidden skills. Both were absent from
claims.json entirely, so "forbidden" existed in prose with nothing enforcing
it.
- PASS no longer reads as a truth certificate: it prints what it did not check
— scope implications, bullet-to-claim support, whether a number is real.
F06 — the scanner stopped fighting the documents
- LaTeX comments are no longer claims; `% never claim Terraform` was a finding
before, which taught the workflow to write around the checker.
- Markup, accent macros and umlauts are normalized, so `\textbf{Snow}flake`
cannot smuggle a forbidden skill past a substring test and
`Universit\"at der Bundeswehr M\"unchen` is recognisably a school.
- Honest denials pass in English and German.
- The triple-list cadence hint knew only English "and", so it silently did
nothing on every German package. Advisory only, and now labelled as such.
Verification
- The six counter-proofs from the report are caught: 9 errors on one synthetic
document, where the old scanner found none.
- All six packages built under current rules scan clean — SBB, NVIDIA, RUAG,
Kdo Cy, Citadel, Aker BP. Four false positives of my own were found and fixed
on the way there; each is now a regression test.
- 13 older packages do report findings. Those look like genuine historical
violations and are deliberately NOT fixed here: F17 governs archives and they
must not be silently rewritten.
- `tests/test_document_scanner.py` added. Full suite 31/31 pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qej5SBvhcbGXHwLqNWiskM
|
||
|
|
afdef7eb94 |
refactor: shared agent workflows (F01) and one application registry (F02)
Checkpoint for the 2026-09-11 project review remediation. Work by a previous agent that ran out of context; committed unchanged as a rollback point before the remaining findings land on top of it. F01 — the two agent directories had drifted into different processes - Six shared workflows under `resume_builder/reference/workflows/`; both `.agents/skills/` and `.claude/skills/` are now thin entrypoints that route to the same file instead of carrying full copies. - The `.claude` copies were the stale side: fixed bullet line variants and character budgets that the newer process had already dropped. Removing them is the point of the change, not collateral. - Parity/link regression test added; corrected the top-level file map, which pointed at a directory that does not exist. F02 — application status was stored in four places and disagreed - New registry `job_scout/state/applications.json` (26 records) with `application_records.py` (schema, validation, transactional write) and `application_tracker.py` (add/update, no quota). - AGENTS.md and CLAUDE.md no longer keep their own status tables; both point at `current_applications.md`, generated from the registry. - Interview-reached is now independent of outcome, so a withdrawal after an interview can record both facts. The old tables are preserved verbatim in `job_scout/state/history/application_status_before_2026-09-11.json`. Verification: `python -m unittest discover -s tests -v` — 18/18 pass. Spot-checked that the detailed SBB and Kdo Cy notes survived the migration into the registry rather than being flattened. Known unresolved, deliberately not invented (see FIX_PROGRESS.md): Aker BP's application date and its Adjacent-despite-79 classification. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qej5SBvhcbGXHwLqNWiskM |