Skip to content

Phase 4 Review — Company & Transformation Monitor (Module 2)

Date: 2026-07-28 · Four-review standard applied to the second business module.

1. Engineering review

Executed and green: ruff clean, mypy strict clean (34 source files), 169 tests passed (was 145), real demo run: 4 sources → 27 quality rules → gate PASS → 11 marts; ingoshift detect-changes prints the five change events.

Findings: - Environment incident (self-inflicted, repaired, documented): one ruff --fix invocation ran from the wrong working directory and modified files far outside the repository, including preinstalled site-packages (3900 .py files touched; unused-import "fixes" broke re-export chains). Repaired from local evidence (openpyxl xml/functions.py re-exports, drawing/geometry.py LineProperties, pathspec's re2 fallback), then verified: openpyxl write/read roundtrip, full test suite, mkdocs build --strict. All later lint runs are scoped to the repo root. Detail in the build log — hiding this would violate the project's own working rules. - Entity resolution is union-find over deterministic keys with no fuzzy auto-merge path in the code at all — quality rule CMP-C5 asserts the rule set stays {exact_name_key, domain, manual_override}. - A real bug was caught by the module's own e2e test: the "longest observed name" display heuristic preferred the one-character-longer TYPO ("Batterietechnick") over the established spelling. Fixed to most-frequent-then-longest. The typo fixture earned its keep.

2. Data review

  • Historization works inside one deterministic run via two committed snapshot fixtures: first_seen/last_seen per canonical, content-hashed snapshots, change events with honest semantics (removed_from_source explicitly says "no real-world claim").
  • Merge auditability is a critical rule (CMP-C4): every source record's entity assignment must appear in company_merge_log; the manual override is logged as manual_override, never silent.
  • The queued pair (Beispiel Automotiv[e] Software) stays two entities plus an open company_review_queue row — conservative by construction (ADR-010).
  • Theme assignments carry the matched keyword; KI respects word boundaries (no match inside "Elektronik") — tested.
  • Cross-module linkage is real: mart_company_overview.postings_linked joins the synthetic jobs employers to canonical companies via the shared entity key (Demo IT Consulting → 10 postings).

3. Business review

  • US-06/07/08/09 now have data-layer answers: company profiles with themes and evidence trail, change events since the previous snapshot, transparent per-theme indicators (companies_total / companies_current / postings_linked), and a fully auditable merge history.
  • No composite "Transformation Index" exists (ADR-013): the brief permits one only with published formula, weights, and sensitivity analysis; the component indicators answer the decision questions without smuggling opinion into arithmetic. All 13 themes appear in the mart, including zero-count ones.
  • Dashboard/API remain environment-blocked (as in Phase 3) — tracked, not faked.

4. Honesty review

  • Every company is synthetic and says so: (SYNTHETIC) survives normalization into entity keys and canonical names; data_class travels into dim_company, snapshots, and both new marts. ✅
  • Removal semantics do not overclaim (source-level disappearance only). ✅
  • The environment incident is disclosed in the build log rather than buried. ✅
  • Checked: README/backlog wording states module 2's data layer is done on synthetic snapshots, with curated-real seed explicitly future work. ✅

Gate decision: Phase 4 passes for its in-environment scope. Carried: dashboard/API (environment-blocked), CI first run, C-03 source re-verification, DuckDB/Postgres restoration, curated-real company seed. Proceed to Phase 5 (Tender & Research Radar).