Forge
csharpdeeb25a2
1namespace CascadeIDE.Features.Chat;
2
3/// <summary>Сквозная линия продукта (spine) сессии — ортогональна тредам ([ADR 0096](../../docs/adr/0096-intercom-topic-card-summary-and-product-spine.md)).</summary>
4public sealed record ChatProductSpine(
5 string LineTitle,
6 string CurrentFocus,
7 IReadOnlyList<string> Milestones,
8 bool IncludeInAgentContext)
9{
10 public static ChatProductSpine Empty { get; } = new("", "", [], false);
11
12 public bool HasContent =>
13 !string.IsNullOrWhiteSpace(LineTitle)
14 || !string.IsNullOrWhiteSpace(CurrentFocus)
15 || Milestones.Count > 0;
16
17 public bool HasFocusOrMilestones =>
18 !string.IsNullOrWhiteSpace(CurrentFocus) || Milestones.Count > 0;
19
20 public string FormatCardBody()
21 {
22 var lines = new List<string>();
23 if (!string.IsNullOrWhiteSpace(CurrentFocus))
24 lines.Add(CurrentFocus.Trim());
25 foreach (var milestone in Milestones)
26 {
27 if (string.IsNullOrWhiteSpace(milestone))
28 continue;
29 lines.Add("• " + milestone.Trim());
30 }
31
32 return lines.Count == 0 ? "Задай фокус линии и вехи над чатом." : string.Join('\n', lines);
33 }
34
35 public string? BuildAgentContextPrefix()
36 {
37 if (!IncludeInAgentContext || !HasContent)
38 return null;
39
40 var lines = new List<string> { "[Продуктовая линия — сжатый срез]" };
41 if (!string.IsNullOrWhiteSpace(LineTitle))
42 lines.Add($"Линия: {LineTitle.Trim()}");
43 if (!string.IsNullOrWhiteSpace(CurrentFocus))
44 lines.Add($"Фокус: {CurrentFocus.Trim()}");
45 var bullets = Milestones
46 .Where(m => !string.IsNullOrWhiteSpace(m))
47 .Take(3)
48 .Select(m => $"• {m.Trim()}")
49 .ToList();
50 if (bullets.Count > 0)
51 lines.AddRange(bullets);
52 lines.Add("---");
53 return string.Join(Environment.NewLine, lines);
54 }
55
56 public static IReadOnlyList<string> ParseMilestonesText(string? text) =>
57 (text ?? "")
58 .Replace("\r", "")
59 .Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
60 .Where(line => line.Length > 0)
61 .Take(8)
62 .ToList();
63
64 public static string JoinMilestonesText(IReadOnlyList<string> milestones) =>
65 string.Join(Environment.NewLine, milestones);
66}
67
View only · write via MCP/CIDE