{
  "schemaVersion": 1,
  "study": "cold-email-csv-import-error-study",
  "title": "CSV import preview: five validation fixes checked against 14 fixtures",
  "status": "limited-controlled-evidence-available; field-study-pending",
  "scope": "Collection template, not a dataset or completed field study. All null values are intentionally uncollected.",
  "unitOfObservation": "csv-fixture",
  "requiredInputs": "Synthetic files only, with fixed expectations before execution.",
  "controls": "Reset isolated workspace for import trials; preview-only observations do not establish insertion behavior.",
  "primaryAnalysis": "Record exact field differences and visible errors, not just an HTTP or job success status.",
  "registration": {
    "owner": null,
    "protocolVersion": "1",
    "registeredAt": null,
    "population": null,
    "eligibilityRules": null,
    "primaryOutcomeDefinition": null,
    "denominator": null,
    "observationWindow": null,
    "targetSampleAndJustification": null,
    "assignmentProcedureAndSeed": null,
    "exclusionRules": null,
    "safetyStopConditions": null,
    "missingDataPolicy": null,
    "retentionAndAccessOwner": null
  },
  "collectionRules": [
    "Assign pseudonymous IDs; do not store mailbox passwords, access tokens or unnecessary identifiers.",
    "Freeze the outcome and exclusions before collection; retain exclusions with reasons.",
    "Do not use repeated observations as independent people. Record clustering by person, company or mailbox.",
    "Do not treat a software test, simulated reply or researcher-written example as participant or campaign evidence.",
    "Record complaints and opt-outs and follow the actual suppression workflow.",
    "For interviews obtain permission before recording and respect withdrawal.",
    "Publish aggregate or redacted evidence only after review; keep original private records outside the public website."
  ],
  "fieldDictionary": {
    "fixture_id": {
      "required": true,
      "type": "string, number or boolean as specified by the registered protocol; null until collected",
      "meaning": "fixture id",
      "missingValue": null
    },
    "input_reference": {
      "required": true,
      "type": "string, number or boolean as specified by the registered protocol; null until collected",
      "meaning": "input reference",
      "missingValue": null
    },
    "parser_version": {
      "required": true,
      "type": "string, number or boolean as specified by the registered protocol; null until collected",
      "meaning": "parser version",
      "missingValue": null
    },
    "mapping": {
      "required": true,
      "type": "string, number or boolean as specified by the registered protocol; null until collected",
      "meaning": "mapping",
      "missingValue": null
    },
    "options": {
      "required": true,
      "type": "string, number or boolean as specified by the registered protocol; null until collected",
      "meaning": "options",
      "missingValue": null
    },
    "expected_outcome": {
      "required": true,
      "type": "string, number or boolean as specified by the registered protocol; null until collected",
      "meaning": "expected outcome",
      "missingValue": null
    },
    "observed_outcome": {
      "required": true,
      "type": "string, number or boolean as specified by the registered protocol; null until collected",
      "meaning": "observed outcome",
      "missingValue": null
    },
    "discrepancy": {
      "required": true,
      "type": "string, number or boolean as specified by the registered protocol; null until collected",
      "meaning": "discrepancy",
      "missingValue": null
    }
  },
  "blankRecord": {
    "observation_id": null,
    "fixture_id": null,
    "input_reference": null,
    "parser_version": null,
    "mapping": null,
    "options": null,
    "expected_outcome": null,
    "observed_outcome": null,
    "discrepancy": null,
    "excluded": false,
    "exclusion_reason": null,
    "protocol_deviation": null
  },
  "records": [],
  "analysisStatus": "not-run",
  "results": null,
  "interpretationLimits": "Do not use real contact lists as public fixtures. Re-running an import may change duplicate outcomes unless the workspace is reset. Publish results only after the evidence, method and limitations have been reviewed. This protocol provides no benchmark, expected lift or completed-study claim.",
  "procedure": [
    "Create fixtures for BOM, quoted commas, embedded newlines, duplicate headers, invalid addresses, empty fields and formula-like values.",
    "Run fixtures in an isolated workspace with sending disabled. Save mapping, options, parser version and resulting record counts.",
    "Before collection, write the primary outcome, observation window, exclusion rules and stopping conditions. Preserve excluded observations with a reason rather than quietly removing them.",
    "Pilot the procedure with fictional or owned test data, resolve ambiguous fields, and freeze a dated protocol version before the main run."
  ],
  "interviewPrompts": [],
  "controlledEvidence": {
    "url": "https://zintara.io/research-data/2026-09-16/controlled-results.json",
    "limits": "The baseline evidence remains unchanged. Post-fix evidence is a separate download. These selected fixtures are not a random sample of customer files, and 14 matches do not establish a production failure rate. Preview validates only the requested sample (five rows in the HTTP handler), not every later record or mailbox. Direct import processing remains a separate path.",
    "followupURL": "https://zintara.io/research-data/2026-09-16/csv-preview-fix-results.json"
  }
}
