@lumenflow/core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/README.md +119 -0
- package/dist/active-wu-detector.d.ts +33 -0
- package/dist/active-wu-detector.js +106 -0
- package/dist/adapters/filesystem-metrics.adapter.d.ts +108 -0
- package/dist/adapters/filesystem-metrics.adapter.js +519 -0
- package/dist/adapters/terminal-renderer.adapter.d.ts +106 -0
- package/dist/adapters/terminal-renderer.adapter.js +337 -0
- package/dist/arg-parser.d.ts +63 -0
- package/dist/arg-parser.js +560 -0
- package/dist/backlog-editor.d.ts +98 -0
- package/dist/backlog-editor.js +179 -0
- package/dist/backlog-generator.d.ts +111 -0
- package/dist/backlog-generator.js +381 -0
- package/dist/backlog-parser.d.ts +45 -0
- package/dist/backlog-parser.js +102 -0
- package/dist/backlog-sync-validator.d.ts +78 -0
- package/dist/backlog-sync-validator.js +294 -0
- package/dist/branch-drift.d.ts +34 -0
- package/dist/branch-drift.js +51 -0
- package/dist/cleanup-install-config.d.ts +33 -0
- package/dist/cleanup-install-config.js +37 -0
- package/dist/cleanup-lock.d.ts +139 -0
- package/dist/cleanup-lock.js +313 -0
- package/dist/code-path-validator.d.ts +146 -0
- package/dist/code-path-validator.js +537 -0
- package/dist/code-paths-overlap.d.ts +55 -0
- package/dist/code-paths-overlap.js +245 -0
- package/dist/commands-logger.d.ts +77 -0
- package/dist/commands-logger.js +254 -0
- package/dist/commit-message-utils.d.ts +25 -0
- package/dist/commit-message-utils.js +41 -0
- package/dist/compliance-parser.d.ts +150 -0
- package/dist/compliance-parser.js +507 -0
- package/dist/constants/backlog-patterns.d.ts +20 -0
- package/dist/constants/backlog-patterns.js +23 -0
- package/dist/constants/dora-constants.d.ts +49 -0
- package/dist/constants/dora-constants.js +53 -0
- package/dist/constants/gate-constants.d.ts +15 -0
- package/dist/constants/gate-constants.js +15 -0
- package/dist/constants/linter-constants.d.ts +16 -0
- package/dist/constants/linter-constants.js +16 -0
- package/dist/constants/tokenizer-constants.d.ts +15 -0
- package/dist/constants/tokenizer-constants.js +15 -0
- package/dist/core/scope-checker.d.ts +97 -0
- package/dist/core/scope-checker.js +163 -0
- package/dist/core/tool-runner.d.ts +161 -0
- package/dist/core/tool-runner.js +393 -0
- package/dist/core/tool.constants.d.ts +105 -0
- package/dist/core/tool.constants.js +101 -0
- package/dist/core/tool.schemas.d.ts +226 -0
- package/dist/core/tool.schemas.js +226 -0
- package/dist/core/worktree-guard.d.ts +130 -0
- package/dist/core/worktree-guard.js +242 -0
- package/dist/coverage-gate.d.ts +108 -0
- package/dist/coverage-gate.js +196 -0
- package/dist/date-utils.d.ts +75 -0
- package/dist/date-utils.js +140 -0
- package/dist/dependency-graph.d.ts +142 -0
- package/dist/dependency-graph.js +550 -0
- package/dist/dependency-guard.d.ts +54 -0
- package/dist/dependency-guard.js +142 -0
- package/dist/dependency-validator.d.ts +105 -0
- package/dist/dependency-validator.js +154 -0
- package/dist/docs-path-validator.d.ts +36 -0
- package/dist/docs-path-validator.js +95 -0
- package/dist/domain/orchestration.constants.d.ts +99 -0
- package/dist/domain/orchestration.constants.js +97 -0
- package/dist/domain/orchestration.schemas.d.ts +280 -0
- package/dist/domain/orchestration.schemas.js +211 -0
- package/dist/domain/orchestration.types.d.ts +133 -0
- package/dist/domain/orchestration.types.js +12 -0
- package/dist/error-handler.d.ts +116 -0
- package/dist/error-handler.js +136 -0
- package/dist/file-classifiers.d.ts +62 -0
- package/dist/file-classifiers.js +108 -0
- package/dist/gates-agent-mode.d.ts +81 -0
- package/dist/gates-agent-mode.js +94 -0
- package/dist/generate-traceability.d.ts +107 -0
- package/dist/generate-traceability.js +411 -0
- package/dist/git-adapter.d.ts +395 -0
- package/dist/git-adapter.js +649 -0
- package/dist/git-staged-validator.d.ts +32 -0
- package/dist/git-staged-validator.js +48 -0
- package/dist/hardcoded-strings.d.ts +61 -0
- package/dist/hardcoded-strings.js +270 -0
- package/dist/incremental-lint.d.ts +78 -0
- package/dist/incremental-lint.js +129 -0
- package/dist/incremental-test.d.ts +39 -0
- package/dist/incremental-test.js +61 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +61 -0
- package/dist/invariants/check-automated-tests.d.ts +50 -0
- package/dist/invariants/check-automated-tests.js +166 -0
- package/dist/invariants-runner.d.ts +103 -0
- package/dist/invariants-runner.js +527 -0
- package/dist/lane-checker.d.ts +50 -0
- package/dist/lane-checker.js +319 -0
- package/dist/lane-inference.d.ts +39 -0
- package/dist/lane-inference.js +195 -0
- package/dist/lane-lock.d.ts +211 -0
- package/dist/lane-lock.js +474 -0
- package/dist/lane-validator.d.ts +48 -0
- package/dist/lane-validator.js +114 -0
- package/dist/logs-lib.d.ts +104 -0
- package/dist/logs-lib.js +207 -0
- package/dist/lumenflow-config-schema.d.ts +272 -0
- package/dist/lumenflow-config-schema.js +207 -0
- package/dist/lumenflow-config.d.ts +95 -0
- package/dist/lumenflow-config.js +236 -0
- package/dist/manual-test-validator.d.ts +80 -0
- package/dist/manual-test-validator.js +200 -0
- package/dist/merge-lock.d.ts +115 -0
- package/dist/merge-lock.js +251 -0
- package/dist/micro-worktree.d.ts +159 -0
- package/dist/micro-worktree.js +427 -0
- package/dist/migration-deployer.d.ts +69 -0
- package/dist/migration-deployer.js +151 -0
- package/dist/orchestration-advisory-loader.d.ts +28 -0
- package/dist/orchestration-advisory-loader.js +87 -0
- package/dist/orchestration-advisory.d.ts +58 -0
- package/dist/orchestration-advisory.js +94 -0
- package/dist/orchestration-di.d.ts +48 -0
- package/dist/orchestration-di.js +57 -0
- package/dist/orchestration-rules.d.ts +57 -0
- package/dist/orchestration-rules.js +201 -0
- package/dist/orphan-detector.d.ts +131 -0
- package/dist/orphan-detector.js +226 -0
- package/dist/path-classifiers.d.ts +57 -0
- package/dist/path-classifiers.js +93 -0
- package/dist/piped-command-detector.d.ts +34 -0
- package/dist/piped-command-detector.js +64 -0
- package/dist/ports/dashboard-renderer.port.d.ts +112 -0
- package/dist/ports/dashboard-renderer.port.js +25 -0
- package/dist/ports/metrics-collector.port.d.ts +132 -0
- package/dist/ports/metrics-collector.port.js +26 -0
- package/dist/process-detector.d.ts +84 -0
- package/dist/process-detector.js +172 -0
- package/dist/prompt-linter.d.ts +72 -0
- package/dist/prompt-linter.js +312 -0
- package/dist/prompt-monitor.d.ts +15 -0
- package/dist/prompt-monitor.js +205 -0
- package/dist/rebase-artifact-cleanup.d.ts +145 -0
- package/dist/rebase-artifact-cleanup.js +433 -0
- package/dist/retry-strategy.d.ts +189 -0
- package/dist/retry-strategy.js +283 -0
- package/dist/risk-detector.d.ts +108 -0
- package/dist/risk-detector.js +252 -0
- package/dist/rollback-utils.d.ts +76 -0
- package/dist/rollback-utils.js +104 -0
- package/dist/section-headings.d.ts +43 -0
- package/dist/section-headings.js +49 -0
- package/dist/spawn-escalation.d.ts +90 -0
- package/dist/spawn-escalation.js +253 -0
- package/dist/spawn-monitor.d.ts +229 -0
- package/dist/spawn-monitor.js +672 -0
- package/dist/spawn-recovery.d.ts +82 -0
- package/dist/spawn-recovery.js +298 -0
- package/dist/spawn-registry-schema.d.ts +98 -0
- package/dist/spawn-registry-schema.js +108 -0
- package/dist/spawn-registry-store.d.ts +146 -0
- package/dist/spawn-registry-store.js +273 -0
- package/dist/spawn-tree.d.ts +121 -0
- package/dist/spawn-tree.js +285 -0
- package/dist/stamp-status-validator.d.ts +84 -0
- package/dist/stamp-status-validator.js +134 -0
- package/dist/stamp-utils.d.ts +100 -0
- package/dist/stamp-utils.js +229 -0
- package/dist/state-machine.d.ts +26 -0
- package/dist/state-machine.js +83 -0
- package/dist/system-map-validator.d.ts +80 -0
- package/dist/system-map-validator.js +272 -0
- package/dist/telemetry.d.ts +80 -0
- package/dist/telemetry.js +213 -0
- package/dist/token-counter.d.ts +51 -0
- package/dist/token-counter.js +145 -0
- package/dist/usecases/get-dashboard-data.usecase.d.ts +52 -0
- package/dist/usecases/get-dashboard-data.usecase.js +61 -0
- package/dist/usecases/get-suggestions.usecase.d.ts +100 -0
- package/dist/usecases/get-suggestions.usecase.js +153 -0
- package/dist/user-normalizer.d.ts +41 -0
- package/dist/user-normalizer.js +141 -0
- package/dist/validators/phi-constants.d.ts +97 -0
- package/dist/validators/phi-constants.js +152 -0
- package/dist/validators/phi-scanner.d.ts +58 -0
- package/dist/validators/phi-scanner.js +215 -0
- package/dist/worktree-ownership.d.ts +50 -0
- package/dist/worktree-ownership.js +74 -0
- package/dist/worktree-scanner.d.ts +103 -0
- package/dist/worktree-scanner.js +168 -0
- package/dist/worktree-symlink.d.ts +99 -0
- package/dist/worktree-symlink.js +359 -0
- package/dist/wu-backlog-updater.d.ts +17 -0
- package/dist/wu-backlog-updater.js +37 -0
- package/dist/wu-checkpoint.d.ts +124 -0
- package/dist/wu-checkpoint.js +233 -0
- package/dist/wu-claim-helpers.d.ts +26 -0
- package/dist/wu-claim-helpers.js +63 -0
- package/dist/wu-claim-resume.d.ts +106 -0
- package/dist/wu-claim-resume.js +276 -0
- package/dist/wu-consistency-checker.d.ts +95 -0
- package/dist/wu-consistency-checker.js +567 -0
- package/dist/wu-constants.d.ts +1275 -0
- package/dist/wu-constants.js +1382 -0
- package/dist/wu-create-validators.d.ts +42 -0
- package/dist/wu-create-validators.js +93 -0
- package/dist/wu-done-branch-only.d.ts +63 -0
- package/dist/wu-done-branch-only.js +191 -0
- package/dist/wu-done-messages.d.ts +119 -0
- package/dist/wu-done-messages.js +185 -0
- package/dist/wu-done-pr.d.ts +72 -0
- package/dist/wu-done-pr.js +174 -0
- package/dist/wu-done-retry-helpers.d.ts +85 -0
- package/dist/wu-done-retry-helpers.js +172 -0
- package/dist/wu-done-ui.d.ts +37 -0
- package/dist/wu-done-ui.js +69 -0
- package/dist/wu-done-validators.d.ts +411 -0
- package/dist/wu-done-validators.js +1229 -0
- package/dist/wu-done-worktree.d.ts +182 -0
- package/dist/wu-done-worktree.js +1097 -0
- package/dist/wu-helpers.d.ts +128 -0
- package/dist/wu-helpers.js +248 -0
- package/dist/wu-lint.d.ts +70 -0
- package/dist/wu-lint.js +234 -0
- package/dist/wu-paths.d.ts +171 -0
- package/dist/wu-paths.js +178 -0
- package/dist/wu-preflight-validators.d.ts +86 -0
- package/dist/wu-preflight-validators.js +251 -0
- package/dist/wu-recovery.d.ts +138 -0
- package/dist/wu-recovery.js +341 -0
- package/dist/wu-repair-core.d.ts +131 -0
- package/dist/wu-repair-core.js +669 -0
- package/dist/wu-schema-normalization.d.ts +17 -0
- package/dist/wu-schema-normalization.js +82 -0
- package/dist/wu-schema.d.ts +793 -0
- package/dist/wu-schema.js +881 -0
- package/dist/wu-spawn-helpers.d.ts +121 -0
- package/dist/wu-spawn-helpers.js +271 -0
- package/dist/wu-spawn.d.ts +158 -0
- package/dist/wu-spawn.js +1306 -0
- package/dist/wu-state-schema.d.ts +213 -0
- package/dist/wu-state-schema.js +156 -0
- package/dist/wu-state-store.d.ts +264 -0
- package/dist/wu-state-store.js +691 -0
- package/dist/wu-status-transition.d.ts +63 -0
- package/dist/wu-status-transition.js +382 -0
- package/dist/wu-status-updater.d.ts +25 -0
- package/dist/wu-status-updater.js +116 -0
- package/dist/wu-transaction-collectors.d.ts +116 -0
- package/dist/wu-transaction-collectors.js +272 -0
- package/dist/wu-transaction.d.ts +170 -0
- package/dist/wu-transaction.js +273 -0
- package/dist/wu-validation-constants.d.ts +60 -0
- package/dist/wu-validation-constants.js +66 -0
- package/dist/wu-validation.d.ts +118 -0
- package/dist/wu-validation.js +243 -0
- package/dist/wu-validator.d.ts +62 -0
- package/dist/wu-validator.js +325 -0
- package/dist/wu-yaml-fixer.d.ts +97 -0
- package/dist/wu-yaml-fixer.js +264 -0
- package/dist/wu-yaml.d.ts +86 -0
- package/dist/wu-yaml.js +222 -0
- package/package.json +114 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WU Transaction - Atomic write operations for wu:done
|
|
3
|
+
*
|
|
4
|
+
* WU-1369: Implements transactional pattern for metadata updates.
|
|
5
|
+
* Collects all changes in memory, validates, then writes atomically.
|
|
6
|
+
*
|
|
7
|
+
* Pattern:
|
|
8
|
+
* 1. Create transaction
|
|
9
|
+
* 2. Collect all pending writes (in memory)
|
|
10
|
+
* 3. Validate pending state
|
|
11
|
+
* 4. Commit (write all files) or abort (discard)
|
|
12
|
+
*
|
|
13
|
+
* This ensures no partial state on validation failure:
|
|
14
|
+
* - If validation fails → no files written
|
|
15
|
+
* - If any write fails → error with cleanup info
|
|
16
|
+
*/
|
|
17
|
+
import { existsSync, writeFileSync, mkdirSync, readFileSync, unlinkSync } from 'node:fs';
|
|
18
|
+
import path from 'node:path';
|
|
19
|
+
import { LOG_PREFIX, EMOJI } from './wu-constants.js';
|
|
20
|
+
import { createError, ErrorCodes } from './error-handler.js';
|
|
21
|
+
/**
|
|
22
|
+
* Transaction for atomic metadata updates
|
|
23
|
+
*
|
|
24
|
+
* Usage:
|
|
25
|
+
* ```js
|
|
26
|
+
* const tx = new WUTransaction(id);
|
|
27
|
+
*
|
|
28
|
+
* // Collect pending changes
|
|
29
|
+
* tx.addWrite(wuPath, yamlContent, 'WU YAML');
|
|
30
|
+
* tx.addWrite(statusPath, statusContent, 'status.md');
|
|
31
|
+
*
|
|
32
|
+
* // Validate (no writes happen yet)
|
|
33
|
+
* const validation = tx.validate();
|
|
34
|
+
* if (!validation.valid) {
|
|
35
|
+
* tx.abort();
|
|
36
|
+
* return;
|
|
37
|
+
* }
|
|
38
|
+
*
|
|
39
|
+
* // Commit all changes atomically
|
|
40
|
+
* const result = tx.commit();
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export class WUTransaction {
|
|
44
|
+
wuId;
|
|
45
|
+
pendingWrites;
|
|
46
|
+
committed;
|
|
47
|
+
aborted;
|
|
48
|
+
createdAt;
|
|
49
|
+
/**
|
|
50
|
+
* Create a new transaction
|
|
51
|
+
* @param {string} wuId - WU ID for logging context
|
|
52
|
+
*/
|
|
53
|
+
constructor(wuId) {
|
|
54
|
+
this.wuId = wuId;
|
|
55
|
+
this.pendingWrites = new Map();
|
|
56
|
+
this.committed = false;
|
|
57
|
+
this.aborted = false;
|
|
58
|
+
this.createdAt = new Date();
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Add a pending file write operation
|
|
62
|
+
*
|
|
63
|
+
* @param {string} filePath - File path to write
|
|
64
|
+
* @param {string} content - Content to write
|
|
65
|
+
* @param {string} description - Human-readable description
|
|
66
|
+
* @throws {Error} If transaction already committed or aborted
|
|
67
|
+
*/
|
|
68
|
+
addWrite(filePath, content, description) {
|
|
69
|
+
if (this.committed) {
|
|
70
|
+
throw createError(ErrorCodes.TRANSACTION_ERROR, `Cannot add writes to committed transaction (${this.wuId})`, { wuId: this.wuId, path: filePath });
|
|
71
|
+
}
|
|
72
|
+
if (this.aborted) {
|
|
73
|
+
throw createError(ErrorCodes.TRANSACTION_ERROR, `Cannot add writes to aborted transaction (${this.wuId})`, { wuId: this.wuId, path: filePath });
|
|
74
|
+
}
|
|
75
|
+
this.pendingWrites.set(filePath, {
|
|
76
|
+
path: filePath,
|
|
77
|
+
content,
|
|
78
|
+
description,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get pending writes for inspection
|
|
83
|
+
* @returns {PendingWrite[]}
|
|
84
|
+
*/
|
|
85
|
+
getPendingWrites() {
|
|
86
|
+
return Array.from(this.pendingWrites.values());
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get count of pending writes
|
|
90
|
+
* @returns {number}
|
|
91
|
+
*/
|
|
92
|
+
get size() {
|
|
93
|
+
return this.pendingWrites.size;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Check if transaction has been committed
|
|
97
|
+
* @returns {boolean}
|
|
98
|
+
*/
|
|
99
|
+
get isCommitted() {
|
|
100
|
+
return this.committed;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Check if transaction has been aborted
|
|
104
|
+
* @returns {boolean}
|
|
105
|
+
*/
|
|
106
|
+
get isAborted() {
|
|
107
|
+
return this.aborted;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Validate pending writes (pre-commit checks)
|
|
111
|
+
*
|
|
112
|
+
* Checks:
|
|
113
|
+
* - All parent directories can be created
|
|
114
|
+
* - No duplicate paths with different content
|
|
115
|
+
* - Content is valid (non-empty for critical files)
|
|
116
|
+
*
|
|
117
|
+
* @returns {{ valid: boolean, errors: string[] }}
|
|
118
|
+
*/
|
|
119
|
+
validate() {
|
|
120
|
+
const errors = [];
|
|
121
|
+
if (this.pendingWrites.size === 0) {
|
|
122
|
+
errors.push('No pending writes in transaction');
|
|
123
|
+
return { valid: false, errors };
|
|
124
|
+
}
|
|
125
|
+
for (const [filePath, write] of this.pendingWrites) {
|
|
126
|
+
// Check content is defined
|
|
127
|
+
if (write.content === undefined || write.content === null) {
|
|
128
|
+
errors.push(`${write.description}: Content is undefined`);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
// Check parent directory exists or can be created
|
|
132
|
+
const dir = path.dirname(filePath);
|
|
133
|
+
if (dir && dir !== '.' && !existsSync(dir)) {
|
|
134
|
+
// Will be created during commit - just note for logging
|
|
135
|
+
console.log(`${LOG_PREFIX.DONE} Will create directory: ${dir}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return { valid: errors.length === 0, errors };
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Commit all pending writes atomically
|
|
142
|
+
*
|
|
143
|
+
* Writes all files in a single batch. If any write fails,
|
|
144
|
+
* reports which files were written vs failed.
|
|
145
|
+
*
|
|
146
|
+
* @returns {{ success: boolean, written: string[], failed: { path: string, error: string }[] }}
|
|
147
|
+
* @throws {Error} If transaction already committed or aborted
|
|
148
|
+
*/
|
|
149
|
+
commit() {
|
|
150
|
+
if (this.committed) {
|
|
151
|
+
throw createError(ErrorCodes.TRANSACTION_ERROR, `Transaction already committed (${this.wuId})`, { wuId: this.wuId });
|
|
152
|
+
}
|
|
153
|
+
if (this.aborted) {
|
|
154
|
+
throw createError(ErrorCodes.TRANSACTION_ERROR, `Cannot commit aborted transaction (${this.wuId})`, { wuId: this.wuId });
|
|
155
|
+
}
|
|
156
|
+
const written = [];
|
|
157
|
+
const failed = [];
|
|
158
|
+
console.log(`${LOG_PREFIX.DONE} ${EMOJI.SUCCESS} Transaction COMMIT - writing ${this.pendingWrites.size} files atomically`);
|
|
159
|
+
for (const [filePath, write] of this.pendingWrites) {
|
|
160
|
+
try {
|
|
161
|
+
// Ensure parent directory exists
|
|
162
|
+
const dir = path.dirname(filePath);
|
|
163
|
+
if (dir && dir !== '.' && !existsSync(dir)) {
|
|
164
|
+
mkdirSync(dir, { recursive: true });
|
|
165
|
+
}
|
|
166
|
+
// Write file
|
|
167
|
+
writeFileSync(filePath, write.content, { encoding: 'utf-8' });
|
|
168
|
+
written.push(filePath);
|
|
169
|
+
console.log(`${LOG_PREFIX.DONE} ${EMOJI.SUCCESS} ${write.description}`);
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
const errMessage = err instanceof Error ? err.message : String(err);
|
|
173
|
+
failed.push({ path: filePath, error: errMessage });
|
|
174
|
+
console.error(`${LOG_PREFIX.DONE} ${EMOJI.FAILURE} ${write.description}: ${errMessage}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
this.committed = true;
|
|
178
|
+
this.pendingWrites.clear();
|
|
179
|
+
const success = failed.length === 0;
|
|
180
|
+
if (!success) {
|
|
181
|
+
console.error(`${LOG_PREFIX.DONE} ${EMOJI.WARNING} Transaction completed with ${failed.length} failures`);
|
|
182
|
+
}
|
|
183
|
+
return { success, written, failed };
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Abort transaction (discard pending writes)
|
|
187
|
+
*
|
|
188
|
+
* Since no writes have been made, this just clears pending changes.
|
|
189
|
+
* This is the key benefit of the transactional pattern.
|
|
190
|
+
*/
|
|
191
|
+
abort() {
|
|
192
|
+
if (this.committed) {
|
|
193
|
+
console.warn(`${LOG_PREFIX.DONE} ${EMOJI.WARNING} Aborting already-committed transaction`);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const count = this.pendingWrites.size;
|
|
197
|
+
this.pendingWrites.clear();
|
|
198
|
+
this.aborted = true;
|
|
199
|
+
console.log(`${LOG_PREFIX.DONE} ${EMOJI.WARNING} Transaction ABORTED - ${count} pending writes discarded`);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Get transaction state for debugging
|
|
203
|
+
*/
|
|
204
|
+
getState() {
|
|
205
|
+
return {
|
|
206
|
+
wuId: this.wuId,
|
|
207
|
+
committed: this.committed,
|
|
208
|
+
aborted: this.aborted,
|
|
209
|
+
pendingCount: this.pendingWrites.size,
|
|
210
|
+
files: Array.from(this.pendingWrites.keys()),
|
|
211
|
+
createdAt: this.createdAt.toISOString(),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Read file content for transaction (pre-compute backup)
|
|
217
|
+
*
|
|
218
|
+
* @param {string} filePath - File to read
|
|
219
|
+
* @returns {string|null} - File content or null if doesn't exist
|
|
220
|
+
*/
|
|
221
|
+
export function readFileForTransaction(filePath) {
|
|
222
|
+
if (!existsSync(filePath)) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
return readFileSync(filePath, { encoding: 'utf-8' });
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Create a transaction state snapshot for rollback
|
|
229
|
+
*
|
|
230
|
+
* Captures current file contents before any modifications.
|
|
231
|
+
* Used if git operations fail after transaction commit.
|
|
232
|
+
*
|
|
233
|
+
* @param {string[]} filePaths - Paths to snapshot
|
|
234
|
+
* @returns {Map<string, string|null>} - Map of path to content (null = didn't exist)
|
|
235
|
+
*/
|
|
236
|
+
export function createTransactionSnapshot(filePaths) {
|
|
237
|
+
const snapshot = new Map();
|
|
238
|
+
for (const filePath of filePaths) {
|
|
239
|
+
snapshot.set(filePath, readFileForTransaction(filePath));
|
|
240
|
+
}
|
|
241
|
+
return snapshot;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Restore files from snapshot (for rollback after commit)
|
|
245
|
+
*
|
|
246
|
+
* @param {Map<string, string|null>} snapshot - Snapshot from createTransactionSnapshot
|
|
247
|
+
* @returns {{ restored: string[], errors: { path: string, error: string }[] }}
|
|
248
|
+
*/
|
|
249
|
+
export function restoreFromSnapshot(snapshot) {
|
|
250
|
+
const restored = [];
|
|
251
|
+
const errors = [];
|
|
252
|
+
for (const [filePath, content] of snapshot) {
|
|
253
|
+
try {
|
|
254
|
+
if (content === null) {
|
|
255
|
+
// File didn't exist before - delete if it exists now
|
|
256
|
+
if (existsSync(filePath)) {
|
|
257
|
+
unlinkSync(filePath);
|
|
258
|
+
restored.push(filePath);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
// Restore original content
|
|
263
|
+
writeFileSync(filePath, content, { encoding: 'utf-8' });
|
|
264
|
+
restored.push(filePath);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
const errMessage = err instanceof Error ? err.message : String(err);
|
|
269
|
+
errors.push({ path: filePath, error: errMessage });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return { restored, errors };
|
|
273
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WU Validation Constants (WU-1243)
|
|
3
|
+
*
|
|
4
|
+
* Centralizes magic numbers for lane inference and incident validation.
|
|
5
|
+
* Extracted from lane-inference.mjs and agent-incidents.mjs for DRY compliance.
|
|
6
|
+
*
|
|
7
|
+
* @module wu-validation-constants
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Lane inference scoring weights.
|
|
11
|
+
* Code path matches are weighted higher than keywords because
|
|
12
|
+
* file paths are more reliable signals for lane classification.
|
|
13
|
+
*
|
|
14
|
+
* The 10:3 ratio (~3.3x) reflects that a code path match is approximately
|
|
15
|
+
* 3x more indicative of the correct lane than a keyword match.
|
|
16
|
+
*/
|
|
17
|
+
export declare const WEIGHTS: {
|
|
18
|
+
/** Weight for code path pattern matches (more reliable signal) */
|
|
19
|
+
CODE_PATH_MATCH: number;
|
|
20
|
+
/** Weight for keyword matches in description (less specific signal) */
|
|
21
|
+
KEYWORD_MATCH: number;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Confidence score configuration for lane inference.
|
|
25
|
+
*
|
|
26
|
+
* WU-2438: Changed from percentage-based (0-100) to absolute scoring.
|
|
27
|
+
* Raw scores (sum of WEIGHTS) are now returned directly.
|
|
28
|
+
* Higher score = better match, regardless of config size.
|
|
29
|
+
*/
|
|
30
|
+
export declare const CONFIDENCE: {
|
|
31
|
+
/** Minimum confidence value (no matches) */
|
|
32
|
+
MIN: number;
|
|
33
|
+
/** Maximum confidence value (legacy, kept for backward compatibility) */
|
|
34
|
+
MAX: number;
|
|
35
|
+
/**
|
|
36
|
+
* Minimum confidence threshold to return a suggestion.
|
|
37
|
+
* Set to 0 to always return best match (even low confidence).
|
|
38
|
+
* Note: With absolute scoring, this threshold is compared against raw scores.
|
|
39
|
+
*/
|
|
40
|
+
THRESHOLD: number;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* String length validation limits for incident logging.
|
|
44
|
+
* Prevents abuse while allowing meaningful content.
|
|
45
|
+
*/
|
|
46
|
+
export declare const VALIDATION_LIMITS: {
|
|
47
|
+
/** Minimum title length (prevents truncated/empty titles) */
|
|
48
|
+
TITLE_MIN: number;
|
|
49
|
+
/** Maximum title length (keeps logs readable) */
|
|
50
|
+
TITLE_MAX: number;
|
|
51
|
+
/** Minimum description length (prevents one-liners) */
|
|
52
|
+
DESCRIPTION_MIN: number;
|
|
53
|
+
/** Maximum description length (prevents unbounded logging) */
|
|
54
|
+
DESCRIPTION_MAX: number;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Valid incident categories for agent issue logging.
|
|
58
|
+
* Duplicated from agent-incidents.mjs z.enum for use in default arrays.
|
|
59
|
+
*/
|
|
60
|
+
export declare const INCIDENT_CATEGORIES: readonly ["workflow", "tooling", "confusion", "violation", "error"];
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WU Validation Constants (WU-1243)
|
|
3
|
+
*
|
|
4
|
+
* Centralizes magic numbers for lane inference and incident validation.
|
|
5
|
+
* Extracted from lane-inference.mjs and agent-incidents.mjs for DRY compliance.
|
|
6
|
+
*
|
|
7
|
+
* @module wu-validation-constants
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Lane inference scoring weights.
|
|
11
|
+
* Code path matches are weighted higher than keywords because
|
|
12
|
+
* file paths are more reliable signals for lane classification.
|
|
13
|
+
*
|
|
14
|
+
* The 10:3 ratio (~3.3x) reflects that a code path match is approximately
|
|
15
|
+
* 3x more indicative of the correct lane than a keyword match.
|
|
16
|
+
*/
|
|
17
|
+
export const WEIGHTS = {
|
|
18
|
+
/** Weight for code path pattern matches (more reliable signal) */
|
|
19
|
+
CODE_PATH_MATCH: 10,
|
|
20
|
+
/** Weight for keyword matches in description (less specific signal) */
|
|
21
|
+
KEYWORD_MATCH: 3,
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Confidence score configuration for lane inference.
|
|
25
|
+
*
|
|
26
|
+
* WU-2438: Changed from percentage-based (0-100) to absolute scoring.
|
|
27
|
+
* Raw scores (sum of WEIGHTS) are now returned directly.
|
|
28
|
+
* Higher score = better match, regardless of config size.
|
|
29
|
+
*/
|
|
30
|
+
export const CONFIDENCE = {
|
|
31
|
+
/** Minimum confidence value (no matches) */
|
|
32
|
+
MIN: 0,
|
|
33
|
+
/** Maximum confidence value (legacy, kept for backward compatibility) */
|
|
34
|
+
MAX: 100,
|
|
35
|
+
/**
|
|
36
|
+
* Minimum confidence threshold to return a suggestion.
|
|
37
|
+
* Set to 0 to always return best match (even low confidence).
|
|
38
|
+
* Note: With absolute scoring, this threshold is compared against raw scores.
|
|
39
|
+
*/
|
|
40
|
+
THRESHOLD: 0,
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* String length validation limits for incident logging.
|
|
44
|
+
* Prevents abuse while allowing meaningful content.
|
|
45
|
+
*/
|
|
46
|
+
export const VALIDATION_LIMITS = {
|
|
47
|
+
/** Minimum title length (prevents truncated/empty titles) */
|
|
48
|
+
TITLE_MIN: 5,
|
|
49
|
+
/** Maximum title length (keeps logs readable) */
|
|
50
|
+
TITLE_MAX: 100,
|
|
51
|
+
/** Minimum description length (prevents one-liners) */
|
|
52
|
+
DESCRIPTION_MIN: 10,
|
|
53
|
+
/** Maximum description length (prevents unbounded logging) */
|
|
54
|
+
DESCRIPTION_MAX: 2000,
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Valid incident categories for agent issue logging.
|
|
58
|
+
* Duplicated from agent-incidents.mjs z.enum for use in default arrays.
|
|
59
|
+
*/
|
|
60
|
+
export const INCIDENT_CATEGORIES = [
|
|
61
|
+
'workflow',
|
|
62
|
+
'tooling',
|
|
63
|
+
'confusion',
|
|
64
|
+
'violation',
|
|
65
|
+
'error',
|
|
66
|
+
];
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WU Exposure Validation (WU-1999, WU-2022)
|
|
3
|
+
*
|
|
4
|
+
* WU-1999: Validates exposure field and UI pairing for wu:done.
|
|
5
|
+
* Provides warnings (not errors) to guide completion without blocking.
|
|
6
|
+
*
|
|
7
|
+
* WU-2022: Adds BLOCKING validation for feature accessibility.
|
|
8
|
+
* When exposure=ui, ensures the feature is actually accessible via navigation.
|
|
9
|
+
*
|
|
10
|
+
* Part of INIT-031 Phase 4: Prevent backend-without-UI pattern.
|
|
11
|
+
*
|
|
12
|
+
* @see {@link tools/wu-done.mjs} - Consumer
|
|
13
|
+
* @see {@link tools/lib/wu-schema.mjs} - WU schema with exposure field
|
|
14
|
+
* @see {@link tools/lib/wu-constants.mjs} - WU_EXPOSURE values
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Warning message templates with remediation guidance.
|
|
18
|
+
* All messages include the WU ID for context.
|
|
19
|
+
*/
|
|
20
|
+
export declare const EXPOSURE_WARNING_MESSAGES: {
|
|
21
|
+
/**
|
|
22
|
+
* Warning when exposure field is missing entirely.
|
|
23
|
+
* @param {string} wuId - The WU identifier
|
|
24
|
+
* @returns {string} Warning message with remediation
|
|
25
|
+
*/
|
|
26
|
+
MISSING_EXPOSURE: (wuId: any) => string;
|
|
27
|
+
/**
|
|
28
|
+
* Warning when API exposure lacks UI pairing WUs.
|
|
29
|
+
* @param {string} wuId - The WU identifier
|
|
30
|
+
* @returns {string} Warning message with remediation
|
|
31
|
+
*/
|
|
32
|
+
MISSING_UI_PAIRING: (wuId: any) => string;
|
|
33
|
+
/**
|
|
34
|
+
* Warning when API exposure lacks UI verification in acceptance criteria.
|
|
35
|
+
* @param {string} wuId - The WU identifier
|
|
36
|
+
* @returns {string} Warning message with remediation
|
|
37
|
+
*/
|
|
38
|
+
MISSING_UI_VERIFICATION: (wuId: any) => string;
|
|
39
|
+
/**
|
|
40
|
+
* Recommendation for user_journey when exposure is UI.
|
|
41
|
+
* @param {string} wuId - The WU identifier
|
|
42
|
+
* @returns {string} Warning message with remediation
|
|
43
|
+
*/
|
|
44
|
+
MISSING_USER_JOURNEY: (wuId: any) => string;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Validate exposure field and UI pairing for a WU.
|
|
48
|
+
*
|
|
49
|
+
* This is a non-blocking validation that returns warnings, not errors.
|
|
50
|
+
* Use during wu:done to guide completion without preventing it.
|
|
51
|
+
*
|
|
52
|
+
* Checks:
|
|
53
|
+
* 1. exposure field is present (warns if missing)
|
|
54
|
+
* 2. If exposure=api, warns if no ui_pairing_wus specified
|
|
55
|
+
* 3. If exposure=api, checks acceptance criteria for UI verification mention
|
|
56
|
+
* 4. If exposure=ui, recommends user_journey field if not present
|
|
57
|
+
*
|
|
58
|
+
* @param {object} wu - WU YAML object
|
|
59
|
+
* @param {string} wu.id - WU identifier
|
|
60
|
+
* @param {string} [wu.exposure] - Exposure type (ui, api, backend-only, documentation)
|
|
61
|
+
* @param {string[]} [wu.ui_pairing_wus] - Related UI WU IDs for API exposure
|
|
62
|
+
* @param {string} [wu.user_journey] - User journey description for UI exposure
|
|
63
|
+
* @param {string[]|object} [wu.acceptance] - Acceptance criteria
|
|
64
|
+
* @param {ValidateExposureOptions} [options] - Validation options
|
|
65
|
+
* @returns {{valid: boolean, warnings: string[]}} Validation result
|
|
66
|
+
*/
|
|
67
|
+
interface ValidateExposureOptions {
|
|
68
|
+
/** Skip all exposure validation */
|
|
69
|
+
skipExposureCheck?: boolean;
|
|
70
|
+
}
|
|
71
|
+
export declare function validateExposure(wu: any, options?: ValidateExposureOptions): {
|
|
72
|
+
valid: boolean;
|
|
73
|
+
warnings: any[];
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Error message templates for accessibility validation (WU-2022).
|
|
77
|
+
* These are BLOCKING errors, not warnings.
|
|
78
|
+
*/
|
|
79
|
+
export declare const ACCESSIBILITY_ERROR_MESSAGES: {
|
|
80
|
+
/**
|
|
81
|
+
* Error when UI exposure lacks navigation accessibility proof.
|
|
82
|
+
* @param {string} wuId - The WU identifier
|
|
83
|
+
* @returns {string} Error message with remediation guidance
|
|
84
|
+
*/
|
|
85
|
+
UI_NOT_ACCESSIBLE: (wuId: any) => string;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Validate feature accessibility for UI-exposed WUs (WU-2022).
|
|
89
|
+
*
|
|
90
|
+
* This is a BLOCKING validation that returns errors (not warnings).
|
|
91
|
+
* When exposure=ui, the feature must be verifiably accessible.
|
|
92
|
+
*
|
|
93
|
+
* Accessibility is verified by ANY of:
|
|
94
|
+
* 1. navigation_path field is specified (explicit route)
|
|
95
|
+
* 2. code_paths includes a page.tsx file (Next.js page)
|
|
96
|
+
* 3. tests.manual includes navigation/accessibility verification
|
|
97
|
+
*
|
|
98
|
+
* Non-UI exposures (api, backend-only, documentation) pass automatically.
|
|
99
|
+
* Missing exposure field passes (legacy WUs, handled by WU-1999 warning).
|
|
100
|
+
*
|
|
101
|
+
* @param {object} wu - WU YAML object
|
|
102
|
+
* @param {string} wu.id - WU identifier
|
|
103
|
+
* @param {string} [wu.exposure] - Exposure type (ui, api, backend-only, documentation)
|
|
104
|
+
* @param {string} [wu.navigation_path] - Route where UI is accessible
|
|
105
|
+
* @param {string[]} [wu.code_paths] - Files modified by this WU
|
|
106
|
+
* @param {object} [wu.tests] - Test specifications
|
|
107
|
+
* @param {ValidateFeatureAccessibilityOptions} [options] - Validation options
|
|
108
|
+
* @returns {{valid: boolean, errors: string[]}} Validation result
|
|
109
|
+
*/
|
|
110
|
+
interface ValidateFeatureAccessibilityOptions {
|
|
111
|
+
/** Skip all accessibility validation */
|
|
112
|
+
skipAccessibilityCheck?: boolean;
|
|
113
|
+
}
|
|
114
|
+
export declare function validateFeatureAccessibility(wu: any, options?: ValidateFeatureAccessibilityOptions): {
|
|
115
|
+
valid: boolean;
|
|
116
|
+
errors: any[];
|
|
117
|
+
};
|
|
118
|
+
export {};
|