Format learnings as individual list items grouped by category. Only includes **Repo** and **Workflow** learnings. Code learnings (with file:line references) are stored in the change's unhashed section, not in the context file — they're noisy, they drift with edits, and in a large project they'd grow unbounded. Returns a map of heading → list items so callers can merge into existing headings inst
(learnings: &Learnings)
| 156 | /// - cargo test --lib is faster for auth changes |
| 157 | /// ``` |
| 158 | pub fn format_learnings_markdown(learnings: &Learnings) -> String { |
| 159 | let mut out = String::new(); |
| 160 | |
| 161 | if !learnings.repo.is_empty() { |
| 162 | out.push_str("### Repo\n"); |
| 163 | for item in &learnings.repo { |
| 164 | out.push_str(&format!("- {}\n", item)); |
| 165 | } |
| 166 | out.push('\n'); |
| 167 | } |
| 168 | |
| 169 | // Code learnings are intentionally NOT written to the context file. |
| 170 | // They live in the change's unhashed section where the server can |
| 171 | // render them with CRDT graph anchoring. The context file only gets |
| 172 | // the durable, location-independent knowledge. |
| 173 | |
| 174 | if !learnings.workflow.is_empty() { |
| 175 | out.push_str("### Workflow\n"); |
| 176 | for item in &learnings.workflow { |
| 177 | out.push_str(&format!("- {}\n", item)); |
| 178 | } |
| 179 | out.push('\n'); |
| 180 | } |
| 181 | |
| 182 | out |
| 183 | } |
| 184 | |
| 185 | /// Count how many learnings would be written to the context file. |
| 186 | /// |