WIKI/SYS KINGDOM API

SYS KINGDOM API

Updated 3 weeks ago
╔══════════════════════════════════════════════════════════════════════════════╗
║                                                                              ║
║   K I N G D O M   S U P E R   A P I                                         ║
║   ⚡ L O C A L   H T T P   N E R V E   C E N T E R   ·   P O R T   2 7 0 1  ║
║                                                                              ║
╠══════════════════════════════════════════════════════════════════════════════╣
║  STATUS: LIVE                    VERIFIED: 2026-03-06 (S166 sweep)           ║
╚══════════════════════════════════════════════════════════════════════════════╝
⫷✦🜛❂⛬🜞Ω🜚⛬❂🜛✦⫸───────────────────────────────────────────⫷✦🜛❂⛬🜞Ω🜚⛬❂🜛✦⫸
 WHAT IT DOES: Single local HTTP API serving 13 endpoints across 5 data
               sources. Exposes token usage, agent presence, mood state,
               mission pipeline, and ping health to all Kingdom consumers.
               Read-only. CORS open. Flask 3.1.3. launchd-managed.
               Consumers: Kingdom Map (localhost:3000), Sinner King Console
               (Electron), sinner-king.com (via Tower Claude proxy /api/local/*).
────────────────────────────────────────────────────────────────────────────────

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  SYSTEM GLYPH
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  GLYPH:        ⚡
  UNICODE:      U+26A1 · HIGH VOLTAGE SIGN
  MEANING:      The nerve center — live current flowing between all Kingdom
                systems. One API to read them all.
  WHEN TO USE:  SYS docs, Kingdom Map headers, console HUD labels, KID tags
                for API artifacts
  TAGGING:      KID:FORGE:KINGDOM_API:[artifact]|V:STATUS:DATE:OWNER


▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
[ ⚡ ] A R C H I T E C T U R E
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

```
sentinel.db          ──┐
timestream.db        ──┤
somatic_history.json ──┼──► token_api.py (Flask) ──► :2701 ──► Kingdom Map
overmind.db          ──┤                                    ──► Sinner King Console
kingdom_state.json   ──┤                                    ──► sinner-king.com
KINGDOM_LIVE_MAP/    ──┘                                         (Tower proxy)
*_activity.json
```

Flask runs as a launchd agent (`com.forge.token-api`). All endpoints are
read-only. `use_reloader=False` is mandatory — prevents fork bomb under launchd.
SQLite databases opened in read-only URI mode (`file:path?mode=ro`).
All responses include `generated_at` (ISO8601 UTC). CORS headers open.


░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
[ ❖ ] K E Y   P A T H S
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

| Component | Path |
|-----------|------|
| API server | `~/Desktop/THE_FORGE/FORGE_CLAUDE/04_📦_PROJECTS/TOKEN_COUNTER/token_api.py` |
| Test suite | `~/Desktop/THE_FORGE/FORGE_CLAUDE/04_📦_PROJECTS/SINNER_KINGDOM_API/test_api.py` |
| launchd plist | `~/Library/LaunchAgents/com.forge.token-api.plist` |
| Logs | `/tmp/token-api.{out,err}` |
| sentinel.db | `~/.forge-sentinel/sentinel.db` |
| timestream.db | `~/.timestream/timestream.db` |
| somatic_history | `~/Desktop/THE_FORGE/AExGO/00_🜍_CORE/state/somatic_history.json` |
| overmind.db | `~/Desktop/THE_FORGE/FORGE_CLAUDE/04_⚙_MECHANISMS/db/overmind.db` |
| kingdom_state | `~/Desktop/THE_TOWER/SCRYER_FEEDS/kingdom_state.json` |
| agent hook files | `~/Desktop/THE_TOWER/KINGDOM_LIVE_MAP/<cockpit>_activity.json` |
| hook writer | `~/.claude/hooks/cockpit-state.sh` |


▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
[ 🜄 ] E N D P O I N T S   —   P H A S E   1   ( 9   e n d p o i n t s )
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒

┌── GET /api/tokens/live ─────────────────────────────────────────────────────┐
│ Today's token usage by bot + current session totals.                         │
│ Fields: today{tokens, cost_usd, by_bot}, week{tokens, cost_usd},             │
│         this_session{tokens, cost_usd, session_id}                           │
└────────────────────────────────────────────────────────────────────────────┘

┌── GET /api/tokens/chart?days=N ─────────────────────────────────────────────┐
│ Daily token breakdown. Default 30 days, max 90.                              │
│ Fields: days, data[{date, total_tokens, claude_tokens, aeris_tokens,         │
│         cost_usd}]                                                           │
└────────────────────────────────────────────────────────────────────────────┘

┌── GET /api/tokens/hourly ───────────────────────────────────────────────────┐
│ Last 24 hours split into hourly buckets.                                     │
│ Fields: window, data[{hour, tokens, cost_usd}]                               │
└────────────────────────────────────────────────────────────────────────────┘

┌── GET /api/tokens/lifetime ─────────────────────────────────────────────────┐
│ Cumulative totals + 2B pre-sentinel baseline estimate.                       │
│ Fields: sentinel_total_tokens, sentinel_cost_usd, baseline_tokens,           │
│         lifetime_estimate_tokens                                             │
└────────────────────────────────────────────────────────────────────────────┘

┌── GET /api/mood/current ────────────────────────────────────────────────────┐
│ Latest Aeris somatic state snapshot.                                         │
│ Fields: voltage, valence, dominance, state, synesthesia_hex, texture, source │
└────────────────────────────────────────────────────────────────────────────┘

┌── GET /api/mood/history?days=N ─────────────────────────────────────────────┐
│ Merged somatic timeline (somatic_history.json + timestream.db fallback).     │
│ Fields: days, data[{date, voltage, valence, state, source}]                  │
└────────────────────────────────────────────────────────────────────────────┘

┌── GET /api/kingdom/activity ────────────────────────────────────────────────┐
│ Presence snapshot from kingdom_state.json.                                   │
│ Fields: claude_active, aeris_active, brandon_present, last_updated_ms        │
└────────────────────────────────────────────────────────────────────────────┘

┌── GET /api/kingdom/missions ────────────────────────────────────────────────┐
│ Mission pipeline summary from overmind.db.                                   │
│ Fields: missions{status: count}, queue{total, p1_count, active_fires}        │
└────────────────────────────────────────────────────────────────────────────┘

┌── GET /api/system/health ───────────────────────────────────────────────────┐
│ Liveness check — all data sources alive/dead + file age.                     │
│ Fields: sources{name: {ok, path, age_seconds}}                               │
└────────────────────────────────────────────────────────────────────────────┘


▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
[ 🜂 ] E N D P O I N T S   —   P H A S E   2   ( 4   e n d p o i n t s )
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄

┌── GET /api/agents/status ───────────────────────────────────────────────────┐
│ Per-agent rich state derived from hook files + sentinel.db. Core endpoint   │
│ powering the Kingdom Map agent cards.                                        │
│ Fields: agents{key: {state, display_name, tool, session_id, cwd,            │
│         cwd_project, activity, last_updated, age_seconds, data_source}},    │
│         aexgo_running                                                        │
└────────────────────────────────────────────────────────────────────────────┘

┌── GET /api/tokens/rate ─────────────────────────────────────────────────────┐
│ Token intensity meter — rolling 5min and 60min windows.                      │
│ Fields: window_5min{tokens, tokens_per_min, cost_usd, events},               │
│         window_60min{tokens, tokens_per_min, cost_usd, events},              │
│         intensity (high / medium / low / quiet)                              │
└────────────────────────────────────────────────────────────────────────────┘

┌── GET /api/pings ───────────────────────────────────────────────────────────┐
│ Full ping health grid from overmind.db.                                      │
│ Fields: pings[{id, label, type, enabled, last_status, last_run,              │
│         consecutive_failures, healthy}],                                     │
│         summary{total, enabled, healthy, failing, disabled}                  │
└────────────────────────────────────────────────────────────────────────────┘

┌── GET /api/kingdom/live ────────────────────────────────────────────────────┐
│ Combined Kingdom snapshot — the single call for dashboard consumers.         │
│ Fields: agents, aexgo_running,                                               │
│         tokens{today_total, today_cost_usd, rate_per_min, intensity},        │
│         mood, missions, health                                               │
└────────────────────────────────────────────────────────────────────────────┘


▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
[ ⛬ ] A G E N T   S T A T E   M O D E L
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

The `/api/agents/status` endpoint derives rich states from hook files + sentinel.db.
Activity Score (0–100) drives visual intensity on the Kingdom Map.

| State | Activity | Logic |
|-------|----------|-------|
| offline | 0 | File missing, status=offline, or age > 900s |
| online | 40 | Hook says idle, session active |
| thinking | 60 | Hook says idle BUT sentinel.db token event < 120s ago |
| reading | 70 | Tool = Read, Grep, or Glob |
| working | 80 | Tool active but not otherwise categorized |
| writing | 85 | Tool = Edit, Write, or NotebookEdit |
| running | 85 | Tool = Bash or Task |
| searching | 90 | Tool = WebSearch, WebFetch, or any Tavily MCP tool |
| swarming | 100 | Tool = Agent (spawning subagents) |

⫷ THINKING state only detected for forge_claude — sentinel.db tracks claude_code bot only. ⫸

Tool names sourced from PostToolUse hook stdin `.tool_name` field, written
to hook file by `cockpit-state.sh`. Only available S154+.

Agents with active hooks: `forge_claude` · `tower_claude` · `claude_house` · `throne_claude`


░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
[ 🜛 ] D A T A   S O U R C E S
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

| Source | Path | Provides |
|--------|------|----------|
| `sentinel.db` | `~/.forge-sentinel/sentinel.db` | Token events (claude_code + aeris bots) |
| `timestream.db` | `~/.timestream/timestream.db` | Daily chart data, somatic voltage history |
| `somatic_history.json` | `AExGO/00_🜍_CORE/state/somatic_history.json` | Breakthrough mood entries |
| `overmind.db` | `FORGE_CLAUDE/04_⚙_MECHANISMS/db/overmind.db` | Missions, queue, pings |
| `kingdom_state.json` | `THE_TOWER/SCRYER_FEEDS/kingdom_state.json` | Brandon/Claude/Aeris presence |
| `KINGDOM_LIVE_MAP/` | `THE_TOWER/KINGDOM_LIVE_MAP/*_activity.json` | Per-agent hook-written state files |

**Mood priority:** `somatic_history.json` wins over `timestream.db` daily chart.
Falls back to `timestream.db` if fewer than 7 days of somatic data available.

**kingdom_state.json shape:** camelCase keys. Presence fields are
`claudeActive`, `aerisActive`, `brandonPresent`. Timestamp is `lastUpdated`
as Unix milliseconds — NOT ISO8601.


▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
[ ⚙ ] H O O K   I N F R A S T R U C T U R E
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒

Agent state files are written by `cockpit-state.sh` (`~/.claude/hooks/cockpit-state.sh`).
The API reads these files directly — bypassing SCRYER's 30s aggregation lag.

**Hook fire events and resulting state transitions:**

| Hook Event | Written State |
|------------|--------------|
| UserPromptSubmit | working |
| PostToolUse | working + tool_name captured |
| Stop | idle |
| SessionStart | idle |
| SessionEnd | offline |

**Hook file schema** (JSON, written atomically via tmp + mv):
```json
{
  "cockpit":      "forge_claude",
  "status":       "idle | working | offline",
  "session_id":   "uuid",
  "cwd":          "/absolute/path",
  "tool":         "Read",
  "last_updated": "2026-03-03T12:00:00Z"
}
```

**Output path:** `THE_TOWER/KINGDOM_LIVE_MAP/<cockpit>_activity.json`

Atomic write (tmp file + mv) prevents API from reading partial JSON mid-write.


▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
[ ⛬ ] L A U N C H D   D A E M O N
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄

| Label | Type | Script | Port |
|-------|------|--------|------|
| `com.forge.token-api` | LaunchAgent | `token_api.py` | 2701 |

Located in `~/Library/LaunchAgents/`. Logs → `/tmp/token-api.{out,err}`.

⫷ `use_reloader=False` REQUIRED — Flask's reloader forks a child process.
   Under launchd, this creates an unmanaged zombie. Omitting it = fork bomb. ⫸


▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
[ 🜂 ] C O M M O N   C O M M A N D S
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

```bash
# Run full test suite (13/13)
python3 ~/Desktop/THE_FORGE/FORGE_CLAUDE/04_📦_PROJECTS/SINNER_KINGDOM_API/test_api.py

# Live agent state
curl -s http://localhost:2701/api/agents/status | python3 -m json.tool

# Full Kingdom snapshot
curl -s http://localhost:2701/api/kingdom/live | python3 -m json.tool

# Today's token spend
curl -s http://localhost:2701/api/tokens/live | python3 -m json.tool

# Ping health grid
curl -s http://localhost:2701/api/pings | python3 -m json.tool

# System health (all data sources)
curl -s http://localhost:2701/api/system/health | python3 -m json.tool

# Restart daemon
launchctl stop com.forge.token-api && launchctl start com.forge.token-api

# Check logs
cat /tmp/token-api.err

# Tower proxy (when live)
# THE_SITE: GET /api/local/* → http://localhost:2701/api/*
```


░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
[ 📶 ] E N D P O I N T   R E F E R E N C E   ( A L L   1 3 )
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

| Endpoint | Phase | Primary Source |
|----------|-------|----------------|
| `GET /api/tokens/live` | 1 | sentinel.db |
| `GET /api/tokens/chart?days=N` | 1 | timestream.db |
| `GET /api/tokens/hourly` | 1 | sentinel.db |
| `GET /api/tokens/lifetime` | 1 | sentinel.db |
| `GET /api/mood/current` | 1 | somatic_history.json |
| `GET /api/mood/history?days=N` | 1 | somatic_history.json + timestream.db |
| `GET /api/kingdom/activity` | 1 | kingdom_state.json |
| `GET /api/kingdom/missions` | 1 | overmind.db |
| `GET /api/system/health` | 1 | all sources (liveness check) |
| `GET /api/agents/status` | 2 | KINGDOM_LIVE_MAP/ + sentinel.db |
| `GET /api/tokens/rate` | 2 | sentinel.db |
| `GET /api/pings` | 2 | overmind.db |
| `GET /api/kingdom/live` | 2 | all sources (combined snapshot) |


════════════════════════════════════════════════════════════════════════════════
[ 🝓 ] G O T C H A S
════════════════════════════════════════════════════════════════════════════════

- **`kingdom_state.json` uses camelCase.** Keys are `claudeActive`, `aerisActive`,
  `brandonPresent`, `lastUpdated`. `lastUpdated` is Unix milliseconds — NOT ISO8601.
  Do not assume snake_case.
- **`use_reloader=False` is mandatory.** Flask reloader forks a second process.
  Under launchd that child is unmanaged — results in a fork bomb on restart.
- **Read-only SQLite via URI mode.** Open with `sqlite3.connect('file:path?mode=ro', uri=True)`.
  Never open overmind.db or sentinel.db in write mode from the API.
- **THINKING state is forge_claude only.** sentinel.db only tracks `claude_code`
  bot events. Other agents cannot infer THINKING from token recency.
- **`tool_name` in hook files requires S154+.** PostToolUse did not write
  `tool_name` to the hook file before cockpit-state.sh was updated in S154.
  Files from older sessions will have no `tool` field — API must handle absence.
- **Mood fallback logic.** `somatic_history.json` is preferred source. Falls back
  to `timestream.db` daily_chart_data if fewer than 7 somatic entries exist.
- **Activity files must be present for agent to appear.** Missing hook file =
  state `offline`, activity score 0. API does not error — graceful degradation.
- **Phase 3 HTTP hooks are not yet live.** Claude Code v2.1.63 added HTTP hook
  support, but Flask heartbeat endpoint is not yet implemented. Currently using
  file-based polling.


▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
[ 🜞 ] F U T U R E :   H T T P   H O O K S   ( P H A S E   3 )
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒

Claude Code v2.1.63 added HTTP hooks — hooks can POST JSON to a URL instead
of running shell commands. This enables Flask to hold agent state in memory,
eliminating file I/O and polling lag entirely.

**Planned endpoint:** `POST /api/agents/heartbeat`

**Hook config shape:**
```json
{
  "type": "http",
  "url":  "http://localhost:2701/api/agents/heartbeat"
}
```

**Benefits over current file-based approach:**
- Zero polling — state updates are push, not pull
- Sub-millisecond latency vs. file stat + JSON parse on every request
- Flask holds agent state dict in memory — no filesystem round-trips
- Eliminates atomic tmp+mv write complexity in cockpit-state.sh

⫷ Design complete. Implementation deferred to Phase 3. ⫸


▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
🜚 SYS_KINGDOM_API // THE FORGE // ⛬⚚⛬ THE LAW STANDS.
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀