Skip to content

Latest commit

 

History

History
256 lines (206 loc) · 14.7 KB

File metadata and controls

256 lines (206 loc) · 14.7 KB

MemoryValidator Integration Contract v0.1

Status: frozen corrected T001 v0.1 candidate — MV-CORE-T001-C001

This document is the integration authority for later parallel work. Git and committed artifacts are authoritative; chat history is not. Any change to this contract requires a separately authorized bounded task labelled CONTRACT CHANGE. Future work must not change it silently.

C001 is the explicitly authorized CONTRACT CHANGE / bounded correction of the pre-Final-Gate T001 candidate at 1c6229dd416d776011b013b637ab2508b463d582. It is not the T001 Final Gate. The corrected required authority fields and canonicalization below supersede that unreleased candidate; old candidate documents missing those fields fail closed. There is no automatic migration and no general permission to change published contracts. See C001_VERIFICATION.md for the correction/test mapping.

Namespace ownership

Namespace Ownership
MemoryValidator.Core.Identity Typed identities and material configuration canonicalization
MemoryValidator.Core.Contracts Version headers, status enums, configuration and module envelopes
MemoryValidator.Core.State Run manifest, generation guard, and explicit state machine
MemoryValidator.Core.Persistence Durable authority store and file-promotion adapter boundary
MemoryValidator.Core.Recovery Recovery decisions derived from committed authority
MemoryValidator.Core.Evidence Immutable observation, provenance, tool, and integrity contracts
MemoryValidator.Core.Findings Evidence-backed interpretations; never recommendations
MemoryValidator.Core.Invariants Typed domain errors and cross-contract validation
MemoryValidator.Core.Serialization The one JSON profile and bounded canonicalization rules

Future collectors and tool/benchmark adapters own namespaces outside MemoryValidator.Core.*. They consume Core contracts; Core never references them.

Dependency direction

Identity, version headers, and status enums are foundational. Evidence and Findings depend on typed identities and version headers; ModuleResult may carry independent Evidence proof. State composes those contracts. Persistence composes State plus Serialization. Recovery reads through the locked file Persistence boundary. Adapters may depend inward on Core; Core must not depend outward on adapters, UI, CLI, network, hardware APIs, or tool SDKs.

The Core uses the .NET BCL. A new runtime dependency requires a separately reviewed license, purpose, exact version, and necessity decision.

Identity types

  • RunId: unique execution identity, run_<guid-n>.
  • GenerationId: unique generation identity, gen_<guid-n>.
  • ModuleRunId: unique module execution identity, mod_<guid-n>.
  • EvidenceId: unique observation identity, evd_<guid-n>.
  • FindingId: unique interpretation identity, fnd_<guid-n>.
  • ConfigurationId: deterministic content identity, cfg_<sha256>.

The Run also persists generation_sequence (zero-based, at most 2,147,483,646), generation_lineage (unique IDs in authority-owned progression order), and authority_revision (nonnegative Int64, never reset on generation change). Evidence, ModuleResult, and Finding carry the generation sequence as part of ownership. retired_evidence_ids prevents an Evidence identity from being rebound after its generation's current observations are retired. This is an identity ledger, not a historical Evidence store. Uniqueness enforcement is within the Run's persisted lineage; independent Run stores are not a global identity registry.

GUID text is 32 lowercase hexadecimal characters with no separators. SHA-256 text is 64 lowercase hexadecimal characters. Default/uninitialized identity structs are invalid.

Identity material must never include hostname, username, IP, MAC, MachineGuid, disk serial, Windows key, email, or another personal/device-unique identifier.

Configuration canonicalization

ConfigurationId hashes UTF-8 JSON produced by MV-CONFIG-C14N-0.1:

  1. Fields are emitted in this exact order: memory_capacity_bytes, module_count, channel_count, memory_technology, configured_data_rate_mt_per_second, and primary_timings.
  2. memory_technology uses .NET 10 Unicode whitespace trimming, Unicode NFC, invariant uppercase, then NFC again. Null/blank or ill-formed Unicode is rejected. Internal whitespace is retained; compatibility normalization (NFKC) is not used.
  3. Integers use invariant base-10 JSON numbers with no exponent, leading plus, or unnecessary leading zeros in canonical output.
  4. primary_timings is either JSON null or an object ordered as cas_latency, ras_to_cas_delay, row_precharge, active_to_precharge.
  5. The technology value emits only ASCII letters, digits, space, underscore, hyphen, and period literally. Every other UTF-16 code unit is escaped as \uXXXX with uppercase hexadecimal; a supplementary character uses its two surrogate escapes. This allow-list is explicit and does not depend on the encoder's changing block list.
  6. JSON has no insignificant whitespace or BOM. SHA-256 is computed over those exact UTF-8 bytes. Required nullable primary_timings is always emitted; missing is invalid, whereas null is a distinct documented material configuration.

Only these documented, non-private material fields participate. A change to normalized material must change ConfigurationId; logically equivalent normalized strings retain the same ID. Producer/schema versions do not participate.

Status enums

JSON enum values use uppercase snake case.

ExecutionStatus: SUCCESS, ERROR, TIMEOUT, SKIPPED.

DiagnosticStatus: PASS, FAIL, REVIEW, UNKNOWN, CAPACITY_FAIL.

They are independent dimensions. ERROR, TIMEOUT, and other execution outcomes do not imply diagnostic FAIL. After execution ERROR or TIMEOUT, absent independent diagnostic Evidence, the diagnostic status must be UNKNOWN.

Every constructor, factory, and deserializer rejects undefined status enums. ERROR and TIMEOUT require error metadata. A non-UNKNOWN diagnosis after either failure requires a nonempty independent_diagnostic_evidence bundle, not merely an Evidence ID. Each bundled observation must be valid, uniquely referenced in evidence_ids, owned by the same Run/generation ID/sequence/configuration/ModuleRun, and observed no later than execution completion. At authority append/reload it must exactly match already committed Evidence, including all known metadata. All result references must belong to that ModuleRun. Error metadata is never diagnostic proof. Core validates this evidence-backed producer claim; it does not infer a hardware diagnosis from payloads or execute a diagnostic/recommendation engine.

Result envelopes

Every persisted public contract has top-level schema_name, schema_version, and producer_version. ModuleResult additionally binds run_id, generation_id, generation_sequence, configuration_id, and module_run_id; both statuses; UTC start/completion; duration; Evidence references; optional typed error; is_partial; and optional independent diagnostic Evidence (absent means an empty bundle; null is invalid). Nullable tool and error may be absent or explicit null and are omitted when null on write. Required metrics and collection fields cannot be null.

A failed or partial module result is additive. It cannot replace the run manifest or erase unrelated committed Evidence.

Persistence boundary

IRunAuthorityStore is the authoritative mutation boundary. Every durable mutation accepts expectedGeneration, expectedGenerationSequence, and expectedRevision. The store acquires its local exclusive file lock, reloads committed authority, checks all three exact preconditions inside that same serialized boundary, and rejects stale input before mutation or a temporary write. Every successful mutation advances revision exactly once. A generation restart additionally advances sequence exactly once, appends one never-used GenerationId, and retains retired Evidence identities. The revision does not restart at zero. File-lock contention retries for a bounded ten seconds using a monotonic elapsed-time clock; it does not choose authority by timestamp.

New authority must be CREATED, sequence 0, revision 0, one lineage ID, and empty current/retired artifact collections. An already advanced or FINALIZED snapshot cannot be imported through Create. FINALIZED rejects every further durable mutation, including append operations, generation changes, and configuration changes.

Persistence writes a complete immutable snapshot:

serialize -> same-directory temp -> Flush(true) -> read/deserialize/validate -> promote -> reopen actual destination -> validate and byte-compare

Existing authority uses File.Replace with a backup; first authority uses same-directory File.Move. Reads and recovery consult only the configured authority path. .tmp.*, .bak, and .lock artifacts are never authority.

The actual destination must match the validated durable candidate bytes exactly before success is reported. A no-op promotion, valid-but-different replacement, missing file, or corrupt destination fails closed. A post-promotion failure may have changed the destination; it does not prove rollback. Backup deletion occurs only after verification, and a retained backup is never automatically selected. Reserved temp/backup/lock paths cannot be configured as an authority path.

Adapter boundary

IAuthorityFilePromoter isolates filesystem promotion for fault testing and platform adaptation. Implementations must preserve the previous destination when reporting a failed promotion. No other T001 adapter exists. Future collectors and benchmark adapters must return versioned Core contracts and may not mutate authority directly. Promotion failure is an execution/persistence failure; the destination must be reloaded and validated before further use.

Recovery's public entry point is AuthorityRecoveryService(FileRunAuthorityStore). It accepts expected RunId, generation ID/sequence, revision, and requested configuration, loads and assesses the committed destination under one file lock, and returns that authority identity in its assessment. The policy and assessment constructor are internal; an arbitrary in-memory manifest or arbitrary store implementation cannot authorize RESUME_ALLOWED. Assessments are snapshots, not permission to bypass a later mutation's CAS. No recovery method executes a process or hardware action.

Schema naming and version rules

Names are lowercase dotted tokens:

  • memoryvalidator.run-manifest
  • memoryvalidator.configuration
  • memoryvalidator.module-result
  • memoryvalidator.evidence
  • memoryvalidator.finding

T001 supports contract version 0.1 exactly. C001 readers fail closed on unrecognized fields rather than perform lossy authoritative rewrites. A later optional additive field requires explicitly coordinated reader/writer support; it is not silently skipped. A removal, rename, type change, enum semantic change, required-field addition, canonicalization change, or meaning change is breaking and requires a new version plus CONTRACT CHANGE authorization. Unsupported schema names or versions fail closed. T001 has no migration engine.

Serialization rules

  • UTF-8 JSON, snake_case property names, uppercase snake-case enum strings.
  • Persisted contract strings and metric names must contain well-formed UTF-16 before serialization; isolated high or low surrogates are rejected rather than rewritten as U+FFFD. A v0.1 nonblank string contains at least one code unit outside this explicit .NET 10 whitespace set: U+0009..U+000D, U+0020, U+0085, U+00A0, U+1680, U+2000..U+200A, U+2028, U+2029, U+202F, U+205F, and U+3000. U+FEFF is not whitespace in this contract.
  • Enum integers, undefined names, case variants, and padded names are rejected.
  • Required constructor parameters are enforced.
  • Comments, trailing commas, and duplicate object property names are rejected.
  • Null optional properties may be omitted.
  • Unknown properties fail closed at every typed level; payload JSON and named metric entries are explicitly open data, not unknown contract fields.
  • Schema name/version checks run for all five standalone persisted contract types as well as manifest children. No manifest-only compatibility shortcut exists.
  • Bounded integral JSON numbers are accepted only when mathematically exact (for example 2.0 and 2e0 read as 2); canonical writes use integer notation. Decimal fields must be exactly representable without rounding, truncation, or underflow. Schemas express the same Int32/Int64/UInt64 bounds and decimal coefficient/scale limits.
  • Callers must use CoreJson; alternate serializer defaults are not authoritative.

Error semantics

Authority contract failures use typed CoreContractException subclasses and stable codes, including STALE_GENERATION, STALE_GENERATION_SEQUENCE, STALE_AUTHORITY_REVISION, GENERATION_ID_REUSE, ILLEGAL_STATE_TRANSITION, UNSUPPORTED_SCHEMA_VERSION, PERSISTENCE_PROMOTION_FAILED, and AUTHORITY_COMMIT_VERIFICATION_FAILED. Preconditions and candidate validation reject before promotion. Post-promotion verification failure has the distinct no-success/no-assumed-rollback semantics described above. Standalone JSON shape/lexical errors may surface JsonException; the file authority boundary wraps them as contract validation failures. Tool/process failure is an execution fact, not a hardware diagnosis.

Time representation

Persisted times are DateTimeOffset values with an explicit zero UTC offset and JSON RFC 3339 representation with uppercase T and Z or +00:00, within DateTimeOffset's year range 0001 through 9999, seconds 00 through 59, and at most seven fractional digits. Generic RFC 3339 year-zero and leap-second spellings are intentionally excluded because they are not representable by the v0.1 runtime type. Naive/local timestamps, -00:00, and non-zero offsets are rejected. Duration is rounded from exact integer ticks to elapsed milliseconds, midpoint away from zero, and must agree with start/completion. Evidence observation cannot follow its commit; child commits/completions/creation cannot follow the containing authority snapshot. No authority ordering is inferred from wall-clock time.

Hash and canonicalization rules

Configuration uses MV-CONFIG-C14N-0.1. Evidence observation integrity uses MV-JSON-C14N-0.1: object property names sort by ordinal UTF-16 code-unit order, arrays retain order, duplicate object names are rejected, insignificant whitespace is removed, and JSON number lexical spelling is material. Evidence hashes a fixed object containing sorted metrics and canonical payload, using SHA-256 lowercase hex.

This is bounded canonicalization, not a claim of RFC 8785 compliance. Changing either canonicalization rule is a breaking contract change.