Skip to content

spec: write the behaviours the deleted comments described as requirements - #477

Merged
typeless merged 1 commit into
mainfrom
wip/ears-from-comments
Sep 19, 2026
Merged

typeless merged 1 commit into
mainfrom
wip/ears-from-comments

Conversation

@typeless

Copy link
Copy Markdown
Owner

Follow-up to #476, as agreed: the behaviours the deleted comments described, written as EARS requirements.

What is added. 42 requirements across 11 areas: 7 new area files (change-detection, configure, group-references, record-write, scoped-builds, tupfile-evaluation, variant-builds) and 4 extended (command-record, dep-scan, record-read, reset), plus 4 further discharge: lines on existing requirements. Every discharge names an e2e scenario that exists; spec-check passes at 195 requirements, 0 gaps.

What was cut. Of the 82 candidates recovered from the comments, 19 restated an existing requirement and were dropped (4 became extra discharges), and 7 claims whose only test could not fail on them were not written: the edge kind of a group in the inputs section, a multi-rule depfile, the words a derived scan drops, an env-driven branch flip whose command text also changes, which branch a phi-node output is recorded against, the plain-reference arm of demand-driven group parsing, and a variant-build routing sentence that belongs to command-record.

Review. Drafted by one planner and eleven per-area writers on Opus, then reviewed by a separate Opus agent on six grounds (vacuity, discharge fidelity, conformance honesty, truth against the binary, README form, duplication). It returned 17 findings; all are fixed in the commit, including two reference lines that named an upstream symbol that does not exist (variant_check) and one that placed tf.variant in the wrong function. Five nits about weak but true witnesses (a [shell]-tagged discharge Windows CI skips, two scenarios that self-disable under root, two that assert only "not a no-op") are left as they are and are the natural next tests to strengthen.

Conformance. Two deviations from tup are recorded for the first time: an imported env var that later vanishes is treated as unchanged against the recorded value (tup's env_cb takes NULL as a mismatch), and a file is included once per guard context (tup's parser_include_file re-parses every include).

🤖 Generated with Claude Code

https://claude.ai/code/session_01StgwMENEyfBnEoe4pvAdtQ

…ents

PR #476 removed the comments from the files #475 touched and kept
what they said in its commit body. Some of those sentences were not
implementation notes but behaviours a user or a later build observes,
each already witnessed by a named e2e scenario that no requirement
cited. Those become requirements here: 42 across eleven areas, seven
of them new (change-detection, configure, group-references,
record-write, scoped-builds, tupfile-evaluation, variant-builds) and
four extended (command-record, dep-scan, record-read, reset).

Every discharge names a test that exists and asserts the sentence, and
every sentence forbids an implementation; claims whose only test could
not fail on them were cut rather than cited: the edge kind of a group
written in the inputs section, a multi-rule depfile (the fixture splits
on `&&` into two single-rule scans), the words a derived scan drops, an
env-driven branch flip whose command text also changes, the branch a
phi-node output is recorded against, the plain-reference arm of
demand-driven group parsing, and a variant-build routing sentence that
belonged to command-record. A different-model review of the drafts
found those plus two upstream citations naming a symbol that does not
exist (`variant_check`) and one misplaced assignment (`tf.variant` is
set in `parse`, not `parse_tupfile`), all corrected. Nineteen
candidates restated a requirement that already exists and were
dropped; four of them instead join existing requirements as further
discharges. The pass-ordering and arithmetic-width notes stay in
#476's body as mechanism.

Conformance was read, not guessed: a `tup-conformant` reference names
an upstream symbol that was opened, and two behaviours found to
diverge are recorded as deliberate deviations for the first time --
putup treats an imported env var that later vanishes as unchanged
against the recorded value where tup's env_cb takes NULL as a
mismatch, and putup includes a file once per guard context where
parser_include_file re-parses on every include.

Ref: #476

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

PR metrics

Performance (gcc example, Linux)

Workload Instructions CPU time Page faults D1 miss LL miss Wall Peak RSS
parse 1685 M 0.61 s 15.1 k 0.7% 0.1% 0.604 s 34.7 MB
dry-run 2340 M 0.68 s 16.6 k 0.8% 0% 0.703 s 40.3 MB (+0.1MB)

Deterministic signals: instructions (cachegrind-simulated instruction reads — exact across runs, no PMU needed), page faults, peak RSS, and the cachegrind D1/LL miss rates. CPU time is user+sys from time(1).

Internal statistics (gcc example, up-to-date dry run)

Metric Value
Tupfiles parsed 24
Commands 3545
Commands scheduled 0
Files checked 5834
Files changed 0
Files in index 6173
Graph edges 381415
Index size (bytes) 7811994
Implicit deps 344126
Hash computations 197
Hashes skipped (stat cache) 5636
Stat calls 5885
Parse time (ms) 530.1 (-2.7%)
Total time (ms) 688.7 (-2.8%)
Runner CPU AMD EPYC 7763 64-Core Processor

Counters from putup -n --stat on the fully-built gcc example (up-to-date dry run): deterministic work measures — a jump in commands scheduled, hash computations, or stat calls is a real behavior change, not noise. Timings are the minimum over repeated runs, compared only against a baseline from the same CPU model; the counters are the regression signal.

Binary size (Linux)

Binary .text .data .bss File
putup 599.3 KB 2.3 KB 98.8 KB 711.4 KB

Code churn (whole codebase, last 30d)

Files Lines written Still present Churned Churn rate
28 2320 1997 323 13.9%

Of the lines written across the codebase in the last 30 days, how many are already gone — work that was written and then discarded or rewritten inside the same window. This is the state of the tree including this PR, not a measure of the PR itself. Only code we write is counted: tests, examples, vendored and generated files, CI plumbing and prose are excluded. 1582 lines were deleted in the window in total, most of them older than it.

Where the churn is
File Lines written then discarded
src/parser/eval.cpp 77
src/graph/builder.cpp 69
src/graph/dag.cpp 53
src/index/entry.cpp 44
include/pup/core/token_list.hpp 23
include/pup/parser/eval.hpp 16
src/cli/cmd_build.cpp 8
src/index/reader.cpp 8
include/pup/core/instruction.hpp 7
src/core/instruction.cpp 7

Test coverage (lines)

Overall Median file Min file Max file
88.8% 96.9% 14.7% include/pup/parser/token.hpp 100.0% include/pup/core/arena.hpp

105 files · 17801/20056 lines covered

Deltas vs main@b445a2906.

Updated for 4a2d5be

@typeless
typeless merged commit dca0140 into main Sep 19, 2026
13 checks passed
@typeless
typeless deleted the wip/ears-from-comments branch September 19, 2026 15:09
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