Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@
| Thread-scoped recent-turn observable | `Partially shipped` | `CodexThread.makeRecentTurns(limit:)` now vends a bounded recent-turn observable that prewarms from the local history store, supports explicit older/newer whole-turn window expansion, seeds upstream paging cursors even when the visible initial window came from local history, and falls back to `thread/turns/list` when needed. Live probing showed that upstream turn paging is available only after a non-ephemeral thread has materialized at least one user turn, so recent observable startup now degrades to an empty local-only view for the known ephemeral and pre-materialized live runtime responses instead of surfacing raw protocol text. `RecentTurns` now ships named cache-policy presets for chat UIs, full inspectors, and compact history rails; tracks both resident item counts and weighted resident item cost; slims low-value payloads out of older non-visible completed turns before evicting whole turns; rehydrates slimmed turns when they become visible again; and uses scroll-position, visibility, phase, and velocity signals to drive protected residency plus earlier prefetch. Richer weighting heuristics and deeper policy tuning are still open. |
| Thread-scoped recent-file observable | `Partially shipped` | `CodexThread.makeRecentFiles(limit:)` and `makeRecentFiles(_:)` now vend a file-centric recent-files observable that hydrates from persisted file-change items, keeps one resident entry per file-change item, enriches live entries from `item/fileChange/outputDelta` and `item/fileChange/patchUpdated`, can load older file entries from the same turn before stepping farther back through older turns, and supports selection-aware shell-versus-payload slimming with automatic payload rehydration for protected files. `CodexThread.RecentFilesQD` gives callers a repeatable descriptor for the initial resident file window and cache policy. Live probing exercises a real create/edit/delete scenario, and recent-file startup now inherits the same empty local-only degradation as recent-turns for the known live history-unavailable responses. The current weighting now accounts for diff structure and line volume, and shell summaries prefer concise edit summaries over raw terminal status when sealed payload is available. The remaining open work is better payload-cost calibration at the margins and richer structured patch presentation beyond the current text preview. |
| Thread-scoped recent-command observable | `Partially shipped` | `CodexThread.makeRecentCommands(limit:)` and `makeRecentCommands(_:)` now vend a command-centric recent-commands observable that hydrates from persisted `commandExecution` items, keeps one resident entry per command item, enriches live entries from `item/commandExecution/outputDelta`, can load older command entries from the same turn before stepping farther back through older turns, and supports selection-aware shell-versus-output slimming with automatic output rehydration for protected commands. `CodexThread.RecentCommandsQD` gives callers a repeatable descriptor for the initial resident command window and cache policy. Recent-command startup now inherits the same empty local-only degradation as recent-turns for the known live history-unavailable responses. Current output weighting accounts for output size and line structure, and shell summaries prefer concise command and output summaries over raw transport detail. The remaining open work is better output-cost calibration and sharper shell-summary heuristics. |
| App-wide observable companion | `In Progress` | `CodexAppServer.makeLibrary()` and `CodexAppServer.Library` now expose Core Data-backed value snapshots for unarchived, archived, cwd-grouped, and repository-grouped threads, current Git branch and origin metadata, bindable sort/grouping policies, thread-list query descriptors, scoped refresh actions, library-local selection, recently selected ordering, local reloads after app-wide thread/turn events, and app-wide model/MCP/hook snapshots for launcher and sidebar UI. `CodexWorkspace` now promotes active permission-profile provenance and runtime filesystem/network permission facts from thread sessions, but the library still needs richer app-wide Git observables and broader app-wide settings/actions. |
| Public query descriptors | `Partially shipped` | `CodexAppServer.ThreadListQD` now provides repeatable thread-list intent for direct app-server `thread/list` reads and app-wide `Library` loading, `CodexFS.FileDiscoveryQD` provides repeatable bounded file-discovery intent over app-server `fs/readDirectory` reads, `CodexThread.HistoryWindowQD` provides repeatable local completed-turn window intent for recent, older, newer, turn-centered, and item-centered reads, and `CodexThread.RecentFilesQD` plus `CodexThread.RecentCommandsQD` describe recent-activity companion startup. Repository grouping now uses app-server Git origin metadata when available and falls back to cwd. Remaining descriptor work includes broader public cursor semantics, selection-centered reads if a concrete caller needs them, and later search-hit hydration. |
| App-wide observable companion | `In Progress` | `CodexAppServer.makeLibrary()` and `CodexAppServer.Library` now expose Core Data-backed value snapshots for unarchived, archived, cwd-grouped, and repository-grouped threads, `CodexWorkspace.ProjectInfo` identity for thread and group displays, `CodexAppServer.ThreadSource` values for source badges, bindable sort/grouping policies, thread-list query descriptors, scoped refresh actions, library-local selection, recently selected ordering, local reloads after app-wide thread/turn events, and app-wide model/MCP/hook snapshots for launcher and sidebar UI. `CodexWorkspace` now promotes active permission-profile provenance, runtime filesystem/network permission facts, and app-server-owned project identity from thread sessions, but the library still needs broader app-wide settings/actions. |
| Public query descriptors | `Partially shipped` | `CodexAppServer.ThreadListQD` now provides repeatable thread-list intent for direct app-server `thread/list` reads and app-wide `Library` loading, `CodexFS.FileDiscoveryQD` provides repeatable bounded file-discovery intent over app-server `fs/readDirectory` reads, `CodexThread.HistoryWindowQD` provides repeatable local completed-turn window intent for recent, older, newer, turn-centered, and item-centered reads, and `CodexThread.RecentFilesQD` plus `CodexThread.RecentCommandsQD` describe recent-activity companion startup. Repository grouping now uses `CodexWorkspace.ProjectInfo`, which identifies a project by Codex-reported Git origin when available and falls back to cwd. Remaining descriptor work includes broader public cursor semantics, selection-centered reads if a concrete caller needs them, and later search-hit hydration. |
| Non-UI local history-reading helpers | `Partially shipped` | `CodexThread` now exposes a lightweight `HistoryWindow` page shape for recent local history, older or newer local windows around a known boundary turn id, centered `windowAroundTurn(...)` reads, centered `windowAroundItem(...)` reads, direct `ClosedTurn` reads for one turn, and convenience array helpers over those same windows. This gives non-UI callers an intentional path into the local history store without binding a UI-oriented observable, while still deferring a broader public cursor model, transcript search surface, and richer history-query helpers. |
| Public API curation | `Shipped / ongoing` | The source-organization pass has split app-wide model, MCP, thread-management, history, and observable companion values into focused public files while preserving `CodexAppServer`, `CodexThread`, and `CodexTurnHandle` as the three real owners. The connected public-surface review closed the v1 ownership model; future curation should stay tied to concrete public API additions. |
| Public API curation | `Shipped / ongoing` | The source-organization pass has split app-wide model, MCP, thread-management, history, and observable companion values into focused public files while preserving `CodexAppServer`, `CodexThread`, and `CodexTurnHandle` as the three real owners. The connected public-surface review closed the v1 ownership model; post-v1 curation now includes app-server-owned project identity and thread source facts for launcher UI without exposing generated wire models. Future curation should stay tied to concrete public API additions. |
| DocC documentation | `Shipped / ongoing` | `Sources/SwiftASB/SwiftASB.docc/` contains a package landing page, public-handle extension pages, conceptual articles for app-wide capabilities, interactive lifecycle, thread management, history/observable companions, generated-wire boundary notes, and copy-pasteable walkthroughs for startup, progress/approval handling, diagnostics/history, and SwiftUI observable companions. The catalog is validated through Xcode `docbuild`; future work is ordinary stale-link, prose, and symbol-comment refinement as the public API grows. |
| Swift Package Index readiness | `Shipped` | `.spi.yml` declares `SwiftASB` as the documentation target, and Swift Package Index lists `gaelic-ghost/SwiftASB` with a documentation link, compatibility/build results, Package ID `9B5839D9-9551-473F-A939-841534A3FC55`, and a 2026-05-06 update timestamp for the latest confirmed indexed release. Recheck SPI after the `v1.1.2` tag is published. |
| Contributor documentation split | `Shipped` | `README.md` is now focused on Swift and SwiftUI package users, while `CONTRIBUTING.md` owns contributor setup, validation, DocC, live-test flags, generated-wire refresh, and PR expectations. |
Expand Down
18 changes: 16 additions & 2 deletions Sources/SwiftASB/History/ThreadHistoryStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,14 @@ actor ThreadHistoryStore {
let forkedFromTurnID: String?
let gitBranch: String?
let gitOriginURL: String?
let gitSHA: String?
let isArchived: Bool
let isClosed: Bool
let modelProvider: String
let name: String?
let preview: String
let rollbacks: [RollbackSnapshot]
let source: CodexAppServer.ThreadSource
let state: StateSnapshot
let statusFlags: [String]
let statusType: String
Expand Down Expand Up @@ -155,12 +157,14 @@ actor ThreadHistoryStore {
let forkedFromThreadID: String?
let gitBranch: String?
let gitOriginURL: String?
let gitSHA: String?
let isArchived: Bool
let isClosed: Bool
let lastCompletedTurnAt: Int?
let modelProvider: String
let name: String?
let preview: String
let source: CodexAppServer.ThreadSource
let statusFlags: [String]
let statusType: String
let updatedAt: Int
Expand Down Expand Up @@ -644,12 +648,14 @@ actor ThreadHistoryStore {
forkedFromTurnID: thread.forkedFromTurnID,
gitBranch: thread.gitBranch,
gitOriginURL: thread.gitOriginURL,
gitSHA: thread.gitSHA,
isArchived: thread.isArchived,
isClosed: thread.isClosed,
modelProvider: thread.modelProvider,
name: thread.name,
preview: thread.preview,
rollbacks: rollbacks,
source: (try Self.decode(CodexAppServer.ThreadSource.self, from: thread.sourceData)) ?? .unknown,
state: .init(completeness: state.completeness),
statusFlags: (try Self.decode([String].self, from: thread.statusFlagsData)) ?? [],
statusType: thread.statusType,
Expand Down Expand Up @@ -930,11 +936,13 @@ actor ThreadHistoryStore {
thread.currentDirectoryPath = info.currentDirectoryPath
thread.ephemeral = info.ephemeral
thread.forkedFromThreadID = info.forkedFromThreadID
thread.gitBranch = info.gitInfo?.branch
thread.gitOriginURL = info.gitInfo?.originURL
thread.gitBranch = info.projectInfo.repository?.branch
thread.gitOriginURL = info.projectInfo.repository?.originURL
thread.gitSHA = info.projectInfo.repository?.sha
thread.modelProvider = info.modelProvider
thread.name = info.name
thread.preview = info.preview
thread.sourceData = try? encode(info.source)
thread.statusType = info.status.type.rawValue
thread.statusFlagsData = try? encode(info.status.activeFlags.map(\.rawValue))
thread.updatedAt = Int64(info.updatedAt)
Expand Down Expand Up @@ -1099,12 +1107,14 @@ actor ThreadHistoryStore {
forkedFromThreadID: thread.forkedFromThreadID,
gitBranch: thread.gitBranch,
gitOriginURL: thread.gitOriginURL,
gitSHA: thread.gitSHA,
isArchived: thread.isArchived,
isClosed: thread.isClosed,
lastCompletedTurnAt: Self.lastCompletedTurnAt(for: thread),
modelProvider: thread.modelProvider,
name: thread.name,
preview: thread.preview,
source: try decode(CodexAppServer.ThreadSource.self, from: thread.sourceData) ?? .unknown,
statusFlags: try decode([String].self, from: thread.statusFlagsData) ?? [],
statusType: thread.statusType,
updatedAt: Int(thread.updatedAt)
Expand Down Expand Up @@ -1488,9 +1498,11 @@ actor ThreadHistoryStore {
attribute("forkedFromTurnID", .stringAttributeType, isOptional: true),
attribute("gitBranch", .stringAttributeType, isOptional: true),
attribute("gitOriginURL", .stringAttributeType, isOptional: true),
attribute("gitSHA", .stringAttributeType, isOptional: true),
attribute("modelProvider", .stringAttributeType, isOptional: false),
attribute("name", .stringAttributeType, isOptional: true),
attribute("preview", .stringAttributeType, isOptional: false),
attribute("sourceData", .binaryDataAttributeType, isOptional: true),
attribute("statusType", .stringAttributeType, isOptional: false),
attribute("statusFlagsData", .binaryDataAttributeType, isOptional: true),
attribute("updatedAt", .integer64AttributeType, isOptional: false),
Expand Down Expand Up @@ -1718,12 +1730,14 @@ final class HistoryThread: NSManagedObject {
@NSManaged var forkedFromTurnID: String?
@NSManaged var gitBranch: String?
@NSManaged var gitOriginURL: String?
@NSManaged var gitSHA: String?
@NSManaged var id: String
@NSManaged var isArchived: Bool
@NSManaged var isClosed: Bool
@NSManaged var modelProvider: String
@NSManaged var name: String?
@NSManaged var preview: String
@NSManaged var sourceData: Data?
@NSManaged var state: HistoryThreadState?
@NSManaged var statusFlagsData: Data?
@NSManaged var statusType: String
Expand Down
Loading