Move questions and reviews into the transcript; agents answer findings

This commit is contained in:
Ian Gulliver
2026-10-19 09:14:21 -07:00
parent eb7e0a13c4
commit 27ff0f457b
21 changed files with 903 additions and 801 deletions
+26 -35
View File
@@ -38,7 +38,6 @@ func untilCancelled() async {
@Observable
final class ChangesModel {
let store: Store
let compact: Bool
private(set) var changes: TaskChanges?
private(set) var error = ""
private(set) var diffs: [String: Result<String, ApiError>] = [:]
@@ -52,20 +51,19 @@ final class ChangesModel {
@ObservationIgnored private var target = 0
@ObservationIgnored private var fetching: Set<String> = []
init(_ store: Store, compact: Bool) {
init(_ store: Store) {
self.store = store
self.compact = compact
open = store.changesMemory.open
range = store.changesMemory.range
pinRange = store.changesMemory.pinRange
}
var pinned: Int? {
compact ? nil : store.pinned
store.pinned
}
var mode: ChangeMode {
compact ? .main : pinned != nil ? pinRange : range
pinned != nil ? pinRange : range
}
var empty: String {
@@ -217,7 +215,6 @@ final class ChangesModel {
}
struct ChangesView: View {
var compact = false
@Environment(Store.self) private var store
@ViewState private var model: ChangesModel?
@@ -225,14 +222,12 @@ struct ChangesView: View {
VStack(spacing: 0) {
if let model {
ChangesHead(model: model)
if !compact {
ChangesList(model: model)
}
ChangesList(model: model)
}
}
.frame(maxHeight: compact ? nil : .infinity, alignment: .top)
.frame(maxHeight: .infinity, alignment: .top)
.task(id: store.selectedTaskId) {
let m = model ?? ChangesModel(store, compact: compact)
let m = model ?? ChangesModel(store)
model = m
m.retarget()
let off = store.selectedFeed?.appended.add { [weak m] events in
@@ -243,9 +238,7 @@ struct ChangesView: View {
m.stop()
}
.onChange(of: store.pinned) {
if !compact {
model?.retarget()
}
model?.retarget()
}
}
}
@@ -267,7 +260,7 @@ private struct ChangesHead: View {
.textSelection(.enabled)
}
Spacer(minLength: 0)
if !model.compact, let taskId = store.selectedTaskId, let drafts = store.drafts {
if let taskId = store.selectedTaskId, let drafts = store.drafts {
let n = drafts.lineComments(taskId).filter { !trimmed($0.text).isEmpty }.count
if n > 0 {
Button("Send \(n) \(n == 1 ? "comment" : "comments")") {
@@ -317,29 +310,27 @@ private struct ChangesHead: View {
@ViewBuilder
private var toggle: some View {
if !model.compact {
HStack(spacing: 4) {
if model.pinned != nil {
RangeTabButton(label: "Since main", active: model.pinRange == .main) {
model.setPinRange(.main)
}
RangeTabButton(label: "This step", active: model.pinRange == .step) {
model.setPinRange(.step)
}
RangeTabButton(label: "Live", active: false, help: "Back to the live worktree") {
store.pinSnapshot(nil)
}
} else {
RangeTabButton(label: "Since main", active: model.range == .main) {
model.setRange(.main)
}
RangeTabButton(label: "This turn", active: model.range == .turn) {
model.setRange(.turn)
}
HStack(spacing: 4) {
if model.pinned != nil {
RangeTabButton(label: "Since main", active: model.pinRange == .main) {
model.setPinRange(.main)
}
RangeTabButton(label: "This step", active: model.pinRange == .step) {
model.setPinRange(.step)
}
RangeTabButton(label: "Live", active: false, help: "Back to the live worktree") {
store.pinSnapshot(nil)
}
} else {
RangeTabButton(label: "Since main", active: model.range == .main) {
model.setRange(.main)
}
RangeTabButton(label: "This turn", active: model.range == .turn) {
model.setRange(.turn)
}
}
.fixedSize()
}
.fixedSize()
}
}