@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,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Rollback Utilities for WU Tooling
|
|
4
|
+
*
|
|
5
|
+
* WU-1255: Per-file error tracking for robust rollback operations.
|
|
6
|
+
* Ensures all files are attempted even if some fail, with clear error reporting.
|
|
7
|
+
*
|
|
8
|
+
* @see {@link tools/wu-done.mjs} - Consumer (rollbackTransaction function)
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Error entry for failed file restoration
|
|
12
|
+
*/
|
|
13
|
+
interface RollbackError {
|
|
14
|
+
name: string;
|
|
15
|
+
path: string;
|
|
16
|
+
error: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Result of a rollback operation.
|
|
20
|
+
* Tracks which files were restored and which failed.
|
|
21
|
+
*
|
|
22
|
+
* @class
|
|
23
|
+
*/
|
|
24
|
+
export declare class RollbackResult {
|
|
25
|
+
/** Names of successfully restored files */
|
|
26
|
+
restored: string[];
|
|
27
|
+
/** Failed file restorations */
|
|
28
|
+
errors: RollbackError[];
|
|
29
|
+
constructor();
|
|
30
|
+
/**
|
|
31
|
+
* Record a successful file restoration.
|
|
32
|
+
* @param {string} name - File identifier (e.g., 'backlog.md')
|
|
33
|
+
*/
|
|
34
|
+
addSuccess(name: any): void;
|
|
35
|
+
/**
|
|
36
|
+
* Record a failed file restoration.
|
|
37
|
+
* @param {string} name - File identifier
|
|
38
|
+
* @param {string} path - Full file path
|
|
39
|
+
* @param {string} error - Error message
|
|
40
|
+
*/
|
|
41
|
+
addError(name: any, path: any, error: any): void;
|
|
42
|
+
/**
|
|
43
|
+
* Check if all files were restored successfully.
|
|
44
|
+
* @returns {boolean} True if no errors occurred
|
|
45
|
+
*/
|
|
46
|
+
get success(): boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Restore multiple files with per-file error tracking.
|
|
50
|
+
*
|
|
51
|
+
* Each file is restored independently - if one fails, subsequent files
|
|
52
|
+
* are still attempted. This ensures maximum recovery even in partial
|
|
53
|
+
* failure scenarios.
|
|
54
|
+
*
|
|
55
|
+
* @param {Array<{name: string, path: string, content: string}>} filesToRestore - Files to restore
|
|
56
|
+
* @returns {RollbackResult} Result with restored files and any errors
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* const result = rollbackFiles([
|
|
60
|
+
* { name: 'backlog.md', path: '/path/to/backlog.md', content: 'original content' },
|
|
61
|
+
* { name: 'status.md', path: '/path/to/status.md', content: 'original content' },
|
|
62
|
+
* ]);
|
|
63
|
+
*
|
|
64
|
+
* if (!result.success) {
|
|
65
|
+
* console.error('Rollback had errors:', result.errors);
|
|
66
|
+
* }
|
|
67
|
+
*/
|
|
68
|
+
export declare function rollbackFiles(filesToRestore: any): RollbackResult;
|
|
69
|
+
/**
|
|
70
|
+
* Delete multiple files with per-file error tracking.
|
|
71
|
+
*
|
|
72
|
+
* @param {Array<{name: string, path: string}>} filesToDelete - Files to delete
|
|
73
|
+
* @returns {RollbackResult} Result with deleted files and any errors
|
|
74
|
+
*/
|
|
75
|
+
export declare function deleteFiles(filesToDelete: any): RollbackResult;
|
|
76
|
+
export {};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Rollback Utilities for WU Tooling
|
|
4
|
+
*
|
|
5
|
+
* WU-1255: Per-file error tracking for robust rollback operations.
|
|
6
|
+
* Ensures all files are attempted even if some fail, with clear error reporting.
|
|
7
|
+
*
|
|
8
|
+
* @see {@link tools/wu-done.mjs} - Consumer (rollbackTransaction function)
|
|
9
|
+
*/
|
|
10
|
+
/* eslint-disable security/detect-non-literal-fs-filename */
|
|
11
|
+
import { writeFileSync, unlinkSync } from 'node:fs';
|
|
12
|
+
/**
|
|
13
|
+
* Result of a rollback operation.
|
|
14
|
+
* Tracks which files were restored and which failed.
|
|
15
|
+
*
|
|
16
|
+
* @class
|
|
17
|
+
*/
|
|
18
|
+
export class RollbackResult {
|
|
19
|
+
/** Names of successfully restored files */
|
|
20
|
+
restored;
|
|
21
|
+
/** Failed file restorations */
|
|
22
|
+
errors;
|
|
23
|
+
constructor() {
|
|
24
|
+
this.restored = [];
|
|
25
|
+
this.errors = [];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Record a successful file restoration.
|
|
29
|
+
* @param {string} name - File identifier (e.g., 'backlog.md')
|
|
30
|
+
*/
|
|
31
|
+
addSuccess(name) {
|
|
32
|
+
this.restored.push(name);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Record a failed file restoration.
|
|
36
|
+
* @param {string} name - File identifier
|
|
37
|
+
* @param {string} path - Full file path
|
|
38
|
+
* @param {string} error - Error message
|
|
39
|
+
*/
|
|
40
|
+
addError(name, path, error) {
|
|
41
|
+
this.errors.push({ name, path, error });
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check if all files were restored successfully.
|
|
45
|
+
* @returns {boolean} True if no errors occurred
|
|
46
|
+
*/
|
|
47
|
+
get success() {
|
|
48
|
+
return this.errors.length === 0;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Restore multiple files with per-file error tracking.
|
|
53
|
+
*
|
|
54
|
+
* Each file is restored independently - if one fails, subsequent files
|
|
55
|
+
* are still attempted. This ensures maximum recovery even in partial
|
|
56
|
+
* failure scenarios.
|
|
57
|
+
*
|
|
58
|
+
* @param {Array<{name: string, path: string, content: string}>} filesToRestore - Files to restore
|
|
59
|
+
* @returns {RollbackResult} Result with restored files and any errors
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* const result = rollbackFiles([
|
|
63
|
+
* { name: 'backlog.md', path: '/path/to/backlog.md', content: 'original content' },
|
|
64
|
+
* { name: 'status.md', path: '/path/to/status.md', content: 'original content' },
|
|
65
|
+
* ]);
|
|
66
|
+
*
|
|
67
|
+
* if (!result.success) {
|
|
68
|
+
* console.error('Rollback had errors:', result.errors);
|
|
69
|
+
* }
|
|
70
|
+
*/
|
|
71
|
+
export function rollbackFiles(filesToRestore) {
|
|
72
|
+
const result = new RollbackResult();
|
|
73
|
+
for (const file of filesToRestore) {
|
|
74
|
+
try {
|
|
75
|
+
writeFileSync(file.path, file.content, { encoding: 'utf-8' });
|
|
76
|
+
result.addSuccess(file.name);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
80
|
+
result.addError(file.name, file.path, message);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Delete multiple files with per-file error tracking.
|
|
87
|
+
*
|
|
88
|
+
* @param {Array<{name: string, path: string}>} filesToDelete - Files to delete
|
|
89
|
+
* @returns {RollbackResult} Result with deleted files and any errors
|
|
90
|
+
*/
|
|
91
|
+
export function deleteFiles(filesToDelete) {
|
|
92
|
+
const result = new RollbackResult();
|
|
93
|
+
for (const file of filesToDelete) {
|
|
94
|
+
try {
|
|
95
|
+
unlinkSync(file.path);
|
|
96
|
+
result.addSuccess(file.name);
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
100
|
+
result.addError(file.name, file.path, message);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Section Headings Constants
|
|
3
|
+
*
|
|
4
|
+
* Centralized section heading defaults for backlog.md and status.md
|
|
5
|
+
* Eliminates magic strings scattered throughout wu-* tools
|
|
6
|
+
*
|
|
7
|
+
* Usage: Use getSectionHeadingsWithDefaults() to get frontmatter-configured
|
|
8
|
+
* headings with sensible fallbacks if frontmatter is missing/malformed
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Default section headings (fallbacks when frontmatter is missing)
|
|
12
|
+
* Re-exports from wu-constants.mjs for backwards compatibility
|
|
13
|
+
*/
|
|
14
|
+
export declare const DEFAULT_SECTION_HEADINGS: {
|
|
15
|
+
backlog: {
|
|
16
|
+
ready: string;
|
|
17
|
+
in_progress: string;
|
|
18
|
+
blocked: string;
|
|
19
|
+
done: string;
|
|
20
|
+
};
|
|
21
|
+
status: {
|
|
22
|
+
in_progress: string;
|
|
23
|
+
completed: string;
|
|
24
|
+
blocked: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Get section headings with frontmatter override + defaults
|
|
29
|
+
*
|
|
30
|
+
* Replaces scattered pattern: headings.done || '## ✅ Done'
|
|
31
|
+
* Centralizes fallback logic for consistent heading resolution
|
|
32
|
+
*
|
|
33
|
+
* @param {object|null} frontmatter - Parsed frontmatter from backlog.md/status.md
|
|
34
|
+
* @param {'backlog'|'status'} docType - Document type
|
|
35
|
+
* @returns {object} Section headings (configured or default)
|
|
36
|
+
*/
|
|
37
|
+
export declare function getSectionHeadingsWithDefaults(frontmatter: any, docType?: string): {
|
|
38
|
+
ready: any;
|
|
39
|
+
in_progress: any;
|
|
40
|
+
blocked: any;
|
|
41
|
+
done: any;
|
|
42
|
+
completed: any;
|
|
43
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Section Headings Constants
|
|
3
|
+
*
|
|
4
|
+
* Centralized section heading defaults for backlog.md and status.md
|
|
5
|
+
* Eliminates magic strings scattered throughout wu-* tools
|
|
6
|
+
*
|
|
7
|
+
* Usage: Use getSectionHeadingsWithDefaults() to get frontmatter-configured
|
|
8
|
+
* headings with sensible fallbacks if frontmatter is missing/malformed
|
|
9
|
+
*/
|
|
10
|
+
import { getSectionHeadings } from './backlog-parser.js';
|
|
11
|
+
import { BACKLOG_SECTIONS, STATUS_SECTIONS } from './wu-constants.js';
|
|
12
|
+
/**
|
|
13
|
+
* Default section headings (fallbacks when frontmatter is missing)
|
|
14
|
+
* Re-exports from wu-constants.mjs for backwards compatibility
|
|
15
|
+
*/
|
|
16
|
+
export const DEFAULT_SECTION_HEADINGS = {
|
|
17
|
+
backlog: {
|
|
18
|
+
ready: BACKLOG_SECTIONS.READY,
|
|
19
|
+
in_progress: BACKLOG_SECTIONS.IN_PROGRESS,
|
|
20
|
+
blocked: BACKLOG_SECTIONS.BLOCKED,
|
|
21
|
+
done: BACKLOG_SECTIONS.DONE,
|
|
22
|
+
},
|
|
23
|
+
status: {
|
|
24
|
+
in_progress: STATUS_SECTIONS.IN_PROGRESS,
|
|
25
|
+
completed: STATUS_SECTIONS.COMPLETED,
|
|
26
|
+
blocked: STATUS_SECTIONS.BLOCKED,
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Get section headings with frontmatter override + defaults
|
|
31
|
+
*
|
|
32
|
+
* Replaces scattered pattern: headings.done || '## ✅ Done'
|
|
33
|
+
* Centralizes fallback logic for consistent heading resolution
|
|
34
|
+
*
|
|
35
|
+
* @param {object|null} frontmatter - Parsed frontmatter from backlog.md/status.md
|
|
36
|
+
* @param {'backlog'|'status'} docType - Document type
|
|
37
|
+
* @returns {object} Section headings (configured or default)
|
|
38
|
+
*/
|
|
39
|
+
export function getSectionHeadingsWithDefaults(frontmatter, docType = 'backlog') {
|
|
40
|
+
const defaults = DEFAULT_SECTION_HEADINGS[docType];
|
|
41
|
+
const configured = frontmatter ? getSectionHeadings(frontmatter) : {};
|
|
42
|
+
return {
|
|
43
|
+
ready: configured.ready || defaults.ready,
|
|
44
|
+
in_progress: configured.in_progress || defaults.in_progress,
|
|
45
|
+
blocked: configured.blocked || defaults.blocked,
|
|
46
|
+
done: configured.done || defaults.done,
|
|
47
|
+
completed: configured.completed || defaults.completed,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spawn Escalation Module (WU-1952, WU-1967)
|
|
3
|
+
*
|
|
4
|
+
* WU-1967: Replaced Bug WU creation with memory bus signalling.
|
|
5
|
+
* Signals orchestrator inbox instead of creating human-in-loop Bug WUs.
|
|
6
|
+
*
|
|
7
|
+
* Escalation Flow:
|
|
8
|
+
* 1. recoverStuckSpawn() returns { recovered: false, action: ESCALATED_STUCK }
|
|
9
|
+
* 2. escalateStuckSpawn() signals orchestrator via memory bus
|
|
10
|
+
* 3. Spawn status updated to ESCALATED (prevents duplicate signals)
|
|
11
|
+
* 4. Orchestrator decides: retry (1st), block (2nd), human escalate (3rd+)
|
|
12
|
+
*
|
|
13
|
+
* Library-First Note: This is project-specific spawn escalation code for
|
|
14
|
+
* PatientPath's custom spawn-registry.jsonl and memory bus patterns.
|
|
15
|
+
* No external library exists for this domain-specific agent lifecycle management.
|
|
16
|
+
*
|
|
17
|
+
* @see {@link tools/lib/__tests__/spawn-escalation.test.mjs} - Tests
|
|
18
|
+
* @see {@link tools/lib/spawn-recovery.mjs} - Recovery logic
|
|
19
|
+
* @see {@link tools/lib/mem-signal-core.mjs} - Signal creation
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Signal type for spawn failures
|
|
23
|
+
*/
|
|
24
|
+
export declare const SPAWN_FAILURE_SIGNAL_TYPE = "spawn_failure";
|
|
25
|
+
/**
|
|
26
|
+
* Severity levels for spawn failure signals
|
|
27
|
+
*/
|
|
28
|
+
export declare const SignalSeverity: Readonly<{
|
|
29
|
+
WARNING: "warning";
|
|
30
|
+
ERROR: "error";
|
|
31
|
+
CRITICAL: "critical";
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Suggested actions for spawn failure signals
|
|
35
|
+
*/
|
|
36
|
+
export declare const SuggestedAction: Readonly<{
|
|
37
|
+
RETRY: "retry";
|
|
38
|
+
BLOCK: "block";
|
|
39
|
+
HUMAN_ESCALATE: "human_escalate";
|
|
40
|
+
}>;
|
|
41
|
+
/**
|
|
42
|
+
* Escalates a stuck spawn by signalling the orchestrator.
|
|
43
|
+
*
|
|
44
|
+
* WU-1967: Replaced Bug WU creation with memory bus signalling.
|
|
45
|
+
* Called when recoverStuckSpawn() returns ESCALATED_STUCK.
|
|
46
|
+
* Signals orchestrator inbox with spawn failure context.
|
|
47
|
+
*
|
|
48
|
+
* Escalation levels based on recovery attempts:
|
|
49
|
+
* - 1st attempt: severity=warning, suggested_action=retry
|
|
50
|
+
* - 2nd attempt: severity=error, suggested_action=block
|
|
51
|
+
* - 3rd+ attempt: severity=critical, suggested_action=human_escalate
|
|
52
|
+
*
|
|
53
|
+
* @param {string} spawnId - ID of the stuck spawn
|
|
54
|
+
* @param {Object} options - Options
|
|
55
|
+
* @param {string} options.baseDir - Base directory for .beacon/
|
|
56
|
+
* @param {boolean} [options.dryRun=false] - If true, returns signal without sending
|
|
57
|
+
* @returns {Promise<EscalationResult>} Escalation result with signal details
|
|
58
|
+
*
|
|
59
|
+
* @throws {Error} If spawn not found
|
|
60
|
+
* @throws {Error} If spawn already escalated (duplicate prevention)
|
|
61
|
+
* @throws {Error} If no escalation audit log exists
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* // After recoverStuckSpawn returns ESCALATED_STUCK
|
|
65
|
+
* const result = await escalateStuckSpawn('spawn-1234', { baseDir: '/path/to/project' });
|
|
66
|
+
* console.log(`Signal sent: ${result.signalId}, action: ${result.signal.suggested_action}`);
|
|
67
|
+
*/
|
|
68
|
+
export interface EscalateStuckSpawnOptions {
|
|
69
|
+
/** Base directory for .beacon/ */
|
|
70
|
+
baseDir?: string;
|
|
71
|
+
/** If true, return spec only without sending signal */
|
|
72
|
+
dryRun?: boolean;
|
|
73
|
+
}
|
|
74
|
+
export declare function escalateStuckSpawn(spawnId: any, options?: EscalateStuckSpawnOptions): Promise<{
|
|
75
|
+
signalId: string;
|
|
76
|
+
signal: {
|
|
77
|
+
type: string;
|
|
78
|
+
severity: "error" | "warning" | "critical";
|
|
79
|
+
spawn_id: any;
|
|
80
|
+
target_wu_id: any;
|
|
81
|
+
parent_wu_id: any;
|
|
82
|
+
lane: any;
|
|
83
|
+
recovery_action: any;
|
|
84
|
+
recovery_attempts: any;
|
|
85
|
+
last_checkpoint: any;
|
|
86
|
+
suggested_action: "retry" | "block" | "human_escalate";
|
|
87
|
+
message: string;
|
|
88
|
+
};
|
|
89
|
+
spawnStatus: "escalated";
|
|
90
|
+
}>;
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spawn Escalation Module (WU-1952, WU-1967)
|
|
3
|
+
*
|
|
4
|
+
* WU-1967: Replaced Bug WU creation with memory bus signalling.
|
|
5
|
+
* Signals orchestrator inbox instead of creating human-in-loop Bug WUs.
|
|
6
|
+
*
|
|
7
|
+
* Escalation Flow:
|
|
8
|
+
* 1. recoverStuckSpawn() returns { recovered: false, action: ESCALATED_STUCK }
|
|
9
|
+
* 2. escalateStuckSpawn() signals orchestrator via memory bus
|
|
10
|
+
* 3. Spawn status updated to ESCALATED (prevents duplicate signals)
|
|
11
|
+
* 4. Orchestrator decides: retry (1st), block (2nd), human escalate (3rd+)
|
|
12
|
+
*
|
|
13
|
+
* Library-First Note: This is project-specific spawn escalation code for
|
|
14
|
+
* PatientPath's custom spawn-registry.jsonl and memory bus patterns.
|
|
15
|
+
* No external library exists for this domain-specific agent lifecycle management.
|
|
16
|
+
*
|
|
17
|
+
* @see {@link tools/lib/__tests__/spawn-escalation.test.mjs} - Tests
|
|
18
|
+
* @see {@link tools/lib/spawn-recovery.mjs} - Recovery logic
|
|
19
|
+
* @see {@link tools/lib/mem-signal-core.mjs} - Signal creation
|
|
20
|
+
*/
|
|
21
|
+
import fs from 'node:fs/promises';
|
|
22
|
+
import path from 'node:path';
|
|
23
|
+
import { SpawnRegistryStore } from './spawn-registry-store.js';
|
|
24
|
+
import { SpawnStatus } from './spawn-registry-schema.js';
|
|
25
|
+
import { RECOVERY_DIR_NAME } from './spawn-recovery.js';
|
|
26
|
+
let createSignal = null;
|
|
27
|
+
try {
|
|
28
|
+
const mod = await import('@lumenflow/memory/signal');
|
|
29
|
+
createSignal = mod.createSignal;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// @lumenflow/memory not available - signal features disabled
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Log prefix for spawn-escalation messages
|
|
36
|
+
*/
|
|
37
|
+
const LOG_PREFIX = '[spawn-escalation]';
|
|
38
|
+
/**
|
|
39
|
+
* Signal type for spawn failures
|
|
40
|
+
*/
|
|
41
|
+
export const SPAWN_FAILURE_SIGNAL_TYPE = 'spawn_failure';
|
|
42
|
+
/**
|
|
43
|
+
* Severity levels for spawn failure signals
|
|
44
|
+
*/
|
|
45
|
+
export const SignalSeverity = Object.freeze({
|
|
46
|
+
WARNING: 'warning',
|
|
47
|
+
ERROR: 'error',
|
|
48
|
+
CRITICAL: 'critical',
|
|
49
|
+
});
|
|
50
|
+
/**
|
|
51
|
+
* Suggested actions for spawn failure signals
|
|
52
|
+
*/
|
|
53
|
+
export const SuggestedAction = Object.freeze({
|
|
54
|
+
RETRY: 'retry',
|
|
55
|
+
BLOCK: 'block',
|
|
56
|
+
HUMAN_ESCALATE: 'human_escalate',
|
|
57
|
+
});
|
|
58
|
+
/**
|
|
59
|
+
* @typedef {Object} SpawnFailureSignal
|
|
60
|
+
* @property {string} type - Always 'spawn_failure'
|
|
61
|
+
* @property {string} severity - 'warning' | 'error' | 'critical'
|
|
62
|
+
* @property {string} spawn_id - Spawn ID
|
|
63
|
+
* @property {string} target_wu_id - Target WU ID
|
|
64
|
+
* @property {string} parent_wu_id - Parent WU ID (orchestrator)
|
|
65
|
+
* @property {string} lane - Lane name
|
|
66
|
+
* @property {string} recovery_action - Recovery action that triggered escalation
|
|
67
|
+
* @property {number} recovery_attempts - Number of recovery attempts
|
|
68
|
+
* @property {string|null} last_checkpoint - Last checkpoint timestamp
|
|
69
|
+
* @property {string} suggested_action - 'retry' | 'block' | 'human_escalate'
|
|
70
|
+
* @property {string} message - Human-readable message
|
|
71
|
+
*/
|
|
72
|
+
/**
|
|
73
|
+
* @typedef {Object} EscalationResult
|
|
74
|
+
* @property {string} signalId - Signal ID (e.g., 'sig-abc12345')
|
|
75
|
+
* @property {SpawnFailureSignal} signal - The signal payload
|
|
76
|
+
* @property {string} spawnStatus - Updated spawn status (ESCALATED)
|
|
77
|
+
*/
|
|
78
|
+
/**
|
|
79
|
+
* @typedef {Object} AuditLogEntry
|
|
80
|
+
* @property {string} timestamp - ISO timestamp of recovery action
|
|
81
|
+
* @property {string} spawnId - ID of the spawn being recovered
|
|
82
|
+
* @property {string} action - Recovery action taken
|
|
83
|
+
* @property {string} reason - Explanation of why action was taken
|
|
84
|
+
* @property {Object} context - Additional context
|
|
85
|
+
*/
|
|
86
|
+
/**
|
|
87
|
+
* Counts existing escalation attempts for a spawn by reading audit logs.
|
|
88
|
+
*
|
|
89
|
+
* @param {string} baseDir - Base directory
|
|
90
|
+
* @param {string} spawnId - Spawn ID to count attempts for
|
|
91
|
+
* @returns {Promise<number>} Number of previous escalation attempts
|
|
92
|
+
*/
|
|
93
|
+
async function countEscalationAttempts(baseDir, spawnId) {
|
|
94
|
+
const recoveryDir = path.join(baseDir, '.beacon', RECOVERY_DIR_NAME);
|
|
95
|
+
try {
|
|
96
|
+
const files = await fs.readdir(recoveryDir);
|
|
97
|
+
const spawnFiles = files.filter((f) => f.startsWith(`${spawnId}-`) && f.endsWith('.json'));
|
|
98
|
+
return spawnFiles.length;
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
if (error.code === 'ENOENT') {
|
|
102
|
+
return 0;
|
|
103
|
+
}
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Determines severity and suggested action based on recovery attempts.
|
|
109
|
+
*
|
|
110
|
+
* @param {number} attempts - Number of recovery attempts
|
|
111
|
+
* @returns {{ severity: string, suggestedAction: string }}
|
|
112
|
+
*/
|
|
113
|
+
function determineEscalationLevel(attempts) {
|
|
114
|
+
if (attempts <= 1) {
|
|
115
|
+
return {
|
|
116
|
+
severity: SignalSeverity.WARNING,
|
|
117
|
+
suggestedAction: SuggestedAction.RETRY,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
else if (attempts === 2) {
|
|
121
|
+
return {
|
|
122
|
+
severity: SignalSeverity.ERROR,
|
|
123
|
+
suggestedAction: SuggestedAction.BLOCK,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
return {
|
|
128
|
+
severity: SignalSeverity.CRITICAL,
|
|
129
|
+
suggestedAction: SuggestedAction.HUMAN_ESCALATE,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Find the most recent escalation audit log for a spawn.
|
|
135
|
+
*
|
|
136
|
+
* @param {string} baseDir - Base directory
|
|
137
|
+
* @param {string} spawnId - Spawn ID to find audit log for
|
|
138
|
+
* @returns {Promise<AuditLogEntry|null>} Audit log entry or null if not found
|
|
139
|
+
*/
|
|
140
|
+
async function findEscalationAuditLog(baseDir, spawnId) {
|
|
141
|
+
const recoveryDir = path.join(baseDir, '.beacon', RECOVERY_DIR_NAME);
|
|
142
|
+
try {
|
|
143
|
+
const files = await fs.readdir(recoveryDir);
|
|
144
|
+
// Filter files for this spawn ID, sorted by name (timestamp-based)
|
|
145
|
+
const spawnFiles = files
|
|
146
|
+
.filter((f) => f.startsWith(`${spawnId}-`) && f.endsWith('.json'))
|
|
147
|
+
.sort()
|
|
148
|
+
.reverse(); // Most recent first
|
|
149
|
+
if (spawnFiles.length === 0) {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
// Read the most recent audit log
|
|
153
|
+
const auditPath = path.join(recoveryDir, spawnFiles[0]);
|
|
154
|
+
const content = await fs.readFile(auditPath, 'utf-8');
|
|
155
|
+
return JSON.parse(content);
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
if (error.code === 'ENOENT') {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Builds a spawn failure signal payload.
|
|
166
|
+
*
|
|
167
|
+
* @param {Object} spawn - Spawn event data
|
|
168
|
+
* @param {AuditLogEntry} auditLog - Escalation audit log
|
|
169
|
+
* @param {number} attempts - Number of recovery attempts
|
|
170
|
+
* @returns {SpawnFailureSignal} Signal payload
|
|
171
|
+
*/
|
|
172
|
+
function buildSpawnFailureSignal(spawn, auditLog, attempts) {
|
|
173
|
+
const { severity, suggestedAction } = determineEscalationLevel(attempts);
|
|
174
|
+
const lastCheckpoint = auditLog.context.lastCheckpoint || null;
|
|
175
|
+
return {
|
|
176
|
+
type: SPAWN_FAILURE_SIGNAL_TYPE,
|
|
177
|
+
severity,
|
|
178
|
+
spawn_id: spawn.id,
|
|
179
|
+
target_wu_id: spawn.targetWuId,
|
|
180
|
+
parent_wu_id: spawn.parentWuId,
|
|
181
|
+
lane: spawn.lane,
|
|
182
|
+
recovery_action: auditLog.action,
|
|
183
|
+
recovery_attempts: attempts,
|
|
184
|
+
last_checkpoint: lastCheckpoint,
|
|
185
|
+
suggested_action: suggestedAction,
|
|
186
|
+
message: `Spawn ${spawn.id} for ${spawn.targetWuId} stuck: ${auditLog.reason}`,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
export async function escalateStuckSpawn(spawnId, options = {}) {
|
|
190
|
+
const { baseDir = process.cwd(), dryRun = false } = options;
|
|
191
|
+
const registryDir = path.join(baseDir, '.beacon', 'state');
|
|
192
|
+
// Load spawn registry
|
|
193
|
+
const store = new SpawnRegistryStore(registryDir);
|
|
194
|
+
try {
|
|
195
|
+
await store.load();
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
throw new Error(`Spawn ${spawnId} not found: registry unavailable`);
|
|
199
|
+
}
|
|
200
|
+
// Find the spawn
|
|
201
|
+
const spawn = store.getById(spawnId);
|
|
202
|
+
if (!spawn) {
|
|
203
|
+
throw new Error(`Spawn ${spawnId} not found in registry`);
|
|
204
|
+
}
|
|
205
|
+
// Check if signal module is available
|
|
206
|
+
if (!createSignal) {
|
|
207
|
+
throw new Error('Signal module (@lumenflow/memory) not available - cannot escalate');
|
|
208
|
+
}
|
|
209
|
+
// WU-1967: Check if already escalated (prevents duplicate signals)
|
|
210
|
+
if (spawn.status === SpawnStatus.ESCALATED) {
|
|
211
|
+
throw new Error(`Spawn ${spawnId} already escalated`);
|
|
212
|
+
}
|
|
213
|
+
// Find escalation audit log
|
|
214
|
+
const auditLog = await findEscalationAuditLog(baseDir, spawnId);
|
|
215
|
+
if (!auditLog) {
|
|
216
|
+
throw new Error(`No escalation audit log found for spawn ${spawnId}`);
|
|
217
|
+
}
|
|
218
|
+
// Count previous escalation attempts
|
|
219
|
+
const attempts = await countEscalationAttempts(baseDir, spawnId);
|
|
220
|
+
// Build signal payload
|
|
221
|
+
const signalPayload = buildSpawnFailureSignal(spawn, auditLog, attempts);
|
|
222
|
+
if (dryRun) {
|
|
223
|
+
console.log(`${LOG_PREFIX} [dry-run] Would signal orchestrator`);
|
|
224
|
+
console.log(`${LOG_PREFIX} [dry-run] Severity: ${signalPayload.severity}`);
|
|
225
|
+
console.log(`${LOG_PREFIX} [dry-run] Suggested action: ${signalPayload.suggested_action}`);
|
|
226
|
+
console.log(`${LOG_PREFIX} [dry-run] Message: ${signalPayload.message}`);
|
|
227
|
+
return {
|
|
228
|
+
signalId: 'sig-dry-run',
|
|
229
|
+
signal: signalPayload,
|
|
230
|
+
spawnStatus: SpawnStatus.ESCALATED,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
// WU-1967: Send signal to orchestrator inbox
|
|
234
|
+
console.log(`${LOG_PREFIX} Signalling orchestrator for spawn ${spawnId}`);
|
|
235
|
+
console.log(`${LOG_PREFIX} Target WU: ${spawn.targetWuId}`);
|
|
236
|
+
console.log(`${LOG_PREFIX} Severity: ${signalPayload.severity}`);
|
|
237
|
+
console.log(`${LOG_PREFIX} Suggested action: ${signalPayload.suggested_action}`);
|
|
238
|
+
// Create signal with structured message (JSON payload in message field)
|
|
239
|
+
const signalResult = await createSignal(baseDir, {
|
|
240
|
+
message: JSON.stringify(signalPayload),
|
|
241
|
+
wuId: spawn.parentWuId, // Signal targets the orchestrator (parent WU)
|
|
242
|
+
lane: spawn.lane,
|
|
243
|
+
});
|
|
244
|
+
// Update spawn status to ESCALATED (prevents duplicate signals)
|
|
245
|
+
await store.updateStatus(spawnId, SpawnStatus.ESCALATED);
|
|
246
|
+
console.log(`${LOG_PREFIX} Signal sent: ${signalResult.signal.id}`);
|
|
247
|
+
console.log(`${LOG_PREFIX} Spawn ${spawnId} status updated to ESCALATED`);
|
|
248
|
+
return {
|
|
249
|
+
signalId: signalResult.signal.id,
|
|
250
|
+
signal: signalPayload,
|
|
251
|
+
spawnStatus: SpawnStatus.ESCALATED,
|
|
252
|
+
};
|
|
253
|
+
}
|