# FriiDump Native Report Requirements for the Compatibility Database

**Document version:** 1.0
**Target database baseline:** FriiDump Compatibility Database v1.2.0
**Audience:** FriiDump developers and maintainers
**Purpose:** Define the machine-readable evidence FriiDump must produce for future compatibility testing.

---

## 1. Objective

FriiDump must produce a self-contained JSON report for each test execution so that the compatibility database can preserve the exact drive, firmware, media, result, provenance, and measured performance of that run.

The report is evidence only. It must not claim or directly change a public compatibility status. Public compatibility assessments remain curated separately and may only become report-backed after an administrator accepts and links the report to the exact firmware and platform scope.

The current interchange schema is:

```text
friidump-test-result.v1
```

The preferred filename suffix is:

```text
.friidump.json
```

---

## 2. Required output behavior

For database-compatible operation, FriiDump must be able to emit **one report per execution**. Native reporting requires exactly one primary dump output; combined raw and ISO output is rejected so `dump.output_path`, byte count, hashes, and the `dump_output` artifact remain unambiguous.

A report represents exactly:

- one FriiDump invocation;
- one physical or emulated drive;
- one live firmware identity;
- one disc or diagnostic media state;
- one final result.

FriiDump must not place multiple runs inside one JSON document. Batch submission is performed by selecting multiple individual report files.

Native report generation is enabled by default for normal dump invocations. Without a report option, FriiDump writes the report beside the final FriiDump log and derives the filename from that log filename by replacing the final `.log` suffix with `.friidump.json`.

The command-line overrides are:

```text
--report-json <file>       Override the complete report pathname.
--report-dir <directory>   Override only the destination directory.
--firmware-modified <note> Declare modified firmware and record the explanation.
```

`--report-json` and `--report-dir` may be combined. When combined, the filename from `--report-json` is retained while `--report-dir` replaces its directory. When `--firmware-modified` is omitted, stock firmware is assumed. FriiDump must not infer modified firmware from the selected drive profile.

The report should be written automatically when the run reaches a final state, including:

- successful complete dump;
- partial dump;
- seed-retrieval failure;
- dump failure after successful seed retrieval;
- no-media diagnostic;
- wrong-media diagnostic;
- media-transition diagnostic;
- user cancellation or another interrupted run when enough state exists to describe it honestly.

An interrupted run must not be reported as successful.

### Recommended write behavior

The final report should be written atomically:

1. Write the complete JSON to a temporary file.
2. Flush and close it.
3. Rename it to the final `.friidump.json` name.

This prevents an incomplete JSON file from appearing to be a finished report.

---

## 3. Root format identity

Every report must contain this exact identity:

```json
{
  "schema": "friidump-test-result.v1",
  "format": {
    "name": "FriiDump Interchange Format",
    "generation": 1,
    "serialization": "json"
  }
}
```

The JSON document must be UTF-8.

The schema is strict. Unknown root fields and unknown fields inside defined objects are rejected. Compatible future additions require coordinated schema work; FriiDump must not add arbitrary fields to generation 1 reports.

---

## 4. Required root objects

Every report must contain all of these root fields:

```text
schema
format
generated_utc
generator
run
drive
media
seed
dump
hashes
reference
profile
notes
artifacts
```

Fields that do not apply must still be present with an appropriate `null`, `false`, `not_attempted`, or `not_applicable` value.

---

## 5. Run identity and timestamps

### 5.1 Run UUID

`run.run_id` must be a UUID generated once for the execution.

Requirements:

- Generate it at or before the start of the run.
- Preserve it throughout the run.
- A retry is a new run and receives a new UUID.
- Re-exporting the exact same stored run must preserve the original UUID.
- Never reuse a UUID for different report content.

The database uses the run UUID as part of duplicate and conflict detection. Reusing a UUID with changed content creates a review conflict.

### 5.2 Time fields

All timestamps must be ISO-8601 UTC timestamps, preferably with a `Z` suffix.

```text
generated_utc
run.started_utc
run.completed_utc
```

For a native FriiDump run:

- `run.started_utc` should record the authoritative execution start time.
- `run.completed_utc` should record the authoritative final-state time.
- `generated_utc` records when the JSON report was generated.
- `completed_utc` must not precede `started_utc`.
- If a timestamp genuinely cannot be known, use `null`; do not invent one.

A reconstructed historical report may have unknown run timestamps, but native FriiDump should normally provide both.

---

## 6. Generator identity

FriiDump must record the exact executable identity:

```json
"generator": {
  "name": "FriiDump",
  "version": "0.5.3.15-pf1",
  "build_commit": "40-character-git-commit-or-null"
}
```

Requirements:

- `name` must be exactly `FriiDump`.
- `version` must identify the running build.
- `build_commit` should contain the full 40-character Git commit when available.
- Do not substitute a package date, branch name, or abbreviated commit for the full commit field.

---

## 7. Exact drive and firmware identity

The `drive` object must describe the drive actually used by the run:

```json
"drive": {
  "vendor": "HL-DT-ST",
  "model": "DVD-ROM GDR8163B",
  "firmware_revision": "0M26",
  "interface": "ATAPI",
  "device_path": "F:",
  "firmware_modified": false,
  "modification_note": null
}
```

Requirements:

- Populate vendor, model, and firmware revision from the live device inquiry.
- Preserve the exact meaningful firmware revision.
- Do not substitute a label revision, expected revision, or profile revision for the live inquiry result.
- `firmware_modified` must always be a Boolean.
- When `firmware_modified` is `true`, `modification_note` must explain the relevant modification.
- Stock and modified firmware are separate compatibility identities.
- `device_path` is descriptive and may be `null` when unavailable.

A report can only be linked to an assessment with the same exact firmware identity and platform.

---

## 8. Media identity

The `media.platform` value must be one of:

```text
gamecube
wii
xbox
dvd
unknown
```

The media object is:

```json
"media": {
  "platform": "gamecube",
  "title": "Sonic Mega Collection",
  "region": "USA",
  "disc_id": null
}
```

Requirements:

- Use the actual tested platform.
- For unforced GameCube/Wii runs, classify the platform from the unscrambled
  sector-0 platform magic after seed retrieval: Wii magic `0x5d1c9ea3` at
  byte `0x18`, otherwise GameCube magic `0xc2339f3d` at byte `0x1c`.
- The sector-0 platform magic overrides a conflicting legacy capacity-probe
  result. Explicit `-T` and `-S` selections remain authoritative.
- Include the disc title when media is present and it can be determined.
- Include region and disc ID when known.
- Use `null` rather than guessed values.
- Diagnostic no-media runs should normally use `platform: "unknown"` and null media identity fields.

The database maps GameCube and Wii reports into the shared `gcwii` assessment platform while retaining the original report platform.

---

## 9. Test type and final result

### 9.1 Allowed test types

```text
full_dump
seed_only
partial_dump
diagnostic_no_media
diagnostic_wrong_media
media_transition
other
```

### 9.2 Allowed run results

```text
pass
partial
fail
not_applicable
```

### 9.3 Required mappings

| Situation | `run.test_type` | `run.result` |
|---|---|---|
| Complete successful dump | `full_dump` | `pass` |
| Run stopped after producing valid partial progress | `partial_dump` | `partial` |
| Seed-only test succeeds | `seed_only` | `pass` |
| Seed retrieval fails | `seed_only` | `fail` |
| No disc inserted | `diagnostic_no_media` | `not_applicable` |
| Wrong media inserted | `diagnostic_wrong_media` | `not_applicable` |
| Media transition test | `media_transition` | normally `not_applicable` |
| Unclassified test | `other` | honest final result |

A no-media or wrong-media diagnostic is not evidence that the drive is incompatible.

---

## 10. Seed-stage reporting

The `seed` object must always be present:

```json
"seed": {
  "attempted": true,
  "result": "pass",
  "duration_seconds": 6.0
}
```

Allowed seed results:

```text
pass
partial
fail
not_attempted
not_applicable
```

Requirements:

- `attempted` must reflect whether FriiDump actually attempted seed retrieval.
- `duration_seconds` must measure the seed stage only.
- Use a non-negative numeric duration when measured.
- Use `null` when no defensible measurement exists.
- Do not include seed time in `dump.duration_seconds`.

---

## 11. Dump-stage reporting

The `dump` object must always be present:

```json
"dump": {
  "attempted": true,
  "result": "pass",
  "sector_count": 712880,
  "byte_count": 1459978240,
  "duration_seconds": 7241.31,
  "failure_stage": null,
  "failure_sector": null,
  "output_path": "sonic.iso"
}
```

Allowed dump results:

```text
pass
partial
fail
not_attempted
not_applicable
```

### Complete successful dump

A successful dump must include:

- `sector_count`;
- `byte_count`;
- `duration_seconds` when measured;
- at least one output hash for a warning-free report;
- `failure_stage: null`;
- `failure_sector: null`.

### Partial dump

A partial dump should include:

- the number of sectors actually completed;
- the number of output or payload bytes actually completed;
- the measured elapsed dump time, when defensible;
- the stage where the run stopped;
- the failure or stopping sector, when known;
- the partial output path, when an output exists.

Do not report the planned final size as `byte_count` for a partial run.

### Failed dump

A failed dump should identify `failure_stage`. Examples include:

```text
seed_retrieval
raw_sector_read
output_write
finalization
reference_verification
user_cancelled
```

Use the most specific stable machine-readable value available.

---

## 12. Throughput and measurement scope

The database calculates measured throughput from the report:

```text
MiB/hour = byte_count × 3600 ÷ duration_seconds ÷ 1,048,576
```

FriiDump must not provide an estimated or instantaneous progress rate as the completed-run average.

For a meaningful calculation:

- `dump.byte_count` must describe the bytes represented by the measurement.
- `dump.duration_seconds` must describe the time spent producing those same bytes.
- The duration should exclude seed retrieval.
- Post-dump hashing and reference matching should not be included unless the measurement is explicitly defined to include them.
- A zero or unknown duration must be represented as `null`, not as a fabricated small value.

### 12.1 Required measurement scopes

The compatibility database recognizes:

```text
full_optical_payload
assembled_output
partial_progress
unknown
```

The generation-1 JSON schema has no dedicated measurement-scope property. FriiDump must therefore place the scope in a controlled note using this exact form:

```text
Measurement scope: full_optical_payload.
```

Other valid forms are:

```text
Measurement scope: assembled_output.
Measurement scope: partial_progress.
Measurement scope: unknown.
```

The importer reads the `measurement scope:` token case-insensitively.

### 12.2 Scope definitions

#### `full_optical_payload`

Use when `byte_count` and `duration_seconds` represent a complete optical payload read.

Examples:

- complete GameCube optical dump;
- complete Wii optical dump;
- complete ordinary DVD optical read.

#### `assembled_output`

Use when the timed operation creates a final image by combining optical reads with copied, generated, synthetic, padded, or finalized regions.

This is required for the current Original Xbox assembled-output workflow when the reported bytes and time describe the final assembled image rather than only physical optical reads.

Assembled-output throughput must not be presented as directly comparable to optical-only throughput.

#### `partial_progress`

Use when the run did not complete and the byte/time pair describes only actual progress before failure or cancellation.

A partial-progress rate is not a completed-dump average.

#### `unknown`

Use when no defensible measurement classification exists.

### 12.3 Native automatic inference

The database can infer `full_optical_payload` for a native successful GameCube, Wii, or DVD full dump, but FriiDump should still emit an explicit scope note. Explicit scope is mandatory for Xbox and any nonstandard output workflow.

---

## 13. Output hashes

The `hashes` object must always contain all four keys:

```json
"hashes": {
  "crc32": "01b52739",
  "md5": "85a525df1481d0ad67d8761f832dca12",
  "sha1": null,
  "sha256": null
}
```

Requirements:

- Use lowercase or uppercase hexadecimal; the importer normalizes to lowercase.
- Hashes must describe the exact output represented by `dump.output_path`.
- A successful complete dump should provide at least one hash.
- Prefer recording every hash FriiDump already calculates.
- Do not hash a different file, temporary file, or logical payload while describing the final output file.
- Use `null` when a hash was not calculated.

Required lengths:

```text
CRC32   8 hexadecimal characters
MD5    32 hexadecimal characters
SHA-1  40 hexadecimal characters
SHA-256 64 hexadecimal characters
```

---

## 14. Reference verification

The `reference` object describes software-side comparison results:

```json
"reference": {
  "provider": "redump",
  "result": "match",
  "reference_id": null
}
```

Allowed results:

```text
match
mismatch
not_checked
not_applicable
```

Requirements:

- A `match` should identify the reference provider.
- Use `not_checked` when no comparison was performed.
- Use `not_applicable` for diagnostic runs where reference comparison has no meaning.
- Reference match or mismatch is report evidence, not a direct hardware compatibility status.
- FriiDump must not convert a Redump result into a published compatibility assessment.

---

## 15. FriiDump profile identity

The `profile` object must always be present:

```json
"profile": {
  "support_tier": "known_supported_profile_hardening",
  "cdb_offset": "0x5E0",
  "gate_address": "0x90024FF7"
}
```

Requirements:

- Record the support tier actually selected by FriiDump.
- Record the selected CDB offset and firmware gate address when applicable.
- Hexadecimal addresses must begin with `0x`.
- Use `null` when the value does not apply or is not known.
- Do not report analyzer candidates as confirmed runtime values unless FriiDump actually selected them.

---

## 16. Notes and evidence provenance

`notes` is an array of concise factual strings.

For a native FriiDump-generated report:

- Do not add `Evidence origin: reconstructed...`.
- Do not add a converter identity.
- Do not claim the report was reconstructed or imported.
- The database classifies a report as `native_report` by default.
- Include the controlled measurement-scope note.
- Include concise information that cannot be represented elsewhere.
- Do not place a compatibility status recommendation in the notes.
- Do not copy large portions of the text log into the notes.

Example:

```json
"notes": [
  "Measurement scope: full_optical_payload.",
  "Complete optical dump; output hashes calculated after the timed read."
]
```

The phrases used by the historical converter are reserved for reconstructed evidence and must not be emitted by native FriiDump:

```text
Evidence origin: reconstructed ...
Source artifact: ...
Source artifact SHA-256: ...
Converter: ...
```

---

## 17. Artifact inventory

`artifacts` is an array. Each entry must contain:

```text
type
path
bytes
sha256
```

Example:

```json
"artifacts": [
  {
    "type": "log",
    "path": "docs/debug/gdr8163b_0m26.log",
    "bytes": 48320,
    "sha256": "64-hex-character-sha256"
  },
  {
    "type": "dump_output",
    "path": "Sonic Mega Collection.iso",
    "bytes": 1459978240,
    "sha256": null
  }
]
```

Requirements:

- Artifact paths are descriptive metadata.
- Use a stable type such as `log`, `dump_output`, or another documented FriiDump artifact type.
- Record artifact byte size and SHA-256 when FriiDump knows them.
- Use `null` when a path, size, or SHA-256 is unavailable.
- The report importer does not open arbitrary paths from the JSON.
- The report file itself is preserved separately by the database after acceptance.

---

## 18. Native report versus reconstructed historical report

Future FriiDump output must be native evidence.

| Property | Native FriiDump report | Reconstructed historical report |
|---|---|---|
| Evidence origin | Inferred as `native_report` | Declared in controlled notes |
| Run timestamps | Normally authoritative | May be unknown |
| Converter identity | Not present | Present |
| Source-log identity | Optional normal artifact | Required reconstruction provenance |
| Measurement scope | Emitted by FriiDump | Recovered from historical evidence |
| Report generation | During or immediately after run | Later conversion from archived logs |

FriiDump must not imitate reconstruction provenance in new native reports.

---

## 19. Database workflow implications

A generated report does not automatically change public compatibility data.

The workflow is:

1. FriiDump generates one `.friidump.json` report.
2. The report is submitted or imported.
3. The report is validated and fingerprinted.
4. An administrator accepts or rejects it.
5. An accepted report becomes reviewed evidence.
6. An administrator may link it to an assessment with the same exact firmware and platform.
7. A tested compatibility status may be published only when accepted evidence is linked.

FriiDump therefore reports facts, not final compatibility conclusions.

---

## 20. Duplicate and reproducibility requirements

The database evaluates duplicate identity using:

```text
source system + run UUID
exact report-file SHA-256
normalized report SHA-256
```

FriiDump requirements:

- Each new execution gets a new UUID.
- The same stored execution must retain its UUID when exported again.
- FriiDump should serialize reports deterministically where practical.
- Do not regenerate the same run with a new `generated_utc` and changed content while preserving the old UUID.
- Do not reuse a report file as a template without replacing its run UUID.
- A resumed run should be clearly treated as either the same persisted execution or a new execution; it must not ambiguously reuse identity.

---

## 21. Filename requirements

Preferred filename:

```text
<disc title>.friidump.json
```

Examples:

```text
Sonic Mega Collection.friidump.json
Red Faction II [TQ00501A].friidump.json
friidump-diagnostic-no-media-<run-id>.friidump.json
```

Requirements:

- The `.friidump.json` suffix is required by the public submission workflow.
- Sanitize characters invalid on the host filesystem.
- Avoid overwriting an earlier report.
- Use a collision-safe suffix when two runs have the same title.
- The root `schema` field, not the filename alone, determines the format.

---

## 22. Warning-free evidence policy

A report may be schema-valid while still generating quality warnings. FriiDump should produce warning-free reports whenever the information is available.

Avoid these warning conditions:

- modified firmware without `modification_note`;
- media present but no disc title;
- failed dump without `failure_stage`;
- successful dump with no output hash;
- reference match without a reference provider.

Warnings do not always invalidate a report, but they reduce evidence quality and require additional review.

---

## 23. Minimum acceptance checklist for FriiDump

A FriiDump implementation is ready for database integration when all of the following pass:

- [ ] Emits exactly one UTF-8 `.friidump.json` file per finalized run.
- [ ] Uses `friidump-test-result.v1`.
- [ ] Emits every required root object and required child field.
- [ ] Rejects or prevents unknown schema fields.
- [ ] Generates a unique persistent UUID per run.
- [ ] Records authoritative UTC start and completion timestamps.
- [ ] Records exact FriiDump version and full build commit.
- [ ] Records exact live drive and firmware inquiry identity.
- [ ] Separates stock and modified firmware.
- [ ] Provides a modification note for modified firmware.
- [ ] Records platform and media identity without guessing.
- [ ] Uses correct test-type and result mappings.
- [ ] Separates seed duration from dump duration.
- [ ] Records actual sectors, bytes, and elapsed time.
- [ ] Does not report planned final bytes as partial progress.
- [ ] Emits an explicit `Measurement scope:` note.
- [ ] Uses `assembled_output` for the current Xbox assembled-image metric.
- [ ] Provides at least one output hash for successful dumps.
- [ ] Records reference verification separately from compatibility status.
- [ ] Records the selected runtime profile identity.
- [ ] Does not emit reconstruction provenance for native runs.
- [ ] Preserves exact report identity on re-export.
- [ ] Writes the final JSON atomically.
- [ ] Passes schema and semantic validation with zero errors.
- [ ] Produces warning-free successful-run fixtures.
- [ ] Includes automated fixtures for success, partial, seed failure, and diagnostics.

---

## 24. Required test fixtures

FriiDump development should include at least these report-generation tests:

1. **Successful GameCube full dump**
   - `full_dump` / `pass`
   - `full_optical_payload`
   - sectors, bytes, duration, hash
   - stock firmware

2. **Successful Xbox assembled output**
   - `full_dump` / `pass`
   - `assembled_output`
   - explicit non-comparable scope
   - modified firmware when applicable

3. **Partial optical dump**
   - `partial_dump` / `partial`
   - actual progress bytes and sectors
   - `partial_progress`
   - failure stage and sector

4. **Seed-retrieval failure**
   - `seed_only` / `fail`
   - dump `not_attempted`
   - no fabricated dump size or throughput

5. **No-media diagnostic**
   - `diagnostic_no_media` / `not_applicable`
   - unknown media identity
   - no compatibility conclusion

6. **Modified-firmware identity**
   - `firmware_modified: true`
   - non-empty modification note

7. **Duplicate export**
   - same stored run exports with the same UUID and equivalent normalized content

8. **New retry**
   - same drive and disc, but a new execution receives a new UUID

---

## 25. Native successful-run template

```json
{
  "schema": "friidump-test-result.v1",
  "format": {
    "name": "FriiDump Interchange Format",
    "generation": 1,
    "serialization": "json"
  },
  "generated_utc": "2026-07-21T20:15:00Z",
  "generator": {
    "name": "FriiDump",
    "version": "REPLACE_WITH_VERSION",
    "build_commit": "REPLACE_WITH_FULL_40_CHARACTER_COMMIT_OR_NULL"
  },
  "run": {
    "run_id": "REPLACE_WITH_UUID",
    "started_utc": "2026-07-21T18:00:00Z",
    "completed_utc": "2026-07-21T20:14:31Z",
    "test_type": "full_dump",
    "result": "pass"
  },
  "drive": {
    "vendor": "HL-DT-ST",
    "model": "DVD-ROM GDR8163B",
    "firmware_revision": "0M26",
    "interface": "ATAPI",
    "device_path": "F:",
    "firmware_modified": false,
    "modification_note": null
  },
  "media": {
    "platform": "gamecube",
    "title": "Sonic Mega Collection",
    "region": "USA",
    "disc_id": null
  },
  "seed": {
    "attempted": true,
    "result": "pass",
    "duration_seconds": 6.0
  },
  "dump": {
    "attempted": true,
    "result": "pass",
    "sector_count": 712880,
    "byte_count": 1459978240,
    "duration_seconds": 7241.31,
    "failure_stage": null,
    "failure_sector": null,
    "output_path": "Sonic Mega Collection.iso"
  },
  "hashes": {
    "crc32": "01b52739",
    "md5": "85a525df1481d0ad67d8761f832dca12",
    "sha1": null,
    "sha256": null
  },
  "reference": {
    "provider": "redump",
    "result": "match",
    "reference_id": null
  },
  "profile": {
    "support_tier": "known_supported_profile_hardening",
    "cdb_offset": "0x5E0",
    "gate_address": "0x90024FF7"
  },
  "notes": [
    "Measurement scope: full_optical_payload.",
    "Complete optical dump; output hashes calculated after the timed read."
  ],
  "artifacts": [
    {
      "type": "log",
      "path": "friidump.log",
      "bytes": null,
      "sha256": null
    }
  ]
}
```

---

## 26. Validation target

During development, reports should be validated against:

```text
schemas/friidump-test-result.v1.schema.json
```

The compatibility database package also provides semantic validation through:

```text
bin/validate-report.php
```

Acceptance target:

```text
valid=true
errors=0
warnings=0
```

The native-report implementation should be considered incomplete until its automated fixtures pass both JSON Schema validation and the database semantic validator.

---

## 27. Summary of the new FriiDump obligations

The primary new obligation is not merely “write a JSON log.” FriiDump must produce durable, exact, reviewable evidence with:

- stable per-run identity;
- authoritative timestamps;
- exact live firmware identity;
- honest final-state semantics;
- defensible byte and duration measurements;
- explicit measurement scope;
- output hashes;
- clear separation between native evidence, reference verification, and curated compatibility status.

This report becomes the long-term evidence record behind the public compatibility database. It must therefore favor exactness and honesty over optimistic inference.
