diff --git a/docs/now/2026-09-13-one-card-for-the-unified-agent-operations-system.md b/docs/now/2026-09-13-one-card-for-the-unified-agent-operations-system.md new file mode 100644 index 000000000..031ac4099 --- /dev/null +++ b/docs/now/2026-09-13-one-card-for-the-unified-agent-operations-system.md @@ -0,0 +1,11 @@ +# NOW -- One card for the unified agent-operations system (2026-09-13) + +## One card for the unified agent-operations system (Closes #3607) + +- `specs/system/unified-agent-operations.t27` (module `system::unified_agent_operations`, `KIND = "system"`, `VERSION = 1`) names the four layers the repositories form -- `contracts` (t27), `control` (Queen, Bees, the `t27-queen` Inngest app), `edge` (999 bot, Mini App, Hive, CRM, media library, vibee-render), `evidence` (GoldenFloat registry, AX7203, Golden Sieve, papers) -- with `AUTHORITY_FLOWS_DOWN = true`: a lower layer never edits a higher one. 14 `SUBSYSTEMS`, 5 `SATELLITES`. +- Contract rules as fields: `CARD_REQUIRED` (six fields or the card is refused, `ON_BAD_CARD = "refuse-card-serve-rest"`), `STATUS_TAGS`, `FORBIDDEN_CLAIMS = ["first", "only", "best"]`, `DRIFT_CHECK = "regenerate-and-diff"` as a required status, `SOURCE_LANGUAGE = "en"` with generated `ru`, a one-card `FAST_PATH`, the change folder and the `[P]` parallel mark. +- Scheduler as an interface over an engine: `SCHEDULER_ENGINE = "inngest"`, `SCHEDULER_ALTERNATES = ["temporal"]`; every cron card must carry `SCHEDULE, TZ, JITTER_S, OVERLAP, CATCHUP` because a five-field expression alone is ambiguous on DST days; external `postgres`/`redis` state, 30/14-day run/trace retention, engine image pinned (measured 2026-09-13: fork image `ghcr.io/ghashtag/inngest:mcp-auth` until upstream PR inngest/inngest#4860 ships). +- Approvals: `HITL_MODEL = "wait-for-event"`, 72 h timeout into `question`, seven `NEEDS_APPROVAL` tools (merge, Railway variables and services, refund, external messages, secret rotation, data delete); a Bee patch is accepted by `["task-contract", "t27c"]`, the Queen owns the merge decision, the Bee sees the full trace. Budgets are card fields: `BEE_MAX_ITER = 8`, `BEE_MAX_TOKENS = 400000`, `RUN_MAX_MINUTES = 90`. +- Media, measured 2026-09-13 on the Railway CPU services: Qwen3-VL-2B Q8 at 17-30 tok/s prompt, about 1.5-3 tok/s generation; a four-frame clip scaled 448 px by width only reached 1514 prompt tokens and missed the 300 s timeout twice, so the card fixes `VISION_FRAME_LONGEST_SIDE = 448`, `VISION_VIDEO_MAX_TOKENS = 200` and lists the owner fallbacks in order. STT minimum `RTFX 2`, hallucination filter on, unread files reported as unread. +- Evidence fields are read from the registry (2026-09-12): `FORMATS = 83`, `SW_BITEXACT = 75`, Tier-E decode 14 / compute 19, `SILICON_CLAIMED = false`. Eight owner-only items are counted, not performed. +- Not checked: the card was not run through `t27c` on the authoring host (no checkout there); it is ASCII-only and follows the shape of `specs/automation/inngest-queen-scheduler.t27`. Not claimed: no host reads this card yet; no CONTROL field changes. The Russian plan that comments on it is gHashTag/999-multibots-telegraf PR #2387. diff --git a/specs/system/unified-agent-operations.t27 b/specs/system/unified-agent-operations.t27 new file mode 100644 index 000000000..18938e992 --- /dev/null +++ b/specs/system/unified-agent-operations.t27 @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: Apache-2.0 +// specs/system/unified-agent-operations.t27 -- the one system that the Trinity repositories form +// together: canonical contracts (t27), the Queen and her Bees, the Inngest scheduler, the 999 +// application edge (bot, Mini App, Hive, CRM, media library), the self-hosted inference services +// (whisper = Speaches, vision = llama.cpp + Qwen3-VL) and the evidence tracks (GoldenFloat, AX7203, +// Golden Sieve, publications). This card names the parts, the contracts between them, the gates +// every change must pass and the budgets every run must keep. It claims nothing that a witness has +// not shown: every numeric field below is either a limit we choose or a value measured on +// 2026-09-13 and marked so. Hosts read this card with the compiler (t27_analyze -> ConstDecl); +// the Russian development plan (999-multibots-telegraf/docs/, the Russian "unified plan" file) is generated +// commentary on this card, never the other way round. +// phi^2 + 1/phi^2 = 3 | TRINITY + +module system::unified_agent_operations { + + pub const KIND : str = "system"; + pub const ID : str = "unified-agent-operations"; + pub const VERSION : u8 = 1; + pub const OWNER : str = "gHashTag"; + pub const AUTHORED : str = "2026-09-13"; + + // ---------------------------------------------------------------- layers + // Four layers, one direction of authority: a lower layer never edits a higher one. + // 1 contracts -- gHashTag/t27 specs/**; the only place logic and English text originate. + // 2 control -- Queen (trios agent-server), Bees, the t27-queen Inngest app, this card. + // 3 edge -- 999-multibots-telegraf: bot, Mini App, Hive, CRM, vibee-render, 999 Inngest app. + // 4 evidence -- GoldenFloat registry, AX7203 transcripts, Golden Sieve verdicts, papers. + pub const LAYERS : [4]str = ["contracts", "control", "edge", "evidence"]; + pub const AUTHORITY_FLOWS_DOWN : bool = true; + + // Subsystems as the inventory of 2026-09-13 lists them (the Russian unified plan, section 1). + pub const SUBSYSTEMS : [14]str = [ + "t27-toolchain", "trinity-reconstruction", "queen-hive-bees", "t27-queen-scheduler", + "999-bot-miniapp", "999-inngest", "999-crm-media", "whisper-speaches", "vision-llamacpp", + "goldenfloat-registry", "ax7203-fpga", "golden-sieve", "tri-net", "publications" + ]; + // Related but separately governed: leela, turbobaby, woody-weed, igla, browseros-trios. + pub const SATELLITES : [5]str = ["leela", "turbobaby", "woody-weed", "igla-training", "browseros-trios"]; + + // ------------------------------------------------------------- contracts + // Every card carries these fields or is refused (fail-closed, never fail-open). + pub const CARD_REQUIRED : [6]str = ["KIND", "ID", "VERSION", "OWNER", "REPO", "ENABLED"]; + // A card that does not typecheck is listed as refused and skipped; the rest are served. + pub const ON_BAD_CARD : str = "refuse-card-serve-rest"; + // Status vocabulary for prose derived from cards. Nothing else is allowed in generated text. + pub const STATUS_TAGS : [4]str = ["measured", "decision", "question", "known"]; + // Words no generated text may contain (Trinity honesty rule). + pub const FORBIDDEN_CLAIMS : [3]str = ["first", "only", "best"]; + // Text the host generates from a card must be regenerated, never hand-edited; a CI check + // compares regenerated output with the committed one and fails on drift (Spec Kit lesson: + // "the spec does not update itself"). + pub const DRIFT_CHECK : str = "regenerate-and-diff"; + pub const DRIFT_CHECK_REQUIRED_STATUS : str = "t27-drift"; + // Localization is generated from the English card; a Russian file never carries new logic. + pub const SOURCE_LANGUAGE : str = "en"; + pub const GENERATED_LANGUAGES : [1]str = ["ru"]; + // Small change fast path: one card, one host file, no new field -> skip proposal/design, + // keep compile + drift + tests. Anything larger takes the full change folder. + pub const FAST_PATH_MAX_CARDS : u8 = 1; + pub const CHANGE_FOLDER : [4]str = ["proposal.md", "specs/", "design.md", "tasks.md"]; + // Tasks safe to run in parallel are marked [P]; the Queen hands each [P] group to one Bee. + pub const PARALLEL_MARK : str = "[P]"; + + // -------------------------------------------------------------- scheduler + // The scheduler is an interface; Inngest is its current engine (self-hosted, Railway). + // Swapping the engine must not touch specs/crons or specs/skills. + pub const SCHEDULER_INTERFACE : str = "specs/automation/inngest-queen-scheduler.t27"; + pub const SCHEDULER_ENGINE : str = "inngest"; + pub const SCHEDULER_ALTERNATES : [1]str = ["temporal"]; + // Every cron card must declare these, because a five-field cron alone is ambiguous on + // DST days ("may run zero, one, or two times") and says nothing about overlap or backfill. + pub const CRON_REQUIRED : [5]str = ["SCHEDULE", "TZ", "JITTER_S", "OVERLAP", "CATCHUP"]; + pub const CRON_TZ_DEFAULT : str = "UTC"; + pub const CRON_OVERLAP_VALUES : [3]str = ["skip", "buffer-one", "allow"]; + pub const CRON_CATCHUP_VALUES : [2]str = ["none", "last-missed"]; + // Self-hosted engine: one box plus external state, or state is lost with the box. + pub const ENGINE_STATE_EXTERNAL : bool = true; + pub const ENGINE_STATE_STORES : [2]str = ["postgres", "redis"]; + // Runs and traces are deleted by policy, not by accident; the engine does not do it alone. + pub const RUN_RETENTION_DAYS : u16 = 30; + pub const TRACE_RETENTION_DAYS : u16 = 14; + // Engine version is pinned by digest and moved by PR. Measured 2026-09-13: fork image + // ghcr.io/ghashtag/inngest:mcp-auth (v1.44.0 + PR inngest/inngest#4860); return to the + // official image is an owner step after the upstream release (cron watcher 01f8b516). + pub const ENGINE_PINNED : bool = true; + + // ------------------------------------------------------------ approvals + // Human-in-the-loop is an event, never a blocking call: the run parks on wait-for-event + // and resumes on approve/reject or times out into "question". + pub const HITL_MODEL : str = "wait-for-event"; + pub const HITL_TIMEOUT_H : u16 = 72; + pub const HITL_ON_TIMEOUT : str = "question"; + // Approval is declared per tool, not per agent. These tools always need it. + pub const NEEDS_APPROVAL : [7]str = [ + "git.merge", "railway.variable.set", "railway.service.create", "payment.refund", + "telegram.send.external", "secret.rotate", "data.delete" + ]; + // The owner's one-word merge command and the PR footer that negates it are Russian literals + // kept in the edge repository (this file stays English); the host reads them from there. + pub const MERGE_WORD_SOURCE : str = "999-multibots-telegraf/docs/OWNER-DECISIONS.md"; + pub const PR_FOOTER_REQUIRED : bool = true; + // A Bee patch is accepted only after the task contract and the compiler both pass on the + // host side; a second agent's opinion is not a verifier (MAST: missing task verification). + pub const BEE_ACCEPT : [2]str = ["task-contract", "t27c"]; + pub const QUEEN_OWNS_MERGE_DECISION : bool = true; + pub const BEE_SEES_FULL_TRACE : bool = true; + + // --------------------------------------------------------------- budgets + // Multi-agent runs cost about 15x a chat turn; budgets are card fields, not runtime knobs. + pub const BEE_MAX_ITER : u8 = 8; + pub const BEE_MAX_TOKENS : u32 = 400000; + pub const QUEEN_MAX_BEES_PER_TASK : u8 = 4; + pub const RUN_MAX_MINUTES : u16 = 90; + pub const ON_BUDGET_EXCEEDED : str = "stop-report-question"; + + // -------------------------------------------------------------- secrets + // Secrets live in the process environment or the owner-restored .env; scripts and skills + // never read them from a cloud CLI or API, never print a value (name, length, prefix only). + pub const SECRET_SOURCES : [2]str = ["process-env", "owner-dotenv"]; + pub const SECRET_PRINT : str = "name-length-prefix"; + // Public surfaces that carry no auth of their own must sit behind a private network or a + // proxy with a key: Speaches /docs and /openapi.json, llama.cpp GET /props, Inngest UI. + pub const PRIVATE_ONLY_SURFACES : [3]str = ["whisper:/docs", "vision:/props", "inngest:/"]; + + // --------------------------------------------------------------- media + // Speech to text: the self-hosted Speaches service; quality is a rate, RTFx, not a feeling. + pub const STT_SERVICE : str = "whisper"; + pub const STT_RTFX_MIN : u8 = 2; + // Roughly one transcript in a hundred contains invented phrases; a hallucination filter is + // part of the pipeline, and an unread file is reported as unread, never as empty. + pub const STT_HALLUCINATION_FILTER : bool = true; + // The marker text itself is a localized string of the edge repository (media-library.md). + pub const UNREAD_MARKER_SOURCE : str = "999-multibots-telegraf/docs/crm/media-library.md"; + // Vision: llama.cpp server with Qwen3-VL-2B on CPU. Measured 2026-09-13 on Railway: + // prompt processing 17-30 tok/s, generation about 1.5-3 tok/s; a four-frame clip at + // 448 px width-only scaling produced 1514 prompt tokens and did not finish in 300 s. + pub const VISION_SERVICE : str = "vision"; + pub const VISION_MODEL : str = "ggml-org/Qwen3-VL-2B-Instruct-GGUF:Q8_0"; + pub const VISION_FRAMES : u8 = 4; + pub const VISION_FRAME_LONGEST_SIDE : u16 = 448; + pub const VISION_VIDEO_MAX_TOKENS : u16 = 200; + pub const VISION_TIMEOUT_S : u16 = 300; + // Fallbacks, in order, when a clip still misses the timeout (owner decision, not automatic): + pub const VISION_FALLBACKS : [3]str = ["frames=2", "quant=Q4_K_M", "timeout=600"]; + // Inference images are pinned; a daily-moving build broke prompt speed upstream (b10780). + pub const INFERENCE_IMAGES_PINNED : bool = true; + + // ------------------------------------------------------------ reliability + // Reliability is measured by repeated runs: pass^k over K runs with fault injection, on the + // served cron/skill catalog, before a card's CONTROL may say "inngest". + pub const RELIABILITY_K : u8 = 5; + pub const RELIABILITY_FAULT_RATE_PCT : u8 = 20; + pub const RELIABILITY_METRIC : str = "pass^k"; + // Config is a blueprint (this card); state is a row in the state store. State never enters + // a card, and a card never carries a run id. + pub const CONFIG_STATE_SEPARATED : bool = true; + + // -------------------------------------------------------------- evidence + // Numbers about formats and hardware are read from the registry and board transcripts. + // Measured or registry-read 2026-09-12: 83 formats; 75 strict SW-bitexact; Tier-E snapshot + // 33/83 (decode 14, compute 19). The HW union above that is a question, not a claim. + pub const FORMATS : u8 = 83; + pub const SW_BITEXACT : u8 = 75; + pub const HW_TIER_E_DECODE : u8 = 14; + pub const HW_TIER_E_COMPUTE : u8 = 19; + pub const SILICON_CLAIMED : bool = false; + // Golden Sieve: every published number passes the cascade; a QUESTION verdict stays visible. + pub const CLAIM_AUDIT : str = "golden-sieve"; + + // ------------------------------------------------------------ boundaries + // Owner-only steps this card cannot perform and does not pretend to (2026-09-13): + // GitHub Actions billing (CI blocked); Inngest Cloud key rotation; 34 Dependabot alerts + // (2 high); inngest image back to official after #4860; render OPENAI_API_KEY answers 401; + // Ludmila 1210 Stars refund; rotation of leaked keys (12 categories); dead GramJS session. + pub const OWNER_ITEMS : u8 = 8; + pub const ENABLED : bool = true; +}