diff --git a/specs/OWNERS.md b/specs/OWNERS.md index 78646970b4..8d8e19a44a 100644 --- a/specs/OWNERS.md +++ b/specs/OWNERS.md @@ -29,7 +29,7 @@ | `ui/` | **T-Queen** | The site's viewport contract as a `.t27` spec (`ui/viewport.t27`, `KIND = "viewport"`): tiers by CSS viewport width, panes per tier, the 44 px touch minimum, the six-size QA matrix and the Queen rail capacity read from `Queen.css`; the site (gHashTag/trinity) generates `viewport.generated.ts` / `.css` from a vendored copy and evaluates the spec's own test blocks; `ui/queen_evidence.t27` (`module ui_queen_evidence`): the evidence constants of the Queen's FFN and Ternary Check panel, from which the site generates `queenEvidence.generated.ts`; canonical here since S10, byte-identical to the copy the site carried alone | | `catalog/` | **T-Queen** | How the site's spec catalog and the Queen map find the repositories that write `.t27` (`catalog/discovery.t27`, `KIND = "discovery"`): the GitHub owners scanned, the exclusions, what makes a candidate qualify (a declaration in the compiler's AST, not a file extension) and the limits; the site (gHashTag/trinity) vendors a byte-identical copy and `scripts/discover-t27-worlds.mjs` reads it through the compiler wasm before touching GitHub | | `t27f/` | **T-Queen** | T27F, the visual spec of a .t27 file (gHashTag/trinity#1648, RFC #1649; definition in `.claude/skills/t27f/SKILL.md`): `t27f/spec_graph.t27` (module `t27f_spec_graph`): the core graph IR a spec becomes -- node and edge kinds, inference labels, source spans, `validate_graph`, source mapping both ways and the node -> ui_plan widget binding, with one hand-read fixture; `t27f/spec_graph_view.t27` (module `t27f_spec_graph_view`): the graph view, a deterministic layout of a spec graph -- one column per node kind, style and row order from the inference label, UNKNOWN nodes drawn alone, every edge with a source line; numbers only, a host draws them; `t27f/ui_plan.t27` (module `t27f_ui_plan`): the renderer-neutral UI plan IR and the trusted widget catalog. Applications built on it: the topic-to-value map of gHashTag/trinity#1677 (`t27f/topic_engine.t27`, module `T27fTopicEngine`): the 3 x 9 = 27 lesson shape, intake and gap rules, keyword routing to one domain, the Bee dispatch cap, the evidence and approval gates, and progression that is never money; driven by the Claude Code skill `.claude/skills/t27f/SKILL.md` through the t27 MCP server; `t27f/reel.t27` (module `T27fReel`): the video format of a topic map and the still views of a Claude Code answer -- honeycomb geometry, focus+context camera, scene catalog, per-target limits, gap styling, the posting gate and the channel per host; numbers only, a host draws them; `t27f/deck.t27` (module `T27fDeck`): the default look of a reel, every scene a presentation slide -- layouts per scene, regions, type sizes, glass card, palette kept off the status colours, contrast and card fades | -| `t27mcp/` | **T-Queen** | The decisions of the t27 MCP server (gHashTag/t27-mcp) as `.t27` specs, compiled to wasm that the server runs: `t27mcp/check_hints.t27` (module `T27mcpCheckHints`): which short "write this instead" hint a compiler message gets for foreign syntax (`in` as a name, `as u3`, `x++`, `a ? b : c`, `match`), and the line number a message names; `t27mcp/examples.t27` (module `T27mcpExamples`): which short slice of the published corpus, pinned to one commit, answers a question about clocked or combinational modules, `fn`, `test` blocks and the reset styles; the server's JavaScript is I/O glue and holds no rule | +| `t27mcp/` | **T-Queen** | The decisions of the t27 MCP server (gHashTag/t27-mcp) as `.t27` specs, compiled to wasm that the server runs: `t27mcp/check_hints.t27` (module `T27mcpCheckHints`): which short "write this instead" hint a compiler message gets for foreign syntax (`in` as a name, `as u3`, `x++`, `a ? b : c`, `match`), and the line number a message names; `t27mcp/examples.t27` (module `T27mcpExamples`): which short slice of the published corpus, pinned to one commit, answers a question about clocked or combinational modules, `fn`, `test` blocks and the reset styles; `t27mcp/spec_brief.t27` (module `T27mcpSpecBrief`): which manifest fields a short spec row keeps and why a failing spec fails (a bit set of reasons plus their text templates); the server's JavaScript is I/O glue and holds no rule | | `trinity/` | **T-Queen** + **A-Architect** | The project manifest of gHashTag/trinity as `.t27` specs (`trinity/project.t27`, `KIND = "project"`; `trinity/capabilities/.t27`, `KIND = "capability"`): the pinned consumer revision, profiles, dispositions and evidence tags, dialect and build counts, dependency pins and the work packages of gHashTag/trinity#988; each card names its owner, canonical spec, implementation and generated paths, build targets, acceptance command and evidence; `tools/trinity_manifest.py` derives the inventory from a clean pinned checkout and holds the cards to it; `trinity/compiler_matrix.t27` (`KIND = "compiler-matrix"`) names the pinned compiler, the backends, the stages and the features of the executable subset with their fixtures under `bootstrap/tests/fixtures/trinity_matrix/`, and `tools/trinity_compiler_matrix.py` measures them; `trinity/build_graph.t27` (`KIND = "build-graph"`) declares the consumer's toolchain, pins, profiles, generated-file boundaries and receipt policy, and `tools/trinity_build_receipt.py` derives the graph, writes the receipts and judges drift; the consumer vendors a byte-identical copy and generates its manifest from it (S12). Shared contracts stay in their own subtrees (`numeric/`, `vsa/`, `queen/`, `tools/`, `docs/`, `ui/`) and are cited, never copied | Each subtree with substantial churn should keep a local **`OWNERS.md`** (see below). diff --git a/specs/t27mcp/spec_brief.t27 b/specs/t27mcp/spec_brief.t27 new file mode 100644 index 0000000000..6e7c492d4c --- /dev/null +++ b/specs/t27mcp/spec_brief.t27 @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: Apache-2.0 +; specs/t27mcp/spec_brief.t27 -- the brief spec row and the "why does it fail" decision of the t27 MCP server +; (gHashTag/t27-mcp). See the epic #10066. +; -- +; t27_specs, t27_spec and t27_grep answer with a spec row. The whole manifest record is about 860 bytes (AST node +; kinds, emitted bytes per backend, tags, a summary), and a model that only wants "does it compile, and if not +; why" pays for all of it on every row. This spec holds the two decisions that were JavaScript in the server: +; - BRIEF_FIELDS / ONE_FIELDS: which manifest fields a brief row keeps. The server copies those keys and nothing +; else; `fields: true` on the tool returns the whole record instead. +; - why_mask(): `health: "fail"` covers unrelated events. A spec that never parsed reports loss 0, tcErrors 0 and +; no failed backend, not because it is clean but because nothing downstream of the parser ran. why_mask turns +; the observable counters into a bit set; WHY_TEXT holds one template per bit, `{}` marks the number or list +; the server fills in. A spec that is not "fail" gets no reasons at all. +; The mask adds no claim of its own: it reads the counters the manifest already records. +; phi^2 + 1/phi^2 = 3 | TRINITY + +module T27mcpSpecBrief; + +pub const BRIEF_FIELDS : [8]str = [ + "path", + "repo", + "name", + "health", + "lines", + "loss", + "tcErrors", + "failedBackends" +]; + +/// t27_spec keeps the brief fields and what a reader asks next about one file. +pub const ONE_FIELDS : [14]str = [ + "path", + "repo", + "name", + "health", + "lines", + "loss", + "tcErrors", + "failedBackends", + "category", + "bytes", + "tokens", + "nodes", + "summary", + "tags" +]; + +pub const W_NOT_PARSED : u32 = 1; +pub const W_BACKEND : u32 = 2; +pub const W_TYPECHECK : u32 = 4; +pub const W_LOSS : u32 = 8; +pub const W_UNKNOWN : u32 = 16; + +/// One template per bit, in bit order. `{}` is the count or the backend list. +pub const WHY_TEXT : [5]str = [ + "not-parsed: the manifest records no AST, so no backend ran", + "backend: {} returned nothing", + "typecheck: {} error(s)", + "round-trip loss: {}", + "unknown: marked fail with no counter to explain it" +]; + +/// The reasons a spec fails, as a bit set. `is_fail` is 1 for health "fail"; the rest are the manifest counters +/// (nodes of the AST, number of failed backends, type-check errors, round-trip loss). +pub fn why_mask(is_fail: u32, nodes: u32, nfailed: u32, tc: u32, loss: u32) -> u32 { + if (is_fail == 0) { return 0; } + var m : u32 = 0; + if (nodes == 0) { m = m + W_NOT_PARSED; } + if (nfailed > 0) { m = m + W_BACKEND; } + if (tc > 0) { m = m + W_TYPECHECK; } + if (loss > 0) { m = m + W_LOSS; } + if (m == 0) { m = W_UNKNOWN; } + return m; +} + +test "why_mask: a spec that is not failing has no reasons" { + assert why_mask(0, 0, 0, 0, 0) == 0; + assert why_mask(0, 120, 3, 2, 1) == 0; +} + +test "why_mask: a spec that never parsed is not-parsed, not unexplained" { + assert why_mask(1, 0, 0, 0, 0) == W_NOT_PARSED; +} + +test "why_mask: each counter sets its own bit, and bits add" { + assert why_mask(1, 50, 2, 0, 0) == W_BACKEND; + assert why_mask(1, 50, 0, 3, 0) == W_TYPECHECK; + assert why_mask(1, 50, 0, 0, 7) == W_LOSS; + assert why_mask(1, 50, 1, 2, 0) == W_BACKEND + W_TYPECHECK; + assert why_mask(1, 0, 1, 0, 1) == W_NOT_PARSED + W_BACKEND + W_LOSS; +} + +test "negative control: a fail with no counter is W_UNKNOWN alone, never silent" { + assert why_mask(1, 50, 0, 0, 0) == W_UNKNOWN; + assert why_mask(1, 50, 0, 0, 0) != 0; +} + +test "why_mask: all four counters at once leave W_UNKNOWN out" { + assert why_mask(1, 0, 2, 3, 4) == W_NOT_PARSED + W_BACKEND + W_TYPECHECK + W_LOSS; + assert why_mask(1, 0, 2, 3, 4) < W_UNKNOWN; +}