feat(FN-3937): document architecture recovery layers and lifecycle alignmen
Added documentation for Fusion's architecture recovery layers (deadlock self-healing, paused-aware in-review filtering) and aligned lifecycle docs, with a new test validating that the self-healing docs stay in sync with the source code. Fusion-Task-Id: FN-3937
This commit is contained in:
@@ -572,7 +572,9 @@ Runtime action-gate flow (v1):
|
|||||||
- `SelfHealingManager` (`self-healing.ts`) — auto-unpause/maintenance recovery actions
|
- `SelfHealingManager` (`self-healing.ts`) — auto-unpause/maintenance recovery actions
|
||||||
- `recoverGhostReviewTasks()` is a fallback only for idle, non-terminal `in-review` states. Terminal/actionable states (notably `status: "failed"`) are preserved and **not** auto-kicked back to `todo`.
|
- `recoverGhostReviewTasks()` is a fallback only for idle, non-terminal `in-review` states. Terminal/actionable states (notably `status: "failed"`) are preserved and **not** auto-kicked back to `todo`.
|
||||||
- `recoverMergeableReviewTasks()` only re-enqueues truly eligible tasks; retry-exhausted review tasks are skipped to avoid re-enqueue/no-op loops that keep refreshing `updatedAt`.
|
- `recoverMergeableReviewTasks()` only re-enqueues truly eligible tasks; retry-exhausted review tasks are skipped to avoid re-enqueue/no-op loops that keep refreshing `updatedAt`.
|
||||||
|
- `recoverAlreadyMergedReviewTasks()` auto-finalizes retry-exhausted `in-review` tasks when self-healing can prove their work already landed on the merge target, preventing deadlocked cards from remaining indefinitely in failed review state.
|
||||||
- `clearStaleBlockedBy()` clears `blockedBy` (and transient `status`) on todo tasks when their blocker is missing, done, archived, paused in-review, or failed in-review with merge retries exhausted. FN-3924 extends this with a dependency-integrity guard: if a task has explicit dependencies and `blockedBy` is not one of the currently unresolved deps, the stale marker is cleared. This repairs rows corrupted by historical overlap re-stamping and lets scheduler re-evaluate from live dependency state.
|
- `clearStaleBlockedBy()` clears `blockedBy` (and transient `status`) on todo tasks when their blocker is missing, done, archived, paused in-review, or failed in-review with merge retries exhausted. FN-3924 extends this with a dependency-integrity guard: if a task has explicit dependencies and `blockedBy` is not one of the currently unresolved deps, the stale marker is cleared. This repairs rows corrupted by historical overlap re-stamping and lets scheduler re-evaluate from live dependency state.
|
||||||
|
- Together, `recoverAlreadyMergedReviewTasks()`, `clearStaleBlockedBy()`, and paused-aware in-review scheduling prevent merge-deadlock loops by finalizing already-landed work, clearing stale dependency blockers, and avoiding paused review cards re-blocking overlap dispatch.
|
||||||
- Merge commit attribution is ownership-aware: a `mergeDetails.commitSha` is trusted only when reachable from `HEAD` **and** attributable to the task via `Fusion-Task-Id` trailer or task-ID-bearing subject. Reachable-but-unowned SHAs are rejected to prevent sibling done tasks from sharing misleading merge metadata.
|
- Merge commit attribution is ownership-aware: a `mergeDetails.commitSha` is trusted only when reachable from `HEAD` **and** attributable to the task via `Fusion-Task-Id` trailer or task-ID-bearing subject. Reachable-but-unowned SHAs are rejected to prevent sibling done tasks from sharing misleading merge metadata.
|
||||||
- `ProjectEngine` settings lifecycle handlers (`project-engine.ts`) treat `enginePaused` as a soft pause: clearing it dispatches runtime resume and, when `autoMerge` is enabled, performs an `in-review` eligibility sweep to requeue mergeable review tasks.
|
- `ProjectEngine` settings lifecycle handlers (`project-engine.ts`) treat `enginePaused` as a soft pause: clearing it dispatches runtime resume and, when `autoMerge` is enabled, performs an `in-review` eligibility sweep to requeue mergeable review tasks.
|
||||||
- `UsageLimitPauser` (`usage-limit-detector.ts`) and `withRateLimitRetry` (`rate-limit-retry.ts`)
|
- `UsageLimitPauser` (`usage-limit-detector.ts`) and `withRateLimitRetry` (`rate-limit-retry.ts`)
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ Fusion task columns:
|
|||||||
3. **in-progress** — executor active in isolated worktree
|
3. **in-progress** — executor active in isolated worktree
|
||||||
4. **in-review** — implementation complete; awaiting finalization
|
4. **in-review** — implementation complete; awaiting finalization
|
||||||
- If merge/finalization hits a terminal error, tasks can remain in `in-review` with `status: "failed"` for explicit follow-up. This state is intentionally preserved by recovery (not auto-bounced to `todo`).
|
- If merge/finalization hits a terminal error, tasks can remain in `in-review` with `status: "failed"` for explicit follow-up. This state is intentionally preserved by recovery (not auto-bounced to `todo`).
|
||||||
|
- Self-healing can still auto-finalize retry-exhausted failed review tasks when it can prove their branch content already landed on the merge target, so already-merged work does not deadlock in `in-review`.
|
||||||
5. **done** — merged/finalized
|
5. **done** — merged/finalized
|
||||||
6. **archived** — preserved history, optionally cleaned from filesystem
|
6. **archived** — preserved history, optionally cleaned from filesystem
|
||||||
|
|
||||||
|
|||||||
38
scripts/__tests__/self-healing-docs.test.mjs
Normal file
38
scripts/__tests__/self-healing-docs.test.mjs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import test from "node:test";
|
||||||
|
import assert from "node:assert/strict";
|
||||||
|
import { readFileSync } from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
|
const architecturePath = path.resolve(__dirname, "../../docs/architecture.md");
|
||||||
|
const taskManagementPath = path.resolve(__dirname, "../../docs/task-management.md");
|
||||||
|
const architectureDoc = readFileSync(architecturePath, "utf8");
|
||||||
|
const taskManagementDoc = readFileSync(taskManagementPath, "utf8");
|
||||||
|
|
||||||
|
test("architecture self-healing section documents already-merged review recovery layer", () => {
|
||||||
|
assert.ok(
|
||||||
|
architectureDoc.includes("recoverAlreadyMergedReviewTasks()"),
|
||||||
|
"Expected docs/architecture.md to mention recoverAlreadyMergedReviewTasks()",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
architectureDoc.includes("Together, `recoverAlreadyMergedReviewTasks()`, `clearStaleBlockedBy()`, and paused-aware in-review scheduling"),
|
||||||
|
"Expected architecture docs to describe the layered merge-deadlock self-healing defenses",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("task lifecycle docs describe preserved failed review state plus already-landed auto-finalization", () => {
|
||||||
|
assert.ok(
|
||||||
|
taskManagementDoc.includes("This state is intentionally preserved by recovery (not auto-bounced to `todo`)."),
|
||||||
|
"Expected task-management docs to preserve failed in-review tasks",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.match(
|
||||||
|
taskManagementDoc,
|
||||||
|
/Self-healing can still auto-finalize retry-exhausted failed review tasks[\s\S]*already landed on the merge target/,
|
||||||
|
"Expected task-management docs to explain already-landed failed-review auto-finalization",
|
||||||
|
);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user