feat(skills)!: S4 night commands become drain, suspend and resume
Requirement 001 phase 6, S4 (decision 29): - Skills renamed: kvb-org-evening -> kvb-org-drain, kvb-org-sunset -> kvb-org-suspend, kvb-org-sunrise -> kvb-org-resume, kvb-agent-relax -> kvb-agent-drain, kvb-agent-sleep -> kvb-agent-suspend, kvb-agent-wakeup -> kvb-agent-resume; their text uses the new verbs and every reference in skills, README, orchestrator and tests follows. - night.py takes drain, suspend, resume, resume --alone and status. A state file written before the rename keeps working: mode evening reads as drain, sunset as suspend, the awake list as resumed and is rewritten on the next save; the hub's council.night_mode maps the same values. mode: day and handover_night_<session>.md keep their names. - Orchestrator: the Day/Night menu shows Drain, Suspend and Resume, each confirmed, signed through /api/board/sign with the passkey and run as the existing argv job; the old action names are refused. - kvb-skill-cleanup: git rates two renames at 44 and 50 % similarity, under its default threshold, so legacy.py detects renames from 40 %. - tests/test_night_names.py fails on any old name in the tree outside a rename record "old ->". BREAKING CHANGE: the six old skill names and night.py's clear and wake are gone. Run make install (it reinstalls the orchestrator too), then kvb-skill-cleanup to remove the old installed copies; until the install, the running hub calls the old night.py path. Evidence: make test 679 OK, ruff and markdownlint clean (/tmp/s4-make-test-1.log); e2e 22 OK in Chromium and Firefox (/tmp/s4-e2e-3.log); MEDUSA 23 files, the 2 findings are the byte-identical atomic state write that moved with night.py, already accepted after a skeptic at its old path, rescan 0 open. 🎯 Fix: 93 % 💥 Break: 4 % 💸 Cost: 100 % ⏱️ Time: – 🛡️ Security: 100 % 🏆 Score: 89 🚦 Gate: ✅ 90/5, cost and time <= 100, security 100 % Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4d88296e47
commit
5c8b69d53d
24 files changed
+420
-176
No files matched your search
@@ -14,7 +14,8 @@ CLASSES = ("post", "call", "newsletter", "broadcast", "mayday", "pan-pan", "secu
|
||||
RECEIPT = "receipt"
|
||||
ALARMS = ("mayday", "pan-pan", "security")
|
||||
VERSION = 2
|
||||
MODES = ("evening", "sunset")
|
||||
MODES = ("drain", "suspend")
|
||||
RENAMED_MODES = {"evening": "drain", "sunset": "suspend"}
|
||||
RADIO_LIMIT = 5000
|
||||
GRANT_LIMIT = 50
|
||||
MAYDAY_ACTIVE = 7200
|
||||
@@ -154,8 +155,17 @@ def grants(rows: list[dict], window: tuple[float, float], claims: list[dict], ta
|
||||
|
||||
|
||||
def night_mode(council: Path) -> str:
|
||||
"""Args:
|
||||
council: the council directory; night.json in it may still hold a
|
||||
mode from before the rename, read as its successor.
|
||||
|
||||
Returns:
|
||||
One of MODES, or day.
|
||||
"""
|
||||
data = read_json(council / "night.json")
|
||||
mode = data.get("mode") if isinstance(data, dict) else None
|
||||
if isinstance(mode, str):
|
||||
mode = RENAMED_MODES.get(mode, mode)
|
||||
return mode if mode in MODES else "day"
|
||||
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ from .signed import message_signed, signing
|
||||
from .skill_scripts import NIGHT, RADIO, RASCI
|
||||
|
||||
NIGHTS = {
|
||||
"evening": (["set", "evening"], "Operator ran kvb-org-evening in the Agent Orchestrator: run kvb-agent-relax; verify with night.py status."),
|
||||
"sunset": (["set", "sunset"], "Operator ran kvb-org-sunset in the Agent Orchestrator: run kvb-agent-sleep; verify with night.py status."),
|
||||
"sunrise": (["clear"], "Operator ran kvb-org-sunrise: run kvb-agent-wakeup; verify with night.py status."),
|
||||
"drain": (["drain"], "Operator ran kvb-org-drain in the Agent Orchestrator: run kvb-agent-drain; verify with night.py status."),
|
||||
"suspend": (["suspend"], "Operator ran kvb-org-suspend in the Agent Orchestrator: run kvb-agent-suspend; verify with night.py status."),
|
||||
"resume": (["resume"], "Operator ran kvb-org-resume: run kvb-agent-resume; verify with night.py status."),
|
||||
}
|
||||
UNSAFE = re.compile(r"[^A-Za-z0-9._-]+")
|
||||
DIRECT = {"post": ["post"], "call": ["send", "call"]}
|
||||
|
||||
@@ -11,7 +11,7 @@ OUTPUT_LIMIT = 4000
|
||||
SAFE_PATH = "/usr/local/bin:/usr/bin:/bin"
|
||||
RADIO = "kvb-org-radio/scripts/radio.py"
|
||||
RASCI = "kvb-org-rasci/scripts/rasci.py"
|
||||
NIGHT = "kvb-org-sunset/scripts/night.py"
|
||||
NIGHT = "kvb-org-suspend/scripts/night.py"
|
||||
OPERATOR_SCRIPT = "kvb-org-operator/scripts/operator.py"
|
||||
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
--host-state: the state directory's path on the host, named in the radio
|
||||
rows that carry an upload or a voice recording.
|
||||
--skills: installed skills directory holding the kvb-org-radio,
|
||||
kvb-org-rasci and kvb-org-sunset scripts.
|
||||
kvb-org-rasci and kvb-org-suspend scripts.
|
||||
--transcripts: directory the Claude Code transcripts (*.jsonl) lie under.
|
||||
--templates: directory holding index.html.j2 and the *.js modules it
|
||||
includes.
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
const clear = iconBtn("bi-life-preserver", "Cancel mayday", "btn small danger", () => confirmAct("clear-mayday"));
|
||||
const mode = h("span", {});
|
||||
const night = h("details", {class: "menu"}, h("summary", named("Day/Night"), icon("bi-moon-stars"), caret()), h("div", {class: "menu-box"}, mode,
|
||||
h("p", {class: "muted"}, "Evening: agents finish their task. Sunset: they sleep. Sunrise: all wake up."),
|
||||
h("p", {class: "muted"}, "Drain: agents finish their task and take nothing new. Suspend: they park their work and idle. Resume: all continue from the handover. Your passkey signs each."),
|
||||
h("div", {class: "actions"}, ACTIONS.slice(1).map(([id, label]) => btn(label, "btn small", () => confirmAct(id))))));
|
||||
return {bar: h("div", {class: "toolbar", role: "toolbar", "aria-label": "Controls"}, toAll(), clear, iconBtn("bi-sort-down", "Priority", "btn small", openAgentOrder, "Priority: agent order in the hierarchy"), night), clear, mode};
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
const KIND_TONES = {radio: "teal", review: "info", ask: "warn", decision: "violet", operator: "bad", register: "neutral", rename: "info", cron: "teal", rule: "ok", approval: "ok", run: "info", transcript: "neutral"};
|
||||
const VIEW_ICONS = {"fuer-dich": "bi-person-check", funk: "bi-broadcast", arbeit: "bi-briefcase", transkripte: "bi-chat-left-text"};
|
||||
const ITEM_LABELS = {review: "Review", ask: "Ask", decision: "Decision", operator: "Operator", rule: "Rule request"};
|
||||
const NIGHT = {day: ["Day", "ok"], evening: ["Evening", "warn"], sunset: ["Night", "violet"]};
|
||||
const ACTIONS = [["clear-mayday", "Cancel mayday", "Lift the radio silence of the active mayday?"], ["evening", "Evening", "Send all agents into the evening (kvb-agent-relax)?"], ["sunset", "Sunset", "Put all agents to sleep (kvb-agent-sleep)?"], ["sunrise", "Sunrise", "Wake all agents (kvb-agent-wakeup)?"]];
|
||||
const NIGHT = {day: ["Day", "ok"], drain: ["Draining", "warn"], suspend: ["Suspended", "violet"]};
|
||||
const ACTIONS = [["clear-mayday", "Cancel mayday", "Lift the radio silence of the active mayday?"], ["drain", "Drain", "Drain all agents: finish the current task, accept nothing new (kvb-agent-drain)?"], ["suspend", "Suspend", "Suspend all agents: park work, write the handover, idle (kvb-agent-suspend)?"], ["resume", "Resume", "Resume all agents from their handover (kvb-agent-resume)?"]];
|
||||
const UPLOAD_LIMIT = 50 * 1024 * 1024;
|
||||
const STREAM_KEEP = 5000;
|
||||
const CLASSES = {post: "Post", call: "Call", newsletter: "Newsletter", broadcast: "Broadcast", mayday: "Mayday", "pan-pan": "Pan-Pan", security: "Sécurité", receipt: "Read", grant: "Grant"};
|
||||
|
||||
Reference in new issue
Block a user