Skip to content

Add parent/child thread delegation primitives#1779

Closed
ratulsarna wants to merge 5 commits intopingdotgg:mainfrom
ratulsarna:parent-child-thread-primitives
Closed

Add parent/child thread delegation primitives#1779
ratulsarna wants to merge 5 commits intopingdotgg:mainfrom
ratulsarna:parent-child-thread-primitives

Conversation

@ratulsarna
Copy link
Copy Markdown

@ratulsarna ratulsarna commented Apr 6, 2026

Summary

  • Add parentThreadId as first-class state on threads, enabling one thread to create and link to a child thread within the same project
  • Enforce creation-time invariants: parent must exist, same project, not deleted, not self-referencing (archived parents are valid)
  • Persist and hydrate parentThreadId end-to-end: contracts → decider → projector → SQLite projection → snapshot query → web store
  • Backward-compatible: historical events and snapshots without the field decode to null

Implementation areas

  • Contracts (packages/contracts): OrchestrationThread, ThreadCreateCommand, bootstrap metadata, ThreadCreatedPayload with decode defaults
  • Decider (apps/server): parent validation with requireThreadNotDeleted helper, ?? null normalization for internal callers
  • Projections (apps/server): migration 020, repository/service schema, pipeline, projector, snapshot query
  • Web store (apps/web): Thread and SidebarThreadSummary types, snapshot sync, event handler, sidebar equality check
  • Bootstrap (apps/server): ws.ts dispatch propagates parentThreadId from bootstrap metadata

Validation

  • bun fmt: pass
  • bun lint: pass
  • bun typecheck: pass (7/7 packages)
  • bun run test: pass (61 files, 659 tests)
  • Per-task bugs lane reviews on all 4 implementation tasks
  • Full branch bugs lane final review

Design decisions

  • parentThreadId lives on the child thread only — no childThreadIds mirror, no relationship table
  • Creation-time linking only (v1) — no reparenting, no cycle walks needed
  • Lifecycle is non-cascading — delete/archive/revert do not propagate across the relationship
  • Separate from existing implementationThreadId / sourceProposedPlan (coexist for now)

Note

Add parent/child thread delegation primitives across contracts, store, and persistence

  • Adds parentThreadId: ThreadId | null to the Thread, SidebarThreadSummary, OrchestrationThread, ThreadCreateCommand, and ThreadCreatedPayload types/schemas in orchestration.ts and types.ts, defaulting to null for historical records.
  • Adds a database migration (020_ProjectionThreadsParentThreadId.ts) to add a nullable parent_thread_id column to projection_threads, and updates the repository upsert/select queries accordingly.
  • Enforces parent-child invariants in the thread.create decider: rejects self-parenting, missing/deleted parents, and cross-project parents; adds requireThreadNotDeleted to commandInvariants.ts.
  • Propagates parentThreadId through the full stack: projector, snapshot query, projection pipeline, client store mapping, sidebar summaries, and thread creation bootstrap in the WebSocket layer.
  • Behavioral Change: sidebarThreadSummariesEqual now includes parentThreadId in its equality check, so sidebar updates will trigger whenever parentThreadId changes.

Macroscope summarized add129b.

Extend OrchestrationThread, ThreadCreateCommand,
ThreadTurnStartBootstrapCreateThread, and ThreadCreatedPayload with a
nullable parentThreadId field. Uses Schema.withDecodingDefault so
historical events and snapshots that lack the field decode to null.
Validate parentThreadId on thread.create: parent must exist, be in the
same project, not be deleted, and not be the child itself. Archived
parents are allowed. Normalize parentThreadId via ?? null to handle
internal callers that omit the field. Propagate parentThreadId through
the bootstrap create-and-start dispatch path in ws.ts.
Add migration 020 for parent_thread_id column on projection_threads.
Update repository schema, SQL INSERT/UPDATE/SELECT queries, projection
pipeline, in-memory projector, and snapshot query to carry
parentThreadId end-to-end. Existing rows without the column default
to null.
Add parentThreadId to Thread and SidebarThreadSummary interfaces. Map
it through snapshot sync, event-driven thread.created handling, sidebar
summary construction, and sidebar equality checks. Update all thread
construction call sites and test fixtures to include the field.
Add parentThreadId: null to all server-side thread.create command
builders, snapshot fixtures, and bootstrap createThread metadata in
test files that were not covered by earlier task slices.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 6, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 771fd6f7-dd7c-4cfa-84a8-467140f07d8b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Apr 6, 2026
@ratulsarna
Copy link
Copy Markdown
Author

Sorry about this.

@ratulsarna ratulsarna closed this Apr 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant