# Changelog of Greenhouse, Lever, Ashby, Workable, Workday & Recruitee (`debonaire_sedan/job-tracker-career-boards`) Actor

- **URL**: https://apify.com/debonaire_sedan/job-tracker-career-boards/changelog.md
- **Full Actor documentation**: https://apify.com/debonaire_sedan/job-tracker-career-boards.md

## Changelog

All notable changes to this Actor are documented here. This file is referenced by
`.actor/actor.json` via the `changelog` key.

### 0.2.3 — fix: partial Workday boards reported as failed with zero rows

#### Fixed

- A Workday board that listed postings but could not satisfy the facet-sum
  completeness check (for example Illumina: 165 unique postings vs a facet sum
  of 494) was reported as `boards_failed: 1` with `error: null` and emitted
  zero rows, even though every listing request succeeded. `ok` conflated
  "board scraped successfully" with "board is 100% complete".
- `BoardResult` now carries `complete` and `incomplete_reason` separately
  from `ok`. The Workday adapter reports `ok=true` whenever the listing
  succeeded (including a healthy board with zero open roles), sets
  `complete` from the facet-sum arithmetic, and fills `incomplete_reason`
  with the concrete cause (facet-sum mismatch, failed slice, or posting cap).
  A board with no postings because of an actual failure still reports
  `ok=false` with the reason as its error.
- The run summary status (`complete`/`incomplete`) is now derived from the
  `complete` flag, so a partial board keeps its rows, counts under
  `boards_found`, and records why it is incomplete.

#### Verified

- Local run against the Illumina Workday tenant with `includeWorkdayDetail`:
  `boards_found 1, boards_failed 0, jobs_found 165, detail_fetched 165,
  detail_errors 0`; emitted rows carry exact `posted_at`, `employment_type`,
  descriptions and `job_url`. The same input previously reported the board as
  failed with zero rows.
- All 81 unit tests pass; no test pinned the old conflated behavior.

### 0.2.2 — Store-facing copy and version alignment

#### Changed

- Updated the Actor title and Store-facing schema titles to list all six supported boards: Greenhouse, Lever, Ashby, Workable, Workday and Recruitee. The previous published title still named only five boards even though the description, README, input, output, dataset and discovery code all expected Recruitee. This removes the mismatch between the Store title and the rest of the listing.

#### Metadata

- Bumped `.actor/actor.json` version to `0.2` and kept `buildTag = latest`. The Apify platform only accepts `MAJOR.MINOR` version numbers (each push creates a new build such as `0.2.1` under that version), so this release is `0.2` on the platform; `0.2.1` and `0.2.2` are repository-level patch markers for the copy and repair passes. No behavior changes; this is a copy and metadata alignment release.

#### Not changed

- Behavior, adapters, normalization, input defaults, dataset schema and views are unchanged from 0.2.1.

### 0.2.1 — repair pass: offline runs, Workday detail URL, Recruitee, missing columns

#### Fixed

- Workday detail requests were sent to `/wday/cxs/wday/cxs/{tenant}/…` because the
  detail path (already absolute) had `/wday/cxs` prepended a second time. Every
  Workday detail call would have 404ed. The path is now used as built.
- `WorkdayAdapter.fetch_details` called the `_s` helper unqualified and crashed with
  `NameError` whenever a detail record had no `timeType`.
- `python -m src.main` could not run off the platform: the local Actor stand-in was
  missing the async context manager protocol and its `get_input` was not awaitable,
  so every offline run died on the first statement of `main`.
- The run summary was never written to the dataset because `board_jobs` was used
  before assignment, and `_stable_row_id` raised `IndexError` on a Workday
  placeholder row with no id, no link and empty `bulletFields`.
- `company_name` and `posted_at_source` were dropped during normalization, so the two
  documented columns never reached the dataset. Both are now emitted by the
  normalizer, and a Workday row with no `timeType` reports `employment_type` null
  rather than an empty string.
- `RecruiteeAdapter` was missing from `src/platforms/additional.py` even though the
  README, `actor.json`, `input_schema.json`, `discovery.py`, `fields.py` and the test
  suite all expect it. It is restored and registered in `ADAPTERS` (six boards again).
- The `data` and `operations` category rules had double-escaped regex escapes
  (`\\s`, `\\b`), so the "data centre" exclusion never applied and such titles were
  filed under `data` instead of `engineering`.
- `tools/run_local.py` passed the generic `include_salary_details` keyword to the
  Workday adapter and crashed on any `--detail` run; Workday detail is now driven by
  `includeWorkdayDetail`, matching the Actor.

#### Added

- `tools/run_local.py` writes a run log and reports `INCOMP` separately from `FAIL`.
  It reads Actor input JSON, resolves the same workload, and writes `join_*.json`, one
  CSV per platform and `column_fill_*.csv` under `runs/reports/`.
- `examples/sample_actor_input.json`: the five-board input the local runner defaults to.
- `main_local()` accepts explicit input/output paths, forces its file log, and starts
  each run from a fresh dataset.

#### Documentation

- README Live results now holds measured runs with their commands, plus the current
  column-fill numbers, and lists what has not been measured yet.

### 0.2 — Workday details, plain-text HTML, and output/schema additions### Behavior changes

- Workday job detail is now fetched by default for every Workday posting when
  `includeWorkdayDetail` is true (the new default). Workday detail requests are
  no longer controlled by `includeDetail` or `detailMax`. Other boards still use
  `includeDetail` and `detailMax` as before.
- Workday detail requests use the internal `/wday/cxs/{tenant}/{site}{externalPath}`
  endpoint, with `externalPath` percent-encoded while preserving `/`, `%`,
  `-`, `_`, `.`, `~`, `!`, `$`, `&`, `'`, `(`, `)`, `*`, `+`, `,`, `;`, `=`,
  `:`, and `@`.
- Workday listings now split by facet when the offset-0 total is at or above the
  verified 2000-result cap, with a 3-deep split cap. Each slice stops at its
  offset-0 total, not at a later page's `total`. Duplicates are removed by
  `externalPath` within the board. A posting with no public link is still emitted
  with `job_url` null.
- Workday rows now include `posted_at` from the detail record when available,
  with `posted_at_source = "exact"`. The relative-label estimate is used only
  when detail is off or fails. `employment_type` is mapped from Workday
  `timeType`. `description_html` is the raw Workday `jobDescription`; `description_text`
  is derived with the new plain-text routine.
- Workday calls are subject to a robots.txt check before each request (Accept
  `text/plain, */*`; 404 = allowed; 200 = parsed; other = stop the board) and to a
  `/refreshFacet/` block. Workday requests are made with a non-browser User-Agent
  and a 0.5-second pause after each request, with retries on 429 and 5xx.
- A new plain-text-from-HTML routine replaces `<br>`, `</p>`, `</li>`,
  `</h1>`–`</h6>`, and `</div>` with newlines, replaces remaining tags with a
  single space, decodes entities per line, collapses whitespace, drops empty
  lines, and joins with newlines.
- `company_name` now uses the Greenhouse `company_name` response field when
  present, then the name typed in `companies`, then the slug.
- Run summary in the key-value store now records per-board status, incomplete
  reasons, rows emitted, rows without a link, rows filtered out, detail requested,
  detail fetched, detail errors, requests made and duration, plus run totals.

#### New inputs

- `includeWorkdayDetail` (boolean, default `true`): enable Workday detail
  fetching.

#### New output fields (additive; null when unknown)

- `description_text`, `description_html`
- `employment_type`
- `workplace_type`
- `posted_at_source`
- `company_name`

#### Schema and metadata changes

- `.actor/input_schema.json`: added `includeWorkdayDetail`; updated `includeDetail`
  and `detailMax` descriptions to exclude Workday.
- `.actor/dataset_schema.json`: declares all fields the code writes to dataset
  rows.
- `.actor/actor.json`: version bumped to `0.2`; added `changelog` key pointing
  at `CHANGELOG.md`.

#### Documentation

- README and CHANGELOG now document Workday detail behavior, the plain-text HTML
  routine, the new fields, the Workday terms/robots.txt disclosure, the free-plan
  50-row cap wording, and the derived-field accuracy caveat.

#### Not included in this version

- SmartRecruiters, Pinpoint, Personio, and Teamtailor adapters (deferred; not
  verified for this push).
- Watch mode (`onlyChanges`), derived-field accuracy measurement, and coverage
  reporting (deferred; not implemented for this push).
