Skip to content

Decisions index

DECISIONS.md in the repository is append-only: a record that a later record supersedes, corrects or extends keeps its original text. This page, generated from the log at every docs build, lists each record with the later records that cite it and the relation their wording names, so a reader can tell what still stands before relying on it. A citation is a pointer to read, not a verdict; a record cited by nothing later is, as far as the log knows, current.

Record Decision Cited by later records
D1 One Kafka Streams application per declared process
D2 A channel is identified by (topic ID, partition) D21, D26, D33
D3 Causal metadata wire format: one reserved header, strict canonical binary D94, D98 (supersedes)
D4 Dependencies are summarized as one maximum position per channel D52 (corrects), D115
D5 Deliverability: settled frontier from fed-or-never plus the hold-back buffer D6, D78, D102, D104, D115
D6 The host's read-position report is the feed itself plus committed group offsets D26, D35 (corrects), D115 (supersedes)
D7 An internal wall-clock punctuator ingests facts D20, D44, D115 (supersedes)
D8 Failing closed stops the whole process, by exception D94
D9 auto.offset.reset=none, with initial positions pre-committed while the group is empty D25, D26, D74, D76, D104, D109, D115 (narrows)
D10 Re-feeds below the session floor are dropped; contradictions within an execution fail closed D25, D26, D36, D45, D78 (narrows), D91, D115
D11 Parsley owns the KafkaStreams lifecycle; nothing weaker is constructible D111
D12 The seam: Effects handle(Delivery, StateReader); reads live, writes returned D26, D60
D13 An application payload its own serde cannot decode fails the step D62 (implements), D81
D14 Application stores are byte stores; serdes apply at the seam; changelog-name serde scoping
D15 Emissions inherit the delivered message's timestamp and default partitioning D111
D16 Deterministic drain: channels in total order, to fixpoint
D17 Ordering state: one reserved store; held bodies persisted only if still held at step end D57, D102, D106, D110
D18 Reserved prefixes: parsley. for headers, __parsley. for stores D56
D19 Toolchain: Kafka clients/Streams 3.9.1, Java 21, Maven, JUnit 5 D57, D69 (supersedes), D70 (supersedes)
D20 The facts interval is configurable, one second by default D115 (supersedes)
D21 A deleted topic settles its remaining positions; dead incarnations are vacuous D26, D46 (corrects), D93, D105, D115
D22 Log starts are attributed to a topic ID only under a describe-after-query identity check D26, D50, D79, D107, D115 (supersedes)
D23 Self-dependency is impossible by construction; adversarial self-deps hold forever D26, D105
D24 A step is the host's transaction; several deliveries may share one step
D25 Structural 16 mechanics: refusal by held-scan; leave/rejoin by retained state D74, D106
D26 Assumptions taken, and what breaks if one proves false D46, D78, D104 (corrects), D115 (corrects)
D27 Naming: candidate.parsley:parsley, packages candidate.parsley.* D64 (corrects)
D28 Emissions always carry the causes header, even when empty
D29 Null keys and values bypass serdes; tombstones pass through
D30 Diagnostics: the decision unit reports its blockers D103
D31 A joining channel starts above the delivered causal past D41, D42, D74, D102, D105, D106
D32 A channel is declared dead only after consecutive confirming rounds D40 (corrects), D44 (supersedes), D115 (supersedes)
D33 Topic names are bound to channel identity in ordering state; recreation refuses D36, D44, D47, D76 (reverses), D115
D34 No deliveries from within processor initialisation
D35 A read_committed probe settles trailing never-yielding runs; corrects D6 D78, D107 (corrects), D115 (supersedes)
D36 When prior state exists, missing group offsets restart from earliest D48, D74 (corrects), D111, D115 (narrows)
D37 Exception handlers are unoverridable configuration D51 (extends), D80 (extends)
D38 The runtime refuses stranded held messages by reading the changelog D57
D39 Received topics may have unequal partition counts
D40 Correction to D32's blast-radius claim D44 (corrects), D75, D115 (supersedes)
D41 The simulation oracle observes the feed; owed delivery is excused only by ground-truth delivered past
D42 The oracle bounds expression from above, judged at send time
D43 The generator reaches refusals; the harness survives them; catch margins are asserted per mode D112, D115
D44 Channel death needs corroboration; recreation is affirmative; the debounce is time-based D50, D75 (corrects), D78, D82, D84, D85 (extends), D89, D112, D115 (supersedes)
D45 An in-execution feed regression fails closed, wherever it lies relative to the session floor D77, D115
D46 A dead channel with undelivered held messages fails the process closed; corrects D21 D104, D115
D47 The bootstrap scan diagnoses identity change before judging removal
D48 Initial positions are committed through group membership, never by admin alteration D50, D79, D80, D86, D108 (closes)
D49 A task-width change against prior state is refused at start; names the Streams width validation D59
D50 Test seams for the bootstrap and facts source: real broker, phase hooks, injected clock, overridable describe
D51 Client interceptors and the timestamp extractor join the unoverridable set; extends D37 D80 (extends)
D52 A metadata budget in bytes, enforced on receipt and on emission; corrects D4's attribution D75, D93, D98 (supersedes), D115
D53 Frontier size is logged every facts round and surfaced at 80% of budget D90, D103, D115
D54 Position facts are gathered on one background thread; applied on the stream thread D74, D107, D115 (supersedes)
D55 Per-process status: state plus refusal reason, readable programmatically D59, D72, D73, D77, D92, D103 (resolves), D109, D111
D56 The seam's header view is application headers only; the reserved refusal names its reason D73, D87
D57 The ordering store's changelog requests logging and compaction explicitly D110
D58 Declared topic names must stay clear of the runtime's namespace
D59 Partition expansion is handled by restart; mid-run it gets a parsley diagnosis D109
D60 StateReader keeps point lookups only; enumeration stays out of v1
D61 Naming: the wrong-edit hazard is fixed; mechanical enforcement is deferred, recorded as a deviation
D62 Emissions are matched to the declared send set by topic name; the emission's Channel supplies the serdes D73 (supersedes)
D63 close() releases every resource, each step isolated and bounded D109
D64 Real coordinates: io.github.tobyjamesclements:parsley, packages io.github.tobyjamesclements.parsley.* (corrects D27) D99
D65 The mutation gate's skip flag is bound to a declared property D67 (supersedes)
D66 The mutation gate covers the core and the API, not the Kafka adapter D67 (supersedes)
D67 No mutation gate; the three gaps it found are recorded here instead (supersedes D65, D66) D106, D112
D68 kafka-metadata:test dropped; the rest of the broker test stack is load-bearing
D69 Kafka 3.9.2 (supersedes D19's version pin) D70 (supersedes)
D70 Kafka 4.3.1 (supersedes D69 and D19's pin) D71 (amends)
D71 Avro dropped from the test dependencies (amends D70)
D72 Names applied at vendoring (implements ASSESSMENT §5.2's decide-now) D77
D73 The api/ surface validates at declaration; the send seam resolves the declared channel by name (supersedes D62's serde-supply and duplicate-sends choices; resolves ASSESSMENT §1.14 and §1.15's send-set bullet) D81 (extends)
D74 Re-established read positions are checked against durable coverage; corrects D36's "never lossy" D104, D105, D112, D115 (narrows)
D75 A nameless topic id is never confirmed dead; corrects D44's four-fold window D84, D85 (extends), D89, D115 (supersedes)
D76 Lost ordering state under surviving Streams offsets refuses at start D79, D82, D84 (extends), D102, D114
D77 A report/feed contradiction has its own reason; OUT_OF_ORDER_FEED is feed order alone D78, D91, D93, D103, D106, D115 (narrows)
D78 Compacted received topics are an Assumption 10 reliance; the probe residual is recorded D115 (supersedes)
D79 Read-path hardenings: stable bootstrap reads, true-end changelog scan, offsets inside the confirmed window D86 (extends), D92
D80 The membership protocol joins the unoverridable set; extends D37/D51, and the promised revisit
D81 Seam and runtime diagnoses name their conditions; extends D73's taxonomy D92, D94, D95, D98, D115
D82 Hand-built consumers are pinned against mutating the cluster D88 (corrects), D92
D83 The reserved zero topic ID is undecodable metadata; the facts round tolerates unanswerable ids D88, D92, D95, D105 (extends), D113
D84 Prior state is keyed on ordering records, and prior-state describes are corroborated; extends D76 D88 (corrects), D96, D102, D113 (extends), D115
D85 Verdict windows require observed continuity; recreation is debounced; contradicted verdicts are rescinded (extends D44/D75) D88 (corrects), D115 (corrects)
D86 A partially-covering stable listing is retried before the group join; extends D79 D92, D96, D97
D87 Seam and configuration minors from the kafka-layer audit, in one sweep D88 (corrects), D95, D115
D88 The audit fixes, reviewed adversarially; corrections to D82, D84, D85 and D87 D96, D105, D107 (implements), D115 (narrows)
D89 The eviction horizon is pinned by scripted-round evidence; name learning extracted as a seam D95, D97 (corrects), D115
D90 The 80%-of-budget warning is pinned through a latch seam plus one stderr-capture wiring test D97
D91 Mid-run supersession is pinned structurally over ProcessEngine, not through the sim harness D112, D114, D115
D92 ParsleyRuntime's diagnosis, changelog-read and identity-floor behaviours get unit seams; pins issue #95's gaps E–G D95, D96 (extends), D97 (corrects), D112
D93 The engine's error sites are pinned at reason-and-message level; the per-message budget gate is discriminated by raw length D98
D94 Codec refusal diagnoses are pinned message-level; the position floor is pinned at the value objects D100
D95 The processor's refusal sites, the bootstrap join wait and the facts round's abort paths get direct pins D97 (corrects)
D96 Start-path refusal decisions are pinned through scripted functional seams; extends D92 into the determination and recheck loops D97 (corrects)
D97 Review corrections to the D89–D96 pins: two trials that did not discriminate, seam waits parameterized, wiring gaps closed, two claims narrowed (corrects D89, D92, D95, D96)
D98 Causes wire format: entries grouped by topic id, varint structural fields, fixed-width positions (supersedes D3's value grammar and D52's affine-size check) D99 (retires), D101 (supersedes), D102, D106
D99 Issue #96's session companion lands as its own package, session, over the public surface D100 (extends)
D100 Review hardenings to the session companion: compile-checked coverage exhaustiveness, identity merges, and shared fences (extends D99)
D101 The grouped grammar releases as version byte 0x01 (supersedes D98's renumbering rejection)
D102 Hold-back memory is bounded by the heads, a flush costs the holds it writes, and the emission header is encoded once per frontier change D105, D106, D110, D114, D115
D103 Each task publishes its delivery state, and status() carries it (fulfils D53's promise) D107, D111, D114, D115
D104 Retention crossing a held message fails the holder closed; the log-start check runs against the settled position (corrects D26's Assumption 10 line; the retention dual of D46) D112, D115 (corrects)
D105 The reserved maximum position is undecodable metadata and untrusted state (wire-format constraint 7; extends D83)
D106 Review pins over the core: D67's gaps closed, the emission header pinned byte for byte, the simulator's timestamps decorrelated from positions D112
D107 A facts round's tail is watched time; the probe is batched over the channels held heads wait on; the seed round does not probe (implements D88's spelling, whose pin did not cover the round tail; corrects D35's cost claim) D115 (corrects)
D108 A concurrent cold start waits for other instances' bootstrap members and replaces a refused stream thread (closes D48's residual S1)
D109 Substrate-detected stops that recur identically carry their reason; start() says what it returns into; close() is bounded on every leg D111, D115
D110 The ordering store is cached, and the bootstrap view keeps a held message's presence rather than its body
D111 The runtime can be waited on, an emission may carry its own timestamp, and the seam's documentation says what the code does D114 (narrows), D115
D112 Five pins a mutation trial showed the suite lacked, and the sabotage mode D91 recorded as missing
D113 Declared-topic resolution corroborates an unknown-topic answer before refusing (extends D84) D115
D114 Runbooks: what an operator does when a process fails closed, reason by reason; the gaps the runbooks expose are recorded, not closed
D115 The facts round is removed: a cause names a committed record, receipt is the only liveness input, retention is the fetch's to refuse, identity is checked once per task initialisation (wire-format constraint 8; supersedes D6, D7, D20, D22, D32, D35, D40, D44, D54, D75, D78, D85, D89, D91, D104, D107; narrows D9, D36, D74, D77, D88; corrects D26's Assumption 15 line; amends SPEC Liveness 3, Structural 13 and 15, Host obligation 2, Assumptions 13, 15 and 17)

At a glance

115 records. Named as superseded or reversed by a later record: D3, D6, D7, D19, D20, D22, D32, D33, D35, D40, D44, D52, D54, D62, D65, D66, D69, D75, D78, D98. Named as corrected, refuted or amended in part: D4, D21, D26, D27, D36, D70, D82, D84, D85, D87, D89, D92, D95, D96, D104, D107. Every other citation is an extension or a reference; read the citing record to see which.