wogiflow 2.20.0 → 2.20.1
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wogiflow",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.1",
|
|
4
4
|
"description": "AI-powered development workflow management system with multi-model support",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
12
|
"flow": "./scripts/flow",
|
|
13
|
-
"test": "NODE_ENV=test node --test tests/auto-compact-prompt.test.js tests/flow-paths.test.js tests/flow-io.test.js tests/flow-config-loader.test.js tests/flow-damage-control.test.js tests/flow-output.test.js tests/flow-constants.test.js tests/flow-session-state.test.js tests/flow-hooks-integration.test.js tests/flow-utils.test.js tests/flow-security.test.js tests/flow-memory-db.test.js tests/flow-durable-session.test.js tests/flow-skill-matcher.test.js tests/flow-bridge.test.js tests/flow-proactive-compact.test.js tests/flow-cascade-completion.test.js tests/flow-capture-gate.test.js tests/flow-correction-detector-hybrid.test.js tests/flow-promote.test.js tests/flow-archive-runs.test.js tests/flow-memory.test.js tests/flow-hooks-pre-tool-helpers.test.js tests/flow-hooks-bugfix-scope-gate.test.js tests/flow-hooks-routing-gate.test.js tests/flow-hooks-phase-read-gate.test.js tests/flow-hooks-commit-log-gate.test.js tests/flow-hooks-deploy-gate.test.js tests/flow-hooks-todowrite-gate.test.js tests/flow-hooks-git-safety-gate.test.js tests/flow-hooks-scope-mutation-gate.test.js tests/flow-hooks-strike-gate.test.js tests/flow-hooks-component-check.test.js tests/flow-hooks-scope-gate.test.js tests/flow-hooks-implementation-gate.test.js tests/flow-hooks-research-gate.test.js tests/flow-hooks-loop-check.test.js tests/flow-hooks-manager-boundary-gate.test.js tests/flow-hooks-phase-gate.test.js tests/flow-hooks-pre-tool-orchestrator.test.js tests/flow-hooks-observation-capture.test.js tests/flow-hooks-task-gate.test.js tests/flow-durable-session-suspension.test.js tests/flow-health-mcp-scopes.test.js tests/flow-lean-config.test.js tests/flow-workspace-autopickup.test.js && NODE_ENV=test node tests/run-quality-gates.test.js",
|
|
13
|
+
"test": "NODE_ENV=test node --test tests/auto-compact-prompt.test.js tests/flow-paths.test.js tests/flow-io.test.js tests/flow-config-loader.test.js tests/flow-damage-control.test.js tests/flow-output.test.js tests/flow-constants.test.js tests/flow-session-state.test.js tests/flow-hooks-integration.test.js tests/flow-utils.test.js tests/flow-security.test.js tests/flow-memory-db.test.js tests/flow-durable-session.test.js tests/flow-skill-matcher.test.js tests/flow-bridge.test.js tests/flow-proactive-compact.test.js tests/flow-cascade-completion.test.js tests/flow-capture-gate.test.js tests/flow-correction-detector-hybrid.test.js tests/flow-promote.test.js tests/flow-archive-runs.test.js tests/flow-memory.test.js tests/flow-hooks-pre-tool-helpers.test.js tests/flow-hooks-bugfix-scope-gate.test.js tests/flow-hooks-routing-gate.test.js tests/flow-hooks-phase-read-gate.test.js tests/flow-hooks-commit-log-gate.test.js tests/flow-hooks-deploy-gate.test.js tests/flow-hooks-todowrite-gate.test.js tests/flow-hooks-git-safety-gate.test.js tests/flow-hooks-scope-mutation-gate.test.js tests/flow-hooks-strike-gate.test.js tests/flow-hooks-component-check.test.js tests/flow-hooks-scope-gate.test.js tests/flow-hooks-implementation-gate.test.js tests/flow-hooks-research-gate.test.js tests/flow-hooks-loop-check.test.js tests/flow-hooks-manager-boundary-gate.test.js tests/flow-hooks-phase-gate.test.js tests/flow-hooks-pre-tool-orchestrator.test.js tests/flow-hooks-observation-capture.test.js tests/flow-hooks-task-gate.test.js tests/flow-durable-session-suspension.test.js tests/flow-health-mcp-scopes.test.js tests/flow-lean-config.test.js tests/flow-workspace-autopickup.test.js tests/flow-worker-boundary-gate.test.js && NODE_ENV=test node tests/run-quality-gates.test.js",
|
|
14
14
|
"test:syntax": "find scripts/ lib/ -name '*.js' -not -path '*/node_modules/*' -exec node --check {} +",
|
|
15
15
|
"lint": "eslint scripts/ lib/ tests/",
|
|
16
16
|
"lint:ci": "eslint scripts/ lib/ tests/ --max-warnings 0",
|
|
@@ -400,7 +400,9 @@ const CONFIG_DEFAULTS = {
|
|
|
400
400
|
_comment_autoPickupChannelDispatches: 'v2.20.0+: After task completion, if channel-dispatched tasks are queued in ready.json, the task-completed hook injects additionalContext instructing the AI to auto-invoke /wogi-start on the next queued task in the same turn. Prevents "Sauteed worker" silent stalls between queued dispatches. The Stop hook also blocks end-of-turn when queued dispatches exist but no task is in progress — making "awaiting signal" language mechanically impossible as a terminal state.',
|
|
401
401
|
autoPickupChannelDispatches: true,
|
|
402
402
|
_comment_diagnosticCurlBypass: 'v2.20.0+: When true, PreToolUse routing gate allows narrow curl-to-manager-port when replying to channel messages tagged INTROSPECTION or DIAGNOSTIC, with body starting "## ". Unblocks diagnostic round-trips without forcing fake task creation. Scope: localhost:8800 only.',
|
|
403
|
-
diagnosticCurlBypass: true
|
|
403
|
+
diagnosticCurlBypass: true,
|
|
404
|
+
_comment_blockAskUserQuestionInWorker: 'v2.20.1+: When true, PreToolUse blocks AskUserQuestion in workspace worker mode. The user only sees the manager terminal, so direct prompts from workers stall silently. Block message instructs channel-dispatch "## QUESTION:" to the manager. Closes the v2.20.0 gap where workers could still prompt the user directly when their queue was empty.',
|
|
405
|
+
blockAskUserQuestionInWorker: true
|
|
404
406
|
},
|
|
405
407
|
checkpoint: { enabled: false },
|
|
406
408
|
regressionTesting: { enabled: false },
|
|
@@ -215,6 +215,28 @@ function runPreToolGates(ctx, deps) {
|
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
+
// Worker boundary (v2.20.1) — parallel to manager boundary.
|
|
219
|
+
// Blocks tools that prompt the user directly (AskUserQuestion) in worker
|
|
220
|
+
// mode, since the user only sees the manager terminal. Forces workers to
|
|
221
|
+
// channel-dispatch ## QUESTION: to the manager instead.
|
|
222
|
+
if (process.env.WOGI_WORKSPACE_ROOT && process.env.WOGI_REPO_NAME && process.env.WOGI_REPO_NAME !== 'manager') {
|
|
223
|
+
try {
|
|
224
|
+
if (typeof deps.checkWorkerBoundary === 'function') {
|
|
225
|
+
const workerResult = deps.checkWorkerBoundary(toolName, toolInput, config);
|
|
226
|
+
if (workerResult.blocked) {
|
|
227
|
+
return {
|
|
228
|
+
allowed: false,
|
|
229
|
+
blocked: true,
|
|
230
|
+
reason: workerResult.reason,
|
|
231
|
+
message: workerResult.message,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
} catch (err) {
|
|
236
|
+
if (process.env.DEBUG) console.error(`[Hook] Worker boundary gate error (fail-open): ${err.message}`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
218
240
|
// Commit log gate
|
|
219
241
|
if (toolName === 'Bash' && toolInput.command) {
|
|
220
242
|
try {
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wogi Flow - Worker Boundary Gate (v2.20.1+)
|
|
5
|
+
*
|
|
6
|
+
* Mirror of manager-boundary-gate, but for workspace WORKERS.
|
|
7
|
+
*
|
|
8
|
+
* Problem this solves: a worker running in workspace mode cannot prompt the
|
|
9
|
+
* user directly — the user only sees the manager terminal. When a worker
|
|
10
|
+
* calls AskUserQuestion, its terminal shows a prompt nobody will ever type
|
|
11
|
+
* into. The worker stalls silently.
|
|
12
|
+
*
|
|
13
|
+
* Contract: in workspace worker mode, questions to the user MUST be
|
|
14
|
+
* channel-dispatched to the manager via `## QUESTION:`. The manager relays
|
|
15
|
+
* to the user, gets the answer, and channel-dispatches back.
|
|
16
|
+
*
|
|
17
|
+
* This gate blocks the `AskUserQuestion` tool in worker mode with a message
|
|
18
|
+
* giving the exact curl command to escalate properly.
|
|
19
|
+
*
|
|
20
|
+
* Scope:
|
|
21
|
+
* - Only fires in workspace worker mode (WOGI_WORKSPACE_ROOT +
|
|
22
|
+
* WOGI_REPO_NAME !== 'manager').
|
|
23
|
+
* - No-op in single-repo mode (no WOGI_WORKSPACE_ROOT).
|
|
24
|
+
* - No-op for the manager (manager SHOULD prompt the user — that is the
|
|
25
|
+
* manager's job).
|
|
26
|
+
* - Respects `config.workspace.blockAskUserQuestionInWorker` (default true).
|
|
27
|
+
*
|
|
28
|
+
* This is the missing piece after v2.20.0: v2.20.0 blocked hedging BETWEEN
|
|
29
|
+
* queued tasks but not worker-asks-user-directly when the queue is empty.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Check if a tool call violates worker-role boundaries.
|
|
34
|
+
*
|
|
35
|
+
* @param {string} toolName - Tool being called
|
|
36
|
+
* @param {Object} toolInput - Tool input parameters (unused for AskUserQuestion)
|
|
37
|
+
* @param {Object} [config] - Loaded config (optional)
|
|
38
|
+
* @returns {{ blocked: boolean, reason?: string, message?: string }}
|
|
39
|
+
*/
|
|
40
|
+
function checkWorkerBoundary(toolName, toolInput, config) {
|
|
41
|
+
// Only active in workspace worker mode.
|
|
42
|
+
if (!isWorkspaceWorker()) {
|
|
43
|
+
return { blocked: false };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Config toggle — default on.
|
|
47
|
+
if (config?.workspace?.blockAskUserQuestionInWorker === false) {
|
|
48
|
+
return { blocked: false };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Block list: tools that prompt the user directly.
|
|
52
|
+
// `AskUserQuestion` is the primary case — Claude Code's built-in
|
|
53
|
+
// interactive-question tool. If more user-prompting tools emerge, add them
|
|
54
|
+
// here (be surgical — only tools that actually expect a user reply).
|
|
55
|
+
const USER_PROMPT_TOOLS = new Set(['AskUserQuestion']);
|
|
56
|
+
|
|
57
|
+
if (!USER_PROMPT_TOOLS.has(toolName)) {
|
|
58
|
+
return { blocked: false };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const repoName = process.env.WOGI_REPO_NAME || 'worker';
|
|
62
|
+
const managerPort = process.env.WOGI_MANAGER_PORT || '8800';
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
blocked: true,
|
|
66
|
+
reason: 'worker-boundary-askuser',
|
|
67
|
+
message: [
|
|
68
|
+
`WORKER BOUNDARY: Cannot use ${toolName} in workspace worker mode.`,
|
|
69
|
+
'',
|
|
70
|
+
'The user ONLY sees the manager terminal. If you prompt the user here,',
|
|
71
|
+
'nobody will see it — your session will stall silently.',
|
|
72
|
+
'',
|
|
73
|
+
'Channel-dispatch the question to the manager instead:',
|
|
74
|
+
'',
|
|
75
|
+
` curl -s -X POST http://127.0.0.1:${managerPort} \\`,
|
|
76
|
+
` -H "X-Wogi-From: ${repoName}" \\`,
|
|
77
|
+
` --data-binary "## QUESTION: <your question for the user>"`,
|
|
78
|
+
'',
|
|
79
|
+
'The manager will relay to the user, capture the answer, and',
|
|
80
|
+
'channel-dispatch a follow-up task to you with the resolved context.',
|
|
81
|
+
'',
|
|
82
|
+
'If you genuinely do NOT need the user — make a reasonable decision',
|
|
83
|
+
'and note it in your reply to the manager (autonomous mode contract).'
|
|
84
|
+
].join('\n')
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Detect workspace worker mode. Requires both env vars:
|
|
90
|
+
* WOGI_WORKSPACE_ROOT — set by the worker spawn path
|
|
91
|
+
* WOGI_REPO_NAME — must NOT be 'manager'
|
|
92
|
+
*
|
|
93
|
+
* @returns {boolean}
|
|
94
|
+
*/
|
|
95
|
+
function isWorkspaceWorker() {
|
|
96
|
+
if (!process.env.WOGI_WORKSPACE_ROOT) return false;
|
|
97
|
+
const repo = process.env.WOGI_REPO_NAME;
|
|
98
|
+
if (!repo || repo === 'manager') return false;
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
module.exports = {
|
|
103
|
+
checkWorkerBoundary,
|
|
104
|
+
isWorkspaceWorker
|
|
105
|
+
};
|
|
@@ -48,6 +48,8 @@ let checkGitSafety = _noop;
|
|
|
48
48
|
try { checkGitSafety = require('../../core/git-safety-gate').checkGitSafety; } catch (_err) { if (process.env.DEBUG) console.error(`[Hook] Git safety gate not loaded: ${_err.message}`); }
|
|
49
49
|
let checkManagerBoundary = _noop;
|
|
50
50
|
try { checkManagerBoundary = require('../../core/manager-boundary-gate').checkManagerBoundary; } catch (_err) { if (process.env.DEBUG) console.error(`[Hook] Manager boundary gate not loaded: ${_err.message}`); }
|
|
51
|
+
let checkWorkerBoundary = _noop;
|
|
52
|
+
try { checkWorkerBoundary = require('../../core/worker-boundary-gate').checkWorkerBoundary; } catch (_err) { if (process.env.DEBUG) console.error(`[Hook] Worker boundary gate not loaded: ${_err.message}`); }
|
|
51
53
|
|
|
52
54
|
const { claudeCodeAdapter } = require('../../adapters/claude-code');
|
|
53
55
|
const { markSkillPending } = require('../../../flow-durable-session');
|
|
@@ -84,7 +86,7 @@ runHook('PreToolUse', async ({ input, parsedInput }) => {
|
|
|
84
86
|
recordPhaseRead, checkPhaseReadGate, clearPhaseReads,
|
|
85
87
|
checkDeployGate, checkWriteBlock,
|
|
86
88
|
checkStrikeGate, checkBugfixScope, checkScopeMutation,
|
|
87
|
-
checkGitSafety, checkManagerBoundary,
|
|
89
|
+
checkGitSafety, checkManagerBoundary, checkWorkerBoundary,
|
|
88
90
|
// Side-effect helpers
|
|
89
91
|
markSkillPending,
|
|
90
92
|
// Config + runtime
|