The Totem Forge · Stage-1 Prototype

Aethelgard the signal-ingestion engine for the Totem Protocol / ShurIQ stack

A Rails 8.1 ingestion engine, real-time dashboard, and REA value-flow attestation store — built non-destructively and fully revertibly, so it can be explored without ever touching a load-bearing production system.

Posture SANDBOX SerpApi live · read-only Baseline 37fb5fb Rails 8.1 · Ruby 3.4.2 · Postgres 17 · Hotwire Repo local-only · outside the vault

01 — What it is

A contributor to the stack, never a competing source of truth

Aethelgard tracks breaking marketplace signals and parses them through the lens of structural gaps and REA (Resource-Event-Agent) value-flows. The vault and git history stay canonical for base facts; Oxigraph, the Report Studio, and the Letta Witness keep their roles. Aethelgard's genuine net-new value is ingestion — the Report Studio is generation, not ingestion.

A

Ingest

SerpApi sweeps public Google News into deduplicated signals, asynchronously via Sidekiq.

B

Attest

When a structural gap closes, it records an REA value-event — the seed of a bioavailable attestation layer.

C

Visualize

A live Hotwire dashboard streams rows and re-ranks the SBPI projection in real time over Turbo Streams.

02 — The isolation contract

It cannot mutate any production system

The load-bearing design decision. Two independent layers of safety mean the prototype is physically incapable of damaging the live stack in its default posture.

LAYER 1

Physical isolation

A standalone git repo at ~/Documents/projects/aethelgard, outside the Obsidian vault and outside the live React / Cloudflare / Turso / Oxigraph stack. Never tracked by the vault's git.

Soft revert git reset --hard 37fb5fb
Hard revert rm -rf the repo + dropdb the namespaced databases. Nothing else is touched.

LAYER 2

Integration isolation

Every load-bearing touchpoint goes through an adapter gated by a single master switch, AETHELGARD_LIVE (default false). Going live is a per-adapter opt-in: flip the switch and fill one endpoint URL at a time.

AETHELGARD_LIVE = false · default SANDBOX posture

Default runtime posture — what each adapter actually does:

SerpApi
live

Read-only Google News. Gated by key presence, not the master switch. Not load-bearing.

InfraNodus
stub

Deterministic replay fixtures. No socket opened.

Letta Witness
no-op

The only write path. Logs what it would attest, returns a stub receipt.

Report Studio
stub

Replay stack rank from fixtures.

Vault / Oxigraph
untouched

No writes. Canonical stores keep their roles.

03 — The pipeline

How a signal flows

Ingestion is async — the controller returns a 303 in ~18ms while the sweep runs in Sidekiq. Each new signal threads the bridge pipeline and broadcasts its row live.

Ingest form
ingestions#create → 303 in ~18ms

A query term is submitted; the controller enqueues a sweep and returns immediately.

IngestSignalsJob
Sidekiq · queue: ingestion

Calls SerpApiIngestor — the one deliberate live integration (read-only public Google News).

MarketSignal
dedup by source_urn

One row per article persisted to local Postgres. (Named MarketSignal — see the gotcha below.)

ProcessSignalJob
Sidekiq · per-signal

Runs InfranodusBridge.analyze (stub). If a structural gap closes → an REA ValueEvent + LettaWitness.post_pattern (no-op).

Turbo Streams
after_*_commit broadcast

The row appears / updates live on the dashboard and the SBPI projection re-ranks in-memory.

Why the SBPI projection moves

BrandRegistry is the single source of truth for both the stack rank and actor extraction — which reads the company named in the headline, not the news source. So ingesting brand news re-ranks the projection. The delta is bounded: +0.3 per closed gap, capped at +14, projection capped at 100, so a burst reads as momentum without breaking the 0–100 scale.

Demo recipe — ingest in sequence and watch the stream fill and the projection re-rank: VantaDrataSprinto.

04 — Data model

REA value-flow — not a 16×8 grid

Honoring the vault's corrections: Resource-Event-Agent value-flows across three temporal layers, mapped to the sbpi.ttl upper ontology.

signals  model: MarketSignal

columnmeaning
source_urnunique signal identity (dedup key)
actor_urncompany named in the headline
engine_sourcegoogle_news, …
payload_bodytitle + snippet
metadata_dumpfull API JSON (jsonb)
processing_stateingested · processed · failed

value_events  REA EconomicEvents

columnmeaning
event_typeEconomicEvent · Transformation
temporal_layerobservation · plan · recipe
resource_classCapital · Intelligence/Narrative · Relational/Network · Infrastructure
bridged_gap_idthe InfraNodus gap that closed
quantity_modifierweight on the SBPI delta

05 — Project map

Where everything lives

Cold-start read order: README → the isolation core → the brand registry → the process job → the ingestor → the three adapters → the dashboard view.

~/Documents/projects/aethelgard/
├── CLAUDE.md                         agent orientation + non-negotiable rules
├── README.md                         canonical run / revert / isolation summary
├── config/initializers/
│   └── aethelgard.rb                 ISOLATION CORE — posture + adapter wiring (read first)
├── lib/aethelgard/
│   ├── brand_registry.rb             single source of truth: stack rank + actor extraction
│   └── fixtures.rb                   deterministic replay fixtures for the stubs
├── app/jobs/
│   ├── ingest_signals_job.rb         enqueues a SerpApi sweep
│   └── process_signal_job.rb         per-signal bridge → ValueEvent → broadcast
├── app/services/
│   ├── serp_api_ingestor.rb          live Google News (the one live integration)
│   └── aethelgard/adapters/
│       ├── infranodus_bridge.rb      stub — replay fixtures, no socket
│       ├── letta_witness.rb          no-op the only write path
│       └── report_studio.rb          stub — replay stack rank
├── app/models/{market_signal,value_event}.rb
├── app/controllers/{dashboards,ingestions}_controller.rb
├── app/views/dashboards/{show,_signal_row}.html.erb
└── db/migrate · schema.rb · seeds.rb

Gotchas already encoded — don't re-hit these

Signal shadows Ruby's stdlib ::Signal and breaks Signal.trap (Puma/Sidekiq) → the model is MarketSignal with self.table_name = "signals".

Sidekiq 7.3.x ✗ connection_pool 3.x — positional pop(timeout) removed → connection_pool pinned ~> 2.5.

Foreman tears down the whole stack when any process exits; tailwindcss:watch exits without a TTY → for headless verification run web + sidekiq as separate processes.

06 — Stage-2 roadmap

What's next, in risk order

Stage-1 is complete and paused. It is not wired into any cron, automation, or deploy, and stays a sandbox until a Stage-2 decision is made.

Flip the InfraNodus adapter live lowest risk

Read-only /analyze first — gap verdicts become real structural analysis instead of deterministic stubs. The registered next_action; safe because /analyze does not write.

Live Report Studio pulls medium

Real per-vertical stack ranks from the Worker-API instead of replay fixtures.

Letta Witness write path live highest care

The one true mutation. Stays a no-op until everything else is proven.

The dynamic agentic ingest matrix Stage-2 proper

Onboarding intake → ingestion classifier agent → custom stream engine: Farcaster Hub, GitHub commits/issues, specialized SerpApi queries.

Corrections to carry — do not regress

✕ No MuninnDB
Aspirational only. Cognitive primitives = Letta + InfraNodus + the RDF/SHACL ontology. Treat as a future adapter.
✕ No 16×8 matrix
Use REA value-flow + the ValueFlows vocabulary.
✕ No GEM framework
The lens is Negative Space / structural gaps; the score is SBPI, derived — not a new framework.
✕ Don't re-implement the brain
Aethelgard ingests and visualizes. Vault + Oxigraph stay canonical; Report Studio = generation.

07 — Agent read-in

For the agent picking this up

A second Claude Code agent, rooted in the totem-terminal vault, can get fully caught up from one document. The code is reachable from the vault via a gitignored symlink — read access without breaking physical isolation.

The single read-in doc

Project map, pipeline, isolation recap, REA model, Stage-2 roadmap, and a consolidated index of every scattered source.

projects/Totem-framework/AETHELGARD-AGENT-ONBOARDING.md

Code access from the vault

Gitignored symlink → the standalone repo. Read any file through it without the vault's git ever tracking the code.

projects/Totem-framework/aethelgard-code/~/Documents/projects/aethelgard