SOURCES
Raw PDF, YouTube URL, or plain text excerpt submitted and committed durably to Postgres before extraction.
The rules-ingestion-pipeline project supplies the missing automated ingestion path for an already-built, already-tested rule validation and sealing backend. The existing backend — a Supabase PostgreSQL database in schema sovereign plus Python gate scripts running on Replit free tier — validates small verified Python functions ("rules") with formal pre/postconditions through a 6-gate pipeline (G1–G6) and permanently admits them via a single Postgres function sovereign.finalize_candidate(candidate_id, revision).
Today every rule candidate is created manually: the operator writes the Python function by hand, inserts it into rule_candidates via SQL, runs the gate scripts by hand, and calls finalize_candidate by hand. There is no automated path from a raw source to a candidate.
This document specifies the automated ingestion pipeline that closes that gap: raw source in (PDF textbook/paper, YouTube video URL, or plain text course excerpt), extracted text, durably chunked with source location metadata, LLM-proposed rule candidate with a Hoare-style contract, insertion into rule_candidates, automatic invocation of engine_main.py's evaluate(), and automatic finalize_candidate on all-6-gates-PASS. Failed candidates remain permanently recorded and are never deleted.
The audience is the single human actor — a non-technical solo operator working from a mobile phone only, with zero budget, on Supabase free tier and Replit free tier. The document is written so that this operator can build, run, and monitor the pipeline incrementally from a phone, and so that any engineer assisting them can implement it without redesigning the existing backend.
What is being built. A first-party ingestion pipeline that turns raw sources into validated rule candidates and, when all six gates pass, into sealed sovereign rules. The pipeline is the only new product surface; the existing validation and sealing backend is treated as a fixed, external, already-tested dependency that must not be redesigned.
What is not being built. The existing sovereign schema tables (rule_candidates, rule_gate_receipts, sovereign_rules, policy_manifests, policy_bounds, audit_events), the sovereign.finalize_candidate Postgres function, and the Python gate scripts (engine_main.py, engine_g2.py, engine_g3.py, engine_g5.py, engine_g6.py, engine_seal.py, supa_client.py) are already built and tested. They are consumed as-is. No new gate, no new sealing path, no new policy mechanism, and no replacement of finalize_candidate is introduced.
Delivery and access ownership. The pipeline is a first-party, application-owned system with a single human actor. Because the operator must privately own and resume durable, actor-specific ingestion state (submitted sources, chunk queues, proposal queues, candidate processing state) across Replit container sleep and restarts, application-owned identity is required. First use establishes identity anonymously (self-service enrollment); returning use verifies identity before any protected ingestion or pipeline control is available. The entry interaction that establishes access is itself anonymous; protected ingestion and pipeline controls are unavailable until identity is established. No differentiated permissions, roles, or visibility rules are introduced — the operator is the sole human actor and has full control over their own ingestion state.
Current vs. future boundary. Everything in this document is current. No future-horizon capabilities are specified by the source. The pipeline must not require any paid service, VPS, or persistent server, and must not rely on local disk or in-memory state as the source of truth at any step.
Durable state. Postgres is the durable source of truth at every step. All new pipeline state (sources, chunks, queue entries, LLM proposals, candidate processing state, provider retry/fallback state) lives in Postgres tables. Replit containers may sleep, restart, or lose local disk at any time without losing in-progress work.
Validation strength. LLM calls go through a free-tier-compatible provider (e.g., OpenRouter free models) with explicit fallback handling if a model becomes unavailable or rate-limited. Fallback must never silently degrade validation strength: if no acceptable model is available, the affected work item is parked in an explicit provider-retry/fallback state rather than being processed with a weaker model or skipped.
Code safety. LLM-generated Python is never executed with real inputs during validation. It is only parsed and analyzed (AST) by the existing gate pipeline. No arbitrary code execution of LLM-generated code is allowed outside a strictly bounded, isolated process.
Runtime services and infrastructure. The pipeline is delivered as a small set of runnable services, and new pipeline APIs and domain modules are added to the existing shared backend rather than to a new process:
sovereign Supabase PostgreSQL database, which remains the durable source of truth for all pipeline and rule state.sovereign Supabase PostgreSQL database remains the durable source of truth at every step.These services add no product requirements and do not change the access decisions above. The pipeline worker that claims queue work and drives extraction, proposal, evaluation, and sealing runs inside the shared backend process, triggered by the scheduled trigger or the operator's manual trigger; it is not a separate always-on daemon, because no guaranteed always-on process is available on Replit free tier.
Not applicable. No reference directive in the authoritative source declares a content_source; the source material is the user-authored requirement thread and the already-built backend description, both of which are preserved as requirements rather than as a content inventory.
The pipeline is delivered as a headless, background-automated system with a single first-party operator surface. The page contract for this project is a single operator console page plus an anonymous entry state, both owned by the first-party application.
The single first-party operator surface. It is the working context for submitting raw sources, monitoring extraction and chunking, monitoring LLM proposal generation, monitoring candidate evaluation and sealing, and inspecting the durable state of every source, chunk, proposal, and candidate. It is protected: it is only reachable after identity is established.
candidate_id, revision, proposal, code_artifact, hoare_triple, domain_claim, domain_type, concept_maturity, digest, created_at, and the six gate receipts (gate_id G1–G6, result PASS/FAIL/INDETERMINATE/NOT_RUN, measured_values, policy_digest, input_digest, checker_version, execution_verified).rule_id, seal_id, title, code_artifact, hoare_triple, active, activated_at.candidate_id, rule_id, or seal_id for reference.rule_candidates row).rule_gate_receipts row).sovereign_rules row).rule_candidates row and its six gate receipts.sovereign_rules row.rule_id, seal_id, title, and activated_at.finalize_candidate rejection) and the durable record is preserved.The anonymous pre-identity entry state for the operator console. It is the only surface reachable before identity is established. It exists because the protected operator console cannot own the interaction that establishes access to itself.
Each requirement is a distinct story point with provenance, lifecycle facts, and observable acceptance. Provenance is explicit (stated in the authoritative user requirement thread), basic_default (accepted default), or required_inference (indispensable inferred mechanics).
FR-1 — Submit a raw source. As the Solo Operator, I should be able to submit a raw source of one of three kinds — a PDF textbook/paper, a YouTube video URL, or a plain text excerpt from a course — so that the pipeline can turn it into validated rule candidates.
explicit.FR-2 — Durable source state. As the Solo Operator, I should have every submitted source recorded durably in Postgres before any extraction begins, so that a Replit container sleep or restart never loses a submitted source.
explicit (Postgres must be the durable source of truth at every step).FR-3 — Extract text from a PDF. As the Solo Operator, I should have the pipeline extract text content from a submitted PDF textbook/paper so that its content can be chunked and proposed as rules.
explicit.FR-4 — Extract text from a YouTube video. As the Solo Operator, I should have the pipeline extract transcript/captions from a submitted YouTube video URL so that its content can be chunked and proposed as rules.
explicit.FR-5 — Accept a plain text excerpt. As the Solo Operator, I should be able to submit a plain text excerpt from a course directly, so that short course material can be processed without a PDF or video.
explicit.FR-6 — Chunk extracted text into bounded, ordered pieces. As the Solo Operator, I should have extracted text split into bounded, ordered pieces so that each piece can be sent to the LLM as a self-contained proposal unit.
explicit.FR-7 — Preserve source location metadata on every chunk. As the Solo Operator, I should have every chunk carry source location metadata (page number for PDFs, timestamp for YouTube, excerpt offset for plain text) so that every proposed rule can be traced back to its exact source location.
explicit.FR-8 — Durable chunk storage. As the Solo Operator, I should have every chunk stored durably in Postgres so that work is never lost across Replit container sleep or restart.
explicit.FR-9 — Send a chunk to the LLM for rule proposal. As the Solo Operator, I should have the pipeline send a chunk (or a set of chunks) to an LLM asking it to propose ONE small, pure, self-contained Python function that encodes a provable fact/rule from that text, along with a Hoare-style precondition/postcondition contract.
explicit.FR-10 — Enforce the proposal shape. As the Solo Operator, I should have the LLM asked for a function that is small, pure, self-contained, with a single entry point, no imports, no side effects, 120–2500 characters, and loop-free preferred, so that proposals are compatible with the existing gate pipeline.
explicit.FR-11 — Require a Hoare-style contract. As the Solo Operator, I should have the LLM return a Hoare-style precondition/postcondition contract alongside the function, so that the existing gate pipeline can validate the rule against its contract.
explicit.FR-12 — Strict parseable output format. As the Solo Operator, I should have the LLM prompt require a strict, parseable output format so that the pipeline can reliably extract the function and contract without ambiguity.
explicit (question 4 asks for an exact prompt structure yielding a strict parseable format).FR-13 — Detect malformed, oversized, or unparseable LLM output before insertion. As the Solo Operator, I should have the pipeline detect malformed, oversized, or unparseable LLM output before it is inserted as a candidate, so that the existing gate pipeline is not polluted with proposals that cannot be evaluated.
explicit (question 5 asks whether to detect before insertion or insert everything and let the gate pipeline reject it).rule_candidates.FR-14 — Provider fallback without weakening validation. As the Solo Operator, I should have LLM calls go through a free-tier-compatible provider (e.g., OpenRouter free models) with explicit fallback handling if a model becomes unavailable or rate-limited, without silently degrading validation strength.
explicit.FR-15 — Insert the LLM proposal as a new rule_candidates row. As the Solo Operator, I should have the LLM's proposal inserted as a new row in rule_candidates respecting the exact existing schema (candidate_id, revision, proposal, code_artifact, hoare_triple, domain_claim, domain_type, concept_maturity, digest, created_at), so that the existing gate pipeline can evaluate it.
explicit.rule_candidates row is written with all required fields populated, including a computed digest.FR-16 — Respect rule_candidates immutability. As the Solo Operator, I should have rule_candidates rows remain immutable once inserted (trigger-enforced), so that the existing backend's integrity guarantees are preserved.
explicit.rule_candidates row; corrections are made by inserting a new revision.FR-17 — Automatically trigger engine_main.py's evaluate() on each new candidate. As the Solo Operator, I should have the pipeline automatically trigger engine_main.py's evaluate() on each newly inserted candidate, so that I no longer run the gate scripts by hand.
explicit.rule_candidates row.evaluate(candidate) runs the existing gates G1–G6 and posts gate receipts to rule_gate_receipts.FR-18 — Automatically call finalize_candidate when all 6 gates pass. As the Solo Operator, I should have the pipeline automatically call finalize_candidate when all 6 gates pass, so that sealed rules are produced without manual SQL or manual finalize calls.
explicit.policy_digest.sovereign.finalize_candidate(candidate_id, revision) is called; on success it returns the new rule_id and a sovereign_rules row is written.finalize_candidate rejection (duplicate code/title, policy mismatch, advisory lock contention) is recorded durably; the candidate remains permanently recorded.FR-19 — Leave failed candidates as-is and move on. As the Solo Operator, I should have the pipeline leave a candidate as-is (already permanently recorded, never deleted) when any gate fails, and move to the next chunk, so that failed candidates are preserved for inspection and the pipeline keeps making progress.
explicit.FR-20 — Preserve the existing validation and sealing paths. As the Solo Operator, I should have the existing engine evaluation and finalize_candidate flow remain the only validation and sealing paths, so that the pipeline never introduces an alternative validation or sealing mechanism.
required_inference (indispensable to preserve the explicit constraint that finalize_candidate is the ONLY path to seal a rule).engine_main.py's evaluate(); all sealing goes through sovereign.finalize_candidate.FR-21 — Postgres-only job queue. As the Solo Operator, I should have the job queue implemented using only Postgres tables (no Redis, no external queue service) to track pending chunks and pending LLM proposals, so that a crashed or sleeping worker can resume safely without duplicating work or losing a chunk.
explicit.FR-22 — Survive Replit container sleep/restart. As the Solo Operator, I should have the pipeline survive Replit container sleep/restart without losing in-progress work, with nothing relying on local disk or in-memory state as the source of truth.
explicit.FR-23 — Idempotent work claiming. As the Solo Operator, I should have work claiming be idempotent so that a worker that wakes up after a sleep does not duplicate work.
required_inference (indispensable to satisfy the explicit "without duplicating work" requirement).FR-24 — First-use self-service enrollment. As the Solo Operator, I should be able to establish my identity on first use through self-service enrollment, so that I can privately own and resume my durable ingestion state.
required_inference (indispensable to make the accepted journey executable; the operator must privately own durable actor-specific state).FR-25 — Returning verification. As the Solo Operator, I should be able to verify my identity on return, so that I can resume my durable ingestion state.
required_inference (indispensable to make the accepted journey executable).FR-26 — Protected operator console. As the Solo Operator, I should have the operator console protected so that my durable ingestion state is only reachable after identity is established.
required_inference (indispensable to protect durable actor-specific state).FR-27 — Inspect durable pipeline state. As the Solo Operator, I should be able to inspect the durable state of every source, chunk, proposal, candidate, and sealed rule from the operator console, so that I can monitor the pipeline from my phone.
explicit (the operator must monitor the pipeline from a mobile phone).FR-28 — Retry a parked work item. As the Solo Operator, I should be able to retry a work item parked in provider-retry/fallback state once a provider is available again, so that no work is permanently stuck.
required_inference (indispensable to make the explicit provider fallback requirement usable).FR-29 — No paid service, VPS, or persistent server. As the Solo Operator, I should have the pipeline require no paid service, VPS, or persistent server, so that it operates within my zero-budget constraint.
explicit.FR-30 — No arbitrary code execution of LLM-generated code. As the Solo Operator, I should have no arbitrary code execution of LLM-generated code outside a strictly bounded, isolated process, with the generated Python only parsed/analyzed (AST) and never executed with real inputs during validation.
explicit.Product context. The Solo Operator is the sole human actor for rules-ingestion-pipeline. They are non-technical and currently work from a mobile phone only, with no computer available. They already operate a working backend (Supabase PostgreSQL in schema sovereign, Python gate scripts on Replit free tier) that validates and seals rules through a 6-gate pipeline. Their recurring problem is that every rule candidate is created manually: they write the Python function by hand, insert it into rule_candidates via SQL, run the gate scripts by hand, and call finalize_candidate by hand. They need the automated ingestion pipeline to replace that manual work.
Primary goal. Submit a raw source (PDF textbook/paper, YouTube video URL, or plain text course excerpt) and have the pipeline turn it into validated rule candidates and, when all six gates pass, into sealed sovereign rules — without manual SQL insertion, manual gate runs, or manual finalize calls — all within zero-budget free-tier limits and from a mobile phone.
Distinct accepted responsibilities.
Relevant inputs and decisions.
Interactions with other accepted participants. The Solo Operator is the only human actor. The pipeline interacts with external providers (the LLM provider, e.g., OpenRouter free models) and with the existing backend (Supabase Postgres, the Python gate scripts, and finalize_candidate). These are non-persona actors; the operator does not interact with them directly except through the operator console.
Observable success. A source the operator submitted becomes one or more sealed sovereign rules without manual SQL insertion, manual gate runs, or manual finalize calls; failed candidates remain permanently recorded and inspectable; the pipeline survives Replit container sleep and restart without losing in-progress work; and no paid service, VPS, or persistent server is required.
Source-backed constraints. Zero budget; Supabase free tier (pauses after 1 week inactivity, no automatic backups); Replit free tier (containers sleep after inactivity, local disk is NOT persistent, no guaranteed always-on process); non-technical solo operator working from a mobile phone only; no arbitrary code execution of LLM-generated code outside a strictly bounded, isolated process; LLM calls through a free-tier-compatible provider with explicit fallback handling without silently degrading validation strength; Postgres as the durable source of truth at every step; no paid service, VPS, or persistent server.
rule_candidates row with all required fields populated, including a computed digest.engine_main.py's evaluate() on the new candidate; the existing gates G1–G6 run and post gate receipts to rule_gate_receipts.policy_digest, the pipeline automatically calls sovereign.finalize_candidate(candidate_id, revision); on success it returns the new rule_id and a sovereign_rules row is written.rule_candidates; the chunk is marked failed and the pipeline moves to the next chunk.rule_candidates row and its six gate receipts, including measured_values, policy_digest, input_digest, checker_version, and execution_verified.finalize_candidate rejection such as duplicate code/title or policy mismatch).No CREATIVE DIRECTION block was supplied, and the authoritative source specifies no colors, fonts, or brand. The following is a coherent, accessible default for a phone-first, non-technical operator console. It is labeled as a default and is not product behavior.
[Default — not specified by user]
#F7F5F0 (warm off-white)#FFFFFF#EFEBE3#D9D3C7#1F1B16#5C554A#1F6F5C (deep teal-green)#185A4B#2E7D4F#B26A00#B3261E#3A5A8C#14120F#1E1B17#2A2621#3A352E#F2EEE7#B8B0A3#4FB39A#5FBF85#E0A24A#E5736C#7FA3D6"IBM Plex Sans", system-ui, sans-serif; body in "IBM Plex Sans", system-ui, sans-serif; code and identifiers in "IBM Plex Mono", ui-monospace, monospace.The public entry is the anonymous Ingestion Entry state. Its signature concept is a "source-to-seal" vertical trace: a single, phone-width vertical line that runs from a source icon at the top, through three labeled nodes (Extract, Chunk, Propose), to a candidate node, and finally to a sealed-rule node at the bottom. Each node is a small, tappable card showing the stage name and a one-line description of what happens there. The line is drawn in the accent color (#1F6F5C) and the nodes use the status colors (info, warning, success) to preview the pipeline's real states. The two entry actions — first-use enrollment and returning verification — sit as two clearly separated buttons below the trace. The concept recomposes only accepted content (the pipeline's stages and the two entry paths); it introduces no new behavior, page, or destination. It is implementable as a single responsive column with CSS-drawn connectors and no imagery.
No CREATIVE DIRECTION block was supplied. The tempo is chosen for the product's audience: a non-technical solo operator on a mobile phone, often on a slow connection, who needs to read durable state clearly and act without distraction. The appropriate tempo is restrained.
Interaction Model: Static Motion Tempo: restrained Hero Dimensionality: flat
Landing Hero Motion Brief
explicit. Rationale: the operator's hard zero-budget constraint.explicit. Rationale: stated free-tier behavior. Mitigation: the operator's scheduled or manual trigger keeps the project active; durable state is the operator's responsibility given no automatic backups.explicit. Rationale: stated free-tier behavior.explicit.explicit.explicit.service_role key; no direct Postgres connection from Python. Provenance: explicit.rule_candidates rows are immutable once inserted (trigger-enforced); rule_gate_receipts are append-only with no update/delete allowed; failed candidates are never deleted. Provenance: explicit.sovereign.finalize_candidate(candidate_id, revision) is the ONLY path to seal a rule; it is idempotent, atomic, checks all 6 gate receipts are PASS against the current approved policy_digest, acquires an advisory lock, rejects exact code/title duplicates against currently active rules, writes the audit event, and returns the new rule_id. Provenance: explicit.explicit.sovereign schema tables, the finalize_candidate function, and the Python gate scripts must not be redesigned. Provenance: explicit.explicit.Source-specified choices are preserved exactly. Defaults are labeled.
sovereign, with the existing tables rule_candidates, rule_gate_receipts, sovereign_rules, policy_manifests, policy_bounds, audit_events, and the existing function sovereign.finalize_candidate. New pipeline tables are added in the same schema (see Assumptions and Constraints for the proposed new tables). Provenance: explicit.sovereign Supabase PostgreSQL database, which remains the durable source of truth for all pipeline and rule state. [Default — not specified by user][Default — not specified by user][Default — not specified by user][Default — not specified by user][Default — not specified by user]engine_main.py, engine_g2.py, engine_g3.py, engine_g5.py, engine_g6.py, engine_seal.py, supa_client.py) plus new pipeline scripts. Provenance: explicit.service_role key via supa_client.py; no direct Postgres connection from Python. Provenance: explicit.explicit.pypdf (pure-Python, low memory, no native dependencies) as the primary choice, with pdfminer.six as a fallback for PDFs that pypdf cannot extract. [Default — not specified by user]youtube-transcript-api (pure-Python, no API key, low memory) as the primary choice. [Default — not specified by user]httpx (async-capable, low memory) for LLM provider calls and Supabase REST calls. [Default — not specified by user]pg_cron job or a free external cron service such as cron-job.org) that calls the Replit pipeline entry point, plus the operator's manual trigger from the operator console. [Default — not specified by user][Default — not specified by user][Default — not specified by user]sovereign, the finalize_candidate function, and the Python gate scripts) is fully built and tested and is consumed as-is. [Assumption — source-stated][Assumption — source-stated][Assumption — default]pg_cron job or a free external cron service) is available to wake the Replit container periodically. [Assumption — default][Assumption — source-stated]These are concrete schema proposals for the new pipeline state. They live in the sovereign schema alongside the existing tables and do not modify any existing table.
sovereign.ingestion_sources — one row per submitted raw source.
source_id (uuid, primary key)operator_id (uuid, references the operator identity)source_kind (text, one of pdf, youtube, text)source_reference (text: file name, URL, or excerpt label)extracted_text (text, nullable until extraction completes)stage (text: submitted, extracting, chunking, proposing, evaluating, sealing, done, failed, parked)failure_reason (text, nullable)created_at (timestamptz)updated_at (timestamptz)sovereign.ingestion_chunks — one row per bounded, ordered chunk.
chunk_id (uuid, primary key)source_id (uuid, references ingestion_sources)order_index (integer, stable order within the source)chunk_text (text)location_metadata (jsonb: {page: n} for PDFs, {timestamp: "hh:mm:ss"} for YouTube, {offset: n} for plain text)created_at (timestamptz)sovereign.ingestion_queue — the Postgres-only job queue for pending chunks and pending LLM proposals.
queue_id (uuid, primary key)work_kind (text: chunk_proposal, candidate_evaluation, candidate_sealing)source_id (uuid, nullable)chunk_id (uuid, nullable)candidate_id (uuid, nullable)revision (integer, nullable)status (text: pending, claimed, done, failed, parked)claimed_by (text, nullable: worker identifier)claimed_at (timestamptz, nullable)lease_expires_at (timestamptz, nullable)attempt_count (integer, default 0)last_error (text, nullable)created_at (timestamptz)updated_at (timestamptz)sovereign.ingestion_proposals — one row per LLM proposal, before and after insertion into rule_candidates.
proposal_id (uuid, primary key)chunk_id (uuid, references ingestion_chunks)provider (text)model (text)prompt_text (text)raw_response (text)parsed_code_artifact (text, nullable)parsed_hoare_triple (text, nullable)validation_result (text: valid, malformed, oversized, unparseable, missing_contract)validation_reason (text, nullable)candidate_id (uuid, nullable, references rule_candidates once inserted)created_at (timestamptz)sovereign.ingestion_provider_state — one row per provider/model availability observation.
provider_state_id (uuid, primary key)provider (text)model (text)available (boolean)rate_limited_until (timestamptz, nullable)observed_at (timestamptz)[Constraint — source-stated][Constraint — source-stated][Constraint — source-stated][Constraint — source-stated][Constraint — source-stated][Constraint — source-stated]sovereign schema tables, the finalize_candidate Postgres function as the ONLY path to seal a rule, and the Python gate scripts. [Constraint — source-stated]service_role key; no direct Postgres connection from Python. [Constraint — source-stated]rule_candidates rows are immutable once inserted (trigger-enforced); rule_gate_receipts are append-only with no update/delete allowed. [Constraint — source-stated][Constraint — source-stated]This build order answers question 6 of the authoritative source and is prioritized so that each step is a small, testable piece that can be built and verified from a phone.
sovereign.ingestion_sources table and a minimal operator console page that submits a plain text excerpt and writes a durable source row. Verify from the phone that the row persists across a Replit container restart. This is the concrete first-build-step.sovereign.ingestion_chunks table and chunk the extracted text into bounded, ordered pieces with location metadata. Verify that chunks persist durably and are ordered correctly.sovereign.ingestion_queue table with status, claim, and lease fields. Verify that a claimed work item is reclaimed after its lease expires and that claiming is idempotent.pypdf (with pdfminer.six fallback) and extract text from a small PDF. Verify page-level location metadata.youtube-transcript-api and extract a transcript from a short video. Verify timestamp-level location metadata.rule_candidates row with a computed digest. Verify immutability.engine_main.py's evaluate() on the new candidate and verify that gate receipts are posted to rule_gate_receipts.sovereign.finalize_candidate when all six gate receipts are PASS and verify that a sovereign_rules row is written.pg_cron job or a free external cron service) that wakes the Replit container and runs the pipeline. Verify that the pipeline resumes from durable state after a container sleep.sovereign.rule_candidates representing a proposed rule before sealing. Immutable once inserted (trigger-enforced).sovereign.rule_gate_receipts recording a gate's result (PASS, FAIL, INDETERMINATE, or NOT_RUN) with measured_values, policy_digest, input_digest, checker_version, and execution_verified. Append-only.sovereign.sovereign_rules produced by finalize_candidate, with rule_id, seal_id, title, code_artifact, hoare_triple, active, and activated_at.finalize_candidate: the single Postgres function sovereign.finalize_candidate(candidate_id, revision) that is the ONLY path to seal a rule. Idempotent, atomic, checks all 6 gate receipts are PASS against the current approved policy_digest, acquires an advisory lock, rejects exact code/title duplicates against currently active rules, writes the audit event, and returns the new rule_id.sovereign.policy_manifests with manifest_sha256, approved, and approved_at. Versioned approved policy.sovereign.policy_bounds with manifest_version, gate, metric, min_v, and max_v. Numeric thresholds per gate.sovereign.audit_events with event_id, event_type, event_payload, prev_hash, and event_hash. Hash-chained append-only log.rule_candidates.
A raw source is committed durably to Postgres, then extracted to text and split into bounded, ordered chunks, each chunk carrying its source location — page number, timestamp, or excerpt offset. Every chunk goes to a free-tier LLM that proposes one small, pure, self-contained Python function with a Hoare-style precondition and postcondition contract, and the proposal is inserted as an immutable rule_candidates row.
The existing engine then evaluates the candidate through the six gates G1–G6. When all six return PASS against the current approved policy digest, sovereign.finalize_candidate seals it into sovereign_rules. Any failure leaves the candidate permanently recorded, never deleted, and the pipeline moves to the next chunk.
Entry state is anonymous. The operator console is protected.Raw PDF, YouTube URL, or plain text excerpt submitted and committed durably to Postgres before extraction.
Bounded, ordered pieces of extracted text, each carrying page number, timestamp, or excerpt offset.
One small, pure, self-contained Python function plus a Hoare-style precondition/postcondition contract per chunk.
Immutable rule_candidates row with a computed digest and six gate receipts G1–G6.
sovereign_rules row written by sovereign.finalize_candidate when all six gates PASS.
06 — LedgerOperating facts
Seven facts the operator can rely on before entering the pipeline. Each row is a constraint the system already enforces, not a promise about it.
Queue — Postgres only
Store — Supabase free tier
Workers — Replit free tier
Deletes — None
Entry
First-use self-service enrollment and returning verification are handled inside the anonymous Ingestion Entry state. No pipeline run data is read on this public page.

A raw source is committed durably to Postgres, then extracted to text and split into bounded, ordered chunks, each chunk carrying its source location — page number, timestamp, or excerpt offset. Every chunk goes to a free-tier LLM that proposes one small, pure, self-contained Python function with a Hoare-style precondition and postcondition contract, and the proposal is inserted as an immutable rule_candidates row.
The existing engine then evaluates the candidate through the six gates G1–G6. When all six return PASS against the current approved policy digest, sovereign.finalize_candidate seals it into sovereign_rules. Any failure leaves the candidate permanently recorded, never deleted, and the pipeline moves to the next chunk.
Entry state is anonymous. The operator console is protected.Raw PDF, YouTube URL, or plain text excerpt submitted and committed durably to Postgres before extraction.
Bounded, ordered pieces of extracted text, each carrying page number, timestamp, or excerpt offset.
One small, pure, self-contained Python function plus a Hoare-style precondition/postcondition contract per chunk.
Immutable rule_candidates row with a computed digest and six gate receipts G1–G6.
sovereign_rules row written by sovereign.finalize_candidate when all six gates PASS.
06 — LedgerOperating facts
Seven facts the operator can rely on before entering the pipeline. Each row is a constraint the system already enforces, not a promise about it.
Queue — Postgres only
Store — Supabase free tier
Workers — Replit free tier
Deletes — None
Entry
First-use self-service enrollment and returning verification are handled inside the anonymous Ingestion Entry state. No pipeline run data is read on this public page.
No comments yet. Be the first!