| 157 | } |
| 158 | |
| 159 | function writeHandoffDoc(state) { |
| 160 | try { |
| 161 | const handoffsDir = path.join(PROJECT_ROOT, '.planning', 'handoffs'); |
| 162 | if (!fs.existsSync(handoffsDir)) fs.mkdirSync(handoffsDir, { recursive: true }); |
| 163 | |
| 164 | const dateSlug = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); |
| 165 | const handoffFile = path.join(handoffsDir, `session-${dateSlug}.md`); |
| 166 | |
| 167 | const lines = [ |
| 168 | `# Session Handoff — ${new Date().toISOString()}`, |
| 169 | `> Auto-saved by pre-compact hook before context compression.`, |
| 170 | `> To continue: read this file + the campaign/fleet file listed below.`, |
| 171 | '', |
| 172 | ]; |
| 173 | |
| 174 | if (state.activeCampaign) { |
| 175 | lines.push(`## Active Campaign: ${state.activeCampaign}`); |
| 176 | lines.push(`File: .planning/campaigns/${state.activeCampaign}.md`); |
| 177 | if (state.recentContext) { |
| 178 | lines.push('', '### Active Context', state.recentContext); |
| 179 | } |
| 180 | if (state.continuationState) { |
| 181 | lines.push('', '### Continuation State', state.continuationState); |
| 182 | } |
| 183 | lines.push(''); |
| 184 | } |
| 185 | |
| 186 | if (state.activeFleetSession) { |
| 187 | lines.push(`## Active Fleet Session: ${state.activeFleetSession}`); |
| 188 | lines.push(`File: .planning/fleet/session-${state.activeFleetSession}.md`); |
| 189 | lines.push(''); |
| 190 | } |
| 191 | |
| 192 | if (state.pendingResearch.length) { |
| 193 | lines.push('## Recent Research Artifacts'); |
| 194 | lines.push('These files were modified in the last 2 hours and may contain unsaved analysis:'); |
| 195 | for (const f of state.pendingResearch) lines.push(`- ${f}`); |
| 196 | lines.push(''); |
| 197 | } |
| 198 | |
| 199 | if (!state.activeCampaign && !state.activeFleetSession && !state.pendingResearch.length) { |
| 200 | lines.push('No active campaigns or recent research detected at time of compaction.'); |
| 201 | } |
| 202 | |
| 203 | fs.writeFileSync(handoffFile, lines.join('\n')); |
| 204 | } catch { /* non-critical */ } |
| 205 | } |
| 206 | |
| 207 | main(); |