GUESTBOOK.EXEcontact.exe
CONTINUITY

</continuity>

CONTINUITY

A hash-chained decision ledger that answers questions after the author leaves

38.5 pts

macro-F1 the fine-tuned tagger gains over few-shot prompting the same 2B base model, on a held-out split

0 → 8

of 36 questions about the firm answered from model weights alone — untuned base, then fine-tuned on the ledger

3 layers

of ledger immutability, one of which survives a privileged session disabling every trigger on the table

no key

semantic search over the whole corpus runs inside the browser tab — no API key, no round trip

SPECIFICATIONS

ROLESOLO BUILD
YEAR2026
TYPEWEB + DESKTOP
STATUSLIVE
STACKtypescript · react · vite · tauri 2 · supabase · postgresql · pgvector · transformers.js +4 more
LINKS[live ↗][github ↗]
AVAILABILITYcontinuity-nu.vercel.app

Quantitative trading desks lose strategies when the people who wrote them leave.

A strategy continuity layer for quantitative trading desks.Quant firms lose strategies when the people who wrote them leave; Continuity captures the reasoning behind strategy research at the moment it happens, hash-chains it into an append-only ledger, and turns that ledger back into knowledge-risk analytics, regulator-shaped handover packs and a searchable memory of the desk.

README.TXT: CONTINUITY (20 KB)[full readme →]

== WHAT IS THIS ==

────────────────────────────────────────

A strategy continuity layer for quantitative trading desks. Quant firms lose strategies when the people who wrote them leave; Continuity captures the reasoning behind strategy research at the moment it happens, hash-chains it into an append-only ledger, and turns that ledger back into knowledge-risk analytics, regulator-shaped handover packs and a searchable memory of the desk. A 2B model fine-tuned on the ledger answers questions about the firm offline, and the product ships the screen that shows the model losing to the record when it is wrong. Live, with every row of data synthetic and labelled as such.

== </the problem> ==

────────────────────────────────────────

Quantitative trading desks lose strategies when the people who wrote them leave. The court record has the extreme version — a strategy earning about a billion a year losing more than half its profits in the month after two traders resigned — but the ordinary version is worse because it is invisible: PM turnover of 15 to 20 percent a year against strategies that outlive their author's seat, and nothing anywhere that records *why* a parameter was set where it was set. Regulators have asked for exactly this in writing for years and firms answer with documentation written after the fact. The industry built world-class platforms for research data and none for research reasoning, which is the half that walks out of the building.

role & context

Solo: the Postgres schema and the immutability it enforces, the React front end, the Tauri desktop shell, the hybrid retrieval stack, both fine-tunes and the evaluation harness that scores them. Built to a fixed external brief against a hard deadline, then continued as a personal project once the brief was satisfied — which is why the limitations are the longest section in the write-up rather than the shortest.

== </my approach> ==

────────────────────────────────────────

Treat the reasoning as an append-only, hash-chained ledger and make everything else a projection of it. Capture ambiently rather than asking anyone to write documentation: a post-commit hook files commits that touch strategy code and a model drafts the record, a person approves it with one keystroke, and meeting transcripts enter through the same path transcribed inside the browser. Then earn the schema back — knowledge-risk analytics scored per strategy, replay of the decision genealogy at any past moment, regulator-shaped handover packs generated as pure functions from rows, and retrieval that runs in the browser tab with no key and no round trip. Finally, fine-tune two small models on the desk's own records so the tagging and the answering work with no network at all, and build the screen that shows the model losing to the record when it is wrong.

== </the story> ==

────────────────────────────────────────

A federal court filing describes a strategy earning about a billion dollars a year losing more than half its profits in the month after two traders resigned. Portfolio-manager turnover at multi-manager funds runs 15 to 20 percent a year, so the average strategy outlives the seat of the person who wrote it. Finance already mandates the fire drill — two weeks of block leave with system access cut — and nobody scores whether the desk would pass it.

The industry solved the adjacent problem completely. Firms built world-class platforms for research *data*; nobody built one for research *reasoning*. The reasoning lives in a departed person's head, in a Slack thread nobody can find, and in the fifteen minutes of a meeting that evaporated as soon as it ended. Regulators have been asking for it in writing for years: RTS 6 wants a record of when each material algorithm change was made, who made it, who approved it and its nature; SR 11-7 wants documentation a stranger could read; SYSC 25.9 says handover material should include judgement and opinion, not just facts and figures.

Continuity is less a dashboard than a database with an opinion. The schema is the product and the interfaces exist to feed it and to ask it questions. Every meaningful thing in the system is an event in an append-only, hash-chained ledger first and a projection everywhere else. A post-commit hook files each commit as an artifact and asks for a decision record when the commit touches strategy code; a model writes the draft and a person approves it with one key. Meeting transcripts enter through the same path, transcribed inside the browser tab with no audio leaving it.

What the ledger buys is everything downstream of it. Knowledge risk is scored per strategy — bus factor adapted from the truck factor, Herfindahl concentration borrowed from competition economics — and never per person, because a product that ranks individuals is a different and much worse product. Replay is nearly free on an append-only record, because the state at a past moment simply *is* the events up to it: drag a scrubber and the decision genealogy assembles, then turns amber the moment it passes a resignation. Ask a question about a departed colleague and the answer comes back in their own words, quoted and cited, with the line above it saying they resigned three days ago.

Then the harder half. A 2B model, LoRA fine-tuned on this machine, tags every decision with one of seven types and a risk flag, so the classification path needs no network at all. A second fine-tune puts the ledger itself into the weights, so the model answers questions about the desk offline. That one both works and is the thing this project got wrong first, and the run that failed is still in the repository, because a negative result that gets deleted teaches nobody anything.

Every colour, radius, motion duration, claim and sprint entry in the repository is checked by a script, and `pnpm check` runs six of them. That is not thoroughness for its own sake: three of those guards were found, mid-build, to be passing while the rule they protected was broken.

== </architecture> ==

────────────────────────────────────────

Two shells, one front end, one database. A React and Vite application, wrapped in a Tauri 2 desktop shell that adds a tray icon and a global quick-capture hotkey, served on the web as a static SPA with a handful of Vercel functions beside it. Supabase Postgres underneath, with row-level security, Realtime and pgvector. The embedding model runs in the browser tab.

`events` is the source of truth and everything else — decisions, links, scores — is a projection. Immutability is three layers deep, and they are deliberately not equivalent. Update and delete are never granted on the table, so they do not exist for the application role. A trigger raises on update and delete, and a separate statement-level trigger raises on truncate, because truncate does not fire row-level triggers at all. And a unique constraint on `(firm_id, prev_hash)` with `nulls not distinct` rejects both a grafted branch and a second genesis row — which is the only one of the three that survives a privileged session turning every trigger off. A `before insert` trigger takes an advisory lock and chains each row to the sha256 of the one before it.

Retrieval is hybrid and runs entirely client-side: a 384-dimension embedding model downloaded to the tab, blended with BM25, with a keyword-only fallback when the model cannot download. The lexical half is not decoration. Asked why the expiry window is capped, dense embeddings return everything about the expiry book and rank the record that literally answers it below them; and because the embedding model returns a cosine around 0.75 for text with nothing to do with the corpus, a semantic-only threshold has to be set inside the noise.

The two models are separate jobs. The tagger is a LoRA fine-tune of a 2B Qwen with a strict parser: anything that is not one line of the expected JSON with a known label is counted as unparseable and excluded from the class metrics rather than coerced to a default class. The firm model is a second fine-tune on the ledger's own records, evaluated on a fact probe and a refusal set that are scored separately and must be read together.

Compliance documents are pure functions from rows to markdown — the same corpus always produces the same bytes, which is the only thing that makes a pack hash worth storing. Reads and exports append to the same ledger they read from, so `My record` can show every member what was captured from them and everyone who has looked at it.

With no credentials at all the application still runs: it generates the same corpus in the browser that the seed script loads into Postgres. Not a mock — literally the same generator, so what renders with no backend is what the database contains after seeding, and the two cannot drift apart without a test failing.

== </key features> ==

────────────────────────────────────────

Three layers of immutability, and they are not equivalent

Update and delete are never granted; triggers raise on update, delete and separately on truncate, which does not fire row-level triggers at all; and a unique constraint on (firm_id, prev_hash) rejects a grafted branch and a second genesis row. Measured under `session_replication_role = replica`: every trigger is off, all three mutations succeed, and the constraint still holds. So the triggers are tamper resistance and the chain is tamper evidence, which is a weaker claim than the design started with and a true one.

Verify recomputes every hash in the browser

Asking the server whether the server is right proves nothing, so the page rebuilds each hash from the event's own contents. That cost an exact reimplementation of Postgres jsonb rendering in TypeScript — key ordering by length before byte value, a space after every colon, a loud refusal for numbers that would not round-trip — checked against a live Postgres over fifteen awkward payloads. The sweep halts on the first broken row, because everything after it is unverifiable rather than wrong.

Answers in a departed person's voice are quoted, never generated

Every line is a sentence they actually typed, with the record it came from named. Nothing is rephrased in their voice. When the corpus holds nothing they wrote on the subject, the product says so — and that answer is worth as much as the others, because it names a gap that was invisible until somebody needed it.

Retrieval with no API key and no round trip

The embedding model runs in the tab, blended with BM25 and falling back to keyword search when it cannot download. The relevance floor is measured rather than chosen: answerable questions score 0.88 to 0.93 blended, unanswerable ones top out at 0.47, and the floor sits at 0.60 in the gap — a gap that only exists because of the lexical half, since the embedding model returns a cosine near 0.75 for text with nothing to do with the corpus.

A fine-tune reported next to the arm that makes it mean something

The tagger scores a perfect macro-F1 on a held-out split, which alone is equally consistent with a good model and a trivial benchmark. Few-shot prompting the same base model with all seven classes and two worked examples each scores 0.6155, so the 38.5-point gap is the claim — and the caveat that the corpus is template-generated travels with it everywhere it is printed.

Scored per strategy, never per person

Bus factor adapted from the truck factor, Herfindahl concentration borrowed from competition economics, and a vacation-readiness score named after a fire drill finance already runs and nobody grades. There is a top-holder field so the departure simulation can name orphaned work and no per-person score anywhere in the product — any view that would rank individuals is a design bug.

Reads and exports are events on the same ledger

Opening another desk's strategy or exporting a handover pack appends a row, and every member can see what was captured from them and everyone who read it. Exporting also prompts for a one-line justification recorded on that access event: a justification nobody can see changes nothing, one the subject can see changes quite a lot.

== </key decisions> ==

────────────────────────────────────────

DECISION 01

**Extractive, never generative, when the voice belongs to a named person.** Ask about a departed colleague and every line of the answer is a sentence they actually typed, quoted, with its source named. A generated sentence in a named person's voice is a thing they never said presented as a thing they said, and in a product whose entire argument is that the record is trustworthy that is not a small problem. It is also stronger this way: what lands with a reader is recognition, not fluency. When the corpus holds nothing they wrote about the question, the product says exactly that — an answer worth as much as the others, because it names a gap that stayed invisible until somebody needed it and found nobody left to ask.

DECISION 02

**A draft looks like a draft until a person approves it, and approving costs one keystroke.** That keystroke is the product. It is the difference between a system that documents a desk and one that generates plausible text about a desk, and it costs about ten seconds. A machine-written record that is visually indistinguishable from a human-approved one is the fastest way to lose the trust the whole thing is asking for.

DECISION 03

**Every score is a property of a strategy, never of a person.** There is a top-holder field so the departure simulation can name orphaned work, and there is no per-person score anywhere in the product. Any view that would rank individuals is treated as a design bug rather than a feature request. The dollar figure is deliberately narrow for the same reason: it sums the attributed revenue of books where that person is the top holder *and* the bus factor is one, and a book somebody else has also written about is listed as covered and not counted at all.

DECISION 04

**Reading is an event.** Opening another desk's strategy or exporting a pack appends to the same ledger. Every member can see what was captured from them and everyone who looked at it. That screen is the acceptability condition for the rest of the product: capture that is continuous and ambient is only defensible if the people it captures can see what it holds, and a promise in a contract is not the same thing as a screen. If the view is uncomfortable to show somebody, the capture behind it was wrong, not the view.

DECISION 05

**Verify does not ask the server whether the server is right.** The page rebuilds every hash from the event's own contents in the browser and compares it with what the ledger stored. That required reproducing Postgres jsonb rendering exactly in TypeScript — keys ordered by length before byte value, a space after every colon, and a loud refusal for numbers that would not round-trip rather than a hash that silently differs — checked against a live Postgres over fifteen deliberately awkward payloads. The sweep halts on the first broken row rather than running to the end, because everything after a rewritten row is unverifiable rather than wrong, and reporting it as wrong would claim more than the evidence supports.

DECISION 06

**Tamper resistance and tamper evidence are named separately, because they are not the same claim.** Under `set session_replication_role = replica` every trigger on the events table is off and update, delete and truncate all succeed; the unique constraint still holds. So the triggers are resistance and the chain is evidence. Claiming the rows cannot be edited would be false, and the true version is stronger: an edited row produces a different sha256 and the verify sweep names the exact row where history was rewritten. One limit is stated plainly rather than buried — an attacker who edits a row *and* recomputes every hash after it produces an internally consistent chain. That is true of every hash chain, and it is exactly what the external anchor is for. The chain proves internal consistency; the anchor proves the chain existed in that shape at a point in time. Neither claim covers the other.

DECISION 07

**The model is not allowed to outrank the record, and the product ships the screen where it loses.** Asked why the expiry window is capped, retrieval returns five real passages, the best at 0.93, including the decision that answers it — and the fine-tuned model replies that it cannot answer. The product strikes that sentence through, labels it *not found in the record*, and puts the passages that do answer it above. Grounding that only ever agrees with the model is decoration.

DECISION 08

**The failed training run stays in the repository.** The first firm-model run scored 9 of 36 on facts and 0 of 12 on refusals: the tuning worked and the model still failed, because it learned the ledger and also learned that declining is never the answer. The cause was data design rather than training — 33 refusals against 686 answerable pairs, made worse by an expansion step that cached paraphrases for facts and not for refusals, so what reached training was 6.6 percent. Rebalancing to 20.1 percent moved refusal accuracy from 0.0 to 0.4167 while fact accuracy moved 0.25 to 0.2222, inside the noise of a 36-item probe. The finding is that the share of refusals in the training data controls refusal behaviour almost directly and costs very little accuracy, and it only exists because the bad run was kept.

DECISION 09

**A perfect score is reported with the arm that makes it mean something.** The tagger scores macro-F1 1.0000 on a held-out split, which on its own is equally consistent with a good model and a trivial benchmark. The few-shot arm — the same base model, the same parser, the same split, all seven classes described in the system prompt with two worked examples each — scores 0.6155. The 38.5-point gap is the number worth quoting, and the caveat that the corpus is template-generated travels with it everywhere it appears.

DECISION 10

**Stop training when the measurement stops moving.** Training was cut at 300 of 1000 configured iterations: validation loss was 0.002 at iteration 200 and that checkpoint already scored a perfect validation macro-F1, so the remaining 800 iterations would have taken half an hour to measure nothing.

== </what i learned> ==

────────────────────────────────────────
>

The weaker claim was the stronger one. "The rows cannot be edited" was false, and the version that replaced it — the triggers are tamper resistance, the chain is tamper evidence — is both true and more persuasive, because it survives the obvious follow-up question instead of collapsing on it. The limit nobody had asked about yet, that recomputing every downstream hash produces an internally consistent chain, is now printed on the page rather than waiting to be discovered.

>

A perfect score is not evidence until something bounds it. Macro-F1 1.0 says nothing on its own; the few-shot arm at 0.6155 is what converts it into a finding, because it separates "the model learned something" from "the benchmark was trivial". The arm that could embarrass the result is the one that makes it publishable.

>

Refusal behaviour is a data-design property, not a training property. The first firm-model run scored 0 of 12 on refusals with 6.6 percent refusals in the training data; rebalancing to 20.1 percent moved it to 0.4167 and cost almost nothing in fact accuracy. Neither more iterations nor a higher rank would have found that, and keeping the failed run is the only reason the comparison exists at all.

>

Three of the repository's own guard scripts were passing while the rule they protected was broken. A guard that has never failed is not evidence that the rule holds; it is an untested assertion. The contrast test that eventually caught --text-secondary at 6.87:1 against a stated 7:1 bar had been green the whole time, because the design document measured against the lightest surface rather than the darkest one text actually sits on.

>

Building the screen where your own model loses is worth more than the model. The grounding layer only means something because there is a documented case of it striking through the fine-tuned model's answer and putting the retrieved passages above it. A grounding layer that has only ever agreed with the model has not been shown to work.

next:

Two gaps a reviewer can legitimately attack, both named in the repo. The firm model's refusal accuracy is 0.4167 and that is not good enough — it still invents an answer more often than it declines, and the one lever known to move it, the share of refusals in the training data, has obvious headroom left and costs almost nothing in fact accuracy. And every number here is measured on a synthetic corpus generated from templates, so what would actually settle whether the tagger works is a few hundred records written by people who sometimes disagree with each other, labelled twice. External anchoring of the chain head is wired and waiting on a Bitcoin confirmation rather than on code.

typescript · react · vite · tauri 2 · supabase · postgresql · pgvector · transformers.js · mlx · lora · qwen3.5 · vitest

BUILD.TXT: CONTINUITY (9 KB)[the build record →]

== </what the audit found> ==

────────────────────────────────────────

The product's whole argument is that the record can be trusted, so the first thing audited was whether the database actually enforces that — and not in the way the design had assumed. Postgres was granted only select and insert on the events table, with triggers raising on update, delete and separately on truncate, since truncate does not fire row-level triggers at all and a single trigger looks like it covers a gap it does not. Measured rather than assumed: under `set session_replication_role = replica` every trigger on the table is off, and update, delete and truncate all succeed. So the trigger layer is tamper resistance and nothing more. The layer that survives is a unique constraint on `(firm_id, prev_hash)` with `nulls not distinct`, which rejects both a grafted branch and a second genesis row even with every trigger disabled. The honest description that came out of the audit — the triggers are tamper resistance, the chain is tamper evidence — is stronger than the claim it replaced, and it is the one that ships.

== </what was repaired> ==

────────────────────────────────────────

The verify page rebuilds every hash from the event's own contents rather than asking the server whether the server is right, and that required reproducing Postgres jsonb rendering exactly in TypeScript: keys ordered by length before byte value, a space after every colon, and a loud refusal for numbers that would not round-trip instead of a hash that silently differs. It is checked against a live Postgres over fifteen deliberately awkward payloads and then recomputes sixty seeded event hashes. Three of the repository's own guard scripts were found mid-build to be passing while the rule they protected was broken, which is why there are six of them now and why `pnpm check` runs all six. Several tests earned their place by failing first: the contrast test caught `--text-secondary` measuring 6.87:1 inside a recessed pane against a stated 7:1 bar, because the design document had measured against the lightest surface rather than the darkest one text actually sits on; the departure test caught a tag present on every decision in a strategy counting as covered ground, so as soon as one other person touched a book nothing in it looked orphaned; and the transcript parser test pins that a sentence containing a colon is not a speaker line, or "The rule is simple: cut size" gets attributed to a person named "The rule is simple". The largest repair is the first fine-tuning run of the firm model, and it is kept in the repository rather than deleted: it scored 9 of 36 on facts and 0 of 12 on refusals. The tuning had worked and the model had still failed, because it learned the ledger and also learned that declining is never the answer. The cause was data design, not training — that run authored 33 refusals against 686 answerable pairs, and the expansion step made it worse because facts had cached paraphrases and refusals did not, so what reached training was 6.6 percent.

== </what was measured> ==

────────────────────────────────────────

The tagger is a LoRA fine-tune of a 2B Qwen trained on the same laptop that ran the build, and on a held-out split the training never saw it scores macro-F1 1.0000, accuracy 1.0000, risk accuracy 1.0000 and zero unparseable outputs over 300 rows at 462 ms p50. The number worth quoting is not the 1.0 — a perfect score alone is equally consistent with a good model and a trivial benchmark. It is the 38.5-point gap to the few-shot arm: the same base model, the same parser, the same split, with all seven classes described in the system prompt and two worked examples each, scores 0.6155. So the task is not solvable by prompting, and the adapter has learned something a prompt cannot express. Rebalancing the firm model's training data from 6.6 percent refusals to 20.1 percent moved refusal accuracy from 0.0 to 0.4167 while fact accuracy moved 0.25 to 0.2222, which is inside the noise of a 36-item probe — the share of refusals in the training data controls refusal behaviour almost directly and costs very little accuracy. The untuned base scores 0 of 36 on facts about this desk and a perfect 12 of 12 on refusals by refusing everything, which is exactly why refusal accuracy must never be quoted on its own. Retrieval's relevance floor is measured rather than chosen: questions the corpus can answer score 0.88 to 0.93 blended and questions it cannot top out at 0.47, so the floor sits at 0.60 in the gap — and that gap only exists because of the lexical half, since the embedding model returns a cosine near 0.75 for text with nothing to do with the corpus.

== </decisions> ==

────────────────────────────────────────

DECISION 01

Answers about a departed colleague are extractive, never generated — every line is a sentence they actually typed, quoted, with its source named

because A generated sentence in a named person's voice is a thing they never said, presented as a thing they said. In a product whose entire argument is that the record is trustworthy, that is not a small problem. It is also stronger this way: what lands with a reader is recognition, not fluency.

DECISION 02

A model-drafted decision record looks like a draft until a person approves it, and approving costs one keystroke

because That keystroke is the difference between a system that documents a desk and one that generates plausible text about a desk, and it costs about ten seconds. A machine-written record visually indistinguishable from a human-approved one is the fastest way to lose the trust the whole product is asking for.

DECISION 03

Every score is a property of a strategy, never of a person — there is no per-person score anywhere in the product

because The analytics answer which books would be orphaned, not who is a liability. There is a top-holder field so the departure simulation can name orphaned work, and any view that would rank individuals is treated as a design bug rather than a feature request.

DECISION 04

Reading another desk's strategy and exporting a pack are themselves events on the same ledger, and every member can see what was captured from them and everyone who looked at it

because Capture that is continuous and ambient is only defensible if the people it captures can see what it holds, and a promise in a contract is not the same thing as a screen. If that view is uncomfortable to show somebody, the capture behind it was wrong, not the view.

DECISION 05

The verify page recomputes every hash client-side from the event's own contents instead of calling a server endpoint

because Asking the server whether the server is right proves nothing. It cost an exact reimplementation of Postgres jsonb rendering in TypeScript, tested against a live database, and that is the price of the page meaning what it says.

DECISION 06

The sweep halts on the first broken row rather than running to the end

because Everything after a rewritten row is unverifiable rather than wrong, and reporting it as wrong would be a stronger claim than the evidence supports.

DECISION 07

Semantic search runs entirely in the browser tab, with the embedding model downloaded to the client and a keyword fallback when it cannot load

because The product's argument is that the reasoning behind a strategy can be searched without leaving the building. Making that true in the demo turns an on-premise slide into a demonstration — and it is why the deployed site works with no API key at all.

DECISION 08

Retrieval is hybrid rather than dense-only, and the relevance floor is measured rather than picked

because Asked why the expiry window is capped, dense embeddings return everything about the expiry book and rank the record that literally answers it below them; BM25 supplies the exactness the vectors lack. The embedding model also returns a cosine around 0.75 for text with nothing to do with the corpus, so a semantic-only threshold has to be set inside the noise.

DECISION 09

Unparseable tagger output is counted and excluded from the class metrics rather than coerced to a default class

because Coercing would import the majority class as a free win, inflate accuracy, and hide exactly the template bugs the strict parser exists to surface.

DECISION 10

The fine-tuned model is not allowed to outrank the record, and the product ships a screen showing it losing

because Asked why the expiry window is capped, retrieval returns five real passages including the one that answers it, and the fine-tuned model replies that it cannot answer. The product strikes that sentence through, labels it not found in the record, and puts the passages above it. Grounding that only ever agrees with the model is decoration.

DECISION 11

The failed first training run stays in the repository

because A negative result that gets deleted teaches nobody anything, and this one carries the finding: refusal share in the training data, not training length or rank, is what controls whether a small model knows how to decline.

DECISION 12

Training stopped at 300 of 1000 configured iterations

because Validation loss was 0.002 at iteration 200 and that checkpoint already scored a perfect validation macro-F1, so the remaining 800 iterations would have taken half an hour to measure nothing.

DECISION 13

Compliance documents are pure functions from rows to markdown

because The same corpus always produces the same bytes, which is what makes a pack hash worth storing at all. Exporting also prompts for a one-line justification recorded on an access event: a justification nobody can see changes nothing, one the subject can see changes quite a lot.

DECISION 14

With no credentials the app generates the same corpus in the browser that the seed script loads into Postgres

because Not a mock — literally the same generator, so what renders with no backend is what the database contains after seeding, and the two cannot drift apart without a test failing.

LIMITS.TXT: CONTINUITY (2 KB)[where it doesn't work →]

== </where it doesn’t work> ==

────────────────────────────────────────

Every row of data is synthetic — the firm, the people, the strategies and the revenue figures are invented, and the product says so in its footer and beside every dollar amount. Database-level immutability is tamper resistance, not proof: the triggers stop mutation, the hash chain evidences it, and an attacker who edits a row and recomputes every hash after it produces an internally consistent chain — which is why the head is meant to be anchored externally, and that anchoring is not live, because a real receipt is pending for hours before a Bitcoin block confirms it. The tagger's perfect score is measured on a held-out split of a template-generated corpus, so it demonstrates that a 2B model can learn forty templates and cannot show it works on decisions a person wrote; the few-shot arm at 0.6155 is what proves the adapter is doing real work, not that the work generalises. The firm model's refusal accuracy is 0.4167 — it still invents an answer more often than it declines when asked something the ledger does not hold — and both it and the 0.2222 fact accuracy are measured on a 36-item probe and a 12-item refusal set, which are small. Two planned comparison arms against a frontier model were never run because the free-tier quota was exhausted, and they are recorded as omitted rather than reported as zero; the stronger version of that table has a frontier model also scoring near zero, which is what would prove the knowledge is genuinely proprietary rather than merely absent from a small model. The drafting and debrief routes need an API key that is not provisioned and return an honest 503 without one, and the on-prem tagger and the firm model run locally by design, so the deployed site reports them as unreachable rather than pretending. The desktop build is unsigned, printing from it is disabled because window.print() in the macOS webview produces a blank PDF and there is still no official Tauri print plugin, and rate limiting on the server routes is in-memory per instance, which is fine for a demo and is not a real rate limit.

LIVE · continuity-nu.vercel.app