Skip to content

spec(t27f): spec_graph -- the core graph IR a .t27 spec becomes (Closes #10020) - #10029

Merged
gHashTag merged 3 commits into
masterfrom
claude/affectionate-mahavira-86b04d
Oct 17, 2026
Merged

gHashTag merged 3 commits into
masterfrom
claude/affectionate-mahavira-86b04d

Conversation

@gHashTag

@gHashTag gHashTag commented Oct 17, 2026 •

Copy link
Copy Markdown
Owner

Closes #10020

T27F is the visual spec of .t27 (epic gHashTag/trinity#1648, RFC gHashTag/trinity#1649; AST/IR audit gHashTag/trinity#1650). Its core is the graph a spec becomes before any view draws it. Until now that IR existed nowhere. This PR writes it as a spec, so that a future exporter has a contract to meet and a validator to pass.

What specs/t27f/spec_graph.t27 decides

  • Vocabulary: GRAPH_IR_VERSION = 1. Node kinds: module, const, fn, test, invariant, bench, use, opaque. Edge kinds: calls, uses, tested_by, constrains, data_flow. Labels: exact, derived, suggested, unknown. All are u8 codes with name tables. Allowed endpoint kinds per edge kind are node-kind bit masks, and an invariant rebuilds them from the named kinds.
  • Records: SpecGraph holds parallel arrays, as UiPlan does. Every node has kind, label, name and span (line_start, line_end). Every edge has kind, endpoints, label and source line. SpecGraphNode is the node-inspector record.
  • Validation: validate_graph returns GRAPH_OK or the first rule broken, out of 18. first_bad_node and first_bad_edge name the record that broke it. Rules of note:
    • a SUGGESTED node without a span is refused;
    • an UNKNOWN node takes no edges;
    • an edge is never stronger than either of its endpoints;
    • an EXACT or SUGGESTED edge needs a line inside an endpoint's span.
  • Source mapping both ways: node_at(n) gives the span. node_at_line(l) gives the innermost node of a line, and a comment line maps to the module.
  • Derivation: tested_by_matches_calls checks that TESTED_BY is exactly CALLS-from-a-check read backwards.
  • Binding to ui_plan: node_widget(kind, label) picks a catalog widget of specs/t27f/ui_plan.t27. SUGGESTED and UNKNOWN nodes get only a text block. tutorial_08_plan() builds a UI plan from the fixture, and it passes validate_plan.
  • Fixture: specs/tutorial/08_modules_and_arrays.t27 at 2f39502 (93 lines, sha256 c291e925...8039a, unchanged on current master), read by hand into 15 nodes and 16 edges. Every top-level declaration has a node; std.testing is an UNKNOWN opaque node.

Not claimed: t27c has no graph export, there is no renderer, and there is no graph diff. The SKILL.md "What exists" table now splits the core row into schema (this spec) and exporter (still missing).

Lab evidence (Railway, fresh clone at master cc80a305d)

Check Result
t27c test-report specs/t27f/spec_graph.t27 13/13 pass, 0 FAIL, 0 BLOCKED, 0 vacuous (4 to 23 runtime asserts per test), 5 invariants proved at comptime
t27b test specs/t27f/spec_graph.t27 --check (qemu-aarch64) 13 PASS, 0 FAIL
sha256, committed vs lab 392fa5050ada47f8d801338bf89e99c024d1fcc47d619ee748733a180d9e788c on both (1 of 1 match)
Verdict coverage each of the 18 non-OK verdict codes is produced by at least one test case

Negative controls (file mutated on the lab, then restored and re-hashed):

  • EDGE_TO_KINDS[calls] changed from 4 to 6 (calls could end at a const): t27c refuses to compile, because the comptime invariant edge_masks_are_spelled_right fails; t27b fails edge_endpoints_must_exist_and_fit.
  • The power_of_two span changed from 66-68 to 66-73: source_mapping_goes_both_ways fails on both tools.

One finding during the work: t27c inlines an imported module, so a top-level name defined in both files fails to compile. Here that was validate_header and ERR_IR_VERSION; this spec uses validate_graph_header and ERR_GRAPH_VERSION.

Files: specs/t27f/spec_graph.t27 (new, .t27 only, ASCII), .claude/skills/t27f/SKILL.md, specs/OWNERS.md (t27f row). Nothing ran on the Mac.

🤖 Generated with Claude Code

#10020)

T27F is the visual spec of .t27 (trinity#1648, RFC trinity#1649). Its core is
the graph a spec turns into before any view draws it; until now that IR did not
exist anywhere. specs/t27f/spec_graph.t27 writes it as a spec:

- GRAPH_IR_VERSION 1; node kinds (module, const, fn, test, invariant, bench,
  use, opaque), edge kinds (calls, uses, tested_by, constrains, data_flow) and
  labels (exact, derived, suggested, unknown) as u8 codes with name tables.
- SpecGraph / GraphNode records: every node has a source span, every edge a
  source line.
- validate_graph returns the first broken rule of 18 (version, path, capacity,
  module root, node kind/label/name, span order/outside/missing, edge kind,
  dangling, endpoint kinds, unknown node, label strength, line, duplicate);
  first_bad_node / first_bad_edge name the record.
- Source mapping both ways: node_at(n) gives the span, node_at_line(l) the
  innermost node of a line.
- TESTED_BY is DERIVED from CALLS (tested_by_matches_calls).
- node_widget binds kind x label to a ui_plan catalog widget; SUGGESTED and
  UNKNOWN nodes get only a text block.
- Fixture: specs/tutorial/08_modules_and_arrays.t27 read by hand (15 nodes,
  16 edges), and a UI plan built from it that passes validate_plan.

Not claimed: no t27c exporter, no renderer, no graph diff.

SKILL.md "What exists" splits the core row into schema (this spec) and
exporter (still missing); specs/OWNERS.md t27f row names the new module.

Lab (Railway, master cc80a30): t27c test-report 13/13 pass, 0 FAIL,
0 BLOCKED, 0 vacuous, 5 invariants proved; t27b --check 13 PASS, 0 FAIL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-17 17:04:44 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 49
PRs with All Checks Green 1
READY 0
FAILING 49
PENDING 0
NO CHECKS YET 0

These columns do not partition: 0 + 49 + 0 + 0 = 49, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=e769ef021713 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-17 17:08:57 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 49
PRs with All Checks Green 1
READY 0
FAILING 49
PENDING 0
NO CHECKS YET 0

These columns do not partition: 0 + 49 + 0 + 0 = 49, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=e769ef021713 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

… the corpus (Closes #10020)

The types ratchet flagged GraphNode as a new conflicted type name:
specs/test_framework/graph_drift_detection.t27 already defines it.
Lab re-run: t27c test-report 13/13, 0 vacuous; t27b --check 13 PASS.
sha256 392fa5050ada47f8d801338bf89e99c024d1fcc47d619ee748733a180d9e788c.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-17 17:13:23 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 48
PRs with All Checks Green 2
READY 0
FAILING 48
PENDING 0
NO CHECKS YET 0

These columns do not partition: 0 + 48 + 0 + 0 = 48, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=e769ef021713 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@gHashTag
gHashTag merged commit 9a7d54a into master Oct 17, 2026
24 of 30 checks passed
gHashTag added a commit that referenced this pull request Oct 17, 2026
… (#10059)

#10049 merged into the already-merged #10029 branch instead of master,
so its files never reached master. This is the same squash commit
(3456f62), cherry-picked cleanly onto current master.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

spec(t27f): the spec graph IR -- what a .t27 file becomes before T27F draws it

1 participant