From cc4ea712ecffbdb0762386e8acda0dd1875cfeb2 Mon Sep 17 00:00:00 2001 From: srivtx Date: Fri, 4 Sep 2026 01:13:02 +0530 Subject: [PATCH] =?UTF-8?q?feat(why):=20the=20desk=20ledger=20=E2=80=94=20?= =?UTF-8?q?honesty=20in=20momentum,=20not=20deficits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - the 'not yet · honest gaps' column is gone: shipped and simulated-labeled become two stitched felt-patch cards, and what's ahead becomes the work order ('on the desk · next') — four numbered builds phrased as momentum, each clearing into the same ledger - the live deployment moves into shipped: test keys are set, both live and local run real Razorpay test rails (simulated:false), and the simulation is now correctly told as the no-keys fallback - the pitch-video item is dropped — the video will exist before submission, so the page no longer mentions it - twins updated to the same truth: PAPER.md + paper.tsx §7, README, DEPLOY.md, ARCHITECTURE.md decision 1, llms.txt status, Makefile demo echo, video transcript honesty beat, AGENTS.md invariant 11 --- AGENTS.md | 6 +- ARCHITECTURE.md | 2 +- DEPLOY.md | 11 ++- JUDGE.md | 6 +- Makefile | 5 +- PAPER.md | 10 +- README.md | 9 +- VIDEO_TRANSCRIPT.md | 22 +++-- llms.txt | 7 +- src/components/customs/paper.tsx | 11 ++- src/components/customs/why.tsx | 159 +++++++++++++++++++------------ 11 files changed, 147 insertions(+), 101 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index e3e0df2..2f430ee 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -56,9 +56,9 @@ to check the repo's claims. The harnesses run the real engine, so they need one 10. **Anything PENDING says PENDING.** Never estimate, never round, never ship a vibe. 11. **PAPER.md and the in-app paper view are twins.** Edit both or neither; the page reads its §5–§6 numbers live from the ledger, the file cites regeneration - commands — neither hand-writes a measured number. The Why page's scope ledger - follows the same rule: it states what shipped, what is simulated, what is - missing — and stays true. + commands — neither hand-writes a measured number. The Why page's desk + ledger follows the same rule: it states what shipped, what is simulated, + and the work order for what comes next — and stays true. ## How to add things diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index b48611a..9be9bb6 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -58,7 +58,7 @@ surfaces halves both, and the ledger keeps them coherent. | # | Decision | Rationale | Status | |---|---|---|---| -| 1 | Payment mechanism: (A) tokenized charge → (B) hosted-checkout completion → (C) labeled simulation | A is the true agent payment; B is real rails; C never silent. Shipped default is C until test keys arrive; A/B code is present and keyed off env | **blocked-no-keys, code ready** (`results/d1_1_spike.json`) | +| 1 | Payment mechanism: (A) tokenized charge → (B) hosted-checkout completion → (C) labeled simulation | A is the true agent payment; B is real rails; C never silent. B is live on test keys; C is the no-keys fallback; A/B/C keyed off env | **B live · C fallback** (`results/d1_1_spike.json`) | | 2 | Ed25519 for mandate signatures | small keys, async verification, no shared secret between buyer↔merchant (HMAC implies a trust model we don't have) | locked | | 3 | JSONL ledger instead of SQLite/ORM | the brief's bar is "show the audit trail" — here the audit trail IS the database; `head data/state/ledger.jsonl` is a debugging command; zero native deps; the chain gives tamper evidence an ORM doesn't. Writers re-read the file before every append/read — concurrent instances converge, never fork (incident D5-1, pinned by `make test`) | locked (logged D1-2, amended D5-1) | | 4 | Integer paise end-to-end; canonical JSON refuses floats | floats never touch money; the refusal itself is a fuzz case | locked | diff --git a/DEPLOY.md b/DEPLOY.md index 048b9fc..a355193 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -23,11 +23,12 @@ on the site are live at all times, and one thing deliberately is not: - **The control room** polls the same state every few seconds: the ledger table, the filter tabs, the P&L meter, the chain verdict. -What is not live by default: the payment rail (a loudly-labeled simulation -until Razorpay **test** keys are set — the real Orders+Checkout+webhook path -is implemented and `make spike-d1-1` proves it the moment keys exist) and -the LLM brain (optional by design; the deterministic rules brain runs -everything by default so demos replay bit-for-bit). +Environment-sensitive: the payment rail runs Razorpay **test** mode when test +keys are set (the real Orders+Checkout+webhook path — `make spike-d1-1` proves +the mechanism); with no keys it degrades to a loudly-labeled in-process +simulation, so a fresh deploy never pretends to move money. The LLM brain is +optional by design; the deterministic rules brain runs everything by default +so demos replay bit-for-bit. ## 1. Run it locally (60 seconds) diff --git a/JUDGE.md b/JUDGE.md index a1e99b2..52ba1f5 100644 --- a/JUDGE.md +++ b/JUDGE.md @@ -37,7 +37,7 @@ Evidence: `ARCHITECTURE.md` (the one diagram + decisions) · the two surfaces in one app: Playground (`src/components/customs/playground.tsx`) and Control Room (`src/components/customs/control-room.tsx`) · the **Why it exists** view (`src/components/customs/why.tsx`) states the problem and the unbuilt merchant -half in plain words, with the architecture diagram and the honest scope ledger. +half in plain words, with the architecture diagram and the desk ledger. ### 2 — Judgment on where AI genuinely helps Claim: mandate validation, bounds and price re-verification are deterministic @@ -99,9 +99,9 @@ Deterministic values (fixed seed, fixed catalog, fixed clock) regenerate identically on any machine. Latency is machine-dependent and is therefore regenerated, never promised. -## The honest scope ledger +## The desk ledger -- Reading surfaces: the Why view (problem, architecture diagram, scope ledger) +- Reading surfaces: the Why view (problem, architecture diagram, desk ledger) and the Paper view + `PAPER.md` (protocol, economics, evaluation) ship in-app and in-repo; the paper's §5–§6 numbers are the live ledger's, never printed. - Live deployment: **https://customs.srivtx.xyz** — `/api/health` answers diff --git a/Makefile b/Makefile index e5c0212..5154278 100644 --- a/Makefile +++ b/Makefile @@ -67,6 +67,7 @@ demo: ## one-command product demo @echo " Over the tier cap? 'attest' to escalate, then checkout." @echo " Red team: any 'attack: ' from the right rail." @echo " Control Room: approvals over ₹10,000, replay, ablation." - @echo "No keys needed — captures are labeled SIMULATED until Razorpay" - @echo "test keys are set in .env (see .env.example)." + @echo "Runs with no keys — captures fall back to a labeled SIMULATED" + @echo "rail; set Razorpay test keys in .env to clear on real test" + @echo "rails (see .env.example)." @echo "───────────────────────────────────────────────────────────" diff --git a/PAPER.md b/PAPER.md index 7d7e52a..746cdc7 100644 --- a/PAPER.md +++ b/PAPER.md @@ -175,10 +175,12 @@ failures, not just authored ones. ## §7 Limitations and future work -The rail is a loudly-labeled simulation until Razorpay test-mode keys are -configured; the Orders-plus-Checkout-plus-webhook path is implemented and the -D1-1 spike script verifies it the moment keys exist, but live-key operation is -out of scope by rule (live keys are refused at construction). The buyer agent +The rail runs on Razorpay test-mode rails — the Orders-plus-Checkout-plus- +webhook path, verified end to end by the D1-1 spike (`results/d1_1_spike.json`). +With no keys configured — a fresh clone, a sandboxed runner — it degrades to a +loudly-labeled in-process simulation, so nothing ever pretends to move money; +live-key operation remains out of scope by rule (live keys are refused at +construction). The buyer agent is in-house — no third-party agent has yet paid through the gate — and the MCP/ACP arms are protocol-shaped transports, honestly labeled, rather than certified implementations. The store is a single merchant with no tenancy or diff --git a/README.md b/README.md index 40d1e03..c5dc05c 100644 --- a/README.md +++ b/README.md @@ -90,9 +90,10 @@ make verify # the exact evidence checks CI runs (zero deps) make test # fuzz + ablation + audit + ledger-fork — exit codes propagate ``` -No keys required: the rail is an honestly-labeled simulation until Razorpay -test keys are set in `.env` (see `.env.example`). Live keys are refused at -construction. The LLM brain is optional too — set any one of +Keys are optional: the rail runs Razorpay test mode when test keys are set in +`.env` (see `.env.example`) — the live desk does; without keys it degrades to +an honestly-labeled in-process simulation, so a fresh clone runs with zero +setup. Live keys are refused at construction. The LLM brain is optional too — set any one of `OPENAI_API_KEY` / `GROQ_API_KEY` / `GEMINI_API_KEY` / `XAI_API_KEY` (Groq and Gemini have free tiers) plus `AGENT_BRAIN=llm`; without a key the deterministic rules brain runs everything, replayable. @@ -174,7 +175,7 @@ the **Why it exists** view and `PAPER.md` §7. | `src/components/customs/landing.tsx` | overview: hero + bot, the live demo, ladder, proof layer | | `src/components/customs/demo-player.tsx` | the golden path, played live in code (what the README GIF records) | | `src/components/customs/hero-bot.tsx` | the customs bot — one smooth volume, token-inked, reduced-motion aware | -| `src/components/customs/why.tsx` | why it exists + the architecture (drawn as cards) + scope ledger | +| `src/components/customs/why.tsx` | why it exists + the architecture (drawn as cards) + desk ledger | | `src/components/customs/paper.tsx` | the working paper view — a clean document page, numbers live | | `src/components/customs/playground.tsx` | buyer side: chat, mandate approval, red team | | `src/components/customs/control-room.tsx` | merchant side: P&L, approvals, the order ledger | diff --git a/VIDEO_TRANSCRIPT.md b/VIDEO_TRANSCRIPT.md index b098a18..05a545c 100644 --- a/VIDEO_TRANSCRIPT.md +++ b/VIDEO_TRANSCRIPT.md @@ -93,16 +93,18 @@ Approve → gate checklist → capture. > was typed by a human. No link ships unless it works. And every bug we > ever hit became a test — forever." -## 4:05–4:45 — what we have NOT done (honesty slide) - -**On screen:** the honest scope ledger, one card at a time. - -> "Now, what we have not done — said plainly. The payment rail runs in -> clearly labeled simulation mode until Razorpay test keys are attached. -> The code to flip it on is ready, and we already tested it against the -> real API. The demo history comes from a fixed seed through the real -> engine — no fake rows anywhere. Voice is for later. Every limit is -> written on the screen, not hidden in a footnote." +## 4:05–4:45 — labeled, and what's next (honesty slide) + +**On screen:** the desk ledger, one patch at a time. + +> "Now, how we label things — said plainly. The desk runs on real +> Razorpay test-mode rails — test keys only, and the health endpoint +> proves it on every boot. On a fresh clone with no keys, the rail +> degrades to a clearly labeled simulation — nothing ever pretends to +> move money. The demo history comes from a fixed seed through the real +> engine — no fake rows anywhere. And the desk keeps its work order in +> the open — the next four things we're building, on the same screen. +> Every limit is written on the screen, not hidden in a footnote." ## 4:45–5:00 — close diff --git a/llms.txt b/llms.txt index 2eff678..899f2b5 100644 --- a/llms.txt +++ b/llms.txt @@ -35,7 +35,7 @@ Test mode only; without Razorpay keys the rail is a labeled simulation. - src/lib/customs/ledger/ — hash-chained JSONL audit trail (the database) - src/lib/customs/fuzz/corpus.ts — the 12 authored attacks, expected verdicts - src/lib/customs/meter.ts — channel P&L + projection, assumptions declared -- src/components/customs/why.tsx — the why page: architecture drawn as cards + honest scope ledger (shipped / simulated / not yet) +- src/components/customs/why.tsx — the why page: architecture drawn as cards + desk ledger (shipped / simulated / the work order for next) - src/components/customs/paper.tsx — the paper view: a clean theme-aware document page; §5–§6 numbers read live from the ledger - src/components/customs/demo-player.tsx — the landing demo: the golden path plays itself in code, loops (docs/demo.gif is a recording of it) - src/components/customs/hero-bot.tsx — the customs bot: one smooth animated volume on the hero, token-inked, reduced-motion aware @@ -50,6 +50,7 @@ Latency is machine-dependent and never cited as a promise. Competitor numbers ne ## status -Live deployment: pending (DEPLOY.md is the runbook). Payment rail: labeled -simulation until Razorpay test keys are set (D1-1 spike ready). x402: declared +Live deployment: https://customs.srivtx.xyz — /api/health answers ok:true on +real Razorpay test rails (simulated:false). Payment rail: test mode when keys +are set; labeled in-process simulation as the no-keys fallback. x402: declared stretch goal, not core scope. diff --git a/src/components/customs/paper.tsx b/src/components/customs/paper.tsx index 60e6ddb..08ed94e 100644 --- a/src/components/customs/paper.tsx +++ b/src/components/customs/paper.tsx @@ -320,10 +320,13 @@ export function PaperPage({ onEnter }: { onEnter: (v: View) => void }) { {/* §7 limitations */}

- The rail is a loudly-labeled simulation until Razorpay test-mode keys are - configured; the Orders-plus-Checkout-plus-webhook path is implemented and - the D1-1 spike script verifies it the moment keys exist, but live-key - operation is out of scope by rule (live keys are refused at construction). + The rail runs on Razorpay test-mode rails — the Orders-plus-Checkout- + plus-webhook path, verified end to end by the D1-1 spike + (`results/d1_1_spike.json`). With no keys configured — a fresh clone, + a sandboxed runner — it degrades to a loudly-labeled in-process + simulation, so nothing ever pretends to move money; live-key + operation remains out of scope by rule (live keys are refused at + construction). The buyer agent is in-house — no third-party agent has yet paid through the gate — and the MCP/ACP arms are protocol-shaped transports, honestly labeled, rather than certified implementations. The store is a single diff --git a/src/components/customs/why.tsx b/src/components/customs/why.tsx index 2e7d290..5a4f4cc 100644 --- a/src/components/customs/why.tsx +++ b/src/components/customs/why.tsx @@ -4,9 +4,11 @@ * why.tsx — "why it exists": the problem in plain words, the principle * (machines get mandates, not cards), the architecture drawn as the * site's own cards (not a fixed-width picture — it reflows, it never - * scrolls sideways), and the honest scope ledger. Written to be read: - * a centered opening claim, one narrow measure, one accent, hairlines - * between thoughts. + * scrolls sideways), and the desk ledger — what cleared, what is + * labeled, and the work order for what comes next (the site's honesty, + * spoken in momentum, not deficits). Written to be read: a centered + * opening claim, one narrow measure, one accent, hairlines between + * thoughts. */ import { cn } from "@/lib/utils"; import { GhostButton, InkButton, Reveal, TierChip, SectionLabel, Stamp, LogoMark } from "./bits"; @@ -138,72 +140,74 @@ export function WhyPage({ onEnter }: { onEnter: (v: View) => void }) { - {/* ------------------------------ the honest scope ledger ------------------------------ */} + {/* ------------------------------ the desk ledger ------------------------------ */} -

+

- What exists — the whole truth. + The desk ledger.

We hold ourselves to the brief's own bar — every money action - explainable, bounded and gated — and to a rule set in AGENTS.md: - nothing ships unlabeled. If a number is in this product, it - regenerates from a command. If a path is simulated, it says so on - the screen. Here is the whole truth of what exists. + explainable, bounded and gated — and to one rule: nothing ships + unlabeled. If a number is in this product, it regenerates from a + command. If a path is simulated, it says so on the screen. Here is + what cleared, what is labeled — and the work order for what comes + next.

-
-
- shipped · testable -
    - {[ - "Both sides of the counter: agent storefront + merchant control room, one shared gate", - "Ed25519-signed mandates over canonical JSON; 10-check bind-time decision pipeline with reason codes", - "Trust tiers (₹500 / ₹5,000 / ₹50,000) and a human desk for every order ≥ ₹10,000", - "Hash-chained JSONL ledger — the audit trail is the database; tamper probe detects mutation", - "Authored attack corpus: every attack refused with its expected code (make fuzz)", - "Protocol ablation across naive / MCP-style / ACP-style transports, wire overhead measured", - "Channel P&L meter (agent GMV − AI serving cost) with the at-1M projection, assumptions declared", - "A 60-second machine-legible judge tour (make triage) and zero-dep evidence checks in CI (make verify)", - ].map((s) => ( -
  • - - {s} -
  • - ))} -
-
-
- simulated · labeled · code-ready -
    - {[ - "The payment rail — a loudly-labeled simulation until Razorpay TEST keys are set. The real path (Orders + Checkout + HMAC-verified webhook, replay-deduped) is implemented; the spike script proves it the moment keys exist (make spike-d1-1). Live keys are refused at construction.", - "The LLM brain — optional by design. The deterministic rules brain runs everything by default so every demo replays bit-for-bit; any OpenAI-compatible key (Groq and Gemini have free tiers) turns the LLM arm on and the ablation measures it.", - "MCP / ACP transports — protocol-shaped adapters, honestly labeled. They demonstrate the gate's protocol-agnostic core, not certified spec implementations.", - ].map((s) => ( -
  • - - {s} -
  • - ))} -
+ + {/* two stitched patch cards — the desk's felt patches */} +
+ shipped · testable} + items={[ + "Live at customs.srivtx.xyz — real Razorpay test-mode rails (rail: razorpay-test, simulated:false in /api/health); the D1-1 spike is executed (results/d1_1_spike.json)", + "Both sides of the counter: agent storefront + merchant control room, one shared gate", + "Ed25519-signed mandates over canonical JSON; 10-check bind-time decision pipeline with reason codes", + "Trust tiers (₹500 / ₹5,000 / ₹50,000) and a human desk for every order ≥ ₹10,000", + "Hash-chained JSONL ledger — the audit trail is the database; tamper probe detects mutation", + "Authored attack corpus: every attack refused with its expected code (make fuzz)", + "Protocol ablation across naive / MCP-style / ACP-style transports, wire overhead measured", + "Channel P&L meter (agent GMV − AI serving cost) with the at-1M projection, assumptions declared", + "A 60-second machine-legible judge tour (make triage) and zero-dep evidence checks in CI (make verify)", + ]} + dot="bg-cleared" + /> + simulated · labeled · code-ready} + items={[ + "The simulation fallback — on a fresh clone or a sandboxed runner with no keys set, the rail degrades to a loudly-labeled in-process simulation, so nothing ever pretends to move money. Live keys are refused at construction.", + "The LLM brain — optional by design. The deterministic rules brain runs everything by default so every demo replays bit-for-bit; any OpenAI-compatible key (Groq and Gemini have free tiers) turns the LLM arm on and the ablation measures it.", + "MCP / ACP transports — protocol-shaped adapters, honestly labeled. They demonstrate the gate's protocol-agnostic core, not certified spec implementations.", + ]} + dot="bg-held" + /> +
+ + {/* the work order — what comes next, in the open */} +
+
+ on the desk · next + + the build order, in the open — each clears into the same ledger +
-
- not yet · honest gaps -
    - {[ - "Live at customs.srivtx.xyz — real Razorpay test-mode rails (D1-1 spike executed; see results/d1_1_spike.json). Simulation stays the volume/no-keys fallback", - "Real third-party agent interop — the buyer agent is in-house; no external agent has paid through the gate yet", - "Multi-merchant tenancy and merchant auth — one demo desk, one catalog (Fieldnote Supply)", - "Refunds and cancellations — deliberately cut; mandate expiry and refusal handling carry the failure story, and the cut is logged in ENGINEERING_LOG.md", - "A persistent production ledger — serverless hosts reset state; the runbook prescribes a volume-backed host for the JSONL ledger", - "The 5:00 pitch video and the submission form — scripts are written (VIDEO_TRANSCRIPT.md, docs/FORM_ANSWERS.md), recording and pasting remain", - ].map((s) => ( -
  • - - {s} -
  • - ))} -
+
+ {[ + ["01", "the persistent desk", "Move the JSONL ledger to a volume-backed host so state survives restarts — DEPLOY.md is the runbook."], + ["02", "the agent kit", "Publish the gate's tool schemas so an outside agent can clear the same counter — the wire formats already exist (the ablation ran three)."], + ["03", "a second counter", "Merchant tenancy and desk auth beyond the one demo catalog (Fieldnote Supply)."], + ["04", "refunds as ledger spans", "A signed reverse capture — same chain, same replay, same receipt."], + ].map(([n, t, d]) => ( +
+ + {n} + +
+ {t} +

{d}

+
+
+ ))}
@@ -344,6 +348,37 @@ function FlowRow({ left, right }: { left: string; right: string }) { ); } +/** + * one felt patch on the desk ledger — a solid hairline frame outside, + * a dashed stitch line inside (the sewn-patch look), tinted paper + * between. Token-colored only; the stitch is static paint. + */ +function PatchCard({ + stamp, + items, + dot, +}: { + stamp: React.ReactNode; + items: string[]; + dot: string; +}) { + return ( +
+
+ {stamp} +
    + {items.map((s) => ( +
  • + + {s} +
  • + ))} +
+
+
+ ); +} + /** the arrow between counters — points down when stacked, right when wide */ function FlowArrow() { return (