wogiflow 2.22.0 → 2.22.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/.claude/commands/wogi-start.md +3 -3
- package/.claude/commands/wogi-story.md +27 -0
- package/.claude/docs/claude-code-compatibility.md +32 -1
- package/lib/workspace-dispatch-tracking.js +175 -0
- package/lib/workspace-messages.js +1 -0
- package/lib/workspace-routing.js +17 -0
- package/package.json +2 -2
- package/scripts/flow-config-defaults.js +9 -0
- package/scripts/flow-story-gates.js +504 -0
- package/scripts/flow-story.js +205 -7
- package/scripts/hooks/adapters/claude-code.js +18 -37
- package/scripts/hooks/core/overdue-dispatches.js +159 -0
- package/scripts/hooks/entry/claude-code/stop.js +92 -47
- package/scripts/hooks/entry/claude-code/user-prompt-submit.js +18 -0
|
@@ -180,18 +180,18 @@ When epic creation adds 2+ stories to ready.json and `config.bulkOrchestrator.en
|
|
|
180
180
|
|
|
181
181
|
Non-blocking if transition fails.
|
|
182
182
|
|
|
183
|
-
### Effort Level Optimization (Claude Code 2.1.72+)
|
|
183
|
+
### Effort Level Optimization (Claude Code 2.1.72+, xhigh added 2.1.111+)
|
|
184
184
|
|
|
185
185
|
After task level classification (L0-L3), set the reasoning effort level to optimize token usage:
|
|
186
186
|
|
|
187
187
|
| Task Level | Effort | Rationale |
|
|
188
188
|
|------------|--------|-----------|
|
|
189
|
-
| L0 (Epic) | high | Complex planning, multi-file architecture |
|
|
189
|
+
| L0 (Epic) | high (xhigh on Opus 4.7 for deep architectural reasoning) | Complex planning, multi-file architecture |
|
|
190
190
|
| L1 (Story) | high | Multi-criteria implementation |
|
|
191
191
|
| L2 (Task) | medium | Standard 1-5 file changes |
|
|
192
192
|
| L3 (Subtask) | low | Single file, trivial change |
|
|
193
193
|
|
|
194
|
-
This is advisory
|
|
194
|
+
This is advisory. Claude Code's effort levels: `low` / `medium` / `high` are universal. Claude Code 2.1.111+ added `xhigh` (between high and max) and `max` as Opus 4.7-only levels — other models fall back to `high`. Use `/effort` interactively (slider as of 2.1.111) to switch mid-session. The AI should adjust reasoning depth during implementation phases accordingly.
|
|
195
195
|
|
|
196
196
|
### Task Checkpoints (when `config.proactiveCompaction.enabled`)
|
|
197
197
|
|
|
@@ -8,11 +8,38 @@ Run `./scripts/flow story "<title>"` to create a story.
|
|
|
8
8
|
|
|
9
9
|
Load `agents/story-writer.md` for the full story format.
|
|
10
10
|
|
|
11
|
+
## Anti-Deferral Rule (MANDATORY)
|
|
12
|
+
|
|
13
|
+
**Every item the user provides MUST become a work item** (criterion or sub-task). Never silently filter items. If you believe an item should be deferred, **ASK the user** — do not decide autonomously.
|
|
14
|
+
|
|
15
|
+
For multi-item inputs, the command output MUST include: **"All {N} items captured as {criteria|sub-tasks}."** If any item cannot be mapped, the "Unmapped" warning must be surfaced, not suppressed.
|
|
16
|
+
|
|
17
|
+
This rule applies equally to deep-decomposition mode and flat stories.
|
|
18
|
+
|
|
19
|
+
## Specification-Quality Gates (wf-63c0f4cc)
|
|
20
|
+
|
|
21
|
+
Five P0 gates run automatically at creation time (all fail-open):
|
|
22
|
+
|
|
23
|
+
| Gate | Fires When | Effect |
|
|
24
|
+
|------|-----------|--------|
|
|
25
|
+
| 1. Long Input | input ≥40 lines OR ≥5 discrete items | routes to `/wogi-extract-review` |
|
|
26
|
+
| 2. Item Reconciliation | input has ≥3 discrete items | writes manifest, verifies coverage |
|
|
27
|
+
| 3. Consumer Impact | input contains refactor/rename/migrate/etc. | greps consumers, flags phased migration at ≥5 breaking |
|
|
28
|
+
| 4. Scope-Confidence | input mentions "new X" / "existing Y" / "the Z service" | audits assumptions → "Pending Clarifications" block |
|
|
29
|
+
| 5. Intent Bootstrap | IGR artifacts missing + not already scheduled | schedules background bootstrap via session-state.json |
|
|
30
|
+
|
|
31
|
+
Gates enforce **specification quality at creation time**; runtime-quality gates (wiring, typecheck, tests) remain `/wogi-start`'s job.
|
|
32
|
+
|
|
33
|
+
Config: `storyFlow.consumerImpactAnalysis`, `storyFlow.scopeConfidenceAudit`, `storyFlow.itemReconciliation`. All default-true.
|
|
34
|
+
|
|
11
35
|
## Options
|
|
12
36
|
|
|
13
37
|
- `--deep` - Enable deep decomposition mode (auto-generate granular sub-tasks)
|
|
14
38
|
- `--priority <P>` - Set priority P0-P4 (default: P2 from config)
|
|
15
39
|
- `--json` - Output JSON for programmatic access
|
|
40
|
+
- `--skip-gates` - Skip all P0 gates (testing/debug only)
|
|
41
|
+
- `--bypass-long-input` - Skip Gate 1 (set by `/wogi-start` when it already routed long input)
|
|
42
|
+
- `--full-input <txt>` - Full user input for gates (when title is a summary)
|
|
16
43
|
|
|
17
44
|
Examples:
|
|
18
45
|
```bash
|
|
@@ -408,6 +408,37 @@ await cancelTask('wf-123', 'superseded', false);
|
|
|
408
408
|
|
|
409
409
|
- **Hardened "Open in editor" against command injection**: Security hardening for untrusted filenames. **Impact on WogiFlow**: Validates the same pattern in `.claude/rules/security/security-patterns.md` — external inputs going into shell commands must be validated. No WogiFlow code change needed.
|
|
410
410
|
|
|
411
|
+
### Features in 2.1.111+
|
|
412
|
+
|
|
413
|
+
- **`xhigh` effort level for Opus 4.7**: New effort level sitting between `high` and `max`, available via `/effort`, `--effort`, and the model picker. Other models fall back to `high`. `/effort` now opens an interactive slider when called without arguments. **Impact on WogiFlow**: The effort-level mapping in `wogi-start.md` now acknowledges `xhigh`/`max` as Opus 4.7-only. For L0 epics running on Opus 4.7, users may prefer `xhigh` over `high` for deeper architectural reasoning — the mapping table documents this as an option. No code change needed; the mapping is advisory.
|
|
414
|
+
|
|
415
|
+
- **`/ultrareview` built-in command**: Claude Code now ships a native `/ultrareview` that runs parallel multi-agent analysis and critique in the cloud — invoke with no arguments to review the current branch, or `/ultrareview <PR#>` to fetch and review a specific GitHub PR. **Relationship to WogiFlow's review commands**: No collision (`wogi-*` prefix). How to choose:
|
|
416
|
+
- `/ultrareview` — cloud-side parallel multi-agent critique. Zero local setup. Best for standalone branch/PR reviews when you don't have peer models configured.
|
|
417
|
+
- `/wogi-peer-review` — uses the peer models you configured via `/wogi-models-setup` (local/BYO models). Best when you want specific perspectives (e.g., a different vendor's model) or offline/cost-controlled review.
|
|
418
|
+
- `/wogi-review` — single-reviewer code review wired into WogiFlow task state (findings logged to `last-review.json`, triaged via `/wogi-triage`). Best for in-flow review during task execution.
|
|
419
|
+
- `/wogi-review-fix` — auto-applies fixes from `/wogi-review` findings.
|
|
420
|
+
Users can combine them: run `/ultrareview` for a wide-angle cloud critique, then `/wogi-review` for task-linked findings.
|
|
421
|
+
|
|
422
|
+
- **`/less-permission-prompts` built-in skill**: Scans recent transcripts for common read-only Bash and MCP tool calls and proposes a prioritized allowlist for `.claude/settings.json`. **Relationship to WogiFlow**: Complementary to `computeLeanConfig()` in `lib/installer.js` — the installer produces a minimal allowlist at install time, while `/less-permission-prompts` tunes the allowlist based on actual session usage. Suggested workflow: after a few WogiFlow sessions, run `/less-permission-prompts` to prune redundant prompts. Future opportunity: surface this suggestion in `/wogi-health` output.
|
|
423
|
+
|
|
424
|
+
- **Auto-allow for read-only bash with globs and `cd <project-dir> &&` prefix**: Read-only commands like `ls *.ts` and commands starting with `cd <project-dir> &&` no longer trigger a permission prompt. **Impact on WogiFlow**: Reduces prompts during WogiFlow hook-driven validation (lint/typecheck) and user-driven exploration. Allowlist rules in `lib/installer.js` that duplicated these patterns are now redundant — minor cleanup opportunity (tracked, low priority). No action required; the installer's lean-config approach already avoids over-emitting.
|
|
425
|
+
|
|
426
|
+
- **Auto mode for Max subscribers on Opus 4.7**: Auto mode is now available for Max subscribers when using Opus 4.7, and no longer requires `--enable-auto-mode`. 2.1.112 fixed a "claude-opus-4-7 is temporarily unavailable" error in auto mode. **Impact on WogiFlow**: WogiFlow's model registry already lists Opus 4.7 (v2.22.0); auto-mode routing is orthogonal to WogiFlow's hybrid mode. Users on Max with Opus 4.7 benefit automatically.
|
|
427
|
+
|
|
428
|
+
- **`OTEL_LOG_RAW_API_BODIES` env var**: Emits full API request and response bodies as OpenTelemetry log events for debugging. **Impact on WogiFlow**: Useful when debugging hybrid mode (`/wogi-hybrid`) routing and peer-review (`/wogi-peer-review`) model calls — set this env var to see the exact payloads reaching each model. Complements WogiFlow's gate telemetry (`/wogi-gate-stats`) which tracks pass/catch/miss rates at a higher level. Set with: `export OTEL_LOG_RAW_API_BODIES=1`. Note: payloads may contain sensitive data — only enable in development.
|
|
429
|
+
|
|
430
|
+
- **Headless `--output-format stream-json` includes `plugin_errors` on init**: Plugin demotion errors (unsatisfied dependencies, conflicting versions) are now surfaced on the init event in headless mode. **WogiFlow opportunity**: `/wogi-health` could read this stream when running in CI/headless mode to flag plugin-registry issues before they cause silent failures. Tracked as an enhancement.
|
|
431
|
+
|
|
432
|
+
- **Opus 4.7 availability fix (2.1.112)**: Fixed a "claude-opus-4-7 is temporarily unavailable" error in auto mode. Aligned with WogiFlow v2.22.0 registry update. No WogiFlow code change needed.
|
|
433
|
+
|
|
434
|
+
- **Windows improvements**: `CLAUDE_ENV_FILE` and SessionStart hook environment files now apply on Windows (previously a no-op). Permission rules with drive-letter paths are now correctly root-anchored, and paths differing only by drive-letter case are recognized as the same path. **Impact on WogiFlow**: Windows users of WogiFlow's SessionStart hook can now configure environment variables via `CLAUDE_ENV_FILE`. Drive-letter-path permission rules generated by the installer now behave correctly. Automatic improvement after upgrade.
|
|
435
|
+
|
|
436
|
+
- **Miscellaneous UX**: Plan files named after the originating prompt (e.g. `fix-auth-race-snug-otter.md`), `/skills` menu supports sorting by estimated token count (press `t`), Ctrl+U clears the entire input buffer (Ctrl+Y restores), Ctrl+L forces a full redraw, and typo suggestions on near-miss subcommands. Documentation-only for WogiFlow.
|
|
437
|
+
|
|
438
|
+
- **Fixed "Unknown skill: commit" error**: Users without a custom `/commit` skill were seeing this error when Claude Code tried to invoke a non-existent built-in. **Impact on WogiFlow**: No WogiFlow-shipped `/commit` skill (commits go through `/wogi-finalize` and git commit instructions). Users benefit passively from the fix.
|
|
439
|
+
|
|
440
|
+
- **Reliability fixes (all automatic after upgrade)**: Terminal display tearing in iTerm2+tmux, `@`-file suggestions re-scanning entire project in non-git directories, LSP diagnostics from before an edit appearing after it, tab-completing `/resume` behavior, `/context` grid rendering, `/clear` dropping session name, spurious decompression/network/transient errors in the TUI. Reverted v2.1.110 cap on non-streaming fallback retries (now uncapped again). Fixed Bedrock/Vertex/Foundry 429 retries pointing users at the wrong status page, bare URLs unclickable when wrapped in tool output, feedback surveys appearing back-to-back. WogiFlow sessions benefit from all of these automatically.
|
|
441
|
+
|
|
411
442
|
### Simple Mode Naming Distinction
|
|
412
443
|
|
|
413
444
|
Claude Code's `CLAUDE_CODE_SIMPLE` environment variable (which enables a simplified tool set) is **unrelated** to WogiFlow's `loops.simpleMode` (a lightweight task completion loop using string detection). They are separate features that happen to share the word "simple":
|
|
@@ -542,4 +573,4 @@ Run `/keybindings` in Claude Code to customize your shortcuts.
|
|
|
542
573
|
|
|
543
574
|
---
|
|
544
575
|
|
|
545
|
-
*Last updated: 2026-04-
|
|
576
|
+
*Last updated: 2026-04-17*
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wogi Workspace — Dispatch Tracking (wf-d3e67abe)
|
|
5
|
+
*
|
|
6
|
+
* Silent-worker-halt detection via file-based dispatch records.
|
|
7
|
+
*
|
|
8
|
+
* Manager records every dispatch; any pending dispatch past its
|
|
9
|
+
* expectedDeadline without a matching completion/stop message =
|
|
10
|
+
* silent death. Surfaced on the next manager turn via the
|
|
11
|
+
* UserPromptSubmit hook (no background processes).
|
|
12
|
+
*
|
|
13
|
+
* State file: .workspace/state/dispatched-tasks.json
|
|
14
|
+
* Ring buffer of last MAX_ACTIVE records; older overflow to
|
|
15
|
+
* .workspace/state/dispatched-tasks.archive.jsonl (append-only).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const fs = require('node:fs');
|
|
19
|
+
const path = require('node:path');
|
|
20
|
+
const { safeReadJson } = require('./utils');
|
|
21
|
+
|
|
22
|
+
const DEFAULT_DURATION_MS = 30 * 60 * 1000; // 30 min — matches waitForCompletion default
|
|
23
|
+
const MAX_ACTIVE = 100;
|
|
24
|
+
const SCHEMA_VERSION = 1;
|
|
25
|
+
|
|
26
|
+
const VALID_STATUSES = new Set(['pending', 'completed', 'graceful-stop', 'silent-halt']);
|
|
27
|
+
|
|
28
|
+
function stateFilePath(workspaceRoot) {
|
|
29
|
+
return path.join(workspaceRoot, '.workspace', 'state', 'dispatched-tasks.json');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function archiveFilePath(workspaceRoot) {
|
|
33
|
+
return path.join(workspaceRoot, '.workspace', 'state', 'dispatched-tasks.archive.jsonl');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function loadState(workspaceRoot) {
|
|
37
|
+
const data = safeReadJson(stateFilePath(workspaceRoot), null);
|
|
38
|
+
if (data && typeof data === 'object' && Array.isArray(data.dispatches)) {
|
|
39
|
+
return { version: data.version || SCHEMA_VERSION, dispatches: data.dispatches };
|
|
40
|
+
}
|
|
41
|
+
return { version: SCHEMA_VERSION, dispatches: [] };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function saveState(workspaceRoot, state) {
|
|
45
|
+
const filePath = stateFilePath(workspaceRoot);
|
|
46
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
47
|
+
fs.writeFileSync(filePath, JSON.stringify(state, null, 2));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function archiveRecord(workspaceRoot, record) {
|
|
51
|
+
const filePath = archiveFilePath(workspaceRoot);
|
|
52
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
53
|
+
fs.appendFileSync(filePath, JSON.stringify(record) + '\n');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Record a dispatch. Appends to state and trims ring buffer.
|
|
58
|
+
*
|
|
59
|
+
* @param {string} workspaceRoot
|
|
60
|
+
* @param {Object} params
|
|
61
|
+
* @param {string} params.taskId - wf-XXXXXXXX
|
|
62
|
+
* @param {string} params.repoName
|
|
63
|
+
* @param {number} [params.expectedDurationMs=DEFAULT_DURATION_MS]
|
|
64
|
+
* @param {string} [params.dispatchedBy='manager']
|
|
65
|
+
* @returns {Object} the created record
|
|
66
|
+
*/
|
|
67
|
+
function recordDispatch(workspaceRoot, { taskId, repoName, expectedDurationMs, dispatchedBy }) {
|
|
68
|
+
if (!workspaceRoot || typeof workspaceRoot !== 'string') {
|
|
69
|
+
throw new Error('workspaceRoot required');
|
|
70
|
+
}
|
|
71
|
+
if (!/^wf-[0-9a-f]{8}$/i.test(taskId || '')) {
|
|
72
|
+
throw new Error(`Invalid taskId: ${taskId}`);
|
|
73
|
+
}
|
|
74
|
+
if (!repoName || typeof repoName !== 'string') {
|
|
75
|
+
throw new Error('repoName required');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const durationMs = Number.isFinite(expectedDurationMs) && expectedDurationMs > 0
|
|
79
|
+
? expectedDurationMs
|
|
80
|
+
: DEFAULT_DURATION_MS;
|
|
81
|
+
const now = Date.now();
|
|
82
|
+
const dispatchedAt = new Date(now).toISOString();
|
|
83
|
+
const expectedDeadline = new Date(now + durationMs).toISOString();
|
|
84
|
+
|
|
85
|
+
const record = {
|
|
86
|
+
taskId,
|
|
87
|
+
repoName,
|
|
88
|
+
dispatchedAt,
|
|
89
|
+
expectedDeadline,
|
|
90
|
+
expectedDurationMs: durationMs,
|
|
91
|
+
status: 'pending',
|
|
92
|
+
dispatchedBy: dispatchedBy || 'manager',
|
|
93
|
+
reconciledAt: null,
|
|
94
|
+
reconciledReason: null
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const state = loadState(workspaceRoot);
|
|
98
|
+
state.dispatches.push(record);
|
|
99
|
+
|
|
100
|
+
// Ring buffer: overflow oldest records to archive
|
|
101
|
+
while (state.dispatches.length > MAX_ACTIVE) {
|
|
102
|
+
const overflow = state.dispatches.shift();
|
|
103
|
+
try { archiveRecord(workspaceRoot, overflow); }
|
|
104
|
+
catch (_err) { /* non-fatal — archive is best-effort */ }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
saveState(workspaceRoot, state);
|
|
108
|
+
return record;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Reconcile the most recent pending record for a task.
|
|
113
|
+
*
|
|
114
|
+
* @param {string} workspaceRoot
|
|
115
|
+
* @param {string} taskId
|
|
116
|
+
* @param {string} status - 'completed' | 'graceful-stop' | 'silent-halt'
|
|
117
|
+
* @param {string} [reason]
|
|
118
|
+
* @returns {Object|null} updated record, or null if not found
|
|
119
|
+
*/
|
|
120
|
+
function reconcileDispatch(workspaceRoot, taskId, status, reason) {
|
|
121
|
+
if (!VALID_STATUSES.has(status) || status === 'pending') {
|
|
122
|
+
throw new Error(`Invalid reconcile status: ${status}`);
|
|
123
|
+
}
|
|
124
|
+
const state = loadState(workspaceRoot);
|
|
125
|
+
// Find most recent pending record for this taskId (last wins — most recent dispatch)
|
|
126
|
+
for (let i = state.dispatches.length - 1; i >= 0; i--) {
|
|
127
|
+
const r = state.dispatches[i];
|
|
128
|
+
if (r && r.taskId === taskId && r.status === 'pending') {
|
|
129
|
+
r.status = status;
|
|
130
|
+
r.reconciledAt = new Date().toISOString();
|
|
131
|
+
r.reconciledReason = reason || null;
|
|
132
|
+
saveState(workspaceRoot, state);
|
|
133
|
+
return r;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Read all currently-active dispatch records (not archived).
|
|
141
|
+
*
|
|
142
|
+
* @param {string} workspaceRoot
|
|
143
|
+
* @returns {Array<Object>}
|
|
144
|
+
*/
|
|
145
|
+
function readDispatches(workspaceRoot) {
|
|
146
|
+
return loadState(workspaceRoot).dispatches;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Get dispatches whose expectedDeadline has passed and are still pending.
|
|
151
|
+
*
|
|
152
|
+
* @param {string} workspaceRoot
|
|
153
|
+
* @param {number} [now=Date.now()]
|
|
154
|
+
* @returns {Array<Object>} overdue records
|
|
155
|
+
*/
|
|
156
|
+
function getOverdueDispatches(workspaceRoot, now) {
|
|
157
|
+
const ts = Number.isFinite(now) ? now : Date.now();
|
|
158
|
+
const dispatches = readDispatches(workspaceRoot);
|
|
159
|
+
return dispatches.filter(r => {
|
|
160
|
+
if (!r || r.status !== 'pending') return false;
|
|
161
|
+
const deadline = Date.parse(r.expectedDeadline || '');
|
|
162
|
+
return Number.isFinite(deadline) && deadline < ts;
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
module.exports = {
|
|
167
|
+
DEFAULT_DURATION_MS,
|
|
168
|
+
MAX_ACTIVE,
|
|
169
|
+
recordDispatch,
|
|
170
|
+
reconcileDispatch,
|
|
171
|
+
readDispatches,
|
|
172
|
+
getOverdueDispatches,
|
|
173
|
+
stateFilePath,
|
|
174
|
+
archiveFilePath
|
|
175
|
+
};
|
|
@@ -22,6 +22,7 @@ const MESSAGE_TYPES = [
|
|
|
22
22
|
'question', // "Does your side handle X?"
|
|
23
23
|
'bug-report', // "Your endpoint returns 500 when I send Y"
|
|
24
24
|
'task-complete', // "I finished my side of feature Z"
|
|
25
|
+
'worker-stopped', // Graceful Stop hook — worker session ending, not necessarily at task completion
|
|
25
26
|
'needs-help', // "I'm stuck, can you check X on your side?"
|
|
26
27
|
'heads-up', // "I'm about to change Y, just FYI"
|
|
27
28
|
'impact-query', // Pre-dev: "I'm about to change X, will this break you?"
|
package/lib/workspace-routing.js
CHANGED
|
@@ -700,6 +700,8 @@ function checkWorkerHealth(port) {
|
|
|
700
700
|
* @param {string} taskId — task ID to start
|
|
701
701
|
* @param {Object} [opts] — dispatch options
|
|
702
702
|
* @param {string} [opts.effortLevel] — reasoning effort to propagate ('low'|'medium'|'high')
|
|
703
|
+
* @param {number} [opts.expectedDurationMs] — override deadline for silent-halt detection
|
|
704
|
+
* (wf-d3e67abe). Defaults to DEFAULT_DURATION_MS from workspace-dispatch-tracking.
|
|
703
705
|
* @returns {Promise<{ ok: boolean, message: string }>}
|
|
704
706
|
*/
|
|
705
707
|
async function dispatchToChannel(workspaceRoot, repoName, taskId, opts = {}) {
|
|
@@ -739,6 +741,21 @@ async function dispatchToChannel(workspaceRoot, repoName, taskId, opts = {}) {
|
|
|
739
741
|
const dispatchBody = `${effortPrefix}/wogi-start ${taskId}`;
|
|
740
742
|
const result = await httpPost('127.0.0.1', port, dispatchBody);
|
|
741
743
|
if (result.ok) {
|
|
744
|
+
// wf-d3e67abe — record dispatch for silent-halt detection.
|
|
745
|
+
// Fail-open: if tracking write fails, dispatch itself still succeeds.
|
|
746
|
+
try {
|
|
747
|
+
const { recordDispatch } = require('./workspace-dispatch-tracking');
|
|
748
|
+
recordDispatch(workspaceRoot, {
|
|
749
|
+
taskId,
|
|
750
|
+
repoName,
|
|
751
|
+
expectedDurationMs: opts.expectedDurationMs,
|
|
752
|
+
dispatchedBy: process.env.WOGI_REPO_NAME || 'manager'
|
|
753
|
+
});
|
|
754
|
+
} catch (err) {
|
|
755
|
+
if (process.env.DEBUG) {
|
|
756
|
+
console.error(`[dispatchToChannel] Dispatch tracking failed (non-fatal): ${err.message}`);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
742
759
|
return { ok: true, message: `Dispatched /wogi-start ${taskId} to ${repoName} (port ${port})${effortLevel ? ` [effort: ${effortLevel}]` : ''}` };
|
|
743
760
|
}
|
|
744
761
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wogiflow",
|
|
3
|
-
"version": "2.22.
|
|
3
|
+
"version": "2.22.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 tests/flow-worker-boundary-gate.test.js tests/flow-worker-question-classifier.test.js tests/flow-completion-truth-gate-contradictions.test.js tests/flow-structure-sensor.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 tests/flow-worker-question-classifier.test.js tests/flow-completion-truth-gate-contradictions.test.js tests/flow-structure-sensor.test.js tests/flow-workspace-dispatch-tracking.test.js tests/flow-story-gates.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",
|
|
@@ -328,6 +328,15 @@ const CONFIG_DEFAULTS = {
|
|
|
328
328
|
supportEpics: true,
|
|
329
329
|
propagateProgress: true
|
|
330
330
|
},
|
|
331
|
+
|
|
332
|
+
// --- Story Creation Quality Gates (wf-63c0f4cc) ---
|
|
333
|
+
// Specification-quality gates enforced at story CREATION time. Execution-
|
|
334
|
+
// quality gates (runtime wiring, typecheck, tests) remain /wogi-start's job.
|
|
335
|
+
storyFlow: {
|
|
336
|
+
consumerImpactAnalysis: { enabled: true, breakingThreshold: 5 },
|
|
337
|
+
scopeConfidenceAudit: { enabled: true },
|
|
338
|
+
itemReconciliation: { enabled: true, minItems: 3 }
|
|
339
|
+
},
|
|
331
340
|
epics: { enabled: false },
|
|
332
341
|
|
|
333
342
|
// --- Specification & Questions ---
|