wogiflow 1.8.5 → 1.8.7
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/settings.json +1 -1
- package/.workflow/bridges/claude-bridge.js +12 -5
- package/lib/installer.js +44 -43
- package/package.json +1 -1
- package/scripts/flow-auto-context.js +23 -15
- package/scripts/flow-auto-learn.js +1 -0
- package/scripts/flow-config-loader.js +89 -8
- package/scripts/flow-constants.js +4 -1
- package/scripts/flow-context-compact/expander.js +1 -1
- package/scripts/flow-context-compact/section-extractor.js +1 -1
- package/scripts/flow-context-compact/summary-tree.js +1 -1
- package/scripts/flow-correction-detector.js +362 -136
- package/scripts/flow-health.js +11 -0
- package/scripts/flow-hooks.js +12 -5
- package/scripts/flow-review-passes/structure.js +1 -1
- package/scripts/flow-session-end.js +25 -9
- package/scripts/flow-standards-gate.js +1 -1
- package/scripts/flow-start.js +1 -1
- package/scripts/hooks/core/component-check.js +5 -6
- package/scripts/hooks/core/implementation-gate.js +1 -2
- package/scripts/hooks/core/loop-check.js +1 -2
- package/scripts/hooks/core/routing-gate.js +11 -11
- package/scripts/hooks/core/scope-gate.js +1 -1
- package/scripts/hooks/core/session-context.js +34 -0
- package/scripts/hooks/core/task-gate.js +3 -5
- package/scripts/hooks/core/todowrite-gate.js +2 -4
- package/scripts/hooks/entry/claude-code/user-prompt-submit.js +33 -34
- package/scripts/postinstall.js +1 -1
package/.claude/settings.json
CHANGED
|
@@ -327,16 +327,23 @@ Last synced: ${new Date().toISOString()}
|
|
|
327
327
|
// Do not override - see security-patterns.md rule #2
|
|
328
328
|
|
|
329
329
|
/**
|
|
330
|
-
* Get installed WogiFlow version from
|
|
330
|
+
* Get installed WogiFlow version from package.json (canonical source)
|
|
331
331
|
* @returns {string} Version string or 'unknown'
|
|
332
332
|
*/
|
|
333
333
|
_getInstalledVersion() {
|
|
334
334
|
try {
|
|
335
|
-
const
|
|
336
|
-
const
|
|
337
|
-
return
|
|
335
|
+
const pkgPath = path.join(this.projectDir, 'node_modules', 'wogiflow', 'package.json');
|
|
336
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
337
|
+
return pkg.version || 'unknown';
|
|
338
338
|
} catch (err) {
|
|
339
|
-
|
|
339
|
+
// Fallback: try settings.json (legacy)
|
|
340
|
+
try {
|
|
341
|
+
const settingsPath = path.join(this.projectDir, this.cliFolder, 'settings.json');
|
|
342
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
343
|
+
return settings._wogiFlowVersion || 'unknown';
|
|
344
|
+
} catch (err) {
|
|
345
|
+
return 'unknown';
|
|
346
|
+
}
|
|
340
347
|
}
|
|
341
348
|
}
|
|
342
349
|
|
package/lib/installer.js
CHANGED
|
@@ -40,7 +40,6 @@ const DEFAULT_CONFIG = {
|
|
|
40
40
|
version: PACKAGE_VERSION,
|
|
41
41
|
projectName: '',
|
|
42
42
|
cliKey: 'claude',
|
|
43
|
-
strictMode: true,
|
|
44
43
|
projectType: 'unknown'
|
|
45
44
|
};
|
|
46
45
|
|
|
@@ -77,7 +76,17 @@ function getDefaultConfig(overrides = {}) {
|
|
|
77
76
|
small: { maxFiles: 3, maxHours: 1 },
|
|
78
77
|
medium: { maxFiles: 10, maxHours: 4 },
|
|
79
78
|
large: { minFiles: 10, minHours: 4 }
|
|
80
|
-
}
|
|
79
|
+
},
|
|
80
|
+
taskGating: { enabled: true, blockWithoutTask: true, autoCreateTask: false },
|
|
81
|
+
scopeGating: {
|
|
82
|
+
enabled: true,
|
|
83
|
+
mode: 'warn',
|
|
84
|
+
exemptPatterns: ['.workflow/state/**', '.workflow/specs/**', '.workflow/plans/**', 'package.json', 'package-lock.json', 'tsconfig.json']
|
|
85
|
+
},
|
|
86
|
+
implementationGate: { enabled: true },
|
|
87
|
+
todoWriteGate: { enabled: true, blockImplementationWithoutTask: true },
|
|
88
|
+
routingGate: { enabled: true },
|
|
89
|
+
loopEnforcement: { enabled: true }
|
|
81
90
|
},
|
|
82
91
|
execution: {
|
|
83
92
|
maxIterations: 20,
|
|
@@ -104,6 +113,12 @@ function getDefaultConfig(overrides = {}) {
|
|
|
104
113
|
simpleMode: { enabled: false },
|
|
105
114
|
recheckAllAfterFix: true,
|
|
106
115
|
regressionOnRecheck: 'warn'
|
|
116
|
+
},
|
|
117
|
+
tdd: {
|
|
118
|
+
enforced: true,
|
|
119
|
+
defaultForTypes: ['bugfix'],
|
|
120
|
+
requireFailingTestFirst: true,
|
|
121
|
+
testFrameworkDetection: true
|
|
107
122
|
}
|
|
108
123
|
},
|
|
109
124
|
errorRecovery: {
|
|
@@ -114,8 +129,7 @@ function getDefaultConfig(overrides = {}) {
|
|
|
114
129
|
maxAttemptsPerLevel: 3,
|
|
115
130
|
architecturalReassessment: { enabled: false },
|
|
116
131
|
recursive: { enabled: false },
|
|
117
|
-
hypothesisGeneration: { usePatterns: true, useAI: false, aiModel: 'haiku' }
|
|
118
|
-
learning: { recordSuccessfulFixes: true, recordFailedHypotheses: true }
|
|
132
|
+
hypothesisGeneration: { usePatterns: true, useAI: false, aiModel: 'haiku' }
|
|
119
133
|
},
|
|
120
134
|
workflow: { planningStyle: 'feature-based', agentStructure: 'unified' },
|
|
121
135
|
parallelExecution: {
|
|
@@ -195,30 +209,24 @@ function getDefaultConfig(overrides = {}) {
|
|
|
195
209
|
scopeByTaskType: true,
|
|
196
210
|
alwaysCheck: ['naming', 'security'],
|
|
197
211
|
similarityThreshold: 0.8,
|
|
198
|
-
similarityWarningThreshold: 0.6
|
|
199
|
-
learning: { enabled: false }
|
|
200
|
-
},
|
|
201
|
-
validation: {
|
|
202
|
-
afterFileEdit: { enabled: false },
|
|
203
|
-
afterTaskComplete: { enabled: false },
|
|
204
|
-
beforeCommit: { enabled: false }
|
|
212
|
+
similarityWarningThreshold: 0.6
|
|
205
213
|
},
|
|
206
214
|
checkpoint: { enabled: false },
|
|
207
215
|
regressionTesting: { enabled: false },
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
defaultForTypes: ['bugfix'],
|
|
211
|
-
requireFailingTestFirst: true,
|
|
212
|
-
testFrameworkDetection: true
|
|
213
|
-
},
|
|
214
|
-
componentRules: {
|
|
216
|
+
componentReuse: {
|
|
217
|
+
enabled: true,
|
|
215
218
|
preferVariants: true,
|
|
216
219
|
requireAppMapEntry: true,
|
|
217
220
|
requireDetailDoc: false,
|
|
218
221
|
autoGenerateStorybook: false,
|
|
219
|
-
storybookPath: 'src/stories'
|
|
222
|
+
storybookPath: 'src/stories',
|
|
223
|
+
threshold: 30,
|
|
224
|
+
allRegistries: true,
|
|
225
|
+
aiAsJudge: true,
|
|
226
|
+
blockOnSimilar: false,
|
|
227
|
+
injectContext: true
|
|
220
228
|
},
|
|
221
|
-
|
|
229
|
+
reporting: {
|
|
222
230
|
verificationChecklist: false,
|
|
223
231
|
correctionReportsOnFail: false,
|
|
224
232
|
featureReportsOnComplete: false
|
|
@@ -249,7 +257,10 @@ function getDefaultConfig(overrides = {}) {
|
|
|
249
257
|
modelSpecificLearning: true
|
|
250
258
|
},
|
|
251
259
|
modelAdapters: { enabled: false },
|
|
252
|
-
skill: { enabled: false }
|
|
260
|
+
skill: { enabled: false },
|
|
261
|
+
standardsLearning: { enabled: false },
|
|
262
|
+
errorRecoveryLearning: { enabled: false },
|
|
263
|
+
bugFlowLearning: { enabled: false }
|
|
253
264
|
},
|
|
254
265
|
bugFlow: {
|
|
255
266
|
investigationAgents: {
|
|
@@ -258,7 +269,6 @@ function getDefaultConfig(overrides = {}) {
|
|
|
258
269
|
dependencyAnalyzer: { enabled: false }
|
|
259
270
|
},
|
|
260
271
|
autoRoute: true,
|
|
261
|
-
learningEnforcement: { enabled: false },
|
|
262
272
|
inlineDiscovery: {
|
|
263
273
|
maxSearchOperations: 3,
|
|
264
274
|
maxFileReads: 2,
|
|
@@ -299,7 +309,7 @@ function getDefaultConfig(overrides = {}) {
|
|
|
299
309
|
promotion: { enabled: false }
|
|
300
310
|
},
|
|
301
311
|
prd: { enabled: false },
|
|
302
|
-
|
|
312
|
+
contextManagement: {
|
|
303
313
|
compaction: {
|
|
304
314
|
enabled: false,
|
|
305
315
|
thresholds: { warnAt: 50000, compactAt: 80000, maxExpanded: 20000 },
|
|
@@ -328,8 +338,9 @@ function getDefaultConfig(overrides = {}) {
|
|
|
328
338
|
useHaiku: true,
|
|
329
339
|
phases: ['exploring', 'spec_review', 'scenario', 'criteria_check', 'validating']
|
|
330
340
|
},
|
|
331
|
-
|
|
332
|
-
|
|
341
|
+
monitor: { enabled: false }
|
|
342
|
+
},
|
|
343
|
+
taskContext: {
|
|
333
344
|
auto: {
|
|
334
345
|
enabled: false,
|
|
335
346
|
strategy: 'dynamic',
|
|
@@ -346,6 +357,7 @@ function getDefaultConfig(overrides = {}) {
|
|
|
346
357
|
fallbackLimits: { maxFilesHard: 50, maxTokensHard: 150000 },
|
|
347
358
|
lspEnrichment: { enabled: false }
|
|
348
359
|
},
|
|
360
|
+
scoring: { enabled: false },
|
|
349
361
|
session: { enabled: false }
|
|
350
362
|
},
|
|
351
363
|
eval: {
|
|
@@ -525,34 +537,23 @@ function getDefaultConfig(overrides = {}) {
|
|
|
525
537
|
},
|
|
526
538
|
multiApproach: { enabled: false },
|
|
527
539
|
hooks: {
|
|
528
|
-
enabled:
|
|
540
|
+
enabled: true,
|
|
529
541
|
targets: ['claude-code'],
|
|
530
542
|
gracefulDegradation: true,
|
|
531
543
|
timeout: 600000,
|
|
532
544
|
rules: {
|
|
533
|
-
enforcement: {
|
|
534
|
-
taskGating: { enabled: false, blockWithoutTask: true, autoCreateTask: false },
|
|
535
|
-
scopeGating: {
|
|
536
|
-
enabled: false,
|
|
537
|
-
mode: 'warn',
|
|
538
|
-
exemptPatterns: ['.workflow/state/**', '.workflow/specs/**', '.workflow/plans/**', 'package.json', 'package-lock.json', 'tsconfig.json']
|
|
539
|
-
},
|
|
540
|
-
implementationGate: { enabled: false },
|
|
541
|
-
todoWriteGate: { enabled: false, blockImplementationWithoutTask: true },
|
|
542
|
-
routingGate: { enabled: false },
|
|
543
|
-
loopEnforcement: { enabled: false }
|
|
544
|
-
},
|
|
545
545
|
intelligence: {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
546
|
+
sessionContext: { enabled: true, loadSuspendedTasks: true, loadDecisions: true, loadRecentActivity: true },
|
|
547
|
+
promptCapture: { enabled: true },
|
|
548
|
+
correctionDetection: { enabled: true },
|
|
549
|
+
validation: { enabled: true, runAfterEdit: true, afterTaskComplete: false, beforeCommit: false }
|
|
549
550
|
},
|
|
550
551
|
lifecycle: {
|
|
551
|
-
taskCompleted: { enabled:
|
|
552
|
+
taskCompleted: { enabled: true },
|
|
552
553
|
completionSummaries: { enabled: true },
|
|
553
554
|
autoLogging: { enabled: false },
|
|
554
555
|
configChange: { enabled: false },
|
|
555
|
-
setup: { enabled:
|
|
556
|
+
setup: { enabled: true, autoOnboard: false, maintenanceTasks: ['healthCheck', 'cleanupLocks'] },
|
|
556
557
|
sessionCleanup: { enabled: true },
|
|
557
558
|
phaseGate: { enabled: true }
|
|
558
559
|
}
|
package/package.json
CHANGED
|
@@ -356,7 +356,8 @@ function searchComponentIndex(keywords, config = null) {
|
|
|
356
356
|
|
|
357
357
|
// Use config values if available
|
|
358
358
|
const cfg = config || getConfig();
|
|
359
|
-
const
|
|
359
|
+
const autoCfg = cfg.taskContext?.auto || cfg.context?.auto;
|
|
360
|
+
const maxComponentMatches = autoCfg?.maxComponentMatches || 15;
|
|
360
361
|
|
|
361
362
|
try {
|
|
362
363
|
// Use safeJsonParse for prototype pollution protection
|
|
@@ -419,8 +420,9 @@ function grepCodebase(keywords, maxResults = 10, config = null) {
|
|
|
419
420
|
|
|
420
421
|
// Use config values if available
|
|
421
422
|
const cfg = config || getConfig();
|
|
422
|
-
const
|
|
423
|
-
const
|
|
423
|
+
const grepAutoCfg = cfg.taskContext?.auto || cfg.context?.auto;
|
|
424
|
+
const effectiveMaxResults = grepAutoCfg?.maxGrepResults || maxResults;
|
|
425
|
+
const maxContentLines = grepAutoCfg?.maxContentLines || 50;
|
|
424
426
|
|
|
425
427
|
// Only grep for high-value keywords to avoid noise
|
|
426
428
|
const searchKeywords = keywords.high.slice(0, 5);
|
|
@@ -454,7 +456,7 @@ function grepCodebase(keywords, maxResults = 10, config = null) {
|
|
|
454
456
|
if (!results.some(r => r.path === relPath)) {
|
|
455
457
|
// Optionally read file content with truncation
|
|
456
458
|
let content = null;
|
|
457
|
-
if (
|
|
459
|
+
if (grepAutoCfg?.includeContent && isPathWithinProject(file)) {
|
|
458
460
|
try {
|
|
459
461
|
const fullContent = fs.readFileSync(file, 'utf-8');
|
|
460
462
|
const lines = fullContent.split('\n');
|
|
@@ -558,7 +560,8 @@ async function searchSemanticMemory(keywords, config = null) {
|
|
|
558
560
|
if (!cfg.memory?.enabled) return [];
|
|
559
561
|
|
|
560
562
|
const results = [];
|
|
561
|
-
const
|
|
563
|
+
const semAutoCfg = cfg.taskContext?.auto || cfg.context?.auto;
|
|
564
|
+
const maxFacts = semAutoCfg?.maxSemanticFacts || 5;
|
|
562
565
|
|
|
563
566
|
try {
|
|
564
567
|
// Build query from high-value keywords
|
|
@@ -604,7 +607,8 @@ async function searchSemanticMemory(keywords, config = null) {
|
|
|
604
607
|
*/
|
|
605
608
|
async function enrichWithLSP(fileResults, config) {
|
|
606
609
|
// Skip if disabled
|
|
607
|
-
|
|
610
|
+
const autoConfig = config.taskContext?.auto || config.context?.auto;
|
|
611
|
+
if (!autoConfig?.lspEnrichment?.enabled) return fileResults;
|
|
608
612
|
|
|
609
613
|
// Lazy load LSP module to avoid circular dependencies
|
|
610
614
|
let getLSP, isLSPEnabled;
|
|
@@ -621,8 +625,8 @@ async function enrichWithLSP(fileResults, config) {
|
|
|
621
625
|
const lsp = await getLSP();
|
|
622
626
|
if (!lsp) return fileResults;
|
|
623
627
|
|
|
624
|
-
const timeout =
|
|
625
|
-
const maxFiles =
|
|
628
|
+
const timeout = autoConfig?.lspEnrichment?.timeoutMs || 2000;
|
|
629
|
+
const maxFiles = autoConfig?.lspEnrichment?.maxFiles || 5;
|
|
626
630
|
|
|
627
631
|
// Only enrich top N JS/TS files to limit latency
|
|
628
632
|
const filesToEnrich = fileResults
|
|
@@ -688,12 +692,13 @@ function searchWithAstGrep(keywords, taskType = null, config = null) {
|
|
|
688
692
|
const cfg = config || getConfig();
|
|
689
693
|
|
|
690
694
|
// Skip if disabled or ast-grep not available
|
|
691
|
-
|
|
695
|
+
const astAutoCfg = cfg.taskContext?.auto || cfg.context?.auto;
|
|
696
|
+
if (!astAutoCfg?.useAstGrep || !isAstGrepAvailable()) {
|
|
692
697
|
return [];
|
|
693
698
|
}
|
|
694
699
|
|
|
695
700
|
const results = [];
|
|
696
|
-
const maxResults =
|
|
701
|
+
const maxResults = astAutoCfg?.maxAstGrepResults || 5;
|
|
697
702
|
|
|
698
703
|
try {
|
|
699
704
|
// Determine search strategy based on task type
|
|
@@ -855,12 +860,13 @@ async function getAutoContext(description, options = {}) {
|
|
|
855
860
|
const config = getConfig();
|
|
856
861
|
|
|
857
862
|
// Check if auto-context is enabled
|
|
858
|
-
|
|
863
|
+
const autoCtx = config.taskContext?.auto || config.context?.auto;
|
|
864
|
+
if (autoCtx?.enabled === false) {
|
|
859
865
|
return { enabled: false, files: [], context: [] };
|
|
860
866
|
}
|
|
861
867
|
|
|
862
868
|
// v3.0: Use Smart Context System if strategy is 'dynamic'
|
|
863
|
-
const strategy =
|
|
869
|
+
const strategy = autoCtx?.strategy || 'fixed';
|
|
864
870
|
if (strategy === 'dynamic' && smartContextGatherer) {
|
|
865
871
|
const smartResult = await getSmartContext(description, options);
|
|
866
872
|
if (smartResult) {
|
|
@@ -897,8 +903,9 @@ async function getLegacyContext(description, options = {}, config = null) {
|
|
|
897
903
|
checkAndRefreshIndex(config);
|
|
898
904
|
}
|
|
899
905
|
|
|
900
|
-
const
|
|
901
|
-
const
|
|
906
|
+
const autoConf = config.taskContext?.auto || config.context?.auto;
|
|
907
|
+
const maxFiles = options.maxFiles || autoConf?.maxFilesToLoad || 10;
|
|
908
|
+
const showFiles = options.showFiles ?? autoConf?.showLoadedFiles ?? true;
|
|
902
909
|
|
|
903
910
|
// Extract keywords
|
|
904
911
|
const keywords = extractKeywords(description);
|
|
@@ -955,7 +962,8 @@ async function getLegacyContext(description, options = {}, config = null) {
|
|
|
955
962
|
const enrichedUnique = await enrichWithLSP(unique, config);
|
|
956
963
|
|
|
957
964
|
// Re-sort: prioritize files without errors (if LSP enrichment added data)
|
|
958
|
-
|
|
965
|
+
const autoLsp = config.taskContext?.auto || config.context?.auto;
|
|
966
|
+
if (autoLsp?.lspEnrichment?.prioritizeHealthyFiles !== false) {
|
|
959
967
|
enrichedUnique.sort((a, b) => {
|
|
960
968
|
// Files with LSP errors go to bottom
|
|
961
969
|
const aErrors = a.lsp?.errorCount || 0;
|
|
@@ -50,20 +50,20 @@ const KNOWN_CONFIG_KEYS = [
|
|
|
50
50
|
// Core
|
|
51
51
|
'version', 'projectName', 'cli', 'scripts', 'requireApproval',
|
|
52
52
|
// Feature toggles
|
|
53
|
-
'autoLog', 'autoUpdateAppMap', 'strictMode',
|
|
53
|
+
'autoLog', 'autoUpdateAppMap', 'strictMode', 'reporting',
|
|
54
54
|
// Execution
|
|
55
55
|
'hybrid', 'parallel', 'worktree', 'enforcement', 'tasks', 'workflow',
|
|
56
56
|
'loops', 'taskQueue', 'durableSteps', 'suspension', 'phases',
|
|
57
57
|
// Quality & validation
|
|
58
58
|
'qualityGates', 'testing', 'validation', 'specificationMode', 'tdd',
|
|
59
59
|
// Components & registries
|
|
60
|
-
'componentRules', 'componentIndex', 'registries', 'functionRegistry', 'apiRegistry',
|
|
60
|
+
'componentRules', 'componentReuse', 'componentIndex', 'registries', 'functionRegistry', 'apiRegistry',
|
|
61
61
|
// Learning & memory
|
|
62
62
|
'learning', 'corrections', 'automaticMemory', 'automaticPromotion',
|
|
63
63
|
'crossSessionLearning', 'sessionLearning', 'skillLearning', 'memory',
|
|
64
64
|
'codebaseInsights', 'knowledgeRouting',
|
|
65
65
|
// Skills & context
|
|
66
|
-
'skills', 'autoContext', 'context', 'contextMonitor', 'contextScoring',
|
|
66
|
+
'skills', 'autoContext', 'context', 'contextManagement', 'taskContext', 'contextMonitor', 'contextScoring',
|
|
67
67
|
// Review & analysis
|
|
68
68
|
'review', 'reviewFix', 'originTaskTracing', 'standardsCompliance',
|
|
69
69
|
'semanticMatching', 'peerReview', 'triage', 'consistency',
|
|
@@ -162,18 +162,18 @@ function validateConfig(config, warnOnUnknown = true) {
|
|
|
162
162
|
function applyConfigCompatShim(config) {
|
|
163
163
|
if (!config || typeof config !== 'object') return config;
|
|
164
164
|
|
|
165
|
-
// execution <-> tasks + loops (bidirectional)
|
|
165
|
+
// execution <-> tasks + loops (bidirectional, shallow copy to avoid shared references)
|
|
166
166
|
if (config.execution && !config.tasks) {
|
|
167
|
-
config.tasks = config.execution;
|
|
167
|
+
config.tasks = { ...config.execution };
|
|
168
168
|
}
|
|
169
169
|
if (config.tasks && !config.execution) {
|
|
170
|
-
config.execution = config.tasks;
|
|
170
|
+
config.execution = { ...config.tasks };
|
|
171
171
|
}
|
|
172
172
|
if (config.execution && config.execution.loops && !config.loops) {
|
|
173
|
-
config.loops = config.execution.loops;
|
|
173
|
+
config.loops = { ...config.execution.loops };
|
|
174
174
|
}
|
|
175
175
|
if (config.loops && config.execution && !config.execution.loops) {
|
|
176
|
-
config.execution.loops = config.loops;
|
|
176
|
+
config.execution.loops = { ...config.loops };
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
// memory <- memory.automatic, memory.promotion
|
|
@@ -276,6 +276,87 @@ function applyConfigCompatShim(config) {
|
|
|
276
276
|
config.communitySync = config.community.sync;
|
|
277
277
|
}
|
|
278
278
|
|
|
279
|
+
// v1.8.6: Config restructuring compat shims
|
|
280
|
+
// AC1: hooks.rules.enforcement -> enforcement (moved to top-level enforcement)
|
|
281
|
+
if (config.hooks?.rules?.enforcement) {
|
|
282
|
+
const hooksEnforcement = config.hooks.rules.enforcement;
|
|
283
|
+
if (!config.enforcement) config.enforcement = {};
|
|
284
|
+
if (hooksEnforcement.taskGating && !config.enforcement.taskGating) config.enforcement.taskGating = hooksEnforcement.taskGating;
|
|
285
|
+
if (hooksEnforcement.scopeGating && !config.enforcement.scopeGating) config.enforcement.scopeGating = hooksEnforcement.scopeGating;
|
|
286
|
+
if (hooksEnforcement.implementationGate && !config.enforcement.implementationGate) config.enforcement.implementationGate = hooksEnforcement.implementationGate;
|
|
287
|
+
if (hooksEnforcement.todoWriteGate && !config.enforcement.todoWriteGate) config.enforcement.todoWriteGate = hooksEnforcement.todoWriteGate;
|
|
288
|
+
if (hooksEnforcement.routingGate && !config.enforcement.routingGate) config.enforcement.routingGate = hooksEnforcement.routingGate;
|
|
289
|
+
if (hooksEnforcement.loopEnforcement && !config.enforcement.loopEnforcement) config.enforcement.loopEnforcement = hooksEnforcement.loopEnforcement;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// AC3: strictMode object -> reporting
|
|
293
|
+
if (config.strictMode && typeof config.strictMode === 'object' && !config.reporting) {
|
|
294
|
+
config.reporting = config.strictMode;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// AC4: componentRules + hooks.rules.intelligence.componentReuse -> componentReuse
|
|
298
|
+
if (config.componentRules && !config.componentReuse) {
|
|
299
|
+
config.componentReuse = config.componentRules;
|
|
300
|
+
}
|
|
301
|
+
if (config.hooks?.rules?.intelligence?.componentReuse) {
|
|
302
|
+
if (!config.componentReuse) config.componentReuse = {};
|
|
303
|
+
const hooksComponentReuse = config.hooks.rules.intelligence.componentReuse;
|
|
304
|
+
for (const key of Object.keys(hooksComponentReuse)) {
|
|
305
|
+
if (config.componentReuse[key] === undefined) {
|
|
306
|
+
config.componentReuse[key] = hooksComponentReuse[key];
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
// Also expose back as hooks.rules.componentReuse for code that reads that path
|
|
311
|
+
if (config.componentReuse && config.hooks?.rules) {
|
|
312
|
+
if (!config.hooks.rules.componentReuse) config.hooks.rules.componentReuse = { ...config.componentReuse };
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// AC5: scattered learning sub-keys -> learning.*
|
|
316
|
+
if (config.standardsCompliance?.learning && config.learning && !config.learning.standardsLearning) {
|
|
317
|
+
config.learning.standardsLearning = config.standardsCompliance.learning;
|
|
318
|
+
}
|
|
319
|
+
if (config.errorRecovery?.learning && config.learning && !config.learning.errorRecoveryLearning) {
|
|
320
|
+
config.learning.errorRecoveryLearning = config.errorRecovery.learning;
|
|
321
|
+
}
|
|
322
|
+
if (config.bugFlow?.learningEnforcement && config.learning && !config.learning.bugFlowLearning) {
|
|
323
|
+
config.learning.bugFlowLearning = config.bugFlow.learningEnforcement;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// AC6: context -> contextManagement + taskContext
|
|
327
|
+
// Note: mergeWithDefaults may have already created these keys, so check sub-keys not top-level
|
|
328
|
+
if (config.context) {
|
|
329
|
+
if (!config.contextManagement) config.contextManagement = {};
|
|
330
|
+
if (config.context.compaction && !config.contextManagement.compaction) config.contextManagement.compaction = config.context.compaction;
|
|
331
|
+
if (config.context.smart && !config.contextManagement.smart) config.contextManagement.smart = config.context.smart;
|
|
332
|
+
if (config.context.proactive && !config.contextManagement.proactive) config.contextManagement.proactive = config.context.proactive;
|
|
333
|
+
if (config.context.monitor && !config.contextManagement.monitor) config.contextManagement.monitor = config.context.monitor;
|
|
334
|
+
|
|
335
|
+
if (!config.taskContext) config.taskContext = {};
|
|
336
|
+
if (config.context.auto && !config.taskContext.auto) config.taskContext.auto = config.context.auto;
|
|
337
|
+
if (config.context.scoring && !config.taskContext.scoring) config.taskContext.scoring = config.context.scoring;
|
|
338
|
+
if (config.context.session && !config.taskContext.session) config.taskContext.session = config.context.session;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// AC7: tdd -> execution.tdd
|
|
342
|
+
if (config.tdd && config.execution && !config.execution.tdd) {
|
|
343
|
+
config.execution.tdd = config.tdd;
|
|
344
|
+
}
|
|
345
|
+
if (config.execution?.tdd && !config.tdd) {
|
|
346
|
+
config.tdd = config.execution.tdd;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// AC2: top-level validation -> hooks.rules.intelligence.validation
|
|
350
|
+
if (config.validation && config.hooks?.rules?.intelligence?.validation) {
|
|
351
|
+
const v = config.hooks.rules.intelligence.validation;
|
|
352
|
+
if (config.validation.afterTaskComplete !== undefined && v.afterTaskComplete === undefined) {
|
|
353
|
+
v.afterTaskComplete = config.validation.afterTaskComplete;
|
|
354
|
+
}
|
|
355
|
+
if (config.validation.beforeCommit !== undefined && v.beforeCommit === undefined) {
|
|
356
|
+
v.beforeCommit = config.validation.beforeCommit;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
279
360
|
return config;
|
|
280
361
|
}
|
|
281
362
|
|
|
@@ -114,7 +114,7 @@ const KNOWN_CONFIG_KEYS = [
|
|
|
114
114
|
'worktree',
|
|
115
115
|
'qualityGates',
|
|
116
116
|
'testing',
|
|
117
|
-
'
|
|
117
|
+
'componentReuse',
|
|
118
118
|
'mandatorySteps',
|
|
119
119
|
'phases',
|
|
120
120
|
'corrections',
|
|
@@ -136,6 +136,9 @@ const KNOWN_CONFIG_KEYS = [
|
|
|
136
136
|
'damageControl',
|
|
137
137
|
'storyDecomposition',
|
|
138
138
|
'specificationMode',
|
|
139
|
+
'contextManagement',
|
|
140
|
+
'taskContext',
|
|
141
|
+
'reporting',
|
|
139
142
|
];
|
|
140
143
|
|
|
141
144
|
module.exports = {
|
|
@@ -276,7 +276,7 @@ function collapseAll() {
|
|
|
276
276
|
*/
|
|
277
277
|
function checkContextPressure() {
|
|
278
278
|
const config = getConfig();
|
|
279
|
-
const compactionConfig = config.context?.compaction || {};
|
|
279
|
+
const compactionConfig = config.contextManagement?.compaction || config.context?.compaction || {};
|
|
280
280
|
const thresholds = compactionConfig.thresholds || {
|
|
281
281
|
warnAt: 50000,
|
|
282
282
|
compactAt: 80000,
|
|
@@ -125,7 +125,7 @@ function selectNodes(tree, options = {}) {
|
|
|
125
125
|
} = options;
|
|
126
126
|
|
|
127
127
|
const config = getConfig();
|
|
128
|
-
const compactionConfig = config.context?.compaction || {};
|
|
128
|
+
const compactionConfig = config.contextManagement?.compaction || config.context?.compaction || {};
|
|
129
129
|
|
|
130
130
|
const queryKeywords = extractKeywords(query);
|
|
131
131
|
const selected = [];
|
|
@@ -259,7 +259,7 @@ function mergeIntoTree(existingTree, newData) {
|
|
|
259
259
|
|
|
260
260
|
// Apply relevance decay to existing nodes
|
|
261
261
|
const config = getConfig();
|
|
262
|
-
const compactionConfig = config.context?.compaction || DEFAULT_COMPACTION_CONFIG;
|
|
262
|
+
const compactionConfig = config.contextManagement?.compaction || config.context?.compaction || DEFAULT_COMPACTION_CONFIG;
|
|
263
263
|
|
|
264
264
|
if (compactionConfig.relevanceDecay?.enabled) {
|
|
265
265
|
const decayRate = compactionConfig.relevanceDecay.decayPerTurn || 0.05;
|