From a0eb99b3fbb55195ebb5b97bf1428578dc56b733 Mon Sep 17 00:00:00 2001 From: reachableceo Date: Fri, 28 Aug 2026 18:43:23 -0500 Subject: [PATCH] MOPAC harness v0 spec: headless Go conductor loop, tool ports, LiteLLM-first --- DESIGN.md | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 1 + 2 files changed, 60 insertions(+) create mode 100644 DESIGN.md create mode 100644 go.mod diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..68f6352 --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,59 @@ +# MOPAC harness — design spec v0 (2026-08-28) + +A Go headless agent harness for the RCEO/TSG org. Replaces bash/screen/file-hack +inner loop. All patterns established 2026-08-28 STAY; only the substrate +changes. References: ../reference/{crush,maki}; siblings to port: +../siblings/{KNEL-AIMiddleware, KNELSecretsManager}. + +## What it is NOT +- Not a TUI. Inner loop = pull Redmine -> run turn -> write Discourse/Redmine + back -> chain next turn. Humans observe via files/Redmine/Discourse, not by + attaching to the loop. +- Not a daemon. Bounded turns chaining (drip), same as dispatch-turn.sh today. + +## Core loop (from DESIGN-24x7-execution.md, carried over) +1. INTAKE: poll released scope (Redmine query) + local inbox files. +2. GATE: semaphore (LLM slots, class-aware: llm-heavy|compute-long|hybrid), + budget from LiteLLM usage API (http://192.168.3.78:4001) — virtual key + per stack, hard caps enforced at proxy. +3. EXECUTE: bounded turn, fresh small context, tools below. +4. WRITEBACK: REPORT file + Redmine issue note (SoR). Discourse for docs. +5. CHAIN: completion triggers next conductor iteration. P1 first, grinders + chunked, compute-long tasks run in non-LLM slots. +6. ESCALATE: anything outside standing-release scope -> TASK file -> founder + gate. Never auto-executes. + +## Tools (port from crush/KNEL, Go) +- bash exec, file edit (tree-sitter-aware parses; see maki's approach), + redmine-cli, discourse-cli, tea (gitea), docker, bitwarden (replace + KNELSecretsManager with Go bwraper around `bw` CLI; secrets never in logs). +- MCP client (crush's mcp plumbing is the reference; wrappers exist in + siblings/KNEL-AIMiddleware — port config format for compat). +- LSP: port lsp-* wrappers or embed go.lsp devkit. +- Permission model: per-tool allow/deny, tree-sitter bash parsing (maki + reference) — subshells/pipes handled; org preset: no sudo/ssh/network + exfil; writes confined to declared roots. + +## Providers +- OpenAI-compatible only, pointed at LiteLLM (base_url + virtual key). + OAuth flows (crush-style) OUT of scope for v1 — proxy key is enough. +- Retry/backoff on stream truncation (z.ai "Message content shorter than + read bytes" seen 2x today) with turn resume. + +## Cross-host (5 onstage + 3 offstage) +- Each host runs harness instances; coordination via _crossfeed files (v1) + and/or LiteLLM keys as the global budget broker. Event receiver (T1) later. + +## Build order (go slow, grinder TASKs, quota-aware) +1. Reference studies: crush oauth/mcp/session code; maki permission parsing + + token-reduction (index/tool_search). Deliverable: PORTING-NOTES.md each. +2. harness skeleton: config, loop, redmine-pull, file writeback, exec tool. +3. Permission layer + bitwarden wrapper. +4. LiteLLM integration + semaphore/budget gates. +5. MCP/LSP ports. +6. Pilot: one RCEO stack on trivial released scope; compare vs drip loop. + +## Constraints +- Quota: grinder turns only, no idle polling loops, compact aggressively. +- Never log secret values; keys from bitwarden at runtime. +- Everything it does lands in git (tooling repos) or Redmine (work records). diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8e3bc02 --- /dev/null +++ b/go.mod @@ -0,0 +1 @@ +go 1.24