wogiflow 2.20.1 → 2.22.0
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-finalize.md +83 -0
- package/.claude/rules/_internal/self-maintenance.md +1 -1
- package/.claude/settings.json +1 -1
- package/lib/commands/login.js +1 -1
- package/lib/installer.js +5 -5
- package/lib/release-channel.js +1 -1
- package/lib/skill-registry.js +3 -3
- package/lib/workspace-events.js +1 -1
- package/lib/workspace-gates.js +2 -2
- package/lib/workspace-intelligence.js +1 -1
- package/lib/workspace-routing.js +1 -1
- package/lib/workspace.js +16 -17
- package/package.json +2 -2
- package/scripts/base-workflow-step.js +2 -2
- package/scripts/flow-adaptive-learning.js +6 -6
- package/scripts/flow-api-index.js +2 -2
- package/scripts/flow-architect-pass.js +1 -1
- package/scripts/flow-ask.js +1 -1
- package/scripts/flow-assumption-detector.js +1 -1
- package/scripts/flow-audit-gates.js +38 -12
- package/scripts/flow-audit.js +4 -4
- package/scripts/flow-auto-context.js +3 -3
- package/scripts/flow-background.js +1 -1
- package/scripts/flow-best-of-n.js +7 -7
- package/scripts/flow-bridge.js +3 -3
- package/scripts/flow-bug.js +2 -2
- package/scripts/flow-bulk-loop.js +7 -7
- package/scripts/flow-cascade-completion.js +2 -2
- package/scripts/flow-cascade.js +1 -1
- package/scripts/flow-checkpoint.js +2 -2
- package/scripts/flow-clarifying-questions.js +2 -2
- package/scripts/flow-cli.js +2 -2
- package/scripts/flow-code-intelligence.js +4 -4
- package/scripts/flow-community-sync.js +6 -6
- package/scripts/flow-community.js +1 -1
- package/scripts/flow-completion-truth-gate.js +161 -5
- package/scripts/flow-complexity.js +1 -1
- package/scripts/flow-config-defaults.js +16 -4
- package/scripts/flow-config-interactive.js +2 -2
- package/scripts/flow-config-loader.js +1 -1
- package/scripts/flow-config-migrate.js +5 -6
- package/scripts/flow-consistency-check.js +5 -5
- package/scripts/flow-context-compact/expander.js +1 -1
- package/scripts/flow-context-compact/index.js +2 -2
- package/scripts/flow-context-compact/section-extractor.js +3 -3
- package/scripts/flow-context-compact/summary-tree.js +1 -1
- package/scripts/flow-context-estimator.js +1 -1
- package/scripts/flow-context-gatherer.js +6 -6
- package/scripts/flow-context-generator.js +6 -6
- package/scripts/flow-context-init.js +2 -2
- package/scripts/flow-context-manager.js +1 -1
- package/scripts/flow-context-manifest.js +1 -1
- package/scripts/flow-context-monitor.js +5 -5
- package/scripts/flow-context-orchestrator.js +2 -2
- package/scripts/flow-context-scoring.js +4 -4
- package/scripts/flow-contract-scan.js +1 -1
- package/scripts/flow-correct.js +3 -3
- package/scripts/flow-damage-control.js +2 -2
- package/scripts/flow-deploy-gate.js +2 -2
- package/scripts/flow-deploy-history.js +1 -1
- package/scripts/flow-diff.js +3 -3
- package/scripts/flow-done-gates.js +1 -1
- package/scripts/flow-done.js +7 -7
- package/scripts/flow-durable-session.js +1 -1
- package/scripts/flow-entropy-monitor.js +3 -3
- package/scripts/flow-epics.js +5 -5
- package/scripts/flow-error-recovery.js +4 -4
- package/scripts/flow-eval-judge.js +5 -5
- package/scripts/flow-eval.js +7 -7
- package/scripts/flow-export-scanner.js +5 -5
- package/scripts/flow-extraction-review.js +1 -1
- package/scripts/flow-failure-learning.js +9 -9
- package/scripts/flow-feature.js +5 -5
- package/scripts/flow-figma-confirm.js +1 -1
- package/scripts/flow-figma-extract.js +2 -2
- package/scripts/flow-figma-index.js +2 -2
- package/scripts/flow-figma-match.js +1 -1
- package/scripts/flow-figma-mcp-server.js +3 -3
- package/scripts/flow-figma-orchestrator.js +1 -1
- package/scripts/flow-figma-registry.js +2 -2
- package/scripts/flow-function-index.js +2 -2
- package/scripts/flow-gate-confidence.js +2 -2
- package/scripts/flow-gate-telemetry.js +1 -1
- package/scripts/flow-gitignore.js +1 -1
- package/scripts/flow-guided-edit.js +3 -3
- package/scripts/flow-health.js +95 -8
- package/scripts/flow-hooks.js +3 -3
- package/scripts/flow-hybrid-detect.js +2 -2
- package/scripts/flow-hybrid-interactive.js +1 -1
- package/scripts/flow-hybrid-test.js +1 -1
- package/scripts/flow-hypothesis-generator.js +4 -4
- package/scripts/flow-instruction-richness.js +11 -11
- package/scripts/flow-intent-bootstrap.js +1 -1
- package/scripts/flow-intent-framing.js +1 -1
- package/scripts/flow-item-link.js +2 -2
- package/scripts/flow-knowledge-router.js +7 -7
- package/scripts/flow-knowledge-sync.js +3 -3
- package/scripts/flow-learning-orchestrator.js +1 -1
- package/scripts/flow-links.js +2 -2
- package/scripts/flow-log-manager.js +2 -2
- package/scripts/flow-logic-adversary.js +5 -4
- package/scripts/flow-long-input-chunking.js +1 -1
- package/scripts/flow-long-input-cli.js +3 -3
- package/scripts/flow-long-input.js +18 -18
- package/scripts/flow-loop-retry-learning.js +2 -2
- package/scripts/flow-lsp.js +4 -4
- package/scripts/flow-mcp-docs.js +1 -1
- package/scripts/flow-memory-blocks.js +5 -5
- package/scripts/flow-memory-compactor.js +3 -3
- package/scripts/flow-memory-db.js +4 -4
- package/scripts/flow-memory-sync.js +3 -3
- package/scripts/flow-metrics.js +2 -2
- package/scripts/flow-migrate-igr.js +2 -2
- package/scripts/flow-migrate.js +2 -2
- package/scripts/flow-model-adapter.js +4 -4
- package/scripts/flow-model-caller.js +8 -8
- package/scripts/flow-model-config.js +5 -5
- package/scripts/flow-model-profile.js +7 -7
- package/scripts/flow-model-router.js +5 -5
- package/scripts/flow-model-types.js +3 -3
- package/scripts/flow-models.js +8 -8
- package/scripts/flow-morning.js +1 -1
- package/scripts/flow-multi-approach.js +1 -1
- package/scripts/flow-orchestrate-context.js +2 -2
- package/scripts/flow-orchestrate-llm.js +4 -4
- package/scripts/flow-orchestrate-rollback.js +1 -1
- package/scripts/flow-orchestrate-state.js +6 -6
- package/scripts/flow-orchestrate-templates.js +1 -1
- package/scripts/flow-orchestrate-validation.js +2 -2
- package/scripts/flow-orchestrate-validator.js +1 -1
- package/scripts/flow-orchestrate.js +25 -25
- package/scripts/flow-parallel.js +1 -1
- package/scripts/flow-pattern-enforcer.js +7 -7
- package/scripts/flow-pattern-extractor.js +3 -3
- package/scripts/flow-peer-review.js +8 -8
- package/scripts/flow-pending.js +1 -1
- package/scripts/flow-permissions.js +1 -1
- package/scripts/flow-phased-task.js +1 -1
- package/scripts/flow-plan.js +1 -1
- package/scripts/flow-prd-manager.js +2 -2
- package/scripts/flow-product-scanner.js +2 -2
- package/scripts/flow-progress-tracker.js +2 -2
- package/scripts/flow-progress.js +1 -1
- package/scripts/flow-project-analyzer.js +3 -3
- package/scripts/flow-prompt-capture.js +2 -2
- package/scripts/flow-prompt-composer.js +3 -3
- package/scripts/flow-prompt-template.js +4 -4
- package/scripts/flow-providers.js +31 -23
- package/scripts/flow-queue.js +1 -1
- package/scripts/flow-registry-manager.js +4 -4
- package/scripts/flow-regression.js +1 -1
- package/scripts/flow-response-parser.js +1 -1
- package/scripts/flow-resume.js +1 -1
- package/scripts/flow-review-passes/index.js +2 -2
- package/scripts/flow-review-passes/integration.js +3 -3
- package/scripts/flow-review-passes/logic.js +3 -3
- package/scripts/flow-review-passes/security.js +2 -2
- package/scripts/flow-review-passes/structure.js +1 -1
- package/scripts/flow-review.js +11 -11
- package/scripts/flow-revision-tracker.js +2 -2
- package/scripts/flow-roadmap.js +2 -2
- package/scripts/flow-run-trace.js +1 -1
- package/scripts/flow-safety.js +3 -3
- package/scripts/flow-scanner-base.js +1 -1
- package/scripts/flow-scenario-engine.js +7 -7
- package/scripts/flow-schema-drift.js +4 -3
- package/scripts/flow-section-index.js +2 -2
- package/scripts/flow-section-resolver.js +4 -4
- package/scripts/flow-semantic-match.js +3 -3
- package/scripts/flow-session-end.js +56 -0
- package/scripts/flow-session-learning.js +2 -2
- package/scripts/flow-setup-hooks.js +1 -1
- package/scripts/flow-skill-create.js +3 -3
- package/scripts/flow-skill-freshness.js +2 -2
- package/scripts/flow-skill-generator.js +6 -6
- package/scripts/flow-skill-learn.js +7 -7
- package/scripts/flow-skill-matcher.js +2 -2
- package/scripts/flow-solution-optimizer.js +1 -1
- package/scripts/flow-spec-generator.js +5 -5
- package/scripts/flow-spec-verifier.js +2 -2
- package/scripts/flow-stack-wizard.js +6 -6
- package/scripts/flow-standards-checker.js +8 -8
- package/scripts/flow-standards-gate.js +4 -4
- package/scripts/flow-standards-learner.js +2 -2
- package/scripts/flow-start.js +9 -9
- package/scripts/flow-stats-collector.js +2 -2
- package/scripts/flow-status.js +1 -1
- package/scripts/flow-step-changelog.js +3 -3
- package/scripts/flow-step-complexity.js +1 -1
- package/scripts/flow-step-coverage.js +3 -3
- package/scripts/flow-step-knowledge.js +2 -2
- package/scripts/flow-step-pr-tests.js +2 -2
- package/scripts/flow-step-regression.js +3 -3
- package/scripts/flow-step-review.js +5 -5
- package/scripts/flow-story.js +2 -2
- package/scripts/flow-strict-adherence.js +2 -2
- package/scripts/flow-structure-sensor.js +283 -0
- package/scripts/flow-sync-anonymizer.js +3 -3
- package/scripts/flow-task-checkpoint.js +2 -2
- package/scripts/flow-task-classifier.js +2 -2
- package/scripts/flow-task-completion-summary.js +1 -1
- package/scripts/flow-task-enforcer.js +5 -5
- package/scripts/flow-tech-debt.js +3 -3
- package/scripts/flow-template-extractor.js +3 -3
- package/scripts/flow-templates.js +1 -1
- package/scripts/flow-test-api.js +12 -12
- package/scripts/flow-test-discovery.js +9 -9
- package/scripts/flow-test-generate.js +5 -5
- package/scripts/flow-test-integrity.js +3 -3
- package/scripts/flow-test-ui.js +8 -8
- package/scripts/flow-testing-deps.js +4 -4
- package/scripts/flow-tiered-learning.js +3 -3
- package/scripts/flow-todowrite-sync.js +1 -1
- package/scripts/flow-trap-zone.js +1 -1
- package/scripts/flow-verification-profile.js +9 -9
- package/scripts/flow-verify.js +2 -2
- package/scripts/flow-version-check.js +2 -2
- package/scripts/flow-webmcp-generator.js +3 -3
- package/scripts/flow-wiring-verifier.js +13 -13
- package/scripts/flow-worker-question-classifier.js +256 -0
- package/scripts/flow-workflow-steps.js +3 -3
- package/scripts/flow-workflow.js +1 -1
- package/scripts/flow-worktree.js +1 -1
- package/scripts/hooks/adapters/base-adapter.js +2 -2
- package/scripts/hooks/core/commit-log-gate.js +2 -2
- package/scripts/hooks/core/component-check.js +3 -3
- package/scripts/hooks/core/config-change.js +1 -1
- package/scripts/hooks/core/deploy-gate.js +2 -1
- package/scripts/hooks/core/git-safety-gate.js +1 -1
- package/scripts/hooks/core/instructions-loaded.js +1 -1
- package/scripts/hooks/core/loop-check.js +1 -1
- package/scripts/hooks/core/manager-boundary-gate.js +3 -2
- package/scripts/hooks/core/observation-capture.js +6 -6
- package/scripts/hooks/core/phase-gate.js +4 -4
- package/scripts/hooks/core/pre-compact.js +1 -1
- package/scripts/hooks/core/pre-tool-orchestrator.js +1 -1
- package/scripts/hooks/core/routing-gate.js +2 -84
- package/scripts/hooks/core/session-context.js +1 -1
- package/scripts/hooks/core/session-end.js +3 -3
- package/scripts/hooks/core/session-history.js +1 -1
- package/scripts/hooks/core/setup-handler.js +1 -1
- package/scripts/hooks/core/task-boundary-reset.js +2 -4
- package/scripts/hooks/core/task-completed.js +13 -7
- package/scripts/hooks/core/task-created.js +1 -1
- package/scripts/hooks/core/worktree-lifecycle.js +1 -1
- package/scripts/hooks/entry/claude-code/permission-denied.js +4 -2
- package/scripts/hooks/entry/claude-code/stop.js +60 -0
- package/scripts/hooks/entry/claude-code/user-prompt-submit.js +1 -1
- package/scripts/hooks/git/post-commit.js +1 -1
- package/scripts/postinstall.js +7 -7
- package/scripts/preuninstall.js +5 -5
- package/scripts/registries/component-registry.js +2 -2
- package/scripts/registries/contract-scanner.js +11 -11
- package/scripts/registries/schema-registry.js +5 -5
- package/scripts/registries/service-registry.js +9 -9
|
@@ -38,7 +38,7 @@ function getUncommittedCount() {
|
|
|
38
38
|
stdio: ['pipe', 'pipe', 'pipe']
|
|
39
39
|
});
|
|
40
40
|
return output.trim().split('\n').filter(line => line.trim()).length;
|
|
41
|
-
} catch (
|
|
41
|
+
} catch (_err) {
|
|
42
42
|
return 0;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
@@ -131,7 +131,7 @@ function handleSessionEnd(input) {
|
|
|
131
131
|
console.error(`[Session End] Community sync-up failed: ${err.message}`);
|
|
132
132
|
}
|
|
133
133
|
});
|
|
134
|
-
} catch (
|
|
134
|
+
} catch (_err) {
|
|
135
135
|
// Non-critical — community sync module may not be available
|
|
136
136
|
}
|
|
137
137
|
|
|
@@ -144,7 +144,7 @@ function handleSessionEnd(input) {
|
|
|
144
144
|
// Non-critical - memory pipeline may not be available
|
|
145
145
|
});
|
|
146
146
|
}
|
|
147
|
-
} catch (
|
|
147
|
+
} catch (_err) {
|
|
148
148
|
// Non-critical — memory DB may not be available
|
|
149
149
|
}
|
|
150
150
|
|
|
@@ -93,7 +93,7 @@ function handleSetup(options = {}) {
|
|
|
93
93
|
* @param {Object} options
|
|
94
94
|
* @returns {Object} Result: { tasks, message, results }
|
|
95
95
|
*/
|
|
96
|
-
function handleMaintenance(
|
|
96
|
+
function handleMaintenance(_options = {}) {
|
|
97
97
|
if (!isSetupEnabled()) {
|
|
98
98
|
return {
|
|
99
99
|
tasks: [],
|
|
@@ -47,6 +47,7 @@ const fs = require('node:fs');
|
|
|
47
47
|
const path = require('node:path');
|
|
48
48
|
|
|
49
49
|
const { getConfig, PATHS } = require('../../flow-utils');
|
|
50
|
+
const { safeJsonParse } = require('../../flow-io');
|
|
50
51
|
|
|
51
52
|
const PENDING_MARKER_FILE = 'task-just-completed';
|
|
52
53
|
|
|
@@ -157,10 +158,7 @@ function consumeAndTriggerRestart() {
|
|
|
157
158
|
// Consume the marker. Do this BEFORE signaling so we never double-fire if
|
|
158
159
|
// for some reason the signal delivery is delayed and a second Stop-hook
|
|
159
160
|
// invocation races through.
|
|
160
|
-
|
|
161
|
-
try {
|
|
162
|
-
markerPayload = JSON.parse(fs.readFileSync(markerPath, 'utf-8'));
|
|
163
|
-
} catch (_err) { /* payload read is optional */ }
|
|
161
|
+
const markerPayload = safeJsonParse(markerPath, null);
|
|
164
162
|
try {
|
|
165
163
|
fs.unlinkSync(markerPath);
|
|
166
164
|
} catch (err) {
|
|
@@ -168,7 +168,7 @@ async function handleTaskCompleted(input) {
|
|
|
168
168
|
writeJson(readyPath, ready);
|
|
169
169
|
result.completed = true;
|
|
170
170
|
result.message = `Task ${completedTask.id} (${completedTask.title}) moved to completed`;
|
|
171
|
-
} catch (
|
|
171
|
+
} catch (_err) {
|
|
172
172
|
result.message = 'Failed to update ready.json';
|
|
173
173
|
}
|
|
174
174
|
});
|
|
@@ -401,12 +401,18 @@ async function handleTaskCompleted(input) {
|
|
|
401
401
|
{ mode: 0o644 }
|
|
402
402
|
);
|
|
403
403
|
}
|
|
404
|
-
} catch (
|
|
405
|
-
//
|
|
406
|
-
//
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
404
|
+
} catch (err) {
|
|
405
|
+
// Workspace message is the VERIFIED completion signal. A silent failure
|
|
406
|
+
// produces "workers stopped writing since <date>" incidents that are
|
|
407
|
+
// indistinguishable from "no tasks completed recently" — surface on
|
|
408
|
+
// stderr unconditionally so regressions are visible in worker logs.
|
|
409
|
+
// (diagnostic D1, 2026-04-16 honesty-infrastructure review.)
|
|
410
|
+
const reason = err && err.message ? err.message : 'unknown';
|
|
411
|
+
const root = process.env.WOGI_WORKSPACE_ROOT || '(unset)';
|
|
412
|
+
const repo = process.env.WOGI_REPO_NAME || '(unset)';
|
|
413
|
+
console.error(
|
|
414
|
+
`[Task Completed] workspace message write FAILED for ${completedTask.id}: ${reason} (root=${root}, repo=${repo})`
|
|
415
|
+
);
|
|
410
416
|
}
|
|
411
417
|
}
|
|
412
418
|
|
|
@@ -31,7 +31,7 @@ function isTaskCreatedEnabled() {
|
|
|
31
31
|
* @param {Object} input - Parsed hook input from Claude Code
|
|
32
32
|
* @returns {Object} Core result
|
|
33
33
|
*/
|
|
34
|
-
async function handleTaskCreated(
|
|
34
|
+
async function handleTaskCreated(_input) {
|
|
35
35
|
if (!isTaskCreatedEnabled()) {
|
|
36
36
|
return { enabled: false, message: null };
|
|
37
37
|
}
|
|
@@ -25,7 +25,7 @@ const CORE_STATE_FILES = ['ready.json', 'decisions.md'];
|
|
|
25
25
|
|
|
26
26
|
function getEssentialStateFiles() {
|
|
27
27
|
try {
|
|
28
|
-
const { getRegistryMapFiles
|
|
28
|
+
const { getRegistryMapFiles } = require('../../flow-utils');
|
|
29
29
|
return [...CORE_STATE_FILES, ...getRegistryMapFiles()];
|
|
30
30
|
} catch (_err) {
|
|
31
31
|
return [...CORE_STATE_FILES, 'app-map.md', 'function-map.md', 'api-map.md'];
|
|
@@ -31,13 +31,15 @@ runHook('PermissionDenied', async ({ input, parsedInput }) => {
|
|
|
31
31
|
try {
|
|
32
32
|
const fs = require('node:fs');
|
|
33
33
|
const { PATHS } = require('../../../flow-utils');
|
|
34
|
+
const { safeJsonParseString } = require('../../../flow-io');
|
|
34
35
|
const logPath = path.join(PATHS.state, 'permission-denials.json');
|
|
35
36
|
|
|
36
37
|
let denials = [];
|
|
37
38
|
try {
|
|
38
39
|
if (fs.existsSync(logPath)) {
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
const raw = fs.readFileSync(logPath, 'utf-8');
|
|
41
|
+
const parsed = safeJsonParseString(raw, []);
|
|
42
|
+
denials = Array.isArray(parsed) ? parsed : [];
|
|
41
43
|
}
|
|
42
44
|
} catch (_err) {
|
|
43
45
|
denials = [];
|
|
@@ -242,6 +242,66 @@ runHook('Stop', async ({ parsedInput }) => {
|
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
+
// G3 (v2.21.0) — AI-based worker-question classifier.
|
|
246
|
+
//
|
|
247
|
+
// If the worker ends a turn with a question to the user in free text (no tool
|
|
248
|
+
// call, just hedging), Gap B above won't fire when the queue is empty.
|
|
249
|
+
// Regex-based detection was rejected as brittle. Instead: a single Haiku call
|
|
250
|
+
// classifies the final assistant message. If it IS an open question to the
|
|
251
|
+
// user → block with escalation instructions.
|
|
252
|
+
//
|
|
253
|
+
// Fail-open throughout: missing API key, missing transcript, model errors,
|
|
254
|
+
// malformed responses all skip cleanly. Silent-stall false-negatives recover;
|
|
255
|
+
// blocking legitimate stops on classifier bugs does not.
|
|
256
|
+
try {
|
|
257
|
+
const isWorker = process.env.WOGI_WORKSPACE_ROOT &&
|
|
258
|
+
process.env.WOGI_REPO_NAME &&
|
|
259
|
+
process.env.WOGI_REPO_NAME !== 'manager';
|
|
260
|
+
if (isWorker) {
|
|
261
|
+
const { getConfig } = require('../../../flow-utils');
|
|
262
|
+
const config = getConfig();
|
|
263
|
+
const clf = config.workspace?.aiWorkerQuestionClassifier;
|
|
264
|
+
const enabled = clf?.enabled !== false; // default true
|
|
265
|
+
if (enabled && parsedInput?.transcriptPath) {
|
|
266
|
+
const { classifyWorkerQuestion } = require('../../../flow-worker-question-classifier');
|
|
267
|
+
const result = await classifyWorkerQuestion({
|
|
268
|
+
transcriptPath: parsedInput.transcriptPath,
|
|
269
|
+
minConfidence: Number.isFinite(clf?.minConfidence) ? clf.minConfidence : 70,
|
|
270
|
+
model: typeof clf?.model === 'string' ? clf.model : undefined
|
|
271
|
+
});
|
|
272
|
+
if (result?.blocked) {
|
|
273
|
+
const port = process.env.WOGI_MANAGER_PORT || '8800';
|
|
274
|
+
const repo = process.env.WOGI_REPO_NAME;
|
|
275
|
+
const msg = [
|
|
276
|
+
`WORKER→USER QUESTION DETECTED (confidence ${result.confidence}%, threshold ${result.minConfidence}%):`,
|
|
277
|
+
` "${String(result.reason || '').slice(0, 200)}"`,
|
|
278
|
+
'',
|
|
279
|
+
'In workspace mode, workers CANNOT ask the user directly — the user only sees',
|
|
280
|
+
'the manager terminal. Your question will stall silently.',
|
|
281
|
+
'',
|
|
282
|
+
'Channel-dispatch to the manager instead, THEN end the turn:',
|
|
283
|
+
'',
|
|
284
|
+
` curl -s -X POST http://127.0.0.1:${port} \\`,
|
|
285
|
+
` -H "X-Wogi-From: ${repo}" \\`,
|
|
286
|
+
` --data-binary "## QUESTION: <your question>"`,
|
|
287
|
+
'',
|
|
288
|
+
'The manager will relay to the user, capture the answer, and dispatch a',
|
|
289
|
+
'follow-up task to you with the resolved context.',
|
|
290
|
+
'',
|
|
291
|
+
'If you don\'t actually need the user — make a reasonable autonomous decision',
|
|
292
|
+
'and note it in your ## Results reply to the manager. Then end the turn.'
|
|
293
|
+
].join('\n');
|
|
294
|
+
return { __raw: true, continue: true, stopReason: msg };
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
} catch (err) {
|
|
299
|
+
// Fail-OPEN — classifier errors must not block legitimate stops.
|
|
300
|
+
if (process.env.DEBUG) {
|
|
301
|
+
console.error(`[Stop] Worker question classifier error (fail-open): ${err.message}`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
245
305
|
// Check if loop can exit
|
|
246
306
|
return await checkLoopExit();
|
|
247
307
|
}, { failMode: 'warn', failOutput: { continue: false } });
|
|
@@ -15,7 +15,7 @@ const path = require('node:path');
|
|
|
15
15
|
|
|
16
16
|
// Resolve paths relative to this script's location
|
|
17
17
|
const scriptsDir = path.resolve(__dirname, '../..');
|
|
18
|
-
const { getReadyData, saveReadyData, info
|
|
18
|
+
const { getReadyData, saveReadyData, info } = require(path.join(scriptsDir, 'flow-utils'));
|
|
19
19
|
const { success } = require('../../flow-output');
|
|
20
20
|
|
|
21
21
|
/**
|
package/scripts/postinstall.js
CHANGED
|
@@ -62,7 +62,7 @@ function safeJsonParseString(jsonString, defaultValue = null) {
|
|
|
62
62
|
return defaultValue;
|
|
63
63
|
}
|
|
64
64
|
return parsed;
|
|
65
|
-
} catch (
|
|
65
|
+
} catch (_err) {
|
|
66
66
|
return defaultValue;
|
|
67
67
|
}
|
|
68
68
|
}
|
|
@@ -93,7 +93,7 @@ function hasDangerousKeys(obj) {
|
|
|
93
93
|
*/
|
|
94
94
|
function safeClose(fd) {
|
|
95
95
|
if (fd !== null) {
|
|
96
|
-
try { fs.closeSync(fd); } catch (
|
|
96
|
+
try { fs.closeSync(fd); } catch (_err) { /* intentionally ignored */ }
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -520,7 +520,7 @@ function copyClaudeResources() {
|
|
|
520
520
|
}
|
|
521
521
|
try {
|
|
522
522
|
fs.chmodSync(projectSettings, FILE_MODE);
|
|
523
|
-
} catch (
|
|
523
|
+
} catch (_err) { /* non-critical */ }
|
|
524
524
|
} catch (err) {
|
|
525
525
|
if (process.env.DEBUG) {
|
|
526
526
|
console.error(`[postinstall] settings.json initial copy failed: ${err.message}`);
|
|
@@ -608,7 +608,7 @@ function getPackageVersion() {
|
|
|
608
608
|
const content = fs.readFileSync(path.join(PACKAGE_ROOT, 'package.json'), 'utf-8');
|
|
609
609
|
const pkg = safeJsonParseString(content, null);
|
|
610
610
|
return (pkg && pkg.version) || 'unknown';
|
|
611
|
-
} catch (
|
|
611
|
+
} catch (_err) {
|
|
612
612
|
return 'unknown';
|
|
613
613
|
}
|
|
614
614
|
}
|
|
@@ -644,7 +644,7 @@ function regenerateClaudeMd() {
|
|
|
644
644
|
}
|
|
645
645
|
return;
|
|
646
646
|
}
|
|
647
|
-
} catch (
|
|
647
|
+
} catch (_err) {
|
|
648
648
|
// No version file yet — proceed with regen
|
|
649
649
|
}
|
|
650
650
|
|
|
@@ -688,7 +688,7 @@ function regenerateClaudeMd() {
|
|
|
688
688
|
// Record successful regen version for skip gate
|
|
689
689
|
try {
|
|
690
690
|
fs.writeFileSync(versionFile, pkgVersion, { mode: FILE_MODE });
|
|
691
|
-
} catch (
|
|
691
|
+
} catch (_err) {
|
|
692
692
|
// Non-critical — next install will just regen again
|
|
693
693
|
}
|
|
694
694
|
|
|
@@ -1015,7 +1015,7 @@ function main() {
|
|
|
1015
1015
|
// Combine access check and open into single try-catch to avoid TOCTOU
|
|
1016
1016
|
ttyFd = fs.openSync('/dev/tty', 'w');
|
|
1017
1017
|
output = { write: (msg) => fs.writeSync(ttyFd, msg) };
|
|
1018
|
-
} catch (
|
|
1018
|
+
} catch (_err) {
|
|
1019
1019
|
// /dev/tty not available (no terminal, CI, etc.) - fallback to stderr
|
|
1020
1020
|
ttyFd = null;
|
|
1021
1021
|
}
|
package/scripts/preuninstall.js
CHANGED
|
@@ -61,7 +61,7 @@ function readManifest() {
|
|
|
61
61
|
return manifest;
|
|
62
62
|
}
|
|
63
63
|
return null;
|
|
64
|
-
} catch (
|
|
64
|
+
} catch (_err) {
|
|
65
65
|
return null;
|
|
66
66
|
}
|
|
67
67
|
}
|
|
@@ -112,7 +112,7 @@ function cleanupEmptyDirs(baseDir) {
|
|
|
112
112
|
if (remaining.length === 0) {
|
|
113
113
|
fs.rmdirSync(subDir);
|
|
114
114
|
}
|
|
115
|
-
} catch (
|
|
115
|
+
} catch (_err) {
|
|
116
116
|
// Dir already gone or inaccessible
|
|
117
117
|
}
|
|
118
118
|
}
|
|
@@ -156,7 +156,7 @@ function manifestBasedCleanup(manifest) {
|
|
|
156
156
|
preserved.push(path.join(dir, f));
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
|
-
} catch (
|
|
159
|
+
} catch (_err) {
|
|
160
160
|
// Dir doesn't exist or already removed
|
|
161
161
|
}
|
|
162
162
|
}
|
|
@@ -231,7 +231,7 @@ function removeClaudeMd() {
|
|
|
231
231
|
return true;
|
|
232
232
|
}
|
|
233
233
|
return false;
|
|
234
|
-
} catch (
|
|
234
|
+
} catch (_err) {
|
|
235
235
|
return false;
|
|
236
236
|
}
|
|
237
237
|
}
|
|
@@ -254,7 +254,7 @@ function cleanupClaudeDir() {
|
|
|
254
254
|
return { removed: true, preserved: [] };
|
|
255
255
|
}
|
|
256
256
|
return { removed: false, preserved: userFiles };
|
|
257
|
-
} catch (
|
|
257
|
+
} catch (_err) {
|
|
258
258
|
return { removed: false, preserved: [] };
|
|
259
259
|
}
|
|
260
260
|
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
const fs = require('node:fs');
|
|
16
16
|
const path = require('node:path');
|
|
17
|
-
const {
|
|
17
|
+
const { getConfig, color, success, warn, PATHS } = require('../flow-utils');
|
|
18
18
|
const { RegistryPlugin } = require('../flow-registry-manager');
|
|
19
19
|
const { BaseScanner, PROJECT_ROOT } = require('../flow-scanner-base');
|
|
20
20
|
const { info } = require('../flow-output');
|
|
@@ -92,7 +92,7 @@ class ComponentScanner extends BaseScanner {
|
|
|
92
92
|
} else {
|
|
93
93
|
this._scanJSXFile(content, relativePath, category);
|
|
94
94
|
}
|
|
95
|
-
} catch (
|
|
95
|
+
} catch (_err) {
|
|
96
96
|
// Skip files that can't be read
|
|
97
97
|
}
|
|
98
98
|
}
|
|
@@ -57,7 +57,7 @@ function walkSourceFiles(dir, options = {}) {
|
|
|
57
57
|
let entries;
|
|
58
58
|
try {
|
|
59
59
|
entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
60
|
-
} catch (
|
|
60
|
+
} catch (_err) {
|
|
61
61
|
return; // Skip unreadable directories
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -120,12 +120,12 @@ function scanHttpClients(projectRoot, options = {}) {
|
|
|
120
120
|
let content;
|
|
121
121
|
try {
|
|
122
122
|
content = fs.readFileSync(filePath, 'utf-8');
|
|
123
|
-
} catch (
|
|
123
|
+
} catch (_err) {
|
|
124
124
|
continue;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
const relPath = path.relative(projectRoot, filePath);
|
|
128
|
-
const
|
|
128
|
+
const _lines = content.split('\n');
|
|
129
129
|
|
|
130
130
|
for (const pattern of patterns) {
|
|
131
131
|
// Reset lastIndex for global regex
|
|
@@ -192,7 +192,7 @@ function scanRouteDefinitions(projectRoot, options = {}) {
|
|
|
192
192
|
let content;
|
|
193
193
|
try {
|
|
194
194
|
content = fs.readFileSync(filePath, 'utf-8');
|
|
195
|
-
} catch (
|
|
195
|
+
} catch (_err) {
|
|
196
196
|
continue;
|
|
197
197
|
}
|
|
198
198
|
|
|
@@ -286,7 +286,7 @@ function scanNextjsApiRoutes(projectRoot) {
|
|
|
286
286
|
let content;
|
|
287
287
|
try {
|
|
288
288
|
content = fs.readFileSync(filePath, 'utf-8');
|
|
289
|
-
} catch (
|
|
289
|
+
} catch (_err) {
|
|
290
290
|
continue;
|
|
291
291
|
}
|
|
292
292
|
|
|
@@ -352,7 +352,7 @@ function scanEventBus(projectRoot, options = {}) {
|
|
|
352
352
|
let content;
|
|
353
353
|
try {
|
|
354
354
|
content = fs.readFileSync(filePath, 'utf-8');
|
|
355
|
-
} catch (
|
|
355
|
+
} catch (_err) {
|
|
356
356
|
continue;
|
|
357
357
|
}
|
|
358
358
|
|
|
@@ -422,7 +422,7 @@ function scanSharedTypes(projectRoot, options = {}) {
|
|
|
422
422
|
let content;
|
|
423
423
|
try {
|
|
424
424
|
content = fs.readFileSync(filePath, 'utf-8');
|
|
425
|
-
} catch (
|
|
425
|
+
} catch (_err) {
|
|
426
426
|
continue;
|
|
427
427
|
}
|
|
428
428
|
|
|
@@ -495,7 +495,7 @@ function scanEnvVars(projectRoot, options = {}) {
|
|
|
495
495
|
let content;
|
|
496
496
|
try {
|
|
497
497
|
content = fs.readFileSync(filePath, 'utf-8');
|
|
498
|
-
} catch (
|
|
498
|
+
} catch (_err) {
|
|
499
499
|
continue;
|
|
500
500
|
}
|
|
501
501
|
|
|
@@ -531,7 +531,7 @@ function scanEnvVars(projectRoot, options = {}) {
|
|
|
531
531
|
let content;
|
|
532
532
|
try {
|
|
533
533
|
content = fs.readFileSync(envPath, 'utf-8');
|
|
534
|
-
} catch (
|
|
534
|
+
} catch (_err) {
|
|
535
535
|
continue;
|
|
536
536
|
}
|
|
537
537
|
|
|
@@ -588,7 +588,7 @@ function detectProjectType(projectRoot) {
|
|
|
588
588
|
try {
|
|
589
589
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
590
590
|
packageCount += entries.filter(e => e.isDirectory()).length;
|
|
591
|
-
} catch (
|
|
591
|
+
} catch (_err) {
|
|
592
592
|
// skip
|
|
593
593
|
}
|
|
594
594
|
}
|
|
@@ -651,7 +651,7 @@ function getCommitSha(projectRoot) {
|
|
|
651
651
|
encoding: 'utf-8',
|
|
652
652
|
stdio: ['pipe', 'pipe', 'pipe']
|
|
653
653
|
}).trim();
|
|
654
|
-
} catch (
|
|
654
|
+
} catch (_err) {
|
|
655
655
|
return null;
|
|
656
656
|
}
|
|
657
657
|
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
const fs = require('node:fs');
|
|
13
13
|
const path = require('node:path');
|
|
14
14
|
const { RegistryPlugin } = require('../flow-registry-manager');
|
|
15
|
-
const {
|
|
15
|
+
const { safeJsonParse: safeJsonParseFile, PATHS, getTodayDate } = require('../flow-utils');
|
|
16
16
|
|
|
17
17
|
const INDEX_PATH = path.join(PATHS.state, 'schema-index.json');
|
|
18
18
|
const MAP_PATH = path.join(PATHS.state, 'schema-map.md');
|
|
@@ -47,7 +47,7 @@ class SchemaRegistry extends RegistryPlugin {
|
|
|
47
47
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
48
48
|
const ormPackages = ['prisma', '@prisma/client', 'typeorm', 'drizzle-orm', 'sequelize', 'mongoose'];
|
|
49
49
|
if (ormPackages.some(p => allDeps[p])) return true;
|
|
50
|
-
} catch (
|
|
50
|
+
} catch (_err) {
|
|
51
51
|
// ignore
|
|
52
52
|
}
|
|
53
53
|
}
|
|
@@ -197,7 +197,7 @@ class SchemaRegistry extends RegistryPlugin {
|
|
|
197
197
|
const content = fs.readFileSync(file, 'utf-8');
|
|
198
198
|
const relPath = path.relative(PATHS.root, file);
|
|
199
199
|
this._parsePrismaFile(content, relPath);
|
|
200
|
-
} catch (
|
|
200
|
+
} catch (_err) {
|
|
201
201
|
// Skip unreadable files
|
|
202
202
|
}
|
|
203
203
|
}
|
|
@@ -217,7 +217,7 @@ class SchemaRegistry extends RegistryPlugin {
|
|
|
217
217
|
results.push(fullPath);
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
|
-
} catch (
|
|
220
|
+
} catch (_err) {
|
|
221
221
|
// Skip unreadable directories
|
|
222
222
|
}
|
|
223
223
|
return results;
|
|
@@ -368,7 +368,7 @@ class SchemaRegistry extends RegistryPlugin {
|
|
|
368
368
|
}
|
|
369
369
|
}
|
|
370
370
|
}
|
|
371
|
-
} catch (
|
|
371
|
+
} catch (_err) {
|
|
372
372
|
// Skip unreadable directories
|
|
373
373
|
}
|
|
374
374
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
const fs = require('node:fs');
|
|
14
14
|
const path = require('node:path');
|
|
15
15
|
const { RegistryPlugin } = require('../flow-registry-manager');
|
|
16
|
-
const {
|
|
16
|
+
const { safeJsonParse: safeJsonParseFile, PATHS, getTodayDate } = require('../flow-utils');
|
|
17
17
|
|
|
18
18
|
const INDEX_PATH = path.join(PATHS.state, 'service-index.json');
|
|
19
19
|
const MAP_PATH = path.join(PATHS.state, 'service-map.md');
|
|
@@ -314,12 +314,12 @@ class ServiceRegistry extends RegistryPlugin {
|
|
|
314
314
|
if (content.includes('NestMiddleware')) {
|
|
315
315
|
this._parseNestJSMiddleware(content, relPath, 'middleware');
|
|
316
316
|
}
|
|
317
|
-
} catch (
|
|
317
|
+
} catch (_err) {
|
|
318
318
|
// Skip unreadable files
|
|
319
319
|
}
|
|
320
320
|
}
|
|
321
321
|
}
|
|
322
|
-
} catch (
|
|
322
|
+
} catch (_err) {
|
|
323
323
|
// Skip unreadable directories
|
|
324
324
|
}
|
|
325
325
|
}
|
|
@@ -466,12 +466,12 @@ class ServiceRegistry extends RegistryPlugin {
|
|
|
466
466
|
file: relPath
|
|
467
467
|
});
|
|
468
468
|
}
|
|
469
|
-
} catch (
|
|
469
|
+
} catch (_err) {
|
|
470
470
|
// Skip
|
|
471
471
|
}
|
|
472
472
|
}
|
|
473
473
|
}
|
|
474
|
-
} catch (
|
|
474
|
+
} catch (_err) {
|
|
475
475
|
// Skip
|
|
476
476
|
}
|
|
477
477
|
}
|
|
@@ -523,12 +523,12 @@ class ServiceRegistry extends RegistryPlugin {
|
|
|
523
523
|
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
524
524
|
const relPath = path.relative(PATHS.root, fullPath);
|
|
525
525
|
this._parseDjangoFile(content, relPath);
|
|
526
|
-
} catch (
|
|
526
|
+
} catch (_err) {
|
|
527
527
|
// Skip
|
|
528
528
|
}
|
|
529
529
|
}
|
|
530
530
|
}
|
|
531
|
-
} catch (
|
|
531
|
+
} catch (_err) {
|
|
532
532
|
// Skip
|
|
533
533
|
}
|
|
534
534
|
}
|
|
@@ -589,12 +589,12 @@ class ServiceRegistry extends RegistryPlugin {
|
|
|
589
589
|
const relPath = path.relative(PATHS.root, fullPath);
|
|
590
590
|
this._parseGoFile(content, relPath);
|
|
591
591
|
}
|
|
592
|
-
} catch (
|
|
592
|
+
} catch (_err) {
|
|
593
593
|
// Skip
|
|
594
594
|
}
|
|
595
595
|
}
|
|
596
596
|
}
|
|
597
|
-
} catch (
|
|
597
|
+
} catch (_err) {
|
|
598
598
|
// Skip
|
|
599
599
|
}
|
|
600
600
|
}
|