Tapoo Oracle is the analytics extension of Tapoo. It is an
Observable Framework app that reads Tapoo agent-api gameplay
logs and reports agent behavior against the Tapoo Agentic Behavior Rubric.
corepack enable pnpm
make install
make devThen open http://localhost:3000.
Tapoo Oracle accepts Tapoo log exports shaped like:
{
"name": "tapoo",
"platform": "http://0.0.0.0:5500/agents",
"device": "Chrome/152.0.0.0 on macOS",
"version": "2.6.1",
"storageVersion": "5",
"mode": "agent-api",
"downloadedAt": "2026-09-13T13-50-30+02-00",
"entries": [],
"entriesChecksum": "0x5ca3981fae1b8fff"
}Two things are required: name must be tapoo, and entries must hold at least one readable entry.
Everything else is read where an export carries it and reported as "not recorded" where it does not,
because a log is whatever the Tapoo that wrote it produced - exports from before a field existed are read
exactly as they always were. A mode other than agent-api is analyzed too, with a warning that the
rubric describes no other kind of round.
entriesChecksum is the exception that can refuse a load: where a log file records one, its entries are
hashed and the load fails if the two disagree. It is a check, not a signature - the algorithm is public and
keyless, so it catches an accidental save or a hand edit rather than a deliberate rewrite. A file that
records none is read as it always was; nothing follows from the absence.
Input that is not a Tapoo export is rejected. The analyzer does not guess at unknown field names.
.
├─ scripts # CLI, hooks, and the bundling build
├─ src
│ ├─ app.ts # The single entry the page imports
│ ├─ lib # Contracts, rubric engine, adapters, and views
│ │ └─ _snapshot_ # Vendored test payloads; never production input
│ ├─ index.md # Observable page
│ └─ oracle.css # App styles
├─ staged # Generated: the root Observable builds and previews from
├─ Makefile
├─ observablehq.config.js
└─ package.jsonsrc/lib/log-contract.ts validates Tapoo JSON, share-link.ts handles remote URLs and share tokens,
maze.ts decodes mazes, and rubric-context.ts reads a round into the facts rubric-report.ts
answers the rubric against. report-adapters.ts prepares those results for the views. staged/ is generated and gitignored.
| Command | Description |
|---|---|
make install |
Install locked dependencies |
make audit |
Scan the lockfile for known vulnerabilities via OSV Scanner |
make lint |
Run eslint |
make test |
Run Vitest |
make quality |
Run type checking, lint, and tests |
make ci |
Run install, audit, lint, tests, and build |
make dev |
Start Observable preview |
make build |
Build the stripped static site into ./public |
make serve |
Serve ./public; /r/* is rewritten to the app with status 200 |
make deploy |
Build, post-process, and deploy the finished output to Observable |
make agentic-analysis LOGS="a.json" |
Run the terminal report |
make docker-build |
Build the Docker image |
make docker-run |
Build and serve the app in a container on port 3000 |
make docker-shell |
Open an interactive shell inside the container |
Requires Docker or a compatible runtime (e.g. Colima).
Build the image:
make docker-buildServe on http://localhost:3000:
make docker-runThe image runs pnpm build at image-build time and serves the pre-built static site. Re-run make docker-build after source changes.
Open an interactive shell:
make docker-shellThe shell mounts the project root and a named node_modules volume, so edits on the host are visible inside the container without reinstalling dependencies.
Set ORACLE_SITE_BASE when the site is not served from a domain root — a GitHub Pages project site
lives under /<repo>/:
ORACLE_SITE_BASE=/tapoo-oracle/ pnpm run buildHosts with rewrite support should serve index.html for /r/* with status 200. GitHub Pages has no
rewrite rules, so its custom 404.html performs a JavaScript redirect; report links work in browsers
but return 404 to clients that do not execute JavaScript.
Log contents are analyzed in the browser. Downloads time out after 20 seconds and stop at 25 MiB.
Share tokens are reversible and are sent in the /r/<token> request path, so the source URL can appear
in host logs and browser history. Never put credentials directly in a URL. Do not use Gist for
proprietary data: secret gists are unlisted, not private. Sensitive reports need authenticated storage,
CORS, short-lived signed access, retention limits, and a deployment whose request-log policy is trusted.
- Node.js
24 - pnpm
11.25.0 - OSV Scanner — required locally for
make audit(brew install osv-scanner)
Apache License 2.0. See LICENSE.