singularity-forge/src/resources/extensions/sf/commands/handlers/ops.js
2026-05-08 05:51:06 +02:00

460 lines
14 KiB
JavaScript

import { handleRemote } from "../../../remote-questions/mod.js";
import { getAutoSession } from "../../auto/session.js";
import { dispatchDirectPhase } from "../../auto-direct-dispatch.js";
import { handleConfig } from "../../commands-config.js";
import { handleDebug } from "../../commands-debug.js";
import { handleEscalate } from "../../commands-escalate.js";
import {
handleCapture,
handleDoctor,
handleKnowledge,
handleRunHook,
handleSkillHealth,
handleSteer,
handleTriage,
handleUpdate,
} from "../../commands-handlers.js";
import { handleInspect } from "../../commands-inspect.js";
import { handleLogs } from "../../commands-logs.js";
import {
handleCleanupBranches,
handleCleanupProjects,
handleCleanupSnapshots,
handleCleanupWorktrees,
handleRecover,
handleSkip,
} from "../../commands-maintenance.js";
import { handlePrBranch } from "../../commands-pr-branch.js";
import { handleRate } from "../../commands-rate.js";
import { handleSessionReport } from "../../commands-session-report.js";
import { handleShip } from "../../commands-ship.js";
import { handleExport } from "../../export.js";
import { handleHistory } from "../../history.js";
import { handleUndo } from "../../undo.js";
import { projectRoot } from "../context.js";
export async function handleOpsCommand(trimmed, ctx, pi) {
if (trimmed === "init") {
const { detectProjectState } = await import("../../detection.js");
const { handleReinit, showProjectInit } = await import(
"../../init-wizard.js"
);
const basePath = projectRoot();
const detection = detectProjectState(basePath);
if (detection.state === "v2-sf" || detection.state === "v2-sf-empty") {
await handleReinit(ctx, detection);
} else {
await showProjectInit(ctx, pi, basePath, detection);
}
return true;
}
if (trimmed === "keys" || trimmed.startsWith("keys ")) {
const { handleKeys } = await import("../../key-manager.js");
await handleKeys(trimmed.replace(/^keys\s*/, "").trim(), ctx);
return true;
}
if (trimmed === "doctor" || trimmed.startsWith("doctor ")) {
await handleDoctor(trimmed.replace(/^doctor\s*/, "").trim(), ctx, pi);
return true;
}
if (trimmed === "repair" || trimmed.startsWith("repair ")) {
const s = getAutoSession();
const args = trimmed.replace(/^repair\s*/, "").trim();
// Switch to repair work mode
const transition = s.setMode({ workMode: "repair" });
ctx.ui.notify(
`Repair mode: ${transition.from.workMode}${transition.to.workMode}`,
"info",
);
// If --autonomous flag, also set run control
if (args.includes("--autonomous")) {
s.setMode({ runControl: "autonomous" });
ctx.ui.notify(
"Repair will run autonomously until clean or blocked.",
"info",
);
}
// Run doctor diagnostics
await handleDoctor("fix", ctx, pi);
return true;
}
if (trimmed === "uok" || trimmed.startsWith("uok ")) {
const { handleUok } = await import("../../commands-uok.js");
await handleUok(trimmed.replace(/^uok\s*/, "").trim(), ctx);
return true;
}
if (trimmed === "logs" || trimmed.startsWith("logs ")) {
await handleLogs(trimmed.replace(/^logs\s*/, "").trim(), ctx);
return true;
}
if (trimmed === "debug" || trimmed.startsWith("debug ")) {
await handleDebug(trimmed.replace(/^debug\s*/, "").trim(), ctx, pi);
return true;
}
if (trimmed === "escalate" || trimmed.startsWith("escalate ")) {
await handleEscalate(trimmed.replace(/^escalate\s*/, "").trim(), ctx);
return true;
}
if (trimmed === "forensics" || trimmed.startsWith("forensics ")) {
const { handleForensics } = await import("../../forensics.js");
await handleForensics(trimmed.replace(/^forensics\s*/, "").trim(), ctx, pi);
return true;
}
if (trimmed === "scan" || trimmed.startsWith("scan ")) {
const { handleScan } = await import("../../commands-scan.js");
await handleScan(trimmed.replace(/^scan\s*/, "").trim(), ctx, pi);
return true;
}
if (trimmed === "changelog" || trimmed.startsWith("changelog ")) {
const { handleChangelog } = await import("../../changelog.js");
await handleChangelog(trimmed.replace(/^changelog\s*/, "").trim(), ctx, pi);
return true;
}
if (trimmed === "history" || trimmed.startsWith("history ")) {
await handleHistory(
trimmed.replace(/^history\s*/, "").trim(),
ctx,
projectRoot(),
);
return true;
}
if (trimmed === "undo-task" || trimmed.startsWith("undo-task ")) {
const { handleUndoTask } = await import("../../undo.js");
await handleUndoTask(
trimmed.replace(/^undo-task\s*/, "").trim(),
ctx,
pi,
projectRoot(),
);
return true;
}
if (trimmed === "reset-slice" || trimmed.startsWith("reset-slice ")) {
const { handleResetSlice } = await import("../../undo.js");
await handleResetSlice(
trimmed.replace(/^reset-slice\s*/, "").trim(),
ctx,
pi,
projectRoot(),
);
return true;
}
if (trimmed === "undo" || trimmed.startsWith("undo ")) {
await handleUndo(
trimmed.replace(/^undo\s*/, "").trim(),
ctx,
pi,
projectRoot(),
);
return true;
}
if (trimmed === "skip") {
ctx.ui.notify(
"Usage: /skip <unit-id> Example: /skip M001/S01/T03",
"warning",
);
return true;
}
if (trimmed.startsWith("skip ")) {
await handleSkip(
trimmed.replace(/^skip\s*/, "").trim(),
ctx,
projectRoot(),
);
return true;
}
if (trimmed === "recover") {
await handleRecover(ctx, projectRoot());
return true;
}
if (trimmed === "rate" || trimmed.startsWith("rate ")) {
await handleRate(
trimmed.replace(/^rate\s*/, "").trim(),
ctx,
projectRoot(),
);
return true;
}
if (trimmed === "export" || trimmed.startsWith("export ")) {
await handleExport(
trimmed.replace(/^export\s*/, "").trim(),
ctx,
projectRoot(),
);
return true;
}
if (
trimmed === "cleanup projects" ||
trimmed.startsWith("cleanup projects ")
) {
await handleCleanupProjects(
trimmed.replace(/^cleanup projects\s*/, "").trim(),
ctx,
);
return true;
}
if (trimmed === "cleanup worktrees") {
await handleCleanupWorktrees(ctx, projectRoot());
return true;
}
if (trimmed === "cleanup") {
await handleCleanupBranches(ctx, projectRoot());
await handleCleanupSnapshots(ctx, projectRoot());
return true;
}
if (trimmed === "cleanup branches") {
await handleCleanupBranches(ctx, projectRoot());
return true;
}
if (trimmed === "cleanup snapshots") {
await handleCleanupSnapshots(ctx, projectRoot());
return true;
}
if (trimmed.startsWith("capture ") || trimmed === "capture") {
await handleCapture(trimmed.replace(/^capture\s*/, "").trim(), ctx);
return true;
}
if (trimmed === "triage" || trimmed.startsWith("triage ")) {
await handleTriage(
trimmed.replace(/^triage\s*/, "").trim(),
ctx,
pi,
process.cwd(),
);
return true;
}
if (trimmed === "todo" || trimmed.startsWith("todo ")) {
const { handleTodo } = await import("../../commands-todo.js");
await handleTodo(trimmed.replace(/^todo\s*/, "").trim(), ctx, pi);
return true;
}
if (trimmed === "rate" || trimmed.startsWith("rate ")) {
const { handleRate } = await import("../../commands-rate.js");
await handleRate(
trimmed.replace(/^rate\s*/, "").trim(),
ctx,
process.cwd(),
);
return true;
}
if (trimmed === "config") {
await handleConfig(ctx);
return true;
}
if (trimmed === "hooks") {
const { formatHookStatus } = await import("../../post-unit-hooks.js");
ctx.ui.notify(formatHookStatus(), "info");
return true;
}
if (trimmed === "skill-health" || trimmed.startsWith("skill-health ")) {
await handleSkillHealth(
trimmed.replace(/^skill-health\s*/, "").trim(),
ctx,
);
return true;
}
if (trimmed.startsWith("run-hook ")) {
await handleRunHook(trimmed.replace(/^run-hook\s*/, "").trim(), ctx, pi);
return true;
}
if (trimmed === "run-hook") {
ctx.ui.notify(
`Usage: /run-hook <hook-name> <unit-type> <unit-id>
Unit types:
execute-task - Task execution (unit-id: M001/S01/T01)
plan-slice - Slice planning (unit-id: M001/S01)
research-milestone - Milestone research (unit-id: M001)
complete-slice - Slice completion (unit-id: M001/S01)
complete-milestone - Milestone completion (unit-id: M001)
Examples:
/run-hook code-review execute-task M001/S01/T01
/run-hook lint-check plan-slice M001/S01`,
"warning",
);
return true;
}
if (trimmed.startsWith("steer ")) {
await handleSteer(trimmed.replace(/^steer\s+/, "").trim(), ctx, pi);
return true;
}
if (trimmed === "steer") {
ctx.ui.notify(
"Usage: /steer <description of change>. Example: /steer Use Postgres instead of SQLite",
"warning",
);
return true;
}
if (trimmed.startsWith("knowledge ")) {
await handleKnowledge(trimmed.replace(/^knowledge\s+/, "").trim(), ctx);
return true;
}
if (trimmed === "knowledge") {
ctx.ui.notify(
"Usage: /knowledge <rule|pattern|lesson> <description>. Example: /knowledge rule Use real DB for integration tests",
"warning",
);
return true;
}
if (trimmed === "harness" || trimmed.startsWith("harness ")) {
const { handleHarness } = await import("../../commands-harness.js");
await handleHarness(trimmed.replace(/^harness\s*/, "").trim(), ctx);
return true;
}
if (trimmed === "solver-eval" || trimmed.startsWith("solver-eval ")) {
const { handleAutonomousSolverEval } = await import(
"../../autonomous-solver-eval.js"
);
await handleAutonomousSolverEval(
trimmed.replace(/^solver-eval\s*/, "").trim(),
ctx,
projectRoot(),
);
return true;
}
if (trimmed === "migrate" || trimmed.startsWith("migrate ")) {
const { handleMigrate } = await import("../../migrate/command.js");
await handleMigrate(trimmed.replace(/^migrate\s*/, "").trim(), ctx, pi);
return true;
}
if (trimmed === "remote" || trimmed.startsWith("remote ")) {
await handleRemote(trimmed.replace(/^remote\s*/, "").trim(), ctx, pi);
return true;
}
if (trimmed === "dispatch" || trimmed.startsWith("dispatch ")) {
const phase = trimmed.replace(/^dispatch\s*/, "").trim();
if (!phase) {
ctx.ui.notify(
"Usage: /dispatch <phase> (research|plan|execute|complete|reassess|uat|replan)",
"warning",
);
return true;
}
await dispatchDirectPhase(ctx, pi, phase, projectRoot());
return true;
}
if (trimmed === "notifications" || trimmed.startsWith("notifications ")) {
const { handleNotificationsCommand } = await import(
"./notifications-handler.js"
);
await handleNotificationsCommand(
trimmed.replace(/^notifications\s*/, "").trim(),
ctx,
pi,
);
return true;
}
if (trimmed === "inspect") {
await handleInspect(ctx);
return true;
}
if (trimmed === "update") {
await handleUpdate(ctx);
return true;
}
if (trimmed === "fast" || trimmed.startsWith("fast ")) {
const { handleFast } = await import("../../service-tier.js");
await handleFast(trimmed.replace(/^fast\s*/, "").trim(), ctx);
return true;
}
if (trimmed === "mcp" || trimmed.startsWith("mcp ")) {
const { handleMcpStatus } = await import("../../commands-mcp-status.js");
await handleMcpStatus(trimmed.replace(/^mcp\s*/, "").trim(), ctx);
return true;
}
if (trimmed === "extensions" || trimmed.startsWith("extensions ")) {
const { handleExtensions } = await import("../../commands-extensions.js");
await handleExtensions(trimmed.replace(/^extensions\s*/, "").trim(), ctx);
return true;
}
if (trimmed === "rethink") {
const { handleRethink } = await import("../../rethink.js");
await handleRethink(trimmed, ctx, pi);
return true;
}
if (trimmed === "codebase" || trimmed.startsWith("codebase ")) {
const { handleCodebase } = await import("../../commands-codebase.js");
await handleCodebase(trimmed.replace(/^codebase\s*/, "").trim(), ctx, pi);
return true;
}
if (trimmed === "ship" || trimmed.startsWith("ship ")) {
await handleShip(trimmed.replace(/^ship\s*/, "").trim(), ctx, pi);
return true;
}
if (trimmed === "session-report" || trimmed.startsWith("session-report ")) {
await handleSessionReport(
trimmed.replace(/^session-report\s*/, "").trim(),
ctx,
);
return true;
}
if (trimmed === "pr-branch" || trimmed.startsWith("pr-branch ")) {
await handlePrBranch(trimmed.replace(/^pr-branch\s*/, "").trim(), ctx);
return true;
}
if (trimmed === "add-tests" || trimmed.startsWith("add-tests ")) {
const { handleAddTests } = await import("../../commands-add-tests.js");
await handleAddTests(trimmed.replace(/^add-tests\s*/, "").trim(), ctx, pi);
return true;
}
if (trimmed === "scaffold sync" || trimmed.startsWith("scaffold sync ")) {
const { handleScaffoldSync } = await import(
"../../commands-scaffold-sync.js"
);
await handleScaffoldSync(
trimmed.replace(/^scaffold sync\s*/, "").trim(),
ctx,
);
return true;
}
if (trimmed === "scaffold") {
ctx.ui.notify(
"Usage: /scaffold sync [--dry-run] [--include-editing] [--only=<glob>]",
"warning",
);
return true;
}
if (
trimmed === "extract-learnings" ||
trimmed.startsWith("extract-learnings ")
) {
const { handleExtractLearnings } = await import(
"../../commands-extract-learnings.js"
);
await handleExtractLearnings(
trimmed.replace(/^extract-learnings\s*/, "").trim(),
ctx,
pi,
);
return true;
}
if (
trimmed === "worktree" ||
trimmed.startsWith("worktree ") ||
trimmed === "wt" ||
trimmed.startsWith("wt ")
) {
const { handleWorktree } = await import("../../commands-worktree.js");
await handleWorktree(trimmed.replace(/^(worktree|wt)\s*/, "").trim(), ctx);
return true;
}
if (trimmed === "eval-review" || trimmed.startsWith("eval-review ")) {
const { handleEvalReview } = await import("../../commands-eval-review.js");
await handleEvalReview(
trimmed.replace(/^eval-review\s*/, "").trim(),
ctx,
pi,
);
return true;
}
if (trimmed === "plan" || trimmed.startsWith("plan ")) {
const { handlePlan } = await import("../../commands-plan.js");
const handled = await handlePlan(
trimmed.replace(/^plan\s*/, "").trim(),
ctx,
);
if (handled) return true;
ctx.ui.notify("Usage: /plan promote|list|diff|specs ...", "info");
return true;
}
return false;
}