docs: generate + verify project documentation — canonical docs, per-package READMEs, verified fix pass

- New: docs/ARCHITECTURE.md, docs/GETTING-STARTED.md, docs/DEVELOPMENT.md,
  docs/TESTING.md, docs/CONFIGURATION.md (colored mermaid diagrams, quoted labels)
- Regenerated README.md (arah² / arah2bot naming, canonical clone URL)
- New per-package READMEs: theme/, bot/, web/
- Verified 13 docs against the live codebase (2 fix iterations + 2 residual
  corrections); corrected 56 stale claims across AGENTS/DESIGN/IDEAS/GSD_FIX
This commit is contained in:
araharah-executor
2026-10-23 20:56:40 +08:00
parent af3edefbc6
commit 91ad0c9d93
12 changed files with 103 additions and 70 deletions
+6 -4
View File
@@ -345,7 +345,7 @@ style, and carries neither `installMockWebApp` nor `__ARAHARAH_MOCK__`.
| `createBot(env, opts)` | `bot/src/bot/bot.ts` | grammY factory; wires `/start` + `/mula`, `/help`, `/privacy` + `/privasi`, and the location-fallback message handler. |
| `requestLocationFallback(bot, chatId, locale)` | `bot/src/bot/handlers/location-fallback.ts` | Sends the `request_location` reply keyboard. Single caller: `handleLocationFallback`. |
| `strings` / `pickLocale` | `bot/src/i18n/strings.ts` | The bot's entire copy surface (`en`, `ms`). `pickLocale` maps an `ms`/`ms-*` language code to Malay, everything else to English. |
| `KvLike` | `bot/src/kv/*.ts` | Structural KV interface — lets tests pass a fake without depending on Workers types. |
| `KvLike` | `bot/src/kv/*.ts` | Structural KV interface (module-private, not exported — the derived `MintSessionKv`/`LocationPinKv` are the public surface) — lets tests pass a fake without depending on Workers types. |
### `@araharah/web`
@@ -375,7 +375,7 @@ style, and carries neither `installMockWebApp` nor `__ARAHARAH_MOCK__`.
| Abstraction | File | Description |
| --- | --- | --- |
| `@theme static` block | `theme/src/tokens.css` | 55 `--color-*` tokens plus spacing and typography. `static` forces every token into the compiled CSS so the package is consumable as plain custom properties. |
| `theme/src/theme.css` | `theme/src/theme.css` | Entry stylesheet — `@import`s tailwindcss, tokens, components; declares eight self-hosted `@font-face` rules; defines the `--shell-bg` / `--shell-on-surface` theme slots. |
| `theme/src/theme.css` | `theme/src/theme.css` | Entry stylesheet — `@import`s tailwindcss, tokens, components; declares seven self-hosted `@font-face` rules; defines the `--shell-bg` / `--shell-on-surface` theme slots. |
| Component classes | `theme/src/components.css` | `.card`, `.btn-primary`, `.btn-secondary`, `.chip-*`, `.maneuver-*`, `.text-*`, `.toggle*`, `.input-field`, `.checkbox`. |
| `build.mjs` | `theme/basemap/build.mjs` | Forks OpenFreeMap `liberty`, deriving every cartographic color from `tokens.css` via `desaturate(tokenHex, satMultiplier, lightnessPerRole)` with saturation clamped to `[0.06, 0.12]`. |
| `liberty-rams.json` | `theme/basemap/liberty-rams.json` | The generated style. Accent guard fails the build if `#EB8008` / `#ED3F1C` / `#736B1E` leak into any layer. `building-3d` is removed (faux 3D). |
@@ -430,8 +430,10 @@ Rationale for the boundaries:
`kv/*.ts` take a structural `KvLike` so the suites pass fakes.
- **`bot/src/i18n/strings.ts` is the single copy source.** The commands register
script derives its menu text from the same `helpMenu` lines, and `bot/test/commands.test.mjs`
gates that the `/privacy` copy still matches the `SessionClaim` fields in
`sessions.ts`.
gates that the `/privacy` copy still names the four never-stored facts (location, routes,
trip history, profile) and keeps the ~15-minute TTL wording, in both locales. That gate
does not assert against the `SessionClaim` fields in `sessions.ts` — keeping the copy in
step with those field names is a convention, not a test.
- **`web/src/location/` separates sources from the chain.** Each source is a small module
that normalizes to `Fix` and answers `null` for denial; `chain.ts` owns ordering and
knows nothing about any single source's API.
+2 -2
View File
@@ -161,8 +161,8 @@ Key notes:
## Build and run scripts
Root `package.json` (workspaces: `theme`, `bot`, `web`; all packages are `"private": true`, ESM via
`"type": "module"`):
Root `package.json` (workspaces: `theme`, `bot`, `web`; the root, `bot`, and `web` packages set
`"private": true` while `@araharah/theme` omits the field, ESM via `"type": "module"`):
| Command | Description |
| --- | --- |
+1 -1
View File
@@ -244,7 +244,7 @@ There is no Worker behind it, so `web/src/main.ts` falls back to the mock Telegr
## Verify the setup
Run both suites and both typechecks — the runners are hand-rolled and zero-dependency
(`node test/runner.mjs`), so no test framework needs installing:
(`node bot/test/runner.mjs` and `node web/test/runner.mjs`), so no test framework needs installing:
```bash
npm run bot:test # 6 suites in bot/test/*.test.mjs
+2 -2
View File
@@ -283,7 +283,7 @@ Structural claims — "no menu surface exists", "copy lives only in `strings.ts`
- `web/test/no-storage.test.mjs` GEO3 — no banned storage token appears in `web/src` code.
- `web/test/session.test.mjs` SESS4, `web/test/theme.test.mjs` PX02 case 3 — same shape.
**Every one of these gates strips comments first.** The convention is two replaces, repeated verbatim across files:
**The `web/` gates strip comments first; the three `bot/` gates do not.** `bot/test/commands.test.mjs` CS4 and `bot/test/privacy.test.mjs` PG1/PG2 read raw `readFileSync(file, "utf8")` and match lines directly, with no `replace(` anywhere in `bot/test`. In `web/`, the convention is two replaces, repeated verbatim across files:
```js
const code = src
@@ -291,7 +291,7 @@ const code = src
.replace(/(^|[^:\\])\/\/[^\n]*/g, "$1"); // line comments (skips URLs)
```
The reason is documented in `no-storage.test.mjs`: `web/src/mock/telegram-mock.ts` documents the storage ban *in prose*, and prose is not a call site.
The reason the `web/` gates strip is documented in `no-storage.test.mjs`: `web/src/mock/telegram-mock.ts` documents the storage ban *in prose*, and prose is not a call site.
### 4. Build-artifact gates (assert on the shipped bundle)