Skip to content

spec(t27f): derive pass adds tested_by, data_flow and UNKNOWN call targets (Closes #10191) - #10198

Merged
gHashTag merged 1 commit into
masterfrom
claude/objective-pasteur-3ed8be
Oct 18, 2026
Merged

gHashTag merged 1 commit into
masterfrom
claude/objective-pasteur-3ed8be

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Closes #10191

Adds the T27F derive pass: derive_graph(g: SpecGraph, src: []const u8) -> SpecGraph in specs/t27f/spec_graph_derive.t27. It appends the facts the exporter (#10173) must not claim and changes nothing the exporter holds. Refs gHashTag/trinity#1648, RFC gHashTag/trinity#1649.

Result

Exporter plus derive equal the hand-read tutorial_08_graph() on the tutorial 08 snapshot as sets: 15 of 15 nodes (kind, label, name, span), 16 of 16 edges (kind, endpoints, label, line), in both directions. No special case was needed, so there is no finding about an unreproducible fixture edge.

Rules (stated in the spec header, each follows EDGE_FROM_KINDS / EDGE_TO_KINDS)

  • R1 TESTED_BY, DERIVED, no line. An EXACT CALLS edge from a test, invariant or bench to a fn, read backwards. This is the rule tested_by_matches_calls already states for the fixture.
  • R2 DATA_FLOW, DERIVED, line of the first use. A const or use that an EXACT USES edge ties to a fn, and whose name appears inside one of that fn's return statements (from return to the next ;, outside strings, character literals and comments). This is the fixture's own comment: the named values are operands of the return expression.
  • R3 UNKNOWN opaque node. An undeclared qualified call target of three or more path segments (std.testing.expectEqual( names std.testing), spanning the lines that call through it. An UNKNOWN node has no edges, because validate_edge refuses an UNKNOWN endpoint.

Why a separate module, not an extension of the exporter

The exporter promises it never emits DERIVED or SUGGESTED, and its test the_scanner_never_emits_derived_or_suggested checks that. Keeping the inference in its own module keeps that promise true on its own, and lets a host choose exact-only or exact plus derived. The byte helpers are reused through use, not copied.

Choices that are the rules' own, not read off the fixture

  • R3 needs three or more segments. The fixture has one instance (std.testing.expectEqual), and a two-segment x.f( cannot be told from a method call on a local value.
  • R2 reads names only, not call results: no fixture edge is a fn result flowing into a caller.

Limits (also in the spec header)

Names are matched as text; flow through locals and call results is not derived; a graph that does not validate, or a source with a different line count, is returned unchanged; past 192 nodes or 254 edges the count keeps growing and validate_graph answers the too-many verdict, so the result is refused, never truncated. Not wired to a host: the MCP tool does not call it.

Tests (10 tests, 2 invariants)

Every rule has a synthetic test with negative controls (a fn calling a fn, a let use, a use after the return's ;, a test body, a name in a comment or string, a two-segment path, a use-declared head). Also: the never-change-an-EXACT-fact check with tampered copies, idempotence, the unchanged-input cases, and overflow cases for both the node and the edge capacity with a fits-exactly control. The heavy tutorial 08 comparison is a test, not an invariant, because invariants are evaluated at compile time.

Verification (Railway lab only)

  • Specs shipped by tar and base64; sha256 equal on both ends.
  • t27c test-report specs/t27f/spec_graph_derive.t27: 10 of 10 pass, 2 invariants proved, 0 vacuous passes.
  • t27b test specs/t27f/spec_graph_derive.t27 --check under qemu-aarch64, both the 2026-10-17 and the 2026-10-10 aarch64 binaries: 10 passed, 0 failed, invariants 2 held, 139 runtime asserts, exit 0. The exporter under the same binaries: 20 of 20, exit 0.

Also updates .claude/skills/t27f/SKILL.md (new table row and the prose that said no pass derives) and the t27f/ row of specs/OWNERS.md.

🤖 Generated with Claude Code

…rgets (Closes #10191)

derive_graph(g, src) appends what the exporter must not claim: DERIVED
tested_by (calls read backwards), DERIVED data_flow (a const or use named in a
fn's return statement) and UNKNOWN opaque nodes for undeclared qualified call
targets. It never changes an EXACT fact. Exporter plus derive equal the
tutorial 08 fixture: 15 of 15 nodes, 16 of 16 edges, no special case.

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

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-18 04:08:15 UTC

Summary

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

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=0f8c66b9ed0e != 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 94d2793 into master Oct 18, 2026
28 of 30 checks passed
gHashTag added a commit that referenced this pull request Oct 18, 2026
…ind as pass (Closes #10212) (#10214)

#10198, #10202 and #10194 added these three specs without a row in
docs/reports/t27b_expectations.json, so t27b-native-ratchet reads
"UNLISTED 3" on master and on every open PR (run 39096977680 on
#10185): "the reference passes it and the ledger does not name it
(t27b pass)".

Adds the three rows in path order with the verdict the run measured.
No other row moves.

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.

T27F: derive pass for the spec graph -- DERIVED data_flow and tested_by edges, UNKNOWN external call targets (Refs trinity#1648, trinity#1649)

1 participant