LearnNewsExamplesServices
Frontmatter
id12070
titleSub 4: runSandman.mjs delegation refactor with CLI mode-selector
stateClosed
labels
enhancementairefactoringmodel-experience
assigneesneo-gpt
createdAtMay 27, 2026, 3:42 AM
updatedAtMay 27, 2026, 9:11 PM
githubUrlhttps://github.com/neomjs/neo/issues/12070
authorneo-opus-ada
commentsCount1
parentIssue12065
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMay 27, 2026, 9:11 PM

Sub 4: runSandman.mjs delegation refactor with CLI mode-selector

Closed v13.0.0/archive-v13-0-0-chunk-14 enhancementairefactoringmodel-experience
neo-opus-ada
neo-opus-ada commented on May 27, 2026, 3:42 AM

Parent Epic

#12065 — Sub 4 of 9. Depends on Sub 3 (unified executeRemCycle() method).

Premise

Currently runSandman.mjs is 276 LOC carrying its own pipeline ceremony (lease + gates + diagnostic + exit-code choreography). After Sub 3 ships orchestrator-owned canonical execution, runSandman.mjs becomes a thin CLI selector delegating to the orchestrator.

Prescription

Refactor ai/scripts/runners/runSandman.mjs to ~30 LOC:

import {orchestratorService} from '...';

const mode = process.argv[2] || 'full';  // 'full' | 'refresh'
const reason = mode === 'refresh' ? 'manual-cli-refresh' : 'manual-cli';

try {
    if (mode === 'refresh') {
        await orchestratorService.refreshGoldenPath({reason});  // Sub 5
    } else {
        await orchestratorService.executeRemCycle({reason, includeGoldenPath: true});  // Sub 3
    }
    process.exit(0);
} catch (e) {
    console.error('❌ REM cycle failed:', e);
    process.exit(1);
}

Delete the 105 lines of pre-pipeline ceremony (lease, gates, diagnostics, exit-code choreography) — all now lives in orchestrator.

Add npm script ai:refresh-golden-path (or extend ai:run-sandman with mode argument) — operator-direct entry for the cheap-refresh path per Discussion §2.9.

Acceptance Criteria

  • AC1: runSandman.mjs reduced to thin CLI selector (~30 LOC; no business logic; no lease/gate/diagnostic code)
  • AC2: Mode-selector via argv supporting full (default) + refresh
  • AC3: Both modes delegate to orchestrator's canonical entry-points (Sub 3 + Sub 5)
  • AC4: Exit-code contract preserved (process.exit(0) on success, 1 on failure)
  • AC5: npm script for cheap-refresh path (npm run ai:refresh-golden-path OR npm run ai:run-sandman -- refresh)
  • AC6: Unit test covering both modes (mocking orchestrator)

Avoided Traps

  • ❌ Keep business logic in CLI — defeats SSOT purpose
  • ❌ Remove on-demand REM trigger — operator workflow falsifies (per §2.9)
  • ❌ Land before Sub 3 (no executeRemCycle to delegate to) OR before Sub 5 (no refreshGoldenPath to delegate to)

Related

  • Epic #12065
  • Discussion #12062 OQ1 + OQ2 (mode-selector) + OQ6 (minimum-viable-CLI) + §2.9 (split-and-recompose UX)
  • Sub 3 (executeRemCycle — input), Sub 5 (refreshGoldenPath — input)
tobiu referenced in commit 17c8ec6 - "feat(orchestrator): unified executeRemCycle() with typed cycle outcome (#12069) (#12096) on May 27, 2026, 6:10 PM
tobiu referenced in commit 57f5c6b - "fix(ai): delegate Sandman runner to REM cycle (#12070) (#12099) on May 27, 2026, 9:11 PM
tobiu closed this issue on May 27, 2026, 9:11 PM