Skip to content

guard: a type has a ceiling, and the console belongs to the surface - #77

Merged
donislawdev merged 3 commits into
mainfrom
shape/type-ceiling
Sep 7, 2026
Merged

guard: a type has a ceiling, and the console belongs to the surface#77
donislawdev merged 3 commits into
mainfrom
shape/type-ceiling

Conversation

@donislawdev

Copy link
Copy Markdown
Owner

Two axes the existing ceilings cannot see, each with its own guard, its own
pinning half and its own mutations.

A type has a ceiling

The ceilings here measure files, functions and branching. A type is none of
them, and that is a hole this tree can be shown to have rather than a matter of
principle: codeshape_test.go records three lowerings of longestFile, 503 to
457 to 433, and every one was earned by moving code out of engine.go into a
new file beside it. The watched number fell each time. Nothing asked whether the
type a reader has to hold in their head fell with it.

A type is the unit of state. Twenty two fields is twenty two things any of its
twenty eight methods may have changed, and splitting the file those methods live
in does not divide that by anything.

Measured: 271 types, worst is internal/gui/window.runner at 28 methods and 22
fields, with 3 types in the method band and 4 in the field band. All four
numbers are the measurement rather than a number above it, which a third guard
pins - the same rule every other ceiling here lives by.

The bands are a count of things rather than a share of the ceiling, following
the local convention, and the predicate is the existing crowding() rather than
a second copy of it.

Build constraints were measured rather than assumed, because a pinned count that
moves with the environment would go red on one platform only: three files
declare types behind a tag and every one is far below both ceilings and both
bands.

Today's numbers are healthy, so this ceiling buys nothing today. It is bought
for the reason deepestNesting was bought - it costs nothing while nothing
grows, and by the time it would be worth adding, the number it would have to be
set to is already the problem.

The console belongs to the surface

The layer map says which package may import which. It cannot see a line printed
from the engine, because fmt is on everybody's list and always will be.

That matters here rather than as a matter of taste. This tool is run by somebody
else's CI and --json promises a document a script parses. One stray line on the
success path does not fail a run, does not move an exit code, and is invisible to
the guard that a failed run prints nothing on stdout, because that one watches
the failure path. It turns a machine readable report into text no parser accepts.

Layer 4 is the surface and layer 5 is a main package. Everything at 3 or below is
a library and does not reach the console by name - not fmt.Print*, not
os.Stdout or os.Stderr, and not the builtins, which are hardest to notice
because nothing has to be imported for them to work. Passing an io.Writer stays
allowed and is the point.

Read from the syntax tree rather than the text, which is a measurement rather
than caution: internal/oracle keeps Python scripts inside Go raw strings and
calls print() thirty times in them, and a text scan reports every one.

Evidence

  • Ten mutations across the two files, every one caught.
  • Full test set green with the build tags, 406 s.
  • preflight --quick green, all twelve checks.
  • Guards are green today and their pinning halves are what is live: no type is
    over its ceiling and nothing below the surface prints, so both ceilings are
    tripwires with nobody on them, which is stated in their own comments.

No production code changes. One earlier commit removes two symbols from comments
that the punctuation guard correctly refused.

🤖 Generated with Claude Code

donislawdev and others added 3 commits September 7, 2026 08:09
…nk it

The three ceilings here measure files, functions and branching, and a type is
none of them. codeshape_test.go records three lowerings of longestFile, 503 to
457 to 433, and every one was earned the same way: code moved out of engine.go
into a new file beside it. The watched number fell each time and nothing asked
whether the type a reader has to hold in their head fell with it.

A type is the unit of state. Twenty two fields is twenty two things any of its
twenty eight methods may have changed, and splitting the file those methods
live in does not divide that by anything.

Measured on this tree: 271 types, worst is internal/gui/window.runner at 28
methods and 22 fields. Three types reach the method band and four reach the
field band. All four numbers are the measurement rather than a number above it,
which a third guard pins.

The bands are a count of things rather than a share of the ceiling, the local
convention, and the predicate is the existing crowding() rather than a second
copy of it.

Build constraints were measured rather than assumed, because a pinned count
that moves with the environment would go red on one platform only: three files
declare types behind a tag and every one of them is far below both ceilings and
both bands.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The layer map says which package may import which. It cannot see a line printed
from the engine, because fmt is on everybody's list and always will be.

That matters here rather than as a matter of taste. This tool is run by somebody
else's CI and --json promises a document a script parses. One stray line on the
SUCCESS path does not fail a run, does not move an exit code, and is invisible
to the guard that a failed run prints nothing on stdout, because that one
watches the failure path. It turns a machine readable report into text no parser
accepts, and the reader finds out in their pipeline.

Layer 4 is the surface and layer 5 is a main package. Everything at 3 or below
is a library and does not reach the console by name - not fmt.Print, not
os.Stdout or os.Stderr, and not the builtins, which are the hardest to notice
because nothing has to be imported for them to work. Passing an io.Writer stays
allowed and is the point: cmd/tfg hands os.Stdout to cli.Run.

Read from the syntax tree rather than from the text, which is a measurement.
internal/oracle keeps Python scripts inside Go raw strings and calls print()
thirty times in them, and a text scan reports every one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The punctuation guard reads every file in the repository and rule 13 covers
comments in code. The project's own notes use these marks and are outside the
repository, which is why the habit travelled.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@donislawdev
donislawdev merged commit 6599bf5 into main Sep 7, 2026
18 checks passed
@donislawdev
donislawdev deleted the shape/type-ceiling branch September 7, 2026 07:17
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.

1 participant