Bound the session-start digest and cut AGENTS.md duplication #29

Merged
john merged 9 commits from fm/fm-context-footprint into main 2026-09-06 09:18:45 +00:00
Owner

Cuts what firstmate spends on its own startup, without losing a safety boundary.

Measured, re-measured against the same live dataset with the same method

before after
session-start digest 294,131 bytes 91,988 bytes -68.7% (~72.6k -> ~22.7k tokens)
AGENTS.md 71,635 bytes 54,357 bytes -24.1% (590 -> 494 lines)

The digest was the larger problem: it reprinted unbounded material on every session
start, so the cost scaled with fleet history rather than with what the session needed.

Why the figure is stated twice

An earlier measurement of -69.3% was taken before seven review rounds changed the
very code being measured, and some of those fixes add bytes back. That number was
retracted rather than reported. The figures above are the re-measurement against the
current head.

Integrity

The point of a digest is that it is trustworthy, so the cut is verified rather than
assumed: no section dropped, task inventory identical, all 122 backlog rows retained.
Bounding is applied to unbounded repetition, not to content the session needs.

Where a bound could hide something, the digest now says so - a capped value discloses that
it was capped, and the curated-memory notice stays accurate on every build rather than
only the common one.

Validation

Seven review rounds, seven fixes, zero ask-user findings. Pipeline passed.

Cuts what firstmate spends on its own startup, without losing a safety boundary. ## Measured, re-measured against the same live dataset with the same method | | before | after | | |---|---|---|---| | session-start digest | 294,131 bytes | 91,988 bytes | **-68.7%** (~72.6k -> ~22.7k tokens) | | `AGENTS.md` | 71,635 bytes | 54,357 bytes | **-24.1%** (590 -> 494 lines) | The digest was the larger problem: it reprinted unbounded material on every session start, so the cost scaled with fleet history rather than with what the session needed. ## Why the figure is stated twice An earlier measurement of -69.3% was taken **before** seven review rounds changed the very code being measured, and some of those fixes add bytes back. That number was retracted rather than reported. The figures above are the re-measurement against the current head. ## Integrity The point of a digest is that it is trustworthy, so the cut is verified rather than assumed: no section dropped, task inventory identical, **all 122 backlog rows retained**. Bounding is applied to unbounded repetition, not to content the session needs. Where a bound could hide something, the digest now says so - a capped value discloses that it was capped, and the curated-memory notice stays accurate on every build rather than only the common one. ## Validation Seven review rounds, seven fixes, **zero ask-user findings**. Pipeline passed.
Firstmate's own startup material occupied 72.6k of context on a Pi primary,
which does not leave a usable working window on a 100k-context local model.
Measured on the main home's data, the 293,813-byte digest broke down as:

  CONTEXT                            214,978  (73.2%)
    data/learnings.md                190,880  (65.0%)
    data/captain.md                   21,072
    data/projects.md                   2,943
  FLEET STATE                         69,091  (23.5%)
    backlog: 75 held rows             41,486  (14.1%)
    every state/*.meta + status tails 14,276
    backlog: ready/in-flight/blocked   9,898
    quota-ceiling landing marker       3,218
  SUPERVISION block                    3,496
  header/lock/bootstrap/wake queue     2,261
  READ-ONCE CONTRACT                   1,244
  NETWORK CHECKS + NEXT STEP             534

Two changes, both bounding output rather than dropping a source.

config/startup-memory-budget is now SPENT, not only reported. It already
declared an allowance for data/captain.md, data/captain-shared.md, and
data/learnings.md, and bin/fm-startup-memory-budget.sh report already said the
main home was 70,651 estimated tokens against a configured 7,500 - but the
digest printed all three whole regardless. It now prints them in order until
the allowance is gone and marks the first file it has to cut with [BUDGET CUT],
exact byte and estimated-token counts, and an explicit carve-out from the
read-once contract, so a cut file is one the agent is told to read rather than
one it wrongly believes it already has. The cut lands on a line boundary. An
unreadable budget bounds nothing and says so, because completeness is the safe
direction when the bound itself cannot be trusted.

This replaces, rather than adds to, the previous mechanism: the digest was
relying on the delivery harness truncating an oversized payload from the tail,
which cuts mid-sentence, is silent, and takes an unpredictable amount.

The backlog listing's hold_reason prose is capped at 160 characters
(FM_SESSION_START_HOLD_REASON_CAP). No row is dropped and no actionable field
is bounded away, and that is provable rather than assumed: tasks-axi renders the
same row with --fields blocked_by,hold_kind as a literal prefix of the row it
renders with hold_reason appended, so the listing keeps the shorter row verbatim
and caps only the remainder. If the two listings ever disagree in row count or
the prefix relation does not hold, the full listing prints uncapped.

AGENTS.md drops 17,278 bytes of restatement, no rules. Section 2's file-by-file
tree duplicated docs/configuration.md, which owns that layout and had
deliberately declined to carry an exhaustive state tree; the per-file "never
touch" notes are replaced by one broader rule covering families not yet listed.
Section 3's seven-item walkthrough described the digest that prints itself in
that order and states each of those facts inline. Section 4 spelled out the
selection procedure that quota-array-dispatch owns and that names AGENTS.md's
own share. Section 8's landing subsection restated bin/fm-land.sh's header.
Every unique fact was checked for a live owner first; procevent's
supervision requirement moved into section 8 rather than being dropped.

Result on the same data: digest 293,813 -> 90,209 bytes (-69.3%), AGENTS.md
71,635 -> 54,357 bytes (-24.1%). About 72.6k + 17.7k -> 22.3k + 13.4k tokens.

Verified: bin/fm-lint.sh clean, bin/fm-doc-audience-check.sh ok, the
session-bootstrap family green (9 suites, 0 failures) including four new
regression tests, and the rebuilt digest still carries every section, all 9
task records, and all 114 backlog rows the old one did.
no-mistakes(document): Fix stale quota-procedure and open-decisions-cursor doc pointers
All checks were successful
CI / Test coverage guard (pull_request) Successful in 14s
CI / Behavior portable parallel 2 (pull_request) Successful in 3m4s
CI / Behavior portable parallel 1 (pull_request) Successful in 3m13s
CI / Lint shell scripts (pull_request) Successful in 4m34s
CI / Behavior portable serial 1 (pull_request) Successful in 13m4s
CI / Behavior portable serial 4 (pull_request) Successful in 10m39s
CI / Repo invariants (pull_request) Successful in 5s
CI / Behavior portable serial 3 (pull_request) Successful in 14m6s
CI / Behavior portable serial 2 (pull_request) Successful in 16m11s
CI / Behavior tests (Herdr) (pull_request) Successful in 7m38s
95689325c7
john merged commit 05e5051a74 into main 2026-09-06 09:18:45 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
john/firstmate!29
No description provided.