Conformance Process

FRAMING. Construction + Conformance = definitional pair (specification + matching test specification). Design-time for producer and verifier authors. At runtime a verifier applies those same rules while measuring: record tokens, including mismatch. That is not a reject gate that skips measurement, and it is not admission. Admission policy values are not a conformance target. This specification defines no tip-versus-last-beacon submit deadline.

Responsibility. Test-specification half of the Construction + Conformance definitional pair: yes/no rules, permanent negatives, and the one pack. Also the process for claiming an implementation matches that pack. Used by a producer or verifier implementer who wants that claim.

Source. Satoshi Hike 2.3 (tag spec-2.3.0). Section numbers are the specification section numbers:

16. Conformance

Informative. Summary. Conformance is per layer. Matching the one pack byte for byte, and reproducing every permanent negative as a non-match, are part of conformance. They are not the whole of it. Section 16.2 states the rest, including Rules I1–I6. The admission service is not a conformance target. Section 16.1 defines the conformance-small profile, and 16.2 the SDK requirements (Rules I1–I6).

Normative.

Conformance is stated separately for three layers. A layer does not take on another layer’s job.

  1. A conforming producer follows section 13 and emits the deterministic encoding of section 7.3 for every run that reaches I_17. It records evidence. It does not emit a verify record. It does not say accept, refuse, revoke, or held. A producer that pauses a leg for a post, a solve, an ask, a header or peer read, a log write, or a wall clock does not follow section 13 (Rule A6). A producer that withholds the object because of a clock-read failure or another transitory network condition does not follow section 13. Stage 0 has no path key in that encoding.
  2. A conforming verifier follows section 14 and outputs the verify record: measurements as integers and the section 4 tokens. The profile name and, under conformance-small, SAMPLE_BYTES, SLOT_BYTES, TERRAIN_BYTES, and STEPS_PER_LEG are verifier inputs. They appear on the section 14 verify record as measurement provenance. The profile is not absent from that record. The hike object gains no new field. It does not judge those measurements. It does not say accept, refuse, revoke, or held. It does not post a waypoint and it does not ask Bari for a path.
  3. An admission service is not a conformance target. Section 15 is policy for a relying party. Lever values (section 15.4) are policy and are not set by this file. They are not vectors. A service may run section 14 itself and may ignore a submitter-supplied verify record. Doing so does not make the service conform or fail to conform.

Sections 8–14 do not use pass, fail, reject, deny, or admit for the object or for a measurement. Those outcomes are not verifier outputs. The decisions accept, refuse, revoke, and held, and the states in section 15.2, are section 15 only.

Vectors. Conformance means Part A, the Hashcash rule of section 13.1, and the Bari paid rule of section 13.6. A producer or a verifier conforms when its outputs equal the published vectors of the one pack, spec/conformance/pack/, byte for byte, and when it reproduces every permanent negative as a non-match. The pack publishes the seed, the NL4 base words, the terrain digests, the §11.1 fold, the conformance-small leg, checkpoint, and waypoint bytes, one production-size leg, waypoint_equals_seed, the integer rate and anchor comparisons, the thorough-round index draw, the Hashcash challenge and digest for a stated origin and fee header, the Bari paid rule for current, before, after, and outside fee headers (including a wrong origin, and a display-order mismatch: a current, a before, and an after case each built with Bari’s tip hash reversed, each answered 402 under section 9), with the “after” and “wrong nBits” cases published separately for the live plane (mainnet target, including a retarget boundary) and the test plane (fixed synth nBits, section 9), each vector labelled with its plane, the unknown-kind record, and the sign-in wire (sign-in.json, sign-in-origins.json). It does not publish a hike-object encoding, a section 14 record, object_hex, or draw_bytes_hex.

Permanent negatives. The pack carries, and every SDK must reject as non-matching, at least the thirteen negatives below. Each negative is computed at the vector’s profile integers, for the vector’s public key and seed beacon, with the section 10.4 terrain and the section 11.1 step except where its entry says otherwise. A leg negative is the first leg of stage 0, from its Rule A2.2 start (the seed), and is published as legs_le_hex of that leg. A terrain negative is published as the SHA-256 of the whole terrain array. Each entry is a construction this file forbids; it is defined here only so that the pack can pin it as a non-match. The pack generator compares each negative with the honest value of the same vector and stops with an error when they are equal; QA then chooses other fixture inputs. A negative is never removed while the construction it guards stands.

  • slot_summary_fold, xor_accumulator_fold, xor_w_fold, s_plus_w_fold: the four folds that section 11.1 names. Leg negatives.
  • prefold_hoist: the fold that computes once per slot pre(i) = (sum over w of mix64(word(w) XOR w)) mod 2^64 and, on every step that reads slot i, uses S_folded = (pre(i) + S) mod 2^64 in place of the section 11.1 accumulator, then the section 11.1 seal. Leg negative. It is the per-slot summary that section 11.1 forbids: word(w) XOR w does not depend on S.
  • final_stage_hoist: the fold whose S_folded is x XOR (x >> 31), where x is the XOR, over every word of the slot, of mix64 applied to word(w) XOR S without its last line (the value y just before return y XOR (y >> 31) in section 10.1). Leg negative. It is the hoist that section 11.1 describes as informative. Its value equals an XOR accumulator of mix64(word(w) XOR S).
  • partial_slot_read: the section 11.1 fold over word 0 only of the slot each step reads. Leg negative.
  • partial_slot_read_2047: the section 11.1 fold over words 0 … WORDS_PER_SLOT − 2 of the slot each step reads, leaving out the last word. Under section 6 that is 2047 of the 2048 words. Leg negative.
  • one_lane_flip: the section 10.4 fill with the one-lane map of section 10.4 in place of the NL4 base word. Parents and the slot mix are unchanged. Terrain negative.
  • all4_kernel: the section 10.4 fill with the linear map of section 10.4 in place of the NL4 base word. Parents and the slot mix are unchanged. Terrain negative.
  • f3_shared_terrain: the first leg of stage 0 of the vector’s public key, from that key’s own start, run on the terrain of a second public key that the vector states, with the same seed beacon. Leg negative. The f3 in the name is not row F3 of section 19. This negative guards row F4, shared terrain.
  • cached_leg: the first leg of stage 0 in which a step that reads a slot already read earlier in the same leg reuses the S_folded of that earlier read instead of folding the slot with the current S. Leg negative. The vector’s leg reads at least one slot twice.
  • squeezed_seed_terrain: the section 10.4 fill with each of the four lanes replaced by the one 64-bit value P[0] XOR P[1] XOR P[2] XOR P[3], the squeeze that section 10.2 forbids. Terrain negative.

The vectors are language-agnostic. The sign-in wire vectors are not a section 14 record; matching them is not Part A conformance. A vector compares bytes, integers, and tokens. It does not grade a hike object as pass or fail. This pack does not publish section 15 states. Those states are not a conformance target. A section 14 record is defined by section 14. An unknown kind is the Rule A5 line: kind and kind_text only. A current object’s record carries every key section 14 requires, including shape_item, headers, paths, anchors, bookends, N, and S. The compact line that named only profile, shape, checkpoints, waypoints, leg_rate, six_leg, and anchors is not a conformance output. A conforming verifier outputs this section 14 record.

Precedence. This file governs, together with the pack. Where a published vector and a sentence of this file conflict, the conflict is a defect in this specification. It blocks release until a specification change settles which side is right. An implementer reports the conflict and does not pick a side. Where any SDK disagrees with this file or the pack, this file and the pack win and the SDK has a bug, whatever that SDK’s role as a reference implementation (section 16.2). No SDK output settles a conflict, and an SDK behaviour that skips work never becomes conforming because an SDK does it. The conformance runner may mark a vector known-defect until the specification change settles it.

spec/conformance/pack/ is the one pack. No other pack exists, and no file or sentence of this specification names another. Its files and the bytes they pin are listed in manifest.json and README.md in that directory. kat-small.json and test-3leg.json pin terrain digests and per-stage leg, checkpoint, and waypoint bytes at the profile integers in each file. legs_le_hex is the hexadecimal spelling of the little-endian wire bytes le64(leg_result). It is not the %016llx spelling of the integer. They do not pin object_hex, a section 14 record, bookends, or a six-leg draw. The pack is pinned by the SHA-256 of its manifest, recorded in sdk/SPEC_PIN beside the tag of this file (Rule I5). Renaming, adding, or removing a vector changes the pin. No git tag is cut, and no deployment cuts over to KIND v2.2-pcoc-object, until every SDK passes this pack and the production-size vectors. This conformance process document and its siblings under spec/ carry the Satoshi Hike 2.3 rules (tag spec-2.3.0). This file does not create that tag.

When two implementations follow this file at the production constants in section 6, they agree on the terrain bytes, each leg result, each checkpoint, the seed, and each waypoint W_1 … W_17. Given the same path-body bytes and the same headers, they agree on the deterministic encoding of the object.

Section 10 defines the seed, the seed preimage, the NL4 word, and every terrain byte. There is no fill pin. The checkpoint preimage and the waypoint preimage are defined in sections 11 and 12. The leg is defined in section 11. Path bytes on stages 1–17 are the checked body of the successful fetch in section 13.1, or the empty path bytes section 13.3 stores on path_skip or on not fetched by design. A verifier does not fetch those bytes again. Section 14.3 records skip, present, plant match or mismatch or not read or n/a, and d_g. Each verification draws its own six indices, as section 14.6 states, and records each recomputed leg result against the stored leg result.

16.1 Profile conformance-small

The profile in force is the section 6 constants, unless the verifier is running conformance-small. That profile may differ only in SAMPLE_BYTES, SLOT_BYTES, TERRAIN_BYTES, and STEPS_PER_LEG. The profile name and those four integers are verifier inputs. The hike object gains no new field. The verify record must state the profile, and must state SAMPLE_BYTES, SLOT_BYTES, TERRAIN_BYTES, and STEPS_PER_LEG when the profile is conformance-small. A live object still carries the section 6 size fields. When the profile name is conformance-small, all four integers are required inputs. The verifier does not substitute the section 6 values for an omitted integer. It does not change KIND. A verify CLI that passes --profile conformance-small without all four integers is a usage error, exit code 2. This file assigns no default integers to that name. The record states the four integers it was given.

The profile may set only these section 6 parameters:

Parameter Rule ID Why it may shrink
SAMPLE_BYTES P6.5 It is the terrain-sample limb of every checkpoint preimage.
SLOT_BYTES P6.1 It is the slot the step reads and the slot-sample limb of every waypoint preimage.
TERRAIN_BYTES P6.3 It is the terrain fill.
STEPS_PER_LEG P6.7 It is the number of steps in one leg.

WORDS_PER_SLOT, N_SLOTS, and OFFSET_MODULUS are not free integers under the profile. They stay the section 6 formulas (P6.23, P6.24, P6.25) applied to the profile values. SLOT_BYTES is at least 8, a multiple of 8, and at most the section 6 value. STEPS_PER_LEG is at least 1 and at most the section 6 value. SAMPLE_BYTES is at least 1 and at most the section 6 value. TERRAIN_BYTES is at most the section 6 value, an exact multiple of SLOT_BYTES, and at least SAMPLE_BYTES, so OFFSET_MODULUS stays at least 1. The step folds every word of the slot by §11.1: word(w) XOR S, then wrapping addition of mix64, for w = 0 … WORDS_PER_SLOT − 1. There is no w term. Equal words do not cancel under addition. The checkpoint preimage stays 32 + 32 + SAMPLE_BYTES + 8 bytes. The waypoint preimage stays 32 + SLOT_BYTES + 32 + 32 bytes. Hash order does not change.

The profile does not set STAGES, HASH_BYTES, LEG_RESULT_BYTES, PUBLIC_KEY_BYTES, BEACON_BYTES, SEAL_DOMAIN, KIND, FILL, or the mix constants P6.17–P6.22. It does not set a domain label on the seed. It does not set the Hashcash difficulty (P13.5), the ask window (P13.2), or the six-leg draw count (A4.4.1). A thread pool is not required (A4.4.4). Eighteen stages stay eighteen. Waypoint indices, W_17, and the cut-off stay where section 13 puts them.

Legs. legs_per_stage is vector fixture metadata, not a section 6 constant. It is a list of 18 integers, one per stage, each at least 1. Producer KATs use it: the rig’s tip schedule follows that list, and the vector’s object stores those counts as leg_count. Production produce does not read legs_per_stage. Principle 9 still holds: there is no maximum leg count on a live object. A vector that exercises Rule A4.4 needs at least 6 legs in the hike, because fewer than 6 leaves six_leg not defined. The Rule A4.4 draw count stays 6. The thorough-round draw vector is the section 15.5 draw and draws D indices (Thorough rounds, below).

Thorough rounds. The thorough-round index draw vector states its own thorough_rounds, as vector fixture metadata like legs_per_stage. That value is not a policy value, it is not read from section 15.4, and it sets no policy. The vector draws D = 6 · thorough_rounds indices under section 15.5 from its own byte source (Draw bytes, below), read from the first byte. A vector that publishes both a six-leg draw and a thorough draw, or draws for more than one leg total, reads each draw from the first byte of its byte source. No draw continues where another stopped.

Anchor comparison. The integer anchor vector gives a stored stage height H and a candidate inclusion height. Its answer is anchored when the inclusion height is H plus one of ANCHOR_WINDOW_OFFSETS, and not anchored otherwise, as if that header were an interrupt stored on the object and its plant comparison were match. It does not test those two conditions. Rule A4.5 still requires both on a real object. The integer anchor vector is not the anchor-window vector of sections 9 and 14.4, which is a full object.

Draw bytes. Injected draw bytes are rig-only, for a deterministic draw vector: the Rule A4.4 six-leg draw, or the section 15.5 thorough-round draw. A published draw vector names its byte source as a SHA-256 chain from a stated ASCII label: b_0 = SHA-256(label) and b_(n+1) = SHA-256(b_n), concatenated in that order. The pack publishes the label, not the bytes. The rig expands the label into that chain and supplies the bytes in order as the section 14.6 byte source. The verifier consumes them in that order and does not hash them again. They are never a production input. Production verify reads the operating-system CSPRNG. The Rule A4.4 draw count stays 6; the thorough-round draw vector draws D indices (Thorough rounds, above). Fewer than six legs leaves the draw unconsumed and six_leg not defined.

Wire. The hike object gains no new field. Its size fields stay slot_bytes, n_slots, sample_bytes, and steps_per_leg. Under conformance-small those fields hold the verifier’s four integers, and n_slots is the formula. shape_item includes constant when a field differs from the profile in force (A4.1.2). A live producer emits section 6 only.

Rig checks. Whether the six recomputes run together is Rule A4.4.4. A rig does not add a required pool. A rig may also check the producer rules in this file: no leg is paused (Rule A6), the object closes at I_17 with no collection window (section 13.1), exactly one resend after a transport failure (P13.13), and no stop on a failed tip read or a stalled header source (P9.12). Rig-only inputs, not specification parameters, are now_unix_s, nonce_store_start_unix_s (a store restart or flush, and each worker’s process start), the issuing nonce, phase timing, the local mirror contents, a Bari mock, a header-source mock and its clock, injected draw bytes, and the block-height (tip) clock.

The same profile integers and the same inputs produce the same bytes. The profile does not relax an INVARIANT. QA chooses the integers in the published vectors. This section does not fix a second set of production numbers.

16.2 Implementation requirements

Normative.

Rule I1. SDKs are the reference implementations

The per-language SDKs under sdk/ (Rust, Go, Java, C, and any SDK added under these rules) are the reference implementations. There is no other reference tree. Bari, the admission service, and the apps use an SDK; they do not carry their own copy of the construction or of the Hashcash rule. An SDK is a reference implementation only while it passes the whole pack. This file and the pack win over every SDK (section 16, Precedence).

Rule I2. Interfaces

Each SDK exposes at least: the seed and terrain fill (section 10); the leg and the step (section 11); the checkpoint (section 11.4); the waypoint (section 12.2); the Hashcash challenge, digest, and solve (section 13.1); the Bari paid-rule check (Rule BR1); the object encode and decode (section 7.3); the section 14 verify record, including Rule A5; the section 14.6 draw and the section 15.5 thorough draw, each from a supplied byte source; the Rule B2 integer comparison; and the integer anchor comparison (section 16.1, Anchor comparison). Each public function names the section it implements. Its behaviour is that section. An SDK’s own prose does not add a rule.

Rule I3. Producer model

An SDK producer runs the walk on its own thread or threads and runs every post, solve, ask, header-source read, Bari exchange, and log write as asynchronous work (Rule A6). The walk reads the tip through a call that returns at once. No SDK producer sleeps, waits on I/O, takes a lock that I/O holds, or syncs a file on the walk path. A failure of asynchronous work becomes an alert record or a logged miss; it never propagates into the walk. Only a producer failure or explicit cancellation ends a run before I_17. The header source detects a stalled or lagging peer and recovers on its own, asynchronously; a stall never pauses a leg.

Rule I4. Tests

Each SDK runs, on every change: the whole pack; every permanent negative as a non-match; the production-size leg vector; a producer test that injects a stalled header source, a failed tip read, a Bari that never answers, a Bari that answers 503, and a log that cannot be written, and checks that legs keep running, that exactly one resend is made after a transport failure, and that the object closes at I_17; a header-source test, on a mock clock, with one silent peer among HEADER_PEERS_MIN or more, which checks that the silent peer is replaced once HEADER_PEER_SILENCE_SECONDS have passed after another peer announced a header and not before, that a gap in which no peer announces a header replaces no peer, that a fall below HEADER_PEERS_MIN writes a header_peers_low alert and reconnects asynchronously, and that legs keep running and the object closes at I_17 throughout; and a test that a paid waypoint on each of the current, before, and after headers is accepted by its Bari paid-rule check, and that any other POST is answered 402, including a fee header that matches Bari’s tip only when one side is reversed to display order (section 9, P9.17); and, for an SDK that implements the section 15.1 Sign-in door, a nonce-store test on a mock clock in three cases: (a) a submission consumes its nonce, the single-process door restarts while that challenge’s window is still open and drops every row, and the same submission is replayed; (b) the shared nonce-row store is flushed with no process restart, while the window is open, and the same submission is replayed; (c) two door workers with different process starts share one store and receive the same challenge. The test checks that each replay is client malformed, consumes nothing, and runs no policy; that a challenge issued at or after nonce_store_start_unix_s + challenge_clock_skew_seconds is accepted and one issued earlier is malformed; and that both workers in (c) use the one store start and give the same answer for the same challenge.

Rule I5. Versioning and pin

An SDK version is MAJOR.MINOR.PATCH, with MAJOR.MINOR equal to this file’s version, 2.3. A PATCH release does not change any output byte. Each SDK reads sdk/SPEC_PIN, which names the tag of this file and the SHA-256 of the pack manifest, and its test fails when the pack it runs does not match that pin. SDK tags are sdk-<language>-v2.3.<patch>. This file’s tag is spec-2.3.0. When the SDKs move to 2.3, sdk/SPEC_PIN names spec-2.3.0. Until then the SDKs stay at 2.2, which produces and verifies the same bytes. An admission service whose pin is spec-2.3.0 reads a policy file whose spec is "2.2" or "2.3" (section 15.4). Bari and the admission service depend on the Rust SDK at such a tag or by path in the same tree; they do not pin any other tag.

Rule I6. Cost

No SDK implements a cache, table, summary, partial read, or any other shortcut in the terrain, the leg, the step, or the fold (section 11.1). Every step reads and folds the full slot of SLOT_BYTES. Where the host provides SHA-256 instructions, the SDK uses them (section 11.1). An SDK change that raises the measured leg rate at unchanged hardware is a suspected break. It is reviewed against the permanent negatives before release. A reviewed SIMD kernel that loads all SLOT_BYTES bytes of the selected slot and mixes every word may be released. Processing several words of one slot at once (SIMD, or compiler or JIT vectorisation) is the section 11.1 loop and is not an efficiency or a speed-up in the sense of section 11.1, provided that on every step all SLOT_BYTES bytes of the selected slot (16 KiB under the section 6 constants) are loaded, each of the WORDS_PER_SLOT words is mixed with the current S by mix64 with MIX_ADD, and the sum is the section 11.1 wrapping sum. Such a kernel’s rate gain is reported under this rule with equality, mutation and load evidence, and after that review it may be released. Skipping, caching, summarising or reusing any word or value across steps remains a break.

17. Clarifications

Informative.

The items below restate parts of the construction in the sections named here. This section does not add a second construction.

17.1 Waypoint path fetch

Section 13.1 posts W_1 … W_17. It does not post the seed. Asks are for W_1 … W_16 under section 13.1. W_17 is posted and is not asked. No ask is made after the close. Asks are asynchronous, and the object closes at I_17 with the checked paths that have arrived. Test and live use that one rule. On stages 1–17 the field is path, a CBOR byte string, in the key order of section 7.3. Stage 0 has no path key. Those bytes are not an input to section 11.4 or section 12.2. A POST that does not succeed, and an ask that is not a checked 200, are a miss. Produce stores empty bytes and writes path_skip <g> for W_1 … W_16, and continues. It does not withhold the object. W_17 writes not fetched by design 17. A skip is a measurement (Rule A4.5). Rule B4 judges it: anchored_total ≥ min_anchored_paths, wherever those waypoints sit. A present path is measured in section 14.3, including CanonicalPathBody validate_for and the chain bind. Verify does not GET the path again.

17.2 Portable-index height fetch during verify

Verify reads the portable index. For each stored header, including last_interrupt, it GETs {index-url}/index/{height} and records index_comparison and T under Rule A4.2. That header GET is separate from a plant GET of the same URL. A body with no usable header is header not read and can still be plant match. T is header.time, Bitcoin nTime, Unix seconds, only when index_comparison is match. Otherwise T is not read. header.time is the portable index’s record of nTime for the block whose hash is header.hash. index_comparison uses hash and height only. It does not use network. An unsuccessful header read is not read. A hash or height that differs, when the read returned them, is mismatch, and T is not read. That record is part of Rule A4.2. The admission service applies section 15 to the record. Verify does not GET an HTTP tip. Verify does not Observe.

A document whose network is synthetic can still record match on the plant comparison. A header that matches that document is not a mismatch for that network. A match against a synthetic document is not a mainnet fact.

17.3 Path and chain bind

Section 14.3 records plant match, mismatch, or not read for each present path among W_1 … W_16. The inclusion-height GET is made only when that height is in the window and that header is a stored interrupt. Otherwise plant is not read and the index is not read for that path. That not-issued not read is not a missing GET under Rule A4.11. not read also means an issued read that does not return a document. A document that was read and has no plant for that block, or whose plants do not match, or whose network is neither main nor synthetic, is mismatch. A document with no header member can still be plant match. anchored requires the inclusion height in the section 13.1 window, that header stored on the object as an interrupt, and plant match. Plant match alone is not enough. On mismatch and on not read, d_g is not defined. claimed_block is the path body’s block_hash and block_height when those fields can be read, otherwise not defined. The measurement is distinct from Rule A4.2. A skip is not a plant comparison. Verify does not GET the path from Bari again. The pack field index_reads lists only those issued plant heights.

A match on a document whose network is synthetic is not a mainnet fact.

17.4 Several words of one slot at once

Section 11.1 folds the WORDS_PER_SLOT words of the selected slot with a wrapping sum mod 2^64. That sum is associative and commutative, so a kernel that loads all SLOT_BYTES bytes of the slot (16 KiB under the section 6 constants) on every step and mixes several of its words with the current S at once, by SIMD or by compiler or JIT vectorisation, gives the same S_folded, seal, leg, checkpoint, and waypoint bytes as the one-word-at-a-time loop. It is the section 11.1 loop, not an efficiency (Rule I6). Every step still loads every byte of the slot and mixes every word with that step’s S. A kernel that skips, caches, summarises, or reuses any word or value across steps is a break whatever its output on a vector, and the permanent negatives of section 16 stay non-matching.

17.5 Floor baseline and the low-end host

Informative. This subsection adds no rule. Section 11.1’s informative paragraph calls commodity hardware with SHA-256 instructions, for example an AMD Ryzen 5 5600H, “the baseline that sets the floor and the gate policy.” Section 15.5 names the low end of the owned hosts a measurement covers: an Intel Core i7-10610U laptop, which has no SHA-NI. Section 15.5 is the measuring method. It says that method informs the value a policy sets, and that it does not set one. Section 11.1’s paragraph does not set a lever value either. The two sentences name two hosts. They do not set two lever values. Every host runs the same section 11.1 step.

19. Fixed issues — do not reintroduce

Normative. This is the only section of this file that names an earlier construction or an earlier defect. Each entry names a defect class, why it was a defect, and the rule of this file that forbids it. An implementation, a pack vector, or a later revision of this file that reintroduces any of them does not conform. An entry is never removed while the rule it points to stands. The labels F1–F15 are list positions, not rule IDs.

# Defect class Why it was a defect Rule that forbids it
F1 State-free slot fold (“FatSlot”): S_folded = S XOR (XOR over w of (word(w) XOR w)). The inner XOR does not depend on the state, so one 8-byte value per slot stands in for the 16 KiB slot. A table replaces the slot read and the per-step cost collapses. Section 11.1 fold acc = (acc + mix64(word(w) XOR S)) mod 2^64; Rule I6; permanent negative slot_summary_fold (section 16).
F2 Precomputable step term word(w) XOR w. The term does not depend on the state, so it can be computed once per slot and reused on every visit. Section 11.1: the per-word input is word(w) XOR S, with no w term; negatives xor_w_fold, s_plus_w_fold, prefold_hoist.
F3 XOR accumulator fold acc = acc XOR mix64(…) (xorshift linearity). The XOR accumulator is linear across words and across states, so per-slot work separates from the state and a summary can stand in for the read. Section 11.1 wrapping-add fold; negatives xor_accumulator_fold, final_stage_hoist (section 16).
F4 Partial slot reads, lane and seed shortcuts, shared or cached terrain. Each lets a producer skip bytes or reuse work and so pay less than the full slot every step. Sections 10 and 11.1; Rule I6; negatives partial_slot_read, partial_slot_read_2047, one_lane_flip, all4_kernel, f3_shared_terrain, cached_leg, and squeezed_seed_terrain (section 16).
F5 Waypoint post before the next stage’s legs (blocking post). The walk waited on Bari and on the Hashcash solve, so legs paused at every boundary and the measured rate fell. Rule A1.4 (post is asynchronous); Rule A6; Rule I3.
F6 The 15–45 s wait before each path ask. It ran inside the walk and cost about 1,000 s per hike (7.6–8 %). Rates and the floor measured with it understate an honest producer. Section 13.1 (an ask is sent when due, with no wait); P13.7; Rule A6; section 15.5 (re-measure the floor).
F7 One-sided tip-retry reject at Bari. Bari took a fee only on its own tip, retried the previous tip, and rejected a fee on a header one ahead as final. An honest producer that saw a block first lost the plant. Rule BR1 (current, before, or after block, plain 402 otherwise); P13.13 (one background resend after a transport failure).
F8 Single-peer header intake. The producer kept one gossip peer and had no stale-peer check. One silent peer blinded it for 10–20 minutes, and co-located producers failed together. Section 9 Header source; P9.16; P9.12; Rule A6.
F9 Bari pinned to a separate v2.0 SDK tag. Bari’s Hashcash, leaf, and path code came from a different construction than the producers it served, so the two could disagree. Rule I1 (Bari uses an SDK); Rule I5 (one cut tag and sdk/SPEC_PIN).
F10 A clock-read failure, reorg, or stalled source stopping the run or withholding the object. A network event became a lost hike, and reorg handling invited producer-side judgment. P9.12; Rule A6; section 13 (producers ignore reorgs).
F11 A collection window or wait after the final block. It delayed the close and made the object depend on wall-clock policy inside production. P13.9 (close at I_17, at once).
F12 Accepting objects of another kind, or more than one pack. Mixed kinds and packs let two SDKs both claim conformance with different bytes. Rule A5 and reason unknown_kind; section 16 (one pack, sdk/SPEC_PIN).
F13 Policy values written as rules of this file. A chosen number stated as normative could not change without a new specification, and readers took it for part of the construction. Section 15.4 (levers with ranges; values belong to a policy).
F14 Operator re-open of a refused pair. A hand re-open had no state-table row, no deciding tip, and no log rule. It was a discretionary override of the held budgets, open to pressure through a claimed outage. Section 15.2 (refused is closed for the pair under that policy_version: return that outcome, no new cycle); section 15.3 Held bound (the budgets do not reset).
F15 Unbounded hold (“a held PCOC is not refused”). A hold with no finite budget, or a block budget that waited for a tip that never came, kept a submission held for ever: never settled, and the gate’s work never ended. Section 15.3 Held bound (reverify_max_attempts and max_held_blocks are finite integers ≥ 1 that the policy must set; max_held_blocks applies to every hold and starts at the first successful tip read; held_retry_seconds retries without waiting for a tip advance; reason held_bound).

Republished from pcoc 1b9f632 (spec/ six-doc pack; same bytes at e8030ba). Raw markdown.