@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,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spawn Tree Builder (WU-1950)
|
|
3
|
+
*
|
|
4
|
+
* Builds and formats spawn trees for visualization.
|
|
5
|
+
* Used by spawn:list command to display parent-child relationships.
|
|
6
|
+
*
|
|
7
|
+
* Note: Domain-specific tree visualization for spawn registry.
|
|
8
|
+
* Integrates with spawn-registry-store and spawn-registry-schema.
|
|
9
|
+
* No external tree library needed - logic is tightly coupled to spawn data model.
|
|
10
|
+
*
|
|
11
|
+
* @see {@link tools/__tests__/spawn-list.test.mjs} - Tests
|
|
12
|
+
* @see {@link tools/spawn-list.mjs} - CLI command
|
|
13
|
+
* @see {@link tools/lib/spawn-registry-store.mjs} - Data source
|
|
14
|
+
*/
|
|
15
|
+
import fs from 'node:fs/promises';
|
|
16
|
+
import path from 'node:path';
|
|
17
|
+
import { SpawnRegistryStore } from './spawn-registry-store.js';
|
|
18
|
+
import { SpawnStatus } from './spawn-registry-schema.js';
|
|
19
|
+
import { parse as parseYAML } from 'yaml';
|
|
20
|
+
/**
|
|
21
|
+
* Status indicators for terminal output.
|
|
22
|
+
* Using unicode symbols for clear visual distinction.
|
|
23
|
+
*/
|
|
24
|
+
export const STATUS_INDICATORS = Object.freeze({
|
|
25
|
+
[SpawnStatus.PENDING]: '\u25CB', // ○ (white circle)
|
|
26
|
+
[SpawnStatus.COMPLETED]: '\u2713', // ✓ (check mark)
|
|
27
|
+
[SpawnStatus.TIMEOUT]: '\u23F1', // ⏱ (stopwatch)
|
|
28
|
+
[SpawnStatus.CRASHED]: '\u2717', // ✗ (x mark)
|
|
29
|
+
});
|
|
30
|
+
/**
|
|
31
|
+
* Tree node structure
|
|
32
|
+
* @typedef {object} SpawnTreeNode
|
|
33
|
+
* @property {string} wuId - WU ID for this node
|
|
34
|
+
* @property {string|null} spawnId - Spawn ID (null for root)
|
|
35
|
+
* @property {string|null} status - Spawn status (null for root)
|
|
36
|
+
* @property {string|null} lane - Lane (null for root)
|
|
37
|
+
* @property {string|null} spawnedAt - Spawn timestamp (null for root)
|
|
38
|
+
* @property {SpawnTreeNode[]} children - Child nodes
|
|
39
|
+
*/
|
|
40
|
+
/**
|
|
41
|
+
* Builds a spawn tree from flat spawn events.
|
|
42
|
+
*
|
|
43
|
+
* @param {import('./spawn-registry-schema.js').SpawnEvent[]} spawns - Array of spawn events
|
|
44
|
+
* @param {string} rootWuId - Root WU ID to build tree from
|
|
45
|
+
* @returns {SpawnTreeNode} Tree rooted at rootWuId
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* const tree = buildSpawnTree(spawns, 'WU-1000');
|
|
49
|
+
* // { wuId: 'WU-1000', children: [{ wuId: 'WU-1001', ... }] }
|
|
50
|
+
*/
|
|
51
|
+
export function buildSpawnTree(spawns, rootWuId) {
|
|
52
|
+
// Create root node
|
|
53
|
+
/** @type {SpawnTreeNode} */
|
|
54
|
+
const root = {
|
|
55
|
+
wuId: rootWuId,
|
|
56
|
+
spawnId: null,
|
|
57
|
+
status: null,
|
|
58
|
+
lane: null,
|
|
59
|
+
spawnedAt: null,
|
|
60
|
+
children: [],
|
|
61
|
+
};
|
|
62
|
+
if (spawns.length === 0) {
|
|
63
|
+
return root;
|
|
64
|
+
}
|
|
65
|
+
// Build index of spawns by parent WU ID for efficient lookup
|
|
66
|
+
/** @type {Map<string, import('./spawn-registry-schema.js').SpawnEvent[]>} */
|
|
67
|
+
const spawnsByParent = new Map();
|
|
68
|
+
for (const spawn of spawns) {
|
|
69
|
+
const existing = spawnsByParent.get(spawn.parentWuId) ?? [];
|
|
70
|
+
existing.push(spawn);
|
|
71
|
+
spawnsByParent.set(spawn.parentWuId, existing);
|
|
72
|
+
}
|
|
73
|
+
// Recursive function to build tree
|
|
74
|
+
/**
|
|
75
|
+
* @param {string} parentWuId
|
|
76
|
+
* @returns {SpawnTreeNode[]}
|
|
77
|
+
*/
|
|
78
|
+
function buildChildren(parentWuId) {
|
|
79
|
+
const childSpawns = spawnsByParent.get(parentWuId) ?? [];
|
|
80
|
+
return childSpawns.map((spawn) => ({
|
|
81
|
+
wuId: spawn.targetWuId,
|
|
82
|
+
spawnId: spawn.id,
|
|
83
|
+
status: spawn.status,
|
|
84
|
+
lane: spawn.lane,
|
|
85
|
+
spawnedAt: spawn.spawnedAt,
|
|
86
|
+
children: buildChildren(spawn.targetWuId),
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
root.children = buildChildren(rootWuId);
|
|
90
|
+
return root;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Tree branch characters for formatting
|
|
94
|
+
*/
|
|
95
|
+
const TREE_CHARS = Object.freeze({
|
|
96
|
+
VERTICAL: '\u2502', // │
|
|
97
|
+
BRANCH: '\u251C', // ├
|
|
98
|
+
LAST_BRANCH: '\u2514', // └
|
|
99
|
+
HORIZONTAL: '\u2500', // ─
|
|
100
|
+
SPACE: ' ',
|
|
101
|
+
});
|
|
102
|
+
/**
|
|
103
|
+
* Formats a spawn tree for terminal display with indentation and tree characters.
|
|
104
|
+
*
|
|
105
|
+
* @param {SpawnTreeNode} tree - Tree to format
|
|
106
|
+
* @returns {string} Formatted tree string
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* const formatted = formatSpawnTree(tree);
|
|
110
|
+
* // WU-1000 (root)
|
|
111
|
+
* // ├── ○ WU-1001 [spawn-1111] (Operations: Tooling)
|
|
112
|
+
* // │ └── ✓ WU-1002 [spawn-2222] (Core: Backend)
|
|
113
|
+
* // └── ○ WU-1003 [spawn-3333] (Experience: Web)
|
|
114
|
+
*/
|
|
115
|
+
export function formatSpawnTree(tree) {
|
|
116
|
+
const lines = [];
|
|
117
|
+
// Root line
|
|
118
|
+
lines.push(`${tree.wuId} (root)`);
|
|
119
|
+
if (tree.children.length === 0) {
|
|
120
|
+
lines.push(` (no spawns)`);
|
|
121
|
+
return lines.join('\n');
|
|
122
|
+
}
|
|
123
|
+
// Recursive formatting
|
|
124
|
+
/**
|
|
125
|
+
* @param {SpawnTreeNode[]} children
|
|
126
|
+
* @param {string} prefix - Indentation prefix for this level
|
|
127
|
+
*/
|
|
128
|
+
function formatChildren(children, prefix) {
|
|
129
|
+
children.forEach((child, index) => {
|
|
130
|
+
const isLast = index === children.length - 1;
|
|
131
|
+
const branch = isLast
|
|
132
|
+
? `${TREE_CHARS.LAST_BRANCH}${TREE_CHARS.HORIZONTAL}${TREE_CHARS.HORIZONTAL}`
|
|
133
|
+
: `${TREE_CHARS.BRANCH}${TREE_CHARS.HORIZONTAL}${TREE_CHARS.HORIZONTAL}`;
|
|
134
|
+
const indicator = STATUS_INDICATORS[child.status] ?? '?';
|
|
135
|
+
const spawnInfo = child.spawnId ? ` [${child.spawnId}]` : '';
|
|
136
|
+
const laneInfo = child.lane ? ` (${child.lane})` : '';
|
|
137
|
+
lines.push(`${prefix}${branch} ${indicator} ${child.wuId}${spawnInfo}${laneInfo}`);
|
|
138
|
+
// Child prefix: use vertical bar if not last, space if last
|
|
139
|
+
const childPrefix = prefix + (isLast ? ' ' : `${TREE_CHARS.VERTICAL} `);
|
|
140
|
+
formatChildren(child.children, childPrefix);
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
formatChildren(tree.children, '');
|
|
144
|
+
return lines.join('\n');
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Gets all spawns for a WU (both where WU is parent and descendants).
|
|
148
|
+
*
|
|
149
|
+
* Returns all spawns needed to build the full tree from this WU.
|
|
150
|
+
*
|
|
151
|
+
* @param {string} wuId - WU ID to get spawns for
|
|
152
|
+
* @param {string} baseDir - Directory containing spawn-registry.jsonl
|
|
153
|
+
* @returns {Promise<import('./spawn-registry-schema.js').SpawnEvent[]>} Array of spawn events
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* const spawns = await getSpawnsByWU('WU-1000', '.beacon/state');
|
|
157
|
+
*/
|
|
158
|
+
export async function getSpawnsByWU(wuId, baseDir) {
|
|
159
|
+
const store = new SpawnRegistryStore(baseDir);
|
|
160
|
+
try {
|
|
161
|
+
await store.load();
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
// Registry doesn't exist or is invalid
|
|
165
|
+
if (error.code === 'ENOENT') {
|
|
166
|
+
return [];
|
|
167
|
+
}
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
// Get all spawns
|
|
171
|
+
const allSpawns = store.getAllSpawns();
|
|
172
|
+
if (allSpawns.length === 0) {
|
|
173
|
+
return [];
|
|
174
|
+
}
|
|
175
|
+
// Find all spawns in the tree rooted at wuId
|
|
176
|
+
// Start with direct children of wuId
|
|
177
|
+
const result = [];
|
|
178
|
+
const visited = new Set();
|
|
179
|
+
const queue = [wuId];
|
|
180
|
+
while (queue.length > 0) {
|
|
181
|
+
const currentWuId = queue.shift();
|
|
182
|
+
if (visited.has(currentWuId))
|
|
183
|
+
continue;
|
|
184
|
+
visited.add(currentWuId);
|
|
185
|
+
// Find spawns where current WU is the parent
|
|
186
|
+
const childSpawns = store.getByParent(currentWuId);
|
|
187
|
+
for (const spawn of childSpawns) {
|
|
188
|
+
if (!result.some((s) => s.id === spawn.id)) {
|
|
189
|
+
result.push(spawn);
|
|
190
|
+
queue.push(spawn.targetWuId);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return result;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Gets all spawns for an initiative.
|
|
198
|
+
*
|
|
199
|
+
* Reads WU YAML files to find which WUs belong to the initiative,
|
|
200
|
+
* then returns all spawns where parent or target WU belongs to initiative.
|
|
201
|
+
*
|
|
202
|
+
* @param {string} initiativeId - Initiative ID (e.g., 'INIT-001')
|
|
203
|
+
* @param {string} registryDir - Directory containing spawn-registry.jsonl
|
|
204
|
+
* @param {string} wuDir - Directory containing WU YAML files
|
|
205
|
+
* @returns {Promise<import('./spawn-registry-schema.js').SpawnEvent[]>} Array of spawn events
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* const spawns = await getSpawnsByInitiative('INIT-001', '.beacon/state', 'docs/04-operations/tasks/wu');
|
|
209
|
+
*/
|
|
210
|
+
export async function getSpawnsByInitiative(initiativeId, registryDir, wuDir) {
|
|
211
|
+
// Get all WUs belonging to initiative
|
|
212
|
+
const initiativeWuIds = await getWUsForInitiative(initiativeId, wuDir);
|
|
213
|
+
if (initiativeWuIds.size === 0) {
|
|
214
|
+
return [];
|
|
215
|
+
}
|
|
216
|
+
// Load spawn registry
|
|
217
|
+
const store = new SpawnRegistryStore(registryDir);
|
|
218
|
+
try {
|
|
219
|
+
await store.load();
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
if (error.code === 'ENOENT') {
|
|
223
|
+
return [];
|
|
224
|
+
}
|
|
225
|
+
throw error;
|
|
226
|
+
}
|
|
227
|
+
// Filter spawns where parent belongs to initiative
|
|
228
|
+
const allSpawns = store.getAllSpawns();
|
|
229
|
+
return allSpawns.filter((spawn) => initiativeWuIds.has(spawn.parentWuId));
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Reads WU YAML files to find WUs belonging to an initiative.
|
|
233
|
+
*
|
|
234
|
+
* @param {string} initiativeId - Initiative ID
|
|
235
|
+
* @param {string} wuDir - Directory containing WU YAML files
|
|
236
|
+
* @returns {Promise<Set<string>>} Set of WU IDs belonging to initiative
|
|
237
|
+
*/
|
|
238
|
+
async function getWUsForInitiative(initiativeId, wuDir) {
|
|
239
|
+
const wuIds = new Set();
|
|
240
|
+
let files;
|
|
241
|
+
try {
|
|
242
|
+
files = await fs.readdir(wuDir);
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
if (error.code === 'ENOENT') {
|
|
246
|
+
return wuIds;
|
|
247
|
+
}
|
|
248
|
+
throw error;
|
|
249
|
+
}
|
|
250
|
+
const wuFiles = files.filter((f) => f.startsWith('WU-') && f.endsWith('.yaml'));
|
|
251
|
+
for (const file of wuFiles) {
|
|
252
|
+
try {
|
|
253
|
+
const content = await fs.readFile(path.join(wuDir, file), 'utf-8');
|
|
254
|
+
const doc = parseYAML(content);
|
|
255
|
+
if (doc.initiative === initiativeId) {
|
|
256
|
+
wuIds.add(doc.id);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
// Skip files that can't be parsed
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return wuIds;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Converts a spawn tree to JSON format.
|
|
268
|
+
*
|
|
269
|
+
* @param {SpawnTreeNode} tree - Tree to convert
|
|
270
|
+
* @returns {object} JSON-serializable tree
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* const json = treeToJSON(tree);
|
|
274
|
+
* console.log(JSON.stringify(json, null, 2));
|
|
275
|
+
*/
|
|
276
|
+
export function treeToJSON(tree) {
|
|
277
|
+
return {
|
|
278
|
+
wuId: tree.wuId,
|
|
279
|
+
spawnId: tree.spawnId,
|
|
280
|
+
status: tree.status,
|
|
281
|
+
lane: tree.lane,
|
|
282
|
+
spawnedAt: tree.spawnedAt,
|
|
283
|
+
children: tree.children.map((child) => treeToJSON(child)),
|
|
284
|
+
};
|
|
285
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Stamp-status validation utilities
|
|
3
|
+
*
|
|
4
|
+
* WU-1781: Provides utilities to detect and handle legacy WUs with stamp-status mismatches.
|
|
5
|
+
*
|
|
6
|
+
* The problem: WUs with .done stamps but non-done status (e.g., cancelled, ready) cause
|
|
7
|
+
* tasks:validate to fail, which blocks husky pre-push and prevents wu:done from completing.
|
|
8
|
+
*
|
|
9
|
+
* The solution: Detect these legacy artifacts and exempt them from validation to prevent
|
|
10
|
+
* deadlocks, while still enforcing validation on new/active WUs.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* List of parent-only lanes that are deprecated (legacy).
|
|
14
|
+
* WUs with these lanes are considered legacy artifacts and may have stamp-status mismatches.
|
|
15
|
+
* Modern WUs should use sub-lanes like "Operations: Tooling".
|
|
16
|
+
*
|
|
17
|
+
* @type {readonly string[]}
|
|
18
|
+
*/
|
|
19
|
+
export declare const LEGACY_PARENT_ONLY_LANES: readonly string[];
|
|
20
|
+
/**
|
|
21
|
+
* Check if a lane is a deprecated parent-only lane (no sub-lane specified).
|
|
22
|
+
*
|
|
23
|
+
* @param {string|null|undefined} lane - The lane to check
|
|
24
|
+
* @returns {boolean} True if the lane is a parent-only legacy lane
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* isLegacyParentOnlyLane('Intelligence') // true
|
|
28
|
+
* isLegacyParentOnlyLane('Operations: Tooling') // false
|
|
29
|
+
*/
|
|
30
|
+
export declare function isLegacyParentOnlyLane(lane: any): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Check if a WU is a legacy artifact with stamp-status mismatch.
|
|
33
|
+
*
|
|
34
|
+
* A legacy stamped WU is one that:
|
|
35
|
+
* - Has a .done stamp file
|
|
36
|
+
* - Has a status that is NOT 'done'
|
|
37
|
+
*
|
|
38
|
+
* These WUs are historical artifacts from before validation was strict,
|
|
39
|
+
* and should be exempted from the stamp-status consistency check.
|
|
40
|
+
*
|
|
41
|
+
* @param {object} wu - The parsed WU YAML object
|
|
42
|
+
* @param {string} wu.id - WU ID (e.g., 'WU-100')
|
|
43
|
+
* @param {string} wu.status - WU status (e.g., 'done', 'cancelled', 'ready')
|
|
44
|
+
* @param {Set<string>} stampedIds - Set of WU IDs that have .done stamp files
|
|
45
|
+
* @returns {boolean} True if this is a legacy stamped WU with mismatch
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* const stampedIds = new Set(['WU-100', 'WU-101']);
|
|
49
|
+
* isLegacyStampedWU({ id: 'WU-100', status: 'cancelled' }, stampedIds) // true
|
|
50
|
+
* isLegacyStampedWU({ id: 'WU-100', status: 'done' }, stampedIds) // false (no mismatch)
|
|
51
|
+
* isLegacyStampedWU({ id: 'WU-999', status: 'cancelled' }, stampedIds) // false (no stamp)
|
|
52
|
+
*/
|
|
53
|
+
export declare function isLegacyStampedWU(wu: any, stampedIds: any): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Check if a WU ID is exempted from stamp-status validation via config.
|
|
56
|
+
*
|
|
57
|
+
* The .lumenflow.config.yaml can specify exemptions for known historical
|
|
58
|
+
* artifacts that cannot be fixed (e.g., WU-307, WU-311, WU-1152).
|
|
59
|
+
*
|
|
60
|
+
* @param {string} id - WU ID to check
|
|
61
|
+
* @param {string[]|null|undefined} exemptions - List of exempted WU IDs from config
|
|
62
|
+
* @returns {boolean} True if the WU is exempted
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* isExemptedFromStampStatusCheck('WU-307', ['WU-307', 'WU-311']) // true
|
|
66
|
+
* isExemptedFromStampStatusCheck('WU-999', ['WU-307', 'WU-311']) // false
|
|
67
|
+
*/
|
|
68
|
+
export declare function isExemptedFromStampStatusCheck(id: any, exemptions: any): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Determine if a WU should be exempted from stamp-status validation.
|
|
71
|
+
*
|
|
72
|
+
* A WU is exempted if:
|
|
73
|
+
* 1. It's explicitly listed in the config exemptions, OR
|
|
74
|
+
* 2. It's a legacy stamped WU (has stamp but status != done) AND has a legacy parent-only lane
|
|
75
|
+
*
|
|
76
|
+
* @param {object} wu - The parsed WU YAML object
|
|
77
|
+
* @param {Set<string>} stampedIds - Set of WU IDs that have .done stamp files
|
|
78
|
+
* @param {string[]} exemptions - List of exempted WU IDs from config
|
|
79
|
+
* @returns {{ exempted: boolean, reason: string|null }} Whether exempted and why
|
|
80
|
+
*/
|
|
81
|
+
export declare function shouldExemptFromStampStatusCheck(wu: any, stampedIds: any, exemptions?: any[]): {
|
|
82
|
+
exempted: boolean;
|
|
83
|
+
reason: string;
|
|
84
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Stamp-status validation utilities
|
|
3
|
+
*
|
|
4
|
+
* WU-1781: Provides utilities to detect and handle legacy WUs with stamp-status mismatches.
|
|
5
|
+
*
|
|
6
|
+
* The problem: WUs with .done stamps but non-done status (e.g., cancelled, ready) cause
|
|
7
|
+
* tasks:validate to fail, which blocks husky pre-push and prevents wu:done from completing.
|
|
8
|
+
*
|
|
9
|
+
* The solution: Detect these legacy artifacts and exempt them from validation to prevent
|
|
10
|
+
* deadlocks, while still enforcing validation on new/active WUs.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* List of parent-only lanes that are deprecated (legacy).
|
|
14
|
+
* WUs with these lanes are considered legacy artifacts and may have stamp-status mismatches.
|
|
15
|
+
* Modern WUs should use sub-lanes like "Operations: Tooling".
|
|
16
|
+
*
|
|
17
|
+
* @type {readonly string[]}
|
|
18
|
+
*/
|
|
19
|
+
export const LEGACY_PARENT_ONLY_LANES = Object.freeze([
|
|
20
|
+
'Intelligence',
|
|
21
|
+
'Core Systems',
|
|
22
|
+
'Operations',
|
|
23
|
+
'Experience',
|
|
24
|
+
'Discovery',
|
|
25
|
+
]);
|
|
26
|
+
/**
|
|
27
|
+
* Check if a lane is a deprecated parent-only lane (no sub-lane specified).
|
|
28
|
+
*
|
|
29
|
+
* @param {string|null|undefined} lane - The lane to check
|
|
30
|
+
* @returns {boolean} True if the lane is a parent-only legacy lane
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* isLegacyParentOnlyLane('Intelligence') // true
|
|
34
|
+
* isLegacyParentOnlyLane('Operations: Tooling') // false
|
|
35
|
+
*/
|
|
36
|
+
export function isLegacyParentOnlyLane(lane) {
|
|
37
|
+
if (!lane || typeof lane !== 'string') {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const normalizedLane = lane.trim();
|
|
41
|
+
// Check if it's an exact match to a parent-only lane (case-insensitive)
|
|
42
|
+
const lowerLane = normalizedLane.toLowerCase();
|
|
43
|
+
return LEGACY_PARENT_ONLY_LANES.some((parentLane) => parentLane.toLowerCase() === lowerLane);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Check if a WU is a legacy artifact with stamp-status mismatch.
|
|
47
|
+
*
|
|
48
|
+
* A legacy stamped WU is one that:
|
|
49
|
+
* - Has a .done stamp file
|
|
50
|
+
* - Has a status that is NOT 'done'
|
|
51
|
+
*
|
|
52
|
+
* These WUs are historical artifacts from before validation was strict,
|
|
53
|
+
* and should be exempted from the stamp-status consistency check.
|
|
54
|
+
*
|
|
55
|
+
* @param {object} wu - The parsed WU YAML object
|
|
56
|
+
* @param {string} wu.id - WU ID (e.g., 'WU-100')
|
|
57
|
+
* @param {string} wu.status - WU status (e.g., 'done', 'cancelled', 'ready')
|
|
58
|
+
* @param {Set<string>} stampedIds - Set of WU IDs that have .done stamp files
|
|
59
|
+
* @returns {boolean} True if this is a legacy stamped WU with mismatch
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* const stampedIds = new Set(['WU-100', 'WU-101']);
|
|
63
|
+
* isLegacyStampedWU({ id: 'WU-100', status: 'cancelled' }, stampedIds) // true
|
|
64
|
+
* isLegacyStampedWU({ id: 'WU-100', status: 'done' }, stampedIds) // false (no mismatch)
|
|
65
|
+
* isLegacyStampedWU({ id: 'WU-999', status: 'cancelled' }, stampedIds) // false (no stamp)
|
|
66
|
+
*/
|
|
67
|
+
export function isLegacyStampedWU(wu, stampedIds) {
|
|
68
|
+
if (!wu || !wu.id || !stampedIds) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
// Must have a stamp
|
|
72
|
+
const hasStamp = stampedIds.has(wu.id);
|
|
73
|
+
if (!hasStamp) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
// Must have a status that is NOT done
|
|
77
|
+
const status = wu.status;
|
|
78
|
+
if (!status || typeof status !== 'string') {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
// If status is 'done', this is a normal WU (no mismatch)
|
|
82
|
+
if (status.toLowerCase() === 'done') {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
// Has stamp + status != done = legacy mismatch
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Check if a WU ID is exempted from stamp-status validation via config.
|
|
90
|
+
*
|
|
91
|
+
* The .lumenflow.config.yaml can specify exemptions for known historical
|
|
92
|
+
* artifacts that cannot be fixed (e.g., WU-307, WU-311, WU-1152).
|
|
93
|
+
*
|
|
94
|
+
* @param {string} id - WU ID to check
|
|
95
|
+
* @param {string[]|null|undefined} exemptions - List of exempted WU IDs from config
|
|
96
|
+
* @returns {boolean} True if the WU is exempted
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* isExemptedFromStampStatusCheck('WU-307', ['WU-307', 'WU-311']) // true
|
|
100
|
+
* isExemptedFromStampStatusCheck('WU-999', ['WU-307', 'WU-311']) // false
|
|
101
|
+
*/
|
|
102
|
+
export function isExemptedFromStampStatusCheck(id, exemptions) {
|
|
103
|
+
if (!id || !exemptions || !Array.isArray(exemptions)) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
return exemptions.includes(id);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Determine if a WU should be exempted from stamp-status validation.
|
|
110
|
+
*
|
|
111
|
+
* A WU is exempted if:
|
|
112
|
+
* 1. It's explicitly listed in the config exemptions, OR
|
|
113
|
+
* 2. It's a legacy stamped WU (has stamp but status != done) AND has a legacy parent-only lane
|
|
114
|
+
*
|
|
115
|
+
* @param {object} wu - The parsed WU YAML object
|
|
116
|
+
* @param {Set<string>} stampedIds - Set of WU IDs that have .done stamp files
|
|
117
|
+
* @param {string[]} exemptions - List of exempted WU IDs from config
|
|
118
|
+
* @returns {{ exempted: boolean, reason: string|null }} Whether exempted and why
|
|
119
|
+
*/
|
|
120
|
+
export function shouldExemptFromStampStatusCheck(wu, stampedIds, exemptions = []) {
|
|
121
|
+
const id = wu?.id;
|
|
122
|
+
// Check config exemption first
|
|
123
|
+
if (isExemptedFromStampStatusCheck(id, exemptions)) {
|
|
124
|
+
return { exempted: true, reason: 'config exemption' };
|
|
125
|
+
}
|
|
126
|
+
// Check if it's a legacy stamped WU with a legacy lane
|
|
127
|
+
if (isLegacyStampedWU(wu, stampedIds)) {
|
|
128
|
+
const lane = wu.lane;
|
|
129
|
+
if (isLegacyParentOnlyLane(lane)) {
|
|
130
|
+
return { exempted: true, reason: 'legacy parent-only lane with stamp' };
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return { exempted: false, reason: null };
|
|
134
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stamp File Utilities
|
|
3
|
+
*
|
|
4
|
+
* Centralized stamp file operations (create, validate)
|
|
5
|
+
* Eliminates magic string for stamp body template
|
|
6
|
+
*
|
|
7
|
+
* WU-2242: Added format validation for corrupted stamp detection
|
|
8
|
+
*
|
|
9
|
+
* Stamp files (.beacon/stamps/WU-{id}.done) serve as completion markers
|
|
10
|
+
* Used by wu:done, wu:recovery, and validation tools
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Stamp format error types (WU-2242)
|
|
14
|
+
* @readonly
|
|
15
|
+
* @enum {string}
|
|
16
|
+
*/
|
|
17
|
+
export declare const STAMP_FORMAT_ERRORS: Readonly<{
|
|
18
|
+
/** Stamp file is empty or contains only whitespace */
|
|
19
|
+
EMPTY_FILE: "EMPTY_FILE";
|
|
20
|
+
/** Missing WU identifier line (format: WU WU-123 (em dash) Title) */
|
|
21
|
+
MISSING_WU_LINE: "MISSING_WU_LINE";
|
|
22
|
+
/** Missing Completed: YYYY-MM-DD line */
|
|
23
|
+
MISSING_COMPLETED_LINE: "MISSING_COMPLETED_LINE";
|
|
24
|
+
/** Date is not in valid YYYY-MM-DD format or is invalid */
|
|
25
|
+
INVALID_DATE_FORMAT: "INVALID_DATE_FORMAT";
|
|
26
|
+
/** WU ID in stamp does not match expected ID */
|
|
27
|
+
WU_ID_MISMATCH: "WU_ID_MISMATCH";
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* Create stamp file (idempotent - safe to call multiple times)
|
|
31
|
+
*
|
|
32
|
+
* @param {object} params - Parameters
|
|
33
|
+
* @param {string} params.id - WU ID (e.g., 'WU-123')
|
|
34
|
+
* @param {string} params.title - WU title
|
|
35
|
+
* @returns {object} Result { created: boolean, path: string, reason?: string }
|
|
36
|
+
*/
|
|
37
|
+
export declare function createStamp({ id, title }: {
|
|
38
|
+
id: any;
|
|
39
|
+
title: any;
|
|
40
|
+
}): {
|
|
41
|
+
created: boolean;
|
|
42
|
+
path: string;
|
|
43
|
+
reason: string;
|
|
44
|
+
} | {
|
|
45
|
+
created: boolean;
|
|
46
|
+
path: string;
|
|
47
|
+
reason?: undefined;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Validate stamp exists
|
|
51
|
+
*
|
|
52
|
+
* @param {string} stampPath - Path to stamp file
|
|
53
|
+
* @returns {boolean} True if stamp exists
|
|
54
|
+
*/
|
|
55
|
+
export declare function validateStamp(stampPath: any): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Get stamp path using WU_PATHS (consistent with codebase)
|
|
58
|
+
*
|
|
59
|
+
* @param {string} id - WU ID
|
|
60
|
+
* @returns {string} Absolute path to stamp file
|
|
61
|
+
*/
|
|
62
|
+
export declare function getStampPath(id: any): string;
|
|
63
|
+
/**
|
|
64
|
+
* Validate stamp file format (WU-2242)
|
|
65
|
+
*
|
|
66
|
+
* Expected format:
|
|
67
|
+
* ```
|
|
68
|
+
* WU WU-123 (em dash) Title here
|
|
69
|
+
* Completed: 2025-12-31
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* @param {string} wuId - WU ID (e.g., 'WU-123')
|
|
73
|
+
* @param {string} [projectRoot=process.cwd()] - Project root directory
|
|
74
|
+
* @returns {Promise<{valid: boolean, errors: string[], missing?: boolean}>}
|
|
75
|
+
*/
|
|
76
|
+
export declare function validateStampFormat(wuId: any, projectRoot?: string): Promise<{
|
|
77
|
+
valid: boolean;
|
|
78
|
+
errors: any[];
|
|
79
|
+
missing: boolean;
|
|
80
|
+
} | {
|
|
81
|
+
valid: boolean;
|
|
82
|
+
errors: any[];
|
|
83
|
+
missing?: undefined;
|
|
84
|
+
}>;
|
|
85
|
+
/**
|
|
86
|
+
* Parsed stamp metadata
|
|
87
|
+
*/
|
|
88
|
+
interface StampMetadata {
|
|
89
|
+
wuId?: string;
|
|
90
|
+
title?: string;
|
|
91
|
+
completedDate?: string;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Parse stamp content to extract metadata
|
|
95
|
+
*
|
|
96
|
+
* @param {string} content - Stamp file content
|
|
97
|
+
* @returns {StampMetadata}
|
|
98
|
+
*/
|
|
99
|
+
export declare function parseStampContent(content: string): StampMetadata;
|
|
100
|
+
export {};
|