Skip to content

Design: a task closes on merge or cancel; reject with feedback requeues - #62

Merged
mchwang merged 1 commit into
mainfrom
docs/l1-reject-requeues
Sep 26, 2026
Merged

mchwang merged 1 commit into
mainfrom
docs/l1-reject-requeues

Conversation

@mchwang

@mchwang mchwang commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Follow-up from #52 and the F1 contract (#49).

Problem

The design's learning section L1 said "A task closes: it is merged, cancelled, or rejected." Step 8 of the same design says "Reject with feedback" creates the next plan revision and puts the task back in the queue. These contradict each other about when a task closes, and so about when lane J may distill its feedback into lessons.

The F1 runner contract (docs/implementation/runner-lifecycle.md) followed step 8, and carried an interim note saying it governed until the design was reconciled.

Change

  • Design, L1 step 1: a task closes when it is merged or you cancel it. Reject with feedback does not close a task: it requeues it (step 8). Each reject round's feedback stays with the task and is included when the task finally closes.
  • F1 contract: the interim "this contract governs until the design is reconciled" note is replaced by a statement that L1 agrees.

No behaviour changes. This matches what F1 implements: the closed statuses are merged and cancelled, and task-closed is written only for a confirmed merge or a cancel task.

Validation

Docs only; git diff --check is clean. I searched the design for any other place that ties "rejected" to task closure or lessons, and found none.

Readiness report

  • Head: 49603b6
  • CI: test passed on 49603b6
  • Mergeability: mergeable, no conflicts
  • Review threads: none
  • Copilot review (49603b6): approval recommended, no findings
  • Review-lesson audit: no review findings, so no rule changes
  • Deferred follow-up: remove the README's Ask host-limit note and the plan's R1 exception text together when Run Ask in the lane D agent container #54 (Ask in the agent container) merges

🤖 Generated with Claude Code

L1 listed "rejected" as a way a task closes, which contradicted step 8
(Reject with feedback creates the next revision and requeues the task).
The F1 contract already followed step 8; drop its interim note now that
the design agrees.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 26, 2026 18:02

Copilot AI 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.

Copilot review overview

🟢 Approval recommended

The lifecycle rules are consistently reconciled with no unresolved issues.

Review effort: Lite
Findings: None

What changed in this PR

This documentation-only PR reconciles task lifecycle semantics: merge or cancellation closes a task, while rejection requeues it and preserves feedback.

Changes:

  • Updates L1 closure and feedback rules.
  • Aligns the F1 runner contract.
File Description
docs/​implementation/​runner-lifecycle.md Aligns F1 with the reconciled design.
docs/​designs/​codeboost-plan-indexed-review.md Clarifies closure and rejection-feedback retention.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@mchwang
mchwang merged commit 369a528 into main Sep 26, 2026
2 checks passed
mchwang added a commit that referenced this pull request Sep 30, 2026
* F1d: startup recovery and the single-runner lock

acquireRunnerLock: owner-only parent directory, no-follow identify or create,
refuse hard links and symlinks, then an OS lock on
~/.codeboost/locks/<dev>-<ino>.runner-lock (SQLite exclusive locking) that
the OS releases on exit or crash; verify() after the Store opens. The CLI
takes the lock before starting and releases it after shutdown.

recoverStartup: stop leftover preparation groups, D recovery (injected until
transaction (settlement precedence, cancel and time-limit guards, requeue
claim), storage removal, attempt-directory sweep, merged-task repair, and a
fail-closed stop for unrecorded preparation. Store: runner owner token,
preparation and allocation markers, requeue claim at admission, and
releasePreparation with an open-files check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep held runner locks referenced so GC cannot release them

A caller that dropped the returned RunnerLock let its SQLite connection be
garbage-collected, which released the OS lock while the runner was still
alive. Found by a CI failure of the cross-process lock test on #60. The new
test drops the lock and forces GC in a child, and fails without the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Start the merge-repair recovery test from a task in review

main (#62, #53) lets only a task in review begin a merge attempt, so the
test puts its queued task in review before it records the merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep recovery fail-closed: unowned directories, unreadable start times, symlinked roots, unstopped exports

- The attempt-directory sweep skips every unowned preparation, including
  one an earlier startup already finalized. Before, the second startup
  deleted its directory while step 7 still blocked on it.
- ps runs with LC_ALL=C, and a start time Date.parse cannot read counts
  as ours, so a live preparation group is still stopped.
- hostOpenFiles compares against the resolved directory. On Linux a
  symlink in the runner root made an in-use directory look unused.
- A timed-out export is awaited, for up to the grace period, before its
  task storage is removed. An export that does not stop blocks startup.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <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