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
32 changes: 31 additions & 1 deletion .claude/skills/t27f/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ Rows start at y = 280 + 76k above the focus and 820 + 76k below it. Then check:
On 255910235 (2483 edge lines, 813 specs named):

- 783 cards drew. `base/types` is the hub: 378 direct importers, reached by 400.
- 30 were refused:
- 30 were refused (all drawn since t27#10728, below):
- 29 because the spec's own name is over 58 bytes (`port/trios/...`);
- 1 because a shown neighbour's name is.
- No spec in the corpus is on an import cycle.
Expand All @@ -479,6 +479,36 @@ Traps:
- **Bands are in edge-list order, so a hub shows `account/*` first.** That is the stated rule,
not a ranking; do not caption the first three as the most important.

#### Long names are abbreviated, not refused (t27#10728)

A shown name of at most 58 bytes is drawn byte for byte. A longer one is drawn as its first
segment, `/...`, and the longest run of whole trailing segments that fits
(`port/.../rings/CR-CHAT-03/src/confirmation_tag_chain`). When no whole run fits, it is drawn as
`...` and its last 55 bytes. Only drawn bytes are checked, and the text size follows the drawn
length. `why_card` is unchanged and still refuses a name over 58 bytes.

On 5440d35e1 the sweep compares the new binary with master's, card by card:

- 30 cards are newly drawn, 783 are byte-identical to master, and 0 are lost or refused;
- 0 changed cards and 0 newly drawn cards have no `...`, and 0 identical cards have one;
- 29 abbreviated forms are drawn: 27 `/.../` and 2 `...`, the longest 58 bytes;
- the helpers card (29 importers), a `/.../` focus and a `...` focus passed every pixel check,
with 0 white pixels outside x 100..980.

Lab traps from this run:

- **`pkill -f dn_lab.sh` kills the fs-lab command that runs it**, because the pattern is in that
command's own line. Write `pkill -f '[d]n_lab.sh'`.
- **An untracked seal in the lab checkout makes `git checkout` fail, and the script then tests the
old commit.** Have the script take the commit it must test and stop with `WRONG COMMIT` when
`HEAD` differs. Once the PR adding a seal merges, that seal is tracked, so `rm -f` of it deletes
a tracked file: restore it with `git checkout --` before sealing.
- **Count a kill only on `^ ?FAIL [a-z]`.** The `FAIL 0` summary line otherwise counts as a failing
test, and a surviving mutant reads `KILLED by 1: 0`.
- **A `<` mutant of a 58-byte bound needs an unquotable byte that only the whole-name check
sees.** A 58-byte name with `:` in the middle is `true` under the mutant, because the dots form
hides that byte, and `false` under the rule.

## 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_deps_card.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,23 @@
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:e0771c20aea80a2d085ea8151707616be36da0a1075f48dcc81471b21dfb3624",
"gen_hash_rust": "sha256:8b918de8a45d5fb657999906ab375c03b0f4f75289bb4662a1d34143ba99886d",
"gen_hash_verilog": "sha256:ed6c7559eb3bb422722770679c14d41c53a6a56fe3521d444cdfc408b22eb66c",
"gen_hash_zig": "sha256:eecc2a4bc35cf81dff2bde43f15e53903728aa66d5898de7c916e60fefff1c38",
"gen_hash_c": "sha256:683eaa26f084480224ca235b1b3c8fd3b3054e8b40c21ba9cbda756746e1182f",
"gen_hash_rust": "sha256:2e5b5fa8665015b90bf5adc6868fc719b0017e11b94639791a306cbf0bffbf9e",
"gen_hash_verilog": "sha256:a3778e7e0be41b04d8f4e4bcd5a8584394a1a6f78595832b4292a8aaf781373d",
"gen_hash_zig": "sha256:59fe61003bfe57fce363d3b6072112d96309dfe0a3819486afb7e518d80d1352",
"module": "t27f_deps_card",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-19T01:03:00Z",
"sealed_at": "2026-10-19T01:13:38Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:05e744da11ef490c883a7a46c9d5ee7869a1b21f50f1999e6dda0706d68b5f0d",
"spec_hash": "sha256:96b9f08f0229d5408e2b44e9ced7519f68e898a9d3e8bc7a3c055bd72a93c893",
"spec_path": "specs/t27f/deps_card.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 11,
"total": 11,
"passed": 17,
"total": 17,
"vacuous": 0
},
"toolchain": {
Expand Down
222 changes: 209 additions & 13 deletions specs/t27f/deps_card.t27
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@
; tint): every edge is a line t27c resolved. The subtitle reads ON AN IMPORT CYCLE, in the
; derived gold, exactly when deps_on_cycle holds for the focus;
; - an empty band draws its label with 0 and no connector;
; - a shown name of at most CARD_NAME_MAX bytes is drawn byte for byte. A longer one is drawn
; abbreviated, and the abbreviation shows on the card (gHashTag/t27#10728): its first path
; segment, `/...`, and the longest run of whole trailing segments that keeps it within
; CARD_NAME_MAX; when no run of whole segments fits, `...` and its last CARD_NAME_MAX - 3
; bytes. Only drawn bytes are checked, and the text size follows the drawn length;
; - nothing is drawn (dcard_graph returns 0) for a focus on no line of the edge list, a refused
; walk, or a shown name or font path the graph cannot quote or that does not fit. A name in a
; band past DCARD_ROWS is not drawn, so it is not checked. A graph that does not fit the
; caller's room is refused whole.
; walk, or a drawn byte or font path the graph cannot quote. A name in a band past DCARD_ROWS
; is not drawn, so it is not checked. A graph that does not fit the caller's room is refused
; whole.
; --
; The drawing helpers and the name rules are why_card's, imported, not copied (duplicate-bodies).
; --
Expand All @@ -33,6 +38,8 @@
; - a band shows DCARD_ROWS specs in edge-list order, not the "most important" ones: the card has
; no measure of importance, and does not pretend to;
; - a `use` line t27c does not resolve is in neither band (deps_unknown, #10702, lists those);
; - two long names can abbreviate to the same text. The abbreviation says a name was cut; it
; does not say which spec it is, and the card does not claim it does;
; - nothing posts the card. Publishing it is the owner's call.
; phi^2 + 1/phi^2 = 3 | TRINITY

Expand Down Expand Up @@ -72,6 +79,8 @@ pub const DCARD_MORE : str = " more$";
pub const DCARD_REACHES : str = "reaches $";
pub const DCARD_REACHED : str = " / reached by $";
pub const DCARD_FOOT : str = " / every edge exact$";
pub const DCARD_CUT : str = "/...$";
pub const DCARD_DOTS : str = "...$";

// ---- geometry ----

Expand Down Expand Up @@ -99,6 +108,87 @@ pub fn dcard_name_font(len: usize) -> usize {
return f;
}

// ---- long names ----

/// Where the first path segment of the shown name s[a..b] ends: its first '/', or b.
pub fn dcard_head_end(s: []const u8, a: usize, b: usize) -> usize {
var i : usize = a;
while (i < b) {
if (s[i] == '/') { return i; }
i += 1;
}
return b;
}

/// Where the kept tail of the shown name s[a..b] begins when it is whole segments: the first '/'
/// past the head from which head, `/...` and the rest fit CARD_NAME_MAX. b when none fits.
pub fn dcard_seg_from(s: []const u8, a: usize, b: usize) -> usize {
const h : usize = dcard_head_end(s, a, b);
const cut : usize = lit_len(DCARD_CUT);
if (h >= b or h - a + cut >= CARD_NAME_MAX) { return b; }
const room : usize = CARD_NAME_MAX - (h - a) - cut;
var j : usize = h + 1;
while (j < b) {
if (s[j] == '/' and b - j <= room) { return j; }
j += 1;
}
return b;
}

/// Where the byte-cut tail of a shown name ending at b begins.
pub fn dcard_dots_from(b: usize) -> usize {
return b - (CARD_NAME_MAX - lit_len(DCARD_DOTS));
}

/// Is every byte of s[x..y] quotable.
pub fn dcard_quotable_span(s: []const u8, x: usize, y: usize) -> bool {
var i : usize = x;
while (i < y) {
if (card_quotable(s[i]) == false) { return false; }
i += 1;
}
return true;
}

/// How many bytes the shown name of s[f..t] draws: itself up to CARD_NAME_MAX, else its
/// abbreviation.
pub fn dcard_drawn_len(s: []const u8, f: usize, t: usize) -> usize {
const a : usize = card_name_from(s, f, t);
const b : usize = card_name_to(s, a, t);
if (b - a <= CARD_NAME_MAX) { return b - a; }
const j : usize = dcard_seg_from(s, a, b);
if (j < b) { return dcard_head_end(s, a, b) - a + lit_len(DCARD_CUT) + (b - j); }
return CARD_NAME_MAX;
}

/// Can s[f..t] be drawn: a shown name of at least one byte whose drawn bytes are all quotable.
pub fn dcard_name_ok(s: []const u8, f: usize, t: usize) -> bool {
const a : usize = card_name_from(s, f, t);
const b : usize = card_name_to(s, a, t);
if (b <= a) { return false; }
if (b - a <= CARD_NAME_MAX) { return dcard_quotable_span(s, a, b); }
const j : usize = dcard_seg_from(s, a, b);
if (j < b) {
return dcard_quotable_span(s, a, dcard_head_end(s, a, b)) and dcard_quotable_span(s, j, b);
}
return dcard_quotable_span(s, dcard_dots_from(b), b);
}

/// Write the drawn form of s[f..t]'s shown name.
pub fn dcard_put_name(out: []u8, w: usize, cap: usize, s: []const u8, f: usize, t: usize) -> usize {
const a : usize = card_name_from(s, f, t);
const b : usize = card_name_to(s, a, t);
if (b - a <= CARD_NAME_MAX) { return deps_put_span(out, w, cap, s, a, b); }
const j : usize = dcard_seg_from(s, a, b);
if (j < b) {
var p : usize = deps_put_span(out, w, cap, s, a, dcard_head_end(s, a, b));
p = deps_put_lit(out, p, cap, DCARD_CUT);
return deps_put_span(out, p, cap, s, j, b);
}
const q : usize = deps_put_lit(out, w, cap, DCARD_DOTS);
return deps_put_span(out, q, cap, s, dcard_dots_from(b), b);
}

// ---- reading the walks ----

/// Can the first DCARD_ROWS lines of set[lo..hi] be drawn.
Expand All @@ -107,7 +197,7 @@ pub fn dcard_band_ok(set: []const u8, lo: usize, hi: usize) -> bool {
var i : usize = lo;
while (i < hi and r < DCARD_ROWS) {
const e : usize = line_end(set, i, hi);
if (card_name_ok(set, i, e) == false) { return false; }
if (dcard_name_ok(set, i, e) == false) { return false; }
r += 1;
i = e + 1;
}
Expand All @@ -132,10 +222,8 @@ pub fn dcard_put_band(out: []u8, w: usize, cap: usize, font: []const u8, fnl: us
const y : usize = row_y + r * dcard_row_step();
p = card_put_box(out, p, cap, CARD_BOX_X, y, CARD_BOX_W, DCARD_ROW_H, tint, 0);
p = card_put_box(out, p, cap, CARD_BOX_X, y, CARD_BOX_W, DCARD_ROW_H, ok, CARD_BORDER);
const a : usize = card_name_from(set, i, e);
const b : usize = card_name_to(set, a, e);
p = card_text_open(out, p, cap, font, fnl, dcard_name_font(b - a));
p = deps_put_span(out, p, cap, set, a, b);
p = card_text_open(out, p, cap, font, fnl, dcard_name_font(dcard_drawn_len(set, i, e)));
p = dcard_put_name(out, p, cap, set, i, e);
p = card_text_close(out, p, cap, VIEW_TEXT, 0, y + DCARD_ROW_H / 2);
r += 1;
i = e + 1;
Expand Down Expand Up @@ -171,7 +259,7 @@ pub fn dcard_graph(buf: []const u8, n: usize, focus: []const u8, ff: usize, ft:
if (card_quotable(font[fi]) == false) { return 0; }
fi += 1;
}
if (card_name_ok(focus, ff, ft) == false) { return 0; }
if (dcard_name_ok(focus, ff, ft) == false) { return 0; }
if (deps_walk(buf, n, focus, ff, ft, DEPS_IMPORTS, DEPS_MAX_DEPTH, imp, icap, ib) != DEPS_OK) { return 0; }
if (deps_walk(buf, n, focus, ff, ft, DEPS_IMPORTERS, DEPS_MAX_DEPTH, rev, rcap, rb) != DEPS_OK) { return 0; }
const isn : usize = ib[deps_depth(ib, DEPS_MAX_DEPTH) + 1];
Expand Down Expand Up @@ -210,10 +298,8 @@ pub fn dcard_graph(buf: []const u8, n: usize, focus: []const u8, ff: usize, ft:
}
w = card_put_box(out, w, cap, CARD_BOX_X, DCARD_FOCUS_Y, CARD_BOX_W, DCARD_FOCUS_H, tint, 0);
w = card_put_box(out, w, cap, CARD_BOX_X, DCARD_FOCUS_Y, CARD_BOX_W, DCARD_FOCUS_H, ok, DCARD_FOCUS_BORDER);
const a : usize = card_name_from(focus, ff, ft);
const b : usize = card_name_to(focus, a, ft);
w = card_text_open(out, w, cap, font, fnl, card_font(b - a));
w = deps_put_span(out, w, cap, focus, a, b);
w = card_text_open(out, w, cap, font, fnl, card_font(dcard_drawn_len(focus, ff, ft)));
w = dcard_put_name(out, w, cap, focus, ff, ft);
w = card_text_close(out, w, cap, VIEW_TEXT, 0, DCARD_FOCUS_Y + DCARD_FOCUS_H / 2);
if (di > 0) {
w = dcard_put_uses(out, w, cap, font, fnl, DCARD_FOCUS_Y + DCARD_FOCUS_H, DCARD_DOWN_ROW_Y);
Expand Down Expand Up @@ -498,3 +584,113 @@ test negative_control_a_font_path_the_graph_cannot_quote_is_not_drawn {
assert dcard_graph(g, lit_len(g), "a$", 0, 1, bad, lit_len(bad), &imp, 256, &ib, &rev, 256, &rb, &out, 8192) == 0;
assert dcard_graph(g, lit_len(g), "a$", 0, 1, CARD_TEST_FONT, 0, &imp, 256, &ib, &rev, 256, &rb, &out, 8192) == 0;
}

pub const DCARD_N58 : str = "abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abc$";
pub const DCARD_LSEG : str = "port/trios/crates/trios-chat/rings/CR-CHAT-07/src/cover_traffic_inter_arrival_autocorrelation_guard$";
pub const DCARD_LSEG_DRAWN : str = "port/.../cover_traffic_inter_arrival_autocorrelation_guard$";
pub const DCARD_LMID : str = "port/trios/crates/trios-chat/rings/CR-CHAT-03/src/external_commit$";
pub const DCARD_LMID_DRAWN : str = "port/.../trios-chat/rings/CR-CHAT-03/src/external_commit$";
pub const DCARD_LDOTS : str = "port/trios/crates/trios-chat/rings/CR-CHAT-07/src/cover_traffic_inter_destination_timing_uniformity_guard$";
pub const DCARD_LDOTS_DRAWN : str = "...cover_traffic_inter_destination_timing_uniformity_guard$";
pub const DCARD_LONG : str = "specs/port/trios/crates/trios-chat/rings/CR-CHAT-07/src/cover_traffic_inter_arrival_autocorrelation_guard.t27\tspecs/port/trios/crates/trios-chat/common/helpers.t27\nspecs/port/trios/crates/trios-chat/rings/CR-CHAT-03/src/external_commit.t27\tspecs/port/trios/crates/trios-chat/common/helpers.t27\n$";

test dcard_a_name_that_fits_is_drawn_byte_for_byte {
var out : [256]u8 = undefined;
const s : str = DCARD_N58;
assert lit_len(s) == CARD_NAME_MAX;
assert dcard_drawn_len(s, 0, lit_len(s)) == CARD_NAME_MAX;
const w : usize = dcard_put_name(&out, 0, 256, s, 0, lit_len(s));
assert w == CARD_NAME_MAX;
assert card_count(&out, w, s) == 1;
assert card_count(&out, w, "...$") == 0;
const p : str = "specs/a/b.t27$";
const wp : usize = dcard_put_name(&out, 0, 256, p, 0, lit_len(p));
assert wp == 3;
assert card_count(&out, wp, "a/b$") == 1;
}

test dcard_a_long_name_keeps_its_head_and_the_longest_whole_tail_that_fits {
var out : [256]u8 = undefined;
const s : str = DCARD_LSEG;
assert lit_len(s) == 99;
const w : usize = dcard_put_name(&out, 0, 256, s, 0, lit_len(s));
assert w == lit_len(DCARD_LSEG_DRAWN);
assert w == CARD_NAME_MAX;
assert card_count(&out, w, DCARD_LSEG_DRAWN) == 1;
assert dcard_drawn_len(s, 0, lit_len(s)) == w;
const m : str = DCARD_LMID;
const wm : usize = dcard_put_name(&out, 0, 256, m, 0, lit_len(m));
assert wm == lit_len(DCARD_LMID_DRAWN);
assert wm == 56;
assert card_count(&out, wm, DCARD_LMID_DRAWN) == 1;
assert dcard_drawn_len(m, 0, lit_len(m)) == wm;
}

test dcard_a_long_name_with_no_whole_tail_that_fits_keeps_its_last_bytes {
var out : [256]u8 = undefined;
const s : str = DCARD_LDOTS;
assert lit_len(s) == 105;
assert dcard_seg_from(s, 0, lit_len(s)) == lit_len(s);
const w : usize = dcard_put_name(&out, 0, 256, s, 0, lit_len(s));
assert w == CARD_NAME_MAX;
assert card_count(&out, w, DCARD_LDOTS_DRAWN) == 1;
assert dcard_drawn_len(s, 0, lit_len(s)) == w;
const flat : str = "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijXYZ$";
const wf : usize = dcard_put_name(&out, 0, 256, flat, 0, lit_len(flat));
assert wf == CARD_NAME_MAX;
assert card_count(&out, wf, "...ijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijXYZ$") == 1;
}

test dcard_a_long_name_is_checked_only_where_it_is_drawn {
const hid : str = "port/tr:os/crates/trios-chat/rings/CR-CHAT-07/src/cover_traffic_inter_arrival_autocorrelation_guard$";
assert dcard_name_ok(hid, 0, lit_len(hid));
const hd : str = "po:t/trios/crates/trios-chat/rings/CR-CHAT-07/src/cover_traffic_inter_arrival_autocorrelation_guard$";
assert dcard_name_ok(hd, 0, lit_len(hd)) == false;
const tl : str = "port/trios/crates/trios-chat/rings/CR-CHAT-07/src/cover_traffic_inter:arrival_autocorrelation_guard$";
assert dcard_name_ok(tl, 0, lit_len(tl)) == false;
const dh : str = "port/tr:os/crates/trios-chat/rings/CR-CHAT-07/src/cover_traffic_inter_destination_timing_uniformity_guard$";
assert dcard_name_ok(dh, 0, lit_len(dh));
const dt : str = "port/trios/crates/trios-chat/rings/CR-CHAT-07/src/cover_traffic_inter_destination:timing_uniformity_guard$";
assert dcard_name_ok(dt, 0, lit_len(dt)) == false;
assert dcard_name_ok(DCARD_LSEG, 0, lit_len(DCARD_LSEG));
assert dcard_name_ok(DCARD_LDOTS, 0, lit_len(DCARD_LDOTS));
const n58 : str = "abcdefghij/abcd:fghij/abcdefghij/abcdefghij/abcdefghij/abc$";
assert lit_len(n58) == CARD_NAME_MAX;
assert dcard_name_ok(n58, 0, lit_len(n58)) == false;
}

test dcard_draws_a_card_with_long_names_abbreviated_at_their_drawn_size {
var imp : [512]u8 = undefined;
var rev : [512]u8 = undefined;
var ib : [35]usize = undefined;
var rb : [35]usize = undefined;
var out : [8192]u8 = undefined;
const g : str = DCARD_LONG;
const hp : str = "specs/port/trios/crates/trios-chat/common/helpers.t27$";
const w : usize = dcard_graph(g, lit_len(g), hp, 0, lit_len(hp), CARD_TEST_FONT, lit_len(CARD_TEST_FONT), &imp, 512, &ib, &rev, 512, &rb, &out, 8192);
assert w > 0;
assert w <= 8192;
assert card_count(&out, w, "fontsize=32:text='port/trios/crates/trios-chat/common/helpers'$") == 1;
assert card_count(&out, w, "fontsize=24:text='port/.../cover_traffic_inter_arrival_autocorrelation_guard'$") == 1;
assert card_count(&out, w, "fontsize=25:text='port/.../trios-chat/rings/CR-CHAT-03/src/external_commit'$") == 1;
assert card_count(&out, w, "/.../$") == 2;
assert card_count(&out, w, "text='IMPORTED BY 2'$") == 1;
const fp : str = "specs/port/trios/crates/trios-chat/rings/CR-CHAT-07/src/cover_traffic_inter_arrival_autocorrelation_guard.t27$";
const wf : usize = dcard_graph(g, lit_len(g), fp, 0, lit_len(fp), CARD_TEST_FONT, lit_len(CARD_TEST_FONT), &imp, 512, &ib, &rev, 512, &rb, &out, 8192);
assert wf > 0;
assert card_count(&out, wf, "fontsize=24:text='port/.../cover_traffic_inter_arrival_autocorrelation_guard'$") == 1;
assert card_count(&out, wf, "text='port/trios/crates/trios-chat/common/helpers'$") == 1;
assert card_count(&out, wf, "text='IMPORTS 1'$") == 1;
}

test negative_control_a_long_name_whose_drawn_bytes_cannot_be_quoted_is_not_drawn {
var imp : [512]u8 = undefined;
var rev : [512]u8 = undefined;
var ib : [35]usize = undefined;
var rb : [35]usize = undefined;
var out : [8192]u8 = undefined;
const g : str = "port/trios/crates/trios-chat/rings/CR-CHAT-07/src/cover_traffic_inter:arrival_autocorrelation_guard\tx\n$";
assert dcard_graph(g, lit_len(g), "x$", 0, 1, CARD_TEST_FONT, lit_len(CARD_TEST_FONT), &imp, 512, &ib, &rev, 512, &rb, &out, 8192) == 0;
const h : str = "port/tr:os/crates/trios-chat/rings/CR-CHAT-07/src/cover_traffic_inter_arrival_autocorrelation_guard\tx\n$";
assert dcard_graph(h, lit_len(h), "x$", 0, 1, CARD_TEST_FONT, lit_len(CARD_TEST_FONT), &imp, 512, &ib, &rev, 512, &rb, &out, 8192) > 0;
}
Loading