martbost f27388a322 Chatbot: catch the PIF question when nobody says "PIF", and stop inventing references
Follow-on to the risk rewrite. Two gaps it exposed.

Members ask this without the word PIF: "should I fund their first package", "can I
buy it for them", "can I front someone the $20". Those were falling through to the
AI, which answered reasonably but told the member to "read the full warning on your
training page" - a page section that does not exist and that they would go looking
for. The pattern now also matches a paying verb plus an explicit for-someone-else
phrase, so these get the full canned answer with the risk in it. It deliberately
needs BOTH halves: "which package should I buy" must not be stolen.

The prompt now forbids sending anyone to a warning, guide or page section that is
not in the PAGES list, and requires plain ASCII (the model was emitting non-breaking
hyphens in "Wi-Fi").

Fixed two first-match-wins routing bugs, one of them mine from the previous commit:
"what do I get for buying a package" was returning the commission split, because I
had widened the earnings pattern to "what do I get" when it should only ever have
been "what do I get paid". And "should I buy the $20 package" previously matched
nothing at all and burned an AI call on a question we have a written answer for.

CANNED is an ordered list, so any pattern edit can silently steal a neighbour. The
suite now pins a 19-case routing table across PIF, price, earnings and the tank, so
the next person to widen a regex finds out immediately. qa/chatbot-parse.mjs is 35
assertions. qa/run.sh member: 0 bugs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 05:41:54 -05:00
2026-09-14 05:40:26 -05:00
2026-09-14 05:40:26 -05:00

InstantAdPay — site

Membership advertising with immutable on-chain settlement. Zero-dependency Node server (RM Circle pattern): static pages + JSON API + SSE ledger.

Architecture

  • server.js — http server: pages, /api/*, /join/<id> sponsor links, SSE feed
  • chain.js — contract reader + persistent event indexer (free public RPCs)
  • auth.js — SIWE wallet sign-in (EIP-4361), sessions in the volume
  • accounts.js — site-side records only (free members, last-touch sponsor attribution, handles). The CHAIN is the source of truth for money/credits.
  • public/ — landing, live ledger, member area; no client libraries

Chain flip (rehearsal → mainnet)

Everything chain-specific lives in data/config.json (volume): {contract, chainId, chainName, explorer, rpcs, deployBlock}. Defaults point at the Amoy rehearsal deployment. Launch = deploy the mainnet contract, wipe accounts.json/sessions.json/chain-index.json, PATCH /api/admin/chain with the mainnet values, set rehearsal:false via /api/admin/site. Same code, different config.

Run

PORT=3100 node server.js       # DATA_DIR defaults to ./data

Admin API auth: Authorization: Bearer $ADMIN_PASSWORD.

Spec: ../CONTRACT-SPEC.md (v1.0.3-frozen). Contracts: ../contracts/.

Chatbot knowledge is part of every change

chatbot.js answers members two ways: CANNED regex answers and systemPrompt() for the AI. Any change that a member could ask about (a new pane, a rule, a price, a limit, a fix they noticed) is not done until both are updated in the same commit, and KNOWLEDGE_DATE in chatbot.js is bumped. The QA runner (bash qa/run.sh public) fails when a release note on the live site is newer than that date.

S
Description
InstantAdPay membership advertising site
Readme 39 MiB
Languages
JavaScript 78.8%
HTML 17%
CSS 4.1%
Shell 0.1%