Skip to content

Commit bdfa21a

Browse files
diberryCopilot
andcommitted
fix(nap): account for separator newlines in decision archival budget
Fixes off-by-N error in nap command's decision archival where newline separators between entries weren't counted in the byte budget, causing archives to exceed the target size. Closes #123 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent cf5ed8b commit bdfa21a

3 files changed

Lines changed: 24 additions & 4 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
"@bradygaster/squad-cli": patch
3+
---
4+
5+
fix(nap): account for separator newlines in decision archival budget
6+
7+
The budget calculation in archiveDecisions() did not account for the newline
8+
separators added during content reassembly. This caused the final recentContent
9+
to exceed DECISION_THRESHOLD even after archival. Fix adds reassemblyOverhead
10+
and per-entry separator bytes to the budget calculation.
11+
12+
Closes #123

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file.
44

55
## [Unreleased]
66

7+
### Fixed
8+
- **Nap archival budget** (#123) — account for separator newlines in decision archival budget calculation
9+
710
### Added — Full Work Monitor for squad watch (#708)
811
- `--execute` flag spawns Copilot sessions to work on actionable issues autonomously
912
- Multi-platform support — auto-detects GitHub vs Azure DevOps from git remote URL

packages/squad-cli/src/cli/core/nap.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -386,17 +386,22 @@ function archiveDecisions(squadDir: string, dryRun: boolean): NapAction | null {
386386
dated.sort((a, b) => a.daysAgo! - b.daysAgo!);
387387

388388
// Keep the most recent dated entries that fit under the threshold
389-
// along with all undated entries and the header
389+
// along with all undated entries and the header.
390+
// Account for separator newlines added during reassembly:
391+
// recentContent = header + '\n' + entries.join('\n') + '\n'
392+
// Each entry contributes +1 byte for its join separator (overestimates
393+
// by 1 byte for the last entry, which is a safe margin).
390394
const headerEnd = entries.length > 0 ? entries[0]!.start : lines.length;
391395
const headerSize = Buffer.byteLength(lines.slice(0, headerEnd).join('\n'), 'utf8');
396+
const reassemblyOverhead = 2; // '\n' after header + trailing '\n'
392397
const undatedSize = undated.reduce(
393-
(sum, e) => sum + Buffer.byteLength(lines.slice(e.start, e.end).join('\n'), 'utf8'), 0,
398+
(sum, e) => sum + Buffer.byteLength(lines.slice(e.start, e.end).join('\n'), 'utf8') + 1, 0,
394399
);
395-
let budget = DECISION_THRESHOLD - headerSize - undatedSize;
400+
let budget = DECISION_THRESHOLD - headerSize - reassemblyOverhead - undatedSize;
396401

397402
const keptDated: typeof entries = [];
398403
for (const e of dated) {
399-
const entrySize = Buffer.byteLength(lines.slice(e.start, e.end).join('\n'), 'utf8');
404+
const entrySize = Buffer.byteLength(lines.slice(e.start, e.end).join('\n'), 'utf8') + 1;
400405
if (budget >= entrySize) {
401406
budget -= entrySize;
402407
keptDated.push(e);

0 commit comments

Comments
 (0)