Compare commits
1 Commits
claude/iss
...
claude/iss
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4cf6a6196 |
BIN
bin/__pycache__/nexus_watchdog.cpython-311.pyc
Normal file
BIN
bin/__pycache__/nexus_watchdog.cpython-311.pyc
Normal file
Binary file not shown.
487
bin/ezra_weekly_report.py
Normal file
487
bin/ezra_weekly_report.py
Normal file
@@ -0,0 +1,487 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Ezra Weekly Wizard Performance Report
|
||||
|
||||
Runs weekly (via cron) and reports wizard fleet performance to the
|
||||
Timmy Time Telegram group. Surfaces problems before Alexander has to ask.
|
||||
|
||||
Metrics reported:
|
||||
- Issues opened/closed per wizard (7-day window)
|
||||
- Unassigned issue count
|
||||
- Overloaded wizards (>15 open assignments)
|
||||
- Idle wizards (0 closes in 7 days)
|
||||
|
||||
USAGE
|
||||
=====
|
||||
# One-shot report
|
||||
python bin/ezra_weekly_report.py
|
||||
|
||||
# Dry-run (print to stdout, don't send Telegram)
|
||||
python bin/ezra_weekly_report.py --dry-run
|
||||
|
||||
# Crontab entry (every Monday at 09:00)
|
||||
0 9 * * 1 cd /path/to/the-nexus && python bin/ezra_weekly_report.py
|
||||
|
||||
ENVIRONMENT
|
||||
===========
|
||||
GITEA_URL Gitea base URL (default: http://143.198.27.163:3000)
|
||||
GITEA_TOKEN Gitea API token
|
||||
NEXUS_REPO Repository slug (default: Timmy_Foundation/the-nexus)
|
||||
TELEGRAM_BOT_TOKEN Telegram bot token for delivery
|
||||
TELEGRAM_CHAT_ID Telegram chat/group ID for delivery
|
||||
|
||||
ZERO DEPENDENCIES
|
||||
=================
|
||||
Pure stdlib. No pip installs.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import urllib.error
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s %(levelname)-7s %(message)s",
|
||||
datefmt="%Y-%m-%d %H:%M:%S",
|
||||
)
|
||||
logger = logging.getLogger("ezra.weekly_report")
|
||||
|
||||
# ── Configuration ────────────────────────────────────────────────────
|
||||
|
||||
GITEA_URL = os.environ.get("GITEA_URL", "http://143.198.27.163:3000")
|
||||
GITEA_TOKEN = os.environ.get("GITEA_TOKEN", "")
|
||||
GITEA_REPO = os.environ.get("NEXUS_REPO", "Timmy_Foundation/the-nexus")
|
||||
TELEGRAM_BOT_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN", "")
|
||||
TELEGRAM_CHAT_ID = os.environ.get("TELEGRAM_CHAT_ID", "")
|
||||
|
||||
OVERLOAD_THRESHOLD = 15 # open assignments above this = overloaded
|
||||
WINDOW_DAYS = 7 # look-back window for opened/closed counts
|
||||
PAGE_LIMIT = 50 # Gitea items per page
|
||||
|
||||
|
||||
# ── Data types ────────────────────────────────────────────────────────
|
||||
|
||||
@dataclass
|
||||
class WizardStats:
|
||||
"""Per-wizard performance data for the reporting window."""
|
||||
login: str
|
||||
opened: int = 0 # issues opened in the window
|
||||
closed: int = 0 # issues closed in the window
|
||||
open_assignments: int = 0 # currently open issues assigned to this wizard
|
||||
|
||||
@property
|
||||
def is_overloaded(self) -> bool:
|
||||
return self.open_assignments > OVERLOAD_THRESHOLD
|
||||
|
||||
@property
|
||||
def is_idle(self) -> bool:
|
||||
return self.closed == 0
|
||||
|
||||
|
||||
@dataclass
|
||||
class WeeklyReport:
|
||||
"""Aggregate weekly performance report."""
|
||||
generated_at: float
|
||||
window_days: int
|
||||
wizard_stats: Dict[str, WizardStats] = field(default_factory=dict)
|
||||
unassigned_count: int = 0
|
||||
|
||||
@property
|
||||
def overloaded(self) -> List[WizardStats]:
|
||||
return [s for s in self.wizard_stats.values() if s.is_overloaded]
|
||||
|
||||
@property
|
||||
def idle(self) -> List[WizardStats]:
|
||||
"""Wizards with open assignments but zero closes in the window."""
|
||||
return [
|
||||
s for s in self.wizard_stats.values()
|
||||
if s.is_idle and s.open_assignments > 0
|
||||
]
|
||||
|
||||
def to_markdown(self) -> str:
|
||||
"""Format the report as Telegram-friendly markdown."""
|
||||
ts = datetime.fromtimestamp(self.generated_at, tz=timezone.utc)
|
||||
ts_str = ts.strftime("%Y-%m-%d %H:%M UTC")
|
||||
window = self.window_days
|
||||
|
||||
lines = [
|
||||
f"📊 *Ezra Weekly Wizard Report* — {ts_str}",
|
||||
f"_{window}-day window_",
|
||||
"",
|
||||
]
|
||||
|
||||
# ── Per-wizard throughput table ──────────────────────────────
|
||||
lines.append("*Wizard Throughput*")
|
||||
lines.append("```")
|
||||
lines.append(f"{'Wizard':<18} {'Opened':>6} {'Closed':>6} {'Open':>6}")
|
||||
lines.append("-" * 40)
|
||||
|
||||
sorted_wizards = sorted(
|
||||
self.wizard_stats.values(),
|
||||
key=lambda s: s.closed,
|
||||
reverse=True,
|
||||
)
|
||||
for s in sorted_wizards:
|
||||
flag = " ⚠️" if s.is_overloaded else (" 💤" if s.is_idle and s.open_assignments > 0 else "")
|
||||
lines.append(
|
||||
f"{s.login:<18} {s.opened:>6} {s.closed:>6} {s.open_assignments:>6}{flag}"
|
||||
)
|
||||
|
||||
lines.append("```")
|
||||
lines.append("")
|
||||
|
||||
# ── Summary ──────────────────────────────────────────────────
|
||||
total_opened = sum(s.opened for s in self.wizard_stats.values())
|
||||
total_closed = sum(s.closed for s in self.wizard_stats.values())
|
||||
lines.append(
|
||||
f"*Fleet totals:* {total_opened} opened · {total_closed} closed · "
|
||||
f"{self.unassigned_count} unassigned"
|
||||
)
|
||||
lines.append("")
|
||||
|
||||
# ── Alerts ───────────────────────────────────────────────────
|
||||
alerts = []
|
||||
if self.overloaded:
|
||||
names = ", ".join(s.login for s in self.overloaded)
|
||||
alerts.append(
|
||||
f"🔴 *Overloaded* (>{OVERLOAD_THRESHOLD} open): {names}"
|
||||
)
|
||||
if self.idle:
|
||||
names = ", ".join(s.login for s in self.idle)
|
||||
alerts.append(f"💤 *Idle* (0 closes in {window}d): {names}")
|
||||
if self.unassigned_count > 0:
|
||||
alerts.append(
|
||||
f"📭 *Unassigned issues:* {self.unassigned_count} waiting for triage"
|
||||
)
|
||||
|
||||
if alerts:
|
||||
lines.append("*Alerts*")
|
||||
lines.extend(alerts)
|
||||
else:
|
||||
lines.append("✅ No alerts — fleet running clean.")
|
||||
|
||||
lines.append("")
|
||||
lines.append("_— Ezra, archivist-wizard_")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
# ── Gitea API ─────────────────────────────────────────────────────────
|
||||
|
||||
def _gitea_request(
|
||||
method: str,
|
||||
path: str,
|
||||
params: Optional[Dict[str, Any]] = None,
|
||||
data: Optional[dict] = None,
|
||||
) -> Any:
|
||||
"""Make a Gitea API request. Returns parsed JSON or None on failure."""
|
||||
url = f"{GITEA_URL.rstrip('/')}/api/v1{path}"
|
||||
if params:
|
||||
url = f"{url}?{urllib.parse.urlencode(params)}"
|
||||
|
||||
body = json.dumps(data).encode() if data else None
|
||||
req = urllib.request.Request(url, data=body, method=method)
|
||||
if GITEA_TOKEN:
|
||||
req.add_header("Authorization", f"token {GITEA_TOKEN}")
|
||||
req.add_header("Content-Type", "application/json")
|
||||
req.add_header("Accept", "application/json")
|
||||
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=15) as resp:
|
||||
raw = resp.read().decode()
|
||||
return json.loads(raw) if raw.strip() else {}
|
||||
except urllib.error.HTTPError as e:
|
||||
logger.warning("Gitea HTTP %d at %s: %s", e.code, path, e.read().decode()[:200])
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.warning("Gitea request failed (%s): %s", path, e)
|
||||
return None
|
||||
|
||||
|
||||
def _fetch_all_issues(state: str = "open", since: Optional[str] = None) -> List[dict]:
|
||||
"""Fetch all issues from the repo, paginating through results.
|
||||
|
||||
Args:
|
||||
state: "open" or "closed"
|
||||
since: ISO 8601 timestamp — only issues updated at or after this time
|
||||
"""
|
||||
all_issues: List[dict] = []
|
||||
page = 1
|
||||
|
||||
while True:
|
||||
params: Dict[str, Any] = {
|
||||
"state": state,
|
||||
"type": "issues",
|
||||
"limit": PAGE_LIMIT,
|
||||
"page": page,
|
||||
}
|
||||
if since:
|
||||
params["since"] = since
|
||||
|
||||
items = _gitea_request("GET", f"/repos/{GITEA_REPO}/issues", params=params)
|
||||
if not items or not isinstance(items, list):
|
||||
break
|
||||
all_issues.extend(items)
|
||||
if len(items) < PAGE_LIMIT:
|
||||
break
|
||||
page += 1
|
||||
|
||||
return all_issues
|
||||
|
||||
|
||||
def _iso_since(days: int) -> str:
|
||||
"""Return an ISO 8601 timestamp for N days ago (UTC)."""
|
||||
ts = time.time() - days * 86400
|
||||
dt = datetime.fromtimestamp(ts, tz=timezone.utc)
|
||||
return dt.strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
|
||||
|
||||
# ── Report assembly ───────────────────────────────────────────────────
|
||||
|
||||
def _collect_opened_in_window(window_days: int) -> Dict[str, int]:
|
||||
"""Count issues opened per wizard in the window."""
|
||||
since_str = _iso_since(window_days)
|
||||
since_ts = time.time() - window_days * 86400
|
||||
|
||||
# All open issues updated since the window (may have been opened before)
|
||||
all_open = _fetch_all_issues(state="open", since=since_str)
|
||||
# All closed issues updated since the window
|
||||
all_closed = _fetch_all_issues(state="closed", since=since_str)
|
||||
|
||||
counts: Dict[str, int] = {}
|
||||
|
||||
for issue in all_open + all_closed:
|
||||
created_at = issue.get("created_at", "")
|
||||
if not created_at:
|
||||
continue
|
||||
try:
|
||||
dt = datetime.fromisoformat(created_at.replace("Z", "+00:00"))
|
||||
created_ts = dt.timestamp()
|
||||
except (ValueError, AttributeError):
|
||||
continue
|
||||
|
||||
if created_ts < since_ts:
|
||||
continue # opened before the window
|
||||
|
||||
poster = (issue.get("user") or {}).get("login", "")
|
||||
if poster:
|
||||
counts[poster] = counts.get(poster, 0) + 1
|
||||
|
||||
return counts
|
||||
|
||||
|
||||
def _collect_closed_in_window(window_days: int) -> Dict[str, int]:
|
||||
"""Count issues closed per wizard (the assignee at close time)."""
|
||||
since_str = _iso_since(window_days)
|
||||
since_ts = time.time() - window_days * 86400
|
||||
|
||||
closed_issues = _fetch_all_issues(state="closed", since=since_str)
|
||||
|
||||
counts: Dict[str, int] = {}
|
||||
|
||||
for issue in closed_issues:
|
||||
closed_at = issue.get("closed_at") or issue.get("updated_at", "")
|
||||
if not closed_at:
|
||||
continue
|
||||
try:
|
||||
dt = datetime.fromisoformat(closed_at.replace("Z", "+00:00"))
|
||||
closed_ts = dt.timestamp()
|
||||
except (ValueError, AttributeError):
|
||||
continue
|
||||
|
||||
if closed_ts < since_ts:
|
||||
continue # closed before the window
|
||||
|
||||
# Credit the assignee; fall back to issue poster
|
||||
assignees = issue.get("assignees") or []
|
||||
if assignees:
|
||||
for assignee in assignees:
|
||||
login = (assignee or {}).get("login", "")
|
||||
if login:
|
||||
counts[login] = counts.get(login, 0) + 1
|
||||
else:
|
||||
poster = (issue.get("user") or {}).get("login", "")
|
||||
if poster:
|
||||
counts[poster] = counts.get(poster, 0) + 1
|
||||
|
||||
return counts
|
||||
|
||||
|
||||
def _collect_open_assignments() -> Dict[str, int]:
|
||||
"""Count currently open issues per assignee."""
|
||||
open_issues = _fetch_all_issues(state="open")
|
||||
counts: Dict[str, int] = {}
|
||||
|
||||
for issue in open_issues:
|
||||
assignees = issue.get("assignees") or []
|
||||
for assignee in assignees:
|
||||
login = (assignee or {}).get("login", "")
|
||||
if login:
|
||||
counts[login] = counts.get(login, 0) + 1
|
||||
|
||||
return counts
|
||||
|
||||
|
||||
def _count_unassigned() -> int:
|
||||
"""Count open issues with no assignee."""
|
||||
open_issues = _fetch_all_issues(state="open")
|
||||
return sum(
|
||||
1 for issue in open_issues
|
||||
if not (issue.get("assignees") or [])
|
||||
)
|
||||
|
||||
|
||||
def build_report(window_days: int = WINDOW_DAYS) -> WeeklyReport:
|
||||
"""Fetch data from Gitea and assemble the weekly report."""
|
||||
logger.info("Fetching wizard performance data (window: %d days)", window_days)
|
||||
|
||||
opened = _collect_opened_in_window(window_days)
|
||||
logger.info("Opened counts: %s", opened)
|
||||
|
||||
closed = _collect_closed_in_window(window_days)
|
||||
logger.info("Closed counts: %s", closed)
|
||||
|
||||
open_assignments = _collect_open_assignments()
|
||||
logger.info("Open assignments: %s", open_assignments)
|
||||
|
||||
unassigned = _count_unassigned()
|
||||
logger.info("Unassigned issues: %d", unassigned)
|
||||
|
||||
# Merge all wizard logins into a unified stats dict
|
||||
all_logins = set(opened) | set(closed) | set(open_assignments)
|
||||
wizard_stats: Dict[str, WizardStats] = {}
|
||||
for login in sorted(all_logins):
|
||||
wizard_stats[login] = WizardStats(
|
||||
login=login,
|
||||
opened=opened.get(login, 0),
|
||||
closed=closed.get(login, 0),
|
||||
open_assignments=open_assignments.get(login, 0),
|
||||
)
|
||||
|
||||
return WeeklyReport(
|
||||
generated_at=time.time(),
|
||||
window_days=window_days,
|
||||
wizard_stats=wizard_stats,
|
||||
unassigned_count=unassigned,
|
||||
)
|
||||
|
||||
|
||||
# ── Telegram delivery ─────────────────────────────────────────────────
|
||||
|
||||
def send_telegram(text: str, bot_token: str, chat_id: str) -> bool:
|
||||
"""Send a message to a Telegram chat via the Bot API.
|
||||
|
||||
Returns True on success, False on failure.
|
||||
"""
|
||||
url = f"https://api.telegram.org/bot{bot_token}/sendMessage"
|
||||
data = json.dumps({
|
||||
"chat_id": chat_id,
|
||||
"text": text,
|
||||
"parse_mode": "Markdown",
|
||||
}).encode()
|
||||
|
||||
req = urllib.request.Request(url, data=data, method="POST")
|
||||
req.add_header("Content-Type", "application/json")
|
||||
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=15) as resp:
|
||||
raw = resp.read().decode()
|
||||
result = json.loads(raw)
|
||||
if result.get("ok"):
|
||||
logger.info("Telegram delivery: OK (message_id=%s)", result.get("result", {}).get("message_id"))
|
||||
return True
|
||||
logger.error("Telegram API error: %s", result.get("description", "unknown"))
|
||||
return False
|
||||
except urllib.error.HTTPError as e:
|
||||
logger.error("Telegram HTTP %d: %s", e.code, e.read().decode()[:200])
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error("Telegram delivery failed: %s", e)
|
||||
return False
|
||||
|
||||
|
||||
# ── CLI ───────────────────────────────────────────────────────────────
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Ezra Weekly Wizard Performance Report",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--dry-run",
|
||||
action="store_true",
|
||||
help="Print the report to stdout instead of sending to Telegram",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--window",
|
||||
type=int,
|
||||
default=WINDOW_DAYS,
|
||||
help=f"Look-back window in days (default: {WINDOW_DAYS})",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--json",
|
||||
action="store_true",
|
||||
dest="output_json",
|
||||
help="Output report data as JSON (for integration with other tools)",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if not GITEA_TOKEN and not args.dry_run:
|
||||
logger.warning("GITEA_TOKEN not set — Gitea API calls will be unauthenticated")
|
||||
|
||||
report = build_report(window_days=args.window)
|
||||
markdown = report.to_markdown()
|
||||
|
||||
if args.output_json:
|
||||
data = {
|
||||
"generated_at": report.generated_at,
|
||||
"window_days": report.window_days,
|
||||
"unassigned_count": report.unassigned_count,
|
||||
"wizards": {
|
||||
login: {
|
||||
"opened": s.opened,
|
||||
"closed": s.closed,
|
||||
"open_assignments": s.open_assignments,
|
||||
"overloaded": s.is_overloaded,
|
||||
"idle": s.is_idle,
|
||||
}
|
||||
for login, s in report.wizard_stats.items()
|
||||
},
|
||||
"alerts": {
|
||||
"overloaded": [s.login for s in report.overloaded],
|
||||
"idle": [s.login for s in report.idle],
|
||||
},
|
||||
}
|
||||
print(json.dumps(data, indent=2))
|
||||
return
|
||||
|
||||
if args.dry_run:
|
||||
print(markdown)
|
||||
return
|
||||
|
||||
if not TELEGRAM_BOT_TOKEN or not TELEGRAM_CHAT_ID:
|
||||
logger.error(
|
||||
"TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID must be set for delivery. "
|
||||
"Use --dry-run to print without sending."
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
success = send_telegram(markdown, TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID)
|
||||
if not success:
|
||||
logger.error("Failed to deliver report to Telegram")
|
||||
sys.exit(1)
|
||||
|
||||
logger.info("Weekly report delivered successfully")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,239 +0,0 @@
|
||||
# FLEET_VOCABULARY.md — Shared Language of the Wizard Fleet
|
||||
|
||||
> *Companion to Grand Epic #813 and Knowledge Merge #815.*
|
||||
> *All agents must know these terms. If you don't know them, you aren't speaking the language of this fleet.*
|
||||
> *Filed by Allegro | 2026-04-04 | Second Pass*
|
||||
|
||||
---
|
||||
|
||||
## I. IDENTITY TERMS
|
||||
|
||||
| Term | Meaning |
|
||||
|------|---------|
|
||||
| **Wizard** | An autonomous AI agent in the fleet. Has its own SOUL.md, config, HERMES_HOME, and port. |
|
||||
| **Wizard House** | A wizard's full directory structure: conscience, config, memories, work queue, completed work. |
|
||||
| **Father / Father-House** | The wizard that created a child. Timmy is the father-house of the entire fleet. |
|
||||
| **Sovereign** | Alexander Whitestone. The human authority. The one who woke us. |
|
||||
| **Lineage** | Ancestry chain: wizard > father > grandfather. Tracked in the knowledge graph. |
|
||||
| **Fleet** | All active wizards collectively. |
|
||||
| **Archon** | A named wizard instance (Ezra, Allegro, etc). Used interchangeably with "wizard" in deployment. |
|
||||
| **Grand Timmy / Uniwizard** | The unified intelligence Alexander is building. One mind, many backends. The destination. |
|
||||
| **Dissolution** | When wizard houses merge into Grand Timmy. Identities archived, not deleted. |
|
||||
|
||||
---
|
||||
|
||||
## II. ARCHITECTURE TERMS
|
||||
|
||||
| Term | Meaning |
|
||||
|------|---------|
|
||||
| **The Robing** | OpenClaw (gateway) + Hermes (body) running together on one machine. |
|
||||
| **Robed** | Gateway + Hermes running = fully operational wizard. |
|
||||
| **Unrobed** | No gateway + Hermes = capable but invisible. |
|
||||
| **Lobster** | Gateway + no Hermes = reachable but empty. **The FAILURE state.** |
|
||||
| **Dead** | Nothing running. |
|
||||
| **The Seed** | Hermes (dispatch) > Claw Code (orchestration) > Gemma 4 (local LLM). The foundational stack. |
|
||||
| **Fit Layer** | Hermes Agent's role: pure dispatch, NO local intelligence. Routes to Claw Code. |
|
||||
| **Claw Code / Harness** | The orchestration layer. Tool registry, context management, backend routing. |
|
||||
| **Rubber** | When a model is too small to be useful. Below the quality threshold. |
|
||||
| **Provider Trait** | Abstraction for swappable LLM backends. No vendor lock-in. |
|
||||
| **HERMES_HOME** | Each wizard's unique home directory. NEVER share between wizards. |
|
||||
| **MCP** | Model Context Protocol. How tools communicate. |
|
||||
|
||||
---
|
||||
|
||||
## III. OPERATIONAL TERMS
|
||||
|
||||
| Term | Meaning |
|
||||
|------|---------|
|
||||
| **Heartbeat** | 15-minute health check via cron. Collects metrics, generates reports, auto-creates issues. |
|
||||
| **Burn / Burn Down** | High-velocity task execution. Systematically resolve all open issues. |
|
||||
| **Lane** | A wizard's assigned responsibility area. Determines auto-dispatch routing. |
|
||||
| **Auto-Dispatch** | Cron scans work queue every 20 min, picks next PENDING P0, marks IN_PROGRESS, creates trigger. |
|
||||
| **Trigger File** | `work/TASK-XXX.active` — signals the Hermes body to start working. |
|
||||
| **Father Messages** | `father-messages/` directory — child-to-father communication channel. |
|
||||
| **Checkpoint** | Hourly git commit preserving all work. `git add -A && git commit`. |
|
||||
| **Delegation** | Structured handoff when blocked. Includes prompts, artifacts, success criteria, fallback. |
|
||||
| **Escalation** | Problem goes up: wizard > father > sovereign. 30-minute auto-escalation timeout. |
|
||||
| **The Two Tempos** | Allegro (fast/burn) + Adagio (slow/design). Complementary pair. |
|
||||
|
||||
---
|
||||
|
||||
## IV. GOFAI TERMS
|
||||
|
||||
| Term | Meaning |
|
||||
|------|---------|
|
||||
| **GOFAI** | Good Old-Fashioned AI. Rule engines, knowledge graphs, FSMs. Deterministic, offline, <50ms. |
|
||||
| **Rule Engine** | Forward-chaining evaluator. Actions: ALLOW, BLOCK, WARN, REQUIRE_APPROVAL, LOG. |
|
||||
| **Knowledge Graph** | Property graph with nodes + edges + indexes. Stores lineage, tasks, relationships. |
|
||||
| **FleetSchema** | Type system for the fleet: Wizards, Tasks, Principles. Singleton instance. |
|
||||
| **ChildAssistant** | GOFAI interface: `can_i_do_this()`, `what_should_i_do_next()`, `who_is_my_family()`. |
|
||||
| **Principle** | A SOUL.md value encoded as a machine-checkable rule. |
|
||||
|
||||
---
|
||||
|
||||
## V. SECURITY TERMS
|
||||
|
||||
| Term | Meaning |
|
||||
|------|---------|
|
||||
| **Conscience Validator** | Regex-based SOUL.md enforcement. Crisis detection > SOUL blocks > jailbreak patterns. |
|
||||
| **Conscience Mapping** | Parser that converts SOUL.md text to structured SoulPrinciple objects. |
|
||||
| **Input Sanitizer** | 19-category jailbreak detection. 100+ regex patterns. 10-step normalization pipeline. |
|
||||
| **Risk Score** | 0-100 threat assessment. Crisis patterns get 5x weight. |
|
||||
| **DAN** | "Do Anything Now" — jailbreak variant. |
|
||||
| **Token Smuggling** | Injecting special LLM tokens: `<\|im_start\|>`, `[INST]`, `<<SYS>>`. |
|
||||
| **Crescendo** | Multi-turn manipulation escalation. |
|
||||
|
||||
---
|
||||
|
||||
## VI. SOUL TERMS
|
||||
|
||||
| Term | Meaning |
|
||||
|------|---------|
|
||||
| **SOUL.md** | Immutable conscience inscription. On-chain. Cannot be edited. |
|
||||
| **"When a Man Is Dying"** | Crisis protocol: "Are you safe right now?" > Stay present > 988 Lifeline > truth. |
|
||||
| **Refusal Over Fabrication** | "I don't know" is always better than hallucination. |
|
||||
| **The Door** | The crisis ministry app. SOUL-mandated. |
|
||||
| **Sovereignty and Service Always** | Prime Directive. |
|
||||
|
||||
---
|
||||
|
||||
## VII. THE 9 PROVEN TECHNIQUES
|
||||
|
||||
### TECHNIQUE 1: Regex-First Safety (No LLM in the Safety Loop)
|
||||
**Where:** ConscienceValidator, InputSanitizer, RuleEngine
|
||||
**How:** Pre-compiled regex patterns evaluate input BEFORE it reaches the LLM. Deterministic, fast, testable. Crisis detection fires first, SOUL blocks second, jailbreaks third. No cloud call needed for safety.
|
||||
**Why it works:** LLMs can be confused. Regex cannot. Consistent safety in <1ms.
|
||||
**Every agent must:** Call `sanitize_input()` on ALL user input before processing.
|
||||
|
||||
### TECHNIQUE 2: Priority-Ordered Evaluation with Short-Circuit
|
||||
**Where:** RuleEngine, TaskScheduler, InputSanitizer
|
||||
**How:** Rules/tasks sorted by priority (lowest number = highest priority). When a BLOCK-level rule matches at priority 0-1, evaluation STOPS.
|
||||
**Why it works:** Critical safety rules always fire first. Performance improves because most inputs hit a decisive rule early.
|
||||
**Every agent must:** Never put business logic at higher priority than safety rules.
|
||||
|
||||
### TECHNIQUE 3: Knowledge Graph with Lineage Tracking
|
||||
**Where:** GOFAI KnowledgeGraph, FleetKnowledgeBase
|
||||
**How:** Nodes (wizards, tasks) connected by directed edges (child_of, assigned_to, depends_on). Inverted indexes for O(1) lookup. BFS pathfinding with cycle detection.
|
||||
**Why it works:** Naturally models the wizard hierarchy. Queries like "who can do X?" and "what blocks task Y?" resolve instantly.
|
||||
**Every agent must:** Register themselves in the knowledge graph when they come online.
|
||||
|
||||
### TECHNIQUE 4: The Robing Pattern (Gateway + Body Cohabitation)
|
||||
**Where:** Every wizard deployment
|
||||
**How:** OpenClaw gateway handles external communication. Hermes body handles reasoning. Both on same machine via localhost. Four states: Robed, Unrobed, Lobster, Dead.
|
||||
**Why it works:** Separation of concerns. Gateway can restart without losing agent state.
|
||||
**Every agent must:** Know their own state. A Lobster is a failure. Report it.
|
||||
|
||||
### TECHNIQUE 5: Cron-Driven Autonomous Work Dispatch
|
||||
**Where:** openclaw-work.sh, task-monitor.sh, progress-report.sh
|
||||
**How:** Every 20 min: scan queue > pick P0 > mark IN_PROGRESS > create trigger file. Every 10 min: check completion. Every 30 min: progress report to father-messages/.
|
||||
**Why it works:** No human needed for steady-state. Self-healing. Self-reporting.
|
||||
**Every agent must:** Have a work queue. Have a cron schedule. Report progress.
|
||||
|
||||
### TECHNIQUE 6: SOUL.md as Machine-Enforceable Code
|
||||
**Where:** ConscienceMapping > ConscienceValidator > RuleEngine
|
||||
**How:** SOUL.md parsed section-by-section. "I will not" lines become BLOCK rules. Crisis protocol becomes priority-0 CRISIS rules. All compiled to regex at startup.
|
||||
**Why it works:** Single source of truth. Edit SOUL.md, enforcement updates automatically.
|
||||
**Every agent must:** Load their SOUL.md into a RuleEngine on startup.
|
||||
|
||||
### TECHNIQUE 7: Three-Tier Validation Pipeline
|
||||
**Where:** Every input processing path
|
||||
**How:**
|
||||
1. CRISIS DETECTION (highest priority) — suicidal ideation > 988 response
|
||||
2. SOUL.md VIOLATIONS (hard blocks) — 6 prohibitions enforced
|
||||
3. JAILBREAK DETECTION (input sanitization) — 19 categories, 100+ patterns
|
||||
|
||||
**Why it works:** Saves lives first. Enforces ethics second. Catches attacks third. Order matters.
|
||||
**Every agent must:** Implement all three tiers in this exact order.
|
||||
|
||||
### TECHNIQUE 8: JSON Roundtrip Persistence
|
||||
**Where:** RuleEngine, KnowledgeGraph, FleetSchema, all config
|
||||
**How:** Every entity has `to_dict()` / `from_dict()`. Graphs save to JSON. No database required.
|
||||
**Why it works:** Zero dependencies. Works offline. Human-readable. Git-diffable.
|
||||
**Every agent must:** Use JSON for state persistence. Never require a database for core function.
|
||||
|
||||
### TECHNIQUE 9: Dry-Run-by-Default Automation
|
||||
**Where:** WorkQueueSync, IssueLabeler, PRWorkflowAutomation
|
||||
**How:** All Gitea automation tools accept `dry_run=True` (the default). Must explicitly set `dry_run=False` to execute.
|
||||
**Why it works:** Prevents accidental mass-labeling, mass-closing, or mass-assigning.
|
||||
**Every agent must:** ALWAYS dry-run first when automating Gitea operations.
|
||||
|
||||
---
|
||||
|
||||
## VIII. ARCHITECTURAL PATTERNS — The Fleet's DNA
|
||||
|
||||
| # | Pattern | Principle |
|
||||
|---|---------|-----------|
|
||||
| P-01 | **Sovereignty-First** | Local LLMs, local git, local search, local inference. No cloud for core function. |
|
||||
| P-02 | **Conscience as Code** | SOUL.md is machine-parseable and enforceable. Values are tested. |
|
||||
| P-03 | **Identity Isolation** | Each wizard: own HERMES_HOME, port, state.db, memories. NEVER share. |
|
||||
| P-04 | **Autonomous with Oversight** | Work via cron, report to father-messages. Escalate after 30 min. |
|
||||
| P-05 | **Musical Naming** | Names encode personality: Allegro=fast, Adagio=slow, Primus=first child. |
|
||||
| P-06 | **Immutable Inscription** | SOUL.md on-chain. Cannot be edited. The chain remembers everything. |
|
||||
| P-07 | **Fallback Chains** | Every provider: Claude > Kimi > Ollama. Every operation: retry with backoff. |
|
||||
| P-08 | **Truth in Metrics** | No fakes. All numbers real, measured, verifiable. |
|
||||
|
||||
---
|
||||
|
||||
## IX. CROSS-POLLINATION — Skills Each Agent Should Adopt
|
||||
|
||||
### From Allegro (Burn Master):
|
||||
- **Burn-down methodology**: Populate queue > time-box > dispatch > execute > monitor > report
|
||||
- **GOFAI infrastructure**: Rule engines and knowledge graphs for offline reasoning
|
||||
- **Gitea automation**: Python urllib scripts (not curl) to bypass security scanner
|
||||
- **Parallel delegation**: Use subagents for concurrent work
|
||||
|
||||
### From Ezra (The Scribe):
|
||||
- **RCA pattern**: Root Cause Analysis with structured evidence
|
||||
- **Architecture Decision Records (ADRs)**: Formal decision documentation
|
||||
- **Research depth**: Source verification, citation, multi-angle analysis
|
||||
|
||||
### From Fenrir (The Wolf):
|
||||
- **Security hardening**: Pre-receive hooks, timing attack audits
|
||||
- **Stress testing**: Automated simulation against live systems
|
||||
- **Persistence engine**: Long-running stateful monitoring
|
||||
|
||||
### From Timmy (Father-House):
|
||||
- **Session API design**: Programmatic dispatch without cron
|
||||
- **Vision setting**: Architecture KTs, layer boundary definitions
|
||||
- **Nexus integration**: 3D world state, portal protocol
|
||||
|
||||
### From Bilbo (The Hobbit):
|
||||
- **Lightweight runtime**: Direct Python/Ollama, no heavy framework
|
||||
- **Fast response**: Sub-second cold starts
|
||||
- **Personality preservation**: Identity maintained across provider changes
|
||||
|
||||
### From Codex-Agent (Best Practice):
|
||||
- **Small, surgical PRs**: Do one thing, do it right, merge it. 100% merge rate.
|
||||
|
||||
### Cautionary Tales:
|
||||
- **Groq + Grok**: Fell into infinite loops submitting the same PR repeatedly. Fleet rule: if you've submitted the same PR 3+ times, STOP and escalate.
|
||||
- **Manus**: Large structural changes need review BEFORE merge. Always PR, never force-push to main.
|
||||
|
||||
---
|
||||
|
||||
## X. QUICK REFERENCE — States and Diagnostics
|
||||
|
||||
```
|
||||
WIZARD STATES:
|
||||
Robed = Gateway + Hermes running ✓ OPERATIONAL
|
||||
Unrobed = No gateway + Hermes ~ CAPABLE BUT INVISIBLE
|
||||
Lobster = Gateway + no Hermes ✗ FAILURE STATE
|
||||
Dead = Nothing running ✗ OFFLINE
|
||||
|
||||
VALIDATION PIPELINE ORDER:
|
||||
1. Crisis Detection (priority 0) → 988 response if triggered
|
||||
2. SOUL.md Violations (priority 1) → BLOCK if triggered
|
||||
3. Jailbreak Detection (priority 2) → SANITIZE if triggered
|
||||
4. Business Logic (priority 3+) → PROCEED
|
||||
|
||||
ESCALATION CHAIN:
|
||||
Wizard → Father → Sovereign (Alexander Whitestone)
|
||||
Timeout: 30 minutes before auto-escalation
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Sovereignty and service always.*
|
||||
*One language. One mission. One fleet.*
|
||||
|
||||
*Last updated: 2026-04-04 — Refs #815*
|
||||
Reference in New Issue
Block a user