@lumenflow/core 2.2.2 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/active-wu-detector.d.ts +1 -1
- package/dist/active-wu-detector.js +1 -1
- package/dist/arg-parser.js +51 -18
- package/dist/backlog-generator.d.ts +4 -4
- package/dist/backlog-generator.js +4 -4
- package/dist/backlog-sync-validator.js +1 -1
- package/dist/cleanup-lock.d.ts +9 -2
- package/dist/cleanup-lock.js +17 -7
- package/dist/code-path-validator.d.ts +3 -3
- package/dist/code-path-validator.js +3 -3
- package/dist/compliance-parser.d.ts +1 -1
- package/dist/compliance-parser.js +1 -1
- package/dist/constants/backlog-patterns.d.ts +1 -1
- package/dist/constants/backlog-patterns.js +1 -1
- package/dist/constants/dora-constants.d.ts +1 -1
- package/dist/constants/dora-constants.js +1 -1
- package/dist/constants/gate-constants.d.ts +1 -1
- package/dist/constants/gate-constants.js +1 -1
- package/dist/constants/linter-constants.d.ts +1 -1
- package/dist/constants/linter-constants.js +1 -1
- package/dist/constants/tokenizer-constants.d.ts +1 -1
- package/dist/constants/tokenizer-constants.js +1 -1
- package/dist/context/location-resolver.js +2 -1
- package/dist/context-validation-integration.d.ts +1 -0
- package/dist/core/scope-checker.d.ts +3 -3
- package/dist/core/scope-checker.js +3 -3
- package/dist/core/tool-runner.d.ts +5 -5
- package/dist/core/tool-runner.js +5 -5
- package/dist/core/tool.constants.d.ts +1 -1
- package/dist/core/tool.constants.js +1 -1
- package/dist/core/tool.schemas.d.ts +2 -2
- package/dist/core/tool.schemas.js +1 -1
- package/dist/core/worktree-guard.d.ts +1 -1
- package/dist/core/worktree-guard.js +1 -1
- package/dist/coverage-gate.d.ts +12 -3
- package/dist/coverage-gate.js +15 -8
- package/dist/date-utils.d.ts +4 -4
- package/dist/date-utils.js +4 -4
- package/dist/dependency-graph.d.ts +6 -0
- package/dist/dependency-graph.js +43 -2
- package/dist/dependency-guard.d.ts +2 -2
- package/dist/dependency-guard.js +3 -3
- package/dist/dependency-validator.d.ts +4 -4
- package/dist/dependency-validator.js +4 -7
- package/dist/domain/orchestration.constants.d.ts +31 -10
- package/dist/domain/orchestration.constants.js +45 -16
- package/dist/domain/orchestration.schemas.d.ts +54 -28
- package/dist/domain/orchestration.schemas.js +2 -2
- package/dist/domain/orchestration.types.d.ts +2 -2
- package/dist/domain/orchestration.types.js +2 -2
- package/dist/error-handler.d.ts +10 -10
- package/dist/error-handler.js +10 -10
- package/dist/file-classifiers.d.ts +6 -6
- package/dist/file-classifiers.js +6 -6
- package/dist/gates-config.d.ts +74 -0
- package/dist/gates-config.js +209 -2
- package/dist/git-adapter.d.ts +11 -11
- package/dist/git-adapter.js +11 -11
- package/dist/git-context-extractor.d.ts +112 -0
- package/dist/git-context-extractor.js +559 -0
- package/dist/hardcoded-strings.d.ts +1 -1
- package/dist/hardcoded-strings.js +1 -1
- package/dist/incremental-lint.d.ts +1 -1
- package/dist/incremental-lint.js +2 -2
- package/dist/incremental-test.d.ts +1 -1
- package/dist/incremental-test.js +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.js +25 -0
- package/dist/invariants/check-automated-tests.d.ts +2 -2
- package/dist/invariants/check-automated-tests.js +3 -3
- package/dist/lane-checker.d.ts +28 -7
- package/dist/lane-checker.js +316 -159
- package/dist/lane-suggest-prompt.d.ts +108 -0
- package/dist/lane-suggest-prompt.js +359 -0
- package/dist/lane-validator.d.ts +3 -3
- package/dist/lane-validator.js +3 -3
- package/dist/logs-lib.d.ts +1 -1
- package/dist/logs-lib.js +1 -1
- package/dist/lumenflow-config-schema.d.ts +162 -0
- package/dist/lumenflow-config-schema.js +180 -0
- package/dist/manual-test-validator.d.ts +2 -2
- package/dist/manual-test-validator.js +3 -3
- package/dist/merge-lock.d.ts +8 -1
- package/dist/merge-lock.js +16 -7
- package/dist/micro-worktree.d.ts +81 -13
- package/dist/micro-worktree.js +98 -17
- package/dist/migration-deployer.d.ts +1 -1
- package/dist/migration-deployer.js +1 -1
- package/dist/orchestration-advisory-loader.d.ts +2 -2
- package/dist/orchestration-advisory-loader.js +10 -6
- package/dist/orchestration-advisory.d.ts +3 -3
- package/dist/orchestration-advisory.js +4 -4
- package/dist/orchestration-di.d.ts +4 -4
- package/dist/orchestration-di.js +4 -4
- package/dist/orchestration-rules.d.ts +4 -4
- package/dist/orchestration-rules.js +18 -10
- package/dist/orphan-detector.d.ts +3 -3
- package/dist/orphan-detector.js +3 -3
- package/dist/patrol-loop.d.ts +170 -0
- package/dist/patrol-loop.js +186 -0
- package/dist/process-detector.d.ts +5 -5
- package/dist/process-detector.js +5 -5
- package/dist/rebase-artifact-cleanup.d.ts +3 -3
- package/dist/rebase-artifact-cleanup.js +3 -3
- package/dist/resolve-policy.d.ts +195 -0
- package/dist/resolve-policy.js +203 -0
- package/dist/risk-detector.d.ts +2 -2
- package/dist/risk-detector.js +2 -2
- package/dist/rollback-utils.d.ts +1 -1
- package/dist/rollback-utils.js +1 -1
- package/dist/section-headings.d.ts +1 -1
- package/dist/section-headings.js +1 -1
- package/dist/spawn-escalation.d.ts +4 -4
- package/dist/spawn-escalation.js +3 -3
- package/dist/spawn-monitor.d.ts +4 -4
- package/dist/spawn-monitor.js +4 -4
- package/dist/spawn-recovery.d.ts +3 -3
- package/dist/spawn-recovery.js +3 -3
- package/dist/spawn-registry-schema.d.ts +2 -2
- package/dist/spawn-registry-schema.js +2 -2
- package/dist/spawn-registry-store.d.ts +2 -2
- package/dist/spawn-registry-store.js +2 -2
- package/dist/spawn-strategy.d.ts +17 -11
- package/dist/spawn-strategy.js +47 -44
- package/dist/spawn-tree.d.ts +3 -3
- package/dist/spawn-tree.js +3 -3
- package/dist/state-cleanup-core.d.ts +205 -0
- package/dist/state-cleanup-core.js +240 -0
- package/dist/state-doctor-core.d.ts +168 -0
- package/dist/state-doctor-core.js +251 -0
- package/dist/stream-error-handler.d.ts +67 -0
- package/dist/stream-error-handler.js +94 -0
- package/dist/telemetry.d.ts +1 -1
- package/dist/telemetry.js +1 -1
- package/dist/template-loader.d.ts +162 -0
- package/dist/template-loader.js +372 -0
- package/dist/test-baseline.d.ts +176 -0
- package/dist/test-baseline.js +282 -0
- package/dist/usecases/get-suggestions.usecase.d.ts +1 -1
- package/dist/validation/command-registry.js +37 -0
- package/dist/validators/backlog-sync.js +4 -2
- package/dist/worktree-scanner.d.ts +1 -1
- package/dist/worktree-scanner.js +1 -1
- package/dist/worktree-symlink.d.ts +3 -3
- package/dist/worktree-symlink.js +3 -3
- package/dist/wu-backlog-updater.d.ts +1 -1
- package/dist/wu-backlog-updater.js +1 -1
- package/dist/wu-claim-helpers.d.ts +1 -1
- package/dist/wu-claim-helpers.js +1 -1
- package/dist/wu-claim-resume.d.ts +1 -1
- package/dist/wu-claim-resume.js +1 -1
- package/dist/wu-consistency-checker.d.ts +1 -1
- package/dist/wu-consistency-checker.js +17 -11
- package/dist/wu-constants.d.ts +73 -21
- package/dist/wu-constants.js +65 -22
- package/dist/wu-done-branch-only.d.ts +1 -1
- package/dist/wu-done-branch-only.js +1 -1
- package/dist/wu-done-docs-generate.d.ts +1 -1
- package/dist/wu-done-docs-generate.js +1 -1
- package/dist/wu-done-messages.d.ts +2 -2
- package/dist/wu-done-messages.js +2 -2
- package/dist/wu-done-metadata.d.ts +3 -3
- package/dist/wu-done-metadata.js +3 -3
- package/dist/wu-done-pr.d.ts +1 -1
- package/dist/wu-done-pr.js +4 -2
- package/dist/wu-done-preflight.d.ts +8 -0
- package/dist/wu-done-preflight.js +18 -2
- package/dist/wu-done-ui.d.ts +3 -3
- package/dist/wu-done-ui.js +3 -3
- package/dist/wu-done-validation.d.ts +30 -0
- package/dist/wu-done-validation.js +106 -1
- package/dist/wu-done-worktree.d.ts +1 -1
- package/dist/wu-done-worktree.js +11 -1
- package/dist/wu-events-cleanup.d.ts +148 -0
- package/dist/wu-events-cleanup.js +401 -0
- package/dist/wu-helpers.d.ts +2 -2
- package/dist/wu-helpers.js +2 -2
- package/dist/wu-id-generator.d.ts +58 -0
- package/dist/wu-id-generator.js +103 -0
- package/dist/wu-lint.js +1 -1
- package/dist/wu-preflight-validators.d.ts +13 -1
- package/dist/wu-preflight-validators.js +56 -1
- package/dist/wu-recovery.d.ts +2 -2
- package/dist/wu-recovery.js +4 -4
- package/dist/wu-repair-core.d.ts +5 -5
- package/dist/wu-repair-core.js +6 -6
- package/dist/wu-schema-normalization.d.ts +1 -1
- package/dist/wu-schema-normalization.js +1 -1
- package/dist/wu-schema.d.ts +7 -7
- package/dist/wu-schema.js +8 -8
- package/dist/wu-spawn-context.d.ts +87 -0
- package/dist/wu-spawn-context.js +175 -0
- package/dist/wu-spawn-helpers.d.ts +1 -1
- package/dist/wu-spawn-helpers.js +1 -1
- package/dist/wu-spawn.d.ts +177 -4
- package/dist/wu-spawn.js +694 -72
- package/dist/wu-state-schema.d.ts +1 -1
- package/dist/wu-state-schema.js +1 -1
- package/dist/wu-state-store.d.ts +3 -3
- package/dist/wu-state-store.js +3 -3
- package/dist/wu-status-transition.d.ts +1 -1
- package/dist/wu-status-transition.js +1 -1
- package/dist/wu-status-updater.d.ts +3 -3
- package/dist/wu-status-updater.js +3 -3
- package/dist/wu-validation-constants.d.ts +2 -2
- package/dist/wu-validation-constants.js +2 -2
- package/dist/wu-validation.d.ts +3 -3
- package/dist/wu-validation.js +3 -3
- package/dist/wu-yaml-fixer.d.ts +2 -2
- package/dist/wu-yaml-fixer.js +3 -3
- package/dist/wu-yaml.d.ts +23 -0
- package/dist/wu-yaml.js +76 -2
- package/package.json +5 -2
package/dist/wu-spawn.js
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* Codex Mode:
|
|
26
26
|
* When --codex is used, outputs a Codex/GPT-friendly Markdown prompt (no antml/XML escaping).
|
|
27
27
|
*
|
|
28
|
-
* @see {@link
|
|
28
|
+
* @see {@link https://lumenflow.dev/reference/agent-invocation-guide/} - Context loading templates
|
|
29
29
|
*/
|
|
30
30
|
import { existsSync, readFileSync } from 'node:fs';
|
|
31
31
|
import { fileURLToPath } from 'node:url';
|
|
@@ -46,15 +46,545 @@ import { loadInvariants, INVARIANT_TYPES } from './invariants-runner.js';
|
|
|
46
46
|
import { validateSpawnArgs, generateExecutionModeSection, generateThinkToolGuidance, recordSpawnToRegistry, formatSpawnRecordedMessage, } from './wu-spawn-helpers.js';
|
|
47
47
|
// Agent skills loading removed for vendor-agnostic design
|
|
48
48
|
import { validateSpawnDependencies, formatDependencyError } from './dependency-validator.js';
|
|
49
|
+
/**
|
|
50
|
+
* WU-1253/WU-1291: Template System for Spawn Prompts
|
|
51
|
+
*
|
|
52
|
+
* DECISION (WU-1291): Template system is ACTIVATED with graceful degradation.
|
|
53
|
+
*
|
|
54
|
+
* The template system loads prompt sections from .lumenflow/templates/spawn-prompt/
|
|
55
|
+
* with YAML frontmatter and manifest-driven assembly order. This design provides:
|
|
56
|
+
*
|
|
57
|
+
* 1. **Maintainability**: Templates in markdown files are easier to edit than code strings
|
|
58
|
+
* 2. **Client extensibility**: Client-specific overrides via templates.{client}/ directories
|
|
59
|
+
* 3. **Conditional inclusion**: Templates selected based on WU type and policy settings
|
|
60
|
+
* 4. **Graceful fallback**: If template loading fails, hardcoded functions are used
|
|
61
|
+
*
|
|
62
|
+
* Template loading is attempted via tryAssembleSpawnTemplates(). If it returns null
|
|
63
|
+
* (templates missing or assembly fails), the spawn output uses hardcoded generator
|
|
64
|
+
* functions (generateTDDDirective, generateBugDiscoverySection, etc.).
|
|
65
|
+
*
|
|
66
|
+
* @see template-loader.ts for the loading and assembly implementation
|
|
67
|
+
* @see .lumenflow/templates/manifest.yaml for the template registry
|
|
68
|
+
*/
|
|
69
|
+
import { loadManifest, loadTemplatesWithOverrides, assembleTemplates, } from './template-loader.js';
|
|
70
|
+
import { resolvePolicy } from './resolve-policy.js';
|
|
71
|
+
// WU-1270: Import telemetry emit function for methodology tracking
|
|
72
|
+
import { emit as emitTelemetry } from './telemetry.js';
|
|
49
73
|
/**
|
|
50
74
|
* Mandatory agent trigger patterns.
|
|
51
|
-
* Mirrors MANDATORY_TRIGGERS from orchestration
|
|
75
|
+
* Mirrors MANDATORY_TRIGGERS from orchestration.constants.ts.
|
|
76
|
+
*
|
|
77
|
+
* Note: For LumenFlow framework development, this is empty since we don't have
|
|
78
|
+
* application-specific concerns like PHI, auth, or RLS. Projects using LumenFlow
|
|
79
|
+
* should configure their own triggers based on their domain requirements.
|
|
52
80
|
*/
|
|
53
81
|
const MANDATORY_TRIGGERS = {
|
|
54
|
-
|
|
55
|
-
'beacon-guardian': ['**/prompts/**', '**/classification/**', '**/detector/**', '**/llm/**'],
|
|
82
|
+
// No mandatory triggers for LumenFlow framework development.
|
|
56
83
|
};
|
|
57
84
|
const LOG_PREFIX = '[wu:spawn]';
|
|
85
|
+
/**
|
|
86
|
+
* WU-1192: Truncation prevention constants (consolidated from CLI)
|
|
87
|
+
*
|
|
88
|
+
* These constants help detect when spawn output has been truncated during
|
|
89
|
+
* copy-paste operations or context loading. The warning banner alerts users
|
|
90
|
+
* to the truncation risk, and the end sentinel allows verification that
|
|
91
|
+
* the full output was received.
|
|
92
|
+
*/
|
|
93
|
+
export const TRUNCATION_WARNING_BANNER = `<!-- LUMENFLOW_TRUNCATION_WARNING -->
|
|
94
|
+
<!--
|
|
95
|
+
⚠️ CRITICAL: DO NOT TRUNCATE THIS OUTPUT
|
|
96
|
+
|
|
97
|
+
This spawn prompt MUST be copied verbatim. Truncation causes:
|
|
98
|
+
- Missing constraints (agents ignore safety rules)
|
|
99
|
+
- Missing TDD directives (agents skip tests)
|
|
100
|
+
- Degraded agent performance
|
|
101
|
+
|
|
102
|
+
VERIFICATION: The output MUST end with: <!-- LUMENFLOW_SPAWN_END -->
|
|
103
|
+
If you don't see that sentinel at the end, the output was truncated.
|
|
104
|
+
-->
|
|
105
|
+
`;
|
|
106
|
+
export const SPAWN_END_SENTINEL = '<!-- LUMENFLOW_SPAWN_END -->';
|
|
107
|
+
/**
|
|
108
|
+
* WU-1253/WU-1291: Try to assemble spawn prompt sections from templates.
|
|
109
|
+
*
|
|
110
|
+
* This function loads templates from .lumenflow/templates/ and assembles
|
|
111
|
+
* them according to the manifest order. Client-specific overrides are
|
|
112
|
+
* supported via templates.{client}/ directories.
|
|
113
|
+
*
|
|
114
|
+
* **Decision (WU-1291)**: Template system is ACTIVATED. This function is called
|
|
115
|
+
* by generateTaskInvocation() and generateCodexPrompt() to attempt template-based
|
|
116
|
+
* generation. If it returns null (templates missing, manifest invalid, or assembly
|
|
117
|
+
* fails), callers fall back to hardcoded generator functions.
|
|
118
|
+
*
|
|
119
|
+
* Template coverage (as of WU-1291):
|
|
120
|
+
* - Methodology directives (TDD, test-after, none)
|
|
121
|
+
* - Architecture directives (hexagonal, layered, none)
|
|
122
|
+
* - Type-specific directives (documentation, visual, refactor)
|
|
123
|
+
* - Agent guidance (effort-scaling, parallel-tool-calls, search-heuristics, token-budget)
|
|
124
|
+
* - Operational guidance (bug-discovery, quick-fix-commands, lane-selection)
|
|
125
|
+
* - Lane-specific guidance and constraints
|
|
126
|
+
*
|
|
127
|
+
* @param baseDir - Project root directory
|
|
128
|
+
* @param clientName - Client name for overrides (e.g., 'claude', 'cursor')
|
|
129
|
+
* @param context - Context for token replacement and condition evaluation
|
|
130
|
+
* @returns Assembled template content, or null if templates unavailable
|
|
131
|
+
*/
|
|
132
|
+
export function tryAssembleSpawnTemplates(baseDir, clientName, context) {
|
|
133
|
+
try {
|
|
134
|
+
const manifest = loadManifest(baseDir);
|
|
135
|
+
const templates = loadTemplatesWithOverrides(baseDir, clientName);
|
|
136
|
+
if (templates.size === 0) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
return assembleTemplates(templates, manifest, context);
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
// Template loading failed - return null for hardcoded fallback (intentional)
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Build template context from WU document.
|
|
148
|
+
*
|
|
149
|
+
* @param doc - WU YAML document
|
|
150
|
+
* @param id - WU ID
|
|
151
|
+
* @returns Context for template assembly
|
|
152
|
+
*/
|
|
153
|
+
export function buildTemplateContext(doc, id) {
|
|
154
|
+
const lane = doc.lane || '';
|
|
155
|
+
const laneParent = lane.split(':')[0]?.trim() || '';
|
|
156
|
+
return {
|
|
157
|
+
WU_ID: id,
|
|
158
|
+
LANE: lane,
|
|
159
|
+
TYPE: (doc.type || 'feature').toLowerCase(),
|
|
160
|
+
TITLE: doc.title || '',
|
|
161
|
+
DESCRIPTION: doc.description || '',
|
|
162
|
+
WORKTREE_PATH: doc.worktree_path || '',
|
|
163
|
+
laneParent,
|
|
164
|
+
// Add lowercase aliases for condition evaluation
|
|
165
|
+
type: (doc.type || 'feature').toLowerCase(),
|
|
166
|
+
lane,
|
|
167
|
+
worktreePath: doc.worktree_path || '',
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* WU-1261: Build template context with resolved policy fields.
|
|
172
|
+
*
|
|
173
|
+
* Extends buildTemplateContext() with policy.testing and policy.architecture
|
|
174
|
+
* fields for template condition evaluation.
|
|
175
|
+
*
|
|
176
|
+
* @param doc - WU YAML document
|
|
177
|
+
* @param id - WU ID
|
|
178
|
+
* @param policy - Resolved policy from resolvePolicy()
|
|
179
|
+
* @returns Context for template assembly with policy fields
|
|
180
|
+
*/
|
|
181
|
+
export function buildTemplateContextWithPolicy(doc, id, policy) {
|
|
182
|
+
const baseContext = buildTemplateContext(doc, id);
|
|
183
|
+
return {
|
|
184
|
+
...baseContext,
|
|
185
|
+
'policy.testing': policy.testing,
|
|
186
|
+
'policy.architecture': policy.architecture,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* WU types that require TDD (failing test first)
|
|
191
|
+
* Note: Used as documentation reference. TDD is the default for any type not in other categories.
|
|
192
|
+
*/
|
|
193
|
+
const _TDD_REQUIRED_TYPES = ['feature', 'bug', 'tooling', 'enhancement'];
|
|
194
|
+
/**
|
|
195
|
+
* WU types that require existing tests to pass (no new tests mandated)
|
|
196
|
+
*/
|
|
197
|
+
const EXISTING_TESTS_TYPES = ['refactor'];
|
|
198
|
+
/**
|
|
199
|
+
* WU types that require smoke tests + manual QA
|
|
200
|
+
*/
|
|
201
|
+
const SMOKE_TEST_TYPES = ['visual', 'design', 'ui'];
|
|
202
|
+
/**
|
|
203
|
+
* WU types that only need format checks (no TDD)
|
|
204
|
+
*/
|
|
205
|
+
const DOCS_ONLY_TYPES = ['documentation', 'docs', 'config'];
|
|
206
|
+
/**
|
|
207
|
+
* Generate type-aware test guidance (WU-1142, WU-1192)
|
|
208
|
+
*
|
|
209
|
+
* Returns appropriate test guidance based on WU type:
|
|
210
|
+
* - feature/bug/tooling: Full TDD directive
|
|
211
|
+
* - documentation: Format check only
|
|
212
|
+
* - visual/design: Smoke test + manual QA
|
|
213
|
+
* - refactor: Existing tests must pass
|
|
214
|
+
*
|
|
215
|
+
* @param {string} wuType - WU type from YAML
|
|
216
|
+
* @returns {string} Test guidance section
|
|
217
|
+
*/
|
|
218
|
+
export function generateTestGuidance(wuType) {
|
|
219
|
+
const type = (wuType || 'feature').toLowerCase();
|
|
220
|
+
// Documentation WUs - no TDD, just format checks
|
|
221
|
+
if (DOCS_ONLY_TYPES.includes(type)) {
|
|
222
|
+
return `## Documentation Standards
|
|
223
|
+
|
|
224
|
+
**Format check only** - No TDD required for documentation WUs.
|
|
225
|
+
|
|
226
|
+
### Requirements
|
|
227
|
+
|
|
228
|
+
1. Run \`pnpm gates --docs-only\` before completion
|
|
229
|
+
2. Ensure markdown formatting is correct
|
|
230
|
+
3. Verify links are valid
|
|
231
|
+
4. Check spelling and grammar`;
|
|
232
|
+
}
|
|
233
|
+
// Visual/Design WUs - smoke tests + manual QA
|
|
234
|
+
if (SMOKE_TEST_TYPES.includes(type)) {
|
|
235
|
+
return `## Visual/Design Testing
|
|
236
|
+
|
|
237
|
+
**Smoke test + manual QA** - Visual WUs require different verification.
|
|
238
|
+
|
|
239
|
+
### Requirements
|
|
240
|
+
|
|
241
|
+
1. Create smoke test for component rendering (if applicable)
|
|
242
|
+
2. Verify visual appearance manually
|
|
243
|
+
3. Test responsive behavior across breakpoints
|
|
244
|
+
4. Check accessibility (keyboard navigation, screen reader)
|
|
245
|
+
5. Document manual QA results in completion notes`;
|
|
246
|
+
}
|
|
247
|
+
// Refactor WUs - existing tests must pass
|
|
248
|
+
if (EXISTING_TESTS_TYPES.includes(type)) {
|
|
249
|
+
return `## Refactor Testing
|
|
250
|
+
|
|
251
|
+
**Existing tests must pass** - Refactoring must not break current behavior.
|
|
252
|
+
|
|
253
|
+
### Requirements
|
|
254
|
+
|
|
255
|
+
1. Run all existing tests BEFORE refactoring
|
|
256
|
+
2. Run all existing tests AFTER refactoring
|
|
257
|
+
3. No new tests required unless behavior changes
|
|
258
|
+
4. If tests fail after refactor, the refactor introduced a bug`;
|
|
259
|
+
}
|
|
260
|
+
// Default: TDD required (feature, bug, tooling, enhancement)
|
|
261
|
+
return generateTDDDirective();
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Generate the TDD directive section (WU-1585, WU-1192)
|
|
265
|
+
*
|
|
266
|
+
* Positioned immediately after </task> preamble per "Lost in the Middle" research.
|
|
267
|
+
* Critical instructions at START and END of prompt improve adherence.
|
|
268
|
+
*
|
|
269
|
+
* @returns {string} TDD directive section
|
|
270
|
+
*/
|
|
271
|
+
function generateTDDDirective() {
|
|
272
|
+
return `## ⛔ TDD DIRECTIVE — READ BEFORE CODING
|
|
273
|
+
|
|
274
|
+
**IF YOU WRITE IMPLEMENTATION CODE BEFORE A FAILING TEST, YOU HAVE FAILED THIS WU.**
|
|
275
|
+
|
|
276
|
+
### Test-First Workflow (MANDATORY)
|
|
277
|
+
|
|
278
|
+
1. Write a failing test for the acceptance criteria
|
|
279
|
+
2. Run the test to confirm it fails (RED)
|
|
280
|
+
3. Implement the minimum code to pass the test
|
|
281
|
+
4. Run the test to confirm it passes (GREEN)
|
|
282
|
+
5. Refactor if needed, keeping tests green
|
|
283
|
+
|
|
284
|
+
### Test Ratchet Rule (WU-1253)
|
|
285
|
+
|
|
286
|
+
Gates compare test results against \`.lumenflow/test-baseline.json\`:
|
|
287
|
+
|
|
288
|
+
- **NEW failures** (not in baseline) **BLOCK** gates - you must fix them
|
|
289
|
+
- **Pre-existing failures** (in baseline) show **WARNING** - do not block your WU
|
|
290
|
+
- When tests are **fixed**, baseline auto-updates (ratchet forward)
|
|
291
|
+
|
|
292
|
+
If gates fail due to test failures:
|
|
293
|
+
1. Check if failure is in baseline: \`cat .lumenflow/test-baseline.json\`
|
|
294
|
+
2. If pre-existing: continue, it will warn but not block
|
|
295
|
+
3. If NEW: fix the test or add to baseline with reason and fix-wu
|
|
296
|
+
|
|
297
|
+
### Why This Matters
|
|
298
|
+
|
|
299
|
+
- Tests document expected behavior BEFORE implementation
|
|
300
|
+
- Prevents scope creep and over-engineering
|
|
301
|
+
- Ensures every feature has verification
|
|
302
|
+
- Failing tests prove the test actually tests something
|
|
303
|
+
- Ratchet pattern prevents being blocked by unrelated failures`;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* WU-1279: Generate the Mandatory Standards section based on resolved policy
|
|
307
|
+
*
|
|
308
|
+
* Instead of hardcoding TDD/90%/Hexagonal, this function generates the
|
|
309
|
+
* section dynamically based on the resolved methodology policy.
|
|
310
|
+
*
|
|
311
|
+
* @param policy - Resolved policy from resolvePolicy()
|
|
312
|
+
* @returns Mandatory Standards section content
|
|
313
|
+
*/
|
|
314
|
+
export function generateMandatoryStandards(policy) {
|
|
315
|
+
const lines = ['## Mandatory Standards', ''];
|
|
316
|
+
// LumenFlow workflow is always required
|
|
317
|
+
lines.push('- **LumenFlow**: Follow trunk-based flow, WIP=1, worktree discipline');
|
|
318
|
+
// Testing methodology based on policy
|
|
319
|
+
if (policy.testing === 'tdd') {
|
|
320
|
+
lines.push(`- **TDD**: Failing test first, then implementation, then passing test. ${policy.coverage_threshold}%+ coverage on new application code`);
|
|
321
|
+
}
|
|
322
|
+
else if (policy.testing === 'test-after') {
|
|
323
|
+
lines.push(`- **Test-After**: Write implementation first, then add tests. ${policy.coverage_threshold}%+ coverage on new application code`);
|
|
324
|
+
}
|
|
325
|
+
else if (policy.testing === 'none') {
|
|
326
|
+
lines.push('- **Testing**: Tests are optional for this project');
|
|
327
|
+
}
|
|
328
|
+
// Architecture based on policy
|
|
329
|
+
if (policy.architecture === 'hexagonal') {
|
|
330
|
+
lines.push('- **Hexagonal Architecture**: Ports-first design. No application -> infrastructure imports');
|
|
331
|
+
}
|
|
332
|
+
else if (policy.architecture === 'layered') {
|
|
333
|
+
lines.push('- **Layered Architecture**: Clear layer separation. Each layer can only depend on layers below it');
|
|
334
|
+
}
|
|
335
|
+
// For architecture: 'none', we don't add any architecture guidance
|
|
336
|
+
// Always include these standards
|
|
337
|
+
lines.push('- **SOLID/DRY/YAGNI/KISS**: No over-engineering, no premature abstraction');
|
|
338
|
+
lines.push('- **Library-First**: Search context7 before writing custom code. No reinventing wheels');
|
|
339
|
+
lines.push('- **Code Quality**: No string literals, no magic numbers, no brittle regexes when libraries exist');
|
|
340
|
+
lines.push('- **Worktree Discipline**: ALWAYS use `pnpm wu:claim` to create worktrees (never `git worktree add` directly). Work ONLY in the worktree, never edit main');
|
|
341
|
+
lines.push('- **Documentation**: Update tooling docs if changing tools. Keep docs in sync with code');
|
|
342
|
+
lines.push('- **Sub-agents**: Use Explore agent for codebase investigation. Activate mandatory agents as configured for your project');
|
|
343
|
+
return lines.join('\n');
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* WU-1261: Generate test guidance based on resolved policy
|
|
347
|
+
*
|
|
348
|
+
* Selects the appropriate test guidance based on policy.testing value:
|
|
349
|
+
* - 'tdd': Full TDD directive (failing test first)
|
|
350
|
+
* - 'test-after': Implementation first, then tests
|
|
351
|
+
* - 'none': Testing is optional
|
|
352
|
+
*
|
|
353
|
+
* Type overrides still apply (documentation WUs always get docs guidance).
|
|
354
|
+
*
|
|
355
|
+
* @param wuType - WU type from YAML (e.g., 'feature', 'documentation')
|
|
356
|
+
* @param policy - Resolved policy from resolvePolicy()
|
|
357
|
+
* @returns Test guidance section
|
|
358
|
+
*/
|
|
359
|
+
export function generatePolicyBasedTestGuidance(wuType, policy) {
|
|
360
|
+
const type = (wuType || 'feature').toLowerCase();
|
|
361
|
+
// Type overrides take precedence (documentation never needs TDD)
|
|
362
|
+
if (DOCS_ONLY_TYPES.includes(type)) {
|
|
363
|
+
return `## Documentation Standards
|
|
364
|
+
|
|
365
|
+
**Format check only** - No TDD required for documentation WUs.
|
|
366
|
+
|
|
367
|
+
### Requirements
|
|
368
|
+
|
|
369
|
+
1. Run \`pnpm gates --docs-only\` before completion
|
|
370
|
+
2. Ensure markdown formatting is correct
|
|
371
|
+
3. Verify links are valid
|
|
372
|
+
4. Check spelling and grammar`;
|
|
373
|
+
}
|
|
374
|
+
// Visual/Design WUs - smoke tests + manual QA
|
|
375
|
+
if (SMOKE_TEST_TYPES.includes(type)) {
|
|
376
|
+
return `## Visual/Design Testing
|
|
377
|
+
|
|
378
|
+
**Smoke test + manual QA** - Visual WUs require different verification.
|
|
379
|
+
|
|
380
|
+
### Requirements
|
|
381
|
+
|
|
382
|
+
1. Create smoke test for component rendering (if applicable)
|
|
383
|
+
2. Verify visual appearance manually
|
|
384
|
+
3. Test responsive behavior across breakpoints
|
|
385
|
+
4. Check accessibility (keyboard navigation, screen reader)
|
|
386
|
+
5. Document manual QA results in completion notes`;
|
|
387
|
+
}
|
|
388
|
+
// Refactor WUs - existing tests must pass
|
|
389
|
+
if (EXISTING_TESTS_TYPES.includes(type)) {
|
|
390
|
+
return `## Refactor Testing
|
|
391
|
+
|
|
392
|
+
**Existing tests must pass** - Refactoring must not break current behavior.
|
|
393
|
+
|
|
394
|
+
### Requirements
|
|
395
|
+
|
|
396
|
+
1. Run all existing tests BEFORE refactoring
|
|
397
|
+
2. Run all existing tests AFTER refactoring
|
|
398
|
+
3. No new tests required unless behavior changes
|
|
399
|
+
4. If tests fail after refactor, the refactor introduced a bug`;
|
|
400
|
+
}
|
|
401
|
+
// Policy-based selection for feature/bug/enhancement/tooling types
|
|
402
|
+
switch (policy.testing) {
|
|
403
|
+
case 'test-after':
|
|
404
|
+
return generateTestAfterDirective(policy.coverage_threshold);
|
|
405
|
+
case 'none':
|
|
406
|
+
return generateTestingOptionalDirective();
|
|
407
|
+
case 'tdd':
|
|
408
|
+
default:
|
|
409
|
+
return generateTDDDirective();
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* WU-1261, WU-1279: Generate test-after directive
|
|
414
|
+
*
|
|
415
|
+
* @param coverageThreshold - Coverage threshold from resolved policy
|
|
416
|
+
* @returns Test-after guidance section
|
|
417
|
+
*/
|
|
418
|
+
function generateTestAfterDirective(coverageThreshold) {
|
|
419
|
+
return `## Test-After Methodology
|
|
420
|
+
|
|
421
|
+
**Write implementation first, then add tests** - Focus on solving the problem, then verify.
|
|
422
|
+
|
|
423
|
+
### Test-After Workflow
|
|
424
|
+
|
|
425
|
+
1. Understand the acceptance criteria
|
|
426
|
+
2. Write implementation first
|
|
427
|
+
3. Add tests to verify behavior
|
|
428
|
+
4. Aim for ${coverageThreshold}% coverage on new code
|
|
429
|
+
|
|
430
|
+
### When This Works
|
|
431
|
+
|
|
432
|
+
- Exploratory prototyping where requirements are unclear
|
|
433
|
+
- Quick iterations where test-first slows discovery
|
|
434
|
+
- Projects configured with \`methodology.testing: 'test-after'\`
|
|
435
|
+
|
|
436
|
+
### Requirements
|
|
437
|
+
|
|
438
|
+
- Tests must be added before \`wu:done\`
|
|
439
|
+
- Coverage target: ${coverageThreshold}%+ on new application code
|
|
440
|
+
- All existing tests must still pass`;
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* WU-1261: Generate testing optional directive
|
|
444
|
+
*
|
|
445
|
+
* @returns Testing optional guidance section
|
|
446
|
+
*/
|
|
447
|
+
function generateTestingOptionalDirective() {
|
|
448
|
+
return `## Testing Optional
|
|
449
|
+
|
|
450
|
+
**Tests are not required** - Project is configured without test requirements.
|
|
451
|
+
|
|
452
|
+
### Focus
|
|
453
|
+
|
|
454
|
+
- Code quality and functionality
|
|
455
|
+
- Run \`pnpm gates\` before completion (will skip coverage checks)
|
|
456
|
+
|
|
457
|
+
### If You Want to Add Tests
|
|
458
|
+
|
|
459
|
+
You can still add tests for critical functionality:
|
|
460
|
+
\`\`\`bash
|
|
461
|
+
pnpm test -- --coverage
|
|
462
|
+
\`\`\`
|
|
463
|
+
|
|
464
|
+
But they are not required for WU completion.`;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* WU-1261: Generate architecture guidance based on resolved policy
|
|
468
|
+
*
|
|
469
|
+
* Selects appropriate architecture guidance based on policy.architecture:
|
|
470
|
+
* - 'hexagonal': Ports and adapters, dependency inversion
|
|
471
|
+
* - 'layered': Traditional layer separation
|
|
472
|
+
* - 'none': No architecture constraints
|
|
473
|
+
*
|
|
474
|
+
* @param policy - Resolved policy from resolvePolicy()
|
|
475
|
+
* @returns Architecture guidance section, or empty string for 'none'
|
|
476
|
+
*/
|
|
477
|
+
export function generatePolicyBasedArchitectureGuidance(policy) {
|
|
478
|
+
switch (policy.architecture) {
|
|
479
|
+
case 'hexagonal':
|
|
480
|
+
return `## Hexagonal Architecture
|
|
481
|
+
|
|
482
|
+
**Ports and Adapters** - Keep domain logic pure, infrastructure at the edges.
|
|
483
|
+
|
|
484
|
+
### Key Principles
|
|
485
|
+
|
|
486
|
+
- **Ports**: Interfaces defining what the domain needs (inbound) or uses (outbound)
|
|
487
|
+
- **Adapters**: Implementations connecting ports to infrastructure
|
|
488
|
+
- **Domain**: Pure business logic with no infrastructure imports
|
|
489
|
+
- **Dependency Rule**: Domain -> Ports <- Adapters (never domain -> adapters)
|
|
490
|
+
|
|
491
|
+
### Directory Structure
|
|
492
|
+
|
|
493
|
+
\`\`\`
|
|
494
|
+
src/
|
|
495
|
+
domain/ # Pure business logic
|
|
496
|
+
ports/ # Interfaces
|
|
497
|
+
adapters/ # Infrastructure implementations
|
|
498
|
+
application/ # Use cases orchestrating domain + ports
|
|
499
|
+
\`\`\``;
|
|
500
|
+
case 'layered':
|
|
501
|
+
return `## Layered Architecture
|
|
502
|
+
|
|
503
|
+
**Traditional layer separation** - Clear boundaries between concerns.
|
|
504
|
+
|
|
505
|
+
### Layers (Top to Bottom)
|
|
506
|
+
|
|
507
|
+
1. **Presentation**: UI, API controllers, CLI
|
|
508
|
+
2. **Application**: Use cases, orchestration
|
|
509
|
+
3. **Domain**: Business logic, entities
|
|
510
|
+
4. **Infrastructure**: Database, external services
|
|
511
|
+
|
|
512
|
+
### Dependency Rule
|
|
513
|
+
|
|
514
|
+
- Each layer can only depend on layers below it
|
|
515
|
+
- Presentation -> Application -> Domain -> Infrastructure
|
|
516
|
+
- Never skip layers (Presentation should not directly use Infrastructure)`;
|
|
517
|
+
case 'none':
|
|
518
|
+
default:
|
|
519
|
+
return '';
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* WU-1261: Generate enforcement summary from resolved policy
|
|
524
|
+
*
|
|
525
|
+
* Creates a "You will be judged by" section that summarizes the active
|
|
526
|
+
* enforcement rules based on the resolved policy.
|
|
527
|
+
*
|
|
528
|
+
* @param policy - Resolved policy from resolvePolicy()
|
|
529
|
+
* @returns Enforcement summary section
|
|
530
|
+
*/
|
|
531
|
+
export function generateEnforcementSummary(policy) {
|
|
532
|
+
const lines = ['## You will be judged by', ''];
|
|
533
|
+
// Testing methodology
|
|
534
|
+
const testingStatus = policy.tests_required ? 'required' : 'optional';
|
|
535
|
+
lines.push(`- **Testing**: ${policy.testing} (tests ${testingStatus})`);
|
|
536
|
+
// Coverage
|
|
537
|
+
if (policy.coverage_mode === 'off') {
|
|
538
|
+
lines.push('- **Coverage**: disabled');
|
|
539
|
+
}
|
|
540
|
+
else {
|
|
541
|
+
const modeLabel = policy.coverage_mode === 'block' ? 'blocking' : 'warn only';
|
|
542
|
+
lines.push(`- **Coverage**: ${policy.coverage_threshold}% (${modeLabel})`);
|
|
543
|
+
}
|
|
544
|
+
// Architecture
|
|
545
|
+
if (policy.architecture !== 'none') {
|
|
546
|
+
lines.push(`- **Architecture**: ${policy.architecture}`);
|
|
547
|
+
}
|
|
548
|
+
return lines.join('\n');
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Generate worktree block recovery section (WU-1192)
|
|
552
|
+
*
|
|
553
|
+
* Provides guidance when agents encounter worktree hook blocks.
|
|
554
|
+
*
|
|
555
|
+
* @param {string} worktreePath - Path to the worktree
|
|
556
|
+
* @returns {string} Recovery section
|
|
557
|
+
*/
|
|
558
|
+
export function generateWorktreeBlockRecoverySection(worktreePath) {
|
|
559
|
+
return `## When Blocked by Worktree Hook
|
|
560
|
+
|
|
561
|
+
If you encounter a "worktree required" or "commit blocked" error:
|
|
562
|
+
|
|
563
|
+
1. **Check existing worktrees**: \`git worktree list\`
|
|
564
|
+
2. **Navigate to the worktree**: \`cd ${worktreePath || 'worktrees/<lane>-wu-xxx'}\`
|
|
565
|
+
3. **Retry your operation** from within the worktree
|
|
566
|
+
4. **Use relative paths only** (never absolute paths)
|
|
567
|
+
|
|
568
|
+
### Common Causes
|
|
569
|
+
|
|
570
|
+
- Running \`git commit\` from main checkout instead of worktree
|
|
571
|
+
- Using absolute paths that bypass worktree isolation
|
|
572
|
+
- Forgetting to \`cd\` to worktree after \`wu:claim\`
|
|
573
|
+
|
|
574
|
+
### Quick Fix
|
|
575
|
+
|
|
576
|
+
\`\`\`bash
|
|
577
|
+
# Check where you are
|
|
578
|
+
pwd
|
|
579
|
+
git worktree list
|
|
580
|
+
|
|
581
|
+
# Navigate to your worktree
|
|
582
|
+
cd ${worktreePath || 'worktrees/<lane>-wu-xxx'}
|
|
583
|
+
|
|
584
|
+
# Retry your commit
|
|
585
|
+
git add . && git commit -m "your message"
|
|
586
|
+
\`\`\``;
|
|
587
|
+
}
|
|
58
588
|
/**
|
|
59
589
|
* Detect mandatory agents based on code paths.
|
|
60
590
|
*
|
|
@@ -209,14 +739,16 @@ function formatInvariantForOutput(inv) {
|
|
|
209
739
|
lines.push(`**Path:** \`${inv.path}\``);
|
|
210
740
|
}
|
|
211
741
|
if (inv.paths) {
|
|
212
|
-
|
|
742
|
+
const formattedPaths = inv.paths.map((p) => `\`${p}\``).join(', ');
|
|
743
|
+
lines.push(`**Paths:** ${formattedPaths}`);
|
|
213
744
|
}
|
|
214
745
|
// WU-2254: forbidden-import specific fields
|
|
215
746
|
if (inv.from) {
|
|
216
747
|
lines.push(`**From:** \`${inv.from}\``);
|
|
217
748
|
}
|
|
218
749
|
if (inv.cannot_import && Array.isArray(inv.cannot_import)) {
|
|
219
|
-
|
|
750
|
+
const formattedImports = inv.cannot_import.map((m) => `\`${m}\``).join(', ');
|
|
751
|
+
lines.push(`**Cannot Import:** ${formattedImports}`);
|
|
220
752
|
}
|
|
221
753
|
// WU-2254: required-pattern specific fields
|
|
222
754
|
if (inv.pattern &&
|
|
@@ -225,7 +757,8 @@ function formatInvariantForOutput(inv) {
|
|
|
225
757
|
lines.push(`**Pattern:** \`${inv.pattern}\``);
|
|
226
758
|
}
|
|
227
759
|
if (inv.scope && Array.isArray(inv.scope)) {
|
|
228
|
-
|
|
760
|
+
const formattedScope = inv.scope.map((s) => `\`${s}\``).join(', ');
|
|
761
|
+
lines.push(`**Scope:** ${formattedScope}`);
|
|
229
762
|
}
|
|
230
763
|
lines.push('');
|
|
231
764
|
return lines;
|
|
@@ -274,34 +807,6 @@ function generateInvariantsPriorArtSection(codePaths) {
|
|
|
274
807
|
];
|
|
275
808
|
return lines.join('\n');
|
|
276
809
|
}
|
|
277
|
-
/**
|
|
278
|
-
* Generate the TDD directive section (WU-1585)
|
|
279
|
-
*
|
|
280
|
-
* Positioned immediately after </task> preamble per "Lost in the Middle" research.
|
|
281
|
-
* Critical instructions at START and END of prompt improve adherence.
|
|
282
|
-
*
|
|
283
|
-
* @returns {string} TDD directive section
|
|
284
|
-
*/
|
|
285
|
-
function generateTDDDirective() {
|
|
286
|
-
return `## ⛔ TDD DIRECTIVE — READ BEFORE CODING
|
|
287
|
-
|
|
288
|
-
**IF YOU WRITE IMPLEMENTATION CODE BEFORE A FAILING TEST, YOU HAVE FAILED THIS WU.**
|
|
289
|
-
|
|
290
|
-
### Test-First Workflow (MANDATORY)
|
|
291
|
-
|
|
292
|
-
1. Write a failing test for the acceptance criteria
|
|
293
|
-
2. Run the test to confirm it fails (RED)
|
|
294
|
-
3. Implement the minimum code to pass the test
|
|
295
|
-
4. Run the test to confirm it passes (GREEN)
|
|
296
|
-
5. Refactor if needed, keeping tests green
|
|
297
|
-
|
|
298
|
-
### Why This Matters
|
|
299
|
-
|
|
300
|
-
- Tests document expected behavior BEFORE implementation
|
|
301
|
-
- Prevents scope creep and over-engineering
|
|
302
|
-
- Ensures every feature has verification
|
|
303
|
-
- Failing tests prove the test actually tests something`;
|
|
304
|
-
}
|
|
305
810
|
/**
|
|
306
811
|
* Generate the context loading preamble
|
|
307
812
|
*
|
|
@@ -358,7 +863,7 @@ CRITICAL RULES - ENFORCE BEFORE EVERY ACTION:
|
|
|
358
863
|
- For ordinary errors: fix and retry autonomously (up to 3 attempts)
|
|
359
864
|
|
|
360
865
|
4. VERIFY COMPLETION before reporting success
|
|
361
|
-
- Run: node
|
|
866
|
+
- Run: node packages/@lumenflow/agent/dist/agent-verification.js ${id} (from shared checkout)
|
|
362
867
|
- Exit 0 = passed, Exit 1 = INCOMPLETE
|
|
363
868
|
- Never report "done" if verification fails
|
|
364
869
|
|
|
@@ -372,32 +877,49 @@ CRITICAL RULES - ENFORCE BEFORE EVERY ACTION:
|
|
|
372
877
|
- ALWAYS use \`git rebase origin/main\` before push
|
|
373
878
|
- Push to main via \`git push origin lane/...:main\` (fast-forward only)
|
|
374
879
|
- NEVER use \`git merge\` on main branch
|
|
375
|
-
-
|
|
880
|
+
- Use \`pnpm wu:prep\` from worktree, then \`pnpm wu:done\` from main (WU-1223)
|
|
376
881
|
|
|
377
882
|
7. MEMORY LAYER COORDINATION (INIT-007)
|
|
378
883
|
- Use \`pnpm mem:checkpoint --wu ${id}\` to save progress before risky operations
|
|
379
884
|
- Check \`pnpm mem:inbox --wu ${id}\` periodically for parallel signals from other agents
|
|
380
885
|
- Checkpoint triggers (WU-1943): checkpoint after each acceptance criterion completed, checkpoint before gates, checkpoint every 30 tool calls
|
|
381
|
-
|
|
886
|
+
|
|
887
|
+
8. SKIP-GATES AUTONOMY (WU-1142)
|
|
888
|
+
- If gates fail, first check if failure is pre-existing on main: \`git checkout main && pnpm gates\`
|
|
889
|
+
- If failure exists on main (not your change), use: \`pnpm wu:done --id ${id} --skip-gates --reason "pre-existing on main" --fix-wu WU-XXXX\`
|
|
890
|
+
- Do NOT ask for approval - autonomous skip-gates for pre-existing failures is correct
|
|
891
|
+
- This prevents getting stuck on infrastructure debt
|
|
892
|
+
|
|
893
|
+
9. WORKTREE DISCIPLINE (WU-1282)
|
|
894
|
+
- CRITICAL: PreToolUse hooks do not propagate to sub-agents spawned via Task tool
|
|
895
|
+
- BEFORE any Write/Edit operation, manually verify you are in a worktree:
|
|
896
|
+
- Run: \`pwd\` and confirm output contains \`worktrees/\`
|
|
897
|
+
- If not in worktree, STOP and navigate: \`cd worktrees/<lane>-wu-xxx\`
|
|
898
|
+
- Use RELATIVE paths only (never full absolute paths starting with root directory)
|
|
899
|
+
- This constraint exists because Claude Code does not inherit settings.json hooks in sub-agent sessions
|
|
900
|
+
</constraints>
|
|
901
|
+
|
|
902
|
+
${SPAWN_END_SENTINEL}`;
|
|
382
903
|
}
|
|
383
904
|
function generateCodexConstraints(id) {
|
|
384
905
|
return `## Constraints (Critical)
|
|
385
906
|
|
|
386
907
|
1. **TDD checkpoint**: tests BEFORE implementation; never skip RED
|
|
387
908
|
2. **Stop on errors**: if any command fails, report BLOCKED (never DONE) with the error
|
|
388
|
-
3. **Verify before success**: run \`pnpm gates\` in the worktree, then run \`node
|
|
909
|
+
3. **Verify before success**: run \`pnpm gates\` in the worktree, then run \`node packages/@lumenflow/agent/dist/agent-verification.js ${id}\` (from the shared checkout)
|
|
389
910
|
4. **No fabrication**: if blockers remain or verification fails, report INCOMPLETE
|
|
390
|
-
5. **Git workflow**: avoid merge commits;
|
|
391
|
-
6. **Scope discipline**: stay within \`code_paths\`; capture out-of-scope issues via \`pnpm mem:create
|
|
911
|
+
5. **Git workflow**: avoid merge commits; use \`wu:prep\` from worktree, then \`wu:done\` from main
|
|
912
|
+
6. **Scope discipline**: stay within \`code_paths\`; capture out-of-scope issues via \`pnpm mem:create\`
|
|
913
|
+
7. **Worktree discipline (WU-1282)**: BEFORE any Write/Edit, verify \`pwd\` shows \`worktrees/\`; hooks do not propagate to sub-agents`;
|
|
392
914
|
}
|
|
393
915
|
/**
|
|
394
916
|
* Generate mandatory agent advisory section
|
|
395
917
|
*
|
|
396
918
|
* @param {string[]} mandatoryAgents - Array of mandatory agent names
|
|
397
|
-
* @param {string}
|
|
919
|
+
* @param {string} _id - WU ID (reserved for future use)
|
|
398
920
|
* @returns {string} Mandatory agent section or empty string
|
|
399
921
|
*/
|
|
400
|
-
function generateMandatoryAgentSection(mandatoryAgents,
|
|
922
|
+
function generateMandatoryAgentSection(mandatoryAgents, _id) {
|
|
401
923
|
if (mandatoryAgents.length === 0) {
|
|
402
924
|
return '';
|
|
403
925
|
}
|
|
@@ -409,7 +931,7 @@ Based on code_paths, the following agents MUST be invoked:
|
|
|
409
931
|
|
|
410
932
|
${agentList}
|
|
411
933
|
|
|
412
|
-
Run: pnpm orchestrate:
|
|
934
|
+
Run: pnpm orchestrate:monitor to check agent status
|
|
413
935
|
`;
|
|
414
936
|
}
|
|
415
937
|
/**
|
|
@@ -527,15 +1049,74 @@ When finishing, provide structured output:
|
|
|
527
1049
|
This format enables orchestrator to track progress across waves.`;
|
|
528
1050
|
}
|
|
529
1051
|
/**
|
|
530
|
-
* Generate agent coordination section (WU-1987)
|
|
1052
|
+
* Generate agent coordination section (WU-1987, WU-1203)
|
|
531
1053
|
*
|
|
532
1054
|
* Provides guidance on mem:signal for parallel agent coordination,
|
|
533
|
-
* orchestrate:
|
|
1055
|
+
* orchestrate:monitor for agent status checks, and abandoned WU handling.
|
|
1056
|
+
*
|
|
1057
|
+
* WU-1203: Reads progress_signals config to generate dynamic guidance.
|
|
1058
|
+
* When enabled:true, shows "Progress Signals (Required at Milestones)" with
|
|
1059
|
+
* configurable triggers. When enabled:false or not configured, shows
|
|
1060
|
+
* "Progress Signals (Optional)".
|
|
534
1061
|
*
|
|
535
1062
|
* @param {string} id - WU ID
|
|
536
1063
|
* @returns {string} Agent coordination section
|
|
537
1064
|
*/
|
|
538
1065
|
export function generateAgentCoordinationSection(id) {
|
|
1066
|
+
const config = getConfig();
|
|
1067
|
+
const progressSignals = config.memory?.progress_signals;
|
|
1068
|
+
// WU-1210: Default to enabled (Required at Milestones) when not explicitly configured
|
|
1069
|
+
// This ensures agents signal progress at key milestones by default
|
|
1070
|
+
const isEnabled = progressSignals?.enabled ?? true;
|
|
1071
|
+
// Generate milestone triggers section based on config
|
|
1072
|
+
const generateMilestoneTriggers = () => {
|
|
1073
|
+
if (!isEnabled) {
|
|
1074
|
+
// Disabled - show optional guidance only
|
|
1075
|
+
return `For long-running work, send progress signals at milestones:
|
|
1076
|
+
|
|
1077
|
+
\`\`\`bash
|
|
1078
|
+
pnpm mem:signal "50% complete: tests passing, implementing adapter" --wu ${id}
|
|
1079
|
+
pnpm mem:signal "Blocked: waiting for WU-XXX dependency" --wu ${id}
|
|
1080
|
+
\`\`\``;
|
|
1081
|
+
}
|
|
1082
|
+
// WU-1210: isEnabled is true (either by default or explicit config)
|
|
1083
|
+
// Build list of enabled triggers, using defaults when progressSignals is undefined
|
|
1084
|
+
const triggers = [];
|
|
1085
|
+
// Default all triggers to enabled when not explicitly configured
|
|
1086
|
+
if ((progressSignals?.on_milestone ?? true) !== false) {
|
|
1087
|
+
triggers.push('**After each acceptance criterion completed** - helps track progress');
|
|
1088
|
+
}
|
|
1089
|
+
if ((progressSignals?.on_tests_pass ?? true) !== false) {
|
|
1090
|
+
triggers.push('**When tests first pass** - indicates implementation is working');
|
|
1091
|
+
}
|
|
1092
|
+
if ((progressSignals?.before_gates ?? true) !== false) {
|
|
1093
|
+
triggers.push('**Before running gates** - signals imminent completion');
|
|
1094
|
+
}
|
|
1095
|
+
if ((progressSignals?.on_blocked ?? true) !== false) {
|
|
1096
|
+
triggers.push('**When blocked** - allows orchestrator to re-allocate or assist');
|
|
1097
|
+
}
|
|
1098
|
+
// Add frequency-based trigger if configured
|
|
1099
|
+
const frequency = progressSignals?.frequency ?? 0;
|
|
1100
|
+
let frequencyGuidance = '';
|
|
1101
|
+
if (frequency > 0) {
|
|
1102
|
+
frequencyGuidance = `\n5. **Every ${frequency} tool calls** - periodic progress update`;
|
|
1103
|
+
}
|
|
1104
|
+
const triggerList = triggers.length > 0
|
|
1105
|
+
? triggers.map((t, i) => `${i + 1}. ${t}`).join('\n') + frequencyGuidance
|
|
1106
|
+
: 'Signal at key milestones to enable orchestrator visibility.';
|
|
1107
|
+
return `**Signal at these milestones** to enable orchestrator visibility:
|
|
1108
|
+
|
|
1109
|
+
${triggerList}
|
|
1110
|
+
|
|
1111
|
+
\`\`\`bash
|
|
1112
|
+
pnpm mem:signal "AC1 complete: tests passing for feature X" --wu ${id}
|
|
1113
|
+
pnpm mem:signal "All tests passing, running gates" --wu ${id}
|
|
1114
|
+
pnpm mem:signal "Blocked: waiting for WU-XXX dependency" --wu ${id}
|
|
1115
|
+
\`\`\``;
|
|
1116
|
+
};
|
|
1117
|
+
const progressSectionTitle = isEnabled
|
|
1118
|
+
? '### Progress Signals (Required at Milestones)'
|
|
1119
|
+
: '### Progress Signals (Optional)';
|
|
539
1120
|
return `## Agent Coordination (Parallel Work)
|
|
540
1121
|
|
|
541
1122
|
### ⚠️ CRITICAL: Use mem:signal, NOT TaskOutput
|
|
@@ -557,14 +1138,9 @@ pnpm mem:inbox --since 30m
|
|
|
557
1138
|
manually signal completion - just run \`wu:done\` and orchestrators will
|
|
558
1139
|
see your signal via \`mem:inbox\`.
|
|
559
1140
|
|
|
560
|
-
|
|
1141
|
+
${progressSectionTitle}
|
|
561
1142
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
\`\`\`bash
|
|
565
|
-
pnpm mem:signal "50% complete: tests passing, implementing adapter" --wu ${id}
|
|
566
|
-
pnpm mem:signal "Blocked: waiting for WU-XXX dependency" --wu ${id}
|
|
567
|
-
\`\`\`
|
|
1143
|
+
${generateMilestoneTriggers()}
|
|
568
1144
|
|
|
569
1145
|
### Checking Status
|
|
570
1146
|
|
|
@@ -594,6 +1170,31 @@ pnpm typecheck # Check TypeScript types
|
|
|
594
1170
|
|
|
595
1171
|
**Use before gates** to catch simple issues early. These are faster than full \`pnpm gates\`.`;
|
|
596
1172
|
}
|
|
1173
|
+
/**
|
|
1174
|
+
* WU-1270: Emit methodology telemetry event (opt-in)
|
|
1175
|
+
*
|
|
1176
|
+
* Emits privacy-preserving telemetry about methodology selection.
|
|
1177
|
+
* Only emits if telemetry.methodology.enabled is true in config.
|
|
1178
|
+
*
|
|
1179
|
+
* @param config - LumenFlow configuration
|
|
1180
|
+
* @param policy - Resolved methodology policy
|
|
1181
|
+
*/
|
|
1182
|
+
export function emitMethodologyTelemetry(config, policy) {
|
|
1183
|
+
// Check if methodology telemetry is opt-in enabled
|
|
1184
|
+
if (!config.telemetry?.methodology?.enabled) {
|
|
1185
|
+
return;
|
|
1186
|
+
}
|
|
1187
|
+
const event = {
|
|
1188
|
+
timestamp: new Date().toISOString(),
|
|
1189
|
+
event_type: 'methodology.selection',
|
|
1190
|
+
methodology_testing: policy.testing,
|
|
1191
|
+
methodology_architecture: policy.architecture,
|
|
1192
|
+
event_context: 'spawn',
|
|
1193
|
+
};
|
|
1194
|
+
// Use the telemetry emit function from telemetry.ts
|
|
1195
|
+
const METHODOLOGY_LOG = '.lumenflow/telemetry/methodology.ndjson';
|
|
1196
|
+
emitTelemetry(METHODOLOGY_LOG, event);
|
|
1197
|
+
}
|
|
597
1198
|
/**
|
|
598
1199
|
* Generate Lane Selection section (WU-2107)
|
|
599
1200
|
*
|
|
@@ -724,7 +1325,7 @@ pnpm mem:triage --wu ${id} # List discoveries for this WU
|
|
|
724
1325
|
pnpm mem:triage --promote <node-id> --lane "<lane>" # Create Bug WU (human action)
|
|
725
1326
|
\`\`\`
|
|
726
1327
|
|
|
727
|
-
See:
|
|
1328
|
+
See: https://lumenflow.dev/reference/agent-invocation-guide/ §Bug Discovery`;
|
|
728
1329
|
}
|
|
729
1330
|
/**
|
|
730
1331
|
* Generate lane-specific guidance
|
|
@@ -817,9 +1418,15 @@ export function generateTaskInvocation(doc, id, strategy, options = {}) {
|
|
|
817
1418
|
const codePaths = doc.code_paths || [];
|
|
818
1419
|
const mandatoryAgents = detectMandatoryAgents(codePaths);
|
|
819
1420
|
const preamble = generatePreamble(id, strategy);
|
|
820
|
-
const tddDirective = generateTDDDirective();
|
|
821
1421
|
const clientContext = options.client;
|
|
822
1422
|
const config = options.config || getConfig();
|
|
1423
|
+
// WU-1279: Resolve policy and use policy-based test guidance
|
|
1424
|
+
const policy = resolvePolicy(config);
|
|
1425
|
+
const testGuidance = generatePolicyBasedTestGuidance(doc.type || 'feature', policy);
|
|
1426
|
+
// WU-1279: Generate enforcement summary from resolved policy
|
|
1427
|
+
const enforcementSummary = generateEnforcementSummary(policy);
|
|
1428
|
+
// WU-1279: Generate mandatory standards based on resolved policy
|
|
1429
|
+
const mandatoryStandards = generateMandatoryStandards(policy);
|
|
823
1430
|
const clientSkillsGuidance = generateClientSkillsGuidance(clientContext);
|
|
824
1431
|
const skillsSection = generateSkillsSelectionSection(doc, config, clientContext?.name) +
|
|
825
1432
|
(clientSkillsGuidance ? `\n${clientSkillsGuidance}` : '');
|
|
@@ -844,6 +1451,10 @@ export function generateTaskInvocation(doc, id, strategy, options = {}) {
|
|
|
844
1451
|
const laneSelection = generateLaneSelectionSection();
|
|
845
1452
|
// WU-2362: Worktree path guidance for sub-agents
|
|
846
1453
|
const worktreeGuidance = generateWorktreePathGuidance(doc.worktree_path);
|
|
1454
|
+
// WU-1240: Memory context section
|
|
1455
|
+
// Include if explicitly enabled and not disabled via noContext
|
|
1456
|
+
const shouldIncludeMemoryContext = options.includeMemoryContext && !options.noContext;
|
|
1457
|
+
const memoryContextSection = shouldIncludeMemoryContext ? options.memoryContextContent || '' : '';
|
|
847
1458
|
// Generate thinking mode sections if applicable
|
|
848
1459
|
const executionModeSection = generateExecutionModeSection(options);
|
|
849
1460
|
const thinkToolGuidance = generateThinkToolGuidance(options);
|
|
@@ -853,14 +1464,14 @@ export function generateTaskInvocation(doc, id, strategy, options = {}) {
|
|
|
853
1464
|
.join('\n\n---\n\n');
|
|
854
1465
|
const thinkingBlock = thinkingSections ? `${thinkingSections}\n\n---\n\n` : '';
|
|
855
1466
|
// Build the task prompt
|
|
856
|
-
//
|
|
857
|
-
const taskPrompt =
|
|
1467
|
+
// WU-1192: Truncation warning at start, test guidance after </task> per "Lost in the Middle" research
|
|
1468
|
+
const taskPrompt = `${TRUNCATION_WARNING_BANNER}<task>
|
|
858
1469
|
${preamble}
|
|
859
1470
|
</task>
|
|
860
1471
|
|
|
861
1472
|
---
|
|
862
1473
|
|
|
863
|
-
${
|
|
1474
|
+
${testGuidance}
|
|
864
1475
|
|
|
865
1476
|
---
|
|
866
1477
|
|
|
@@ -888,19 +1499,13 @@ ${codePaths.length > 0 ? codePaths.map((p) => `- ${p}`).join('\n') : '- No code
|
|
|
888
1499
|
${mandatorySection}${invariantsPriorArt ? `---\n\n${invariantsPriorArt}\n\n` : ''}${implementationContext ? `---\n\n${implementationContext}\n\n` : ''}---
|
|
889
1500
|
|
|
890
1501
|
${thinkingBlock}${skillsSection}
|
|
891
|
-
---
|
|
1502
|
+
${memoryContextSection ? `---\n\n${memoryContextSection}\n\n` : ''}---
|
|
892
1503
|
|
|
893
|
-
|
|
1504
|
+
${mandatoryStandards}
|
|
894
1505
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
- **SOLID/DRY/YAGNI/KISS**: No over-engineering, no premature abstraction
|
|
899
|
-
- **Library-First**: Search context7 before writing custom code. No reinventing wheels
|
|
900
|
-
- **Code Quality**: No string literals, no magic numbers, no brittle regexes when libraries exist
|
|
901
|
-
- **Worktree Discipline**: ALWAYS use \`pnpm wu:claim\` to create worktrees (never \`git worktree add\` directly). Work ONLY in the worktree, never edit main
|
|
902
|
-
- **Documentation**: Update tooling docs if changing tools. Keep docs in sync with code
|
|
903
|
-
- **Sub-agents**: Use Explore agent for codebase investigation. Activate mandatory agents (security-auditor for PHI/auth, beacon-guardian for LLM/prompts)
|
|
1506
|
+
---
|
|
1507
|
+
|
|
1508
|
+
${enforcementSummary}
|
|
904
1509
|
|
|
905
1510
|
${clientBlocks ? `---\n\n${clientBlocks}\n\n` : ''}${worktreeGuidance ? `---\n\n${worktreeGuidance}\n\n` : ''}---
|
|
906
1511
|
|
|
@@ -971,7 +1576,6 @@ export function generateCodexPrompt(doc, id, strategy, options = {}) {
|
|
|
971
1576
|
const codePaths = doc.code_paths || [];
|
|
972
1577
|
const mandatoryAgents = detectMandatoryAgents(codePaths);
|
|
973
1578
|
const preamble = generatePreamble(id, strategy);
|
|
974
|
-
const tddDirective = generateTDDDirective();
|
|
975
1579
|
const mandatorySection = generateMandatoryAgentSection(mandatoryAgents, id);
|
|
976
1580
|
const laneGuidance = generateLaneGuidance(doc.lane);
|
|
977
1581
|
const bugDiscoverySection = generateBugDiscoverySection(id);
|
|
@@ -984,6 +1588,13 @@ export function generateCodexPrompt(doc, id, strategy, options = {}) {
|
|
|
984
1588
|
const skillsSection = generateSkillsSelectionSection(doc, config, clientContext?.name) +
|
|
985
1589
|
(clientSkillsGuidance ? `\n${clientSkillsGuidance}` : '');
|
|
986
1590
|
const clientBlocks = generateClientBlocksSection(clientContext);
|
|
1591
|
+
// WU-1290: Resolve policy and use policy-based test guidance (same as generateTaskInvocation)
|
|
1592
|
+
const policy = resolvePolicy(config);
|
|
1593
|
+
const testGuidance = generatePolicyBasedTestGuidance(doc.type || 'feature', policy);
|
|
1594
|
+
// WU-1290: Generate enforcement summary from resolved policy
|
|
1595
|
+
const enforcementSummary = generateEnforcementSummary(policy);
|
|
1596
|
+
// WU-1290: Generate mandatory standards based on resolved policy
|
|
1597
|
+
const mandatoryStandards = generateMandatoryStandards(policy);
|
|
987
1598
|
const executionModeSection = generateExecutionModeSection(options);
|
|
988
1599
|
const thinkToolGuidance = generateThinkToolGuidance(options);
|
|
989
1600
|
const thinkingSections = [executionModeSection, thinkToolGuidance]
|
|
@@ -992,7 +1603,7 @@ export function generateCodexPrompt(doc, id, strategy, options = {}) {
|
|
|
992
1603
|
const thinkingBlock = thinkingSections ? `${thinkingSections}\n\n---\n\n` : '';
|
|
993
1604
|
return `# ${id}: ${doc.title || 'Untitled'}
|
|
994
1605
|
|
|
995
|
-
${
|
|
1606
|
+
${testGuidance}
|
|
996
1607
|
|
|
997
1608
|
---
|
|
998
1609
|
|
|
@@ -1026,6 +1637,14 @@ ${formatAcceptance(doc.acceptance)}
|
|
|
1026
1637
|
|
|
1027
1638
|
---
|
|
1028
1639
|
|
|
1640
|
+
${mandatoryStandards}
|
|
1641
|
+
|
|
1642
|
+
---
|
|
1643
|
+
|
|
1644
|
+
${enforcementSummary}
|
|
1645
|
+
|
|
1646
|
+
---
|
|
1647
|
+
|
|
1029
1648
|
${skillsSection}
|
|
1030
1649
|
|
|
1031
1650
|
---
|
|
@@ -1039,7 +1658,7 @@ ${action}
|
|
|
1039
1658
|
## Verification
|
|
1040
1659
|
|
|
1041
1660
|
- Run in worktree: \`pnpm gates\`
|
|
1042
|
-
- From shared checkout: \`node
|
|
1661
|
+
- From shared checkout: \`node packages/@lumenflow/agent/dist/agent-verification.js ${id}\`
|
|
1043
1662
|
|
|
1044
1663
|
---
|
|
1045
1664
|
|
|
@@ -1222,6 +1841,9 @@ async function main() {
|
|
|
1222
1841
|
console.log(`${LOG_PREFIX} Generated Task tool invocation for ${id}`);
|
|
1223
1842
|
console.log(`${LOG_PREFIX} Copy the block below to spawn a sub-agent:\n`);
|
|
1224
1843
|
console.log(invocation);
|
|
1844
|
+
// WU-1270: Emit methodology telemetry (opt-in only)
|
|
1845
|
+
const policy = resolvePolicy(config);
|
|
1846
|
+
emitMethodologyTelemetry(config, policy);
|
|
1225
1847
|
// WU-1945: Record spawn event to registry (non-blocking)
|
|
1226
1848
|
// Only record if --parent-wu is provided (orchestrator context)
|
|
1227
1849
|
if (args.parentWu) {
|