wogiflow 2.4.2 → 2.4.4
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 +124 -0
- package/.claude/docs/claude-code-compatibility.md +51 -0
- package/.claude/docs/explore-agents.md +11 -0
- package/.claude/settings.json +12 -1
- package/.workflow/models/registry.json +1 -1
- package/bin/flow +11 -1
- package/lib/workspace-contracts.js +599 -0
- package/lib/workspace-intelligence.js +600 -0
- package/lib/workspace-messages.js +441 -0
- package/lib/workspace-routing.js +485 -0
- package/lib/workspace-sync.js +339 -0
- package/lib/workspace.js +1073 -0
- package/package.json +4 -4
- package/scripts/MEMORY-ARCHITECTURE.md +1 -1
- package/scripts/base-workflow-step.js +136 -0
- package/scripts/flow-adaptive-learning.js +8 -9
- package/scripts/flow-aggregate.js +11 -6
- package/scripts/flow-api-index.js +4 -6
- package/scripts/flow-assumption-detector.js +0 -2
- package/scripts/flow-audit.js +15 -2
- package/scripts/flow-auto-context.js +8 -12
- package/scripts/flow-auto-learn.js +49 -49
- package/scripts/flow-background.js +5 -6
- package/scripts/flow-bridge-state.js +8 -10
- package/scripts/flow-bulk-loop.js +1 -3
- package/scripts/flow-bulk-orchestrator.js +1 -3
- package/scripts/flow-cascade-completion.js +0 -2
- package/scripts/flow-cascade.js +4 -4
- package/scripts/flow-checkpoint.js +10 -13
- package/scripts/flow-code-intelligence.js +10 -12
- package/scripts/flow-community-sync.js +4 -4
- package/scripts/flow-community.js +12 -20
- package/scripts/flow-config-defaults.js +28 -2
- package/scripts/flow-config-interactive.js +9 -5
- package/scripts/flow-config-loader.js +49 -92
- package/scripts/flow-config-substitution.js +0 -2
- package/scripts/flow-context-estimator.js +4 -4
- package/scripts/flow-context-init.js +10 -12
- package/scripts/flow-context-manager.js +0 -2
- package/scripts/flow-context-scoring.js +2 -2
- package/scripts/flow-contract-scan.js +6 -9
- package/scripts/flow-correct.js +29 -27
- package/scripts/flow-correction-detector.js +5 -1
- package/scripts/flow-damage-control.js +47 -54
- package/scripts/flow-decisions-merge.js +4 -14
- package/scripts/flow-diff.js +5 -8
- package/scripts/flow-done-gates.js +786 -0
- package/scripts/flow-done-report.js +123 -0
- package/scripts/flow-done.js +71 -717
- package/scripts/flow-entropy-monitor.js +1 -3
- package/scripts/flow-eval-calibration.js +257 -0
- package/scripts/flow-eval-judge.js +10 -1
- package/scripts/flow-eval.js +14 -5
- package/scripts/flow-extraction-review.js +1 -0
- package/scripts/flow-failure-categories.js +0 -2
- package/scripts/flow-figma-confirm.js +5 -9
- package/scripts/flow-figma-generate.js +8 -10
- package/scripts/flow-figma-index.js +8 -10
- package/scripts/flow-figma-match.js +3 -5
- package/scripts/flow-figma-mcp-server.js +2 -4
- package/scripts/flow-figma-orchestrator.js +2 -3
- package/scripts/flow-figma-registry.js +2 -3
- package/scripts/flow-framework-resolver.js +0 -2
- package/scripts/flow-function-index.js +4 -6
- package/scripts/flow-gate-confidence.js +2 -2
- package/scripts/flow-gitignore.js +0 -2
- package/scripts/flow-guided-edit.js +5 -6
- package/scripts/flow-health.js +5 -6
- package/scripts/flow-hook-errors.js +6 -0
- package/scripts/flow-hook-status.js +263 -0
- package/scripts/flow-hooks.js +17 -29
- package/scripts/flow-http-client.js +9 -8
- package/scripts/flow-hybrid-interactive.js +7 -12
- package/scripts/flow-hybrid-test.js +12 -13
- package/scripts/flow-instruction-richness.js +1 -1
- package/scripts/flow-io.js +21 -4
- package/scripts/flow-knowledge-router.js +9 -3
- package/scripts/flow-learning-orchestrator.js +318 -13
- package/scripts/flow-links.js +5 -7
- package/scripts/flow-long-input-association.js +275 -0
- package/scripts/flow-long-input-chunking.js +1 -0
- package/scripts/flow-long-input-cli.js +0 -2
- package/scripts/flow-long-input-complexity.js +0 -2
- package/scripts/flow-long-input-constants.js +0 -2
- package/scripts/flow-long-input-contradictions.js +351 -0
- package/scripts/flow-long-input-detection.js +0 -2
- package/scripts/flow-long-input-passes.js +885 -0
- package/scripts/flow-long-input-stories.js +1 -1
- package/scripts/flow-long-input-voice.js +0 -2
- package/scripts/flow-long-input.js +425 -3005
- package/scripts/flow-loop-retry-learning.js +2 -3
- package/scripts/flow-lsp.js +3 -3
- package/scripts/flow-mcp-docs.js +3 -4
- package/scripts/flow-memory-db.js +6 -8
- package/scripts/flow-memory-sync.js +18 -11
- package/scripts/flow-metrics.js +1 -2
- package/scripts/flow-model-adapter.js +2 -3
- package/scripts/flow-model-config.js +72 -104
- package/scripts/flow-model-router.js +2 -2
- package/scripts/flow-model-types.js +0 -2
- package/scripts/flow-multi-approach.js +5 -6
- package/scripts/flow-orchestrate-context.js +3 -7
- package/scripts/flow-orchestrate-rollback.js +3 -8
- package/scripts/flow-orchestrate-state.js +8 -14
- package/scripts/flow-orchestrate-templates.js +2 -6
- package/scripts/flow-orchestrate-validator.js +5 -9
- package/scripts/flow-orchestrate.js +126 -103
- package/scripts/flow-output.js +0 -2
- package/scripts/flow-parallel.js +1 -1
- package/scripts/flow-paths.js +23 -2
- package/scripts/flow-pattern-enforcer.js +30 -28
- package/scripts/flow-pattern-extractor.js +3 -4
- package/scripts/flow-pending.js +0 -2
- package/scripts/flow-permissions.js +2 -3
- package/scripts/flow-plugin-registry.js +10 -12
- package/scripts/flow-prd-manager.js +1 -1
- package/scripts/flow-progress.js +7 -9
- package/scripts/flow-prompt-composer.js +3 -3
- package/scripts/flow-prompt-template.js +2 -2
- package/scripts/flow-providers.js +7 -4
- package/scripts/flow-registry-manager.js +7 -12
- package/scripts/flow-regression.js +9 -11
- package/scripts/flow-roadmap.js +2 -2
- package/scripts/flow-run-trace.js +16 -15
- package/scripts/flow-safety.js +2 -5
- package/scripts/flow-scanner-base.js +5 -7
- package/scripts/flow-scenario-engine.js +1 -5
- package/scripts/flow-security.js +29 -0
- package/scripts/flow-session-end.js +32 -41
- package/scripts/flow-session-learning.js +53 -49
- package/scripts/flow-setup-hooks.js +2 -3
- package/scripts/flow-skill-create.js +7 -12
- package/scripts/flow-skill-generator.js +12 -16
- package/scripts/flow-skill-learn.js +17 -8
- package/scripts/flow-skill-matcher.js +1 -2
- package/scripts/flow-spec-generator.js +2 -4
- package/scripts/flow-stack-wizard.js +5 -7
- package/scripts/flow-standards-learner.js +35 -16
- package/scripts/flow-start.js +2 -0
- package/scripts/flow-stats-collector.js +2 -2
- package/scripts/flow-status.js +10 -10
- package/scripts/flow-statusline-setup.js +2 -2
- package/scripts/flow-step-changelog.js +2 -3
- package/scripts/flow-step-comments.js +66 -81
- package/scripts/flow-step-complexity.js +50 -70
- package/scripts/flow-step-coverage.js +3 -5
- package/scripts/flow-step-knowledge.js +2 -3
- package/scripts/flow-step-pr-tests.js +64 -74
- package/scripts/flow-step-regression.js +3 -5
- package/scripts/flow-step-review.js +86 -103
- package/scripts/flow-step-security.js +111 -121
- package/scripts/flow-step-silent-failures.js +56 -83
- package/scripts/flow-step-simplifier.js +52 -70
- package/scripts/flow-story.js +4 -7
- package/scripts/flow-strict-adherence.js +3 -4
- package/scripts/flow-task-checkpoint.js +36 -5
- package/scripts/flow-task-enforcer.js +2 -24
- package/scripts/flow-tech-debt.js +1 -1
- package/scripts/flow-template-extractor.js +1 -0
- package/scripts/flow-templates.js +11 -13
- package/scripts/flow-test-api.js +9 -13
- package/scripts/flow-test-discovery.js +1 -1
- package/scripts/flow-test-generate.js +5 -9
- package/scripts/flow-test-integrity.js +3 -7
- package/scripts/flow-test-ui.js +5 -9
- package/scripts/flow-testing-deps.js +1 -3
- package/scripts/flow-tiered-learning.js +4 -4
- package/scripts/flow-todowrite-sync.js +1 -1
- package/scripts/flow-tokens.js +0 -2
- package/scripts/flow-verification-profile.js +6 -10
- package/scripts/flow-verify.js +12 -16
- package/scripts/flow-version-check.js +4 -12
- package/scripts/flow-webmcp-generator.js +3 -5
- package/scripts/flow-workflow-steps.js +0 -2
- package/scripts/flow-workflow.js +9 -11
- package/scripts/hooks/adapters/claude-code.js +31 -0
- package/scripts/hooks/core/config-change.js +1 -0
- package/scripts/hooks/core/extension-registry.js +0 -2
- package/scripts/hooks/core/instructions-loaded.js +1 -1
- package/scripts/hooks/core/observation-capture.js +5 -5
- package/scripts/hooks/core/phase-gate.js +5 -0
- package/scripts/hooks/core/post-compact.js +1 -12
- package/scripts/hooks/core/research-gate.js +2 -12
- package/scripts/hooks/core/routing-gate.js +6 -0
- package/scripts/hooks/core/task-completed.js +12 -0
- package/scripts/hooks/core/task-created.js +83 -0
- package/scripts/hooks/core/worktree-lifecycle.js +1 -1
- package/scripts/hooks/entry/claude-code/config-change.js +6 -29
- package/scripts/hooks/entry/claude-code/instructions-loaded.js +5 -30
- package/scripts/hooks/entry/claude-code/post-compact.js +4 -31
- package/scripts/hooks/entry/claude-code/post-tool-use.js +121 -172
- package/scripts/hooks/entry/claude-code/pre-tool-use.js +260 -361
- package/scripts/hooks/entry/claude-code/session-end.js +4 -28
- package/scripts/hooks/entry/claude-code/session-start.js +205 -243
- package/scripts/hooks/entry/claude-code/setup.js +8 -49
- package/scripts/hooks/entry/claude-code/stop.js +40 -72
- package/scripts/hooks/entry/claude-code/task-completed.js +4 -28
- package/scripts/hooks/entry/claude-code/task-created.js +15 -0
- package/scripts/hooks/entry/claude-code/user-prompt-submit.js +113 -195
- package/scripts/hooks/entry/claude-code/worktree-create.js +6 -25
- package/scripts/hooks/entry/claude-code/worktree-remove.js +6 -25
- package/scripts/hooks/entry/shared/hook-runner.js +99 -0
- package/scripts/hooks/entry/shared/read-stdin.js +0 -2
- package/scripts/postinstall.js +2 -0
- package/scripts/registries/api-registry.js +0 -2
- package/scripts/registries/component-registry.js +5 -9
- package/scripts/registries/contract-scanner.js +2 -9
- package/scripts/registries/function-registry.js +0 -2
- package/scripts/registries/schema-registry.js +14 -18
- package/scripts/registries/service-registry.js +23 -27
|
@@ -19,14 +19,12 @@ const path = require('node:path');
|
|
|
19
19
|
const memoryDb = require('./flow-memory-db');
|
|
20
20
|
const { getConfig } = require('./flow-config-loader');
|
|
21
21
|
const { color } = require('./flow-output');
|
|
22
|
-
const { getProjectRoot } = require('./flow-paths');
|
|
22
|
+
const { getProjectRoot, PATHS } = require('./flow-paths');
|
|
23
23
|
|
|
24
24
|
// ============================================================
|
|
25
25
|
// Configuration
|
|
26
26
|
// ============================================================
|
|
27
27
|
|
|
28
|
-
const PROJECT_ROOT = getProjectRoot();
|
|
29
|
-
|
|
30
28
|
// ============================================================
|
|
31
29
|
// Output Formatting
|
|
32
30
|
// ============================================================
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wogi Flow - Eval Calibration
|
|
5
|
+
*
|
|
6
|
+
* Stores and retrieves calibrated eval examples for anchoring judge scores.
|
|
7
|
+
* Prevents score drift by providing few-shot examples of what high and low
|
|
8
|
+
* scores look like in practice.
|
|
9
|
+
*
|
|
10
|
+
* Based on Anthropic's harness design research finding that "few-shot examples
|
|
11
|
+
* with detailed score breakdowns calibrated evaluator judgment, reducing score
|
|
12
|
+
* drift across iterations."
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* node flow-eval-calibration.js save <taskId> <quality> — save as calibration example
|
|
16
|
+
* node flow-eval-calibration.js get — get calibration examples for prompt injection
|
|
17
|
+
* node flow-eval-calibration.js list — list all calibration examples
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const path = require('node:path');
|
|
21
|
+
const fs = require('node:fs');
|
|
22
|
+
const { PATHS, safeJsonParse, writeJson } = require('./flow-utils');
|
|
23
|
+
|
|
24
|
+
// ============================================================
|
|
25
|
+
// Constants
|
|
26
|
+
// ============================================================
|
|
27
|
+
|
|
28
|
+
const CALIBRATION_PATH = path.join(PATHS.state, 'eval-calibration.json');
|
|
29
|
+
const MAX_EXAMPLES_PER_QUALITY = 3; // Keep 3 high, 3 low
|
|
30
|
+
|
|
31
|
+
// ============================================================
|
|
32
|
+
// Storage
|
|
33
|
+
// ============================================================
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Load calibration data
|
|
37
|
+
* @returns {Object} { high: [], low: [], lastUpdated }
|
|
38
|
+
*/
|
|
39
|
+
function loadCalibration() {
|
|
40
|
+
return safeJsonParse(CALIBRATION_PATH, {
|
|
41
|
+
high: [],
|
|
42
|
+
low: [],
|
|
43
|
+
lastUpdated: null
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Save a completed eval as a calibration example.
|
|
49
|
+
* Called after /wogi-eval produces scores.
|
|
50
|
+
*
|
|
51
|
+
* @param {Object} params
|
|
52
|
+
* @param {string} params.taskId — the task that was evaluated
|
|
53
|
+
* @param {string} params.quality — "high" or "low"
|
|
54
|
+
* @param {Object} params.scores — { completeness, accuracy, workflowCompliance, tokenEfficiency, quality }
|
|
55
|
+
* @param {string} params.specSummary — brief spec description (first 500 chars)
|
|
56
|
+
* @param {string} params.diffSummary — brief diff description (file count, line count)
|
|
57
|
+
* @param {string} params.notes — judge's justification notes
|
|
58
|
+
*/
|
|
59
|
+
function saveCalibrationExample(params) {
|
|
60
|
+
const { taskId, quality, scores, specSummary, diffSummary, notes } = params;
|
|
61
|
+
|
|
62
|
+
if (quality !== 'high' && quality !== 'low') {
|
|
63
|
+
throw new Error('Quality must be "high" or "low"');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const cal = loadCalibration();
|
|
67
|
+
const example = {
|
|
68
|
+
taskId,
|
|
69
|
+
scores,
|
|
70
|
+
specSummary: (specSummary || '').slice(0, 500),
|
|
71
|
+
diffSummary: (diffSummary || '').slice(0, 200),
|
|
72
|
+
notes: (notes || '').slice(0, 500),
|
|
73
|
+
savedAt: new Date().toISOString()
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
cal[quality].unshift(example);
|
|
77
|
+
|
|
78
|
+
// Keep only MAX_EXAMPLES_PER_QUALITY
|
|
79
|
+
if (cal[quality].length > MAX_EXAMPLES_PER_QUALITY) {
|
|
80
|
+
cal[quality] = cal[quality].slice(0, MAX_EXAMPLES_PER_QUALITY);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
cal.lastUpdated = new Date().toISOString();
|
|
84
|
+
writeJson(CALIBRATION_PATH, cal);
|
|
85
|
+
|
|
86
|
+
return example;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Auto-classify and save an eval result as calibration.
|
|
91
|
+
* High = average score >= 8. Low = average score <= 4.
|
|
92
|
+
*
|
|
93
|
+
* @param {Object} evalResult — from flow-eval.js
|
|
94
|
+
* @returns {Object|null} saved example or null if score is in the middle range
|
|
95
|
+
*/
|
|
96
|
+
function autoSaveFromEval(evalResult) {
|
|
97
|
+
if (!evalResult || !evalResult.scores) return null;
|
|
98
|
+
|
|
99
|
+
const scores = evalResult.scores;
|
|
100
|
+
const values = Object.values(scores).filter(v => typeof v === 'number');
|
|
101
|
+
if (values.length === 0) return null;
|
|
102
|
+
|
|
103
|
+
const avg = values.reduce((sum, v) => sum + v, 0) / values.length;
|
|
104
|
+
|
|
105
|
+
let quality = null;
|
|
106
|
+
if (avg >= 8) quality = 'high';
|
|
107
|
+
else if (avg <= 4) quality = 'low';
|
|
108
|
+
else return null; // Middle range — not a good calibration anchor
|
|
109
|
+
|
|
110
|
+
return saveCalibrationExample({
|
|
111
|
+
taskId: evalResult.taskId,
|
|
112
|
+
quality,
|
|
113
|
+
scores,
|
|
114
|
+
specSummary: evalResult.specSummary || '',
|
|
115
|
+
diffSummary: evalResult.diffSummary || '',
|
|
116
|
+
notes: evalResult.notes || ''
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ============================================================
|
|
121
|
+
// Retrieval (for prompt injection)
|
|
122
|
+
// ============================================================
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get calibration examples formatted for injection into judge/evaluator prompts.
|
|
126
|
+
* Returns 1 high + 1 low example (if available).
|
|
127
|
+
*
|
|
128
|
+
* @returns {string} formatted calibration text, or empty string if no examples
|
|
129
|
+
*/
|
|
130
|
+
function getCalibrationPrompt() {
|
|
131
|
+
const cal = loadCalibration();
|
|
132
|
+
const parts = [];
|
|
133
|
+
|
|
134
|
+
if (cal.high.length > 0) {
|
|
135
|
+
const ex = cal.high[0];
|
|
136
|
+
parts.push(`## Calibration Example: HIGH QUALITY (reference)
|
|
137
|
+
|
|
138
|
+
**Task**: ${ex.taskId}
|
|
139
|
+
**Spec**: ${ex.specSummary}
|
|
140
|
+
**Scores**: completeness=${ex.scores.completeness}, accuracy=${ex.scores.accuracy}, workflowCompliance=${ex.scores.workflowCompliance}, tokenEfficiency=${ex.scores.tokenEfficiency}, quality=${ex.scores.quality}
|
|
141
|
+
**Why this scored high**: ${ex.notes}`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (cal.low.length > 0) {
|
|
145
|
+
const ex = cal.low[0];
|
|
146
|
+
parts.push(`## Calibration Example: LOW QUALITY (reference)
|
|
147
|
+
|
|
148
|
+
**Task**: ${ex.taskId}
|
|
149
|
+
**Spec**: ${ex.specSummary}
|
|
150
|
+
**Scores**: completeness=${ex.scores.completeness}, accuracy=${ex.scores.accuracy}, workflowCompliance=${ex.scores.workflowCompliance}, tokenEfficiency=${ex.scores.tokenEfficiency}, quality=${ex.scores.quality}
|
|
151
|
+
**Why this scored low**: ${ex.notes}`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (parts.length === 0) return '';
|
|
155
|
+
|
|
156
|
+
return `
|
|
157
|
+
## Score Calibration (anchoring examples)
|
|
158
|
+
|
|
159
|
+
Use these real examples to calibrate your scoring. They represent the extremes of the scale — most tasks should score between these.
|
|
160
|
+
|
|
161
|
+
${parts.join('\n\n')}
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
`;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Get calibration examples as structured data
|
|
169
|
+
* @returns {{ high: Object|null, low: Object|null }}
|
|
170
|
+
*/
|
|
171
|
+
function getCalibrationExamples() {
|
|
172
|
+
const cal = loadCalibration();
|
|
173
|
+
return {
|
|
174
|
+
high: cal.high[0] || null,
|
|
175
|
+
low: cal.low[0] || null
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// ============================================================
|
|
180
|
+
// CLI
|
|
181
|
+
// ============================================================
|
|
182
|
+
|
|
183
|
+
function main() {
|
|
184
|
+
const args = process.argv.slice(2);
|
|
185
|
+
const command = args[0];
|
|
186
|
+
|
|
187
|
+
switch (command) {
|
|
188
|
+
case 'save': {
|
|
189
|
+
const taskId = args[1];
|
|
190
|
+
const quality = args[2];
|
|
191
|
+
if (!taskId || !quality) {
|
|
192
|
+
console.error('Usage: flow-eval-calibration.js save <taskId> <high|low>');
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
// Read scores from stdin or eval results
|
|
196
|
+
const evalsDir = path.join(PATHS.workflow, 'evals');
|
|
197
|
+
const evalFiles = fs.existsSync(evalsDir) ? fs.readdirSync(evalsDir).filter(f => f.includes(taskId)) : [];
|
|
198
|
+
if (evalFiles.length === 0) {
|
|
199
|
+
console.error(`No eval results found for task ${taskId}`);
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
const evalResult = safeJsonParse(path.join(evalsDir, evalFiles[0]), null);
|
|
203
|
+
if (evalResult) {
|
|
204
|
+
const saved = saveCalibrationExample({
|
|
205
|
+
taskId,
|
|
206
|
+
quality,
|
|
207
|
+
scores: evalResult.aggregated || evalResult.scores || {},
|
|
208
|
+
specSummary: evalResult.spec?.substring(0, 500) || '',
|
|
209
|
+
diffSummary: `${(evalResult.changedFiles || []).length} files changed`,
|
|
210
|
+
notes: evalResult.notes || evalResult.aggregated?.notes || ''
|
|
211
|
+
});
|
|
212
|
+
console.log(`Saved ${quality} calibration example: ${saved.taskId}`);
|
|
213
|
+
}
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
case 'get':
|
|
218
|
+
console.log(getCalibrationPrompt() || 'No calibration examples yet.');
|
|
219
|
+
break;
|
|
220
|
+
|
|
221
|
+
case 'list': {
|
|
222
|
+
const cal = loadCalibration();
|
|
223
|
+
console.log(`High examples: ${cal.high.length}`);
|
|
224
|
+
for (const ex of cal.high) {
|
|
225
|
+
const values = Object.values(ex.scores).filter(v => typeof v === 'number');
|
|
226
|
+
const avg = values.length > 0 ? values.reduce((s, v) => s + v, 0) / values.length : 0;
|
|
227
|
+
console.log(` ${ex.taskId} — avg ${avg.toFixed(1)} (${ex.savedAt})`);
|
|
228
|
+
}
|
|
229
|
+
console.log(`Low examples: ${cal.low.length}`);
|
|
230
|
+
for (const ex of cal.low) {
|
|
231
|
+
const values = Object.values(ex.scores).filter(v => typeof v === 'number');
|
|
232
|
+
const avg = values.length > 0 ? values.reduce((s, v) => s + v, 0) / values.length : 0;
|
|
233
|
+
console.log(` ${ex.taskId} — avg ${avg.toFixed(1)} (${ex.savedAt})`);
|
|
234
|
+
}
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
default:
|
|
239
|
+
console.log('Usage: flow-eval-calibration.js <save|get|list>');
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ============================================================
|
|
244
|
+
// Exports
|
|
245
|
+
// ============================================================
|
|
246
|
+
|
|
247
|
+
module.exports = {
|
|
248
|
+
loadCalibration,
|
|
249
|
+
saveCalibrationExample,
|
|
250
|
+
autoSaveFromEval,
|
|
251
|
+
getCalibrationPrompt,
|
|
252
|
+
getCalibrationExamples
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
if (require.main === module) {
|
|
256
|
+
main();
|
|
257
|
+
}
|
|
@@ -62,10 +62,19 @@ const DEFAULT_EVAL_CONFIG = {
|
|
|
62
62
|
function buildJudgePrompt(params) {
|
|
63
63
|
const { taskId, specContent, implementationDiff, iterations, tokenEstimate } = params;
|
|
64
64
|
|
|
65
|
+
// Inject calibration examples if available (prevents score drift)
|
|
66
|
+
let calibrationBlock = '';
|
|
67
|
+
try {
|
|
68
|
+
const { getCalibrationPrompt } = require('./flow-eval-calibration');
|
|
69
|
+
calibrationBlock = getCalibrationPrompt();
|
|
70
|
+
} catch (_err) {
|
|
71
|
+
// Calibration module not available — continue without it
|
|
72
|
+
}
|
|
73
|
+
|
|
65
74
|
return `You are an expert code reviewer evaluating AI-generated implementation quality.
|
|
66
75
|
|
|
67
76
|
## Task: ${taskId}
|
|
68
|
-
|
|
77
|
+
${calibrationBlock}
|
|
69
78
|
## Specification
|
|
70
79
|
${specContent}
|
|
71
80
|
|
package/scripts/flow-eval.js
CHANGED
|
@@ -35,7 +35,7 @@ const {
|
|
|
35
35
|
// Constants
|
|
36
36
|
// ============================================================
|
|
37
37
|
|
|
38
|
-
const EVALS_DIR =
|
|
38
|
+
const EVALS_DIR = PATHS.evals;
|
|
39
39
|
|
|
40
40
|
// ============================================================
|
|
41
41
|
// Core Functions
|
|
@@ -171,13 +171,13 @@ function getTaskDiff(taskId, taskRecord) {
|
|
|
171
171
|
function findSpecFile(taskId) {
|
|
172
172
|
// Check common locations
|
|
173
173
|
const candidates = [
|
|
174
|
-
path.join(PATHS.
|
|
175
|
-
path.join(PATHS.
|
|
174
|
+
path.join(PATHS.specs, `${taskId}.md`),
|
|
175
|
+
path.join(PATHS.changes, `${taskId}.md`)
|
|
176
176
|
];
|
|
177
177
|
|
|
178
178
|
// Also search subdirectories of changes/
|
|
179
179
|
try {
|
|
180
|
-
const changesDir =
|
|
180
|
+
const changesDir = PATHS.changes;
|
|
181
181
|
if (fs.existsSync(changesDir)) {
|
|
182
182
|
const entries = fs.readdirSync(changesDir, { withFileTypes: true });
|
|
183
183
|
for (const entry of entries) {
|
|
@@ -202,7 +202,7 @@ function findSpecFile(taskId) {
|
|
|
202
202
|
|
|
203
203
|
// Check ready.json for specPath
|
|
204
204
|
try {
|
|
205
|
-
const ready = readJson(
|
|
205
|
+
const ready = readJson(PATHS.ready, {});
|
|
206
206
|
const allTasks = [
|
|
207
207
|
...(ready.inProgress || []),
|
|
208
208
|
...(ready.ready || []),
|
|
@@ -248,6 +248,15 @@ function saveEvalResult(evalResult) {
|
|
|
248
248
|
|
|
249
249
|
try {
|
|
250
250
|
writeJson(filePath, evalResult);
|
|
251
|
+
|
|
252
|
+
// Auto-save as calibration example if scores are extreme (high or low)
|
|
253
|
+
try {
|
|
254
|
+
const { autoSaveFromEval } = require('./flow-eval-calibration');
|
|
255
|
+
autoSaveFromEval(evalResult);
|
|
256
|
+
} catch (_err) {
|
|
257
|
+
// Calibration module not available — non-critical
|
|
258
|
+
}
|
|
259
|
+
|
|
251
260
|
return filePath;
|
|
252
261
|
} catch (err) {
|
|
253
262
|
if (process.env.DEBUG) {
|
|
@@ -23,6 +23,7 @@ const REVIEW_FILE = path.join(TMP_DIR, 'review-session.json');
|
|
|
23
23
|
|
|
24
24
|
// Colors
|
|
25
25
|
const { colors: c } = require('./flow-output');
|
|
26
|
+
const { PATHS } = require('./flow-utils');
|
|
26
27
|
|
|
27
28
|
// =============================================================================
|
|
28
29
|
// REVIEW SESSION MANAGEMENT
|
|
@@ -13,12 +13,10 @@
|
|
|
13
13
|
|
|
14
14
|
const fs = require('node:fs');
|
|
15
15
|
const path = require('node:path');
|
|
16
|
-
const readline = require('node:readline');
|
|
17
|
-
const { getProjectRoot, colors: c, readJson } = require('./flow-utils');
|
|
16
|
+
const readline = require('node:readline/promises');
|
|
17
|
+
const { getProjectRoot, colors: c, readJson, PATHS } = require('./flow-utils');
|
|
18
18
|
|
|
19
|
-
const
|
|
20
|
-
const WORKFLOW_DIR = path.join(PROJECT_ROOT, '.workflow');
|
|
21
|
-
const DECISIONS_PATH = path.join(WORKFLOW_DIR, 'state', 'figma-decisions.json');
|
|
19
|
+
const DECISIONS_PATH = path.join(PATHS.workflow, 'state', 'figma-decisions.json');
|
|
22
20
|
|
|
23
21
|
const sym = {
|
|
24
22
|
check: '✅',
|
|
@@ -252,9 +250,7 @@ Let's go through each component:
|
|
|
252
250
|
}
|
|
253
251
|
|
|
254
252
|
prompt(question) {
|
|
255
|
-
return
|
|
256
|
-
this.rl.question(question, resolve);
|
|
257
|
-
});
|
|
253
|
+
return this.rl.question(question);
|
|
258
254
|
}
|
|
259
255
|
|
|
260
256
|
printSummary() {
|
|
@@ -295,7 +291,7 @@ ${c.bold}CONFIRMATION SUMMARY${c.reset}
|
|
|
295
291
|
decisions: this.decisions
|
|
296
292
|
}, null, 2));
|
|
297
293
|
|
|
298
|
-
console.log(`${c.dim}Decisions saved to: ${path.relative(
|
|
294
|
+
console.log(`${c.dim}Decisions saved to: ${path.relative(PATHS.root, DECISIONS_PATH)}${c.reset}`);
|
|
299
295
|
}
|
|
300
296
|
}
|
|
301
297
|
|
|
@@ -25,14 +25,12 @@ const { getProjectRoot,
|
|
|
25
25
|
getConfig,
|
|
26
26
|
addRequestLogEntry,
|
|
27
27
|
addAppMapComponent,
|
|
28
|
-
readJson
|
|
28
|
+
readJson, PATHS
|
|
29
29
|
} = require('./flow-utils')
|
|
30
30
|
const { error, info } = require('./flow-output');;
|
|
31
31
|
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
const DECISIONS_PATH = path.join(WORKFLOW_DIR, 'state', 'figma-decisions.json');
|
|
35
|
-
const REGISTRY_PATH = path.join(WORKFLOW_DIR, 'state', 'component-registry.json');
|
|
32
|
+
const DECISIONS_PATH = path.join(PATHS.workflow, 'state', 'figma-decisions.json');
|
|
33
|
+
const REGISTRY_PATH = path.join(PATHS.workflow, 'state', 'component-registry.json');
|
|
36
34
|
|
|
37
35
|
// ============================================================
|
|
38
36
|
// Framework-Specific Templates
|
|
@@ -231,7 +229,7 @@ export class {{name}}Component {
|
|
|
231
229
|
class CodeGenerator {
|
|
232
230
|
constructor(decisions, options = {}) {
|
|
233
231
|
this.decisions = Array.isArray(decisions) ? decisions : decisions.decisions || [];
|
|
234
|
-
this.framework = options.framework || detectFramework(
|
|
232
|
+
this.framework = options.framework || detectFramework(PATHS.root);
|
|
235
233
|
this.templates = FRAMEWORK_TEMPLATES[this.framework] || FRAMEWORK_TEMPLATES.react;
|
|
236
234
|
this.registry = this.loadRegistry();
|
|
237
235
|
|
|
@@ -497,7 +495,7 @@ ${this.formatCSSPropertiesForPrompt(figma.css)}
|
|
|
497
495
|
|
|
498
496
|
_detectSourceRoot() {
|
|
499
497
|
for (const dir of ['src', 'app', 'lib']) {
|
|
500
|
-
if (fs.existsSync(path.join(
|
|
498
|
+
if (fs.existsSync(path.join(PATHS.root, dir))) return dir;
|
|
501
499
|
}
|
|
502
500
|
return '.';
|
|
503
501
|
}
|
|
@@ -633,9 +631,9 @@ Framework: ${output.framework}
|
|
|
633
631
|
}
|
|
634
632
|
|
|
635
633
|
// Save output
|
|
636
|
-
const outputPath = path.join(
|
|
634
|
+
const outputPath = path.join(PATHS.workflow, 'state', 'figma-output.json');
|
|
637
635
|
fs.writeFileSync(outputPath, JSON.stringify(output, null, 2));
|
|
638
|
-
info(`� Full output saved to: ${path.relative(
|
|
636
|
+
info(`� Full output saved to: ${path.relative(PATHS.root, outputPath)}`);
|
|
639
637
|
|
|
640
638
|
// Print prompts for new components
|
|
641
639
|
if (output.prompts.length > 0) {
|
|
@@ -668,7 +666,7 @@ ${'─'.repeat(70)}
|
|
|
668
666
|
tags: ['#figma', ...componentNames.slice(0, 3).map(n => `#component:${n}`)],
|
|
669
667
|
request: 'Figma design analysis and code generation',
|
|
670
668
|
result: `Generated: ${summary.join(', ')}`,
|
|
671
|
-
files: [path.relative(
|
|
669
|
+
files: [path.relative(PATHS.root, outputPath)]
|
|
672
670
|
});
|
|
673
671
|
|
|
674
672
|
console.log('\n📝 Logged to request-log.md');
|
|
@@ -16,12 +16,10 @@
|
|
|
16
16
|
|
|
17
17
|
const fs = require('node:fs');
|
|
18
18
|
const path = require('node:path');
|
|
19
|
-
const { getProjectRoot, readJson } = require('./flow-utils');
|
|
19
|
+
const { getProjectRoot, readJson, PATHS } = require('./flow-utils');
|
|
20
20
|
const { success: printSuccess, error: printError, info: printInfo } = require('./flow-output');
|
|
21
21
|
|
|
22
|
-
const
|
|
23
|
-
const WORKFLOW_DIR = path.join(PROJECT_ROOT, '.workflow');
|
|
24
|
-
const REGISTRY_PATH = path.join(WORKFLOW_DIR, 'state', 'component-registry.json');
|
|
22
|
+
const REGISTRY_PATH = path.join(PATHS.workflow, 'state', 'component-registry.json');
|
|
25
23
|
|
|
26
24
|
// ============================================================
|
|
27
25
|
// Configuration
|
|
@@ -97,11 +95,11 @@ function detectFramework(projectRoot) {
|
|
|
97
95
|
class ComponentScanner {
|
|
98
96
|
constructor(config = {}) {
|
|
99
97
|
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
100
|
-
this.framework = detectFramework(
|
|
98
|
+
this.framework = detectFramework(PATHS.root);
|
|
101
99
|
this.registry = {
|
|
102
100
|
version: '1.0.0',
|
|
103
101
|
scannedAt: null,
|
|
104
|
-
projectRoot:
|
|
102
|
+
projectRoot: PATHS.root,
|
|
105
103
|
framework: this.framework,
|
|
106
104
|
components: [],
|
|
107
105
|
tokens: {
|
|
@@ -136,7 +134,7 @@ class ComponentScanner {
|
|
|
136
134
|
return null;
|
|
137
135
|
}
|
|
138
136
|
|
|
139
|
-
console.log(` Component directory: ${path.relative(
|
|
137
|
+
console.log(` Component directory: ${path.relative(PATHS.root, componentDir)}`);
|
|
140
138
|
console.log(` Parser: ${this.parser ? 'Babel AST' : 'Regex-based'}`);
|
|
141
139
|
|
|
142
140
|
// Scan for tokens first
|
|
@@ -154,14 +152,14 @@ class ComponentScanner {
|
|
|
154
152
|
this.saveRegistry();
|
|
155
153
|
|
|
156
154
|
printSuccess(`Found ${this.registry.components.length} components`);
|
|
157
|
-
console.log(`📄 Registry saved to: ${path.relative(
|
|
155
|
+
console.log(`📄 Registry saved to: ${path.relative(PATHS.root, REGISTRY_PATH)}`);
|
|
158
156
|
|
|
159
157
|
return this.registry;
|
|
160
158
|
}
|
|
161
159
|
|
|
162
160
|
findComponentDir() {
|
|
163
161
|
for (const dir of this.config.componentDirs) {
|
|
164
|
-
const fullPath = path.join(
|
|
162
|
+
const fullPath = path.join(PATHS.root, dir);
|
|
165
163
|
if (fs.existsSync(fullPath)) {
|
|
166
164
|
return fullPath;
|
|
167
165
|
}
|
|
@@ -173,7 +171,7 @@ class ComponentScanner {
|
|
|
173
171
|
console.log('\n📊 Scanning design tokens...');
|
|
174
172
|
|
|
175
173
|
for (const tokenSource of this.config.tokenSources) {
|
|
176
|
-
const fullPath = path.join(
|
|
174
|
+
const fullPath = path.join(PATHS.root, tokenSource);
|
|
177
175
|
if (fs.existsSync(fullPath)) {
|
|
178
176
|
console.log(` Found: ${tokenSource}`);
|
|
179
177
|
await this.parseTokenFile(fullPath);
|
|
@@ -14,12 +14,10 @@
|
|
|
14
14
|
|
|
15
15
|
const fs = require('node:fs');
|
|
16
16
|
const path = require('node:path');
|
|
17
|
-
const { getProjectRoot, safeJsonParse, safeJsonParseString } = require('./flow-utils')
|
|
17
|
+
const { getProjectRoot, safeJsonParse, safeJsonParseString, PATHS } = require('./flow-utils')
|
|
18
18
|
const { error } = require('./flow-output');;
|
|
19
19
|
|
|
20
|
-
const
|
|
21
|
-
const WORKFLOW_DIR = path.join(PROJECT_ROOT, '.workflow');
|
|
22
|
-
const REGISTRY_PATH = path.join(WORKFLOW_DIR, 'state', 'component-registry.json');
|
|
20
|
+
const REGISTRY_PATH = path.join(PATHS.workflow, 'state', 'component-registry.json');
|
|
23
21
|
|
|
24
22
|
// ============================================================
|
|
25
23
|
// Matching Configuration
|
|
@@ -553,7 +551,7 @@ async function main() {
|
|
|
553
551
|
|
|
554
552
|
if (figmaRegistryIndex !== -1) {
|
|
555
553
|
// Use the Figma-sourced multi-page registry
|
|
556
|
-
const figmaRegistryPath = path.join(
|
|
554
|
+
const figmaRegistryPath = path.join(PATHS.workflow, 'state', 'figma-component-registry.json');
|
|
557
555
|
if (!fs.existsSync(figmaRegistryPath)) {
|
|
558
556
|
error('Figma component registry not found.');
|
|
559
557
|
console.error(' Run the multi-page scan first.');
|
|
@@ -31,11 +31,9 @@ const { ComponentScanner } = require('./flow-figma-index');
|
|
|
31
31
|
const { FigmaExtractor } = require('./flow-figma-extract');
|
|
32
32
|
const { SimilarityMatcher, MATCH_CONFIG } = require('./flow-figma-match');
|
|
33
33
|
const { CodeGenerator } = require('./flow-figma-generate');
|
|
34
|
-
const { getProjectRoot, readJson } = require('./flow-utils');
|
|
34
|
+
const { getProjectRoot, readJson, PATHS } = require('./flow-utils');
|
|
35
35
|
|
|
36
|
-
const
|
|
37
|
-
const WORKFLOW_DIR = path.join(PROJECT_ROOT, '.workflow');
|
|
38
|
-
const REGISTRY_PATH = path.join(WORKFLOW_DIR, 'state', 'component-registry.json');
|
|
36
|
+
const REGISTRY_PATH = path.join(PATHS.workflow, 'state', 'component-registry.json');
|
|
39
37
|
|
|
40
38
|
// ============================================================
|
|
41
39
|
// Tool Definitions
|
|
@@ -20,13 +20,12 @@
|
|
|
20
20
|
|
|
21
21
|
const fs = require('node:fs');
|
|
22
22
|
const path = require('node:path');
|
|
23
|
-
const { getProjectRoot, writeJson, readJson } = require('./flow-utils');
|
|
23
|
+
const { getProjectRoot, writeJson, readJson, PATHS } = require('./flow-utils');
|
|
24
24
|
const { FigmaExtractor } = require('./flow-figma-extract');
|
|
25
25
|
const { FigmaComponentRegistry } = require('./flow-figma-registry');
|
|
26
26
|
const { FigmaStateAnalyzer } = require('./flow-figma-state-analyzer');
|
|
27
27
|
|
|
28
|
-
const
|
|
29
|
-
const ORCHESTRATOR_STATE_PATH = path.join(PROJECT_ROOT, '.workflow', 'state', 'figma-orchestrator-state.json');
|
|
28
|
+
const ORCHESTRATOR_STATE_PATH = path.join(PATHS.state, 'figma-orchestrator-state.json');
|
|
30
29
|
|
|
31
30
|
// ============================================================
|
|
32
31
|
// Orchestrator
|
|
@@ -15,11 +15,10 @@
|
|
|
15
15
|
|
|
16
16
|
const fs = require('node:fs');
|
|
17
17
|
const path = require('node:path');
|
|
18
|
-
const { getProjectRoot, readJson, writeJson } = require('./flow-utils');
|
|
18
|
+
const { getProjectRoot, readJson, writeJson, PATHS } = require('./flow-utils');
|
|
19
19
|
const { SimilarityMatcher, MATCH_CONFIG } = require('./flow-figma-match');
|
|
20
20
|
|
|
21
|
-
const
|
|
22
|
-
const REGISTRY_PATH = path.join(PROJECT_ROOT, '.workflow', 'state', 'figma-component-registry.json');
|
|
21
|
+
const REGISTRY_PATH = path.join(PATHS.state, 'figma-component-registry.json');
|
|
23
22
|
|
|
24
23
|
// ============================================================
|
|
25
24
|
// Registry Data Structure
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
const fs = require('node:fs');
|
|
17
17
|
const path = require('node:path');
|
|
18
|
-
const { getProjectRoot, getConfig, color, success, warn, error, safeJsonParse } = require('./flow-utils');
|
|
18
|
+
const { getProjectRoot, getConfig, color, success, warn, error, safeJsonParse, PATHS } = require('./flow-utils');
|
|
19
19
|
const {
|
|
20
20
|
findSimilarItems,
|
|
21
21
|
generateAIDecisionPrompt,
|
|
@@ -24,10 +24,8 @@ const {
|
|
|
24
24
|
} = require('./flow-semantic-match');
|
|
25
25
|
const { BaseScanner, PROJECT_ROOT } = require('./flow-scanner-base');
|
|
26
26
|
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const INDEX_PATH = path.join(STATE_DIR, 'function-index.json');
|
|
30
|
-
const MAP_PATH = path.join(STATE_DIR, 'function-map.md');
|
|
27
|
+
const INDEX_PATH = path.join(PATHS.state, 'function-index.json');
|
|
28
|
+
const MAP_PATH = path.join(PATHS.state, 'function-map.md');
|
|
31
29
|
|
|
32
30
|
// ============================================================
|
|
33
31
|
// Configuration
|
|
@@ -344,7 +342,7 @@ class FunctionScanner extends BaseScanner {
|
|
|
344
342
|
*/
|
|
345
343
|
save() {
|
|
346
344
|
this.prune();
|
|
347
|
-
fs.mkdirSync(
|
|
345
|
+
fs.mkdirSync(PATHS.state, { recursive: true });
|
|
348
346
|
fs.writeFileSync(INDEX_PATH, JSON.stringify(this.registry, null, 2));
|
|
349
347
|
success(`Saved to ${path.relative(PROJECT_ROOT, INDEX_PATH)}`);
|
|
350
348
|
}
|
|
@@ -36,7 +36,7 @@ const {
|
|
|
36
36
|
outputJson,
|
|
37
37
|
printHeader,
|
|
38
38
|
printSection,
|
|
39
|
-
safeJsonParse
|
|
39
|
+
safeJsonParse, PATHS
|
|
40
40
|
} = require('./flow-utils');
|
|
41
41
|
|
|
42
42
|
// ============================================================
|
|
@@ -178,7 +178,7 @@ const DEFAULT_GATE_CONFIG = {
|
|
|
178
178
|
// State
|
|
179
179
|
// ============================================================
|
|
180
180
|
|
|
181
|
-
const STATE_PATH = path.join(
|
|
181
|
+
const STATE_PATH = path.join(PATHS.state, 'gate-confidence.json');
|
|
182
182
|
|
|
183
183
|
/**
|
|
184
184
|
* Get default confidence state.
|