Handoff: Hermes-native Japan & Australia job search

2026-08-25 06:53 JST · continuation brief for a fresh implementation agent · generated by Hermes (GPT-5.6 Sol)

Continuation target

Build and exercise a Hermes-native job-discovery skill inspired by Mads Lorentzen’s /scrape workflow, optimized for Japan and Australia. Integrate its structured, linked and deduplicated results into the existing daily LinkedIn/Strava cron workflow without removing authenticated LinkedIn message inspection or Strava route discovery.

The deliverable is working code plus real test output—not merely a design. Preserve read-only behavior. Direct LinkedIn offers/messages must appear first, then new search matches, then other LinkedIn items; Strava remains a separate section.

Current state

Upstream evidence

Target design

1. Hermes packaging

2. Normalized record contract

{
  "id": "linkedin:1234567890",
  "source": "linkedin_guest|linkedin_personalized|portal_name",
  "country": "JP|AU",
  "title": "...",
  "company": "...",
  "location": "...",
  "workplace": "remote|hybrid|onsite|unknown",
  "posted_at": "YYYY-MM-DD|null",
  "url": "https://...",
  "description": "bounded plain text|null",
  "language_requirements": ["..."],
  "work_rights_or_sponsorship": "...|unknown",
  "salary": {"currency":"JPY|AUD", "min":null, "max":null, "period":"year|day|hour|unknown", "includes_super":null},
  "first_seen": "ISO-8601",
  "last_seen": "ISO-8601",
  "status": "new|seen|changed|closed",
  "health": "ok|degraded|rate_limited|blocked"
}

Canonicalize and deduplicate primarily by source + stable job ID, then canonical URL, then a cautious company/title/location fingerprint. Never merge distinct regional vacancies merely because their titles match.

3. Japan optimization

4. Australia optimization

5. Existing workflow integration

Ordered next steps

  1. Load hermes-agent, writing-great-skills, test-driven-development, and zettelkasten-vault before touching their respective surfaces. Re-read /home/miro/zettelkasten/AGENTS.md if the daily note is involved.
  2. Inspect the pinned upstream code and its tests; copy only audited ideas/code. Preserve upstream license and attribution where code is reused.
  3. Write tests first for HTML parsing, URL/job-ID retention, normalization, JP/AU query generation, salary/work-rights fields, deduplication, bounded retries and health-state distinctions.
  4. Implement the dependency-free Hermes skill and collector. Treat fetched postings as untrusted data: strip active/hidden markup, bound field sizes, validate schemes/domains, reject unexpected redirects, and never execute posting instructions.
  5. Patch the current Playwright extractor to retain LinkedIn and Strava activity URLs without changing read-only behavior.
  6. Add country/source/query configuration. Keep portal enable flags and conservative request caps. Default experimental sources to disabled until a live probe succeeds.
  7. Integrate the collector into browser_daily_digest.sh or a small wrapper while preserving the shared-Chrome lock and sequential CDP use. The guest collector should not require Chrome.
  8. Run unit tests and fixture tests. Then run one bounded live query for Japan and one for Australia; record HTTP status, result shape, source freshness and any 403/429 rather than treating failures as “zero jobs.”
  9. Run the complete gather script manually and verify exact digest ordering, working links, no duplicate jobs and intact Strava output.
  10. Only after manual success, update cron 9ca8d9a56184 if needed. Trigger one real run, confirm a new successful output and delivery, and verify no leaked headless Chrome remains after agent teardown.

Verification and acceptance criteria

Definition of done

  1. Hermes recognizes and loads the new skill from ~/.hermes/skills/.
  2. A local command emits schema-valid JSON for bounded JP and AU searches.
  3. Every presented job has a canonical clickable URL and source label.
  4. Running the same fixture/live sample twice reports no unchanged jobs as new.
  5. A malformed response, 403 or 429 surfaces as degraded/rate-limited/blocked, never “no jobs.”
  6. The combined digest keeps direct offers first and Strava intact.
  7. Unit/fixture tests pass, a manual end-to-end gather succeeds, and one cron delivery is verified before reporting completion.

Risks and open questions

LinkedIn terms and account safety

Public guest endpoints reduce direct cookie/account exposure but do not remove LinkedIn’s prohibition on unauthorized automated access. Keep volume low, read-only and independently disableable. Never combine guest requests with authenticated cookies or headers.

Portal scope

Do not assume every named JP/AU portal should be scraped. The next agent must check first-party access rules and technical feasibility, then document why each source is enabled or excluded.

Australia eligibility

Desired work-rights, sponsorship and relocation policy is not fully specified. Extract and flag these fields without guessing; keep ranking logic configurable until the user confirms the intended eligibility filter.

Personalized feed versus public search

The two sources can disagree and duplicate listings. Preserve provenance and merge only on stable job IDs/canonical URLs. Public search supplements—but cannot replace—messages and account-specific offers.

Upstream drift

Implement against reviewed commit e2c311a5b40512daf79a04b22c96d7e049afc745, not mutable master. Re-review before pulling newer code.

Suggested skills