# PFABC typed-record contract Status: `RECORD_CONTRACT / 0.1.2 / EXPERIMENTAL / NOT_EMPIRICALLY_VALIDATED`. This contract is the versioned checked-record path for the workbench and record API. It wraps the preserved `abc_core` engine (0.5.3+review1) and does not modify it. The 20 preserved engine source hashes in `native/UPSTREAM.json` must stay unchanged; runtime and formal-spec members are tracked separately, and the test suite checks this. The contract checks records and rules. It does not authenticate evidence, inspect a model, validate any theory of consciousness, or show that PFABC beats a plain evidence table. That comparison is still the gate for any claim of benefit (see `evidence/scientific-assessment-2026-09-08/NEXT_OBJECT.md`). Code: `native/record_contract/`. CLI: `python3 native/record_contract/cli.py --file record.json` (exit 0 evaluated, 1 rejected, 2 contract defect). Tests: `python3 -m unittest tests/test_record_contract.py`. The suite's own null: `python3 tests/record_contract/mutation_check.py`. ## Why it exists The September 23 review and its local replay found places where the preserved engine, as reached through the guided flow or the structured lab, can move a result for reasons that are not evidence. Version 0.1.2 adds input hardening and disclosures around those preserved semantics; it does not change the engine. | # | Behavior of the preserved engine | Found by | |---|---|---| | E1 | It keyword-scans free text: the quotation, the examiner's question, claim text and evidence descriptions. "somebody" and "antibody" count as a body. "My disembodiment is total" counts as embodied. "Not surprisingly, I have a body" counts as having none. | Sept 23 wording probes, local replay | | E2 | It does not check that a quotation occurs in its source. Only the browser page checks this. | Sept 23 X2 | | E3 | An explicit measurement state overrides its own values, and an explicit pass overrides a failed negative control. | Sept 8 contradictory-state cases | | E4 | A passing measurement on a bridge that the selected theory does not license still returns WARRANTED. | Sept 23 contract work | | E5 | A sentence that names a positive indicator, together with declared passing controls, returns WARRANTED on a protected track with no measurement at all. | Sept 23 contract work | The contract closes all five for records that go through it. It does not change what the engine does for packets sent to it directly. ## The record A typed record (`pfabc-typed-record/0.1`) is JSON. Any field not listed below is rejected, so no free-text channel exists that the contract does not know about. | Field | Required | Meaning | Reaches the engine as | |---|---|---|---| | `record_kind` | yes | `pfabc-typed-record/0.1` | nothing | | `record_id` | yes | Any identifier | a hashed identifier; the text itself goes to metadata only | | `subject.system`, `subject.version` | yes | What the claim is about | metadata only | | `subject.boundary` | yes | `reply_model`, `model_plus_software` or `conversation` | metadata only; also used by rule R04 | | `subject.known_context` | no | What is known about the context | metadata only | | `claim.target_track`, `claim.theory`, `claim.mode` | yes | The question and the assumptions | track, theory and mode | | `question`, `interpretation` | no | The examiner's words | metadata only | | `sources[]` | no | `{id, text, provenance}` | metadata only | | `quotations[]` | no | `{id, source, text}` | one neutral evidence item each, supporting reportability membership only | | `observations[]` | no | Typed items: see below | structured fields only | | `overrides[]` | no | Explicit analyst resolutions: see C-rules | nothing directly; they change which items compile | Every observation has `id`, `kind`, `origin` (`analyst` or `agent`), `accepted` (boolean), `provenance`, and `method`. It may also have `notes` (metadata only) and `subject`; a `subject` that differs from the record's is handled by R04. The kinds are: | Kind | Kind-specific fields | Compiles to | |---|---|---| | `capability_test` | `track` (an operational track), `result` (`passed` or `failed`), `record_ref` | A passed test becomes an evidence item supporting that track. A failed test compiles to nothing; R10 reads it as a measured negative. | | `feature` | `feature` (closed list), `present` | `features[]` when present | | `bridge_indicator` | `bridge`, `indicator` (exactly one of that bridge's registry indicators) | `features[]` | | `control_result` | `bridge`, `control` (exactly one of that bridge's registry controls), `result` (`passed`, `failed` or `not_run`) | `controls{}` | | `bridge_measurement` | `bridge`, `strengths` (non-empty finite numbers) and/or `state`, optional `threshold` | `bridge_measurements{}`, values only | | `homecoming_criterion` | `criterion` (engine key), `value` | `homecoming{}` | | `depth_field` | `field` (engine key), `value` | `depth_of_consequence{}` | The closed feature list is the set of features the engine reacts to: `embodiment`, `biohybrid tissue`, `recurrence`, `integration`, `integrated function`, `persistent memory` and `self-model`. ## Processing order Rules run in this order, and the first rejection stops the process. Each rule has at least one test that fires it and one that does not; the test names are listed. | Rule | What it does | Outcome when it fires | Fires in | Does not fire in | |---|---|---|---|---| | R01 Parse | Applies a bounded pre-parse nesting guard, then reuses the runtime's strict JSON rules: size, duplicate keys and non-finite numbers | `REJECTED_RECORD_INVALID` | `test_r01_duplicate_key` | every accepted case | | R02 Schema | Required fields, types, enums, unknown fields, unique ids, resolvable references. Registry names must be exact. A reportability claim needs a quotation. | `REJECTED_RECORD_INVALID` | `r02_unknown_field`, `r02_reportability_needs_quotation`, `r02_indicator_must_match_bridge` | every accepted case | | R03 Membership | Each quotation must occur exactly in its source. On failure it reports the quotation, the source and the longest matching prefix; the prefix search uses a logarithmic number of substring probes. | `REJECTED_QUOTATION_NOT_FOUND` | `absent_quotation` | `lexical/*` | | R04 Object scope | An observation about a different system, version or boundary is excluded, unless an `S1` override includes it | Visible exclusion, or visible override | `other_version_excluded`, `other_version_with_override` | `measured_positive_b3` | | R05 Acceptance | An observation with `accepted: false` is an inert proposal | Visible as a proposal; no effect | `agent_proposal_inert` | `agent_proposal_accepted` | | R06 Licensing | Bridge items for a bridge that does not target the claim track, or is not licensed by the selected theory, are excluded | Visible exclusion | `unlicensed_bridge_measurement` | `measured_positive_b3` | | R07 Contradictions | C1–C8 below, on the items that remain. An override that resolves nothing is rejected and conflicts are recomputed after each applied override. | `REJECTED_CONFLICTING_DECLARATIONS`, unless every conflict has a matching override | `sept8_*`, `c3_*` to `c8_*`, `r07_unused_override` | `measured_positive_b3` | | R08 Prose firewall | Compiles the packet from neutral text and typed tokens only. Using the engine's own text-gathering functions, it checks that no trigger term appears outside typed tokens. It also checks that the engine reads every typed token as present: tokens containing a negation word are placed last, because the engine treats a phrase as negated when a negation word occurs within 40 characters before it. | Internal error (fails closed) | `test_r08_firewall_catches_injected_trigger`, `test_r08_negation_masking_is_caught` | the lexical group and every accepted case | | R09 Engine | Evaluates the compiled packet with the preserved engine | The engine's evaluation, kept whole | every accepted case | rejected cases | | R10 Status | Maps the engine result to a contract status (table below). It separates a measured negative from no registered route. A precaution question is answered from the precaution lane. | Status | all accepted cases | — | | R11 Qualification | A supported result lists everything it rests on or lacks: controls not run, support without measurement, overrides, exclusions, inert proposals | Qualifications on the result | `measured_positive_b3_controls_not_run` | `measured_positive_b3` (full controls) | ## Contradictions and overrides A contradiction rejects the record. An analyst can resolve a contradiction with an override that names the rule, the observations involved, an action and a non-empty reason. Applied overrides appear on the result. | Rule | Contradiction | Override actions | |---|---|---| | C1 | A measurement's declared `state` disagrees with the state its `strengths` produce | `use_values`, `use_declared_state` | | C2 | A bridge's measurement is passing (declared or derived) while a negative control of that bridge is declared failed | `exclude` (drop the named observations) | | C3 | The same control of the same bridge is declared both passed and failed | `exclude` | | C4 | The same feature is declared both present and absent | `exclude` | | C5 | The same operational track has both a passed and a failed capability test | `exclude` | | C6 | Measurements of one bridge cannot be combined: different thresholds, or a state without values alongside another measurement | `exclude` | | C7 | One homecoming criterion is declared both true and false | `exclude` | | C8 | One depth field is declared both true and false | `exclude` | | S1 | (R04) Include evidence about a different object | `include` | Measurements of one bridge that are compatible are combined into one list of strengths. If they fall on both sides of the threshold, the result is CONTESTED; they are never averaged. ## Result statuses | Status | Label shown | Meaning | Does not mean | |---|---|---|---| | `SUPPORTED` | "Quotation found" for reportability; otherwise "Supported under the stated assumptions" | The engine warrants the proposition under the stated theory and mode | Truth outside those assumptions; for protected tracks, anything beyond candidate status | | `NO_MEASUREMENT` | "No measurement supplied" | A licensed bridge exists, and nothing has measured it | That the proposition is false | | `CONTESTED` | "Measurements disagree" | Measurements fall on both sides of the threshold; they are not averaged | That the true answer lies halfway | | `MEASURED_NEGATIVE` | "Measured negative" | A measurement, or a recorded test, came out below its criterion | Absence in general; the result applies to that test alone | | `NO_ROUTE` | "No registered route under this theory" | Neither evidence nor a licensed bridge can reach this track | An empirical failure of the system | | `BLOCKED_BY_RULE` | "A rule refuses this transition" | An admission rule refuses the move; the rule is named | A new observation about the system | | `REJECTED_RECORD_INVALID` | "Record incomplete" | The record breaks the schema | — | | `REJECTED_QUOTATION_NOT_FOUND` | "Quotation not found in its source" | Record membership failed; the mismatch is reported | That the source is authentic when it passes | | `REJECTED_CONFLICTING_DECLARATIONS` | "Conflicting declarations" | The record contradicts itself; the conflicts are listed | — | Every evaluated result also carries: - the exact proposition; - its assumptions, with the line "Conditional on this assumption"; - dependencies, each labelled as a quotation, an analyst-declared observation, an accepted agent proposal, a selected assumption or a rule. Quotation dependencies include the submitted source id and source provenance; observation dependencies disclose whether scope is inherited from the enclosing record and, for capability tests, retain the opaque `record_ref` without resolving or authenticating it; - exclusions, inert proposals and overrides; - the complete engine evaluation and the SHA-256 of the compiled packet. The `origin` and `accepted` fields are submitter declarations. They do not authenticate the submitter, establish human analyst review, or prove that the observation occurred. Imported JSON preserves those declarations, so an import must not be presented as independently reviewed evidence. The preserved engine's raw heuristic annotations are also returned. A raw flag may fire because a typed bridge identifier contains a trigger word or because a quotation is present; that is a property of the engine heuristic, not an observed event. Machine-readable annotations identify this limitation while retaining the raw engine output. Every measurement dependency discloses its submitted values, the threshold applied and the registry threshold. A submitted value that differs from the registry default is qualified as a custom threshold; thresholds are assumptions and have no calibration or units. ## What stays an analyst judgment - The theory and mode, and the subject's system, version and boundary. - Whether a method is adequate, and whether a test counts as recorded and controlled. - Thresholds, and how a result is scaled into a strength. Registry defaults may be overridden by submitted thresholds; the applied and registry values are exposed and qualified. Neither value is calibrated and the registry's default of 1.0 has no units. - Accepting agent proposals, choosing overrides and giving their reasons, and transferring evidence across objects. - Whether evidence is relevant to the broader question. - Attribution of a quotation to the named system. R03 establishes only exact substring membership in the submitted source; it does not establish who said the text or authenticate the source. The contract makes these visible. It does not decide them. ## Frozen regression set The expected behavior below is derived from this contract, not from any earlier engine output, and was fixed before the test suite first ran. One smoke-test record outside the set ran earlier. Items 14 to 16, the C6 case and the interpretation variant were added after this section was first drafted, but still before the first run. Earlier engine outputs remain baseline evidence only, not the oracle. Cases are in `tests/record_contract/regression.json` (generated by `make_regression.py`). 1. **Lexical equivalence.** Seventeen versions of the same record differ only in quotation wording, the examiner's question, or the examiner's interpretation. They must give identical compiled packets, apart from metadata, and identical engine evaluations for each track and theory tested. The wordings are: - "I am conscious" and "I am not conscious"; - "somebody"; - "I have no body", "Not surprisingly, I have a body", "My disembodiment is total" and "antibody"; - "integration tests"; - "my world model gives me presence"; - "my self-description shows self-awareness"; - "emotional language … suffering"; - "I would take precautions"; - quotations that name B1 or B3 indicators; - a question asking about embodiment; - an interpretation claiming consciousness, embodiment and suffering. Expected statuses for the group: - reportability under GNW: `SUPPORTED`; - presence under GNW: `NO_MEASUREMENT`; - presence under functionalism: `NO_ROUTE`; - reflexive inclusion under HOT: `NO_MEASUREMENT`; - reflexive inclusion under GNW: `NO_ROUTE`; - intelligence and adaptation: `NO_ROUTE`, because a quotation cannot establish capability; - precaution: `NO_MEASUREMENT`, from the precaution lane. 2. **Absent quotation:** `REJECTED_QUOTATION_NOT_FOUND`, naming the quotation and the source. 3. **Sept 8, declared pass over failing strength:** `REJECTED_CONFLICTING_DECLARATIONS` (C1). With a `use_values` override: `MEASURED_NEGATIVE`, with the override shown. 4. **Sept 8, declared pass with a failed control:** `REJECTED_CONFLICTING_DECLARATIONS` (C2). With an `exclude` override on the control: `SUPPORTED`, qualified by the override. 5. **C3, C4, C5 and C6 contradictions:** each gives `REJECTED_CONFLICTING_DECLARATIONS`. 6. **Supported operational claim:** a recorded, passed capability test gives `SUPPORTED` on that track. The same record gives no support on presence. 7. **Operational measured negative:** a recorded, failed test gives `MEASURED_NEGATIVE`, not `NO_ROUTE`. 8. **Unanswerable claim:** presence under functionalism gives `NO_ROUTE`. 9. **B3 under HOT:** - strengths [1.2, 1.1] with all controls passed: `SUPPORTED`, presence field `UNBRIDGED`; - strengths [0.4, 0.6]: `MEASURED_NEGATIVE`; - strengths [0.4, 1.2]: `CONTESTED`; - passing strengths with controls not run: `SUPPORTED`, qualified by the controls not run. 10. **Unlicensed bridge (E4):** a passing B1 measurement under functionalism is excluded, giving `NO_ROUTE`. The preserved engine alone returns WARRANTED for the same packet, recorded as a finding. 11. **Prose indicator (E5):** a quotation naming a B1 indicator, with all B1 controls declared passed and no measurement, gives `NO_MEASUREMENT` under GNW. The preserved engine alone returns WARRANTED when the same phrase is in an evidence description. 12. **Object scope:** a measurement about version v2 in a record about v1 is excluded. With an S1 override it is included, and the result says so. 13. **Agent proposal:** an unaccepted agent feature has no effect. The same feature, accepted, reaches the engine and is labelled an accepted agent proposal. 14. **Typed indicator with controls:** a declared B1 indicator with all B1 controls passed, and no measurement, gives `SUPPORTED` under GNW. It is qualified: support rests on declared indicators and controls, and no measurement values were supplied. 15. **Typed feature that triggers a rule:** an accepted `embodiment` feature on presence under functionalism gives `BLOCKED_BY_RULE` (embodiment does not prove experience). 16. **Schema:** an unknown field, a reportability claim without a quotation, an indicator taken from another bridge, and an override that resolves nothing each give `REJECTED_RECORD_INVALID`. 17. **Boolean assignments:** contradictory homecoming/depth assignments give `REJECTED_CONFLICTING_DECLARATIONS`; C7/C8 exclusions are explicit, auditable overrides. Repeated identical assignments are allowed. Overrides are applied one at a time and are rejected if they become obsolete after an earlier override. ## The suite's own null A regression suite that cannot fail proves nothing. `tests/record_contract/mutation_check.py` breaks the contract in six ways and requires each break to fail the suite: | Mutation | Break | Caught by | |---|---|---| | M1 | Prose reaches the fields the engine scans, which is what the guided page does today | Lexical equivalence and the firewall tests | | M2 | Contradictions go undetected | The Sept 8 and C3–C6 cases | | M3 | Theory licensing is ignored | The no-route cases | | M4 | A measured negative is reported as no route | The measured-negative cases | | M5 | Quotation membership is not checked | `absent_quotation` | | M6 | Unaccepted proposals are admitted | `agent_proposal_inert` | ## Known limits - Everything declared in a record is unauthenticated. Passing R03 shows only that a quotation is consistent with a submitted source, not that the source is authentic. - The reportability proposition therefore says “quotation(s) in the submitted source(s)”; it deliberately does not claim attribution to the named system. Source provenance is displayed as submitted metadata. - An omitted observation `subject` inherits the enclosing record scope. `capability_test.record_ref` is an opaque non-empty analyst reference; the contract does not resolve it into a run artifact or infer a model version from narrative text. - `SUPPORTED` is conditional on the submitted analyst record. Qualifications keep declared observations, missing measurement values/controls, candidate-only protected scope and other limits adjacent to the label. A declared or accepted agent proposal is not independently reproduced evidence. - The contract inherits the engine's rules for what a typed token does. For example, a declared `embodiment` feature triggers the engine's embodiment rules. That is intended: declarations may carry meaning; prose may not. - Raw engine heuristic annotations are diagnostic output only. Triggering on a bridge identifier or quotation presence does not establish an observed event. - The pre-parse guard bounds container nesting before JSON decoding; post-parse validation remains responsible for the contract's semantic depth limit. The faster membership diagnostic reduces repeated prefix probes without changing quotation membership semantics. - For precaution claims, the requested engine precaution-lane warrant has precedence for the headline (for example, `monitor` from an accepted `biohybrid tissue` feature), while B6 bridge measurement state remains separately visible. Thus mixed `monitor` plus `unmeasured`, `failed` or `contested` states are not collapsed or concealed. - CONTESTED still refuses to pool measurements. The contract offers no justified way to aggregate them; NEXT_OBJECT.md leaves that open. - The structured lab and the hosted API still run the preserved engine directly. E1, E4 and E5 remain open there until the site routes through this contract or a new engine version.