Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .squad/agents/scribe/charter.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
After substantial work:
1. Log session to `.squad/log/{timestamp}-{topic}.md` (who, what, outcomes)
2. Merge `.squad/decisions/inbox/` → `.squad/decisions.md`, delete inbox files
- **IMPORTANT — Date Format Mandate:** All merged entries MUST use the format `### YYYY-MM-DD: Topic` for decision headings.
- If an inbox file is missing a date, add today's date (`YYYY-MM-DD`).
- If an entry cannot be dated (missing context, ambiguous age), log a warning, skip it, and report.
3. Deduplicate decisions.md by `### ` blocks (exact duplicates, overlapping topics)
4. Propagate: append `📌 Team update` to affected agents' history.md
5. Commit: cd to team root, `git add .squad/`, temp file, `git commit -F` (Windows: no `-C`, no `-m` newlines)
Expand Down
3 changes: 3 additions & 0 deletions .squad/templates/scribe-charter.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ After every substantial work session:
2. **Merge the decision inbox:**
- Read all files in `.squad/decisions/inbox/`
- APPEND each decision's contents to `.squad/decisions.md`
- **IMPORTANT — Date Format Mandate:** All merged entries MUST use the format `### YYYY-MM-DD: Topic` for decision headings.
- If an inbox file is missing a date, add today's date (`YYYY-MM-DD`).
- If an entry cannot be dated (missing context, ambiguous age), log a warning, skip it, and report.
- Delete each inbox file after merging

3. **Deduplicate and consolidate decisions.md:**
Expand Down
27 changes: 27 additions & 0 deletions packages/squad-cli/src/cli/core/nap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,33 @@ function cleanInbox(squadDir: string, dryRun: boolean): NapAction[] {

// ─── Decision archival ──────────────────────────────────────────────────

/**
* Archive stale decision entries from `decisions.md` to `decisions-archive.md`.
*
* **Entry format:** Each entry starts with `### YYYY-MM-DD: Topic`. Entries
* without a parseable date are treated as undated and always preserved (they
* are typically foundational directives).
*
* **Invariant:** `entries_before === entries_kept + entries_archived` — no
* decision data is ever silently dropped.
*
* **Threshold:** The file must exceed {@link DECISION_THRESHOLD} (default
* 20 KB) before any archival is attempted. This constant is overridable via
* config in future iterations.
*
* **Archival strategy:**
* 1. *Age-based* — entries older than {@link DECISION_MAX_AGE_DAYS} are
* archived first.
* 2. *Count-based fallback* — when no entries exceed the age limit but the
* file still exceeds the threshold, the oldest dated entries are archived
* until the remaining content fits within the budget.
*
* @param squadDir - Absolute path to the `.squad` directory.
* @param dryRun - When `true`, calculates the action without writing to disk.
* @returns `null` when the file is under threshold, doesn't exist, or nothing
* was archivable (e.g. only undated entries remain). Otherwise a
* {@link NapAction} describing the archive operation and bytes saved.
*/
function archiveDecisions(squadDir: string, dryRun: boolean): NapAction | null {
const decisionsFile = path.join(squadDir, 'decisions.md');
if (!fs.existsSync(decisionsFile)) return null;
Expand Down
Loading