@nathapp/nax 0.50.3 → 0.51.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/CHANGELOG.md +30 -0
- package/dist/nax.js +393 -197
- package/package.json +1 -3
- package/bin/nax.ts +0 -1195
- package/src/acceptance/fix-generator.ts +0 -322
- package/src/acceptance/generator.ts +0 -415
- package/src/acceptance/index.ts +0 -42
- package/src/acceptance/refinement.ts +0 -224
- package/src/acceptance/templates/cli.ts +0 -47
- package/src/acceptance/templates/component.ts +0 -78
- package/src/acceptance/templates/e2e.ts +0 -43
- package/src/acceptance/templates/index.ts +0 -21
- package/src/acceptance/templates/snapshot.ts +0 -50
- package/src/acceptance/templates/unit.ts +0 -48
- package/src/acceptance/types.ts +0 -138
- package/src/agents/acp/adapter.ts +0 -888
- package/src/agents/acp/cost.ts +0 -9
- package/src/agents/acp/index.ts +0 -7
- package/src/agents/acp/interaction-bridge.ts +0 -126
- package/src/agents/acp/parser.ts +0 -119
- package/src/agents/acp/spawn-client.ts +0 -373
- package/src/agents/acp/types.ts +0 -22
- package/src/agents/aider/adapter.ts +0 -135
- package/src/agents/claude/adapter.ts +0 -258
- package/src/agents/claude/complete.ts +0 -80
- package/src/agents/claude/cost.ts +0 -16
- package/src/agents/claude/execution.ts +0 -215
- package/src/agents/claude/index.ts +0 -3
- package/src/agents/claude/interactive.ts +0 -77
- package/src/agents/claude/plan.ts +0 -179
- package/src/agents/codex/adapter.ts +0 -153
- package/src/agents/cost/calculate.ts +0 -154
- package/src/agents/cost/index.ts +0 -10
- package/src/agents/cost/parse.ts +0 -97
- package/src/agents/cost/pricing.ts +0 -59
- package/src/agents/cost/types.ts +0 -45
- package/src/agents/gemini/adapter.ts +0 -177
- package/src/agents/index.ts +0 -18
- package/src/agents/opencode/adapter.ts +0 -106
- package/src/agents/registry.ts +0 -136
- package/src/agents/shared/decompose.ts +0 -154
- package/src/agents/shared/model-resolution.ts +0 -43
- package/src/agents/shared/types-extended.ts +0 -164
- package/src/agents/shared/validation.ts +0 -69
- package/src/agents/shared/version-detection.ts +0 -109
- package/src/agents/types.ts +0 -205
- package/src/analyze/classifier.ts +0 -282
- package/src/analyze/index.ts +0 -16
- package/src/analyze/scanner.ts +0 -171
- package/src/analyze/types.ts +0 -51
- package/src/cli/accept.ts +0 -108
- package/src/cli/agents.ts +0 -87
- package/src/cli/analyze-parser.ts +0 -291
- package/src/cli/analyze.ts +0 -352
- package/src/cli/config-descriptions.ts +0 -219
- package/src/cli/config-diff.ts +0 -103
- package/src/cli/config-display.ts +0 -285
- package/src/cli/config-get.ts +0 -55
- package/src/cli/config.ts +0 -14
- package/src/cli/constitution.ts +0 -17
- package/src/cli/diagnose-analysis.ts +0 -159
- package/src/cli/diagnose-formatter.ts +0 -87
- package/src/cli/diagnose.ts +0 -203
- package/src/cli/generate.ts +0 -250
- package/src/cli/index.ts +0 -42
- package/src/cli/init-context.ts +0 -405
- package/src/cli/init-detect.ts +0 -303
- package/src/cli/init.ts +0 -296
- package/src/cli/interact.ts +0 -295
- package/src/cli/plan.ts +0 -509
- package/src/cli/plugins.ts +0 -122
- package/src/cli/prompts-export.ts +0 -58
- package/src/cli/prompts-init.ts +0 -200
- package/src/cli/prompts-main.ts +0 -183
- package/src/cli/prompts-shared.ts +0 -70
- package/src/cli/prompts-tdd.ts +0 -88
- package/src/cli/prompts.ts +0 -17
- package/src/cli/runs.ts +0 -174
- package/src/cli/status-cost.ts +0 -151
- package/src/cli/status-features.ts +0 -405
- package/src/cli/status.ts +0 -13
- package/src/commands/common.ts +0 -171
- package/src/commands/diagnose.ts +0 -17
- package/src/commands/index.ts +0 -9
- package/src/commands/logs-formatter.ts +0 -201
- package/src/commands/logs-reader.ts +0 -171
- package/src/commands/logs.ts +0 -103
- package/src/commands/precheck.ts +0 -86
- package/src/commands/runs.ts +0 -220
- package/src/commands/unlock.ts +0 -96
- package/src/config/defaults.ts +0 -218
- package/src/config/index.ts +0 -22
- package/src/config/loader.ts +0 -143
- package/src/config/merge.ts +0 -106
- package/src/config/merger.ts +0 -147
- package/src/config/path-security.ts +0 -121
- package/src/config/paths.ts +0 -27
- package/src/config/permissions.ts +0 -63
- package/src/config/runtime-types.ts +0 -522
- package/src/config/schema-types.ts +0 -53
- package/src/config/schema.ts +0 -60
- package/src/config/schemas.ts +0 -426
- package/src/config/test-strategy.ts +0 -71
- package/src/config/types.ts +0 -57
- package/src/config/validate.ts +0 -103
- package/src/constitution/generator.ts +0 -158
- package/src/constitution/generators/aider.ts +0 -41
- package/src/constitution/generators/claude.ts +0 -35
- package/src/constitution/generators/cursor.ts +0 -36
- package/src/constitution/generators/opencode.ts +0 -38
- package/src/constitution/generators/types.ts +0 -33
- package/src/constitution/generators/windsurf.ts +0 -36
- package/src/constitution/index.ts +0 -11
- package/src/constitution/loader.ts +0 -121
- package/src/constitution/types.ts +0 -31
- package/src/context/auto-detect.ts +0 -228
- package/src/context/builder.ts +0 -299
- package/src/context/elements.ts +0 -122
- package/src/context/formatter.ts +0 -107
- package/src/context/generator.ts +0 -343
- package/src/context/generators/aider.ts +0 -34
- package/src/context/generators/claude.ts +0 -28
- package/src/context/generators/codex.ts +0 -28
- package/src/context/generators/cursor.ts +0 -28
- package/src/context/generators/gemini.ts +0 -28
- package/src/context/generators/opencode.ts +0 -30
- package/src/context/generators/windsurf.ts +0 -28
- package/src/context/greenfield.ts +0 -114
- package/src/context/index.ts +0 -34
- package/src/context/injector.ts +0 -279
- package/src/context/parent-context.ts +0 -39
- package/src/context/test-scanner.ts +0 -370
- package/src/context/types.ts +0 -98
- package/src/decompose/apply.ts +0 -50
- package/src/decompose/builder.ts +0 -181
- package/src/decompose/index.ts +0 -8
- package/src/decompose/sections/codebase.ts +0 -26
- package/src/decompose/sections/constraints.ts +0 -32
- package/src/decompose/sections/index.ts +0 -4
- package/src/decompose/sections/sibling-stories.ts +0 -25
- package/src/decompose/sections/target-story.ts +0 -31
- package/src/decompose/types.ts +0 -55
- package/src/decompose/validators/complexity.ts +0 -45
- package/src/decompose/validators/coverage.ts +0 -134
- package/src/decompose/validators/dependency.ts +0 -91
- package/src/decompose/validators/index.ts +0 -35
- package/src/decompose/validators/overlap.ts +0 -128
- package/src/errors.ts +0 -67
- package/src/execution/batching.ts +0 -157
- package/src/execution/crash-heartbeat.ts +0 -77
- package/src/execution/crash-recovery.ts +0 -79
- package/src/execution/crash-signals.ts +0 -165
- package/src/execution/crash-writer.ts +0 -154
- package/src/execution/deferred-review.ts +0 -105
- package/src/execution/dry-run.ts +0 -81
- package/src/execution/escalation/escalation.ts +0 -46
- package/src/execution/escalation/index.ts +0 -13
- package/src/execution/escalation/tier-escalation.ts +0 -346
- package/src/execution/escalation/tier-outcome.ts +0 -143
- package/src/execution/executor-types.ts +0 -73
- package/src/execution/helpers.ts +0 -38
- package/src/execution/index.ts +0 -27
- package/src/execution/iteration-runner.ts +0 -160
- package/src/execution/lifecycle/acceptance-loop.ts +0 -309
- package/src/execution/lifecycle/headless-formatter.ts +0 -83
- package/src/execution/lifecycle/index.ts +0 -11
- package/src/execution/lifecycle/parallel-lifecycle.ts +0 -101
- package/src/execution/lifecycle/precheck-runner.ts +0 -140
- package/src/execution/lifecycle/run-cleanup.ts +0 -81
- package/src/execution/lifecycle/run-completion.ts +0 -247
- package/src/execution/lifecycle/run-initialization.ts +0 -187
- package/src/execution/lifecycle/run-regression.ts +0 -305
- package/src/execution/lifecycle/run-setup.ts +0 -240
- package/src/execution/lifecycle/story-size-prompts.ts +0 -123
- package/src/execution/lock.ts +0 -129
- package/src/execution/parallel-coordinator.ts +0 -281
- package/src/execution/parallel-executor-rectification-pass.ts +0 -117
- package/src/execution/parallel-executor-rectify.ts +0 -136
- package/src/execution/parallel-executor.ts +0 -330
- package/src/execution/parallel-worker.ts +0 -149
- package/src/execution/parallel.ts +0 -13
- package/src/execution/pid-registry.ts +0 -275
- package/src/execution/pipeline-result-handler.ts +0 -221
- package/src/execution/progress.ts +0 -27
- package/src/execution/queue-handler.ts +0 -109
- package/src/execution/runner-completion.ts +0 -171
- package/src/execution/runner-execution.ts +0 -243
- package/src/execution/runner-setup.ts +0 -86
- package/src/execution/runner.ts +0 -265
- package/src/execution/sequential-executor.ts +0 -219
- package/src/execution/status-file.ts +0 -264
- package/src/execution/status-writer.ts +0 -181
- package/src/execution/story-context.ts +0 -266
- package/src/execution/story-selector.ts +0 -76
- package/src/execution/test-output-parser.ts +0 -14
- package/src/execution/timeout-handler.ts +0 -100
- package/src/hooks/index.ts +0 -2
- package/src/hooks/runner.ts +0 -280
- package/src/hooks/types.ts +0 -79
- package/src/interaction/chain.ts +0 -170
- package/src/interaction/index.ts +0 -61
- package/src/interaction/init.ts +0 -84
- package/src/interaction/plugins/auto.ts +0 -243
- package/src/interaction/plugins/cli.ts +0 -300
- package/src/interaction/plugins/telegram.ts +0 -384
- package/src/interaction/plugins/webhook.ts +0 -286
- package/src/interaction/state.ts +0 -171
- package/src/interaction/triggers.ts +0 -250
- package/src/interaction/types.ts +0 -170
- package/src/logger/formatters.ts +0 -84
- package/src/logger/index.ts +0 -16
- package/src/logger/logger.ts +0 -296
- package/src/logger/types.ts +0 -48
- package/src/logging/formatter.ts +0 -355
- package/src/logging/index.ts +0 -22
- package/src/logging/types.ts +0 -93
- package/src/metrics/aggregator.ts +0 -191
- package/src/metrics/index.ts +0 -14
- package/src/metrics/tracker.ts +0 -200
- package/src/metrics/types.ts +0 -115
- package/src/optimizer/index.ts +0 -63
- package/src/optimizer/noop.optimizer.ts +0 -24
- package/src/optimizer/rule-based.optimizer.ts +0 -248
- package/src/optimizer/types.ts +0 -53
- package/src/pipeline/event-bus.ts +0 -297
- package/src/pipeline/events.ts +0 -130
- package/src/pipeline/index.ts +0 -19
- package/src/pipeline/runner.ts +0 -149
- package/src/pipeline/stages/acceptance-setup.ts +0 -144
- package/src/pipeline/stages/acceptance.ts +0 -215
- package/src/pipeline/stages/autofix.ts +0 -262
- package/src/pipeline/stages/completion.ts +0 -110
- package/src/pipeline/stages/constitution.ts +0 -63
- package/src/pipeline/stages/context.ts +0 -122
- package/src/pipeline/stages/execution.ts +0 -359
- package/src/pipeline/stages/index.ts +0 -86
- package/src/pipeline/stages/optimizer.ts +0 -74
- package/src/pipeline/stages/prompt.ts +0 -79
- package/src/pipeline/stages/queue-check.ts +0 -103
- package/src/pipeline/stages/rectify.ts +0 -101
- package/src/pipeline/stages/regression.ts +0 -99
- package/src/pipeline/stages/review.ts +0 -94
- package/src/pipeline/stages/routing.ts +0 -276
- package/src/pipeline/stages/verify.ts +0 -286
- package/src/pipeline/subscribers/events-writer.ts +0 -135
- package/src/pipeline/subscribers/hooks.ts +0 -179
- package/src/pipeline/subscribers/interaction.ts +0 -103
- package/src/pipeline/subscribers/registry.ts +0 -73
- package/src/pipeline/subscribers/reporters.ts +0 -174
- package/src/pipeline/types.ts +0 -220
- package/src/plugins/extensions.ts +0 -225
- package/src/plugins/index.ts +0 -33
- package/src/plugins/loader.ts +0 -352
- package/src/plugins/plugin-logger.ts +0 -41
- package/src/plugins/registry.ts +0 -168
- package/src/plugins/types.ts +0 -206
- package/src/plugins/validator.ts +0 -352
- package/src/prd/index.ts +0 -220
- package/src/prd/schema.ts +0 -268
- package/src/prd/types.ts +0 -273
- package/src/prd/validate.ts +0 -41
- package/src/precheck/checks-agents.ts +0 -63
- package/src/precheck/checks-blockers.ts +0 -23
- package/src/precheck/checks-cli.ts +0 -68
- package/src/precheck/checks-config.ts +0 -102
- package/src/precheck/checks-git.ts +0 -117
- package/src/precheck/checks-system.ts +0 -101
- package/src/precheck/checks-warnings.ts +0 -221
- package/src/precheck/checks.ts +0 -36
- package/src/precheck/index.ts +0 -374
- package/src/precheck/story-size-gate.ts +0 -144
- package/src/precheck/types.ts +0 -31
- package/src/prompts/builder.ts +0 -166
- package/src/prompts/index.ts +0 -2
- package/src/prompts/loader.ts +0 -43
- package/src/prompts/sections/conventions.ts +0 -19
- package/src/prompts/sections/hermetic.ts +0 -41
- package/src/prompts/sections/index.ts +0 -12
- package/src/prompts/sections/isolation.ts +0 -70
- package/src/prompts/sections/role-task.ts +0 -182
- package/src/prompts/sections/story.ts +0 -55
- package/src/prompts/sections/verdict.ts +0 -70
- package/src/prompts/types.ts +0 -21
- package/src/queue/index.ts +0 -2
- package/src/queue/manager.ts +0 -254
- package/src/queue/types.ts +0 -54
- package/src/review/index.ts +0 -8
- package/src/review/orchestrator.ts +0 -154
- package/src/review/runner.ts +0 -303
- package/src/review/types.ts +0 -70
- package/src/routing/batch-route.ts +0 -35
- package/src/routing/builder.ts +0 -81
- package/src/routing/chain.ts +0 -75
- package/src/routing/content-hash.ts +0 -25
- package/src/routing/index.ts +0 -20
- package/src/routing/loader.ts +0 -62
- package/src/routing/router.ts +0 -305
- package/src/routing/strategies/adaptive.ts +0 -215
- package/src/routing/strategies/index.ts +0 -8
- package/src/routing/strategies/keyword.ts +0 -180
- package/src/routing/strategies/llm-prompts.ts +0 -224
- package/src/routing/strategies/llm.ts +0 -320
- package/src/routing/strategies/manual.ts +0 -50
- package/src/routing/strategy.ts +0 -102
- package/src/tdd/cleanup.ts +0 -120
- package/src/tdd/index.ts +0 -22
- package/src/tdd/isolation.ts +0 -117
- package/src/tdd/orchestrator.ts +0 -406
- package/src/tdd/prompts.ts +0 -40
- package/src/tdd/rectification-gate.ts +0 -274
- package/src/tdd/session-runner.ts +0 -263
- package/src/tdd/types.ts +0 -84
- package/src/tdd/verdict-reader.ts +0 -266
- package/src/tdd/verdict.ts +0 -152
- package/src/tui/App.tsx +0 -265
- package/src/tui/components/AgentPanel.tsx +0 -75
- package/src/tui/components/CostOverlay.tsx +0 -118
- package/src/tui/components/HelpOverlay.tsx +0 -107
- package/src/tui/components/StatusBar.tsx +0 -63
- package/src/tui/components/StoriesPanel.tsx +0 -177
- package/src/tui/hooks/useKeyboard.ts +0 -142
- package/src/tui/hooks/useLayout.ts +0 -137
- package/src/tui/hooks/usePipelineEvents.ts +0 -183
- package/src/tui/hooks/usePty.ts +0 -189
- package/src/tui/index.tsx +0 -38
- package/src/tui/types.ts +0 -76
- package/src/utils/errors.ts +0 -12
- package/src/utils/git.ts +0 -245
- package/src/utils/json-file.ts +0 -72
- package/src/utils/log-test-output.ts +0 -25
- package/src/utils/path-security.ts +0 -73
- package/src/utils/queue-writer.ts +0 -54
- package/src/verification/crash-detector.ts +0 -34
- package/src/verification/executor.ts +0 -250
- package/src/verification/index.ts +0 -12
- package/src/verification/orchestrator-types.ts +0 -154
- package/src/verification/orchestrator.ts +0 -76
- package/src/verification/parser.ts +0 -220
- package/src/verification/rectification-loop.ts +0 -172
- package/src/verification/rectification.ts +0 -108
- package/src/verification/runners.ts +0 -129
- package/src/verification/smart-runner.ts +0 -307
- package/src/verification/strategies/acceptance.ts +0 -136
- package/src/verification/strategies/regression.ts +0 -90
- package/src/verification/strategies/scoped.ts +0 -154
- package/src/verification/types.ts +0 -117
- package/src/version.ts +0 -40
- package/src/worktree/dispatcher.ts +0 -6
- package/src/worktree/index.ts +0 -2
- package/src/worktree/manager.ts +0 -193
- package/src/worktree/merge.ts +0 -302
- package/src/worktree/types.ts +0 -4
package/src/logging/formatter.ts
DELETED
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Human-friendly logging formatter with verbosity levels
|
|
3
|
-
*
|
|
4
|
-
* Transforms JSONL log entries into readable output with emoji indicators
|
|
5
|
-
* and supports multiple verbosity modes: quiet, normal, verbose, json
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import chalk from "chalk";
|
|
9
|
-
import type { LogEntry } from "../logger/types.js";
|
|
10
|
-
import { EMOJI, type FormatterOptions, type RunSummary } from "./types.js";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Formatted output entry
|
|
14
|
-
*/
|
|
15
|
-
export interface FormattedEntry {
|
|
16
|
-
/** Formatted string ready for console output */
|
|
17
|
-
output: string;
|
|
18
|
-
/** Whether this entry should be shown in the current verbosity mode */
|
|
19
|
-
shouldDisplay: boolean;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Format a timestamp to local timezone HH:MM:SS
|
|
24
|
-
*/
|
|
25
|
-
export function formatTimestamp(isoTimestamp: string): string {
|
|
26
|
-
const date = new Date(isoTimestamp);
|
|
27
|
-
return date.toLocaleTimeString("en-US", {
|
|
28
|
-
hour12: false,
|
|
29
|
-
hour: "2-digit",
|
|
30
|
-
minute: "2-digit",
|
|
31
|
-
second: "2-digit",
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Format duration in milliseconds to human-readable format
|
|
37
|
-
*/
|
|
38
|
-
export function formatDuration(durationMs: number): string {
|
|
39
|
-
if (durationMs < 1000) {
|
|
40
|
-
return `${durationMs}ms`;
|
|
41
|
-
}
|
|
42
|
-
if (durationMs < 60000) {
|
|
43
|
-
return `${(durationMs / 1000).toFixed(1)}s`;
|
|
44
|
-
}
|
|
45
|
-
const minutes = Math.floor(durationMs / 60000);
|
|
46
|
-
const seconds = Math.floor((durationMs % 60000) / 1000);
|
|
47
|
-
return `${minutes}m ${seconds}s`;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Format cost in dollars
|
|
52
|
-
*/
|
|
53
|
-
export function formatCost(cost: number): string {
|
|
54
|
-
return `$${cost.toFixed(4)}`;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Get emoji for stage name
|
|
59
|
-
*/
|
|
60
|
-
function getStageEmoji(stage: string): string {
|
|
61
|
-
if (stage.includes("routing")) return EMOJI.routing;
|
|
62
|
-
if (stage.includes("execution") || stage.includes("agent")) return EMOJI.execution;
|
|
63
|
-
if (stage.includes("review")) return EMOJI.review;
|
|
64
|
-
if (stage.includes("tdd")) return EMOJI.tdd;
|
|
65
|
-
return EMOJI.info;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Check if entry should be displayed based on verbosity mode
|
|
70
|
-
*/
|
|
71
|
-
function shouldDisplay(entry: LogEntry, mode: string): boolean {
|
|
72
|
-
if (mode === "json") return true;
|
|
73
|
-
if (mode === "quiet") {
|
|
74
|
-
// Only show critical events: run start/end, story pass/fail
|
|
75
|
-
return (
|
|
76
|
-
entry.stage === "run.start" ||
|
|
77
|
-
entry.stage === "run.end" ||
|
|
78
|
-
entry.stage === "story.complete" ||
|
|
79
|
-
entry.level === "error"
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
if (mode === "verbose") return true;
|
|
83
|
-
|
|
84
|
-
// Normal mode: filter out debug logs
|
|
85
|
-
return entry.level !== "debug";
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Format a log entry for human-readable output
|
|
90
|
-
*
|
|
91
|
-
* Supports different verbosity modes and styling options
|
|
92
|
-
*/
|
|
93
|
-
export function formatLogEntry(entry: LogEntry, options: FormatterOptions): FormattedEntry {
|
|
94
|
-
const { mode, useColor = true } = options;
|
|
95
|
-
|
|
96
|
-
// JSON mode: pass through raw JSONL
|
|
97
|
-
if (mode === "json") {
|
|
98
|
-
return {
|
|
99
|
-
output: JSON.stringify(entry),
|
|
100
|
-
shouldDisplay: true,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Check if should display based on mode
|
|
105
|
-
if (!shouldDisplay(entry, mode)) {
|
|
106
|
-
return {
|
|
107
|
-
output: "",
|
|
108
|
-
shouldDisplay: false,
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const timestamp = formatTimestamp(entry.timestamp);
|
|
113
|
-
const colorize = useColor ? chalk : createNoopChalk();
|
|
114
|
-
|
|
115
|
-
// Handle special stages with custom formatting
|
|
116
|
-
if (entry.stage === "run.start") {
|
|
117
|
-
return formatRunStart(entry, colorize, timestamp, mode);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (entry.stage === "story.start" || entry.stage === "iteration.start") {
|
|
121
|
-
return formatStoryStart(entry, colorize, timestamp, mode);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (entry.stage === "story.complete" || entry.stage === "agent.complete") {
|
|
125
|
-
return formatStoryComplete(entry, colorize, timestamp, mode);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (entry.stage.includes("tdd") && entry.message.startsWith("→ Session:")) {
|
|
129
|
-
return formatTDDSession(entry, colorize, timestamp, mode);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Default formatting for other entries
|
|
133
|
-
return formatDefault(entry, colorize, timestamp, mode);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Format run start event
|
|
138
|
-
*/
|
|
139
|
-
function formatRunStart(entry: LogEntry, c: ChalkLike, timestamp: string, mode: string): FormattedEntry {
|
|
140
|
-
const data = entry.data as Record<string, unknown>;
|
|
141
|
-
const lines: string[] = [];
|
|
142
|
-
|
|
143
|
-
lines.push("");
|
|
144
|
-
lines.push(c.bold(c.blue("═".repeat(60))));
|
|
145
|
-
lines.push(c.bold(c.blue(` ${EMOJI.storyStart} NAX RUN STARTED`)));
|
|
146
|
-
lines.push(c.blue("═".repeat(60)));
|
|
147
|
-
lines.push(` ${c.gray("Time:")} ${timestamp}`);
|
|
148
|
-
lines.push(` ${c.gray("Feature:")} ${c.cyan(String(data.feature || "unknown"))}`);
|
|
149
|
-
lines.push(` ${c.gray("Run ID:")} ${c.dim(String(data.runId || "unknown"))}`);
|
|
150
|
-
lines.push(` ${c.gray("Workdir:")} ${c.dim(String(data.workdir || "."))}`);
|
|
151
|
-
lines.push(c.blue("═".repeat(60)));
|
|
152
|
-
lines.push("");
|
|
153
|
-
|
|
154
|
-
return {
|
|
155
|
-
output: lines.join("\n"),
|
|
156
|
-
shouldDisplay: true,
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Format story start event
|
|
162
|
-
*/
|
|
163
|
-
function formatStoryStart(entry: LogEntry, c: ChalkLike, timestamp: string, mode: string): FormattedEntry {
|
|
164
|
-
const data = entry.data as Record<string, unknown>;
|
|
165
|
-
const storyId = String(data.storyId || entry.storyId || "unknown");
|
|
166
|
-
const title = String(data.storyTitle || data.title || "Untitled story");
|
|
167
|
-
const complexity = typeof data.complexity === "string" ? data.complexity : "unknown";
|
|
168
|
-
const tier = typeof data.modelTier === "string" ? data.modelTier : "unknown";
|
|
169
|
-
const attempt = typeof data.attempt === "number" ? data.attempt : 1;
|
|
170
|
-
|
|
171
|
-
const lines: string[] = [];
|
|
172
|
-
lines.push("");
|
|
173
|
-
lines.push(c.bold(`${EMOJI.storyStart} ${c.cyan(storyId)}: ${title}`));
|
|
174
|
-
|
|
175
|
-
if (mode === "verbose") {
|
|
176
|
-
lines.push(` ${c.gray("├─")} Complexity: ${c.yellow(complexity)}`);
|
|
177
|
-
lines.push(` ${c.gray("├─")} Tier: ${c.magenta(tier)}`);
|
|
178
|
-
if (attempt > 1) {
|
|
179
|
-
lines.push(` ${c.gray("└─")} Attempt: ${c.yellow(`#${attempt}`)} ${EMOJI.retry}`);
|
|
180
|
-
} else {
|
|
181
|
-
lines.push(` ${c.gray("└─")} Status: ${c.green("starting")}`);
|
|
182
|
-
}
|
|
183
|
-
} else {
|
|
184
|
-
const metadata = [complexity, tier];
|
|
185
|
-
if (attempt > 1) metadata.push(`attempt #${attempt} ${EMOJI.retry}`);
|
|
186
|
-
lines.push(` ${c.gray(metadata.join(" • "))}`);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return {
|
|
190
|
-
output: lines.join("\n"),
|
|
191
|
-
shouldDisplay: true,
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Format story completion event
|
|
197
|
-
*/
|
|
198
|
-
function formatStoryComplete(entry: LogEntry, c: ChalkLike, timestamp: string, mode: string): FormattedEntry {
|
|
199
|
-
const data = entry.data as Record<string, unknown>;
|
|
200
|
-
const storyId = String(data.storyId || entry.storyId || "unknown");
|
|
201
|
-
const success = data.success ?? true;
|
|
202
|
-
const cost =
|
|
203
|
-
typeof data.cost === "number" ? data.cost : typeof data.estimatedCost === "number" ? data.estimatedCost : 0;
|
|
204
|
-
const duration = typeof data.durationMs === "number" ? data.durationMs : 0;
|
|
205
|
-
const action = data.finalAction || data.action;
|
|
206
|
-
|
|
207
|
-
const emoji = success ? EMOJI.success : action === "escalate" ? EMOJI.retry : EMOJI.failure;
|
|
208
|
-
const statusColor = success ? c.green : action === "escalate" ? c.yellow : c.red;
|
|
209
|
-
const status = success ? "PASSED" : action === "escalate" ? "ESCALATED" : "FAILED";
|
|
210
|
-
|
|
211
|
-
const lines: string[] = [];
|
|
212
|
-
lines.push(statusColor(` ${emoji} ${c.bold(storyId)}: ${status}`));
|
|
213
|
-
|
|
214
|
-
if (mode === "verbose" || mode === "normal") {
|
|
215
|
-
const metadata: string[] = [];
|
|
216
|
-
if (cost > 0) metadata.push(`${EMOJI.cost} ${formatCost(cost)}`);
|
|
217
|
-
if (duration > 0) metadata.push(`${EMOJI.duration} ${formatDuration(duration)}`);
|
|
218
|
-
if (metadata.length > 0) {
|
|
219
|
-
lines.push(` ${c.gray(metadata.join(" "))}`);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
if (mode === "verbose" && data.reason) {
|
|
224
|
-
lines.push(` ${c.gray(`Reason: ${data.reason}`)}`);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
lines.push("");
|
|
228
|
-
|
|
229
|
-
return {
|
|
230
|
-
output: lines.join("\n"),
|
|
231
|
-
shouldDisplay: true,
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Format TDD session start
|
|
237
|
-
*/
|
|
238
|
-
function formatTDDSession(entry: LogEntry, c: ChalkLike, timestamp: string, mode: string): FormattedEntry {
|
|
239
|
-
if (mode === "quiet") {
|
|
240
|
-
return { output: "", shouldDisplay: false };
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const data = entry.data as Record<string, unknown>;
|
|
244
|
-
const role = typeof data.role === "string" ? data.role : "unknown";
|
|
245
|
-
const roleLabel = role.replace(/-/g, " ").replace(/\b\w/g, (l: string) => l.toUpperCase());
|
|
246
|
-
|
|
247
|
-
return {
|
|
248
|
-
output: ` ${c.gray("│")} ${EMOJI.tdd} ${c.cyan(roleLabel)}`,
|
|
249
|
-
shouldDisplay: true,
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* Format default log entry
|
|
255
|
-
*/
|
|
256
|
-
function formatDefault(entry: LogEntry, c: ChalkLike, timestamp: string, mode: string): FormattedEntry {
|
|
257
|
-
const levelEmoji = entry.level === "error" ? EMOJI.failure : entry.level === "warn" ? EMOJI.warning : EMOJI.info;
|
|
258
|
-
const levelColor = entry.level === "error" ? c.red : entry.level === "warn" ? c.yellow : c.gray;
|
|
259
|
-
const stageEmoji = getStageEmoji(entry.stage);
|
|
260
|
-
|
|
261
|
-
const parts = [c.gray(`[${timestamp}]`), levelColor(`${levelEmoji} ${entry.stage}`)];
|
|
262
|
-
|
|
263
|
-
if (entry.storyId) {
|
|
264
|
-
parts.push(c.dim(`[${entry.storyId}]`));
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
parts.push(entry.message);
|
|
268
|
-
|
|
269
|
-
let output = parts.join(" ");
|
|
270
|
-
|
|
271
|
-
// Include data in verbose mode
|
|
272
|
-
if (mode === "verbose" && entry.data && Object.keys(entry.data).length > 0) {
|
|
273
|
-
output += `\n${c.gray(JSON.stringify(entry.data, null, 2))}`;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
return {
|
|
277
|
-
output,
|
|
278
|
-
shouldDisplay: true,
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Format run summary footer
|
|
284
|
-
*/
|
|
285
|
-
export function formatRunSummary(summary: RunSummary, options: FormatterOptions): string {
|
|
286
|
-
const { mode, useColor = true } = options;
|
|
287
|
-
|
|
288
|
-
if (mode === "json") {
|
|
289
|
-
return JSON.stringify(summary);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
const c = useColor ? chalk : createNoopChalk();
|
|
293
|
-
const lines: string[] = [];
|
|
294
|
-
|
|
295
|
-
lines.push("");
|
|
296
|
-
lines.push(c.blue("═".repeat(60)));
|
|
297
|
-
lines.push(c.bold(c.blue(` ${EMOJI.storyComplete} RUN SUMMARY`)));
|
|
298
|
-
lines.push(c.blue("═".repeat(60)));
|
|
299
|
-
|
|
300
|
-
const successRate = summary.total > 0 ? ((summary.passed / summary.total) * 100).toFixed(1) : "0.0";
|
|
301
|
-
const statusColor = summary.failed === 0 ? c.green : summary.passed > summary.failed ? c.yellow : c.red;
|
|
302
|
-
|
|
303
|
-
lines.push(` ${c.gray("Total:")} ${c.bold(summary.total.toString())}`);
|
|
304
|
-
lines.push(` ${c.green(`${EMOJI.success} Passed:`)} ${c.bold(summary.passed.toString())}`);
|
|
305
|
-
|
|
306
|
-
if (summary.failed > 0) {
|
|
307
|
-
lines.push(` ${c.red(`${EMOJI.failure} Failed:`)} ${c.bold(summary.failed.toString())}`);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
if (summary.skipped > 0) {
|
|
311
|
-
lines.push(` ${c.yellow(`${EMOJI.skip} Skipped:`)} ${c.bold(summary.skipped.toString())}`);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
lines.push(` ${c.gray("Success:")} ${statusColor(c.bold(`${successRate}%`))}`);
|
|
315
|
-
lines.push(c.blue("─".repeat(60)));
|
|
316
|
-
lines.push(` ${EMOJI.duration} Duration: ${c.bold(formatDuration(summary.durationMs))}`);
|
|
317
|
-
lines.push(` ${EMOJI.cost} Cost: ${c.bold(formatCost(summary.totalCost))}`);
|
|
318
|
-
lines.push(c.blue("═".repeat(60)));
|
|
319
|
-
lines.push("");
|
|
320
|
-
|
|
321
|
-
return lines.join("\n");
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
/**
|
|
325
|
-
* Chalk-like interface for no-op mode (no colors)
|
|
326
|
-
*/
|
|
327
|
-
interface ChalkLike {
|
|
328
|
-
bold: (s: string) => string;
|
|
329
|
-
dim: (s: string) => string;
|
|
330
|
-
gray: (s: string) => string;
|
|
331
|
-
red: (s: string) => string;
|
|
332
|
-
green: (s: string) => string;
|
|
333
|
-
yellow: (s: string) => string;
|
|
334
|
-
blue: (s: string) => string;
|
|
335
|
-
magenta: (s: string) => string;
|
|
336
|
-
cyan: (s: string) => string;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* Create a no-op chalk instance (returns strings unchanged)
|
|
341
|
-
*/
|
|
342
|
-
function createNoopChalk(): ChalkLike {
|
|
343
|
-
const noop = (s: string) => s;
|
|
344
|
-
return {
|
|
345
|
-
bold: noop,
|
|
346
|
-
dim: noop,
|
|
347
|
-
gray: noop,
|
|
348
|
-
red: noop,
|
|
349
|
-
green: noop,
|
|
350
|
-
yellow: noop,
|
|
351
|
-
blue: noop,
|
|
352
|
-
magenta: noop,
|
|
353
|
-
cyan: noop,
|
|
354
|
-
};
|
|
355
|
-
}
|
package/src/logging/index.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Logging formatter module
|
|
3
|
-
*
|
|
4
|
-
* Provides human-friendly log formatting with multiple verbosity levels
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export {
|
|
8
|
-
formatLogEntry,
|
|
9
|
-
formatRunSummary,
|
|
10
|
-
formatTimestamp,
|
|
11
|
-
formatDuration,
|
|
12
|
-
formatCost,
|
|
13
|
-
type FormattedEntry,
|
|
14
|
-
} from "./formatter.js";
|
|
15
|
-
export {
|
|
16
|
-
EMOJI,
|
|
17
|
-
type VerbosityMode,
|
|
18
|
-
type FormatterOptions,
|
|
19
|
-
type RunSummary,
|
|
20
|
-
type StoryStartData,
|
|
21
|
-
type StageResultData,
|
|
22
|
-
} from "./types.js";
|
package/src/logging/types.ts
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Logging formatter types for human-readable output
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { LogEntry } from "../logger/types.js";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Verbosity mode for log formatting
|
|
9
|
-
*/
|
|
10
|
-
export type VerbosityMode = "quiet" | "normal" | "verbose" | "json";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Emoji indicators for different log events
|
|
14
|
-
*/
|
|
15
|
-
export const EMOJI = {
|
|
16
|
-
// Status indicators
|
|
17
|
-
success: "✓",
|
|
18
|
-
failure: "✗",
|
|
19
|
-
warning: "⚠",
|
|
20
|
-
info: "ℹ",
|
|
21
|
-
skip: "⊘",
|
|
22
|
-
|
|
23
|
-
// Stage/process indicators
|
|
24
|
-
routing: "🎯",
|
|
25
|
-
execution: "⚙️",
|
|
26
|
-
review: "🔍",
|
|
27
|
-
tdd: "🔄",
|
|
28
|
-
agent: "🤖",
|
|
29
|
-
cost: "💰",
|
|
30
|
-
duration: "⏱️",
|
|
31
|
-
|
|
32
|
-
// Story progress
|
|
33
|
-
storyStart: "▶",
|
|
34
|
-
storyComplete: "●",
|
|
35
|
-
retry: "↻",
|
|
36
|
-
} as const;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Run summary statistics
|
|
40
|
-
*/
|
|
41
|
-
export interface RunSummary {
|
|
42
|
-
/** Total stories in run */
|
|
43
|
-
total: number;
|
|
44
|
-
/** Stories that passed */
|
|
45
|
-
passed: number;
|
|
46
|
-
/** Stories that failed */
|
|
47
|
-
failed: number;
|
|
48
|
-
/** Stories that were skipped */
|
|
49
|
-
skipped: number;
|
|
50
|
-
/** Total run duration in milliseconds */
|
|
51
|
-
durationMs: number;
|
|
52
|
-
/** Total cost in dollars */
|
|
53
|
-
totalCost: number;
|
|
54
|
-
/** Run start timestamp */
|
|
55
|
-
startedAt: string;
|
|
56
|
-
/** Run completion timestamp */
|
|
57
|
-
completedAt?: string;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Story start event data
|
|
62
|
-
*/
|
|
63
|
-
export interface StoryStartData {
|
|
64
|
-
storyId: string;
|
|
65
|
-
title: string;
|
|
66
|
-
complexity?: string;
|
|
67
|
-
modelTier?: string;
|
|
68
|
-
attempt?: number;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Stage result event data
|
|
73
|
-
*/
|
|
74
|
-
export interface StageResultData {
|
|
75
|
-
stage: string;
|
|
76
|
-
success: boolean;
|
|
77
|
-
action?: "continue" | "skip" | "fail" | "escalate" | "pause";
|
|
78
|
-
reason?: string;
|
|
79
|
-
cost?: number;
|
|
80
|
-
durationMs?: number;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Formatter options
|
|
85
|
-
*/
|
|
86
|
-
export interface FormatterOptions {
|
|
87
|
-
/** Verbosity mode */
|
|
88
|
-
mode: VerbosityMode;
|
|
89
|
-
/** Whether to use color/emoji (default: true) */
|
|
90
|
-
useColor?: boolean;
|
|
91
|
-
/** Timezone for timestamp formatting (default: system timezone) */
|
|
92
|
-
timezone?: string;
|
|
93
|
-
}
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Metrics Aggregator
|
|
3
|
-
*
|
|
4
|
-
* Calculates aggregate metrics across all runs.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { AggregateMetrics, RunMetrics, StoryMetrics } from "./types";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Calculate aggregate metrics across all runs.
|
|
11
|
-
*
|
|
12
|
-
* Analyzes historical data to compute:
|
|
13
|
-
* - Overall success rates
|
|
14
|
-
* - Per-model efficiency
|
|
15
|
-
* - Complexity prediction accuracy
|
|
16
|
-
* - Cost statistics
|
|
17
|
-
*
|
|
18
|
-
* @param runs - Array of all historical run metrics
|
|
19
|
-
* @returns Aggregate metrics
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```ts
|
|
23
|
-
* const runs = await loadRunMetrics(workdir);
|
|
24
|
-
* const aggregate = calculateAggregateMetrics(runs);
|
|
25
|
-
* console.log(`First pass rate: ${(aggregate.firstPassRate * 100).toFixed(1)}%`);
|
|
26
|
-
* console.log(`Avg cost per story: $${aggregate.avgCostPerStory.toFixed(4)}`);
|
|
27
|
-
* ```
|
|
28
|
-
*/
|
|
29
|
-
export function calculateAggregateMetrics(runs: RunMetrics[]): AggregateMetrics {
|
|
30
|
-
if (runs.length === 0) {
|
|
31
|
-
return {
|
|
32
|
-
totalRuns: 0,
|
|
33
|
-
totalCost: 0,
|
|
34
|
-
totalStories: 0,
|
|
35
|
-
firstPassRate: 0,
|
|
36
|
-
escalationRate: 0,
|
|
37
|
-
avgCostPerStory: 0,
|
|
38
|
-
avgCostPerFeature: 0,
|
|
39
|
-
modelEfficiency: {},
|
|
40
|
-
complexityAccuracy: {},
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Flatten all story metrics
|
|
45
|
-
const allStories: StoryMetrics[] = runs.flatMap((run) => run.stories);
|
|
46
|
-
|
|
47
|
-
const totalRuns = runs.length;
|
|
48
|
-
const totalCost = runs.reduce((sum, run) => sum + run.totalCost, 0);
|
|
49
|
-
const totalStories = allStories.length;
|
|
50
|
-
|
|
51
|
-
// Calculate first pass rate
|
|
52
|
-
const firstPassSuccesses = allStories.filter((s) => s.firstPassSuccess).length;
|
|
53
|
-
const firstPassRate = totalStories > 0 ? firstPassSuccesses / totalStories : 0;
|
|
54
|
-
|
|
55
|
-
// Calculate escalation rate (stories that needed more than 1 attempt)
|
|
56
|
-
const escalatedStories = allStories.filter((s) => s.attempts > 1).length;
|
|
57
|
-
const escalationRate = totalStories > 0 ? escalatedStories / totalStories : 0;
|
|
58
|
-
|
|
59
|
-
// Average costs
|
|
60
|
-
const avgCostPerStory = totalStories > 0 ? totalCost / totalStories : 0;
|
|
61
|
-
const avgCostPerFeature = totalRuns > 0 ? totalCost / totalRuns : 0;
|
|
62
|
-
|
|
63
|
-
// Per-model efficiency
|
|
64
|
-
const modelStats = new Map<
|
|
65
|
-
string,
|
|
66
|
-
{
|
|
67
|
-
attempts: number;
|
|
68
|
-
successes: number;
|
|
69
|
-
totalCost: number;
|
|
70
|
-
}
|
|
71
|
-
>();
|
|
72
|
-
|
|
73
|
-
for (const story of allStories) {
|
|
74
|
-
const modelKey = story.modelUsed;
|
|
75
|
-
const existing = modelStats.get(modelKey) || {
|
|
76
|
-
attempts: 0,
|
|
77
|
-
successes: 0,
|
|
78
|
-
totalCost: 0,
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
modelStats.set(modelKey, {
|
|
82
|
-
attempts: existing.attempts + story.attempts,
|
|
83
|
-
successes: existing.successes + (story.success ? 1 : 0),
|
|
84
|
-
totalCost: existing.totalCost + story.cost,
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const modelEfficiency: AggregateMetrics["modelEfficiency"] = {};
|
|
89
|
-
for (const [modelKey, stats] of modelStats) {
|
|
90
|
-
const passRate = stats.attempts > 0 ? stats.successes / stats.attempts : 0;
|
|
91
|
-
const avgCost = stats.successes > 0 ? stats.totalCost / stats.successes : 0;
|
|
92
|
-
|
|
93
|
-
modelEfficiency[modelKey] = {
|
|
94
|
-
attempts: stats.attempts,
|
|
95
|
-
successes: stats.successes,
|
|
96
|
-
passRate,
|
|
97
|
-
avgCost,
|
|
98
|
-
totalCost: stats.totalCost,
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Complexity prediction accuracy
|
|
103
|
-
const complexityStats = new Map<
|
|
104
|
-
string,
|
|
105
|
-
{
|
|
106
|
-
predicted: number;
|
|
107
|
-
tierCounts: Map<string, number>;
|
|
108
|
-
mismatches: number;
|
|
109
|
-
}
|
|
110
|
-
>();
|
|
111
|
-
|
|
112
|
-
for (const story of allStories) {
|
|
113
|
-
// Use initialComplexity (first-classify prediction) when available; fall back to complexity
|
|
114
|
-
const complexity = story.initialComplexity ?? story.complexity;
|
|
115
|
-
const existing = complexityStats.get(complexity) || {
|
|
116
|
-
predicted: 0,
|
|
117
|
-
tierCounts: new Map<string, number>(),
|
|
118
|
-
mismatches: 0,
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
existing.predicted += 1;
|
|
122
|
-
|
|
123
|
-
// Track which tier was actually used
|
|
124
|
-
const finalTier = story.finalTier;
|
|
125
|
-
existing.tierCounts.set(finalTier, (existing.tierCounts.get(finalTier) || 0) + 1);
|
|
126
|
-
|
|
127
|
-
// Count as mismatch if escalated (initial tier != final tier)
|
|
128
|
-
if (story.modelTier !== story.finalTier) {
|
|
129
|
-
existing.mismatches += 1;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
complexityStats.set(complexity, existing);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const complexityAccuracy: AggregateMetrics["complexityAccuracy"] = {};
|
|
136
|
-
for (const [complexity, stats] of complexityStats) {
|
|
137
|
-
// Find most common final tier
|
|
138
|
-
let maxCount = 0;
|
|
139
|
-
let mostCommonTier = "unknown";
|
|
140
|
-
for (const [tier, count] of stats.tierCounts) {
|
|
141
|
-
if (count > maxCount) {
|
|
142
|
-
maxCount = count;
|
|
143
|
-
mostCommonTier = tier;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
const mismatchRate = stats.predicted > 0 ? stats.mismatches / stats.predicted : 0;
|
|
148
|
-
|
|
149
|
-
complexityAccuracy[complexity] = {
|
|
150
|
-
predicted: stats.predicted,
|
|
151
|
-
actualTierUsed: mostCommonTier,
|
|
152
|
-
mismatchRate,
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return {
|
|
157
|
-
totalRuns,
|
|
158
|
-
totalCost,
|
|
159
|
-
totalStories,
|
|
160
|
-
firstPassRate,
|
|
161
|
-
escalationRate,
|
|
162
|
-
avgCostPerStory,
|
|
163
|
-
avgCostPerFeature,
|
|
164
|
-
modelEfficiency,
|
|
165
|
-
complexityAccuracy,
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Get the last run metrics from the list.
|
|
171
|
-
*
|
|
172
|
-
* @param runs - Array of all run metrics
|
|
173
|
-
* @returns Most recent run, or null if no runs
|
|
174
|
-
*
|
|
175
|
-
* @example
|
|
176
|
-
* ```ts
|
|
177
|
-
* const runs = await loadRunMetrics(workdir);
|
|
178
|
-
* const lastRun = getLastRun(runs);
|
|
179
|
-
* if (lastRun) {
|
|
180
|
-
* console.log(`Last run: ${lastRun.feature} (${lastRun.storiesCompleted}/${lastRun.totalStories} stories)`);
|
|
181
|
-
* }
|
|
182
|
-
* ```
|
|
183
|
-
*/
|
|
184
|
-
export function getLastRun(runs: RunMetrics[]): RunMetrics | null {
|
|
185
|
-
if (runs.length === 0) {
|
|
186
|
-
return null;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Runs are appended chronologically, so last element is most recent
|
|
190
|
-
return runs[runs.length - 1];
|
|
191
|
-
}
|
package/src/metrics/index.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Metrics Tracking
|
|
3
|
-
*
|
|
4
|
-
* Per-story and per-run cost tracking for data-driven routing optimization.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export type { StoryMetrics, RunMetrics, AggregateMetrics } from "./types";
|
|
8
|
-
export {
|
|
9
|
-
collectStoryMetrics,
|
|
10
|
-
collectBatchMetrics,
|
|
11
|
-
saveRunMetrics,
|
|
12
|
-
loadRunMetrics,
|
|
13
|
-
} from "./tracker";
|
|
14
|
-
export { calculateAggregateMetrics, getLastRun } from "./aggregator";
|