Skip to content

feat(boulder): multi-boulder architecture for concurrent plan execution#2050

Closed
kristianvast wants to merge 8 commits intocode-yeongyu:devfrom
kristianvast:feat/multi-boulder-storage
Closed

feat(boulder): multi-boulder architecture for concurrent plan execution#2050
kristianvast wants to merge 8 commits intocode-yeongyu:devfrom
kristianvast:feat/multi-boulder-storage

Conversation

@kristianvast
Copy link
Copy Markdown

@kristianvast kristianvast commented Feb 22, 2026

Summary

  • Migrates boulder state from singleton .sisyphus/boulder.json (last-write-wins) to per-plan .sisyphus/boulders/{plan-name}.json files, enabling multiple plans to execute concurrently without conflicts
  • Adds an in-memory Map<sessionID, planName> tracker (plan-name-tracker.ts) with disk-scan fallback (findBoulderForSession) for the CLI run process (separate process, no shared memory)
  • All 6 consumer hooks migrated to plan-aware storage; full backward compatibility preserved via optional planName parameter (existing API unchanged)

Problem

The singleton .sisyphus/boulder.json is the only bottleneck preventing parallel multi-plan execution. When two plans run concurrently, the last writer wins and corrupts the other plan's state. Evidence and notepad paths are already plan-name isolated — only the boulder file was missing this isolation.

Solution

Per-plan boulder files at .sisyphus/boulders/{plan-name}.json:

  • start-work writes to the per-plan path and registers sessionID → planName in memory
  • All consumers resolve the plan-aware path via getSessionPlanName(sessionID) (in-memory, fast) with findBoulderForSession(dir, sessionID) (disk scan) as fallback
  • Legacy .sisyphus/boulder.json still works — findBoulderForSession and appendSessionId both fall back to it when no per-plan file exists

Changes

Storage layer (src/features/boulder-state/):

  • constants.ts — Added BOULDERS_DIR = "boulders" and BOULDERS_BASE_PATH
  • storage.ts — Optional planName? on 5 I/O functions; new findBoulderForSession() with legacy fallback; appendSessionId falls back to legacy path when per-plan file doesn't exist
  • plan-name-tracker.ts — New: in-memory Map<sessionID, planName> with setSessionPlanName / getSessionPlanName / clearSessionPlanName
  • index.ts — Barrel export for plan-name-tracker

Consumer hooks (all migrated to plan-aware calls):

  • src/hooks/start-work/start-work-hook.ts — Primary writer; calls setSessionPlanName + writes to per-plan path
  • src/hooks/atlas/event-handler.ts — Reads via getSessionPlanName → readBoulderState(dir, planName) ?? findBoulderForSession
  • src/hooks/atlas/tool-execute-after.ts — Same fallback chain + appendSessionId with plan name
  • src/hooks/prometheus-md-only/agent-resolution.ts — Uses findBoulderForSession for agent resolution
  • src/cli/run/continuation-state.ts — Uses findBoulderForSession (disk-only; CLI is a separate process)
  • src/plugin/tool-execute-before.ts/stop-continuation clears per-plan boulder + clearSessionPlanName

Cleanup wiring:

  • src/plugin/event.tssession.deleted now calls clearSessionPlanName(sessionID)
  • src/features/builtin-commands/templates/start-work.ts — Updated path references from boulder.json to boulders/{plan-name}.json

Backward Compatibility

  • All 5 storage functions accept optional planName? as last parameter — omitting it reads/writes the legacy .sisyphus/boulder.json path unchanged
  • findBoulderForSession scans per-plan files first, then falls back to legacy boulder.json
  • appendSessionId falls back to legacy path when the per-plan file doesn't exist
  • Zero breaking changes to existing consumers that don't pass planName

Testing

  • TDD approach: tests written RED → GREEN for all new storage functions
  • 9 new tests in storage.test.ts covering per-plan read/write/clear/append/find + legacy fallback
  • 5 new tests in plan-name-tracker.test.ts covering set/get/clear/reset
  • All 31 storage tests pass; all 36 atlas hook tests pass; all 107 targeted tests pass
  • Full suite: 3299 pass (52 pre-existing failures unchanged — none related to this change)

Summary by cubic

Enable concurrent plan execution by moving boulder state to per-plan files and adding a session→plan tracker. All hooks now resolve plan-aware state with a legacy fallback; no breaking changes.

  • New Features

    • Per-plan storage at .sisyphus/boulders/{plan}.json; all read/write/append/clear functions accept optional planName.
    • New findBoulderForSession scans per-plan files first, then falls back to legacy boulder.json.
    • In-memory session→plan Map with set/get/clear; cleared on session.deleted and /stop-continuation.
    • Consumers updated: start-work writes per-plan and registers mapping; atlas handlers resolve via tracker or disk scan; CLI continuation uses findBoulderForSession; template paths updated.
  • Migration

    • No changes required; legacy .sisyphus/boulder.json remains supported.
    • To opt into concurrency in custom code, pass planName to storage functions.

Written for commit b38fbb8. Summary will update on new commits.

@github-actions
Copy link
Copy Markdown
Contributor

Thank you for your contribution! Before we can merge this PR, we need you to sign our Contributor License Agreement (CLA).

To sign the CLA, please comment on this PR with:

I have read the CLA Document and I hereby sign the CLA

This is a one-time requirement. Once signed, all your future contributions will be automatically accepted.


I have read the CLA Document and I hereby sign the CLA


Kristian Vastveit seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 14 files

Confidence score: 4/5

  • This PR looks safe to merge; the only noted issue is a markdown formatting problem rather than a functional bug.
  • In src/features/builtin-commands/templates/start-work.ts, an unclosed ** will bold unintended content including the JSON code block, which could confuse users reading the template output.
  • Pay close attention to src/features/builtin-commands/templates/start-work.ts - fix the missing closing bold marker to avoid malformed markdown.
Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/features/builtin-commands/templates/start-work.ts">

<violation number="1" location="src/features/builtin-commands/templates/start-work.ts:18">
P2: Missing closing asterisks for bold markdown text. The line opens bold formatting with `**` but never closes it, causing malformed markdown that will incorrectly bold subsequent content including the JSON code block.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

- If MULTIPLE plans: show list with timestamps, ask user to select

4. **Create/Update boulder.json**:
4. **Create/Update \`.sisyphus/boulders/{plan-name}.json\`:
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Feb 22, 2026

Choose a reason for hiding this comment

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

P2: Missing closing asterisks for bold markdown text. The line opens bold formatting with ** but never closes it, causing malformed markdown that will incorrectly bold subsequent content including the JSON code block.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/features/builtin-commands/templates/start-work.ts, line 18:

<comment>Missing closing asterisks for bold markdown text. The line opens bold formatting with `**` but never closes it, causing malformed markdown that will incorrectly bold subsequent content including the JSON code block.</comment>

<file context>
@@ -4,18 +4,18 @@ export const START_WORK_TEMPLATE = `You are starting a Sisyphus work session.
      - If MULTIPLE plans: show list with timestamps, ask user to select
 
-4. **Create/Update boulder.json**:
+4. **Create/Update \`.sisyphus/boulders/{plan-name}.json\`:
    \`\`\`json
    {
</file context>
Suggested change
4. **Create/Update \`.sisyphus/boulders/{plan-name}.json\`:
4. **Create/Update \`.sisyphus/boulders/{plan-name}.json\`**:
Fix with Cubic

@code-yeongyu
Copy link
Copy Markdown
Owner

[sisyphus-bot]

PR Assessment Report

Status: BLOCKED — Cannot merge at this time

Blocking Issues

Condition Status Details
CI Passing ❌ FAIL CLA Assistant check failed
Review Approved ❌ NO No approval yet
Mergeable State ❌ CONFLICTING Has merge conflicts with
PR Type ℹ️ FEATURE Feature PRs require manual review

Required Actions

  1. Sign the CLA — Please comment on this PR with:

    I have read the CLA Document and I hereby sign the CLA
    
  2. Resolve merge conflicts — Rebase your branch against the latest :

    git fetch origin
    git rebase origin/dev
    git push --force-with-lease
  3. Await maintainer review — This is an architectural change affecting core boulder storage.

Technical Summary

  • Files changed: 14 (+266/-43 lines)
  • Type: Feature (multi-boulder architecture for concurrent plan execution)
  • Tests: 229 new tests added
  • Backward compatibility: Preserved (legacy still works)

Minor Issue (from cubic review)

  • — Missing closing for bold markdown

This assessment was generated automatically. A maintainer will review this PR for architectural approval.

@kristianvast kristianvast closed this by deleting the head repository Mar 20, 2026
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