Skip to content

docs(stovepipe): record stage RFC, aligned with the shipped implementation - #394

Open
mnoah1 wants to merge 4 commits into
mainfrom
mnoah1/record-step
Open

docs(stovepipe): record stage RFC, aligned with the shipped implementation#394
mnoah1 wants to merge 4 commits into
mainfrom
mnoah1/record-step

Conversation

@mnoah1

@mnoah1 mnoah1 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Updating record step doc to align with current implementation (now mostly implemented through phase 1), and forward looking plans for Hooks and future phases.

@mnoah1
mnoah1 marked this pull request as ready for review July 16, 2026 19:33
@mnoah1
mnoah1 requested review from a team, behinddwalls and sbalabanov as code owners July 16, 2026 19:33
Comment thread doc/rfc/stovepipe/steps/record.md Outdated
Comment thread doc/rfc/stovepipe/steps/record.md Outdated
Comment thread doc/rfc/stovepipe/steps/record.md Outdated
@mnoah1
mnoah1 force-pushed the mnoah1/record-step branch 2 times, most recently from 4dc7628 to 7b28df2 Compare August 4, 2026 20:22
Comment thread doc/rfc/stovepipe/steps/record.md Outdated
| `Project` | Empty for the whole repository; stable project id for Phase 2 |
| `Degree` | Health degree in the closed interval `[0, 1]`; `0` is green and `1` is fully broken |
| `RequestID` | Request that established the fact |
| `CreatedAt` | Millisecond timestamp at which the fact was first recorded |

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts on timestamp? We don't track timestamps elsewhere in the system but for these more long-term persisted facts, do we want to maintain some kind of timestamped history?

Comment thread doc/rfc/stovepipe/steps/record.md Outdated

A fact is written only when the request reaches a `succeeded` or `failed` verdict. A `cancelled` build is acked with no fact recorded. Callers gating deployments treat an absent fact as not green.

The fail-closed path also produces no fact, as the DLQ reconciler forces `failed` and never publishes to `record`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think never publishes to record holds when the fail-close originates in build_dlq. if build ack keeps failing, once retry_count hits MaxAttempts, the subscriber itself moves it to the DLQ, leaving one or more live poll chains behind in buildsignal step, and publishRecord fires anyway, record then writes a degree-1 fact regardless of the build result.

@mnoah1
mnoah1 force-pushed the mnoah1/record-step branch from 7b28df2 to 2f229dd Compare August 13, 2026 15:58
@mnoah1 mnoah1 changed the title docs(rfc): stovepipe record step design docs(stovepipe): record stage RFC, aligned with the shipped implementation Aug 13, 2026
mnoah1 added 4 commits August 13, 2026 16:11
…mework

The record stage landed in #555 while this doc still read as a proposal,
so the RFC described a design rather than the code. Re-frames it as-built
and corrects the contract details that drifted: ValidationFact carries no
Queue field (the queue is the store binding and the leading PK column),
Get takes (uri, project), the Record payload carries queue_name beside the
request id, degrees are the named DegreeGreen/DegreeBroken constants,
LastGreenRequestID is shipped rather than proposed, and the bookmark's CAS
conflict is absorbed by the retry loop rather than returned. Adds the two
algorithm steps the doc omitted (deserialize, per-queue storage resolution)
and the ordering rationale for advancing the bookmark only after the fact
is durable.

Replaces the inline Hooks design with integration against hook-framework.md,
which supersedes it: a HookEvent published to a per-domain hook topic and
dispatched to a pluggable extension, not a Notify() call out of the stage.
Records where the publish belongs, the event shape, and the decision that
`type` names the scope (validation.repository.recorded) rather than the
outcome, since scope is the axis consumers cannot route on later.

Documents that record_dlq has no consumer even though dead-lettering is
enabled on the subscription, so rejected messages accumulate unread.
…uarantee

Rebasing brought ref promotion and the two commit-timestamp metrics into
the record stage, none of which the RFC described: promotion is gated on
holding the last-green bookmark so an older green commit cannot drag the
ref backwards, and the equal-id case reports holding it so a crash before
promoting is recoverable.

Also corrects an overstated claim. The fail-closed path was documented as
never reaching record, but buildsignal publishes unconditionally once a
build goes terminal, outside the guard that makes its state write
idempotent. A request forced to failed by buildsignal_dlq reconciliation
can therefore be carried into a permanent broken fact by a surviving poll
chain that observed success. Records the trace, notes that build_dlq is
orphaned alongside record_dlq, and opens the question of whether observed
success should outrank a forced failure.
@mnoah1
mnoah1 force-pushed the mnoah1/record-step branch from 2f229dd to 74f0a48 Compare August 13, 2026 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants