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_sourceexplicitly 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 asmanual_override, never silent. - The queued pair (Beispiel Automotiv[e] Software) stays two entities plus an
open
company_review_queuerow — conservative by construction (ADR-010). - Theme assignments carry the matched keyword;
KIrespects word boundaries (no match inside "Elektronik") — tested. - Cross-module linkage is real:
mart_company_overview.postings_linkedjoins 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).