@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,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Lane-to-Code_Paths Validator (WU-1372)
|
|
4
|
+
*
|
|
5
|
+
* Validates that a WU's code_paths are consistent with its assigned lane.
|
|
6
|
+
* This is an advisory validation - it warns but never blocks wu:claim or wu:done.
|
|
7
|
+
*
|
|
8
|
+
* Uses LANE_PATH_PATTERNS from wu-constants.mjs to define which paths
|
|
9
|
+
* are discouraged for each lane parent.
|
|
10
|
+
*
|
|
11
|
+
* Part of INIT-002: Workflow Integrity initiative.
|
|
12
|
+
*
|
|
13
|
+
* @see {@link wu-constants.mjs} - LANE_PATH_PATTERNS definition
|
|
14
|
+
* @see {@link lane-checker.mjs} - extractParent for lane parsing
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {object} LaneValidationResult
|
|
18
|
+
* @property {boolean} hasWarnings - True if any code_paths violate lane patterns
|
|
19
|
+
* @property {string[]} warnings - Human-readable warning messages
|
|
20
|
+
* @property {string[]} violations - List of violating code_paths
|
|
21
|
+
* @property {boolean} skipped - True if validation was skipped (no patterns or no code_paths)
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Validate WU code_paths against lane's expected patterns.
|
|
25
|
+
*
|
|
26
|
+
* Checks if any code_paths match the "exclude" patterns for the lane,
|
|
27
|
+
* unless they also match an "allowExceptions" pattern.
|
|
28
|
+
*
|
|
29
|
+
* @param {object} doc - WU YAML document (parsed)
|
|
30
|
+
* @param {string} lane - Lane name (e.g., "Operations: Tooling")
|
|
31
|
+
* @returns {LaneValidationResult} Validation result with warnings if any
|
|
32
|
+
*/
|
|
33
|
+
export declare function validateLaneCodePaths(doc: any, lane: any): {
|
|
34
|
+
hasWarnings: boolean;
|
|
35
|
+
warnings: any;
|
|
36
|
+
violations: any;
|
|
37
|
+
skipped: boolean;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Log lane validation warnings to console.
|
|
41
|
+
*
|
|
42
|
+
* Helper function to format and display warnings consistently.
|
|
43
|
+
* Uses LOG_PREFIX.CLAIM format.
|
|
44
|
+
*
|
|
45
|
+
* @param {LaneValidationResult} result - Result from validateLaneCodePaths
|
|
46
|
+
* @param {string} logPrefix - Log prefix (e.g., "[wu-claim]")
|
|
47
|
+
*/
|
|
48
|
+
export declare function logLaneValidationWarnings(result: any, logPrefix?: string): void;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Lane-to-Code_Paths Validator (WU-1372)
|
|
4
|
+
*
|
|
5
|
+
* Validates that a WU's code_paths are consistent with its assigned lane.
|
|
6
|
+
* This is an advisory validation - it warns but never blocks wu:claim or wu:done.
|
|
7
|
+
*
|
|
8
|
+
* Uses LANE_PATH_PATTERNS from wu-constants.mjs to define which paths
|
|
9
|
+
* are discouraged for each lane parent.
|
|
10
|
+
*
|
|
11
|
+
* Part of INIT-002: Workflow Integrity initiative.
|
|
12
|
+
*
|
|
13
|
+
* @see {@link wu-constants.mjs} - LANE_PATH_PATTERNS definition
|
|
14
|
+
* @see {@link lane-checker.mjs} - extractParent for lane parsing
|
|
15
|
+
*/
|
|
16
|
+
import micromatch from 'micromatch';
|
|
17
|
+
import { extractParent } from './lane-checker.js';
|
|
18
|
+
import { LANE_PATH_PATTERNS } from './wu-constants.js';
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {object} LaneValidationResult
|
|
21
|
+
* @property {boolean} hasWarnings - True if any code_paths violate lane patterns
|
|
22
|
+
* @property {string[]} warnings - Human-readable warning messages
|
|
23
|
+
* @property {string[]} violations - List of violating code_paths
|
|
24
|
+
* @property {boolean} skipped - True if validation was skipped (no patterns or no code_paths)
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Validate WU code_paths against lane's expected patterns.
|
|
28
|
+
*
|
|
29
|
+
* Checks if any code_paths match the "exclude" patterns for the lane,
|
|
30
|
+
* unless they also match an "allowExceptions" pattern.
|
|
31
|
+
*
|
|
32
|
+
* @param {object} doc - WU YAML document (parsed)
|
|
33
|
+
* @param {string} lane - Lane name (e.g., "Operations: Tooling")
|
|
34
|
+
* @returns {LaneValidationResult} Validation result with warnings if any
|
|
35
|
+
*/
|
|
36
|
+
export function validateLaneCodePaths(doc, lane) {
|
|
37
|
+
const codePaths = doc.code_paths || [];
|
|
38
|
+
// Skip validation if no code_paths
|
|
39
|
+
if (!codePaths || codePaths.length === 0) {
|
|
40
|
+
return {
|
|
41
|
+
hasWarnings: false,
|
|
42
|
+
warnings: [],
|
|
43
|
+
violations: [],
|
|
44
|
+
skipped: true,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// Extract parent lane (e.g., "Operations" from "Operations: Tooling")
|
|
48
|
+
const parentLane = extractParent(lane);
|
|
49
|
+
// Get patterns for this lane parent
|
|
50
|
+
const patterns = LANE_PATH_PATTERNS[parentLane];
|
|
51
|
+
// Skip validation if no patterns defined for this lane
|
|
52
|
+
if (!patterns) {
|
|
53
|
+
return {
|
|
54
|
+
hasWarnings: false,
|
|
55
|
+
warnings: [],
|
|
56
|
+
violations: [],
|
|
57
|
+
skipped: true,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const { exclude = [], allowExceptions = [] } = patterns;
|
|
61
|
+
// Find violations: paths that match exclude patterns but NOT exception patterns
|
|
62
|
+
const violations = codePaths.filter((codePath) => {
|
|
63
|
+
// Check if path matches any exclude pattern
|
|
64
|
+
const matchesExclude = micromatch.isMatch(codePath, exclude, { nocase: true });
|
|
65
|
+
if (!matchesExclude) {
|
|
66
|
+
return false; // Path doesn't match any exclude pattern, not a violation
|
|
67
|
+
}
|
|
68
|
+
// Check if path matches any exception pattern
|
|
69
|
+
if (allowExceptions.length > 0) {
|
|
70
|
+
const matchesException = micromatch.isMatch(codePath, allowExceptions, { nocase: true });
|
|
71
|
+
if (matchesException) {
|
|
72
|
+
return false; // Path is allowed by exception, not a violation
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return true; // Path matches exclude and no exception, this is a violation
|
|
76
|
+
});
|
|
77
|
+
if (violations.length === 0) {
|
|
78
|
+
return {
|
|
79
|
+
hasWarnings: false,
|
|
80
|
+
warnings: [],
|
|
81
|
+
violations: [],
|
|
82
|
+
skipped: false,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// Build warning messages
|
|
86
|
+
const warnings = violations.map((path) => {
|
|
87
|
+
return `Lane "${lane}" typically doesn't include "${path}" (expected for different lane)`;
|
|
88
|
+
});
|
|
89
|
+
return {
|
|
90
|
+
hasWarnings: true,
|
|
91
|
+
warnings,
|
|
92
|
+
violations,
|
|
93
|
+
skipped: false,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Log lane validation warnings to console.
|
|
98
|
+
*
|
|
99
|
+
* Helper function to format and display warnings consistently.
|
|
100
|
+
* Uses LOG_PREFIX.CLAIM format.
|
|
101
|
+
*
|
|
102
|
+
* @param {LaneValidationResult} result - Result from validateLaneCodePaths
|
|
103
|
+
* @param {string} logPrefix - Log prefix (e.g., "[wu-claim]")
|
|
104
|
+
*/
|
|
105
|
+
export function logLaneValidationWarnings(result, logPrefix = '[wu-claim]') {
|
|
106
|
+
if (!result.hasWarnings) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
console.warn(`${logPrefix} Lane/code_paths mismatch detected (advisory only):`);
|
|
110
|
+
for (const warning of result.warnings) {
|
|
111
|
+
console.warn(`${logPrefix} ${warning}`);
|
|
112
|
+
}
|
|
113
|
+
console.warn(`${logPrefix} This is a warning only - proceeding with claim.`);
|
|
114
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logs Library (WU-2064)
|
|
3
|
+
*
|
|
4
|
+
* Core library for unified log aggregation following Anthropic's agent logging patterns.
|
|
5
|
+
* Aggregates logs from multiple sources:
|
|
6
|
+
* - .logs/web.log (structured JSON from Next.js)
|
|
7
|
+
* - .beacon/commands.log (git command audit trail)
|
|
8
|
+
* - .beacon/flow.log (WU flow events)
|
|
9
|
+
* - .logs/tool-audit.ndjson (Claude Code tool usage audit)
|
|
10
|
+
*
|
|
11
|
+
* LIBRARY-FIRST: No general-purpose library exists for project-specific log
|
|
12
|
+
* aggregation across custom log locations. Uses native JSON.parse like existing
|
|
13
|
+
* tail-logs.mjs in the codebase.
|
|
14
|
+
*
|
|
15
|
+
* @see docs/02-technical/standards/logging.md
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Log source configurations
|
|
19
|
+
* Each source has a path relative to project root and a source identifier
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Log entry structure from JSON logs
|
|
23
|
+
*/
|
|
24
|
+
interface LogEntry {
|
|
25
|
+
time?: string;
|
|
26
|
+
level?: string;
|
|
27
|
+
msg?: string;
|
|
28
|
+
message?: string;
|
|
29
|
+
event?: string;
|
|
30
|
+
_source?: string;
|
|
31
|
+
[key: string]: unknown;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Parsed log arguments
|
|
35
|
+
*/
|
|
36
|
+
interface ParsedLogsArgs {
|
|
37
|
+
last?: number;
|
|
38
|
+
level?: string;
|
|
39
|
+
service?: string;
|
|
40
|
+
filter?: string;
|
|
41
|
+
json?: boolean;
|
|
42
|
+
help?: boolean;
|
|
43
|
+
}
|
|
44
|
+
export declare const LOG_SOURCES: {
|
|
45
|
+
path: string;
|
|
46
|
+
source: string;
|
|
47
|
+
}[];
|
|
48
|
+
/**
|
|
49
|
+
* Parse a single log line (NDJSON format)
|
|
50
|
+
*
|
|
51
|
+
* @param {string} line - JSON log line
|
|
52
|
+
* @returns {object|null} Parsed log object or null if invalid
|
|
53
|
+
*/
|
|
54
|
+
export declare function parseLogLine(line: any): any;
|
|
55
|
+
/**
|
|
56
|
+
* Options for filtering logs
|
|
57
|
+
*/
|
|
58
|
+
export interface FilterLogsOptions {
|
|
59
|
+
/** Filter by log level (info, warn, error) */
|
|
60
|
+
level?: string;
|
|
61
|
+
/** Filter by service/message prefix */
|
|
62
|
+
service?: string;
|
|
63
|
+
/** Arbitrary text filter (searches in JSON) */
|
|
64
|
+
filter?: string;
|
|
65
|
+
/** Return only last N entries */
|
|
66
|
+
last?: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Filter log entries by criteria
|
|
70
|
+
*
|
|
71
|
+
* @param {object[]} logs - Array of log objects
|
|
72
|
+
* @param {FilterLogsOptions} options - Filter options
|
|
73
|
+
* @returns {object[]} Filtered logs
|
|
74
|
+
*/
|
|
75
|
+
export declare function filterLogs(logs: LogEntry[], options?: FilterLogsOptions): LogEntry[];
|
|
76
|
+
/**
|
|
77
|
+
* Options for aggregating logs
|
|
78
|
+
*/
|
|
79
|
+
export interface AggregateLogsOptions {
|
|
80
|
+
/** Working directory (defaults to process.cwd()) */
|
|
81
|
+
cwd?: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Aggregate logs from all configured sources
|
|
85
|
+
*
|
|
86
|
+
* @param {AggregateLogsOptions} options - Options
|
|
87
|
+
* @returns {Promise<object[]>} Aggregated and sorted log entries
|
|
88
|
+
*/
|
|
89
|
+
export declare function aggregateLogs(options?: AggregateLogsOptions): Promise<any[]>;
|
|
90
|
+
/**
|
|
91
|
+
* Parse command line arguments for logs command
|
|
92
|
+
*
|
|
93
|
+
* @param {string[]} args - Command line arguments (without node and script)
|
|
94
|
+
* @returns {object} Parsed options
|
|
95
|
+
*/
|
|
96
|
+
export declare function parseLogsArgs(args: string[]): ParsedLogsArgs;
|
|
97
|
+
/**
|
|
98
|
+
* Format a log entry for console display
|
|
99
|
+
*
|
|
100
|
+
* @param {object} log - Log object
|
|
101
|
+
* @returns {string} Formatted log line
|
|
102
|
+
*/
|
|
103
|
+
export declare function formatLogEntry(log: LogEntry): string;
|
|
104
|
+
export {};
|
package/dist/logs-lib.js
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logs Library (WU-2064)
|
|
3
|
+
*
|
|
4
|
+
* Core library for unified log aggregation following Anthropic's agent logging patterns.
|
|
5
|
+
* Aggregates logs from multiple sources:
|
|
6
|
+
* - .logs/web.log (structured JSON from Next.js)
|
|
7
|
+
* - .beacon/commands.log (git command audit trail)
|
|
8
|
+
* - .beacon/flow.log (WU flow events)
|
|
9
|
+
* - .logs/tool-audit.ndjson (Claude Code tool usage audit)
|
|
10
|
+
*
|
|
11
|
+
* LIBRARY-FIRST: No general-purpose library exists for project-specific log
|
|
12
|
+
* aggregation across custom log locations. Uses native JSON.parse like existing
|
|
13
|
+
* tail-logs.mjs in the codebase.
|
|
14
|
+
*
|
|
15
|
+
* @see docs/02-technical/standards/logging.md
|
|
16
|
+
*/
|
|
17
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
18
|
+
import path from 'node:path';
|
|
19
|
+
export const LOG_SOURCES = [
|
|
20
|
+
{ path: '.logs/web.log', source: 'web.log' },
|
|
21
|
+
{ path: '.beacon/commands.log', source: 'commands.log' },
|
|
22
|
+
{ path: '.beacon/flow.log', source: 'flow.log' },
|
|
23
|
+
{ path: '.logs/tool-audit.ndjson', source: 'tool-audit.ndjson' },
|
|
24
|
+
];
|
|
25
|
+
/**
|
|
26
|
+
* Parse a single log line (NDJSON format)
|
|
27
|
+
*
|
|
28
|
+
* @param {string} line - JSON log line
|
|
29
|
+
* @returns {object|null} Parsed log object or null if invalid
|
|
30
|
+
*/
|
|
31
|
+
export function parseLogLine(line) {
|
|
32
|
+
if (!line || typeof line !== 'string') {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
const trimmed = line.trim();
|
|
36
|
+
if (!trimmed) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
return JSON.parse(trimmed);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Filter log entries by criteria
|
|
48
|
+
*
|
|
49
|
+
* @param {object[]} logs - Array of log objects
|
|
50
|
+
* @param {FilterLogsOptions} options - Filter options
|
|
51
|
+
* @returns {object[]} Filtered logs
|
|
52
|
+
*/
|
|
53
|
+
export function filterLogs(logs, options = {}) {
|
|
54
|
+
const { level, service, filter, last } = options;
|
|
55
|
+
let result = logs;
|
|
56
|
+
// Filter by level
|
|
57
|
+
if (level) {
|
|
58
|
+
result = result.filter((log) => log.level === level);
|
|
59
|
+
}
|
|
60
|
+
// Filter by service (message prefix)
|
|
61
|
+
if (service) {
|
|
62
|
+
result = result.filter((log) => {
|
|
63
|
+
const msg = log.msg || log.message || '';
|
|
64
|
+
const pattern = '.' + service + '.';
|
|
65
|
+
return msg.startsWith(service) || msg.includes(pattern);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
// Filter by arbitrary text pattern
|
|
69
|
+
if (filter) {
|
|
70
|
+
result = result.filter((log) => {
|
|
71
|
+
const jsonStr = JSON.stringify(log);
|
|
72
|
+
return jsonStr.includes(filter);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
// Limit to last N entries
|
|
76
|
+
if (last && last > 0) {
|
|
77
|
+
result = result.slice(-last);
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Read and parse a single log file
|
|
83
|
+
*
|
|
84
|
+
* @param {string} filePath - Path to log file
|
|
85
|
+
* @param {string} source - Source identifier for tagging
|
|
86
|
+
* @returns {object[]} Parsed log entries with _source field
|
|
87
|
+
*/
|
|
88
|
+
function readLogFile(filePath, source) {
|
|
89
|
+
if (!existsSync(filePath)) {
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
const content = readFileSync(filePath, 'utf8');
|
|
94
|
+
const lines = content.split('\n').filter(Boolean);
|
|
95
|
+
const logs = [];
|
|
96
|
+
for (const line of lines) {
|
|
97
|
+
const parsed = parseLogLine(line);
|
|
98
|
+
if (parsed) {
|
|
99
|
+
parsed._source = source;
|
|
100
|
+
logs.push(parsed);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return logs;
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Aggregate logs from all configured sources
|
|
111
|
+
*
|
|
112
|
+
* @param {AggregateLogsOptions} options - Options
|
|
113
|
+
* @returns {Promise<object[]>} Aggregated and sorted log entries
|
|
114
|
+
*/
|
|
115
|
+
export async function aggregateLogs(options = {}) {
|
|
116
|
+
const { cwd = process.cwd() } = options;
|
|
117
|
+
const allLogs = [];
|
|
118
|
+
for (const { path: logPath, source } of LOG_SOURCES) {
|
|
119
|
+
const fullPath = path.join(cwd, logPath);
|
|
120
|
+
const logs = readLogFile(fullPath, source);
|
|
121
|
+
allLogs.push(...logs);
|
|
122
|
+
}
|
|
123
|
+
// Sort by time (oldest first)
|
|
124
|
+
allLogs.sort((a, b) => {
|
|
125
|
+
const timeA = new Date(a.time || 0).getTime();
|
|
126
|
+
const timeB = new Date(b.time || 0).getTime();
|
|
127
|
+
return timeA - timeB;
|
|
128
|
+
});
|
|
129
|
+
return allLogs;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Parse command line arguments for logs command
|
|
133
|
+
*
|
|
134
|
+
* @param {string[]} args - Command line arguments (without node and script)
|
|
135
|
+
* @returns {object} Parsed options
|
|
136
|
+
*/
|
|
137
|
+
export function parseLogsArgs(args) {
|
|
138
|
+
const result = {};
|
|
139
|
+
let i = 0;
|
|
140
|
+
while (i < args.length) {
|
|
141
|
+
const arg = args[i];
|
|
142
|
+
if (arg === '--last') {
|
|
143
|
+
i++;
|
|
144
|
+
result.last = parseInt(args[i], 10);
|
|
145
|
+
}
|
|
146
|
+
else if (arg === '--level') {
|
|
147
|
+
i++;
|
|
148
|
+
result.level = args[i];
|
|
149
|
+
}
|
|
150
|
+
else if (arg === '--service') {
|
|
151
|
+
i++;
|
|
152
|
+
result.service = args[i];
|
|
153
|
+
}
|
|
154
|
+
else if (arg === '--filter') {
|
|
155
|
+
i++;
|
|
156
|
+
result.filter = args[i];
|
|
157
|
+
}
|
|
158
|
+
else if (arg === '--json') {
|
|
159
|
+
result.json = true;
|
|
160
|
+
}
|
|
161
|
+
else if (arg === '--help' || arg === '-h') {
|
|
162
|
+
result.help = true;
|
|
163
|
+
}
|
|
164
|
+
// Ignore unknown flags
|
|
165
|
+
i++;
|
|
166
|
+
}
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Format a log entry for console display
|
|
171
|
+
*
|
|
172
|
+
* @param {object} log - Log object
|
|
173
|
+
* @returns {string} Formatted log line
|
|
174
|
+
*/
|
|
175
|
+
export function formatLogEntry(log) {
|
|
176
|
+
const levelColors = {
|
|
177
|
+
debug: '\x1b[36m', // cyan
|
|
178
|
+
info: '\x1b[32m', // green
|
|
179
|
+
warn: '\x1b[33m', // yellow
|
|
180
|
+
error: '\x1b[31m', // red
|
|
181
|
+
};
|
|
182
|
+
const reset = '\x1b[0m';
|
|
183
|
+
const dim = '\x1b[2m';
|
|
184
|
+
const level = log.level || 'info';
|
|
185
|
+
const color = levelColors[level] || reset;
|
|
186
|
+
const time = log.time
|
|
187
|
+
? new Date(log.time).toLocaleTimeString('en-GB', {
|
|
188
|
+
hour12: false,
|
|
189
|
+
hour: '2-digit',
|
|
190
|
+
minute: '2-digit',
|
|
191
|
+
second: '2-digit',
|
|
192
|
+
})
|
|
193
|
+
: '??:??:??';
|
|
194
|
+
const msg = log.msg || log.message || log.event || 'unknown';
|
|
195
|
+
const source = log._source ? dim + '[' + log._source + ']' + reset : '';
|
|
196
|
+
// Build metadata string excluding known fields
|
|
197
|
+
const knownFields = ['time', 'level', 'msg', 'message', 'event', '_source'];
|
|
198
|
+
const meta = {};
|
|
199
|
+
for (const [key, value] of Object.entries(log)) {
|
|
200
|
+
if (!knownFields.includes(key)) {
|
|
201
|
+
meta[key] = value;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const metaStr = Object.keys(meta).length > 0 ? ' ' + JSON.stringify(meta) : '';
|
|
205
|
+
const levelStr = level.toUpperCase().padEnd(5);
|
|
206
|
+
return color + '[' + time + '] ' + levelStr + reset + ' ' + source + ' ' + msg + metaStr;
|
|
207
|
+
}
|