diff --git a/specs/t27mcp/dashboard.t27 b/specs/t27mcp/dashboard.t27 new file mode 100644 index 0000000000..b0c21f64e3 --- /dev/null +++ b/specs/t27mcp/dashboard.t27 @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: Apache-2.0 +; specs/t27mcp/dashboard.t27 -- the session dashboard of the t27 MCP server (gHashTag/t27-mcp): one page that +; tells the agent and the human operator what state the corpus and the session are in, and what to do next. +; See the epic #10066. +; -- +; Agent and operator ask the same questions: is the corpus healthy enough to reuse from, did a tool call fail, +; did a reply grow past what the host shows inline, and what is the next step. This spec grades each number +; and picks the next step; the server only counts its calls, reads the manifest and fills the templates below. +; -- +; The rules: +; - A grade (tone) is one of OK, UNKNOWN, WARN, BAD, in that order of severity. worst() of two grades is the +; more severe one, so UNKNOWN never adds up to OK: a panel with nothing to judge is not a passing panel. +; - Corpus health: BAD when at least 5 in 100 specs fail, WARN when any spec fails or at least 20 in 100 warn, +; UNKNOWN when the manifest names no spec. +; - Session calls: UNKNOWN before the first call, BAD when at least one call in four failed, WARN when any did. +; - Reply size: a reply over REPLY_WARN_BYTES costs the agent context on every turn that keeps it; over +; REPLY_BAD_BYTES the host stores it in a file instead of showing it, and the agent pays a second read. +; On 2026-10-18 a plain t27_status reply was 57,084 bytes, 44 KB of it the list of failing specs. +; - next_step() picks one line of NEXT_TEXT, most urgent first: a failed call, an oversized reply, a failing +; corpus, no call yet, nothing to fix. +; - UNKNOWN_TEXT names what the page cannot know from the server's own data, so a blank is read as unknown +; and not as absent. +; The templates use `{}` for the values the server fills in, left to right, and only single quotes inside. +; phi^2 + 1/phi^2 = 3 | TRINITY + +module T27mcpDashboard; + +/// Grades, in order of severity. +pub const T_OK : u32 = 0; +pub const T_UNKNOWN : u32 = 1; +pub const T_WARN : u32 = 2; +pub const T_BAD : u32 = 3; + +pub const TONE_NAME : [4]str = ["ok", "unknown", "warn", "bad"]; + +/// Reply size thresholds in bytes (see the rules above). +pub const REPLY_WARN_BYTES : u32 = 8192; +pub const REPLY_BAD_BYTES : u32 = 25000; + +/// next_step() answers, as indices into NEXT_TEXT. +pub const N_ERRORS : u32 = 0; +pub const N_BIG : u32 = 1; +pub const N_FAILING : u32 = 2; +pub const N_START : u32 = 3; +pub const N_READY : u32 = 4; + +pub const NEXT_TEXT : [5]str = [ + "A tool call failed in this session. Read its error text before you call again: the same arguments give the same error.", + "A reply passed the size the host shows inline, so it was stored in a file. Ask for less: a limit, a path filter, or t27_spec without source.", + "Many corpus specs fail. t27_status names them; reuse only a spec whose health is ok.", + "No call yet. Look up first: t27_find with what the module does, then t27_spec; write new .t27 only on a miss.", + "Nothing to fix. Look up first (t27_find, t27_specs), run t27_check on .t27 you write, and take the verdict from t27c test-report." +]; + +pub const PANEL_TITLES : [5]str = ["Corpus", "This session", "Next step", "Server", "Not known here"]; + +pub const UNKNOWN_TEXT : [3]str = [ + "Seal frontier: which specs reuse a sealed verdict needs t27c frontier on a checkout.", + "Test receipts: the manifest records that a spec has tests, not that they pass.", + "CI and review state of open pull requests." +]; + +pub const PAGE_TEXT : str = "
{}{}
"; +pub const LINE_TEXT : str = "{}
"; +pub const TABLE_HEAD : str = "| tool | calls | errors | largest reply, bytes |
|---|---|---|---|
| {} | {} | {} | {} |