Ingest issue acknowledgement plan
Status: implemented. Date: 11 October 2026.
Current contracts: source issues architecture, Processing, and source review. The sections describing current behaviour below retain the pre-implementation design context.
On this page
Problem
MTL Explorer reports GPS and media import problems, including files that cannot be read or contain no usable data. Some problems are acceptable to the user, but the same files can keep drawing attention after the user has acknowledged them. Processing outcomes, GPS review decisions, and map notice dismissal do not share one model.
Current behaviour
| Mechanism | Meaning | Storage |
|---|---|---|
| Map Acknowledge | Hide the current failed-file notice | Browser storage, scoped to server URL and account |
| Map Minimize | Close the explanation and leave the compact indicator | Component state |
| GPS Save use settings | Choose map/statistics inclusion and acknowledge current source findings | Server database |
| Media failed-file list | Show filenames and saved errors | Server database, without per-file acknowledgement |
The map acknowledgement survives ordinary logout and login in the same browser. It has no expiry timer. Clearing local application data removes it; another browser or device has its own acknowledgement. Processing, stale-map, offline, and unavailable-status notices remain independent.
The map compares a saved token with the current GPS/media failure counts and the latest failed-file update timestamps. This records a processing snapshot, rather than a decision about the actual problems. Retrying the same bad file can restore the notice. Fixing or removing one file can also restore the notice for the remaining acknowledged files.
GPS review already compares source content and meaningful findings. Cosmetic wording, ordering, and measurement rounding do not invalidate its decisions; new defects can require review even when the source bytes are unchanged. This review model does not control the map's processing-failure notice. A reviewed GPS source can therefore remain a failed file needing attention on the map, while an imported track with quality findings belongs to a separate queue.
Acknowledgement is also coupled to GPS use settings. An empty source should not need a map/statistics exclusion choice merely to stop repeated notices. Conversely, acknowledging a timing problem cannot make its measurements reliable or rebuild a failed import.
The client retains a five-minute freshness snooze and dismiss handler without a current UI caller. This adds an unused dismissal concept alongside the map notice.
Settings → Processing derives its import Needs attention state from the raw failed-file count. A user can inspect failures but cannot acknowledge them there. Hiding the map notice therefore leaves the processing warning active. The user needs an action that clears accepted source problems consistently in both places, while preserving their processing outcomes and explanations.
Current references:
- Map notice and map status resolution.
- Indexer summary and failure timestamp query.
- GPS review persistence and finding identity.
- Freshness store and map loading methods.
- Processing progress and attention state and failed-file details.
- Current processing guide and GPS review guide.
Current database storage
GPS decisions are stored in track_review_decision. Each save appends rows;
the latest applicable row for a source revision and section determines its
choice. This table currently combines use settings and acknowledgement.
| Column | PostgreSQL type | Current meaning |
|---|---|---|
id |
bigint, generated primary key |
Decision history order |
source_id |
bigint, foreign key to indexed_file.id |
GPS source file |
source_hash |
varchar(64) |
Assessed source content hash |
finding_hash |
varchar(64) |
Semantic findings acknowledged by this choice |
section_index |
integer |
Source section, or -1 for an unsectioned source |
decision |
varchar(24) |
INCLUDE, EXCLUDE_MAP, EXCLUDE_STATISTICS, EXCLUDE, or LATER |
decided_at |
timestamp with time zone |
Time of the decision |
All columns are non-null. An index covers
(source_id, source_hash, section_index, id DESC). There is no account column;
the choices apply to the shared library. track_source_review stores the GPS
assessment, diagnosis JSON, and combined review state. The map acknowledgement
has no database row; it remains in browser storage.
See the existing table definitions.
Plan
Use one server-owned issue and acknowledgement model for GPS and media. Acknowledge one file or all current issues through the same operation. Keep processing outcomes and data-use choices separate from acknowledgement.
Responsibilities
| Layer | Responsibility |
|---|---|
| Processing outcome | Record pending, imported, skipped, or failed work and its reason |
| Issue | Describe a meaningful problem, its source revision, severity, and affected features |
| Acknowledgement | Record that an account accepts leaving a particular issue as it is |
| Use settings | Control whether available tracks contribute to the map and statistics |
Acknowledgement does not change source files, processing outcomes, geometry, measurement reliability, or map/statistics use. Use settings remain library decisions; acknowledging issues is an account decision. Informational findings remain visible without requiring acknowledgement.
Keep the existing GPS diagnosis engine, section inspection, and import evidence. Generalise the issue contract and acknowledgement bookkeeping, rather than adding a second acceptance mechanism only for failed indexed files.
Database design
Add two tables: source_issue for GPS/media issues and
source_issue_acknowledgement for current account acknowledgements. Retain
track_review_decision for map/statistics use only. The SQL below describes
the proposed target schema; it is not an applied migration.
Source issues
One row represents one semantic defect in one source revision. A changed revision or meaningful defect creates a different row; updating explanatory wording or retry timestamps does not.
CREATE TABLE source_issue (
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
source_id bigint NOT NULL
REFERENCES indexed_file(id) ON DELETE CASCADE,
source_revision varchar(80) NOT NULL,
finding_hash varchar(64) NOT NULL,
stage varchar(32) NOT NULL,
reason varchar(64) NOT NULL,
severity varchar(16) NOT NULL
CHECK (severity IN ('INFORMATION', 'REVIEW')),
section_index integer NOT NULL DEFAULT -1,
message text NOT NULL,
details jsonb NOT NULL DEFAULT '{}'::jsonb,
first_seen_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
last_seen_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
resolved_at timestamp with time zone,
UNIQUE (source_id, source_revision, finding_hash),
CHECK (section_index >= -1)
);
CREATE INDEX source_issue_active_review_ix
ON source_issue (source_id, id)
WHERE resolved_at IS NULL AND severity = 'REVIEW';
source_id identifies the file through the existing indexer. Its GPS/media
index and location remain in indexed_file; do not duplicate them here.
source_revision is sha256:<content hash> for readable contents. For an
unreadable source, persist an unreadable:<UUID> token for the continuous
unreadable episode and reuse it across retries. It identifies that episode,
not proven file contents. Once the file can be read, resolve the unreadable
issue and assess its actual content revision.
Do not use meta:<size>:<mtime> as a content identity. Metadata can be unavailable
for unreadable sources, and changing modification time alone does not establish
new contents. Available metadata can remain explanatory evidence in details.
finding_hash identifies the semantic defect within that revision.
details holds structured evidence such as affected point indices, counts,
measurements, and affected features. The common issue table uses one normalized
severity: REVIEW requires acknowledgement; INFORMATION does not. The server
maps domain findings through its existing review policy. GPS warnings that
require review map to REVIEW; the assessment-limit exception maps to
INFORMATION while retaining its incomplete-assessment explanation. The
original GPS severities remain in its diagnosis evidence. This mapping must not
treat incomplete assessment as a healthy source. Keep meaningful domain changes,
including severity escalation, in finding_hash even when their normalized
severity is unchanged.
There is no separate review_required column. A meaningful change in normalized
severity belongs in the finding identity, so a newly reviewable defect cannot
inherit a silent acknowledgement. An empty-file informational skip has reason
EMPTY_FILE and severity INFORMATION.
An issue is active while resolved_at is null. Repeated assessment upserts the
same identity and updates its explanation and last_seen_at. Resolve absent
findings only after a complete assessment of their relevant stage. A failed or
limited assessment must not falsely resolve findings it could not check.
Normal source removal retains the existing indexed_file row with status
REMOVED and resolves its issues, preserving history. An explicit hard deletion
or database reset removes the associated issues and acknowledgements through
cascading foreign keys. This is distinct from clearing browser data.
Current account acknowledgements
Store only the current acknowledgement for each account and issue. A row means
acknowledged; no row means pending when the issue is active and reviewable.
Resolution belongs to source_issue, not to an account decision.
CREATE TABLE source_issue_acknowledgement (
issue_id bigint NOT NULL
REFERENCES source_issue(id) ON DELETE CASCADE,
account_key varchar(255) NOT NULL CHECK (account_key <> ''),
acknowledged_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (issue_id, account_key)
);
account_key comes from the canonical authenticated server principal, not from
a submitted username, browser identifier, JWT token, or login/session reference.
Current authentication uses a configured account rather than a persistent user
table, so use its canonical username without a session foreign key. Login case
variants must produce the same key. Renaming that account creates a new scope;
account renaming/migration is outside this change.
Acknowledge inserts a row with ON CONFLICT (issue_id, account_key) DO NOTHING.
Reopen deletes that row. Repeating either operation without an intervening
opposite action is harmless. Keep the original acknowledged_at on duplicate
inserts. No append-only acknowledgement history, request ID, or expected latest
decision protocol is required. The primary key supports the per-issue account
lookup; add further indexes only when query plans justify them.
The primary key prevents duplicate acknowledgements; it does not order opposite user intentions. Concurrent Acknowledge and Reopen requests use ordinary database write ordering. A delayed Acknowledge processed after Reopen can acknowledge the issue again. The UI serializes opposite actions for the same issue while a request is pending, and the API does not add automatic mutation retries. Cross-device writes still follow server processing order. A stronger replay guarantee would require extra state and is outside this design.
Keep the source/issue revision validation described below. It protects a different requirement: an old request must not acknowledge a new defect or source revision. Use the existing transactional source guards where needed; do not introduce a separate lock-ordering protocol for acknowledgement.
There is no browser/device column, expiry column, or global accepted flag on
indexed_file. Account scope is within this installation's database. A file
with three reviewable issues gets three acknowledgement rows when acknowledged;
the UI still counts it as one file.
Shared demo account
Current authentication configures one login in WebSecurityConfig. The demo login response supplies those same credentials to demo visitors. Visitors using that login therefore share one account: an acknowledgement by one visitor is visible to the others.
Accept this shared behaviour for the current demo and clear the affected acknowledgements whenever its demo data is reset. Keep Acknowledge available. Separate visitor accounts or principals are a future authentication feature; do not substitute session identifiers for the account key in ordinary use.
Map and statistics decisions
Keep track_review_decision as the shared-library use-setting history, with
this target shape:
| Column | PostgreSQL type | Planned meaning |
|---|---|---|
id |
bigint, generated primary key |
Use-setting history order |
source_id |
bigint, foreign key to indexed_file.id |
GPS source file |
source_hash |
varchar(64) |
Source content revision the setting applies to |
section_index |
integer |
Existing source-section mapping |
decision |
varchar(24) |
INCLUDE, EXCLUDE_MAP, EXCLUDE_STATISTICS, or EXCLUDE |
decided_by |
varchar(255) |
Canonical account that saved the library setting |
decided_at |
timestamp with time zone |
Time of the setting |
All target columns are non-null. Keep the existing latest-decision index and
add a check constraint for the four use choices. Remove finding_hash from
this table; acknowledgement lives only in source_issue_acknowledgement. Review
later leaves issues pending and writes no use-setting row. A whole-source
save retains the existing section mapping and writes choices for the affected
sections.
decided_by records the actor; it does not make use settings account-specific.
The latest row for (source_id, source_hash, section_index) still controls the
shared library. Existing track exclusion flags can remain projections of these
choices. Refactor track_source_review.review_state and
gps_track.review_status so they are not parallel authorities for an account's
acknowledgement. Keep GPS diagnosis JSON as assessment evidence, with the common
issue rows owning issue lifecycle and the acknowledgement rows owning review.
State lookup and examples
Derive the state for the authenticated account; do not save separate pending or accepted counters:
| Issue row | Acknowledgement row for this account | Effective review state |
|---|---|---|
resolved_at is set |
Present or absent | Resolved |
Active, severity INFORMATION |
Present or absent | No acknowledgement required |
Active, severity REVIEW |
Absent | Pending |
Active, severity REVIEW |
Present | Acknowledged |
For example, issue 101 is a GPS parsing failure for source 42, revision
sha256:<hash A>. Synthetic current acknowledgement rows could look like this:
issue_id |
account_key |
acknowledged_at |
|---|---|---|
| 101 | reviewer | 2026-10-11 12:00:00Z |
| 101 | second-reviewer | 2026-10-11 12:02:00Z |
Issue 101 is acknowledged for these accounts; an account without a row still
sees it as pending. Reopen by reviewer deletes only (101, reviewer); the
second account's acknowledgement remains. A retry with the same contents and
defect keeps issue 101. If source 42 changes to revision sha256:<hash B>
and still fails, create a new issue row without inheriting issue 101's
acknowledgements. Older resolved findings retain their issue records and any
remaining acknowledgement rows, but past Acknowledge/Reopen actions are not
retained as an audit trail.
The pending-file count uses active reviewable issues with no acknowledgement for the authenticated account:
SELECT COUNT(DISTINCT i.source_id)
FROM source_issue i
WHERE i.resolved_at IS NULL
AND i.severity = 'REVIEW'
AND NOT EXISTS (
SELECT 1
FROM source_issue_acknowledgement a
WHERE a.issue_id = i.id AND a.account_key = :account_key
);
Bulk requests carry the exact issue IDs and source revisions in the displayed snapshot. Validate and write them transactionally; new or changed issues are not covered by the acknowledgement.
Issue lifecycle and identity
For each account, a reviewable issue is pending, acknowledged, or resolved. Acknowledgement persists on the server across logout, later logins, browser-data clearing, device changes, and server restarts. Another account retains its own pending issues. There is no automatic expiry.
Use source identity, a content-based source revision, and a semantic defect identity. Reuse the GPS finding identity approach: stage, reason, severity, section, affected observations, and affected count where relevant. Adapt it to individual issues so removal of one defect does not invalidate acknowledgement of another.
Size and modification time can trigger discovery, but do not alone prove that contents changed. Retry counters, processing timestamps, exception wording, finding order, and cosmetic measurement changes must not identify a new issue. Unreadable sources need an explicit revision representation without pretending that their contents were successfully assessed.
| Event | Result |
|---|---|
| User acknowledges current issues | Those issue revisions become acknowledged for that account |
| Logout/login, map reload, restart, or another device | Acknowledged issues stay quiet |
| Retry or rescan finds the same defect in unchanged contents | Acknowledged issues stay quiet |
| Another file is fixed, removed, or changed | Unrelated acknowledgements stay valid |
| A particular problem disappears or its source is removed | That issue becomes resolved |
| Changed source contents still have a reviewable problem | The new source revision requires review |
| Assessment finds a new meaningful defect in unchanged contents | The new defect requires review; existing acknowledgements remain valid |
| User selects Reopen | That account must review the selected issue again |
A successful import resolves import failures that disappeared. It does not automatically resolve unrelated GPS quality findings. Acknowledged and resolved findings remain available with their explanations and current acknowledgement timestamps. Reopen removes the acknowledgement row; no acknowledgement action history is required.
User flow
- Review provides Acknowledge this file's issues for GPS and media.
- The map provides Acknowledge all current issues for the issues represented by its current summary.
- Settings → Processing provides the same overall Acknowledge all current issues action, covering current GPS and media source issues. Each import group also offers acknowledgement for that group's issues.
- These actions preserve the findings and current use settings. Keep the term Acknowledge consistent; do not introduce a separate Accept action.
- Review offers Pending and Acknowledged filters, diagnosis links, Reopen, and Retry where applicable. Retry schedules processing independently of acknowledgement; it does not automatically reopen an unchanged issue.
- GPS retains separate whole-source and section map/statistics settings. Choosing Exclude does not implicitly replace issue acknowledgement.
- Processing reports progress and outcomes, including informational skips, exposes per-file acknowledgement, and links to the same Review entries.
- The map counts distinct files with pending reviewable issues, including quality findings in successfully imported sources. Multiple findings or affected calculations must not count the same source file repeatedly.
- Minimize closes the explanation while leaving the compact indicator. It makes no saved review decision.
Bulk acknowledgement must identify the source and issue revisions represented by the displayed summary or list. File IDs alone are insufficient. Issues that arrive or change while the request is in progress remain pending. Per-file requests must also reject stale issue revisions rather than acknowledge unseen findings. Repeated inserts or deletes are harmless without an intervening opposite action; concurrent opposite actions follow database write ordering.
For example, acknowledge ten files with issues. An unchanged retry stays quiet. Fixing three files stays quiet. If one new file has an issue, the map reports one file needing review.
Settings processing progress
Make Needs attention actionable. Show the number of files with pending source issues and offer Review issues and Acknowledge all current issues on the Processing page. The overall action covers the whole library's current GPS and media issues, independently of map filters and list pagination. A GPS or media group action covers only that index. File details provide the same per-file action as Review.
For source-related attention, derive the warning state from the current account's pending issues, not from raw failure totals. After acknowledgement, clear the source attention badge and warning styling once its pending count reaches zero. If pending issues remain or arrive later, keep Needs attention with the updated count. When processing has finished with no pending issues, show Complete · N files acknowledged if known issues remain; if work is still running, retain its running state and progress. Keep failed/skipped totals and their explanations visible as factual outcomes. Acknowledge does not increase the successful-import count.
Calculations unavailable because of those same source issues must use the same acknowledgement when deciding whether to request attention. They can continue to show unavailable results and their reasons, without another persistent warning asking the user to accept the same limitation. Current operational failures keep their attention state and an appropriate recovery action.
Update Processing, map, and Review summaries together from the bulk response. Only clear source attention after the server confirms the save. Disable overlapping acknowledgement/Reopen actions during submission and show a save failure without clearing warnings. No separate Processing dismissal state or extra acknowledgement table is needed.
Bulk acknowledgement API
Submit the complete selection in one request. Use the same endpoint for an overall action, one import group, selected files, or a single file; only the target array differs. The client must not call a per-file endpoint in a loop or submit only the currently visible list page.
Provide a proposed snapshot endpoint:
GET /api/source-issues/acknowledgement-targets
It returns the complete compact array of pending issue IDs and source
revisions, with counts from that same snapshot. An optional index=GPS or
index=MEDIA limits an import group action. The default includes all pending
GPS/media source issues for the authenticated account. Obtain the array in one
read when preparing the action; do not fetch every detail page or attach the
full array to every progress poll. Display the snapshot counts and submit its
targets without expanding the selection to later arrivals.
Example snapshot response, with content hashes abbreviated for readability:
{
"pendingFileCount": 2,
"targets": [
{ "issueId": 101, "sourceRevision": "sha256:<hash A>" },
{ "issueId": 102, "sourceRevision": "sha256:<hash A>" },
{ "issueId": 203, "sourceRevision": "sha256:<hash B>" }
]
}
The first two issues can belong to one GPS file and the third to a media file.
Submit the full targets array to the proposed write endpoint:
POST /api/source-issues/acknowledgements
Content-Type: application/json
{
"targets": [
{ "issueId": 101, "sourceRevision": "sha256:<hash A>" },
{ "issueId": 102, "sourceRevision": "sha256:<hash A>" },
{ "issueId": 203, "sourceRevision": "sha256:<hash B>" }
]
}
The server supplies account_key from Authentication.getName(). Deduplicate
the targets and match them to active REVIEW issues with the exact submitted
source revisions. Insert acknowledgements through a set-based
INSERT … SELECT … ON CONFLICT DO NOTHING in one transaction. Do not perform
one repository lookup/save or one source reassessment per target. Large input
can use bounded internal SQL batches while retaining one client submission
and one transaction.
Return newly acknowledged, already acknowledged, and stale/resolved target counts, plus refreshed pending-file counts and GPS/media summaries for the current account. Stale or resolved targets are not acknowledged; other valid targets can still succeed. A database failure rolls back the whole write. If a per-file selection is entirely stale, show that its issues changed and refresh instead of claiming success. Issues arriving after the snapshot remain pending and appear in the returned summary.
This needs no persisted bulk-operation record or request ID. The target array defines the selection, and the existing primary key handles duplicate inserts. The opposite-action ordering tradeoff remains the one documented for the current-state table.
Skipped files and operational failures
After the existing stable-file checks, classify zero-byte sources as informational skips. Show their filenames and reasons in Processing without a map review notice. Process them again when their contents change.
Skipped describes an outcome; severity determines whether review is needed. Do not silently classify damaged or unsupported contents, parsing failures, or files without usable GPS observations as acceptable. Record their structured reason, show the issue once, and allow acknowledgement.
Keep pattern exclusions distinct from content-based skips. Do not reuse
EXCLUDED for both meanings. Keep any retained data from an earlier source
revision identified as earlier data; acknowledging or skipping its replacement
does not establish a successful current import.
Job and Google Health failures retain their operational progress, retries, and recovery actions in Processing. Offline, unavailable-status, preparation, and stale-map indicators remain separate from accepted source problems. A file acknowledgement must not hide a current service failure.
Implementation sequence
Implement the common backend model first, then the complete client flow. Ship the consolidated behaviour after both phases pass their checks.
Phase one server model and APIs
- Define the common server issue contract, typed reasons, semantic identity, normalized severity, and lifecycle. Classify source-content problems separately from unexpected processing or service failures. Keep diagnosis and attention policy on the server.
- Add account-scoped acknowledgement persistence and APIs through the existing repository and review services, using the database design. Guard writes with source and issue revisions; support per-file, bulk, and Reopen operations. Add the snapshot and bulk array API with set-based writes and returned summaries. Use the current-state table without an acknowledgement audit trail or replay protocol. Reset shared demo acknowledgements with its data. Use normal Liquibase schema changes without legacy backfill or migration-only endpoints.
- Connect GPS source review and media failures to the common model. Separate GPS acknowledgement from use settings and replace the old acknowledgement bookkeeping. Preserve section choices, measurement restrictions, and the existing assessment-limit policy. Populate common issues during normal imports and explicit reassessment; do not add an automatic GPS backfill.
- Add the narrow zero-byte skip policy and accurate outcome totals. Provide pending and acknowledged summaries and list filters through the common account-aware policy. Export the live OpenAPI schema and regenerate the TypeScript client using the normal server-first workflow. Verify backend identity, lifecycle, account scope, and snapshot guards.
Phase two client flow and cleanup
- Update the map, Review, and Processing flows together using the generated APIs. Keep use settings separate from acknowledgement and count each source file once. Add overall, group, and per-file actions to Processing, and derive its source-related attention from pending issues. Submit each complete bulk selection once and update all summaries from the response. Serialize opposite UI actions while their request is pending; show save failures without adding automatic mutation retries.
- Remove the browser findings-token comparison and
processingFindingsAcknowledgedstorage. Remove the unused freshness snooze, dismiss handler, storage key, and obsolete snooze tests. Retain freshness detection, reload behaviour, and their tests. - Verify the complete lifecycle and demo flow. Update processing, GPS review, media, map, and architecture documentation when the behaviour is implemented. Regenerate the website and installed guide from their sources.
Acceptance checks
- Per-file and bulk acknowledgement produce the same saved result. Neither changes use settings, source contents, or metric support.
- The overall action on the map and Settings → Processing covers all pending GPS/media source issues in its snapshot, including files beyond the visible list page. Group actions cover only their index.
- Each mass action sends one full target array in one write request, with no per-file or pagination submission loop. Server writes use set-based SQL or bounded internal batches, rather than per-issue repository calls.
- After a successful save, Processing clears acknowledged source attention, and map/Review counts agree with it. Failed/skipped totals remain factual, running work retains its progress, and correlated unavailable calculations do not demand another acceptance of the same source limitation.
- A failed bulk transaction clears no warning and commits no acknowledgement. Changed or newly arriving issues remain pending; returned counts show the actual result, including stale targets.
- The same account stays quiet after normal logout, clearing browser data, later login, another device, and server restart. Other accounts remain independent.
- Unchanged retries and rescans, cosmetic diagnosis changes, and removal of other issues do not restore acknowledged notices.
- Changed contents or a new semantic defect require review even when the total issue count is unchanged. Remaining acknowledged defects stay quiet.
- Issues arriving during bulk acknowledgement and stale per-file requests cannot be silently acknowledged. Duplicate inserts keep one acknowledgement row and its original timestamp; repeating Reopen leaves it absent.
- Reopen affects only the current account. Concurrent opposite actions follow database write ordering, with no stronger replay guarantee. Login case variants share the canonical account key; login/session references do not determine acknowledgement ownership.
- Demo visitors using the configured login share acknowledgements. Resetting demo data clears its acknowledgements without affecting another installation.
- Incomplete assessments do not resolve findings they could not check. Source removal retains resolved issue history; explicit database deletion removes dependent rows consistently.
- Corrected or removed sources resolve their corresponding issues. Imported GPS quality findings remain pending until acknowledged or actually resolved.
- Stable zero-byte GPS and media files appear as informational skips without a map review notice. Changed contents are processed again. Damaged and unsupported contents remain reviewable.
- Pending counts agree across the map, Review, and other review summaries and count each source file once. Technical outcome totals remain accurate.
- Normalized severity preserves the existing GPS review policy, including the
assessment-limit exception. A domain severity escalation changes its finding
identity even if normalized severity remains
REVIEW. - Processing, freshness, offline, and service-failure indicators remain accurate independently of source acknowledgement.
Use public or synthetic fixtures. Run backend checks in the development container and relevant client tests for these contracts.