# 24 — Adversarial Principal Review of the Four Decision Documents

Reviewed: `20-mapping.md`, `21-gaps.md`, `22-contracts.md`, `23-roadmap.md` against the spec
digests (`00..06`), the ERP evidence maps (`10..13`), and the original spec at
`files/manufacturing_spec/markdown`. Verdict up front: **the entity coverage is complete and the
GL/stock rails are respected, but the four documents do not agree on the module's identity
(naming/namespace), the roadmap silently reverses two mapping decisions, and several roadmap
phases have unscheduled prerequisites.** None of this is fatal; all of it will cause rework if
the docs are handed to builders as-is.

---

## 1. Spec entities silently dropped from the mapping

**Result: NONE dropped.** All 27 entities in `06-spec-integration.md` §6.2 are present in the
mapping's decision table (rows 1–27): Item, BOM_Header, BOM_Line, Routing_Header,
Routing_Operation, Work_Center, Tool (7 master data); MPS_Header, MPS_Line, Item_MRP_Settings,
MRP_Planned_Order, CRP_Load (5 planning); Production_Order_Header, Order_Component,
Order_Operation, Material_Issue_Header/Line, Confirmation_Header/Yield/Detail,
Goods_Receipt_Header/Line (10 execution); Standard_Cost, Cost_Center, Variance_Record (3
costing); Pegging, Delivery_Schedule (2 cross-cutting). The SFC layer (spec 05) is correctly
treated as a reuse of rows 15+18, matching spec 05 §5.3 ("does not introduce a new master table").

Near-misses worth recording (field/config-level, not entity-level):

- **`cost_driver` has no home.** Spec 04 §4.2 makes `cost_driver ∈ {LaborHours, MachineHours,
  DirectMaterialCost, UnitsProduced}` the overhead-rate denominator and the mapping declares a
  `CostDriver` enum in the skeleton, but NO table in the mapping carries a `cost_driver` column
  (work center? overhead pool? settings key?). The confirmation OH posting (`cost_driver ×
  overhead_rate`) cannot be computed without deciding where it lives.
- **`MRP_Planned_Order.source_demand_id`** (spec §6.2) is not explicitly listed among
  `mfg_mrp_planned_orders` columns in mapping row 11 — pegging depends on it.
- **Tally arithmetic is wrong:** mapping §2 claims "**20 NEW `mfg_*` tables**" but the document
  itself enumerates **24** distinct new tables (verified by grep: bom_substitutes, routing_headers,
  routing_operations, tools, mps_headers, mps_lines, item_mrp_settings, mrp_runs,
  mrp_planned_orders, mrp_exceptions, crp_loads, work_calendars, calendar_shifts, material_issues,
  material_issue_lines, confirmations, confirmation_yields, confirmation_details, goods_receipts,
  goods_receipt_lines, standard_costs, variance_records, peggings, delivery_schedules) — plus
  `mfg_piecework_log` appearing only in 22 (25th). Sizing inputs derived from "20" are understated.

---

## 2. Contract violations (house dependency rules / rail bypasses)

**Positive finding first:** no GL bypass anywhere — every posting in all four documents goes
through `Modules\Accounting\Actions\CreateJournalEntry`, and stock mutation is routed through
`ApproveIssue`/`ApproveReceipt` with the new `reserve()/release()` correctly contributed INTO
Inventory's `StockService`. The Sales-COGS "consuming module owns the GL" pattern is applied
correctly.

Violations and risks found:

- **V1 (real violation): HRM reads a Manufacturing table.** Contracts §1 HRM row: piece-rate
  payroll feed = "a `mfg_piecework_log` **HRM payroll reads**". A foreign module querying an
  `mfg_*` table is exactly the inbound dependency that contracts' own Rule 2 ("No module ever
  imports Manufacturing") forbids. Fix: Manufacturing-side listener pushes rows into an
  HRM-owned staging table via a new `Modules\HRM\Actions\RecordPieceworkEntry`, mirroring how
  every other contract in the same document is shaped.
- **V2 (violates the adopted decision): the entire contracts document is written for the wrong
  module.** 22 uses `Modules\Manufacturing\Events`, permission prefix `manufacturing` in
  `PermissionDependencyRegistry`, `SequenceService::generateNext(company,'manufacturing',…)`,
  `SettingsService::get('manufacturing.*')`, and tables `mfg_work_centers` / `mfg_item_settings`
  / `mfg_pegging`. The mapping (D-01, ratified in the roadmap) decided **extend
  `Modules/Production`**, prefix **`production.*`**, sequence module key **`'production'`**
  (already wired), settings keys **`production.*_account_id`** (mapping §2.4 row 25), and EXTEND
  `production_centers` (no `mfg_work_centers` table exists in the mapping). Implementing 22 as
  written re-creates the duplicate namespace/permission/sequence waste that mapping §1.4
  explicitly calls "pure waste plus a deprecation project".
- **V3 (bypass invitation):** Contracts §1 Inventory row lists
  `StockService::increaseStock/decreaseStock` among what Manufacturing "TAKES". Direct
  increase/decrease without an `InventoryIssue`/`InventoryReceipt` document breaks the document
  trail the mapping itself mandates ("never touch balances directly"). The contract should
  expose only `getIssueCost/getProductCost/getValuationMethod/reserve/release` plus the two
  Approve Actions.
- **V4 (soft):** "CRP reads `cmms_work_orders` directly (read-only query)" — a raw cross-module
  table read instead of an Action/Service. Forward direction, so tolerable, but inconsistent
  with the document's own "Nothing else (no … direct table writes/reads except via Actions)"
  posture; a `CMMS\GetDowntimeWindows` query service would be recipe-clean.
- **V5 (unverified reuse claim):** Mapping row 7 gives `mfg_tools.fixed_asset_id` an "FK →
  Accounting fixed asset for usage-based depreciation". **No evidence document (md/12 included)
  shows that Moon Accounting has any fixed-asset register at all.** Either the FK target does
  not exist (the claim is false and Accounting needs a fixed-asset build — a missed gap), or it
  was never audited. Roadmap Phase 2 books usage depreciation "into overhead" without any
  Accounting prerequisite for this.

---

## 3. Gap analysis quality (false gaps / missed gaps)

**False gaps: none found.** Every Direction-A claim was verified against the evidence maps:
A1/A2 (zero GL, zero stock movement — md/10 §5 grep evidence), A5 (`reserved_quantity` orphan —
md/11 §3), A6 (ProductType Product|Service only — md/11 §1), A8 (no calendar — md/10/13), A10
(no `cmms_asset_meters` — md/13 §4), A11 (PR creation controller-only — md/11 §5), A12
(ApprovalModule Sales|Purchases only — md/12 §7), A13 (PayrollService derives hourly at runtime —
md/13 §2), A14 (no ATP/CTP field on sales_orders — md/13 §1), A18 (no cost_centers.type —
md/12 §4). The "excluded candidates" table (UoM engine, cost centers, sequences, DataScope,
QMS) is also correct — these genuinely exist. One overstatement: the exclusions table says
QMS "NCR/CAPA with `production_order_id` columns waiting" — per md/13 only
`qms_inspection_plans`/`qms_inspections` carry `production_order_id`; `qms_non_conformances`
links only via `inspection_id`.

**Missed real gaps:**

1. **FOVV inputs do not exist.** Spec 04 expects "budget data per cost center and budgeted
   production volume" (expects-from-ERP #11); FOVV = (actual − **budgeted**) × std fixed OH/unit.
   Moon `cost_centers` has **no `budget_amount`/`manager_id`** (md/12 §4 column list) and no
   budgeting feature exists anywhere. The mapping hedges ("+ budget_amount if absent"); 21 has no
   gap entry; roadmap Phase 3 computes all 7 variances with no budget source scheduled. The
   7-variance engine is structurally incomplete without this.
2. **`cost_driver` storage** (see §1) — neither a gap entry nor a mapped column.
3. **Accounting fixed-asset register** (see V5) — required by the mapping's own tool-depreciation
   design, never audited, never listed as a gap.
4. **Inventory `ReceiptReferenceType`/issue reference enums:** md/11 shows
   `reference_type => ReceiptReferenceType::Purchase` is an enum; adding
   `'production_order'` requires extending those Inventory enums — absent from 21 and from
   mapping §4's "touches outside the module" table (only `MovementType` is listed).
5. **`production_centers` capacity/rate columns as a scheduled work item** — mapping row 6
   specifies ~14 new WC columns (daily_capacity, multiplier, efficiency, utilization,
   setup/labor/machine rates, labor_calc, calendar_id, bottleneck_flag…), but no gap entry and
   no roadmap phase ever schedules this EXTEND (see §4.1).

Direction-B critique is strong (subcontracting B3, reversals B7, return-to-stock B14 are real
spec blind spots correctly caught), and the "ATP/CTP is not a spec gap" exclusion is correct.

---

## 4. Roadmap: hidden prerequisites & sizing

1. **The work-center extension is scheduled nowhere.** Phase 2 posts labor/machine/OH from WC
   rates and computes effective capacity = daily × multiplier × eff% × util%, but no phase's
   table scope includes extending `production_centers` with those columns (Phase 1 adds only
   `cost_center_id`). Phase 4 CRP needs `calendar_id` + capacity fields too. Hidden prerequisite
   spanning Phases 2 and 4.
2. **Per-item `costing_method` ordering knot.** Phase 3 (costing) needs it; the mapping houses it
   on `mfg_item_mrp_settings`, which the roadmap builds in **Phase 4**. The roadmap "solves" this
   by migrating `products.cost_method` to an enum in Phase 3 — directly contradicting mapping
   row 1 ("do NOT bloat `products`") and row 23. Pick one home and one phase.
3. **Phase 3 FOVV has no budget source** (see §3.1) — either descope FOVV in v1 (declare 6
   variances) or schedule a budget input.
4. **Phase 2 tool depreciation** depends on the unverified Accounting fixed-asset capability and
   the "usage-driven depreciation variant [that] is net-new in Accounting" (mapping row 7) — not
   in Phase 2's prerequisite list.
5. **Phase 1 reopens a settled decision:** "OR use Inventory documents directly with reference
   linkage (**recommended**; fewer tables)" — the mapping decisively created
   `mfg_material_issues`/`mfg_goods_receipts` precisely because Inventory documents lack
   `issue_type`/`issue_level`/`operation_no`/grade fields. If the roadmap's recommendation is
   followed, those spec fields have nowhere to live; if not, the sentence is noise. Also Phase 1
   `substitute_items` JSON contradicts mapping's `mfg_bom_substitutes` table.
6. **The "addendum-first" mandate has no owner.** 21's headline: every spec-side gap (B1–B25)
   "must be resolved as a written addendum BEFORE the build order starts, or it resurfaces as
   rework". The roadmap allocates zero time/phase to authoring ~25 addenda; D-01..D-14 cover
   only some of them (B5, B6, B11, B19, B20 etc. have no decision row).
7. **Sizing legends conflict:** 21 defines S ≤ 3 dev-days / M ≤ 3 dev-weeks / L > 3 dev-weeks;
   23 defines S ≈ ≤1 wk / M 2–4 wks / L 4–8 wks. A board member mapping gap-sizes onto
   phase-sizes will mis-budget. Phase 1 itself (BOM versioning + multi-level + full state-machine
   rename rippling into Angular atomically + two posting rails + reservations + FE dialogs) is at
   the aggressive end of "L" for a single senior dev; the bottom-line "factory genuinely
   operational at END OF PHASE 1" assumes none of the D-decisions stall.
8. **Quality-status orphan window:** GR lines carry `quality_status` resolved from QMS
   (mapping row 22), but QMS hooks arrive only in Phase 6 — receipts shipped Phases 1–5 need a
   defined default behaviour (auto-Released?) that no document states.

---

## 5. Contradictions between the four documents

| # | Topic | 20-mapping | 21-gaps | 22-contracts | 23-roadmap |
|---|---|---|---|---|---|
| C1 | Module identity / namespace | Extend `Modules/Production`, permission prefix `production.*`, sequence key `'production'` | (follows 20) | **`Modules\Manufacturing`**, prefix `manufacturing`, sequence `'manufacturing'` | Extend Production (D-01) |
| C2 | Settings keys | `production.*_account_id` (§2.4 row 25) | `manufacturing.*_account_id` (A7) | `manufacturing.*` (§3 #13, §4) | `manufacturing.*` (Phases 0/1/2) |
| C3 | Item-settings table | `mfg_item_mrp_settings` | `mfg_item_settings` (A6) | `mfg_item_settings` | `mfg_item_mrp_settings` |
| C4 | Pegging / calendar tables | `mfg_peggings`, `mfg_work_calendars`+`mfg_calendar_shifts` | `mfg_calendars` (A8) | `mfg_pegging` | `mfg_pegging`, `mfg_calendars`+`mfg_calendar_shifts` |
| C5 | Work-center store | EXTEND `production_centers` | — | **`mfg_work_centers`** (nonexistent table, §1 CMMS + §5) | EXTEND `production_centers` |
| C6 | Sales promise column | `sales_orders.promised_date` | `promised_date` (A14) | `promised_delivery_date` | `production_promised_date` (D-12) |
| C7 | Event names | `ConfirmationPosted`, `OperationCompleted`, `ProductionOrderClosed`, `MaterialIssued` | — | `OperationConfirmed`, `ProductionOrderSettled`, `MaterialIssued` | `MaterialsIssued`, `FinishedGoodsReceived`, `ProductionOrderClosed`, `OperationCompleted` |
| C8 | BOM substitutes | `mfg_bom_substitutes` child table | — | — | `substitute_items` JSON v1 |
| C9 | Issue/GR documents | NEW `mfg_*` doc tables (definitive) | — | (follows 20) | "OR use Inventory documents directly (recommended)" |
| C10 | Consignment model | `warehouses.is_consignment` flag (rows 17) | either/or (A15) | "consignment bucket" (unspecified) | `ownership` dimension on balances/movements (Phase 6) |
| C11 | Per-item costing-method home | `mfg_item_mrp_settings`; "do NOT bloat products" | extension table (A6) | `mfg_item_settings` | `products.costing_method` enum migration (Phase 3) |
| C12 | Labor-rate resolution | WC rate v1, HRM deferred (§4 XS) | WC rate recommended (A13) | NET-NEW `HRM\GetLaborRate` Action in the confirmation path | WC rate v1 (D-06) but HRM columns added as Phase 2 prerequisite |
| C13 | Settlement action | `CloseProductionOrder` computes variances | `SettleProductionOrder` (A1) | `SettleProductionOrder` | `CloseProductionOrder` (Phase 1, no variances) |
| C14 | NEW-table tally | "20 NEW" claimed, 24 enumerated | — | +`mfg_piecework_log` (25) | — |

C1/C2 are the dangerous ones: registry contributor name, sequence module key, and settings-key
namespace are **runtime identifiers** — if Phase 0 seeds `production.*` keys while the
confirmation Action (built from 22) resolves `manufacturing.wip_account_id`, postings fail at
the first material issue.

---

## 6. What is sound (credit where due)

- Entity coverage is genuinely complete (27/27) with defensible verdicts; the
  extension-table pattern for Item and the Accounting-owns-cost-centers ruling resolve the
  spec's two ownership ambiguities correctly.
- Evidence discipline is high: every Direction-A gap traces to a file:line in md/10–13, and no
  claimed gap turned out to exist in the ERP.
- The three roadmap inversions (integrations woven in, execution before planning, MPS-lite) are
  well-argued and consistent with the spec's own contradiction (real-time GL rule vs
  integrations-last build order).
- The GL/stock rails are never bypassed; the JE family table (22 §4) matches md/12 §9 exactly.

## 7. Required fixes before board sign-off

1. Rewrite 22 against the D-01 decision: `Modules\Production`, `production.*` permissions,
   `'production'` sequence key, ONE settings namespace (recommend `production.*` to match the
   existing permission/sequence space), `production_centers` not `mfg_work_centers`. Or, if the
   board prefers the `manufacturing` namespace, change D-01's naming addendum — but pick one.
2. Re-route the piecework payroll feed through an HRM-owned Action/table (V1) and drop
   `increaseStock/decreaseStock` from the Manufacturing-facing Inventory contract (V3).
3. Audit Accounting for a fixed-asset register; add a gap entry (and Phase 2 prerequisite) or
   drop `fixed_asset_id` from `mfg_tools` v1.
4. Add gap entries + phase scheduling for: FOVV budget inputs, `cost_driver` storage,
   `production_centers` capacity/rate columns, Inventory reference-type enums.
5. Resolve C6–C11 into single named decisions (add D-15+ rows); fix the "20 NEW" tally; align
   the two sizing legends; assign an owner + timebox for the B1–B25 addenda demanded by 21.
