Skip to content

3.0 - #68

Merged
rbuergi merged 964 commits into
mainfrom
3.0
Mar 31, 2026
Merged

3.0#68
rbuergi merged 964 commits into
mainfrom
3.0

Conversation

@rbuergi

@rbuergi rbuergi commented Mar 21, 2026

Copy link
Copy Markdown
Contributor

Full redesign of core logic. Memex portal, dynamic types, proper persistence on postgresql

rbuergi and others added 30 commits March 11, 2026 11:53
Base: ae3e162 (Samuel's local 3.0 state before pulling Roland's 45 commits)
Overlay: FutuRe data/content/attachments from cd4558d + Chat files

This recreates the exact state Samuel was running when he pushed cd4558d:
- Source code from ae3e162 (pre-pull, with <img> SVG rendering, Organization
  code nodes, flat persistence, etc.)
- Updated FutuRe sample data (FX conversion, profitability reports, exchange
  rates, analysis access files, etc.)
- Chat component files that were gitignored on 3.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Brought all Chat component files from 6415d2f and adapted them to
compile against the ae3e162 codebase:
- IMeshService → IMeshQuery (query operations)
- IMeshService → IPersistenceService (CRUD operations)
- Removed IPathResolver usage (not available at ae3e162)
- Removed MeshNode.MainNode references (satellite concept not yet added)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The runtime-compiled code node referenced IMeshService which doesn't
exist at ae3e162. This caused silent compilation failure at runtime,
preventing all profitability charts from loading in the AnnualReport
pages. IMeshQuery has the same ObserveQuery/QueryAsync methods needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolved 7 conflicts favoring 3.0 changes:
- Removed Code/ files (BusinessUnitLayoutAreas, ExternalDependencies,
  ProfitabilityLayoutAreas) — equivalents exist in _Source/ from 3.0
- FutuReDataLoader.cs: IMeshQuery → IMeshService
- Chat files: IMeshQuery → IMeshService, added IPathResolver,
  MainNode, CreateNodeAsync

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Preserving current working state before switching to 3.0 branch.
Includes access control migration, demo roadmap docs, icon updates,
thread migration, and analysis report work.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
rbuergi and others added 24 commits March 29, 2026 22:41
Uses Markdig AST to build rendered-text → source-position map.
Handles bold, italic, headers, lists, links, code, blockquotes,
strikethrough, and existing comment markers via two-step mapping
(rendered → clean-markdown → raw-with-annotations).

Replaces broken IndexOf-based text search that failed when user
selected text spanning markdown formatting (##, **, etc.).

18 unit tests covering all formatting types and cross-format selections.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…lection mapping

- Custom Markdig renderer injects source positions on p, h1-h6, li, blockquote, strong, em, a, code
- JS reads data-start/data-end from selection ancestors, sends positions in CreateCommentRequest
- Handler uses JS positions directly when available, falls back to MarkdownSourceMap
- Eliminates broken IndexOf text search for formatted content

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- JS uses findSourceMappedAncestor + getTextOffsetInElement for precise
  character offsets from each end of the selection independently
- Handles selections spanning multiple paragraphs, headings, list items
- TreeWalker counts text characters before the selection point

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…eactive updates

- BindData subscribes to GetRemoteStream<MeshNode> on the markdown node address
- Content updates reactively when workspace.UpdateMeshNode() injects markers
- Replaces broken one-time bind that never reflected content changes
- DistinctUntilChanged prevents redundant re-renders

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ExecuteMessageAsync: sync handler with IObservable chain
  - Agent init via ObserveQuery (IObservable), not QueryAsync
  - Context/history from workspace stream .Current (sync read)
  - AI streaming via hub.InvokeAsync (external I/O only)
- Delegation tool: fully reactive with TCS + stream subscriptions
- All plugins (MeshOperations, PlanStorage, Version): CreateNode/UpdateNode/DeleteNode
  via IObservable.Subscribe + TaskCompletionSource, not await *NodeAsync
- Recovery: sync handler marks stale threads cancelled with timestamp
- AccessService.SwitchAccessContext: scoped identity for callbacks
- MainNode: explicitly set on all satellite nodes (threads, messages, comments)
- Coder agent: interactive markdown examples in system prompt
- Tests: CascadingProgressTest (2-level + 3-level hierarchy), ThreadRecoveryTest
- Docs: SatelliteEntityPatterns + SatelliteEntities updated with rules

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…links

- ThreadProgressEntry.StreamingCellPath: each progress entry carries its response message path
- ThreadMessageLayoutAreas: bubble subscribes to parent thread via GetRemoteStream,
  pushes isExecuting/executionStatus when ActiveMessageId matches
- Progress tree UI: sub-thread names link to their thread view, spinners on active nodes
- Tool calls already flow to response message via responseStream.Update()

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…amingArea + ToolCallsArea

- Remove Thread.ParentPath (redundant with MeshNode.MainNode)
- Remove Thread.ActiveProgress + ThreadProgressEntry (delegations live on ToolCallEntry.DelegationPath)
- Thread manages only: IsExecuting, ExecutionStatus, ActiveMessageId
- Add StreamingArea: shows response cell + ToolCallsArea (for parent thread consumption)
- Add ToolCallsArea: watches response message tool calls, shows delegation sub-threads recursively
  - Uses host.UpdateData + GetDataStream for data-driven rendering
  - ImmutableList + DistinctUntilChanged for flicker-free updates
- Progress bar: simple "Generating response..." / "Cancelling..." / "Sending..."
- Message bubble: subscribes to parent thread for isExecuting via GetRemoteStream
- Coder agent: interactive markdown examples added to system prompt
- Fix all test fakes for IChatClientFactory.CreateAgent
- Remove ParentPath from all tests across 15+ test files
- Tests: StreamingAreaTest (3), ToolCallsVisibilityTest (3)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ActiveToolCalls pushed to Thread node during streaming (avoids deadlock from remote subscriptions)
- ToolCallsView reads from thread's own workspace stream (zero cross-hub calls)
- Fix: skip initial child stream emission where IsExecuting=false (child not started yet)
  Only complete TCS when child has Messages (actually executed)
- Tool calls on message bubble: closed by default, click to expand
- Tests: ActiveToolCallsTest (3 tests)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…s bar

- Remove ToolCallsArea, ActiveToolCalls, progress bar entirely
- Tool calls render inline on message bubble: friendly verbs, collapsed args
- Delegations: agent name as link, blinking indicator while pending
- Spinner derived from content (no cross-hub isExecuting subscription)
- Remove cross-hub subscription from ThreadMessageLayoutAreas
- Fix input area overflow for dropdown menus
- Orleans streaming test + tool call formatting
- ExecutionProgress.cs removed (unused)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…gArea

- Delegation tool calls in message bubble now show LayoutAreaView
  pointing to {DelegationPath}/Streaming — sub-thread's active response
- Subscription goes CLIENT → sub-thread hub (no cross-grain issue)
- When delegation completes (Result set), streaming area hidden, ✓ shown
- Spinner derived from content state (no cross-hub isExecuting)
- Remove unused progress bar CSS

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ontent

- Add pending ToolCallEntry to toolCallLog AND push to responseStream.Update()
  immediately when FunctionCallContent arrives (before tool executes)
- Without this, during delegation the streaming loop blocks and tool calls
  never reach the response message
- Patch DelegationPath into pending entries from chatClient.LastDelegationPath
- Set LastDelegationPath before CreateNode (available sooner)
- Recovery: simplified to just clear thread state
- Cancel button shows during IsEffectivelyExecuting, nicer stop icon

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous version called hub.GetLayoutDefinition() twice (once for
the property initializer, once for BuildRules), creating two separate
LayoutDefinition instances. Now uses an explicit constructor to compute
LayoutDefinition once and derive rules from it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@rbuergi rbuergi closed this Mar 31, 2026
@rbuergi
rbuergi deleted the 3.0 branch March 31, 2026 13:57
@rbuergi rbuergi reopened this Mar 31, 2026
@rbuergi
rbuergi merged commit 9c49b57 into main Mar 31, 2026
3 checks passed
rbuergi added a commit that referenced this pull request Aug 25, 2026
…n refusal

The port added an arming-time identity gate (satellite #68): a post whose
scheduler this deployment would refuse to publish as gets NO timer, and is told
so on the post. That is deliberate and is a security property — an un-gated
timed publish could otherwise go out through a profile the principal may not
use — but it made two pre-existing Orleans tests fail, and they were right to.

OrleansScheduledPostTest seeds its posts under ImpersonateAsSystem, purely to
get the write past access control. Post-#68 that no longer describes 'a post
someone scheduled': it describes a SYSTEM-WRITTEN post, whose lastModifiedBy is
the system principal, which correctly gets no timer. So both tests hung 45 s on
AwaitTimer and failed. The satellite shipped this green because its test project
is new and unit-only; the platform has the end-to-end scheduling test, which is
exactly the asymmetry #2258 exists to close.

The fixture now impersonates a PERSON — same mechanism, an identity that is
load-bearing rather than incidental — and the assertions are untouched. Two
things are added rather than relaxed:

  * ScheduledPost_ArmsATimer... now asserts the armed timer NAMES the scheduler.
    That is the #50 regression end to end, on the storage lane that caused it: a
    null CreatedBy here is the production bug, and it is invisible until the slot
    arrives and the publish is refused.
  * ASystemWrittenPost_IsNotArmed_AndSaysWhyOnThePost pins the other half — no
    timer for a platform-written post, AND the reason recorded on the post in the
    words its owner reads, not only on a subscription in the Admin partition they
    cannot see.

Verified: 3/3 Orleans scheduling tests (16 s, was a 46 s timeout), and the 15
pre-existing Monolith social tests that touch this surface are unaffected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

2 participants