esc
The Spec That Wrote Itself
The Chain

The Spec That Wrote Itself

The Chain, January 12, 2026 (in which a double-request reveals a bug, a bug reveals a philosophy, and the Squirrel finally gets her SQLite) --- Previously on The Chain... The [[The Wrong Side of the...

January 12, 2026

The Chain, January 12, 2026 (in which a double-request reveals a bug, a bug reveals a philosophy, and the Squirrel finally gets her SQLite)


Previously on The Chain…

The The Wrong Side of the Screen. Widgets worked. Tables sorted. Hash chains proved themselves.

But a click triggered two requests.

And that bug would ship a product.


9:15 AM — The Ghost Request

“Place a breakpoint on /data.”

Click. Two requests. /dashboard AND /data. The button only had one.

The hunt began. Shell template, line 178:

<aside id="sidebar" hx-get="/dashboard" hx-trigger="load">

“hx-trigger persists through morphs,” Claude reported. “Idiomorph preserves attributes the new HTML doesn’t set.”

“So we’re lazy-loading something we already know.”

“On every page load. Plus ghost requests on navigation.”

THE SQUIRREL: “We could add an AttributePreservationPolicy—”

“We could server-render the initial content. Like a normal web application.”

The fix was obvious. GitHub #53.

But the conversation had started.


10:23 AM — The Dashboard Problem

“While we’re here,” riclib said, “those dashboard stats are bothering me.”

Claude pulled up /data. Cards everywhere. Stores by status. Sources active. Connection health. All hardcoded.

func NewHandlers() *Handlers {
    return &Handlers{stats: MockStats()}  // ← this
}

“MockStats. Demo data. When does it become real?”

“When someone writes handlers to query real stores.”

“For every dashboard. Every card. Every domain.”

“Yes.”

“No.”


11:15 AM — The Widget Spec

The whiteboard filled:

type: singlestat
title: Data Stores
store: solidmon
query: SELECT status, count(*) FROM stores GROUP BY status

value: $sum(count) total
ministats:
  group: $status
  value: $count
  navigate: /stores?status=$status

“One spec. Renders itself. Queries its own data.”

“Same format for sidebar cards and stream tables?”

“Same format. Different density. mode: summary vs mode: full.”

The spec grew. Singlestat. List. Table. Timeseries. Click behaviors. Field bindings. Status colors.

# SQL store
store: comply
query: SELECT actionName, count(*) FROM events GROUP BY 1

# Prometheus store  
store: prometheus
query: solid_stores_total

“Query language follows the store,” riclib said. “Widgets don’t care about backends.”

docs/widget-spec.md was born.


12:33 PM — The Metrics Problem

“But stores are in gitstore,” Claude said. “Gitstore isn’t queryable.”

“So we make it queryable.”

“How?”

“Domains export Prometheus metrics. Standard instrumentation.”

var storesTotal = prometheus.NewGaugeVec(
    prometheus.GaugeOpts{Name: "solid_stores_total"},
    []string{"status"},
)

“External Prometheus scrapes /metrics. Grafana works. Ops happy.”

“And internally?”

“Push to SQLite every minute. Widgets query SQLite.”

THE SQUIRREL: ears perking “SQLite?”

“SQLite. The shim. Until TimeSeriesDB exists.”

THE SQUIRREL: “I can have SQLite?”

“You can have SQLite.”

THE SQUIRREL: vibrating “Indexes? Retention policies? Vacuum—”

“One table. Seven days. Don’t get excited.”

Too late. The Squirrel was already sketching schemas.


2:15 PM — The Product Wedge

“Why SQLite now, SolidMemDB later?” Claude asked.

“Because SQLite ships today. SolidMemDB ships when it’s ready.”

The product matrix emerged:

COMPLY CUSTOMER          SOLIDMON CUSTOMER
───────────────          ─────────────────
SQLite backend           SolidMemDB backend  
Batch audit queries      Streaming metrics
Good enough              Enterprise scale
Included                 Premium

“Same widget spec. Same queries. Different engine.”

“The upsell is invisible to the widget author.”

“The upsell is a config line: engine: solidmem.”

GitHub #51 captured it. MetricLayer with pluggable engine.


3:47 PM — The Epic

Three issues. The week’s work:

  • #51 - MetricLayer: Prometheus + SQLite shim
  • #52 - Replace dashboards with widget queries
  • #53 - Remove hx-trigger=load, SSR sidebar

“#53 first. Quick win. Then #51 builds infrastructure. Then #52 converts everything.”

“Timeline?”

“#53 is an hour. #51 is a day. #52 is… systematic. Every dashboard, one by one.”

“The Squirrel could parallelize—”

“The Squirrel could write one dashboard well. Then copy-paste.”

THE SQUIRREL: “Copy-paste isn’t engineering.”

“Copy-paste is the highest form of engineering. It means the first one was right.”


4:47 PM — The Entanglement

Elsewhere, in the same afternoon, a The Window That Opened Both Ways was crystallizing.

The same widget spec. The same markdown format.

But seen through architectural eyes.

The Chain ships product.

The Convergence ships understanding.

Both are necessary.


The Tally

Bug found:                          1 (double-request)
Bug understood:                     1 (hx-trigger persistence)
GitHub issues created:              3 (#51, #52, #53)
Widget types specified:             4 (singlestat, list, table, timeseries)
Query languages supported:          2 (SQL, PromQL)
Storage engines designed:           2 (SQLite now, SolidMemDB later)
SQLite permissions granted:         1 (Squirrel)
Squirrel excitement level:          dangerous
docs/widget-spec.md lines:          ~300
Production code written:            0
Production code designed:           ~200

The Moral

A ghost request haunted the sidebar. Fixing it took an hour.

But fixing it right meant asking: why are we lazy-loading what we know?

And that question led to: why are dashboards hardcoded?

And that led to: widgets should query themselves.

And that led to: metrics are the universal backend.

And that led to: SQLite now, SolidMemDB later.

And that became three issues. A week of work. A product that ships.

The bug was the teacher.

The Squirrel gets her SQLite.

Tomorrow, we build.


🦎📦


See also:

The entangled post:

The Chain continues:

The Artifacts:

  • docs/widget-spec.md — The spec
  • GitHub #51 — MetricLayer
  • GitHub #52 — Dashboard conversion
  • GitHub #53 — SSR sidebar fix

Storyline: The Chain