Block unverified external plan adoption without granting authority

This commit is contained in:
wassname2
2026-09-15 17:20:27 +08:00
parent 4599b5ad9f
commit ed050658e3
4 changed files with 45 additions and 35 deletions
+7 -9
View File
@@ -13,7 +13,6 @@ import { FOLD_LINE, foldPlan, GOAL_LINE, planRequirements as requirements } from
import { planViews } from "./plan-view.js";
import {
attachGoalPlanDescription,
attachNotice,
childPlanAttached,
childPlanRole,
completeGoalDescription,
@@ -311,12 +310,13 @@ export default function mainSupervisor(pi: ExtensionAPI) {
pi.sendUserMessage(prompt, { deliverAs: "followUp" });
} else pi.sendMessage({ customType: "pi-goals-supervision", content, display: true }, { deliverAs: "nextTurn" });
}
async function confirmOwnership(ctx: ExtensionContext, target: string, text: string, solo = true): Promise<boolean> {
async function confirmOwnership(ctx: ExtensionContext, target: string, text: string): Promise<boolean> {
if (target !== state.plan || state.mode === "chat") { ctx.ui.notify(nativeMessages.externalOwnershipUnknown(target, state.worker), "warning"); return false; }
if (opening) { ctx.ui.notify("A worker launch/resume is still pending; inspect its result before takeover.", "warning"); return false; }
const stamp = generation;
const revision = workerRevision;
const confirmation = solo ? "Worker confirmed stopped" : "Previous supervisor confirmed stopped";
const choice = await ctx.ui.select(solo ? "Confirm all other writers for the current and target plans are stopped (inspect Intercom and their native panes). A missing handle is not proof. Take over in this session?" : "Confirm no other supervisor owns this plan. Preserve any existing worker session and reconnect rather than starting another writer.", [confirmation, "Cancel"]);
const confirmation = "Worker confirmed stopped";
const choice = await ctx.ui.select("Confirm all other writers for the current and target plans are stopped (inspect Intercom and their native panes). A missing handle is not proof. Take over in this session?", [confirmation, "Cancel"]);
if (stamp !== generation || revision !== workerRevision) return false;
if (choice !== confirmation) return false;
if (readFileSync(target, "utf8") !== text) { ctx.ui.notify("Plan changed during takeover; confirm again.", "warning"); return false; }
@@ -695,14 +695,12 @@ export default function mainSupervisor(pi: ExtensionAPI) {
notice = true; fullPlanContextDue = true; refresh(ctx);
ctx.ui.notify(nativeMessages.samePlanRestored, "info"); return;
}
if (!solo && ((state.worker && !state.workerStopped) || state.mode === "supervising")) { ctx.ui.notify("Exit and resolve the existing worker before replacing the plan. The current plan is preserved.", "warning"); return; }
const noted = /^-\s*worker session:\s*(\S+)/im.exec(foldPlan(text))?.[1];
if (!(await confirmOwnership(ctx, target, text, solo))) return;
if (!(await confirmOwnership(ctx, target, text))) return;
const worker = noted ? { sessionFile: resolve(ctx.cwd, noted) } : state.workerStopped ? state.worker : undefined;
state = { mode: solo ? "solo" : "planning", plan: target, worker, workerStopped: solo || (!noted && state.workerStopped) };
state = { mode: "solo", plan: target, worker, workerStopped: true };
generation++; notice = true; fullPlanContextDue = true; save(); refresh(ctx); watchPlan(ctx);
if (solo) enterSolo(ctx);
else send(attachNotice(target, false, noted));
enterSolo(ctx);
return;
}
if (command === "exit") {
+4 -4
View File
@@ -263,11 +263,11 @@ export const soloRole = "Solo mode: implement the approved plan directly; do not
export function soloNotice(planPath: string): string {
return `User authorized solo work on ${planPath} after confirming no other writer remains. ${soloRole}`;
}
export function attachNotice(planPath: string, solo: boolean, notedWorker: string | undefined): string {
return `Attached to the existing plan ${planPath}; read it and its evidence without restarting completed work or re-deriving settled decisions. ${notedWorker ? `Recorded worker session: ${notedWorker}; inspect liveness before resume.` : ""} ${solo ? soloRole : "Present /goals review or /goals ready; no implementation before approval."}`;
}
export const nativeMessages = {
externalOwnershipUnknown: (path: string, worker?: { intercomId?: string; sessionFile?: string; paneId?: string; identity?: { paneId?: string } }) => {
const pane = worker?.identity?.paneId || worker?.paneId;
return `Cannot verify ownership of ${path}: the supported Intercom roster does not identify per-plan supervisors; a missing row is not exit proof. Original supervisor unknown. Current context and authority unchanged; no adoption or takeover authorized. Read-only inspection: read({path:${JSON.stringify(path)}}). ${worker ? `Current worker only (not proof of the target's owner): ${worker.intercomId ? `intercom action:list, locate exact ID ${worker.intercomId}. ` : ""}${worker.sessionFile ? `read({path:${JSON.stringify(worker.sessionFile)}}). ` : ""}${pane ? `herdr pane process-info --pane ${JSON.stringify(pane)}. ` : ""}` : ""}Use /goals status for current references. Return to the original supervisor's saved context only when independently identified; no target can be inferred here.`;
},
samePlanRestored: "Plan context refreshed; mode and worker binding unchanged. No new work authorized.",
workerPause: (paused: boolean) => `Worker ${paused ? "paused" : "unpaused"} locally; no new task submitted and no approval authority granted.`,
taskRequired: "Supply an explicit bounded proposed task for a new worker context.",