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
This commit is contained in:
dennisthiessenandClaude Opus 5 committed 2026-09-11 19:23:13 +02:00
1 parent 0d999ab21b
commit afdef7eb94
33 files changed
+1558 -1768

No files matched your search

@@ -45,8 +45,8 @@ literals the session had flagged as risky.
**What is kept: the recording, not the rationing.** Every application still records fit class, hard
gate, channel, date, stage and outcome. That record is what makes patterns visible instead of
re-derived, and it produced every useful finding to date. `application_cohort.json` continues as a
durable log; `cohort_tracker.py summary` remains a read-only view. There is no slot to consume and no
re-derived. `job_scout/state/applications.json` is the durable registry; `application_cohort.json` is
a generated historical-cohort projection. `cohort_tracker.py summary` is a read-only view. There is no slot to consume and no
application is blocked for lack of one.
**Fit class is now a preparation signal, not a spend limit.** An Evidence Fit of 64 does not mean
@@ -0,0 +1,41 @@
# Current applications
Generated from `job_scout/state/applications.json`; do not edit this view.
Use current outcome and next action below. Imported legacy notes are historical, not current instructions.
| Application | Current outcome | Interview reached | Next action |
|---|---|---|---|
| NVIDIA - Senior DevOps Engineer, Zürich (req JR2024256) | applied | not recorded | **Await response. Raise the working model at first contact** - it went in unresolved and a 5-day-onsite seat would be a late no. Note: `claims.json` has no shell-scripting entry, so **Bash is omitted** from Skills although the JD names it and ten years of Debian admin plus Ansible work plainly involve it - same shape as the Ansible/Linux gaps found 2026-08-27. Confirm with the user and record it. Groovy stays out regardless. |
| RUAG C5I - AI Engineer C5I, Thun (application ID 18027) | applied | not recorded | Await response. Optional but still worthwhile: call **Marco Heinzen** about technical scope and level, and **Frank Haugwitz** about compensation and PSP/project eligibility. **NEW CONTACT 2026-09-07 — `Lars Kauz`, Head of ICT Infrastructure C5I, +41 79 293 93 82, lars.kauz@ruag.ch**, published on the System Engineer C5I posting. Channel is the rationed variable since the 09-05 cohort change, so a published, reachable name matters — **but he heads ICT Infrastructure, the function whose req was ruled out for VMware/VDI/Windows content, and that is NOT demonstrably the Kubernetes platform group Senior DevOps C5I sits in.** He is a warm entry into C5I, not a verified channel for rank 1; Haugwitz stays the recorded gate. Do not react to a single outcome with positioning changes (`application_strategy.md` §38/§74). |
| Schweizer Armee - Kommando Cyber (Kdo Cy), DevOps Engineer III (Data Platform), Zimmerwald (Ref JRQ$540-19848) | rejected_no_interview | not recorded | Closed; no pending application action. Read recorded history before reopening. |
| Citadel Securities — Platform Engineer, Research Platform Engineering, Zürich (also NY/Miami) | applied | not recorded | **Await response** (submitted 2026-08-26). No document work pending. **Two questions travel with this application and must both be asked at first contact, before any interview effort:** (1) **is the application even against the Zürich seat?** — the apply form offered no Zürich, so it may sit against a US req, which is a hard NO on relocation; (2) **hybrid or 5-day onsite?** — unresolved at submission, and 5-day onsite is a likely NO-GO on the Bern constraint. Same shape as the NVIDIA working-model issue: it went out unresolved, so it is now a live screening topic rather than a pre-cleared one. Also unasked: the Zürich compensation figure — the posting's $175–350k is a US/NY pay-transparency disclosure. |
| SBB - Data Engineer (m/w/d), Asset Management Infrastrukturanlagen, Bern (Job ID 103755) | withdrawn_by_candidate | yes | Closed. For future SBB roles assess Niveau L/Kader; do not generalize SBB bands to other employers. |
| AWS (AWS EMEA SARL, Switzerland Branch) — Senior Forward Deployed Engineer, Zürich (job 10504263) | not_proceeding | not recorded | Closed; no pending application action. Read recorded history before reopening. |
| Google — Forward Deployed Engineer III, Google Cloud GTM (French, German), Zürich (req 78350205438567110) | not_proceeding | not recorded | Closed; no pending application action. Read recorded history before reopening. |
| SDU Center for Energy Informatics, Odense DK — PhD, Theme 2 Predictive Maintenance & Asset Management of Smart Energy Networks (job 4159) | not_proceeding | not recorded | Closed; no pending application action. Read recorded history before reopening. |
| Aker BP ASA — Data Product Architect, AI-ready Data Products (FINN 469067315) | rejected_no_interview | not recorded | Closed; no pending application action. Read recorded history before reopening. |
| Google - Software Engineer III, Business Home, Zurich (req 93922217108087494) | rejected_no_interview | not recorded | Closed; no pending application action. Read recorded history before reopening. |
| Microsoft — Principal Forward Deployed Engineer, SWE (German Speaking), Zürich (req 200043897) | applied | not recorded | Done — await response |
| BIS Basel — Senior Data & Analytics Engineer, AI (jr100429, 3-yr term) | applied | not recorded | Prep interview brief when screening lands |
| NATO JWC Stavanger — Staff Officer, AI Engineer (2030 Digitalisation, G15, 3-yr PLN) | applied | not recorded | Await screening; no action until contact |
| Microsoft — Senior SWE, Industry Solutions Engineering (ISE), Zürich (req 200040836) | rejected_no_interview | not recorded | Closed; no pending application action. Read recorded history before reopening. |
| Kraken (Payward) — SRE, AI Agents (remote, CH-eligible) | rejected_no_interview | not recorded | Closed; no pending application action. Read recorded history before reopening. |
| Google — Senior Data Engineer (Merchant Data Science), Zürich/MV | rejected_no_interview | not recorded | Closed; no pending application action. Read recorded history before reopening. |
| Snowflake — Sr SWE, Enterprise (Observe by Snowflake), Zürich | closed_no_response | not recorded | Closed; no pending application action. Read recorded history before reopening. |
| Isovalent (Cisco) Sr Data Engineer, Observability | role_closed | not recorded | Closed; no pending application action. Read recorded history before reopening. |
| Google Zürich Sr SWE Infrastructure (Data Pipeline) | not_proceeding | not recorded | Closed; no pending application action. Read recorded history before reopening. |
| Kraken AI Infrastructure | rejected_no_interview | not recorded | Closed; no pending application action. Read recorded history before reopening. |
| Infineon Doctoral | withdrawn_by_candidate | yes | Closed; no pending application action. Read recorded history before reopening. |
| Infineon AI Engineer | not_proceeding | not recorded | Closed; no pending application action. Read recorded history before reopening. |
| Apple Data Engineer (ISE, Zurich) | rejected_no_interview | not recorded | Closed; no pending application action. Read recorded history before reopening. |
| Google FDE GenAI (Zurich) | paused | not recorded | Likely abandon |
| Equinor — Manager / AI Architect, Agentic systems (Stavanger/Oslo/Rotvoll/Sandsli; req JR106747) | rejected_no_interview | not recorded | Closed; no pending application action. Read recorded history before reopening. |
| QuantCo Cloud Engineer (Europe/Zürich) | rejected_no_interview | not recorded | Closed; no pending application action. Read recorded history before reopening. |
## Current targeting notes
- SBB Niveau K/L is SBB-specific. The reported approximate CHF 145k K ceiling is not a salary anchor for other employers.
- Assess headroom and total package: working time, holidays, office days, commute and verified benefits. Never decline a Thun-area role on salary band alone.
- Childcare-cost coverage at the Swiss Army/Kdo Cy remains unverified; confirm before pricing it.
- Norway remains open selectively; the Swiss compensation threshold does not automatically apply there.
- An interview does not prove how an ATS or recruiter evaluated the application. No causal inference from a single conversion.
+2 -2
View File
@@ -5,7 +5,7 @@
Before generation, editing or critique:
1. Read `resume_builder/canonical/claims.json` completely.
2. Read `config.md` and `AGENTS.md` corrections/status.
2. Read `config.md`, `AGENTS.md` corrections and `resume_builder/reference/current_applications.md`. Application status is authoritative in `job_scout/state/applications.json`; the Markdown view and old cohort JSON are generated projections. Historical events are not current instructions.
3. Run `python resume_builder/helpers/validate_resume_system.py`.
4. Treat canonical claims as higher authority than extractions, experience files, bundles, sessions or outputs.
5. Never use a file under `output/` as source content for a new application. Consult `resume_builder/canonical/historical_outputs.json`.
@@ -88,4 +88,4 @@ After explicit approval:
## Progress and Recovery
Give short progress updates at major steps. Before ending or clearing context, update session Status and the Active Sessions pointer. If interrupted, add a Resume Point describing completed work and the exact next action.
Give short progress updates at major steps. Before ending or clearing context, update session Status and the application registry through the tracker; regenerate its views. Do not duplicate status in AGENTS or CLAUDE. If interrupted, add a Resume Point describing completed work and the exact next action.
@@ -0,0 +1,59 @@
<!-- Shared workflow version: 2026-09-11 -->
# Critique an Application Package
## Startup
1. Read `resume_builder/reference/shared_ops.md`.
2. Read `resume_builder/canonical/claims.json` completely.
3. Read `config.md`, the session file, and the real verbatim JD.
4. Stop if the JD is reconstructed, incomplete or inferred.
5. Read `resume_builder/reference/critique_framework.md` and `resume_builder/support/ai_fingerprint_rules.md`.
6. Read the resume and optional cover letter. Never use either as evidence; verify against canonical claims and experience files.
## Preflight
Run:
```powershell
python resume_builder/helpers/validate_resume_system.py --document <resume.tex>
```
Add `--document <cover_letter.tex>` when a letter exists. Any failure is Tier 1 and prevents approval.
Compile the documents and inspect the PDFs. Extract resume text with `pdftotext` and confirm that employer, formal title and dates appear in the expected order.
## Critique
Follow `critique_framework.md` exactly:
1. Hard-gate audit.
2. Evidence Fit score, independent of writing.
3. Document Quality score, independent of role fit.
4. Channel Strength rating.
5. Competitive and reader-sequence assessment.
6. Canonical claim audit.
7. Tiered fixes.
8. Cover-letter decision/critique.
9. Mechanical verification.
Do not issue a single overall score. Do not label a high-quality document submit-ready when Evidence Fit fails a hard gate.
## Cover-Letter Handling
If the session records `Cover Letter Decision: NO`, do not penalize absence. If a letter exists, first assess whether it should exist under `cl_reference.md`.
## Save and Report
Save `output/<Folder>/critique_<name>.md`. Update the session with:
- Evidence Fit score and Core/Adjacent/Stretch classification.
- Hard-gate result.
- Document Quality score.
- Channel Strength.
- Tier 1 fixes.
- Critique status and date.
Present the fit verdict first, then the two scores and actionable fixes. Wait for explicit user approval before finalization or editing.
When approved, run the finalization checks from `shared_ops.md`. A package with a hard-gate NO-GO may be archived, but must not be described as recommended for submission.
@@ -0,0 +1,48 @@
<!-- Shared workflow version: 2026-09-11 -->
# Edit a Resume or Cover Letter
## Startup
1. Read `shared_ops.md` and `resume_builder/canonical/claims.json` completely.
2. Run the system validator.
3. Read the session, real JD, target `.tex`, critique/feedback, selected profile rules and relevant experience files.
4. Check `historical_outputs.json`. A package marked unsafe must be regenerated from canonical sources rather than lightly polished.
5. If the package was already submitted, preserve it as history. Create a clearly named new version only when the user requests a reusable corrected document.
## Diagnose
Classify requested changes as:
- Truth/provenance correction.
- Fit/framing correction.
- Information hierarchy or readability.
- Content selection.
- Mechanical/LaTeX.
- Blocked because evidence is absent.
Do not treat whitespace, equal bullet lengths or an exact character target as defects. Do not add filler. A critique cannot authorize an unsupported claim.
Present a concise edit plan and wait for explicit confirmation unless the user already approved specific edits.
## Execute
- Source every work claim from canonical IDs and experience files.
- Keep employer/title/date hierarchy conventional.
- Preserve natural bullet lengths and verified ownership scope.
- Remove unsupported skills rather than replacing them with synonyms.
- Update a cover letter only when its session decision is YES or the user explicitly requests it.
- If edits reveal a hard fit gate, update the Evidence Fit classification; writing improvements cannot remove the gate.
## Verify
Run the validator on every edited document, compile, inspect the PDF, and verify extracted text order. Compare before/after for:
- validator failures;
- page count;
- employer/title/date visibility;
- bullet count and relevance;
- duplicated sections;
- readability at normal size.
Update the session Edit History, Document Quality, status and next action. Mark the critique stale after material edits. Present results and wait for approval.
@@ -0,0 +1,42 @@
<!-- Shared workflow version: 2026-09-11 -->
# Decide and Generate a Cover Letter
## Startup
1. Read `shared_ops.md`, `resume_builder/canonical/claims.json`, `cl_reference.md`, the session, real JD and finished resume.
2. Run the validator on the resume.
3. Confirm that the session has a completed resume and a recorded Cover Letter Decision.
## Decision Gate
If the session says NO, explain the recorded reason and stop unless the user explicitly asks to override it. If no decision exists, apply `cl_reference.md` before writing and record YES/NO.
Do not generate a letter merely because an upload field exists or because older workflow expected a three-page package.
## Plan
State in one sentence what the letter adds beyond the resume. Select at most two evidence themes. Verify any named company/product/programme hook from a current primary source and save its URL in the session.
If the only possible content repeats resume bullets or paraphrases company news, change the decision to NO and explain why.
## Generate
- Use the selected audience profile and employer-requested language.
- International Tech/industry: normally 200--300 words in two or three paragraphs.
- Swiss/DACH: one A4 page, appropriate formality.
- Employer-specific: follow the requested format or portal limit.
- Lead with candidate-role connection.
- Add motivation, decision context or a genuine connection.
- Use only claims already present in both the canonical registry and resume.
- Never introduce a new tool, metric, customer, ownership claim or result.
## Verify
Run:
```powershell
python resume_builder/helpers/validate_resume_system.py --document <resume.tex> --document <cover_letter.tex>
```
Compile and inspect the letter. Confirm it is readable, within the employer's limit, and materially different from the resume. Update the session and present the letter for approval. Point to `/critique` next.
@@ -0,0 +1,86 @@
<!-- Shared workflow version: 2026-09-11 -->
# Generate a Resume
## Input
Accept a JD file, pasted JD, or URL. Obtain the real posting text before analysis. If it cannot be retrieved, ask the user to paste it; never reconstruct it.
## Phase 0 — Canonical and JD Preflight
1. Read `resume_builder/reference/shared_ops.md`.
2. Read `resume_builder/canonical/claims.json` completely.
3. Read `config.md`, `AGENTS.md`, `application_strategy.md`, `resume_reference.md`, and `critique_framework.md`.
4. Run `python resume_builder/helpers/validate_resume_system.py`.
5. Verify and save the verbatim JD; record source/date/status.
6. Create the output folder and session from `session_file_template.md`.
## Phase 1 — Fit Gate Before Writing
Build a requirement table with Required/Preferred and Direct/Adjacent/Gap/Constraint classifications. Cite canonical claim IDs for every Direct or Adjacent match.
Compute Evidence Fit and identify hard gates using `critique_framework.md`. Then assign:
- Core.
- Adjacent.
- Stretch.
- No-go.
Record Channel Strength and a warm-channel action for Core roles.
Stop and present the fit decision before resume planning when:
- a hard gate fails;
- the role is Stretch;
- a practical constraint is unresolved.
Proceed on a no-go only after the user explicitly overrides the stated reason. An override does not change the fit classification.
## Phase 2 — Audience and Content Plan
Select International Tech by default. Use Swiss/DACH or Employer-specific format only when the employer/context supports it.
Read the matching role bundle, `skills_taxonomy.md`, `achievement_reframing_guide.md`, and only the experience files needed for selected claims.
Plan:
- Optional 2--3 line summary.
- Four to six evidence-backed skills lines.
- Swisscom 4--5 bullets.
- Bosch 3--4 bullets.
- Zero or one bullet for each older role.
- Normally 11--14 bullets total, with no page-fill quota.
For each proposed bullet show canonical ID, evidence type, scope, and why it belongs. Identify any impact metric that still needs user confirmation.
Apply `cl_reference.md` and propose `Cover Letter Decision: YES/NO` with one reason.
Present the plan and wait for explicit user confirmation before generation.
## Phase 3 — Generate
Copy `resume.cls` and `resume_template.tex` into the output folder. For a Swiss/DACH audience, also read `resume_template_dach.tex` as an audience-policy overlay; it is not a standalone document. Write fresh content from canonical claims and experience records; never copy a historical output.
Rules:
- Employer, formal/transparent title, dates and location come first.
- Do not use tailored themes as job titles.
- Mix natural bullet lengths.
- Use only verified metrics and outcomes.
- Preserve allowed verbs and ownership scope.
- Never add a skill to mirror the JD.
- Certifications appear once.
## Phase 4 — Validate and Inspect
Run:
```powershell
python resume_builder/helpers/validate_resume_system.py --document <resume.tex>
```
Fix every failure. Compile the LaTeX, inspect both pages, and run `pdftotext` to verify parsing and information order. Do not add filler to reduce whitespace.
Update the session with the as-built content, validation results, page count, cover-letter decision, and next action.
Present the finished resume and the original Evidence Fit classification. Wait for approval. If the cover-letter decision is YES, point to `/make-cl`; otherwise point directly to `/critique`.
@@ -0,0 +1,79 @@
<!-- Shared workflow version: 2026-09-11 -->
# Build or Update the Knowledge Base
## Authority Model
The pipeline is:
`source documents -> extractions -> canonical claims -> experience records/bundles -> generated applications`
Generated applications never flow backward into the KB.
Read `resume_builder/canonical/claims.json`, `config.md`, and all relevant extractions before changing normalized sources. Preserve raw source documents. A verified correction must update canonical claims first and then every dependent normalized file.
## Canonical Claim Record
For each employment item or achievement, record:
- stable ID;
- employer, title, dates and location;
- factual scope;
- individual vs shared ownership;
- allowed verbs;
- forbidden overstatements;
- metric/result and verification status;
- evidence source;
- last verified date.
When ownership is ambiguous, use contributing/shared scope and ask the user. Do not default to full ownership.
## Experience Files
Experience files explain facts and context. They may contain example phrasings, but those examples cannot override canonical scope and should not be optimized to fixed line counts.
Every achievement section must include canonical ID, source, ownership scope, status, verified result/metric state, relevant skills and role relevance.
## Skills Taxonomy
Use only these evidence levels:
- Production — current.
- Production — historical.
- Hands-on — current.
- Project / proof of concept.
- Certification / coursework.
- Unverified / never used.
Do not assign Expert/Proficient/Familiar labels. Add a skill to canonical claims before it can appear in a generated document.
## Role Bundles
Each bundle must contain:
1. Defensible positioning.
2. Good-fit roles and hard-gate cautions.
3. Achievement priorities.
4. Safe reframing rules.
5. Evidence-backed skills guidance.
6. Conditional cover-letter guidance.
Bundles may rank evidence; they may not broaden it. Title-defining gaps must be stated explicitly.
## Significance Context
Keep company/industry context separate from candidate impact. Mark external claims for re-verification at application time. Never attach generic scale, economics, customers or market trends to the candidate.
## Correction Propagation
After any correction, search canonical claims, config, extractions, experience files, bundles, support files, templates and active drafts. Historical submitted outputs remain unchanged but update `historical_outputs.json` when they become unsafe for reuse.
## Validation
Run:
```powershell
python resume_builder/helpers/validate_resume_system.py
```
Then review the diff for dates, titles, ownership, metrics and skill evidence. Present the changed claim records and affected downstream files to the user for confirmation.
@@ -0,0 +1,98 @@
<!-- Shared workflow version: 2026-09-11 -->
# Source Evidence Extraction
Use this skill when adding new evidence to `knowledge_base/extractions/`. Extraction preserves what a source supports; it does not tailor claims to a vacancy.
## Required inputs
1. Read `config.md` and the anti-fabrication rules in `AGENTS.md`.
2. Read the complete source material.
3. Check `resume_builder/canonical/claims.json` for existing facts and identifiers.
4. Inspect related extraction files so new evidence does not create a duplicate or contradiction.
Generated resumes, cover letters, critiques, and session files under `output/` are never evidence sources.
## Extraction procedure
### 1. Identify the source
Record:
- source filename and type;
- source date, if known;
- whether it is primary evidence, user-authored notes, or a secondary description;
- the person, employer, project, or publication it concerns.
### 2. Separate evidence from inference
For every potentially reusable fact, record:
- the source-supported statement;
- the exact supporting passage or precise location;
- any interpretation separately as `Inference`;
- confidence: `verified`, `user-confirmed`, `needs verification`, or `do not use`.
Never silently convert an inference into a verified claim.
### 3. Capture career facts precisely
When applicable, extract:
- exact employer, formal title, location, and start/end dates;
- ownership scope and collaborators;
- work performed, method, technology, and domain;
- outcome and beneficiary;
- metrics with units, baseline, period, and attribution;
- publication status, authorship position, and venue;
- current versus historical skill use;
- certification versus practical experience.
For large-company work, describe only the user's component, domain, pipeline, service, or contribution. Do not infer ownership of organization-wide platforms or transformations.
### 4. Record claim controls
For each major claim, include where useful:
- allowed verbs;
- verbs or framings that would overstate ownership;
- safe resume wording;
- known contradictions requiring resolution;
- whether a metric is verified, qualitative only, or still missing.
### 5. Write the extraction
Create or update a focused Markdown file in `knowledge_base/extractions/`. Use a clear structure such as:
```markdown
# Subject
## Source
## Verified facts
## Ownership and attribution
## Outcomes and metrics
## Skills and recency
## Safe claim seeds
## Inferences / open questions
## Conflicts with existing KB
```
Claim seeds are factual building blocks, not polished resume bullets. Do not add unsupported impact language for relevance.
## Publication rules
- Never infer `published`, `accepted`, or `under review` from a manuscript file.
- Preserve the user's author position.
- Institutional funding is not a personal award.
- Follow `config.md` provenance flags.
## Completion
Report:
- files created or updated;
- newly verified facts;
- unresolved contradictions or missing metrics;
- suggested next command: use `setup-build-kb` to promote reviewed evidence into the canonical registry, experience files, bundles, and support files.
Do not update canonical claims from an unreviewed extraction.