oh-my-copilot 4.13.21 → 4.13.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +8 -0
- package/agents/code-reviewer.agent.md +24 -6
- package/agents/designer.agent.md +12 -0
- package/bridge/cli.cjs +2231 -1222
- package/bridge/mcp-server.cjs +678 -261
- package/bridge/runtime-cli.cjs +55 -8
- package/bridge/team.js +507 -38
- package/dist/__tests__/agent-registry.test.js +92 -1
- package/dist/__tests__/agent-registry.test.js.map +1 -1
- package/dist/__tests__/auto-slash-aliases.test.js +6 -6
- package/dist/__tests__/auto-slash-aliases.test.js.map +1 -1
- package/dist/__tests__/auto-update.test.js +132 -2
- package/dist/__tests__/auto-update.test.js.map +1 -1
- package/dist/__tests__/bedrock-model-routing.test.js +18 -17
- package/dist/__tests__/bedrock-model-routing.test.js.map +1 -1
- package/dist/__tests__/delegation-enforcer.test.js +46 -6
- package/dist/__tests__/delegation-enforcer.test.js.map +1 -1
- package/dist/__tests__/hooks/session-end-cleanup.test.d.ts +2 -0
- package/dist/__tests__/hooks/session-end-cleanup.test.d.ts.map +1 -0
- package/dist/__tests__/hooks/session-end-cleanup.test.js +93 -0
- package/dist/__tests__/hooks/session-end-cleanup.test.js.map +1 -0
- package/dist/__tests__/hud/stdin.test.d.ts +2 -0
- package/dist/__tests__/hud/stdin.test.d.ts.map +1 -0
- package/dist/__tests__/hud/stdin.test.js +556 -0
- package/dist/__tests__/hud/stdin.test.js.map +1 -0
- package/dist/__tests__/model-routing-override-three-site-sync.test.d.ts +2 -0
- package/dist/__tests__/model-routing-override-three-site-sync.test.d.ts.map +1 -0
- package/dist/__tests__/model-routing-override-three-site-sync.test.js +75 -0
- package/dist/__tests__/model-routing-override-three-site-sync.test.js.map +1 -0
- package/dist/__tests__/non-claude-provider-detection.test.js +37 -0
- package/dist/__tests__/non-claude-provider-detection.test.js.map +1 -1
- package/dist/__tests__/package-dir-resolution-regression.test.js +25 -0
- package/dist/__tests__/package-dir-resolution-regression.test.js.map +1 -1
- package/dist/__tests__/pre-tool-enforcer.test.js +304 -0
- package/dist/__tests__/pre-tool-enforcer.test.js.map +1 -1
- package/dist/__tests__/session-start-script-context.test.js +121 -0
- package/dist/__tests__/session-start-script-context.test.js.map +1 -1
- package/dist/__tests__/setup-claude-md-script.test.js +44 -1
- package/dist/__tests__/setup-claude-md-script.test.js.map +1 -1
- package/dist/__tests__/skills.test.js +77 -7
- package/dist/__tests__/skills.test.js.map +1 -1
- package/dist/__tests__/wiki-hook-output-format.test.d.ts +2 -0
- package/dist/__tests__/wiki-hook-output-format.test.d.ts.map +1 -0
- package/dist/__tests__/wiki-hook-output-format.test.js +59 -0
- package/dist/__tests__/wiki-hook-output-format.test.js.map +1 -0
- package/dist/agents/definitions.d.ts.map +1 -1
- package/dist/agents/definitions.js +2 -1
- package/dist/agents/definitions.js.map +1 -1
- package/dist/autoresearch/__tests__/decide-outcome.test.d.ts +2 -0
- package/dist/autoresearch/__tests__/decide-outcome.test.d.ts.map +1 -0
- package/dist/autoresearch/__tests__/decide-outcome.test.js +69 -0
- package/dist/autoresearch/__tests__/decide-outcome.test.js.map +1 -0
- package/dist/autoresearch/runtime.d.ts.map +1 -1
- package/dist/autoresearch/runtime.js +16 -2
- package/dist/autoresearch/runtime.js.map +1 -1
- package/dist/cli/__tests__/launch.test.js +23 -0
- package/dist/cli/__tests__/launch.test.js.map +1 -1
- package/dist/cli/__tests__/self-improve-paths.test.js +3 -2
- package/dist/cli/__tests__/self-improve-paths.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +100 -0
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/commands/__tests__/team-role-shorthand.test.js +30 -0
- package/dist/cli/commands/__tests__/team-role-shorthand.test.js.map +1 -1
- package/dist/cli/commands/__tests__/team.test.js +48 -1
- package/dist/cli/commands/__tests__/team.test.js.map +1 -1
- package/dist/cli/commands/team.d.ts +2 -0
- package/dist/cli/commands/team.d.ts.map +1 -1
- package/dist/cli/commands/team.js +9 -2
- package/dist/cli/commands/team.js.map +1 -1
- package/dist/cli/launch.d.ts.map +1 -1
- package/dist/cli/launch.js +7 -0
- package/dist/cli/launch.js.map +1 -1
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +34 -3
- package/dist/cli/team.js.map +1 -1
- package/dist/config/__tests__/loader.test.js +35 -4
- package/dist/config/__tests__/loader.test.js.map +1 -1
- package/dist/config/__tests__/models.test.js +126 -3
- package/dist/config/__tests__/models.test.js.map +1 -1
- package/dist/config/models.d.ts +8 -0
- package/dist/config/models.d.ts.map +1 -1
- package/dist/config/models.js +119 -8
- package/dist/config/models.js.map +1 -1
- package/dist/features/auto-update.d.ts.map +1 -1
- package/dist/features/auto-update.js +53 -5
- package/dist/features/auto-update.js.map +1 -1
- package/dist/features/delegation-enforcer.d.ts.map +1 -1
- package/dist/features/delegation-enforcer.js +10 -9
- package/dist/features/delegation-enforcer.js.map +1 -1
- package/dist/hooks/__tests__/bridge-routing.test.js +1 -0
- package/dist/hooks/__tests__/bridge-routing.test.js.map +1 -1
- package/dist/hooks/autopilot/enforcement.d.ts.map +1 -1
- package/dist/hooks/autopilot/enforcement.js +19 -0
- package/dist/hooks/autopilot/enforcement.js.map +1 -1
- package/dist/hooks/bridge.d.ts.map +1 -1
- package/dist/hooks/bridge.js +135 -4
- package/dist/hooks/bridge.js.map +1 -1
- package/dist/hooks/persistent-mode/index.d.ts +6 -0
- package/dist/hooks/persistent-mode/index.d.ts.map +1 -1
- package/dist/hooks/persistent-mode/index.js +96 -0
- package/dist/hooks/persistent-mode/index.js.map +1 -1
- package/dist/hooks/persistent-mode/stop-hook-blocking.test.js +152 -23
- package/dist/hooks/persistent-mode/stop-hook-blocking.test.js.map +1 -1
- package/dist/hooks/session-end/index.d.ts +9 -2
- package/dist/hooks/session-end/index.d.ts.map +1 -1
- package/dist/hooks/session-end/index.js +90 -35
- package/dist/hooks/session-end/index.js.map +1 -1
- package/dist/hud/stdin.d.ts +12 -1
- package/dist/hud/stdin.d.ts.map +1 -1
- package/dist/hud/stdin.js +123 -18
- package/dist/hud/stdin.js.map +1 -1
- package/dist/hud/types.d.ts +1 -0
- package/dist/hud/types.d.ts.map +1 -1
- package/dist/hud/types.js.map +1 -1
- package/dist/installer/__tests__/session-start-template.test.d.ts +2 -0
- package/dist/installer/__tests__/session-start-template.test.d.ts.map +1 -0
- package/dist/installer/__tests__/session-start-template.test.js +174 -0
- package/dist/installer/__tests__/session-start-template.test.js.map +1 -0
- package/dist/lib/__tests__/mode-state-io.test.js +75 -12
- package/dist/lib/__tests__/mode-state-io.test.js.map +1 -1
- package/dist/lib/mode-state-io.d.ts +11 -0
- package/dist/lib/mode-state-io.d.ts.map +1 -1
- package/dist/lib/mode-state-io.js +64 -0
- package/dist/lib/mode-state-io.js.map +1 -1
- package/dist/lib/worktree-paths.d.ts +12 -0
- package/dist/lib/worktree-paths.d.ts.map +1 -1
- package/dist/lib/worktree-paths.js +75 -0
- package/dist/lib/worktree-paths.js.map +1 -1
- package/dist/planning/__tests__/artifacts.test.d.ts +2 -0
- package/dist/planning/__tests__/artifacts.test.d.ts.map +1 -0
- package/dist/planning/__tests__/artifacts.test.js +486 -0
- package/dist/planning/__tests__/artifacts.test.js.map +1 -0
- package/dist/planning/artifact-names.d.ts +13 -0
- package/dist/planning/artifact-names.d.ts.map +1 -0
- package/dist/planning/artifact-names.js +108 -0
- package/dist/planning/artifact-names.js.map +1 -0
- package/dist/planning/artifacts.d.ts +47 -0
- package/dist/planning/artifacts.d.ts.map +1 -0
- package/dist/planning/artifacts.js +221 -0
- package/dist/planning/artifacts.js.map +1 -0
- package/dist/team/__tests__/api-interop.compatibility.test.js +194 -5
- package/dist/team/__tests__/api-interop.compatibility.test.js.map +1 -1
- package/dist/team/__tests__/model-contract.test.js +92 -2
- package/dist/team/__tests__/model-contract.test.js.map +1 -1
- package/dist/team/__tests__/runtime-v2.dispatch.test.js +30 -0
- package/dist/team/__tests__/runtime-v2.dispatch.test.js.map +1 -1
- package/dist/team/__tests__/scaling.test.js +39 -1
- package/dist/team/__tests__/scaling.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +6 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/api-interop.d.ts.map +1 -1
- package/dist/team/api-interop.js +89 -2
- package/dist/team/api-interop.js.map +1 -1
- package/dist/team/delegation-evidence.d.ts +5 -0
- package/dist/team/delegation-evidence.d.ts.map +1 -0
- package/dist/team/delegation-evidence.js +29 -0
- package/dist/team/delegation-evidence.js.map +1 -0
- package/dist/team/model-contract.d.ts +8 -0
- package/dist/team/model-contract.d.ts.map +1 -1
- package/dist/team/model-contract.js +13 -0
- package/dist/team/model-contract.js.map +1 -1
- package/dist/team/runtime-v2.d.ts +2 -1
- package/dist/team/runtime-v2.d.ts.map +1 -1
- package/dist/team/runtime-v2.js +3 -1
- package/dist/team/runtime-v2.js.map +1 -1
- package/dist/team/state/tasks.d.ts +4 -1
- package/dist/team/state/tasks.d.ts.map +1 -1
- package/dist/team/state/tasks.js +38 -1
- package/dist/team/state/tasks.js.map +1 -1
- package/dist/team/team-ops.d.ts +4 -1
- package/dist/team/team-ops.d.ts.map +1 -1
- package/dist/team/team-ops.js +2 -2
- package/dist/team/team-ops.js.map +1 -1
- package/dist/team/types.d.ts +22 -1
- package/dist/team/types.d.ts.map +1 -1
- package/dist/team/types.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +6 -1
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/dist/tools/__tests__/state-tools.test.js +322 -5
- package/dist/tools/__tests__/state-tools.test.js.map +1 -1
- package/dist/tools/__tests__/wiki-tools-working-directory.test.d.ts +2 -0
- package/dist/tools/__tests__/wiki-tools-working-directory.test.d.ts.map +1 -0
- package/dist/tools/__tests__/wiki-tools-working-directory.test.js +66 -0
- package/dist/tools/__tests__/wiki-tools-working-directory.test.js.map +1 -0
- package/dist/tools/state-tools.d.ts +3 -10
- package/dist/tools/state-tools.d.ts.map +1 -1
- package/dist/tools/state-tools.js +393 -91
- package/dist/tools/state-tools.js.map +1 -1
- package/dist/tools/wiki-tools.js +8 -8
- package/dist/tools/wiki-tools.js.map +1 -1
- package/docs/GETTING-STARTED.md +7 -0
- package/docs/REFERENCE.md +5 -5
- package/docs/copilot-instructions.md +1 -1
- package/package.json +1 -1
- package/scripts/lib/model-routing-override-message.mjs +21 -0
- package/scripts/persistent-mode.cjs +107 -0
- package/scripts/persistent-mode.mjs +102 -0
- package/scripts/post-tool-verifier.mjs +1 -0
- package/scripts/pre-tool-enforcer.mjs +163 -2
- package/scripts/session-start.mjs +63 -0
- package/scripts/setup-copilot-instructions.sh +12 -2
- package/scripts/wiki-pre-compact.mjs +1 -4
- package/skills/configure-notifications/SKILL.md +3 -3
- package/skills/deep-dive/SKILL.md +52 -4
- package/skills/deep-interview/SKILL.md +109 -15
- package/skills/mcp-setup/SKILL.md +60 -45
- package/skills/omc-setup/SKILL.md +3 -3
- package/skills/omc-setup/phases/01-install-claude-md.md +1 -1
- package/skills/omc-setup/phases/04-welcome.md +8 -8
- package/skills/plan/SKILL.md +1 -1
- package/skills/project-session-manager/SKILL.md +2 -2
- package/skills/project-session-manager/psm.sh +1 -1
- package/skills/ralplan/SKILL.md +2 -2
- package/templates/hooks/lib/model-routing-override-message.mjs +21 -0
- package/templates/hooks/persistent-mode.mjs +66 -0
- package/templates/hooks/session-start.mjs +62 -0
|
@@ -182,6 +182,7 @@ Do NOT skip this step. Do NOT move on without fixing the error.
|
|
|
182
182
|
* from causing the stop hook to malfunction in new sessions.
|
|
183
183
|
*/
|
|
184
184
|
const STALE_STATE_THRESHOLD_MS = 2 * 60 * 60 * 1000; // 2 hours
|
|
185
|
+
const PENDING_ASYNC_STATE_STALE_MS = 24 * 60 * 60 * 1000;
|
|
185
186
|
const CANCEL_SIGNAL_TTL_MS = 30_000;
|
|
186
187
|
const TEAM_TERMINAL_PHASES = new Set([
|
|
187
188
|
"completed",
|
|
@@ -229,6 +230,66 @@ function isStaleState(state) {
|
|
|
229
230
|
return age > STALE_STATE_THRESHOLD_MS;
|
|
230
231
|
}
|
|
231
232
|
|
|
233
|
+
|
|
234
|
+
function parseTimestamp(value) {
|
|
235
|
+
if (typeof value !== "string" || value.length === 0) return null;
|
|
236
|
+
const parsed = new Date(value).getTime();
|
|
237
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function isFreshTimestamp(value, ttlMs = PENDING_ASYNC_STATE_STALE_MS) {
|
|
241
|
+
const parsed = parseTimestamp(value);
|
|
242
|
+
return parsed !== null && Date.now() - parsed <= ttlMs;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function hasPendingBackgroundTask(stateDir, sessionId) {
|
|
246
|
+
const safeSessionId = sanitizeSessionId(sessionId);
|
|
247
|
+
const hudPath = safeSessionId
|
|
248
|
+
? join(stateDir, "sessions", safeSessionId, "hud-state.json")
|
|
249
|
+
: join(stateDir, "hud-state.json");
|
|
250
|
+
const hudState = readJsonFile(hudPath);
|
|
251
|
+
return Boolean(hudState?.backgroundTasks?.some((task) => {
|
|
252
|
+
if (task?.status !== "running") return false;
|
|
253
|
+
return isFreshTimestamp(task.startedAt ?? task.startTime);
|
|
254
|
+
}));
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function readPendingWakeupStates(stateDir, sessionId) {
|
|
258
|
+
const safeSessionId = sanitizeSessionId(sessionId);
|
|
259
|
+
const dirs = safeSessionId ? [join(stateDir, "sessions", safeSessionId), stateDir] : [stateDir];
|
|
260
|
+
const fileNames = ["scheduled-wakeup-state.json", "schedule-wakeup-state.json", "wakeup-state.json"];
|
|
261
|
+
const states = [];
|
|
262
|
+
for (const dir of dirs) {
|
|
263
|
+
for (const fileName of fileNames) {
|
|
264
|
+
const state = readJsonFile(join(dir, fileName));
|
|
265
|
+
if (state && typeof state === "object") states.push(state);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return states;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function hasPendingScheduledWakeup(stateDir, sessionId) {
|
|
272
|
+
const now = Date.now();
|
|
273
|
+
return readPendingWakeupStates(stateDir, sessionId).some((state) => {
|
|
274
|
+
const status = typeof state.status === "string" ? state.status.toLowerCase() : "";
|
|
275
|
+
if (["completed", "complete", "cancelled", "canceled", "failed", "expired"].includes(status)) {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
const dueAt = parseTimestamp(
|
|
279
|
+
state.due_at ?? state.wakeup_at ?? state.scheduled_for ?? state.deadline_at ?? state.expires_at,
|
|
280
|
+
);
|
|
281
|
+
if (dueAt !== null) return dueAt > now;
|
|
282
|
+
if (state.active === true || state.pending === true) {
|
|
283
|
+
return isFreshTimestamp(state.created_at ?? state.updated_at ?? state.started_at);
|
|
284
|
+
}
|
|
285
|
+
return false;
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function hasPendingOwnedAsyncWork(stateDir, sessionId) {
|
|
290
|
+
return hasPendingBackgroundTask(stateDir, sessionId) || hasPendingScheduledWakeup(stateDir, sessionId);
|
|
291
|
+
}
|
|
292
|
+
|
|
232
293
|
function normalizeTeamPhase(state) {
|
|
233
294
|
if (!state || typeof state !== "object") return null;
|
|
234
295
|
|
|
@@ -270,6 +331,36 @@ function isAwaitingConfirmation(state) {
|
|
|
270
331
|
return Date.now() - setAtMs < AWAITING_CONFIRMATION_TTL_MS;
|
|
271
332
|
}
|
|
272
333
|
|
|
334
|
+
function isOrphanedAutopilotRoutingEchoState(state) {
|
|
335
|
+
if (!state || typeof state !== "object") return false;
|
|
336
|
+
|
|
337
|
+
const phase = typeof state.phase === "string" ? state.phase.trim().toLowerCase() : "";
|
|
338
|
+
if (phase && phase !== "unspecified") return false;
|
|
339
|
+
|
|
340
|
+
const promptText = [
|
|
341
|
+
state.originalIdea,
|
|
342
|
+
state.original_idea,
|
|
343
|
+
state.prompt,
|
|
344
|
+
state.task_description,
|
|
345
|
+
]
|
|
346
|
+
.filter((value) => typeof value === "string")
|
|
347
|
+
.join("\n")
|
|
348
|
+
.trim();
|
|
349
|
+
|
|
350
|
+
return /^\[MAGIC KEYWORDS?(?: DETECTED)?:\s*AUTOPILOT\s*\]\s*$/i.test(promptText);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function clearLoadedStateFile(loaded) {
|
|
354
|
+
const statePath = loaded?.path;
|
|
355
|
+
if (!statePath || !existsSync(statePath)) return;
|
|
356
|
+
|
|
357
|
+
try {
|
|
358
|
+
unlinkSync(statePath);
|
|
359
|
+
} catch {
|
|
360
|
+
// Best effort: failing to clean an orphan should not re-arm stop blocking.
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
273
364
|
/**
|
|
274
365
|
* Normalize a path for comparison.
|
|
275
366
|
*/
|
|
@@ -721,6 +812,11 @@ async function main() {
|
|
|
721
812
|
return;
|
|
722
813
|
}
|
|
723
814
|
|
|
815
|
+
if (hasPendingOwnedAsyncWork(stateDir, sessionId)) {
|
|
816
|
+
console.log(JSON.stringify({ continue: true, suppressOutput: true }));
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
|
|
724
820
|
// Read all mode states (session-scoped when sessionId provided)
|
|
725
821
|
const ralph = readStateFileWithSession(
|
|
726
822
|
stateDir,
|
|
@@ -866,6 +962,12 @@ async function main() {
|
|
|
866
962
|
}
|
|
867
963
|
|
|
868
964
|
// Priority 2: Autopilot (high-level orchestration)
|
|
965
|
+
if (isOrphanedAutopilotRoutingEchoState(autopilot.state)) {
|
|
966
|
+
clearLoadedStateFile(autopilot);
|
|
967
|
+
console.log(JSON.stringify({ continue: true, suppressOutput: true }));
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
970
|
+
|
|
869
971
|
if (
|
|
870
972
|
autopilot.state?.active && !isAwaitingConfirmation(autopilot.state) &&
|
|
871
973
|
!isStaleState(autopilot.state) &&
|
|
@@ -710,6 +710,7 @@ export function isCopilotCliWriteSuccess(output) {
|
|
|
710
710
|
|
|
711
711
|
const cleaned = stripClaudeTempCwdErrors(output);
|
|
712
712
|
const successPatterns = [
|
|
713
|
+
/(^|\n)The file has been updated successfully\.?(\n|$)/i,
|
|
713
714
|
/(^|\n)The file .+ has been updated successfully\.?(\n|$)/i,
|
|
714
715
|
/(^|\n)File (?:created|written|updated) successfully(?:\s+at:\s*.+)?\.?(\n|$)/i,
|
|
715
716
|
/(^|\n).*file state is current in your context\b.*(\n|$)/i,
|
|
@@ -157,6 +157,152 @@ function readAgentDefinitionModel(subagentType) {
|
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
|
|
161
|
+
const SLOP_RISK_TOOL_NAMES = new Set([
|
|
162
|
+
'Task',
|
|
163
|
+
'TaskCreate',
|
|
164
|
+
'TaskUpdate',
|
|
165
|
+
'Agent',
|
|
166
|
+
'Bash',
|
|
167
|
+
'Edit',
|
|
168
|
+
'MultiEdit',
|
|
169
|
+
'Write',
|
|
170
|
+
'NotebookEdit',
|
|
171
|
+
]);
|
|
172
|
+
const SLOP_FALLBACK_LANGUAGE_PATTERN = /\b(?:fallback|fall\s+back|workaround|work\s+around)\b/i;
|
|
173
|
+
const SLOP_FALLBACK_ACTION_PATTERNS = [
|
|
174
|
+
/\b(?:add|build|create|implement|introduce|make|patch|use|using|write)\s+(?:an?\s+|the\s+)?(?:fallback|workaround)\b/i,
|
|
175
|
+
/\b(?:fallback|workaround)\s+(?:layer|path|handler|shim|patch|implementation|mechanism|mode)\b/i,
|
|
176
|
+
/\bworkaround\s+(?:it|this|that|the|a|an)\b/i,
|
|
177
|
+
/\b(?:fall\s+back|fallback)\s+(?:to|on|onto)\b/i,
|
|
178
|
+
/\bwork\s+around\s+(?:it|this|that|the|a|an)\b/i,
|
|
179
|
+
/\bwork\s+around\s+(?!(?:it|this|that|the|a|an)\b)(?:[a-z0-9][\w-]*\s+){0,5}[a-z0-9][\w-]*\b/i,
|
|
180
|
+
/(?:^|[\s"'`=:/\\])[\w.-]*(?:fallback|workaround)[\w.-]*\.(?:cjs|js|mjs|py|sh|ts|tsx)\b/i,
|
|
181
|
+
];
|
|
182
|
+
const SLOP_BENIGN_TECHNICAL_PATTERNS = [
|
|
183
|
+
/\bfail[-\s]?soft\s+fallback(?:\s+(?:value|behavior|behaviour|result|semantics?))?\b/i,
|
|
184
|
+
/\bfallback\s+(?:value|variable|parameter|argument|option|setting|config(?:uration)?|default)\b/i,
|
|
185
|
+
/\bfallback\s+to\s+(?:the\s+)?default(?:\s+(?:config(?:uration)?|settings?|value|behavior|behaviour|option))?\b/i,
|
|
186
|
+
/\b(?:workaround|work\s+around)\s+for\s+(?:commit|change|issue|bug|regression|version|release|pr|pull\s+request|#[0-9]+|[a-f0-9]{7,40}\b)/i,
|
|
187
|
+
/\b(?:memory|sql|sqlite|mysql|postgres(?:ql)?|typescript|node|browser|runtime)\s+workaround\b/i,
|
|
188
|
+
];
|
|
189
|
+
const SLOP_DOC_CONTEXT_PATTERN = /(?:^|[/\\])(?:docs?|documentation|guides?|instructions?|prompts?|\.om[ctx])(?:[/\\]|$)|\.(?:md|mdx|txt|rst)$/i;
|
|
190
|
+
const SLOP_SELF_REFERENCE_PATH_PATTERN = /(?:^|[/\\])(?:pre-tool-enforcer(?:\.mjs)?|pre-tool-enforcer\.test\.ts)(?:$|[/\\])/i;
|
|
191
|
+
|
|
192
|
+
function collectStringValues(value, output = [], depth = 0) {
|
|
193
|
+
if (depth > 5 || output.length > 100) return output;
|
|
194
|
+
if (typeof value === 'string') {
|
|
195
|
+
output.push(value);
|
|
196
|
+
return output;
|
|
197
|
+
}
|
|
198
|
+
if (Array.isArray(value)) {
|
|
199
|
+
for (const item of value) collectStringValues(item, output, depth + 1);
|
|
200
|
+
return output;
|
|
201
|
+
}
|
|
202
|
+
if (value && typeof value === 'object') {
|
|
203
|
+
for (const [key, child] of Object.entries(value)) {
|
|
204
|
+
// Skip hook/runtime metadata so warnings are driven by user-authored tool intent.
|
|
205
|
+
if (/^(cwd|directory|session_?id|transcript_?path|hook_event_name)$/i.test(key)) continue;
|
|
206
|
+
collectStringValues(child, output, depth + 1);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return output;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function collectLikelyPathValues(value, output = [], depth = 0) {
|
|
213
|
+
if (depth > 5 || output.length > 100 || !value || typeof value !== 'object') return output;
|
|
214
|
+
if (Array.isArray(value)) {
|
|
215
|
+
for (const item of value) collectLikelyPathValues(item, output, depth + 1);
|
|
216
|
+
return output;
|
|
217
|
+
}
|
|
218
|
+
for (const [key, child] of Object.entries(value)) {
|
|
219
|
+
if (typeof child === 'string' && /(?:^|_)(?:file_?path|path|filename|target|command)$/i.test(key)) {
|
|
220
|
+
output.push(child);
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
collectLikelyPathValues(child, output, depth + 1);
|
|
224
|
+
}
|
|
225
|
+
return output;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function stripSlopQuotedAndCodeContexts(text) {
|
|
229
|
+
return text
|
|
230
|
+
.replace(/```[\s\S]*?```/g, '\n')
|
|
231
|
+
.replace(/`[^`\r\n]*`/g, ' ')
|
|
232
|
+
.replace(/(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/g, ' ');
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function splitSlopInspectionSegments(text) {
|
|
236
|
+
return text
|
|
237
|
+
.split(/[\r\n!?;]+/)
|
|
238
|
+
.map(segment => segment.trim())
|
|
239
|
+
.filter(Boolean);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function removeBenignTechnicalSlopFallbackSpans(text) {
|
|
243
|
+
return SLOP_BENIGN_TECHNICAL_PATTERNS.reduce(
|
|
244
|
+
(result, pattern) => {
|
|
245
|
+
const flags = pattern.flags.includes('g') ? pattern.flags : `${pattern.flags}g`;
|
|
246
|
+
return result.replace(new RegExp(pattern.source, flags), ' ');
|
|
247
|
+
},
|
|
248
|
+
text,
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function hasSlopFallbackActionShape(text) {
|
|
253
|
+
const strippedText = stripSlopQuotedAndCodeContexts(text);
|
|
254
|
+
return splitSlopInspectionSegments(strippedText).some(segment => (
|
|
255
|
+
SLOP_FALLBACK_ACTION_PATTERNS.some(pattern => (
|
|
256
|
+
pattern.test(removeBenignTechnicalSlopFallbackSpans(segment))
|
|
257
|
+
))
|
|
258
|
+
));
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function isSelfReferentialSlopContext(toolInput) {
|
|
262
|
+
return collectLikelyPathValues(toolInput).some(value => SLOP_SELF_REFERENCE_PATH_PATTERN.test(value));
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function isDocumentationSlopContext(toolInput) {
|
|
266
|
+
const pathLikeValues = collectLikelyPathValues(toolInput);
|
|
267
|
+
return pathLikeValues.some(value => SLOP_DOC_CONTEXT_PATTERN.test(value));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function shouldWarnForSlopFallbackLanguage(data, toolName, inspectedText) {
|
|
271
|
+
if (!SLOP_RISK_TOOL_NAMES.has(toolName)) return false;
|
|
272
|
+
if (!SLOP_FALLBACK_LANGUAGE_PATTERN.test(inspectedText)) return false;
|
|
273
|
+
|
|
274
|
+
const toolInput = data.toolInput || data.tool_input || {};
|
|
275
|
+
if (isSelfReferentialSlopContext(toolInput)) return false;
|
|
276
|
+
if (isDocumentationSlopContext(toolInput)) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return hasSlopFallbackActionShape(inspectedText);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function generateSlopWarning(data, toolName) {
|
|
284
|
+
const toolInput = data.toolInput || data.tool_input || {};
|
|
285
|
+
const promptLikeFields = {
|
|
286
|
+
prompt: data.prompt,
|
|
287
|
+
userPrompt: data.userPrompt,
|
|
288
|
+
user_prompt: data.user_prompt,
|
|
289
|
+
message: data.message,
|
|
290
|
+
};
|
|
291
|
+
const inspectedText = collectStringValues(toolInput)
|
|
292
|
+
.concat(collectStringValues(promptLikeFields))
|
|
293
|
+
.join('\n');
|
|
294
|
+
if (!shouldWarnForSlopFallbackLanguage(data, toolName, inspectedText)) return '';
|
|
295
|
+
|
|
296
|
+
return '[SLOP WARNING] Detected fallback/workaround language in this tool input. ' +
|
|
297
|
+
'Do not make potential slop: avoid ad-hoc fallback layers, workaround shims, or environment-specific patches unless explicitly justified. ' +
|
|
298
|
+
'For architecture concerns, consult the architect for a concrete design first. ' +
|
|
299
|
+
'If this seems environment-specific, ask the user to confirm constraints before proceeding.';
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function combineHookMessages(...messages) {
|
|
303
|
+
return messages.filter(Boolean).join('\n\n');
|
|
304
|
+
}
|
|
305
|
+
|
|
160
306
|
const SESSION_ID_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,255}$/;
|
|
161
307
|
const MODE_STATE_FILES = [
|
|
162
308
|
'autopilot-state.json',
|
|
@@ -169,6 +315,14 @@ const MODE_STATE_FILES = [
|
|
|
169
315
|
'omc-teams-state.json',
|
|
170
316
|
];
|
|
171
317
|
const QUIET_LEVEL = getQuietLevel();
|
|
318
|
+
const BUILT_IN_TASK_LIST_TOOL_NAMES = new Set([
|
|
319
|
+
'TaskCreate',
|
|
320
|
+
'TaskUpdate',
|
|
321
|
+
'TaskList',
|
|
322
|
+
'TaskGet',
|
|
323
|
+
'TaskOutput',
|
|
324
|
+
'TaskStop',
|
|
325
|
+
]);
|
|
172
326
|
|
|
173
327
|
function getQuietLevel() {
|
|
174
328
|
const parsed = Number.parseInt(process.env.OMC_QUIET || '0', 10);
|
|
@@ -882,7 +1036,7 @@ async function main() {
|
|
|
882
1036
|
|
|
883
1037
|
const todoStatus = getTodoStatus(directory);
|
|
884
1038
|
|
|
885
|
-
if (toolName === 'Task' || toolName === '
|
|
1039
|
+
if (toolName === 'Task' || toolName === 'Agent') {
|
|
886
1040
|
const rawTranscriptPath = data.transcript_path || data.transcriptPath || '';
|
|
887
1041
|
const transcriptPath = resolveTranscriptPath(rawTranscriptPath, directory);
|
|
888
1042
|
const preflightBlock = evaluateAgentHeavyPreflight({
|
|
@@ -895,13 +1049,20 @@ async function main() {
|
|
|
895
1049
|
}
|
|
896
1050
|
}
|
|
897
1051
|
|
|
1052
|
+
const slopWarning = generateSlopWarning(data, toolName);
|
|
898
1053
|
let message;
|
|
899
|
-
if (toolName
|
|
1054
|
+
if (BUILT_IN_TASK_LIST_TOOL_NAMES.has(toolName)) {
|
|
1055
|
+
console.log(JSON.stringify({ continue: true, suppressOutput: true }));
|
|
1056
|
+
return;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
if (toolName === 'Task' || toolName === 'Agent') {
|
|
900
1060
|
const toolInput = data.toolInput || data.tool_input || null;
|
|
901
1061
|
message = generateAgentSpawnMessage(toolInput, stateDir, todoStatus, sessionId);
|
|
902
1062
|
} else {
|
|
903
1063
|
message = generateMessage(toolName, todoStatus, modeActive);
|
|
904
1064
|
}
|
|
1065
|
+
message = combineHookMessages(slopWarning, message);
|
|
905
1066
|
|
|
906
1067
|
if (!message) {
|
|
907
1068
|
console.log(JSON.stringify({ continue: true, suppressOutput: true }));
|
|
@@ -335,6 +335,69 @@ const SESSION_END_MODE_STATE_FILES = [
|
|
|
335
335
|
'skill-active-state.json',
|
|
336
336
|
];
|
|
337
337
|
|
|
338
|
+
import { MODEL_ROUTING_OVERRIDE_MESSAGE } from './lib/model-routing-override-message.mjs';
|
|
339
|
+
export { MODEL_ROUTING_OVERRIDE_MESSAGE };
|
|
340
|
+
|
|
341
|
+
function isTruthyProviderFlag(value) {
|
|
342
|
+
return value === '1' || value === 'true';
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function getSessionModelId() {
|
|
346
|
+
return process.env.CLAUDE_MODEL || process.env.ANTHROPIC_MODEL || '';
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function isBedrockSession() {
|
|
350
|
+
if (isTruthyProviderFlag(process.env.CLAUDE_CODE_USE_BEDROCK)) return true;
|
|
351
|
+
const modelId = getSessionModelId();
|
|
352
|
+
return Boolean(
|
|
353
|
+
modelId && (
|
|
354
|
+
/^((us|eu|ap|global)\.anthropic\.|anthropic\.claude)/i.test(modelId) ||
|
|
355
|
+
(
|
|
356
|
+
/^arn:aws(-[^:]+)?:bedrock:/i.test(modelId) &&
|
|
357
|
+
/:(inference-profile|application-inference-profile)\//i.test(modelId) &&
|
|
358
|
+
modelId.toLowerCase().includes('claude')
|
|
359
|
+
)
|
|
360
|
+
)
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function isVertexSession() {
|
|
365
|
+
if (isTruthyProviderFlag(process.env.CLAUDE_CODE_USE_VERTEX)) return true;
|
|
366
|
+
const modelId = getSessionModelId();
|
|
367
|
+
return Boolean(modelId && modelId.toLowerCase().startsWith('vertex_ai/'));
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function readRoutingForceInheritFromConfig(directory) {
|
|
371
|
+
const configPaths = [
|
|
372
|
+
join(configDir, '.omc-config.json'),
|
|
373
|
+
join(directory, '.omc', 'config.json'),
|
|
374
|
+
];
|
|
375
|
+
|
|
376
|
+
for (const configPath of configPaths) {
|
|
377
|
+
const config = readJsonFile(configPath);
|
|
378
|
+
if (config?.routing?.forceInherit === true) return true;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function shouldEmitModelRoutingOverride(directory) {
|
|
385
|
+
if (process.env.OMC_ROUTING_FORCE_INHERIT === 'true') return true;
|
|
386
|
+
if (process.env.OMC_ROUTING_FORCE_INHERIT === 'false') return false;
|
|
387
|
+
if (readRoutingForceInheritFromConfig(directory)) return true;
|
|
388
|
+
|
|
389
|
+
if (isBedrockSession() || isVertexSession()) return true;
|
|
390
|
+
|
|
391
|
+
const modelId = getSessionModelId();
|
|
392
|
+
if (modelId && !modelId.toLowerCase().includes('claude')) return true;
|
|
393
|
+
|
|
394
|
+
const baseUrl = process.env.ANTHROPIC_BASE_URL || '';
|
|
395
|
+
if (baseUrl && !baseUrl.includes('anthropic.com')) return true;
|
|
396
|
+
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
|
|
338
401
|
function compactBudgetedText(text, maxChars) {
|
|
339
402
|
const notice = '\n...[truncated to preserve SessionStart context budget]';
|
|
340
403
|
if (!text || text.length <= maxChars) return text || '';
|
|
@@ -105,7 +105,16 @@ ensure_local_omc_git_exclude() {
|
|
|
105
105
|
local block_start="# BEGIN OMC local artifacts"
|
|
106
106
|
|
|
107
107
|
if [ -f "$exclude_path" ] && grep -Fq "$block_start" "$exclude_path"; then
|
|
108
|
-
|
|
108
|
+
if grep -Fxq ".omx/" "$exclude_path"; then
|
|
109
|
+
echo "OMC git exclude already configured"
|
|
110
|
+
return 0
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
if [ -s "$exclude_path" ]; then
|
|
114
|
+
printf '\n' >> "$exclude_path"
|
|
115
|
+
fi
|
|
116
|
+
printf '.omx/\n' >> "$exclude_path"
|
|
117
|
+
echo "Updated OMC git exclude for local OMX artifacts"
|
|
109
118
|
return 0
|
|
110
119
|
fi
|
|
111
120
|
|
|
@@ -119,10 +128,11 @@ ensure_local_omc_git_exclude() {
|
|
|
119
128
|
.omcp/*
|
|
120
129
|
!.omcp/skills/
|
|
121
130
|
!.omcp/skills/**
|
|
131
|
+
.omx/
|
|
122
132
|
# END OMC local artifacts
|
|
123
133
|
EOF
|
|
124
134
|
|
|
125
|
-
echo "Configured git exclude for local
|
|
135
|
+
echo "Configured git exclude for local OMC/OMX artifacts (preserving .omcp/skills/)"
|
|
126
136
|
}
|
|
127
137
|
|
|
128
138
|
# Determine target path
|
|
@@ -10,10 +10,7 @@ async function main() {
|
|
|
10
10
|
if (result.additionalContext) {
|
|
11
11
|
console.log(JSON.stringify({
|
|
12
12
|
continue: true,
|
|
13
|
-
|
|
14
|
-
hookEventName: 'PreCompact',
|
|
15
|
-
additionalContext: result.additionalContext,
|
|
16
|
-
},
|
|
13
|
+
systemMessage: result.additionalContext,
|
|
17
14
|
}));
|
|
18
15
|
} else {
|
|
19
16
|
console.log(JSON.stringify({ continue: true, suppressOutput: true }));
|
|
@@ -239,7 +239,7 @@ Telegram Notifications Configured!
|
|
|
239
239
|
Format: Markdown
|
|
240
240
|
Events: session-end, ask-user-question
|
|
241
241
|
|
|
242
|
-
Config saved to: ~/.copilot/.
|
|
242
|
+
Config saved to: ~/.copilot/.omc-config.json
|
|
243
243
|
|
|
244
244
|
You can also set these via environment variables:
|
|
245
245
|
OMC_TELEGRAM_BOT_TOKEN=123456789:ABCdefGHI...
|
|
@@ -481,7 +481,7 @@ Discord Notifications Configured!
|
|
|
481
481
|
Events: session-end, ask-user-question
|
|
482
482
|
Username: OMC
|
|
483
483
|
|
|
484
|
-
Config saved to: ~/.copilot/.
|
|
484
|
+
Config saved to: ~/.copilot/.omc-config.json
|
|
485
485
|
|
|
486
486
|
You can also set these via environment variables:
|
|
487
487
|
OMC_DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...
|
|
@@ -728,7 +728,7 @@ Slack Notifications Configured!
|
|
|
728
728
|
Events: session-end, ask-user-question
|
|
729
729
|
Username: OMC
|
|
730
730
|
|
|
731
|
-
Config saved to: ~/.copilot/.
|
|
731
|
+
Config saved to: ~/.copilot/.omc-config.json
|
|
732
732
|
|
|
733
733
|
You can also set these via environment variables:
|
|
734
734
|
OMC_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
|
|
@@ -7,8 +7,8 @@ triggers:
|
|
|
7
7
|
- "deep-dive"
|
|
8
8
|
- "trace and interview"
|
|
9
9
|
- "investigate deeply"
|
|
10
|
-
pipeline: [deep-dive,
|
|
11
|
-
next-skill:
|
|
10
|
+
pipeline: [deep-dive, plan, autopilot]
|
|
11
|
+
next-skill: plan
|
|
12
12
|
next-skill-args: --consensus --direct
|
|
13
13
|
handoff: .omcp/specs/deep-dive-{slug}.md
|
|
14
14
|
---
|
|
@@ -138,6 +138,12 @@ Use **Claude built-in team mode** to run 3 parallel tracer lanes:
|
|
|
138
138
|
- Rank evidence strength (from controlled reproductions → speculation)
|
|
139
139
|
- Name the **critical unknown** for the lane
|
|
140
140
|
- Recommend the best **discriminating probe**
|
|
141
|
+
- For **Lane 3: Misplacement / SoT Violation** findings, classify every candidate MOVE destination with `ownership_scope` before ranking recommendations:
|
|
142
|
+
- `personal-config`: user-level dotfiles, `[$CLAUDE_CONFIG_DIR|~/.claude]/`, personal repositories, or user-only agent rules
|
|
143
|
+
- `shared-config`: company/org repositories, team-maintained config, or multi-tenant shared rules
|
|
144
|
+
- `external`: third-party, vendor, or OSS upstream repositories outside the user's ownership
|
|
145
|
+
- `project-scoped`: per-project storage owned by the current project boundary
|
|
146
|
+
- For Lane 3, compare source and destination `ownership_scope`; any cross-boundary MOVE (for example `personal-config` → `shared-config`) MUST be flagged with an explicit warning and MUST NOT be surfaced as the default recommendation. Prefer COMPRESS, KEEP, or a same-scope MOVE as the default when available.
|
|
141
147
|
4. **Run a rebuttal round** between the leading hypothesis and the strongest alternative
|
|
142
148
|
5. **Detect convergence**: if two "different" hypotheses reduce to the same mechanism, merge them explicitly
|
|
143
149
|
6. **Leader synthesis**: produce the ranked output below
|
|
@@ -176,6 +182,15 @@ Save to `.omcp/specs/deep-dive-trace-{slug}.md`:
|
|
|
176
182
|
- **Lane 2 ({hypothesis_2})**: {critical_unknown_2}
|
|
177
183
|
- **Lane 3 ({hypothesis_3})**: {critical_unknown_3}
|
|
178
184
|
|
|
185
|
+
## Lane 3 Misplacement / SoT Ownership Scope
|
|
186
|
+
For each MOVE candidate discovered by Lane 3, include:
|
|
187
|
+
|
|
188
|
+
| Source | Candidate destination | ownership_scope | Boundary relationship | Default? | Warning |
|
|
189
|
+
|--------|-----------------------|-----------------|-----------------------|----------|---------|
|
|
190
|
+
| ... | ... | personal-config/shared-config/external/project-scoped | same-scope/cross-boundary | yes/no | ... |
|
|
191
|
+
|
|
192
|
+
Cross-boundary MOVE candidates MUST have `Default? = no` and an explicit warning explaining the source/destination ownership mismatch. They may be listed as flagged alternatives, but the ranked synthesis MUST NOT present them as the default recommendation.
|
|
193
|
+
|
|
179
194
|
## Rebuttal Round
|
|
180
195
|
- Best rebuttal to leader: ...
|
|
181
196
|
- Why leader held / failed: ...
|
|
@@ -274,7 +289,36 @@ When ambiguity ≤ the resolved threshold for this run, generate the spec in **s
|
|
|
274
289
|
|
|
275
290
|
Read `spec_path` and `trace_path` from state (not conversation context) for resume resilience.
|
|
276
291
|
|
|
277
|
-
|
|
292
|
+
### Workflow Pre-Flight
|
|
293
|
+
|
|
294
|
+
Before presenting execution options, run a lightweight workflow pre-flight when active project guidance mentions an issue-driven, worktree-driven, branch-first, or blocking pre-execution workflow. Treat guidance text as policy data from the user's environment; do not invent a gate when no such guidance is present.
|
|
295
|
+
|
|
296
|
+
1. **Detect whether the guidance gate applies** by scanning the active project instructions already in context (for example `AGENTS.md`, `CLAUDE.md`, project docs, or hook-injected guidance) for phrases such as `issue-driven`, `worktree-driven`, `worktree`, `create issue`, `branch`, `do not write code`, `blocking requirement`, or equivalent workflow rules.
|
|
297
|
+
2. **Check repository position** with read-only commands:
|
|
298
|
+
- `git rev-parse --show-toplevel` to confirm the repository root for the pending execution.
|
|
299
|
+
- `git branch --show-current` to identify the current branch; flag protected/default branches such as `main`, `master`, or `dev`.
|
|
300
|
+
- `git worktree list --porcelain` to distinguish a linked task worktree from the primary checkout when possible; flag a primary checkout or missing linked worktree when the guidance requires task worktrees.
|
|
301
|
+
3. **Check for a linked issue** when the guidance is issue-driven:
|
|
302
|
+
- First look for an explicit issue reference in `spec_path`, `trace_path`, the current branch name, and the original task text.
|
|
303
|
+
- If no local reference is found and `gh` is available, optionally run a narrow `gh issue list --limit 20 --json number,title,state` search for a matching open issue.
|
|
304
|
+
- If no issue can be linked, flag `missing linked issue`; do not block on `gh` being unavailable.
|
|
305
|
+
4. **If any precondition is missing**, surface a setup redirect before the execution menu:
|
|
306
|
+
|
|
307
|
+
**Question:** "Spec ready (ambiguity: {score}%). Detected workflow pre-flight issue(s): {findings}. Project guidance appears to require issue/branch/worktree setup before code execution. Set that up first?"
|
|
308
|
+
|
|
309
|
+
**Options:**
|
|
310
|
+
|
|
311
|
+
- **Set up issue/branch/worktree first (Recommended)**
|
|
312
|
+
- Description: "Redirect to the project's setup workflow before any execution skill writes code."
|
|
313
|
+
- Action: Invoke the known project setup skill or workflow if one is named in guidance; otherwise invoke `Skill("oh-my-claudecode:project-session-manager")` with `spec_path` and the pre-flight findings as context. After setup completes, rerun this Phase 5 pre-flight before showing execution options.
|
|
314
|
+
- **Proceed to execution options anyway**
|
|
315
|
+
- Description: "Acknowledge the workflow warning and continue to the normal execution menu."
|
|
316
|
+
- Action: Continue to the execution options below, preserving the warning in handoff context.
|
|
317
|
+
- **Refine further**
|
|
318
|
+
- Description: "Return to Phase 4 interview loop instead of preparing execution."
|
|
319
|
+
- Action: Return to Phase 4 interview loop.
|
|
320
|
+
|
|
321
|
+
If the guidance gate does not apply, or the pre-flight passes, present execution options via `AskUserQuestion`:
|
|
278
322
|
|
|
279
323
|
**Question:** "Your spec is ready (ambiguity: {score}%). How would you like to proceed?"
|
|
280
324
|
|
|
@@ -282,7 +326,7 @@ Present execution options via `AskUserQuestion`:
|
|
|
282
326
|
|
|
283
327
|
1. **Ralplan → Autopilot (Recommended)**
|
|
284
328
|
- Description: "3-stage pipeline: consensus-refine this spec with Planner/Architect/Critic, then execute with full autopilot. Maximum quality."
|
|
285
|
-
- Action: Invoke `Skill("oh-my-copilot:
|
|
329
|
+
- Action: Invoke `Skill("oh-my-copilot:plan")` with `--consensus --direct` flags and the spec file path (`spec_path` from state) as context. The `--direct` flag skips the omc-plan skill's interview phase (the deep-dive interview already gathered requirements), while `--consensus` triggers the Planner/Architect/Critic loop. When consensus completes and produces a plan in `.omcp/plans/`, invoke `Skill("oh-my-copilot:autopilot")` with the consensus plan as Phase 0+1 output — autopilot skips both Expansion and Planning, starting directly at Phase 2 (Execution).
|
|
286
330
|
- Pipeline: `deep-dive spec → omc-plan --consensus --direct → autopilot execution`
|
|
287
331
|
|
|
288
332
|
2. **Execute with autopilot (skip ralplan)**
|
|
@@ -326,6 +370,7 @@ Output: spec.md Output: consensus-plan.md Output: working code
|
|
|
326
370
|
- Use `state_write(mode="deep-interview")` with `state.source = "deep-dive"` for all state persistence
|
|
327
371
|
- Use `state_read(mode="deep-interview")` for resume — check `state.source === "deep-dive"` to distinguish
|
|
328
372
|
- Use `Write` tool to save trace result to `.omcp/specs/deep-dive-trace-{slug}.md` and final spec to `.omcp/specs/deep-dive-{slug}.md`; use `.omcp/state/` or `state_write` for ephemeral artifacts
|
|
373
|
+
- Run the Phase 5 workflow pre-flight before execution options when project guidance requires issue/branch/worktree setup
|
|
329
374
|
- Use `Skill()` to bridge to execution modes (Phase 5) — never implement directly
|
|
330
375
|
- Wrap all trace-derived text in `<trace-context>` delimiters when injecting into prompts
|
|
331
376
|
</Tool_Usage>
|
|
@@ -421,12 +466,15 @@ Why bad: Duplicates deep-interview's behavioral contract. These values should be
|
|
|
421
466
|
- [ ] Phase 2 confirms hypotheses via AskUserQuestion (1 round)
|
|
422
467
|
- [ ] Phase 3 runs trace with 3 parallel lanes (team mode, sequential fallback)
|
|
423
468
|
- [ ] Phase 3 saves trace result to `.omcp/specs/deep-dive-trace-{slug}.md` with per-lane critical unknowns
|
|
469
|
+
- [ ] Lane 3 MOVE candidates include `ownership_scope` and cross-boundary MOVE candidates are warned/flagged, not default recommendations
|
|
424
470
|
- [ ] Phase 4 starts with 3-point injection (initial_idea, codebase_context, question_queue from per-lane unknowns)
|
|
425
471
|
- [ ] Phase 4 references deep-interview SKILL.md Phases 2-4 (not duplicated inline)
|
|
426
472
|
- [ ] Phase 4 handles low-confidence trace gracefully
|
|
427
473
|
- [ ] Phase 4 wraps trace-derived text in `<trace-context>` delimiters (untrusted data guard)
|
|
428
474
|
- [ ] Final spec saved to `.omcp/specs/deep-dive-{slug}.md` in standard deep-interview format
|
|
429
475
|
- [ ] Final spec contains "Trace Findings" section
|
|
476
|
+
- [ ] Phase 5 workflow pre-flight detects issue/worktree/branch preconditions when project guidance requires them
|
|
477
|
+
- [ ] Phase 5 surfaces a setup redirect before execution options when the pre-flight finds missing preconditions
|
|
430
478
|
- [ ] Phase 5 execution bridge passes spec_path explicitly to downstream skills
|
|
431
479
|
- [ ] Phase 5 "Ralplan → Autopilot" option explicitly invokes autopilot after omc-plan consensus completes
|
|
432
480
|
- [ ] State uses `mode="deep-interview"` with `state.source = "deep-dive"` discriminator
|