Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions crates/qbit-prism/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,15 @@ defines:
- `qbit_share_ledger`: append-only canonical share log ordered by `share_seq`
- `qbit_ledger_writer_lease`: one-row coordination table for a single logical
writer/failover epoch
- `qbit_pool_blocks.audit_publication_sequence`: durable confirmation and
reactivation order for current audit evidence, independent of block height
- `qbit_prism_window(...)`: deterministic newest-backward window query with
partial oldest-share weighting

The schema file is cumulative and idempotent. Existing deployments must rerun
it before upgrading when automatic schema initialization is disabled; see the
[ledger operations contract](../../docs/prism-ledger-ops.md#audit-publication-ordering-migration).

Stratum frontends should enqueue share submissions outside this table. Only the
active ledger writer inserts rows into `qbit_share_ledger`; that is what keeps
all miners in the same reward universe.
Expand Down
3 changes: 3 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ This is useful for reviewers and operators who need implementation detail:
writer-lease behavior, compaction contract, and readiness probes.
- [prism-capacity-readiness.md](prism-capacity-readiness.md): optional
Stratum-to-Postgres qualification artifact and standalone validator contract.
- [prism-coordinator-refactor/README.md](prism-coordinator-refactor/README.md):
completed coordinator decomposition, ownership map, validation evidence, and
stacked-PR publication plan.

## Public-Site Guidance

Expand Down
41 changes: 41 additions & 0 deletions docs/prism-coordinator-refactor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# PRISM Coordinator Refactor

Status: **complete** and organized as a nine-PR review stack. No required
roadmap item remains.

The completed tree is integrated with `origin/1.x.x` at `b002caa`. It preserves
the base branch's public hashrate, refresh/livelock, initial/reconnect delivery,
queue-reclamation, and latest-tip priority fixes in the extracted owners. It
also ports the latest retry pacing (`#71`) and delivery-health grace (`#82`)
behavior, plus share hot-path lock isolation (`#83`), into the template,
refresh, candidate, submission, vardiff, delivery, ledger, observability, and
metrics owners. The former exact-hash, literal-authorization,
mandatory-reviewer, and per-slice full-suite workflow is retired.

## Result

`lab/prism/prism_coordinator.py` is now the construction, startup, signal,
stable-facade, and top-level shutdown root. Domain state machines, background
loops, queues, locks, cached observability, persistence, HTTP, and mining work
live in dedicated owners. See [Structure](structure.md) for the boundary and
the documented size exception.

B3 is intentionally omitted: the available evidence does not justify a second
finalization lane or its additional durable handoff. See the
[decision record](b3-decision.md).

The final runnable validation matrix passes. Docker-dependent PostgreSQL,
container lint/build, and both live Stratum targets are `UNAVAILABLE` in the
current environment because the OrbStack daemon is stopped; `qbitd` is also
absent. These are missing-environment evidence, not passes or product
failures. Exact results are in [Validation](validation.md).

## Reference documents

- [Invariants](invariants.md): release behavior that must remain true.
- [Roadmap](roadmap.md): completed slices and decisions.
- [Structure](structure.md): final ownership map and structural audit.
- [Validation](validation.md): risk-based cadence and final evidence.
- [Stacked PRs](stacked-prs.md): publication order and reconstruction rules.
- [A1 audit artifacts](a1-audit-artifacts.md): durable storage contract.
- [B3 decision](b3-decision.md): finalization concurrency evidence.
78 changes: 78 additions & 0 deletions docs/prism-coordinator-refactor/a1-audit-artifacts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# A1 Audit Artifact Contract

A1 is complete. `lab/prism/audit_artifacts.py` owns audit
filesystem authority; `bundle_compiler.py` owns compiler/subprocess work; the
ledger owns database authorization and accepted-block transactions; the
coordinator only composes them and retains narrow compatibility calls.

## Directory and file authority

- Pin audit root and evidence-parent directory descriptors with no-follow
semantics. Perform owned reads, creates, replacement, fsync, scans, and
removals relative to those descriptors.
- A path replacement revokes the store until the original inode is restored or
`reconfigure()` adopts a new authority pair atomically.
- Parse only exact owned names. Malformed lookalikes, symlinks, nonregular
entries, traversal, and out-of-root URIs never grant read, pin, repair, or
deletion authority.
- Track candidate inode identity. Cleanup removes only the exact file created
by the current attempt, including builder-create-then-raise and swapped-path
failures.

## Compiler and verifier boundary

J1 receives a duplicated A1 directory descriptor and reserved candidate name,
creates the canonical output relative to it, and transfers the still-open exact
inode to A1. Compatibility builders use canonicalization fallback and are not
reported as exact compiler output.

Verification uses an unlinked read-only descriptor snapshot, a bounded process
group, timeout, and independent stdout/stderr limits. Trust source, writer key,
literal digest/bytes, and normalized report form the verification identity. A
retry never reuses a prior attempt's success.

## Publication and replay

- PostgreSQL assigns a unique durable `audit_publication_sequence` at the
serialized confirmation boundary. Exact confirmation replay and later
inactive/reactivation transitions reuse it; reactivation does not create an
unpublished ordinal.
- Sequence, not height, hash ordering, process order, or mtime, chooses current
evidence. Hash, height, coinbase, digest, and verification identity remain
integrity fields.
- Allocation/publication lock order is payout balance mutation then the A1
publication guard. The guard uses one pinned internal lock inode with an
in-process reentrant lock plus cross-process `flock`.
- Reload disk evidence while guarded before replay, repair, publish, or prune.
An already-valid exact pair may replay behind a later floor; damaged state
repairs only at the fresh durable-row floor.
- Legacy evidence grants no ordering or pin authority after restart until it is
re-proved against exact confirmed ledger state and adopted at its durable
sequence.

Mutable publication installs the envelope first and evidence second, fsyncing
file and required parent boundaries. Only then does in-memory current evidence
advance. A failure preserves the previous valid pair. Exact replay is
byte/inode stable except for documented global observational counters.

## Bodies, segments, and retention

Inline and external audit bodies expose the same canonical bytes, digest, and
response metadata in memory and PostgreSQL modes. Share-slot merges are
serialized, lossless for disjoint updates, idempotent for identical overlap,
and preserving on conflict. Audit bodies and share segments are durable and not
reference-blind garbage-collected.

Retention runs after successful publication, is best effort, and revalidates
both directory authorities and current/reserved identities at each removal.
Retention 0/1, tied mtimes, concurrent stores/processes, and prune failure may
not delete or regress current evidence. The internal lock file is never exposed
as an artifact.

## Completion evidence

A1 was reconciled with the integrated owners and validated through its direct
artifact/API/ledger/candidate/metrics suites, PostgreSQL parity/migration/process
helpers, Rust audit CLI tests, Docker compile/lint, and diff/temporary-artifact
hygiene. Exact hashes, literal authorization, and same-reviewer verdicts were
intentionally not part of completion.
112 changes: 112 additions & 0 deletions docs/prism-coordinator-refactor/invariants.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Refactor Invariants

These are release constraints, not process gates. If a proposed boundary
conflicts with one, change the boundary.

## Architecture

- `prism_coordinator.py` is the construction, signal, startup, and top-level
shutdown root. Leaf services must not import it.
- Each service owns its mutable state, lock, bounded queue/executor, metrics,
and worker lifecycle. Do not replace the coordinator with a broad context
object.
- Cross-service work that can be superseded carries immutable identity:
connection generation, tip/template generation, payout generation, worker,
difficulty, or durable candidate identity as applicable.
- No socket, RPC, PostgreSQL, subprocess, filesystem, or blocking queue work
runs while a shared coordinator/session lock is held.
- When both are required, a client's vardiff lock is acquired before the
coordinator control lock. Normal share submission takes one immutable
coordinator control snapshot; deduplication and share accounting use their
dedicated owner locks rather than reacquiring the coordinator lock.
- Compatibility delegates may remain only while an in-repository caller needs
them. The implementation body and mutable state remain in one owner.

## Mining work and delivery

- Detected tip, published tip, template artifacts, and payout state remain
distinct. Older work cannot overwrite newer observation authority.
- Publication-critical latest-tip work preempts or defers routine/initial work
without allowing concurrent heavy builders.
- `mining.set_difficulty` and its matching `mining.notify` commit as one client
update after final connection, authorization, tip, template, payout, worker,
and difficulty validation.
- Slow or failed sends do not hold global locks or block unrelated clients.
- Clean-job retirement, same-tip retention, stale grace, and initial/reconnect
queue bounds retain their current behavior.
- Vardiff changes become active only with a job stamped at that difficulty;
every failure or supersession restores speculative state.
- Failed tip refreshes use bounded, jittered owner-held pacing tied to the
observed tip. A successful refresh or a newer tip clears the holdoff, and a
same-tip poll may reuse only a still-fresh coherent template snapshot.

## Shares, candidates, and payout

- A normal share is acknowledged only after its durable ledger transaction.
Accepted counters and vardiff accounting advance at the same boundary.
- A share and required block-candidate intent commit atomically. The durable
outbox is authoritative; the in-memory queue is only a bounded wakeup.
- Duplicate identity uses the immutable job worker and header. Retry or
reauthorization cannot bypass it.
- Candidate replay is idempotent, keeps parents ahead of dependent children,
distinguishes retryable from terminal outcomes, and cannot double-account a
block or regress published evidence.
- Candidate attempt time is durable before processing. Intentional retry waits
wake in bounded heartbeat slices, expose pending/unattempted age and backoff
state, and keep blocked processing phases eligible for watchdog detection.
- A candidate whose network outcome is known but whose durable outbox
finalization failed resumes finalization with bounded pacing. It does not
resubmit the block, recount acceptance, rebuild audit evidence, or re-adopt
the released share-writer floor.
- Payout generations are monotonic and a stale prepared source cannot publish.
Accepted-block preview, final coinbase, confirmed balances, and delivered
jobs must agree.
- Post-accept and blockwait paths only notify the single refresh owner; they do
not enter the heavy refresh lane themselves.

## Audit artifacts

- Owned paths are descriptor-relative, no-follow, strictly parsed, and confined
to pinned directory identities.
- Canonical bytes are verified before durable publication. Writes and mutable
pair replacement are atomic and fsync their required parent boundaries.
- Ledger-assigned audit publication sequence, not height or process order,
decides current evidence across replay, restart, same-height replacement, and
reorg.
- Retention is post-publication best effort and cannot remove a current,
reserved, malformed, symlinked, or unowned entry.
- Audit bodies and share segments remain digest-checked and reconstructable in
memory and PostgreSQL modes.

## Health, HTTP, and metrics

- Health deadlines use monotonic time. Pending age starts at the first
unresolved change and does not slide on churn.
- First-job starvation and current-tip coverage loss have separate grace
clocks. Previously delivered clients do not masquerade as first-job
starvation, and restored coverage resets the coverage-loss clock.
- Publication and successful socket delivery are separate proofs. Cached base
health never masks a newer progress failure.
- Publication divergence is cleared only by a coherent completed publication,
including a no-op poll that proves existing work is current.
- Public routes, status codes, schemas, cache headers, metric names/labels, and
environment defaults remain compatible unless a roadmap item explicitly
authorizes a bounded behavior change.
- `/healthz` and `/metrics` perform no backend, ledger, artifact, or RPC work
after cached observability is complete.
- Metrics copy share counters under the dedicated accounting lock and expose
coordinator-lock contention plus durable candidate pending/backoff state
through narrow snapshots owned by their source services.
- The coordinator-owned HTTP listener reads complete cached metrics only. The
externally managed compatibility handler may render metrics synchronously
while its cache is still uninitialized because it owns no refresher thread.
- An audit HTTP serve-loop exit closes and retires its owned listener before a
replacement listener can start, including unexpected post-readiness exits.

## Shutdown and liveness

Shutdown remains: close admission and signal stop; cancel refresh work; drain
admitted writers; release or deliberately withhold the exact writer lease;
then drain non-writer threads, sockets, and executors. Publication-progress
watchdog protection remains active even when ordinary heartbeat checking is
disabled.
49 changes: 49 additions & 0 deletions docs/prism-coordinator-refactor/roadmap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Completed Roadmap

There is no active work order. Completed commits are implementation history,
not gates that must be reconstructed.

| Area | Result |
| --- | --- |
| foundations, configuration, RPC, shutdown, executors | extracted |
| progress, background services, CTV | extracted |
| payout, templates, bundles, refresh scheduler | extracted |
| sessions, delivery, share writer/recovery | extracted |
| `origin/1.x.x` through `b002caa` | complete, including retry pacing (`#71`), delivery-health grace (`#82`), and share hot-path lock isolation (`#83`) |
| A1 audit artifact ownership | complete |
| B1 candidate submission | complete |
| S4 share classification | complete |
| D1 bounded duplicate index | complete |
| V1 vardiff and idle retarget | complete |
| B2 accepted-block finalization phases | complete |
| B3 second finalization lane | `OMIT` ([decision](b3-decision.md)) |
| O2 cached health | complete |
| O3 cached metrics | complete |
| H1 audit/public HTTP | complete |
| X1 reorg, metrics, watchdog, and seam cleanup | complete |

X1 removed unused re-exports and drifting state mirrors, moved the remaining
reorg, metrics, and watchdog domain bodies to owners, and replaced magic
attribute forwarding with explicit ports and test hooks. Compatibility aliases
or delegates remain only where in-repository callers demonstrate the stable
facade; they do not own duplicated mutable state.

The upstream retry work is owned by `template_artifacts`, `tip_refresh`, and
`block_candidates`; the upstream health correction is owned by `job_delivery`,
`observability`, and `metrics`. The upstream hot-path correction is owned by
`stratum_session`, `job_delivery`, `share_submission`, `vardiff_service`,
`block_candidates`, `share_ledger`, and `metrics`: client vardiff state has a
per-client lock, share accounting has a dedicated lock, normal submission uses
one coordinator control snapshot, and candidate retry state remains observable
without making intentional waits look healthy. Coordinator code only wires
those ports and forwards stable compatibility calls.

The three cumulative milestones—durability/submission,
concurrency/finalization, and observability/cleanup—are complete. The final
tree satisfies the [invariants](invariants.md), the structural result is
recorded in [Structure](structure.md), and the full evidence is recorded in
[Validation](validation.md).

The implementation is organized into the review stack in
[Stacked PRs](stacked-prs.md). This document intentionally avoids commit IDs so
restacking cannot make the completion record stale.
33 changes: 33 additions & 0 deletions docs/prism-coordinator-refactor/stacked-prs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Stacked PR Review Plan

The refactor is published as nine bottom-up PRs. Every published stack commit
must be GPG-signed. PR 1 targets `1.x.x`; each later PR targets the branch
immediately above it so reviewers see only that slice.

| PR | Branch | Scope |
| --- | --- | --- |
| [#73](https://github.com/Qbit-Org/qbit-mining-bootstrap/pull/73) | `prism-test-shards` | mechanical test sharding and shared fixtures; no production behavior |
| [#74](https://github.com/Qbit-Org/qbit-mining-bootstrap/pull/74) | `prism-coordinator-core-owners` | configuration/RPC, lifecycle, payout, templates, bundles, refresh, sessions, delivery, share writing, same-tip template reuse, retry pacing, observed coordinator locking, and per-client vardiff lock wiring |
| [#75](https://github.com/Qbit-Org/qbit-mining-bootstrap/pull/75) | `prism-audit-artifact-owner` | PostgreSQL publication order, audit filesystem authority, compilation/verification, replay, retention, and migration/process gates |
| [#76](https://github.com/Qbit-Org/qbit-mining-bootstrap/pull/76) | `prism-block-candidate-submission` | durable candidate replay, attempt marking, bounded retry heartbeats/backoff state, finalize-only replay pacing, terminalization, and coordinator ports |
| [#77](https://github.com/Qbit-Org/qbit-mining-bootstrap/pull/77) | `prism-share-submission` | single-snapshot share classification, bounded duplicate tracking, and dedicated share-accounting synchronization |
| [#78](https://github.com/Qbit-Org/qbit-mining-bootstrap/pull/78) | `prism-vardiff-finalization` | per-client vardiff/idle-retarget synchronization, named accepted-block finalization phases, and the documented B3 decision |
| [#79](https://github.com/Qbit-Org/qbit-mining-bootstrap/pull/79) | `prism-observability-http` | cached health, separate first-job/coverage-loss grace, complete cached metrics, and audit/public HTTP facade |
| [#80](https://github.com/Qbit-Org/qbit-mining-bootstrap/pull/80) | `prism-final-ownership-cleanup` | reorg reconciler, synchronized metrics snapshots including hot-lock/candidate gauges, watchdog owner, compatibility cleanup, and temporary-seam removal |
| [#81](https://github.com/Qbit-Org/qbit-mining-bootstrap/pull/81) | `prism-refactor-documentation` | final roadmap, ownership audit, validation evidence, stack guide, and ledger migration operations |

Each PR targets the branch immediately above it; PR 1 targets `1.x.x`. Put the
stack position, base branch, dependency, focused validation, and any operator
impact in every PR body. PR 3 must call out the required existing-database
migration and maintenance-window lock; PR 9 carries the durable operator guide.

Address review feedback from the bottom of the stack upward. Amend each fix
into its owning signed commit, then rebase and sign every descendant so each PR
continues to contain one intentional slice. Push rewritten branches together
with explicit force-with-lease expectations; stop if any remote tip changed.

Validate focused behavior per PR. Run cumulative PRISM discovery after PR 2,
PostgreSQL/Rust after PR 3, the image build after PR 6, and the complete final
matrix on PR 9. Merge bottom-up. If the repository squash-merges a lower PR,
rebase the remaining branches onto the new `1.x.x` tip and force-push only with
lease.
Loading
Loading