Merge nucleic/tidy-slate-lynx-t7al into dev
This commit is contained in:
@@ -39,6 +39,7 @@ enum SandboxToolDisplay {
|
|||||||
case "linux_vm_exec", "linux_vm_control": "Linux VM"
|
case "linux_vm_exec", "linux_vm_control": "Linux VM"
|
||||||
case "linux_vm_computer", "linux_vm_computer_batch": "Linux VM screen"
|
case "linux_vm_computer", "linux_vm_computer_batch": "Linux VM screen"
|
||||||
case "linux_container": "Linux container"
|
case "linux_container": "Linux container"
|
||||||
|
case "nucleic_supervise": "Supervising subagents"
|
||||||
default: nil
|
default: nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,6 +68,7 @@ enum SandboxToolDisplay {
|
|||||||
case "mac_vm_request_operator": "Waiting for you to drive the VM…"
|
case "mac_vm_request_operator": "Waiting for you to drive the VM…"
|
||||||
case "mac_vm_control": "Managing the macOS VM…"
|
case "mac_vm_control": "Managing the macOS VM…"
|
||||||
case "linux_vm_control": "Managing the Linux VM…"
|
case "linux_vm_control": "Managing the Linux VM…"
|
||||||
|
case "nucleic_supervise": "Waiting on subagents…"
|
||||||
default: nil
|
default: nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,6 +86,7 @@ enum SandboxToolDisplay {
|
|||||||
case "mac_vm_clear_notifications": "bell.slash"
|
case "mac_vm_clear_notifications": "bell.slash"
|
||||||
case "mac_vm_request_operator": "hand.raised"
|
case "mac_vm_request_operator": "hand.raised"
|
||||||
case "mac_vm_control", "linux_vm_control": "power"
|
case "mac_vm_control", "linux_vm_control": "power"
|
||||||
|
case "nucleic_supervise": "eye"
|
||||||
default: nil
|
default: nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,6 +111,9 @@ struct ToolGroup: Equatable {
|
|||||||
/// Unlike a `Task` subagent, a worker runs as its own observed session, so it carries no
|
/// Unlike a `Task` subagent, a worker runs as its own observed session, so it carries no
|
||||||
/// nested `children` here; its card shows the final output it returned instead.
|
/// nested `children` here; its card shows the final output it returned instead.
|
||||||
static let orchestraSubagentToolName = "mcp__nucleic__nucleic_subagent"
|
static let orchestraSubagentToolName = "mcp__nucleic__nucleic_subagent"
|
||||||
|
/// The supervisor's blocking worker-event drain. Holder-level Orchestra lock notes that have
|
||||||
|
/// no edit card in the parent transcript fold onto this card.
|
||||||
|
static let orchestraSuperviseToolName = "mcp__nucleic__nucleic_supervise"
|
||||||
|
|
||||||
/// Subagent orchestration — a `Task`/`Agent` spawn or a `nucleic_subagent` worker — gets the
|
/// Subagent orchestration — a `Task`/`Agent` spawn or a `nucleic_subagent` worker — gets the
|
||||||
/// gold card treatment, like the Mac.
|
/// gold card treatment, like the Mac.
|
||||||
@@ -157,6 +160,7 @@ enum TranscriptProjection {
|
|||||||
struct PriorEdit: Equatable {
|
struct PriorEdit: Equatable {
|
||||||
let toolCallID: String
|
let toolCallID: String
|
||||||
/// Repo-relative, normalized paths this call writes (`editedPaths` ∘ `normalizeForLock`).
|
/// Repo-relative, normalized paths this call writes (`editedPaths` ∘ `normalizeForLock`).
|
||||||
|
/// Empty marks a `nucleic_supervise` card for unmatched Orchestra worker locks.
|
||||||
let paths: [String]
|
let paths: [String]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,6 +208,9 @@ enum TranscriptProjection {
|
|||||||
let items = showRaw ? coalesced : coalesced.filter { !$0.isDebug }
|
let items = showRaw ? coalesced : coalesced.filter { !$0.isDebug }
|
||||||
let edits = flat.compactMap { item -> PriorEdit? in
|
let edits = flat.compactMap { item -> PriorEdit? in
|
||||||
guard case .tool(let group) = item.kind else { return nil }
|
guard case .tool(let group) = item.kind else { return nil }
|
||||||
|
if isOrchestraSupervise(group) {
|
||||||
|
return PriorEdit(toolCallID: group.toolCallID, paths: [])
|
||||||
|
}
|
||||||
let paths = editedPaths(toolName: group.name, input: group.input)
|
let paths = editedPaths(toolName: group.name, input: group.input)
|
||||||
.map { normalizeForLock($0, worktreeRoot: root) }
|
.map { normalizeForLock($0, worktreeRoot: root) }
|
||||||
.filter { !$0.isEmpty }
|
.filter { !$0.isEmpty }
|
||||||
@@ -243,14 +250,17 @@ enum TranscriptProjection {
|
|||||||
) -> [TranscriptItem] {
|
) -> [TranscriptItem] {
|
||||||
// Each tool item's repo-relative edited paths (only edit-class tools have any), by index.
|
// Each tool item's repo-relative edited paths (only edit-class tools have any), by index.
|
||||||
var editsByIndex: [Int: (id: String, paths: [String])] = [:]
|
var editsByIndex: [Int: (id: String, paths: [String])] = [:]
|
||||||
|
var superviseByIndex: [Int: String] = [:]
|
||||||
for (i, item) in flat.enumerated() {
|
for (i, item) in flat.enumerated() {
|
||||||
guard case .tool(let group) = item.kind else { continue }
|
guard case .tool(let group) = item.kind else { continue }
|
||||||
|
if isOrchestraSupervise(group) { superviseByIndex[i] = group.toolCallID }
|
||||||
let paths = editedPaths(toolName: group.name, input: group.input)
|
let paths = editedPaths(toolName: group.name, input: group.input)
|
||||||
.map { normalizeForLock($0, worktreeRoot: worktreeRoot) }
|
.map { normalizeForLock($0, worktreeRoot: worktreeRoot) }
|
||||||
.filter { !$0.isEmpty }
|
.filter { !$0.isEmpty }
|
||||||
if !paths.isEmpty { editsByIndex[i] = (group.toolCallID, paths) }
|
if !paths.isEmpty { editsByIndex[i] = (group.toolCallID, paths) }
|
||||||
}
|
}
|
||||||
guard !editsByIndex.isEmpty || !priorEdits.isEmpty else { return flat }
|
guard !editsByIndex.isEmpty || !superviseByIndex.isEmpty || !priorEdits.isEmpty
|
||||||
|
else { return flat }
|
||||||
let priorIDs = Set(priorEdits.map(\.toolCallID))
|
let priorIDs = Set(priorEdits.map(\.toolCallID))
|
||||||
|
|
||||||
var locksByCall: [String: [NoteLock]] = [:]
|
var locksByCall: [String: [NoteLock]] = [:]
|
||||||
@@ -279,6 +289,19 @@ enum TranscriptProjection {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if hitID == nil {
|
||||||
|
for j in stride(from: i - 1, through: 0, by: -1) {
|
||||||
|
if let supervise = superviseByIndex[j] { hitID = supervise; break }
|
||||||
|
}
|
||||||
|
if hitID == nil {
|
||||||
|
for j in (i + 1)..<flat.count {
|
||||||
|
if let supervise = superviseByIndex[j] { hitID = supervise; break }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if hitID == nil {
|
||||||
|
hitID = priorEdits.reversed().first(where: { $0.paths.isEmpty })?.toolCallID
|
||||||
|
}
|
||||||
|
}
|
||||||
guard let hitID else { matchedAll = false; break }
|
guard let hitID else { matchedAll = false; break }
|
||||||
if let k = indexByID[hitID] { perCard[k].paths.append(path) }
|
if let k = indexByID[hitID] { perCard[k].paths.append(path) }
|
||||||
else { indexByID[hitID] = perCard.count; perCard.append((hitID, [path])) }
|
else { indexByID[hitID] = perCard.count; perCard.append((hitID, [path])) }
|
||||||
@@ -316,6 +339,10 @@ enum TranscriptProjection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static func isOrchestraSupervise(_ group: ToolGroup) -> Bool {
|
||||||
|
group.name == ToolGroup.orchestraSuperviseToolName || group.name == "nucleic_supervise"
|
||||||
|
}
|
||||||
|
|
||||||
/// Make a raw tool-call path comparable to a lock note's repo-relative path: strip the worktree
|
/// Make a raw tool-call path comparable to a lock note's repo-relative path: strip the worktree
|
||||||
/// root prefix and normalize. A path not under the root is left as-is (it simply won't overlap).
|
/// root prefix and normalize. A path not under the root is left as-is (it simply won't overlap).
|
||||||
/// Mirrors the Mac's `normalizeForLock`.
|
/// Mirrors the Mac's `normalizeForLock`.
|
||||||
|
|||||||
Reference in New Issue
Block a user