fix: byte-bound secondmate home summaries - #35
Merged
Merged
Conversation
added 4 commits
October 3, 2026 02:12
…n marker A registry with thousands of projects pushed the whole home summary past the 262144-byte reader limit, so the parent marked the secondmate unavailable. The producer now cuts oversized base surfaces (projects first) to fit and records one summary_bytes marker per cut surface with kept and omitted counts. Bearings discloses the marker in omitted[]. A summary that already fits is emitted unchanged.
…ons, and correct CI count
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
build it with a simple omission marker
Context: the question was how omitted parts of a second mate's home summary should be shown. Filed 2026-09-06 from the posture display review: the 262144-byte reader limit is enforced only on lifecycle_inventory, so a registry with thousands of projects can still make the whole second mate home summary unreadable and mark the second mate unavailable. The item: byte-bound the complete secondmate home-summary serialization with an omission representation for projects[] and other base surfaces.
What Changed
Risk Assessment
✅ Low: The change bounds oversized summaries, preserves producer classifications, and separates byte omissions from row-bound disclosures without introducing a substantiated defect.
Testing
Targeted regressions and all live CLI scenarios passed. Captured serialized summaries, reader output, and Bearings transcripts. The changed surface has no graphical UI.
Evidence: Observed summary sizes, classifications, and omissions
Source: Observed summary sizes, classifications, and omissions
Evidence: Live CLI transcript
Source: Live CLI transcript
Evidence: Lifecycle compatibility transcript
Source: Lifecycle compatibility transcript
Evidence: Bearings disclosure for an oversized registry
Source: Bearings disclosure for an oversized registry
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 3 issues found → auto-fixed (2) ✅
bin/fm-fleet-snapshot.sh:1352- The complete summary can still exceed 262144 bytes. For example, 3000 archived projects with 100-byte names and one Done record each produce over 300 KB in omitted[].archived_projects alone. This pass empties projects but leaves that disclosure untouched, so summary_file_read still rejects the ledger. Other surviving payloads include parked_projects (bin/fm-fleet-snapshot.sh:1309), reason and invalidity.ids (bin/fm-fleet-snapshot.sh:1262). Budget these nested disclosures and diagnostics at the producer boundary, preserve their classification, and ensure the final serialization fits.bin/fm-fleet-snapshot.sh:1349- Byte cuts can silently turn an unresolved captain decision into an idle classification. With FM_SNAPSHOT_SECONDMATE_DECISIONS=1001, a persistent child secondmate's status can contain 1000 distinct blocked keys with 160-character summaries followed by one needs-decision. The producer reports captain_decision, but this prefix cut drops the final decision. The parent then calls fm_secondmate_summary_at (bin/fm-fleet-snapshot.sh:2123), which derives no_active_work from the retained blocked rows (bin/fm-project-lifecycle.jq:226). The same completeness invariant applies to active_children and holds cuts at bin/fm-fleet-snapshot.sh:1352. Make the shared read-time classifier respect byte omissions rather than infer absence from truncated arrays.tests/fm-bearings-snapshot.test.sh:4961- The added invocation raises the successful suite output from 82 to 83 'ok -' lines, including the new pass at tests/fm-bearings-snapshot.test.sh:4743. The stock macOS CI job still requires exactly 82 at .github/workflows/ci.yml:457, so it fails even when every test passes. Update that expected count.🔧 Fix applied.
1 warning still open:
bin/fm-bearings-snapshot.sh:940- Round 1 fixed classification but left omission accounting behind. With 1001 decisions and FM_SNAPSHOT_SECONDMATE_DECISIONS=1001, a byte cut retaining k rows causes normalization to create a legacy decisions_open omission count of 1001-k. Bearings then reports those same rows under both snapshot-bound and byte-limit disclosures, recommending a row-limit increase that cannot recover them. Exclude byte-cut omissions from legacy row-bound counters at the shared normalization boundary. Siblings: bin/fm-project-lifecycle.jq:172 (queued), :173 (active_children), :174 (holds), :175 (decisions_open), rendered at bin/fm-bearings-snapshot.sh:925, :928, :931, and :934 respectively.🔧 Fix applied.
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
TMPDIR="$PWD/.test-summary-live/tmp" bash tests/.summary-byte-targeted.test.sh, selecting the lifecycle-bound and summary-byte-bound regression tests.python3 .test-summary-live/drive.py, driving real summary publication, parent reads, and Bearings JSON and TOON output.python3 .test-summary-live/adversarial.py, reproducing baseline rejection and exercising zero-row cuts, landed omission accounting, and UTF-8 inputs.python3 .test-summary-live/lifecycle-fit.py, comparing lifecycle-bounded summary bytes against the base producer.Removed disposable homes, temporary test drivers, and the baseline producer copy. Verified the working tree was clean.bin/fm-bearings-contract-lib.sh:290- The generated Bearings contract lists omission recovery hints but omits the new byte-limit hint. Update its authoritative source in a follow-up. This phase permits only documentation files and doc comments.✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.