{
  "_comment": "Programme pipeline. Generated from real state -- test runs, live API reads, ARM. Percentages are back-loaded: reaching Built is 40%, because built-but-unverified is where the defects hid.",
  "components": [
    {
      "blocked_by": null,
      "confidence": "measured",
      "dual_ownership_risk": true,
      "evidence": {
        "incumbent_off": false,
        "live_workload": "prices written to BigCommerce nightly",
        "real_data": "41k price writes in bc_live_writes",
        "tests": {
          "measured": "2026-08-25",
          "passed": 241,
          "suite": "ppd-bc-control-gaps"
        }
      },
      "fraction_through_stage": 1.0,
      "gate_failures": [
        "claims Shadowed with no stored diff",
        "claims Shadowed with no denominator -- 151 of 5,650 read as healthy once",
        "claims Shadowed with no demonstrated failure mode"
      ],
      "group": "Connector",
      "key": "connector.pricing",
      "name": "Pricing flow",
      "note": "Our engine owns price; DCAA's dcaa_UpdateEffectivePriceCost still exists. Live but not retired -- dual ownership.",
      "owner": "ours",
      "percent_complete": 100.0,
      "stage": 6,
      "stage_claim_supported": false,
      "stage_name": "Live"
    },
    {
      "blocked_by": null,
      "confidence": "measured",
      "dual_ownership_risk": false,
      "evidence": {
        "incumbent_off": false,
        "live_workload": "vendor connector writes the live storefront",
        "real_data": "bc_catalog 5,693 rows; 4,995 buyable",
        "tests": {
          "measured": "2026-08-25",
          "passed": 241,
          "suite": "ppd-bc-control-gaps"
        }
      },
      "fraction_through_stage": 1.0,
      "gate_failures": [],
      "group": "Connector",
      "key": "connector.products",
      "name": "Products flow",
      "note": "The VENDOR connector is live and owns this. We observe it; we never shadowed it, so no shadow evidence is owed.",
      "owner": "vendor",
      "percent_complete": 100.0,
      "stage": 6,
      "stage_claim_supported": true,
      "stage_name": "Live"
    },
    {
      "blocked_by": null,
      "confidence": "measured",
      "dual_ownership_risk": true,
      "evidence": {
        "incumbent_off": false,
        "live_workload": "nightly run writes live prices",
        "real_data": "5,207 rows in price_engine; 57 items propose >=20x cost",
        "tests": {
          "measured": "2026-08-25",
          "passed": 241,
          "suite": "ppd-bc-control-gaps"
        }
      },
      "fraction_through_stage": 1.0,
      "gate_failures": [
        "claims Shadowed with no stored diff",
        "claims Shadowed with no denominator -- 151 of 5,650 read as healthy once",
        "claims Shadowed with no demonstrated failure mode"
      ],
      "group": "Pricing",
      "key": "pricing.engine",
      "name": "Price engine and gates",
      "note": "Ceiling and corroboration gates repaired 2026-08-24; 34 of 57 breaches now refuse rather than report.",
      "owner": "ours",
      "percent_complete": 100.0,
      "stage": 6,
      "stage_claim_supported": false,
      "stage_name": "Live"
    },
    {
      "blocked_by": null,
      "confidence": "measured",
      "dual_ownership_risk": false,
      "evidence": {
        "live_workload": "serves the sales onboarding path to reps",
        "no_incumbent": true,
        "real_data": "browser-confirmed 2026-08-26: HTTP 200, 85 published courses with ProPharma-authored titles, resolves to 20.186.94.71",
        "tests": {
          "measured": "2026-08-26",
          "passed": 1,
          "suite": "live load + browser render"
        }
      },
      "fraction_through_stage": 1.0,
      "gate_failures": [],
      "group": "Training",
      "key": "training.portal",
      "name": "Training LMS (training.propharmausa.com)",
      "note": "Live and genuinely populated: 85 published ProPharma courses -- New Rep Sales Onboarding, Advanced Sales Mastery, Industry Deep-Dive Library, Advanced Objection Handling & Buyer Psychology, Remote Work Success. Frappe LMS, browser-confirmed. Unlike the ERP this holds real ProPharma content, which makes it the one place where clicking into a list rewards the click.",
      "owner": "ours",
      "percent_complete": 100.0,
      "stage": 6,
      "stage_claim_supported": true,
      "stage_name": "Live"
    },
    {
      "blocked_by": null,
      "confidence": "measured",
      "dual_ownership_risk": false,
      "evidence": {
        "real_data": "SalesOrder readable via ROAPI; ExternalRef is the key",
        "tests": {
          "measured": "2026-08-25",
          "passed": 241,
          "suite": "ppd-bc-control-gaps"
        }
      },
      "fraction_through_stage": 0.6,
      "gate_failures": [],
      "group": "Connector",
      "key": "connector.orders",
      "name": "Orders flow",
      "note": "Orders land as EO/EC SalesOrders. The gap is release, not intake: 18 On-Hold orders worth [figure withheld].",
      "owner": "ours",
      "percent_complete": 52.0,
      "stage": 4,
      "stage_claim_supported": true,
      "stage_name": "Verified"
    },
    {
      "blocked_by": "DCAA lot field is on no REST endpoint ROAPI can reach, so serial-tracked lines are undetermined against a recalled lot",
      "confidence": "judged",
      "dual_ownership_risk": false,
      "evidence": {
        "blocked_by": "DCAA lot field is on no REST endpoint ROAPI can reach, so serial-tracked lines are undetermined against a recalled lot",
        "real_data": "8 recall jobs enumerated in ARM with cron; 21 compliance.recall* tables readable; alert delivery confirmed by reading the mailbox",
        "tests": {
          "measured": "2026-08-25",
          "passed": 18,
          "suite": "ppd-recall-fix"
        }
      },
      "fraction_through_stage": 0.5,
      "gate_failures": [],
      "group": "Recalls",
      "key": "recalls.alerting",
      "name": "Recall alerting and matcher",
      "note": "Alert path proven end-to-end. The matcher read the wrong field and would never have fired on a real recall -- fixed, but lot capture is still blocked, so it cannot be fully verified.",
      "owner": "ours",
      "percent_complete": 50.0,
      "stage": 4,
      "stage_claim_supported": true,
      "stage_name": "Verified"
    },
    {
      "blocked_by": null,
      "confidence": "measured",
      "dual_ownership_risk": false,
      "evidence": {
        "real_data": "ERPNext DB read 2026-08-26: containers, workspaces, Workspace Link targets (zero dead), Social Login Key, last_login. Platform facts, not business data.",
        "tests": {
          "measured": "2026-08-25",
          "passed": 17,
          "suite": "ppd_unified suites (7+4+6)"
        }
      },
      "fraction_through_stage": 0.5,
      "gate_failures": [],
      "group": "Unified build",
      "key": "unified.platform",
      "name": "ERPNext platform and SSO",
      "note": "PLATFORM ONLY -- this says nothing about data. ERPNext v16.31.1 on frappe_docker, 10 containers up, Caddy TLS, and Office 365 SSO proven: a Microsoft identity is linked and mark@propharmausa.com signed in 2026-08-10 08:00:54. Structure is real too -- 296 custom fields, 13 ppd_unified doctypes, 6 curated workspaces whose shortcuts all resolve. But 17 workspaces are header-only blank pages and the instance holds no ProPharma data at all.",
      "owner": "ours",
      "percent_complete": 50.0,
      "stage": 4,
      "stage_claim_supported": true,
      "stage_name": "Verified"
    },
    {
      "blocked_by": null,
      "confidence": "measured",
      "dual_ownership_risk": false,
      "evidence": {
        "real_data": "27 entities probed as ROAPI, 54 paginated requests, 2026-08-24",
        "tests": {
          "measured": "2026-08-25",
          "passed": 0,
          "suite": "ppd_capture (none found)"
        }
      },
      "fraction_through_stage": 0.4,
      "gate_failures": [
        "claims Built with no passing tests (found 0)"
      ],
      "group": "Unified build",
      "key": "unified.ppd_capture",
      "name": "ppd_capture -- Acumatica capture",
      "note": "Capture proven against live Acumatica read-only. 17 of 27 contract entities readable; 9 unreadable and visible as UNKNOWN.",
      "owner": "ours",
      "percent_complete": 48.0,
      "stage": 4,
      "stage_claim_supported": false,
      "stage_name": "Verified"
    },
    {
      "blocked_by": null,
      "confidence": "measured",
      "dual_ownership_risk": false,
      "evidence": {
        "real_data": null,
        "tests": {
          "measured": "2026-08-25",
          "passed": 7,
          "suite": "ppd_edi.test_edi"
        }
      },
      "fraction_through_stage": 1.0,
      "gate_failures": [],
      "group": "Unified build",
      "key": "unified.ppd_edi",
      "name": "ppd_edi -- X12 850/856 and AS2",
      "note": "Real implementations, no stubs. Never run against a real trading partner, so Built and not Verified.",
      "owner": "ours",
      "percent_complete": 40.0,
      "stage": 3,
      "stage_claim_supported": true,
      "stage_name": "Built"
    },
    {
      "blocked_by": null,
      "confidence": "measured",
      "dual_ownership_risk": false,
      "evidence": {
        "real_data": "runs observed in ARM",
        "shadow": {
          "can_fail": false,
          "denominator": false,
          "diff_stored": true
        },
        "tests": {
          "measured": "2026-08-25",
          "passed": 92,
          "suite": "ppd-connector-status"
        }
      },
      "fraction_through_stage": 0.8,
      "gate_failures": [],
      "group": "Connector",
      "key": "connector.shadow",
      "name": "Connector shadow comparison",
      "note": "Runs every 6h but compared 151 SKUs of 5,650 and reported healthy. A shadow whose sample is frozen and whose check cannot fail is not a shadow.",
      "owner": "ours",
      "percent_complete": 36.0,
      "stage": 3,
      "stage_claim_supported": true,
      "stage_name": "Built"
    },
    {
      "blocked_by": null,
      "confidence": "measured",
      "dual_ownership_risk": false,
      "evidence": {
        "real_data": null,
        "tests": {
          "measured": "2026-08-25",
          "passed": 4,
          "suite": "ppd_csos.test_csos"
        }
      },
      "fraction_through_stage": 0.8,
      "gate_failures": [],
      "group": "Unified build",
      "key": "unified.ppd_csos",
      "name": "ppd_csos -- CSOS / DEA 222",
      "note": "Offline-guarded. Nothing connected to DEA.",
      "owner": "ours",
      "percent_complete": 36.0,
      "stage": 3,
      "stage_claim_supported": true,
      "stage_name": "Built"
    },
    {
      "blocked_by": null,
      "confidence": "measured",
      "dual_ownership_risk": false,
      "evidence": {
        "real_data": null,
        "tests": {
          "measured": "2026-08-25",
          "passed": 0,
          "suite": "ppd_core (none found)"
        }
      },
      "fraction_through_stage": 0.6,
      "gate_failures": [
        "claims Built with no passing tests (found 0)"
      ],
      "group": "Unified build",
      "key": "unified.ppd_core",
      "name": "ppd_core -- data model and DocTypes",
      "note": "15 DocType implementations against 176 doctype SPECS. The 176 is the number that misleads: it counts spec files, not implementations.",
      "owner": "ours",
      "percent_complete": 32.0,
      "stage": 3,
      "stage_claim_supported": false,
      "stage_name": "Built"
    },
    {
      "blocked_by": null,
      "confidence": "judged",
      "dual_ownership_risk": false,
      "evidence": {
        "real_data": null,
        "tests": {
          "measured": "2026-08-25",
          "passed": 0,
          "suite": "ppd_arcos (none found)"
        }
      },
      "fraction_through_stage": 0.5,
      "gate_failures": [
        "claims Built with no passing tests (found 0)"
      ],
      "group": "Unified build",
      "key": "unified.ppd_arcos",
      "name": "ppd_arcos -- ARCOS reporting",
      "note": "Format, collect and exporter exist; no tests found, so the fraction is a judgement rather than a measurement.",
      "owner": "ours",
      "percent_complete": 30.0,
      "stage": 3,
      "stage_claim_supported": false,
      "stage_name": "Built"
    },
    {
      "blocked_by": null,
      "confidence": "judged",
      "dual_ownership_risk": false,
      "evidence": {
        "real_data": null,
        "tests": {
          "measured": "2026-08-25",
          "passed": 7,
          "suite": "ppd_edi.test_edi"
        }
      },
      "fraction_through_stage": 0.4,
      "gate_failures": [],
      "group": "EDI",
      "key": "edi.supplier",
      "name": "Supplier EDI / AS2 transport",
      "note": "ppd_edi covers parsing and intake. Transport needs certificates and SFTP keys, which is a different problem from user SSO. The EdiFabric licence concern is closed -- we are not reusing .NET code.",
      "owner": "ours",
      "percent_complete": 28.0,
      "stage": 3,
      "stage_claim_supported": true,
      "stage_name": "Built"
    },
    {
      "blocked_by": null,
      "confidence": "measured",
      "dual_ownership_risk": false,
      "evidence": {
        "real_data": "78 GIs probed over OData as ROAPI, 2026-08-24",
        "tests": {
          "measured": "2026-08-25",
          "passed": 0,
          "suite": "usage layer (script, no suite)"
        }
      },
      "fraction_through_stage": 0.35,
      "gate_failures": [
        "claims Built with no passing tests (found 0)"
      ],
      "group": "Migration tooling",
      "key": "usage.layer",
      "name": "Usage layer -- what is used vs merely built",
      "note": "v1 measures Generic Inquiries. 43 of 78 are unauthorised to ROAPI, so 55% of the reporting surface is invisible. Table row counts, site-map presence and automation last-fired are all unreachable: every system entity 404s on contract REST.",
      "owner": "ours",
      "percent_complete": 27.0,
      "stage": 3,
      "stage_claim_supported": false,
      "stage_name": "Built"
    },
    {
      "blocked_by": null,
      "confidence": "measured",
      "dual_ownership_risk": false,
      "evidence": {
        "real_data": null,
        "tests": {
          "measured": "2026-08-25",
          "passed": 18,
          "suite": "ppd-recall-fix"
        }
      },
      "fraction_through_stage": 0.3,
      "gate_failures": [],
      "group": "Recalls",
      "key": "recalls.coverage",
      "name": "Supplier recall feed coverage",
      "note": "1 of ~71 suppliers notifies. The path works; the coverage does not.",
      "owner": "ours",
      "percent_complete": 26.0,
      "stage": 3,
      "stage_claim_supported": true,
      "stage_name": "Built"
    },
    {
      "blocked_by": "9 of 26 field mappings name Acumatica fields that do not exist; 4 of those 9 are CRM entities that are 403 to ROAPI, so their mappings cannot even be repaired until a role grant lands",
      "confidence": "measured",
      "dual_ownership_risk": false,
      "evidence": {
        "blocked_by": "9 of 26 field mappings name Acumatica fields that do not exist; 4 of those 9 are CRM entities that are 403 to ROAPI, so their mappings cannot even be repaired until a role grant lands",
        "real_data": "reconciliation 2026-08-25 against live Acumatica via ROAPI -- results.json. It is a real-data read that FAILED, which is why this sits at Built and not Verified.",
        "tests": {
          "measured": "2026-08-25",
          "passed": 6,
          "suite": "ppd_migration"
        }
      },
      "fraction_through_stage": 0.25,
      "gate_failures": [],
      "group": "Unified build",
      "key": "unified.ppd_migration",
      "name": "ppd_migration -- Acumatica to ERPNext migration",
      "note": "Migrated ZERO ProPharma rows. The 2026-08-25 reconciliation returned 26 entities: 0 MATCH, 9 SCHEMA_INVALID, 9 EMPTY_TARGET, 8 GAP. Every populated table in the ERP is ERPNext test fixtures -- Account 2,126 all named _Test* with no account number, Item 29 including Macbook Pro and Photocopier, Supplier 10 of 10 fixtures. Row counts looked like progress; reading the rows showed otherwise.",
      "owner": "ours",
      "percent_complete": 25.0,
      "stage": 3,
      "stage_claim_supported": true,
      "stage_name": "Built"
    },
    {
      "blocked_by": null,
      "confidence": "measured",
      "dual_ownership_risk": false,
      "evidence": {
        "real_data": "5 endpoints probed as ROAPI, 2026-08-24",
        "tests": {
          "measured": "2026-08-25",
          "passed": 20,
          "suite": "test_lot_serial"
        }
      },
      "fraction_through_stage": 1.0,
      "gate_failures": [],
      "group": "DSCSA",
      "key": "dscsa.lot_serial",
      "name": "Lot / serial model",
      "note": "Acumatica overloads one field, LotSerialNbr, on all five endpoints checked. Model keeps lot and serial distinct and refuses to guess.",
      "owner": "ours",
      "percent_complete": 20.0,
      "stage": 2,
      "stage_claim_supported": true,
      "stage_name": "Designed"
    },
    {
      "blocked_by": null,
      "confidence": "judged",
      "dual_ownership_risk": false,
      "evidence": {},
      "fraction_through_stage": 0.6,
      "gate_failures": [],
      "group": "Unified build",
      "key": "unified.order_portal",
      "name": "Order-request portal (BigCommerce replacement)",
      "note": "order_request and order_request_item DocTypes exist; entitlement and approval-workflow specs written. No payments by design.",
      "owner": "ours",
      "percent_complete": 15.2,
      "stage": 2,
      "stage_claim_supported": true,
      "stage_name": "Designed"
    },
    {
      "blocked_by": null,
      "confidence": "measured",
      "dual_ownership_risk": false,
      "evidence": {
        "real_data": "established from the sales history; recorded as a ruling"
      },
      "fraction_through_stage": 1.0,
      "gate_failures": [],
      "group": "Pricing",
      "key": "pricing.elasticity",
      "name": "Elasticity optimiser",
      "note": "Scoped and then correctly stopped: elasticity is UNIDENTIFIABLE here because cost fails the exclusion restriction. More data will not fix it. Margin dispersion and break-even replace it. Not a stall -- a closed question.",
      "owner": "ours",
      "percent_complete": 8.0,
      "stage": 1,
      "stage_claim_supported": true,
      "stage_name": "Scoped"
    },
    {
      "blocked_by": null,
      "confidence": "judged",
      "dual_ownership_risk": false,
      "evidence": {},
      "fraction_through_stage": 0.7,
      "gate_failures": [],
      "group": "DSCSA",
      "key": "dscsa.epcis",
      "name": "EPCIS 2.0 / ePedigree",
      "note": "Event templates specified in the local snapshot. epcis_event DocType exists. Nothing connected.",
      "owner": "ours",
      "percent_complete": 5.6,
      "stage": 1,
      "stage_claim_supported": true,
      "stage_name": "Scoped"
    },
    {
      "blocked_by": null,
      "confidence": "judged",
      "dual_ownership_risk": false,
      "evidence": {},
      "fraction_through_stage": 0.5,
      "gate_failures": [],
      "group": "Customer onboarding",
      "key": "onboarding.customer",
      "name": "Customer onboarding and licence verification",
      "note": "Licence-check state rules and facility M2M model specified. facility_license and licensed_facility DocTypes exist.",
      "owner": "ours",
      "percent_complete": 4.0,
      "stage": 1,
      "stage_claim_supported": true,
      "stage_name": "Scoped"
    },
    {
      "blocked_by": "Contact, Lead, Opportunity, BusinessAccount all HTTP 403 -- needs an Acumatica role grant",
      "confidence": "judged",
      "dual_ownership_risk": false,
      "evidence": {
        "blocked_by": "Contact, Lead, Opportunity, BusinessAccount all HTTP 403 -- needs an Acumatica role grant"
      },
      "fraction_through_stage": 0.4,
      "gate_failures": [],
      "group": "Connector",
      "key": "connector.customers",
      "name": "Customers flow",
      "note": "CRM entities are 403 to ROAPI, so the flow cannot even be measured.",
      "owner": "ours",
      "percent_complete": 3.2,
      "stage": 1,
      "stage_claim_supported": true,
      "stage_name": "Scoped"
    },
    {
      "blocked_by": null,
      "confidence": "judged",
      "dual_ownership_risk": false,
      "evidence": {},
      "fraction_through_stage": 0.3,
      "gate_failures": [],
      "group": "Unified build",
      "key": "unified.crm",
      "name": "CRM (HubSpot replacement)",
      "note": "Migration and dedup mapping specified. No component chosen -- Frappe ships a native CRM. An HSIntegration Acumatica endpoint exists and is unexplored.",
      "owner": "ours",
      "percent_complete": 2.4,
      "stage": 1,
      "stage_claim_supported": true,
      "stage_name": "Scoped"
    },
    {
      "blocked_by": null,
      "confidence": "measured",
      "dual_ownership_risk": false,
      "evidence": {
        "real_data": "main 215 entries vs code-tier1 395; identical backend/requirements.txt; 2026-08-24"
      },
      "fraction_through_stage": 0.0,
      "gate_failures": [],
      "group": "Unified build",
      "key": "unified.architecture",
      "name": "Architecture decision: Frappe vs bespoke FastAPI",
      "note": "TWO architectures in the repo, neither retired. main is a metadata-driven FastAPI/React ERP; unified-build/* adds the Frappe app. Only Frappe was ever stood up. Everything downstream depends on this and it is undecided.",
      "owner": "ours",
      "percent_complete": 0,
      "stage": 0,
      "stage_claim_supported": true,
      "stage_name": "Proposed"
    }
  ],
  "data_state": {
    "consequence": "So 'the unified build is live' is TRUE of the platform and FALSE of the data. No unified-build module may claim Verified on the strength of an ERP row count, and nothing in this programme is Shadowed at all.",
    "detail": "Every populated table is ERPNext test and demo fixtures: Account 2,126 all named _Test* and not one with an account number; Company 21 including _Test Company UAE VAT and Wind Power LLC; Item 29 including Macbook Pro and Photocopier; Supplier 10 of 10 fixtures; Customer 12 being eleven _Test plus ERPNext's demo customer Prestiga-Biz. Zero ProPharma customers, items or suppliers.",
    "headline": "The ERP is live as a platform and holds ZERO migrated ProPharma rows.",
    "how_it_was_missed": "Row counts were read and called real. Counting cannot distinguish data from fixtures because it never looks at a value. One `select name from tabItem` settled it.",
    "measured": "2026-08-26"
  },
  "evidence_required": {
    "Built": "a test count from an actual run, not a claim",
    "Designed": "a data model or interface committed, reviewable",
    "Live": "the component observably carrying real workload",
    "Retired": "the incumbent confirmed off",
    "Scoped": "decisions recorded in a document under version control",
    "Shadowed": "a stored diff, its denominator, and a demonstrated failure mode",
    "Verified": "a read of real production data, with a date and a source system"
  },
  "generated_at": "2026-08-26T13:29:06+00:00",
  "lifecycle": [
    {
      "blurb": "Named and wanted. Nothing started.",
      "cumulative_percent": 0,
      "earns_percent": 0,
      "index": 0,
      "name": "Proposed"
    },
    {
      "blurb": "Requirements understood, open questions closed, decisions recorded.",
      "cumulative_percent": 8,
      "earns_percent": 8,
      "index": 1,
      "name": "Scoped"
    },
    {
      "blurb": "Architecture and data model settled.",
      "cumulative_percent": 20,
      "earns_percent": 12,
      "index": 2,
      "name": "Designed"
    },
    {
      "blurb": "Code written, tests passing.",
      "cumulative_percent": 40,
      "earns_percent": 20,
      "index": 3,
      "name": "Built"
    },
    {
      "blurb": "Proven against real data, not just tests.",
      "cumulative_percent": 60,
      "earns_percent": 20,
      "index": 4,
      "name": "Verified"
    },
    {
      "blurb": "Running alongside the incumbent with a stored diff that can fail.",
      "cumulative_percent": 85,
      "earns_percent": 25,
      "index": 5,
      "name": "Shadowed"
    },
    {
      "blurb": "Cut over, carrying the real workload.",
      "cumulative_percent": 100,
      "earns_percent": 15,
      "index": 6,
      "name": "Live"
    },
    {
      "blurb": "The incumbent is switched off. Dual-ownership risk gone.",
      "cumulative_percent": 100,
      "earns_percent": 0,
      "index": 7,
      "name": "Retired"
    }
  ],
  "totals": {
    "blocked": 3,
    "by_stage": {
      "Built": 9,
      "Designed": 2,
      "Live": 4,
      "Proposed": 1,
      "Scoped": 5,
      "Verified": 4
    },
    "components": 25,
    "dual_ownership_risks": 2,
    "judged": 8,
    "mean_percent": 37.5,
    "measured": 17,
    "unsupported_stage_claims": 6
  }
}
