Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion .claude/skills/t27f/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ the diagram core in detail, then the other surfaces and the topic-map applicatio
| Spec -> graph IR schema (the core) | `specs/t27f/spec_graph.t27` (t27#10020) | spec with tests: node / edge kinds, labels, spans, `validate_graph`, line -> node mapping, node -> ui_plan widget, one hand-read fixture (`specs/tutorial/08_modules_and_arrays.t27`) |
| Graph view: layout of a spec graph | `specs/t27f/spec_graph_view.t27` (t27#10034) | spec with tests: one column per node kind, size / colour / dash / row order from the inference label, UNKNOWN nodes alone in a band, every edge with a source line, node -> widget through `node_widget`; numbers only, laid out on the hand-read fixture; drawn by the MCP tool `t27f_graph` (gHashTag/t27-mcp#9) |
| Graph view for big specs: wrap, fold, expand, hit | `specs/t27f/spec_graph_fold.t27` (t27#10218) | spec with tests: a kind column taller than N = 12 rows wraps into sub-columns so the canvas aspect is near phi (identical to the view when nothing wraps); a fold to one box per kind with the exact count and one arc per pair of kinds with the exact edge count, each labelled by its weakest member; `expand_graph` = one kind plus its direct neighbours, copied verbatim with an origin map; `wrap_hit` / `wrap_hit_line_start` / `wrap_hit_line_end` take a click to a node and its lines; numbers only, the view's colours are not touched |
| Dependencies view: the specs around one spec | `specs/t27f/spec_deps.t27` (t27#10680) | spec with tests: reads `t27c use-edges --specs-dir specs`; layer 0 is the focus, +k the specs k imports away (right), -k the specs k importers away (left), each spec once in its shortest-path layer; every edge-list line between two drawn specs is one `exact` edge, a repeated line drawn once; `cycle=1` when the focus imports itself or is imported by a spec in its own import closure; a walk past the caller's room or depth is refused whole (`refused\tfull` / `refused\tdeep`), never cut. Limits: `use` lines t27c does not resolve are not drawn (#7176); the view flags only the focus, and `deps_cycles` (t27#10693) lists every spec on a cycle, each once, refused whole (`cap + 1`) if anything does not fit; a spec on a cycle through the focus is drawn on both sides; no host draws it yet. Corpus on master e607228f7: 806 specs, 2461 edge lines, nothing refused at depth 32, deepest walks 6, one real cycle (igla race `backend` <-> `rtl`), which `deps_cycles` lists exactly on master f7efbc232 and lists as empty with #10689 |
| Dependencies view: the specs around one spec | `specs/t27f/spec_deps.t27` (t27#10680) | spec with tests: reads `t27c use-edges --specs-dir specs`; layer 0 is the focus, +k the specs k imports away (right), -k the specs k importers away (left), each spec once in its shortest-path layer; every edge-list line between two drawn specs is one `exact` edge, a repeated line drawn once; `cycle=1` when the focus imports itself or is imported by a spec in its own import closure; a walk past the caller's room or depth is refused whole (`refused\tfull` / `refused\tdeep`), never cut. A `use` line t27c does not resolve is not in the edge list, so `deps_unknown` (t27#10702) reads the focus source and writes each such line as `unknown\tpath`, mirroring `use_resolve.rs` (whole path, then one fallback level) without looking for a file; on master f33f269d5 that was 23 lines in 13 specs, byte for byte the `t27c gen` warnings. Limits: the view flags only the focus, and `deps_cycles` (t27#10693) lists every spec on a cycle, each once, refused whole (`cap + 1`) if anything does not fit; a spec on a cycle through the focus is drawn on both sides; no host draws it yet. Corpus on master e607228f7: 806 specs, 2461 edge lines, nothing refused at depth 32, deepest walks 6, one real cycle (igla race `backend` <-> `rtl`), which `deps_cycles` lists exactly on master f7efbc232 and lists as empty with #10689 |
| Spec -> graph IR exporter | `specs/t27f/spec_graph_export.t27` (t27#10162) | spec with tests: `export_graph(path, src)` is a deterministic byte scanner over the source, `export_verdict` is `validate_graph` of the result. One node per top-level declaration (a leading `pub ` is allowed), spans to the matching closing brace, every node and edge EXACT or (unclassifiable) OPAQUE + UNKNOWN, CALLS / USES / CONSTRAINS edges with the line of the use, refusal past 1024 nodes or 4096 edges. On the tutorial 08 snapshot it equals the hand-read fixture on all 14 declaration nodes and all 9 EXACT edges; it does not emit the fixture's `std.testing` UNKNOWN node, nor its 7 DERIVED edges (4 data flow, 3 tested_by), because a scanner never derives; the derive pass below adds them. Limits: textual matching without scope or type resolution, no block comments, no struct/enum bodies, no cross-spec `use` resolution, capacity 1024 nodes and 4096 edges, u16 indices (all 2225 specs in specs/ fit, largest 775 nodes and 3194 edges after derive; anything past the cap is refused, never truncated), takes a `[]const u8` slice rather than `[65536]u8` plus a length. AST/IR audit is trinity#1650, pilot choice #1651 |
| Graph IR derive pass | `specs/t27f/spec_graph_derive.t27` (t27#10191) | spec with tests: `derive_graph(g, src)` appends what the exporter must not claim and changes nothing it holds. R1 DERIVED `tested_by` = every EXACT CALLS edge from a test, invariant or bench to a fn read backwards (no line). R2 DERIVED `data_flow` = a const or `use` that an EXACT USES edge ties to a fn and that is named inside one of the fn's return statements (from `return` to the next `;`), on the line of the first such name. R3 UNKNOWN opaque node = an undeclared qualified call target of three or more segments (`std.testing.expectEqual(` names `std.testing`), spanning the lines that call through it. Exporter plus derive equal the tutorial 08 fixture as sets: 15 of 15 nodes, 16 of 16 edges, no special case. Limits: names matched as text; call results and flow through locals are not derived; R3 needs 3 or more segments (two cannot be told from a method call); a graph that does not validate, or a source of another line count, comes back unchanged; past 1024 nodes or 4096 edges the result is refused with the too-many verdict. Not wired to a host: the MCP tool does not call it |
| UI plan IR + trusted widget catalog | `specs/t27f/ui_plan.t27` (t27#9962) | spec with tests; no renderer draws a plan yet |
Expand Down Expand Up @@ -366,6 +366,24 @@ Railway lab. Do not commit it.
4. Remove the scratch spec, and `git checkout` any spec you swapped in, before you seal
anything.

### Check that the unknown imports match t27c (t27#10702)

`deps_unknown` has an oracle. `t27c gen <spec>` prints `warning: <spec>:<line>: use X resolves
to no spec` on stderr for every `use` line it drops (#7176), so the two lists must agree byte
for byte.

1. On the lab, before any scratch spec is in `specs/`, write three files:
- the gen warnings over every spec (`t27c gen $f > o.zig 2>> warn.txt` over
`git ls-files 'specs/*.t27'`; never write to or read from `/dev/null` there);
- the `use-edges` list;
- every `use` line as `spec<TAB>line` (`grep -E '^[[:space:]]*use '`).
Check that none of them holds `"`, `\` or `$` before you embed it.
2. The scratch spec copies each use line into a small buffer and calls `deps_unknown` with that
line's spec as the focus. It prefixes each output line with the spec and expects
`spec<TAB>unknown<TAB>X` in `git ls-files` order, which is the order gen ran in.
3. Controls: the same list minus one line must FAIL, and so must `w == 0`. On master f33f269d5
it was 23 lines in 13 specs (#7176 had counted 119 in 70), and both controls failed.

## What this skill does not claim

The graph IR is a schema (`specs/t27f/spec_graph.t27`) and `specs/t27f/spec_graph_export.t27` turns source into it, but only exact declarations, spans and edges within the IR's capacity, with `specs/t27f/spec_graph_derive.t27` adding the derived and unknown part by stated rules, and no host calls either yet; no renderer draws a T27F view in the Trinity UI, no
Expand Down
16 changes: 8 additions & 8 deletions .trinity/seals/t27f_t27f_spec_deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,23 @@
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:24377e650e9303759aa6b0b805604ae6d9529c45c10e33242c8be73da902067e",
"gen_hash_rust": "sha256:1753610b6d2287d2dec15cd904813eeb22db4208ecfb98b90cec0e34b76274e9",
"gen_hash_verilog": "sha256:ca51cd614290ebde62e75fa09618241eb221062882dde6d86248a1c28666469b",
"gen_hash_zig": "sha256:add0c9a74743b291f6e2ff110a93868e2a777a7ba99d3126745dc07922ac444e",
"gen_hash_c": "sha256:a827ac501c5bc3a6cb34fb9eed1a765efaf6c65dcaef25c64ff4ab34e053f47f",
"gen_hash_rust": "sha256:ecd73ef257fce64599a99a522559ac91b0fe6a1a364863f163584bdd253e0673",
"gen_hash_verilog": "sha256:47a568b333eb16e44c62b907f678ab98e42ea629611d36a2d52edd91a95e4023",
"gen_hash_zig": "sha256:8082c63e31383157aaa1771ec8d4feaf6b1090da42127267c41b8a8afad06251",
"module": "t27f_spec_deps",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-18T22:30:43Z",
"sealed_at": "2026-10-18T22:58:06Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:b4a87ecfd782bbd552d561fbb39a43b23d8ab4f174b30e1045d52c5cef16d2bb",
"spec_hash": "sha256:c7b44f43776b8a7b0d21aee8a73502e996ec9fb35cd56935bd300b4358f8d4be",
"spec_path": "specs/t27f/spec_deps.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 19,
"total": 19,
"passed": 25,
"total": 25,
"vacuous": 0
},
"toolchain": {
Expand Down
Loading
Loading