Skip to content

feat: add Perch and playable Flight graphs - #5

Merged
AstroQore merged 2 commits into
mainfrom
feat/map-workspaces
Aug 25, 2026
Merged

feat: add Perch and playable Flight graphs#5
AstroQore merged 2 commits into
mainfrom
feat/map-workspaces

Conversation

@AstroQore

Copy link
Copy Markdown
Owner

Summary

  • add the fifth Perch view with native virtualized canvas, multiple user boards, nested rules, independent placement, minimap, dependency editing, keyboard navigation, and durable v9 history
  • add Perch History playback, fixed playhead behavior, paused forks, three-way merge, complete history pagination, and read-only mutation guards
  • add Zoetrope-inspired Flight Graph and shared Graph/Trace event playback with Agent lineage, tool activity, minimap, Moment inspector, event ruler, camera modes, and stable source-time ordering
  • remove the recurring demo replay and SwiftUI layout feedback paths that caused long-running freezes; settled packaged Flight and Perch demos return below the 3 percent CPU budget

Verification

  • swift build
  • swift test --quiet: 1320 tests in 146 suites
  • Scripts/build_app.sh release
  • codesign --verify --deep --strict .build/Auspex.app
  • empty entitlement dictionary; no app sandbox
  • privacy diff grep and git diff --check
  • dark and light Perch/Flight offscreen renders inspected

Release boundary

This PR does not contain a release bump or tag. A Dev release will be cut from main after this PR merges.

AstroQore and others added 2 commits August 25, 2026 02:43
Add the fifth Map view, native virtualized canvas, durable multi-board placement, nested membership rules, dependency editing, and the append-only v9 history foundation.

Co-Authored-By: Codex <noreply@openai.com>
Land the user-owned spatial workspace, event-indexed history, forking and merge flow, and Zoetrope-inspired Flight Graph playback. Keep live observation responsive by narrowing invalidations, bounding clocks, and removing replay/layout feedback loops.

Co-Authored-By: Codex <noreply@openai.com>
@AstroQore
AstroQore merged commit 47c5e6b into main Aug 25, 2026
1 check passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4b61077139

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +211 to +212
for membership in state.memberships.values
where membership.boardID == source.id && membership.isVisible {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Carry hidden memberships into fork branches

When a custom board contains a rule-matching node with a manual .exclude, this filter omits that membership from the fork. A later merge interprets the missing/default branch value as a branch-side change from the historical base and automatically removes the parent's exclusion; the next live synchronization can then make the card visible again. Copy all membership state into the fork, even when a membership is not currently visible.

Useful? React with 👍 / 👎.

Comment on lines +836 to +838
branch.mergeBaseEventID = db.lastInsertedRowID
branch.updatedAt = now
try Self.update(branch, in: db)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reconcile resolved conflicts before advancing the merge base

When both sides changed a position and the user explicitly chooses the parent, applyMerge leaves the conflicting branch position untouched but advances the base to the parent's current state. On the next merge, the parent equals the new base while the branch still differs, so the previously rejected branch position becomes an automatic change and silently overwrites the parent. Before advancing the base, reconcile the branch projection with the chosen result or otherwise persist the resolution so it cannot be reapplied.

Useful? React with 👍 / 👎.

Comment on lines +434 to +435
guard let self else { return }
if case .failure(let error) = result { errorDescription = error.localizedDescription }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Refresh cached placements after a successful move

After a drag succeeds, only the optimistic cards value and the database are updated; synchronizedBySource still contains the old placement. On an active board, the next coalesced adoptLiveSeeds rebuilds the card from that stale cache and snaps it back to its previous position until a board switch or unrelated workspace synchronization reloads the database. Update the cached synchronized node or schedule a synchronization on success.

Useful? React with 👍 / 👎.

Comment on lines +325 to +327
title: snapshot?.identity.title ?? fact.title,
state: snapshot?.state ?? fact.placeholderState,
isStale: snapshot?.isStale ?? false,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Let subagent completion override a stale child snapshot

When the archive includes events emitted by the child, sessions[fact.key] exists, so this expression always prefers the child's last reduced state over the .ended placeholder set by the parent's subagentFinished event. A child whose last own event was thinking or using a tool therefore remains active after its explicit completion, and its graph edge is also rendered active. Track the completion in the effective node state rather than only in the fallback placeholder.

Useful? React with 👍 / 👎.

Comment on lines +326 to +328
updatedAt: now
)
if membership != previousMembership {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Compare membership semantics before updating timestamps

Because synthesized MapMembership equality includes updatedAt, assigning now before this comparison makes every existing membership unequal on every synchronize call, even when its rule result and override did not change. On a selected custom board, a single rule-facing state change can consequently upsert and append history for every node; with the repository's expected hundreds of sessions, repeated bursts cause needless SQLite work and unbounded playback-history growth. Compare ruleMatches and override first, and only stamp/write actual changes.

AGENTS.md reference: AGENTS.md:L108-L118

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant