# Changelog of CA Public Works Apprenticeship Programs (DIR / DAS) (`overlookdata/ca-dir-apprenticeship-programs`) Actor

- **URL**: https://apify.com/overlookdata/ca-dir-apprenticeship-programs/changelog.md
- **Full Actor documentation**: https://apify.com/overlookdata/ca-dir-apprenticeship-programs.md

## Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

### \[0.8.0] - 2026-08-26

#### Removed

- Internal Upwork pitch documents (docs/upwork-proposal-draft.md and
  docs/upwork-submission.md). The pitch closed without award; the actor
  continues as a standalone store product.

### \[0.7.0] - 2026-08-26

#### Changed

- Street address lines and program names now drop DIR's stray trailing
  separators ("426 Alabama St.," parses as "426 Alabama St.").
- `program_key` normalization now ignores punctuation (periods, commas,
  semicolons, colons, apostrophes, quotes) in addition to case and
  whitespace, so DIR formatting quirks such as "J.A.T.C." vs "JATC" or a
  trailing comma no longer produce different keys. Keys computed by earlier
  releases do not match 0.7.0 keys; recompute baselines after upgrading.
- README documents the change-tracking recipe: schedule the actor and diff
  runs on `program_key` downstream.

### \[0.6.0] - 2026-08-19

#### Changed

- Counties and trades inputs are now multi-select pick lists in the Apify
  Console: users choose "Los Angeles" or "Plumbing & Pipefitting" by name and
  never see the underlying DIR codes. Option lists generated from the real
  DIR form data (58 counties, 28 crafts; shared codes shown combined, e.g.
  "Brick Tender / Laborers / Plaster Tender"). Stored values are unchanged
  DIR codes, so the scraper, CLI, API runs, and empty-means-all semantics
  are untouched. If DIR ever adds a county or craft, the runtime still picks
  it up on empty-list sweeps; the dropdown lists need a schema refresh to
  offer it explicitly.
- README input docs reframed to match: Console users pick by name, the code
  tables and example JSON are labeled as API/JSON reference.

### \[0.5.0] - 2026-08-18

#### Added

- Actor output schema (`.actor/output_schema.json`) linking the run output
  view to the default dataset items, completing the Publication tab's Output
  schema requirement.
- Store icon assets (Golden Seal) at `docs/assets/`.

### \[0.4.0] - 2026-08-18

#### Fixed

- Platform runs crashed at startup before reaching actor code: the loose
  `apify>=2.0,<3.0` pin resolved an old crawlee alongside current pydantic,
  which fails to import (`TypeError: cannot specify both default and
  default_factory`). `apify` is now pinned to 4.0.1, which carries a coherent
  crawlee 1.9 / pydantic 2.13 dependency set. Resolved set installed and
  import-verified. No actor code changes were needed; the SDK surface this
  project uses is unchanged in SDK v3/v4.

### \[0.3.0] - 2026-08-18

#### Added

- Dataset schema (`.actor/dataset_schema.json`) with typed fields and a
  Programs table view for the Apify Output tab and store sample output.
- Input schema prefill (`BUTTEC` / `58`) so a first store run succeeds in
  seconds; empty lists still mean a full statewide sweep.
- README "Example runs" section with copy-paste inputs.

#### Changed

- `actor.json`: explicit README and changelog wiring, dataset storage schema
  reference, memory bounds (256 min / 512 default MB) to keep per-run
  platform cost low, actor version synced to 0.3.
- User-Agent no longer embeds a version number.

### \[0.2.0] - 2026-08-18

#### Changed

- Public-facing polish for the Apify Store listing: README rewritten as the
  store page (DAS 140/142 compliance use case up front, county and craft code
  reference tables, data quality section), actor title and description
  updated, input schema titles and descriptions made user-friendly, and the
  User-Agent string updated to identify the published actor.
- Developer documentation (local CLI usage, tests, site behavior notes,
  deploy) moved from README to `docs/DEVELOPMENT.md`.

### \[0.1.0] - 2026-08-18

#### Added

- Start-page parser enumerating 58 county options and trade options collapsed
  by 2-digit code with multi-label handling (code 34 maps to Brick Tender,
  Laborers, Plaster Tender).
- Results-page parser: program blocks (name, address, contact person/title,
  phone, email), stated sponsor count verification with `parse_mismatch`
  flag, `source_data_date` capture, and graceful handling of zero-result
  pages.
- "Object moved" redirect stub detection: one retry, then a persistent
  redirect is recorded as a legitimate zero-sponsor result (verified against
  the live site 2026-08-18), never as a fetch error.
- Async crawler (httpx) with semaphore-bounded concurrency, per-request
  politeness delay, 3 attempts with exponential backoff on 5xx/timeouts, and
  custom User-Agent.
- Program deduplication across (county, trade) queries via SHA-1
  `program_key`, with `variants` capture for differing contact blocks.
- Two output modes: `programs` (default) and `combinations`.
- Apify actor wrapper (`src/main.py`), local CLI runner (`src/cli.py`), and
  offline pytest suite against saved fixtures.
