release: public alpha 0.6.0 baseline

This commit is contained in:
JWeBot Contributors
2026-10-15 03:58:31 +08:00
commit d4242ae07c
238 changed files with 37724 additions and 0 deletions
+134
View File
@@ -0,0 +1,134 @@
# Edge Runbook
JWeBot Edge is the local source of truth for accepted events, command state,
provider work, acknowledgements, and final delivery.
## Routes
| Input after mention removal | Route | Execution |
|---|---|---|
| `/...` | Local | Kernel command or reviewed plugin |
| ordinary text | Chat | Direct DeepSeek client |
| `#...` | Cloud | Optional configured cloud agent |
The bot mention is read from the active profile. The public default is
`@JWeBot`.
## Steam
Commands:
```text
/steam
/steam在线
/steam游戏
/steam全部
/steam刷新
/steam时长 游戏名
/steam时长游戏名
/steam时长游戏名、玩家名
/steam时长游戏名人=玩家名
```
The configured Steam account supplies the owner ID and API key. At runtime the
provider:
1. uses private per-person SteamID mappings when configured, otherwise fetches
the public friend list;
2. batches public player summaries in groups of 100;
3. labels mapped accounts with their group display IDs and accepts their
private Steam query aliases;
4. fuzzy matches the requested game against the owner's public library;
5. falls back to scoped public libraries if the owner has no match;
6. requests the selected AppID for every scoped account with bounded
concurrency;
7. sorts public playtime descending and summarizes private/unavailable data.
For a player-specific query, `、`, `,`, `,`, `@`, or `人=` explicitly separates
the game from the player. The provider matches the live persona name and only
requests that account's game library; ambiguous matches are rejected instead
of guessed.
Steam access is fixed to `api.steampowered.com` through the configured loopback
Mihomo HTTP proxy. There is no direct-network fallback.
## Config
Inspect active profile metadata without printing values:
```sh
./tools/jwebot-config.py status
```
Validate and atomically regenerate:
```sh
./tools/jwebot-config.py activate <profile>
```
Services read:
```text
~/.config/jwebot/current/generated/runtime.env
```
Private context, debug state, incidents, and root evidence live outside Git as
documented in `config/README.md`.
## Health
```sh
runtime_python=${JWEBOT_RUNTIME_PYTHON:-/opt/jwebot/venv/bin/python}
printf '%s\n' '{"op":"health"}' |
"$runtime_python" ~/.local/lib/wechat-health-watch/jwebot_edge.py respond
"$runtime_python" ~/.local/lib/wechat-health-watch/jwebot_edge.py status
```
Expected:
- Edge and adaptive recorder active;
- `NRestarts=0` after the settle window;
- OCR queues empty;
- direct/cloud outboxes empty or actively progressing;
- SQLite `PRAGMA quick_check` returns `ok`;
- legacy OCR services disabled and inactive.
## Delivery Contract
- Fast ACK is persisted before GUI delivery.
- Final work starts independently from final GUI delivery.
- A final reply is not delivered until its ACK is visibly confirmed.
- Steam uses a dedicated progress ACK.
- ACK/local work may pass a queued final that has not started.
- Active GUI work is non-preemptive.
- The GUI sender remains strictly serial.
- Every final send rechecks the selected group fingerprint.
## Failure Handling
Provider failure:
- keep credentials and provider payloads out of logs;
- record only bounded error classes;
- retry through durable queue policy;
- do not bypass the configured proxy.
GUI uncertainty:
- never blindly replay a send after `send_started`;
- preserve the uncertain artifact in private incident state;
- require visual/operator confirmation before retry.
Group mismatch:
- skip delivery;
- keep the event ledgered;
- do not select or navigate to another group automatically.
## Telemetry
Telemetry may include step name, status, elapsed time, queue state, retry count,
and hashed event/group IDs. It must never include message bodies, sender names,
reply text, environment values, credentials, SteamIDs, or provider payloads.
+115
View File
@@ -0,0 +1,115 @@
# Production Deployment
Use this runbook only after a target host has passed the zero-to-running
bootstrap and staging gate.
## Inputs
- clean repository snapshot;
- active validated profile for the target runtime user;
- configured production Python;
- operator-provided SSH alias and local privilege elevation;
- ready WeChat main window on display `:1`.
Do not place hostnames, addresses, usernames, passwords, private keys, or
profile values in the repository or command history.
## Local Gate
```sh
PATH="$PWD/.venv/bin:$PATH" ./tools/check-local.sh
./tools/check-secrets.py --history
```
## Staging
Transfer a clean snapshot without `.git`, local profiles, virtualenvs, debug
state, captures, databases, or archives. On the target:
```sh
JWEBOT_RUNTIME_PYTHON=/opt/jwebot/venv/bin/python \
PATH="/opt/jwebot/venv/bin:$PATH" \
./tools/check-local.sh
```
Verify the active profile:
```sh
/opt/jwebot/venv/bin/python -m jwebot_config status
/opt/jwebot/venv/bin/python -m jwebot_config validate <profile>
```
## Pre-Cutover
Confirm:
1. WeChat main window is visible and meets minimum geometry.
2. Edge and adaptive recorder are active with stable restart counts.
3. Adaptive and legacy OCR queues are empty.
4. Edge direct/cloud outboxes have no failed backlog.
5. Edge SQLite `quick_check` is `ok`.
6. Legacy OCR services are disabled and inactive.
7. A restorable baseline exists.
## Coordinated Cutover
Elevate locally on the target and run:
```sh
JWEBOT_RUNTIME_PYTHON=/opt/jwebot/venv/bin/python \
./deploy/scripts/deploy-jwebot-production.sh \
/path/to/staged/JWeBot \
jwebot
```
The deployer prints an eight-stage progress bar and:
- records root and user service topology;
- copies root and user runtime files;
- backs up generated configuration;
- creates a SQLite online backup and runs `quick_check`;
- refuses non-empty queues or an unready WeChat window;
- installs the runtime;
- leaves legacy OCR disabled;
- verifies Edge health and adaptive restart stability;
- writes and verifies backup SHA-256 checksums;
- rolls back files, state, and unit topology on failure.
## Post-Cutover
```sh
systemctl --user is-active jwebot-edge.service
systemctl --user is-active wechat-ocr-adaptive-recorder.service
systemctl --user show wechat-ocr-adaptive-recorder.service \
-p NRestarts --value
```
```sh
printf '%s\n' '{"op":"health"}' |
/opt/jwebot/venv/bin/python \
~/.local/lib/wechat-health-watch/jwebot_edge.py respond
```
```sh
/opt/jwebot/venv/bin/python - <<'PY'
import sqlite3
from pathlib import Path
path = Path.home() / ".local/state/jwebot-edge/edge.sqlite3"
print(sqlite3.connect(f"file:{path}?mode=ro", uri=True)
.execute("pragma quick_check").fetchone()[0])
PY
```
Player-visible acceptance must use deliberate synthetic messages in the
configured group and confirm exactly one ACK and one final response.
## Rollback
If any gate fails:
1. stop further cutover attempts;
2. verify the coordinated deployer's rollback result;
3. confirm unit topology and SQLite integrity;
4. archive privacy-safe evidence under the active profile;
5. fix and rerun staging before another production attempt.
+138
View File
@@ -0,0 +1,138 @@
# Zero To Running
This runbook prepares a new apt-based Linux host without embedding any private
host, account, group, or provider value in the repository.
JWeBot does not install desktop WeChat itself. Install a compatible client,
create an X11/VNC desktop on display `:1`, sign in manually, and keep the main
window visible before deployment.
## 1. Obtain A Clean Snapshot
Clone or unpack the public repository. Before using a fork:
```sh
./tools/check-secrets.py --history
```
## 2. Prepare The Host
Run as root:
```sh
./deploy/scripts/bootstrap-jwebot.sh \
prepare \
/path/to/JWeBot \
jwebot \
default
```
The six-stage prepare flow:
1. installs OS packages for Python, X11 interaction, screenshots, clipboard,
and OCR fallback;
2. creates the runtime account when absent;
3. creates `/opt/jwebot/venv`;
4. installs runtime Python dependencies and JWeBot packages;
5. generates a private config profile;
6. creates private state directories.
## 3. Configure
Edit:
```text
/home/jwebot/.config/jwebot/profiles/default/
```
At minimum:
- set the bot mention and provider URLs in component TOML;
- put API keys only in `secrets/runtime.env`;
- configure Steam owner ID and loopback proxy when using `/steam`;
- put person aliases only in `context/people.json`;
- configure a notification argv adapter or leave it disabled;
- verify deployment paths.
Activate as the runtime user:
```sh
sudo -u jwebot -H /opt/jwebot/venv/bin/python \
-m jwebot_config activate default
```
## 4. Prepare The Desktop
The runtime expects:
- an X11 desktop at `DISPLAY=:1`;
- the runtime user's `.Xauthority`;
- a visible WeChat main window named `Weixin`;
- a maximized window large enough for the adaptive layout gate;
- loopback VNC on port `5901` for guarded input;
- no second process controlling the same GUI.
VNC/noVNC must remain loopback-only or be reached through an authenticated SSH
tunnel. Never expose it directly.
## 5. Verify
```sh
./deploy/scripts/bootstrap-jwebot.sh \
verify \
/path/to/JWeBot \
jwebot \
default
```
Verify checks runtime imports, required executables, profile validation,
repository config/privacy gates, and the visible WeChat window.
## 6. Deploy
```sh
./deploy/scripts/bootstrap-jwebot.sh \
deploy \
/path/to/JWeBot \
jwebot \
default
```
This invokes the coordinated production deployer. It does not bypass queue,
ready-window, health, SQLite, or restart-stability gates.
## 7. Acceptance
```sh
systemctl --user is-active jwebot-edge.service
systemctl --user is-active wechat-ocr-adaptive-recorder.service
```
```sh
printf '%s\n' '{"op":"health"}' |
/opt/jwebot/venv/bin/python \
~/.local/lib/wechat-health-watch/jwebot_edge.py respond
```
Send synthetic messages in the configured group:
```text
@JWeBot /version
@JWeBot /steam
@JWeBot /steam时长Dota2
```
Confirm one ACK, one final reply, no duplicate delivery, empty queues, stable
restart counts, and SQLite `quick_check=ok`.
## Non-Apt Hosts
Use `prepare` as a dependency manifest:
- install equivalent X11, OCR, Python, and clipboard packages;
- create the same runtime user and virtualenv;
- run `jwebot_config init/activate`;
- run the verify and coordinated deployment gates manually.
Do not translate package names into an unreviewed installer and run it directly
on production.