@nathapp/nax 0.50.3 → 0.51.2
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/README.md +177 -104
- package/dist/nax.js +417 -213
- 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
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Log formatting and display utilities
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { readdirSync } from "node:fs";
|
|
6
|
-
import { join } from "node:path";
|
|
7
|
-
import chalk from "chalk";
|
|
8
|
-
import type { LogEntry, LogLevel } from "../logger/types";
|
|
9
|
-
import { formatLogEntry, formatRunSummary } from "../logging/formatter";
|
|
10
|
-
import type { VerbosityMode } from "../logging/types";
|
|
11
|
-
import { extractRunSummary } from "./logs-reader";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Log level hierarchy for filtering
|
|
15
|
-
*/
|
|
16
|
-
const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {
|
|
17
|
-
debug: 0,
|
|
18
|
-
info: 1,
|
|
19
|
-
warn: 2,
|
|
20
|
-
error: 3,
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Display runs table
|
|
25
|
-
*/
|
|
26
|
-
export async function displayRunsList(runsDir: string): Promise<void> {
|
|
27
|
-
const files = readdirSync(runsDir)
|
|
28
|
-
.filter((f) => f.endsWith(".jsonl") && f !== "latest.jsonl")
|
|
29
|
-
.sort()
|
|
30
|
-
.reverse();
|
|
31
|
-
|
|
32
|
-
if (files.length === 0) {
|
|
33
|
-
console.log(chalk.dim("No runs found"));
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
console.log(chalk.bold("\nRuns:\n"));
|
|
38
|
-
console.log(chalk.gray(" Timestamp Stories Duration Cost Status"));
|
|
39
|
-
console.log(chalk.gray(" ─────────────────────────────────────────────────────────"));
|
|
40
|
-
|
|
41
|
-
for (const file of files) {
|
|
42
|
-
const filePath = join(runsDir, file);
|
|
43
|
-
const summary = await extractRunSummary(filePath);
|
|
44
|
-
|
|
45
|
-
const timestamp = file.replace(".jsonl", "");
|
|
46
|
-
const stories = summary ? `${summary.passed}/${summary.total}` : "?/?";
|
|
47
|
-
const duration = summary ? formatDuration(summary.durationMs) : "?";
|
|
48
|
-
const cost = summary ? `$${summary.totalCost.toFixed(4)}` : "$?.????";
|
|
49
|
-
const status = summary ? (summary.failed === 0 ? chalk.green("✓") : chalk.red("✗")) : "?";
|
|
50
|
-
|
|
51
|
-
console.log(` ${timestamp} ${stories.padEnd(7)} ${duration.padEnd(8)} ${cost.padEnd(8)} ${status}`);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
console.log();
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Display static logs
|
|
59
|
-
*/
|
|
60
|
-
export async function displayLogs(
|
|
61
|
-
filePath: string,
|
|
62
|
-
options: { json?: boolean; story?: string; level?: LogLevel },
|
|
63
|
-
): Promise<void> {
|
|
64
|
-
const file = Bun.file(filePath);
|
|
65
|
-
const content = await file.text();
|
|
66
|
-
const lines = content.trim().split("\n");
|
|
67
|
-
|
|
68
|
-
const mode: VerbosityMode = options.json ? "json" : "normal";
|
|
69
|
-
|
|
70
|
-
for (const line of lines) {
|
|
71
|
-
if (!line.trim()) continue;
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
const entry: LogEntry = JSON.parse(line);
|
|
75
|
-
|
|
76
|
-
if (!shouldDisplayEntry(entry, options)) {
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const formatted = formatLogEntry(entry, { mode, useColor: true });
|
|
81
|
-
|
|
82
|
-
if (formatted.shouldDisplay && formatted.output) {
|
|
83
|
-
console.log(formatted.output);
|
|
84
|
-
}
|
|
85
|
-
} catch {
|
|
86
|
-
// Skip invalid JSON lines
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (!options.json) {
|
|
91
|
-
const summary = await extractRunSummary(filePath);
|
|
92
|
-
if (summary) {
|
|
93
|
-
console.log(formatRunSummary(summary, { mode: "normal", useColor: true }));
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Follow logs in real-time (tail -f mode)
|
|
100
|
-
*/
|
|
101
|
-
export async function followLogs(
|
|
102
|
-
filePath: string,
|
|
103
|
-
options: { json?: boolean; story?: string; level?: LogLevel },
|
|
104
|
-
): Promise<void> {
|
|
105
|
-
const mode: VerbosityMode = options.json ? "json" : "normal";
|
|
106
|
-
|
|
107
|
-
const file = Bun.file(filePath);
|
|
108
|
-
const content = await file.text();
|
|
109
|
-
const lines = content.trim().split("\n");
|
|
110
|
-
|
|
111
|
-
for (const line of lines) {
|
|
112
|
-
if (!line.trim()) continue;
|
|
113
|
-
|
|
114
|
-
try {
|
|
115
|
-
const entry: LogEntry = JSON.parse(line);
|
|
116
|
-
|
|
117
|
-
if (!shouldDisplayEntry(entry, options)) {
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const formatted = formatLogEntry(entry, { mode, useColor: true });
|
|
122
|
-
|
|
123
|
-
if (formatted.shouldDisplay && formatted.output) {
|
|
124
|
-
console.log(formatted.output);
|
|
125
|
-
}
|
|
126
|
-
} catch {
|
|
127
|
-
// Skip invalid JSON lines
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
let lastSize = (await Bun.file(filePath).stat()).size;
|
|
132
|
-
|
|
133
|
-
while (true) {
|
|
134
|
-
await Bun.sleep(500);
|
|
135
|
-
|
|
136
|
-
const currentSize = (await Bun.file(filePath).stat()).size;
|
|
137
|
-
|
|
138
|
-
if (currentSize > lastSize) {
|
|
139
|
-
const newFile = Bun.file(filePath);
|
|
140
|
-
const newContent = await newFile.text();
|
|
141
|
-
const newLines = newContent.slice(lastSize).trim().split("\n");
|
|
142
|
-
|
|
143
|
-
for (const line of newLines) {
|
|
144
|
-
if (!line.trim()) continue;
|
|
145
|
-
|
|
146
|
-
try {
|
|
147
|
-
const entry: LogEntry = JSON.parse(line);
|
|
148
|
-
|
|
149
|
-
if (!shouldDisplayEntry(entry, options)) {
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const formatted = formatLogEntry(entry, { mode, useColor: true });
|
|
154
|
-
|
|
155
|
-
if (formatted.shouldDisplay && formatted.output) {
|
|
156
|
-
console.log(formatted.output);
|
|
157
|
-
}
|
|
158
|
-
} catch {
|
|
159
|
-
// Skip invalid JSON lines
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
lastSize = currentSize;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Check if entry should be displayed based on filters
|
|
170
|
-
*/
|
|
171
|
-
function shouldDisplayEntry(entry: LogEntry, options: { json?: boolean; story?: string; level?: LogLevel }): boolean {
|
|
172
|
-
if (options.story && entry.storyId !== options.story) {
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (options.level) {
|
|
177
|
-
const entryPriority = LOG_LEVEL_PRIORITY[entry.level];
|
|
178
|
-
const filterPriority = LOG_LEVEL_PRIORITY[options.level];
|
|
179
|
-
|
|
180
|
-
if (entryPriority < filterPriority) {
|
|
181
|
-
return false;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
return true;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Format duration in milliseconds
|
|
190
|
-
*/
|
|
191
|
-
export function formatDuration(ms: number): string {
|
|
192
|
-
if (ms < 1000) {
|
|
193
|
-
return `${ms}ms`;
|
|
194
|
-
}
|
|
195
|
-
if (ms < 60000) {
|
|
196
|
-
return `${(ms / 1000).toFixed(1)}s`;
|
|
197
|
-
}
|
|
198
|
-
const minutes = Math.floor(ms / 60000);
|
|
199
|
-
const seconds = Math.floor((ms % 60000) / 1000);
|
|
200
|
-
return `${minutes}m${seconds}s`;
|
|
201
|
-
}
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Log reading and parsing utilities
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { existsSync, readdirSync } from "node:fs";
|
|
6
|
-
import { readdir } from "node:fs/promises";
|
|
7
|
-
import { homedir } from "node:os";
|
|
8
|
-
import { join } from "node:path";
|
|
9
|
-
import type { LogEntry } from "../logger/types";
|
|
10
|
-
import type { MetaJson } from "../pipeline/subscribers/registry";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Swappable dependencies for testing
|
|
14
|
-
*/
|
|
15
|
-
export const _deps = {
|
|
16
|
-
getRunsDir: () => process.env.NAX_RUNS_DIR ?? join(homedir(), ".nax", "runs"),
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Resolve log file path for a runId from the central registry
|
|
21
|
-
*/
|
|
22
|
-
export async function resolveRunFileFromRegistry(runId: string): Promise<string | null> {
|
|
23
|
-
const runsDir = _deps.getRunsDir();
|
|
24
|
-
|
|
25
|
-
let entries: string[];
|
|
26
|
-
try {
|
|
27
|
-
entries = await readdir(runsDir);
|
|
28
|
-
} catch {
|
|
29
|
-
throw new Error(`Run not found in registry: ${runId}`);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
let matched: MetaJson | null = null;
|
|
33
|
-
for (const entry of entries) {
|
|
34
|
-
const metaPath = join(runsDir, entry, "meta.json");
|
|
35
|
-
try {
|
|
36
|
-
const meta: MetaJson = await Bun.file(metaPath).json();
|
|
37
|
-
if (meta.runId === runId || meta.runId.startsWith(runId)) {
|
|
38
|
-
matched = meta;
|
|
39
|
-
break;
|
|
40
|
-
}
|
|
41
|
-
} catch {
|
|
42
|
-
// skip unreadable meta.json entries
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (!matched) {
|
|
47
|
-
throw new Error(`Run not found in registry: ${runId}`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (!existsSync(matched.eventsDir)) {
|
|
51
|
-
console.log(`Log directory unavailable for run: ${runId}`);
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const files = readdirSync(matched.eventsDir)
|
|
56
|
-
.filter((f) => f.endsWith(".jsonl") && f !== "latest.jsonl")
|
|
57
|
-
.sort()
|
|
58
|
-
.reverse();
|
|
59
|
-
|
|
60
|
-
if (files.length === 0) {
|
|
61
|
-
console.log(`No log files found for run: ${runId}`);
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const specificFile = files.find((f) => f === `${matched.runId}.jsonl`);
|
|
66
|
-
return join(matched.eventsDir, specificFile ?? files[0]);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Select latest run file from directory
|
|
71
|
-
*/
|
|
72
|
-
export async function selectRunFile(runsDir: string): Promise<string | null> {
|
|
73
|
-
const files = readdirSync(runsDir)
|
|
74
|
-
.filter((f) => f.endsWith(".jsonl") && f !== "latest.jsonl")
|
|
75
|
-
.sort()
|
|
76
|
-
.reverse();
|
|
77
|
-
|
|
78
|
-
if (files.length === 0) {
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return join(runsDir, files[0]);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Extract run summary from log file
|
|
87
|
-
*/
|
|
88
|
-
export async function extractRunSummary(filePath: string): Promise<{
|
|
89
|
-
total: number;
|
|
90
|
-
passed: number;
|
|
91
|
-
failed: number;
|
|
92
|
-
skipped: number;
|
|
93
|
-
durationMs: number;
|
|
94
|
-
totalCost: number;
|
|
95
|
-
startedAt: string;
|
|
96
|
-
completedAt: string | undefined;
|
|
97
|
-
} | null> {
|
|
98
|
-
const file = Bun.file(filePath);
|
|
99
|
-
const content = await file.text();
|
|
100
|
-
const lines = content.trim().split("\n");
|
|
101
|
-
|
|
102
|
-
let total = 0;
|
|
103
|
-
let passed = 0;
|
|
104
|
-
let failed = 0;
|
|
105
|
-
let skipped = 0;
|
|
106
|
-
let totalCost = 0;
|
|
107
|
-
let startedAt = "";
|
|
108
|
-
let completedAt: string | undefined;
|
|
109
|
-
let firstTimestamp = "";
|
|
110
|
-
let lastTimestamp = "";
|
|
111
|
-
|
|
112
|
-
for (const line of lines) {
|
|
113
|
-
if (!line.trim()) continue;
|
|
114
|
-
|
|
115
|
-
try {
|
|
116
|
-
const entry: LogEntry = JSON.parse(line);
|
|
117
|
-
|
|
118
|
-
if (!firstTimestamp) {
|
|
119
|
-
firstTimestamp = entry.timestamp;
|
|
120
|
-
}
|
|
121
|
-
lastTimestamp = entry.timestamp;
|
|
122
|
-
|
|
123
|
-
if (entry.stage === "run.start") {
|
|
124
|
-
startedAt = entry.timestamp;
|
|
125
|
-
const runData = entry.data as Record<string, unknown>;
|
|
126
|
-
total = typeof runData?.totalStories === "number" ? runData.totalStories : 0;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (entry.stage === "story.complete" || entry.stage === "agent.complete") {
|
|
130
|
-
const data = entry.data as Record<string, unknown>;
|
|
131
|
-
const success = data?.success ?? true;
|
|
132
|
-
const action = data?.finalAction || data?.action;
|
|
133
|
-
|
|
134
|
-
if (success) {
|
|
135
|
-
passed++;
|
|
136
|
-
} else if (action === "skip") {
|
|
137
|
-
skipped++;
|
|
138
|
-
} else {
|
|
139
|
-
failed++;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (data?.cost && typeof data.cost === "number") {
|
|
143
|
-
totalCost += data.cost;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (entry.stage === "run.end") {
|
|
148
|
-
completedAt = entry.timestamp;
|
|
149
|
-
}
|
|
150
|
-
} catch {
|
|
151
|
-
// Skip invalid JSON lines
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (!startedAt) {
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const durationMs = lastTimestamp ? new Date(lastTimestamp).getTime() - new Date(firstTimestamp).getTime() : 0;
|
|
160
|
-
|
|
161
|
-
return {
|
|
162
|
-
total,
|
|
163
|
-
passed,
|
|
164
|
-
failed,
|
|
165
|
-
skipped,
|
|
166
|
-
durationMs,
|
|
167
|
-
totalCost,
|
|
168
|
-
startedAt,
|
|
169
|
-
completedAt,
|
|
170
|
-
};
|
|
171
|
-
}
|
package/src/commands/logs.ts
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Logs command implementation
|
|
3
|
-
*
|
|
4
|
-
* Displays run logs with filtering, follow mode, and multiple output formats.
|
|
5
|
-
* Uses resolveProject() for directory resolution and formatter for output.
|
|
6
|
-
*
|
|
7
|
-
* Re-exports reader and formatter modules for backward compatibility.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { existsSync } from "node:fs";
|
|
11
|
-
import { join } from "node:path";
|
|
12
|
-
import type { LogLevel } from "../logger/types";
|
|
13
|
-
import { resolveProject } from "./common";
|
|
14
|
-
import { displayLogs, displayRunsList, followLogs } from "./logs-formatter";
|
|
15
|
-
import { resolveRunFileFromRegistry, selectRunFile } from "./logs-reader";
|
|
16
|
-
|
|
17
|
-
// Re-exports for backward compatibility
|
|
18
|
-
export { _deps } from "./logs-reader";
|
|
19
|
-
export { extractRunSummary, resolveRunFileFromRegistry, selectRunFile } from "./logs-reader";
|
|
20
|
-
export { displayLogs, displayRunsList, followLogs, formatDuration } from "./logs-formatter";
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Options for logs command
|
|
24
|
-
*/
|
|
25
|
-
export interface LogsOptions {
|
|
26
|
-
/** Explicit project directory (from -d flag) */
|
|
27
|
-
dir?: string;
|
|
28
|
-
/** Follow mode - stream new entries real-time (from --follow / -f flag) */
|
|
29
|
-
follow?: boolean;
|
|
30
|
-
/** Filter to specific story (from --story / -s flag) */
|
|
31
|
-
story?: string;
|
|
32
|
-
/** Filter by log level (from --level flag) */
|
|
33
|
-
level?: LogLevel;
|
|
34
|
-
/** List all runs in table format (from --list / -l flag) */
|
|
35
|
-
list?: boolean;
|
|
36
|
-
/** Select specific run by timestamp (from --run / -r flag) */
|
|
37
|
-
run?: string;
|
|
38
|
-
/** Output raw JSONL (from --json / -j flag) */
|
|
39
|
-
json?: boolean;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Display logs with filtering and formatting
|
|
44
|
-
*/
|
|
45
|
-
export async function logsCommand(options: LogsOptions): Promise<void> {
|
|
46
|
-
// When --run <runId> is provided, resolve via central registry
|
|
47
|
-
if (options.run) {
|
|
48
|
-
const runFile = await resolveRunFileFromRegistry(options.run);
|
|
49
|
-
if (!runFile) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
if (options.follow) {
|
|
53
|
-
await followLogs(runFile, options);
|
|
54
|
-
} else {
|
|
55
|
-
await displayLogs(runFile, options);
|
|
56
|
-
}
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Resolve project directory
|
|
61
|
-
const resolved = resolveProject({ dir: options.dir });
|
|
62
|
-
const naxDir = join(resolved.projectDir, "nax");
|
|
63
|
-
|
|
64
|
-
// Read config to get feature name
|
|
65
|
-
const configPath = resolved.configPath;
|
|
66
|
-
const configFile = Bun.file(configPath);
|
|
67
|
-
const config = await configFile.json();
|
|
68
|
-
const featureName = config.feature;
|
|
69
|
-
|
|
70
|
-
if (!featureName) {
|
|
71
|
-
throw new Error("No feature specified in config.json");
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const featureDir = join(naxDir, "features", featureName);
|
|
75
|
-
const runsDir = join(featureDir, "runs");
|
|
76
|
-
|
|
77
|
-
// Validate runs directory exists
|
|
78
|
-
if (!existsSync(runsDir)) {
|
|
79
|
-
throw new Error(`No runs directory found for feature: ${featureName}`);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Handle --list mode (show runs table)
|
|
83
|
-
if (options.list) {
|
|
84
|
-
await displayRunsList(runsDir);
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Determine which run to display (latest by default — --run handled above via registry)
|
|
89
|
-
const runFile = await selectRunFile(runsDir);
|
|
90
|
-
|
|
91
|
-
if (!runFile) {
|
|
92
|
-
throw new Error("No runs found for this feature");
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Handle follow mode
|
|
96
|
-
if (options.follow) {
|
|
97
|
-
await followLogs(runFile, options);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Display static logs
|
|
102
|
-
await displayLogs(runFile, options);
|
|
103
|
-
}
|
package/src/commands/precheck.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Precheck command implementation
|
|
3
|
-
*
|
|
4
|
-
* Runs precheck validations and displays results in human or JSON format.
|
|
5
|
-
* Uses resolveProject() for directory resolution.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { existsSync } from "node:fs";
|
|
9
|
-
import { join } from "node:path";
|
|
10
|
-
import chalk from "chalk";
|
|
11
|
-
import { loadConfig } from "../config";
|
|
12
|
-
import { loadPRD } from "../prd";
|
|
13
|
-
import { EXIT_CODES, runPrecheck } from "../precheck";
|
|
14
|
-
import { resolveProject } from "./common";
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Options for precheck command
|
|
18
|
-
*/
|
|
19
|
-
export interface PrecheckOptions {
|
|
20
|
-
/** Feature name (from -f flag) */
|
|
21
|
-
feature?: string;
|
|
22
|
-
/** Explicit project directory (from -d flag) */
|
|
23
|
-
dir?: string;
|
|
24
|
-
/** Output JSON format (from --json flag) */
|
|
25
|
-
json?: boolean;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Run precheck command
|
|
30
|
-
*
|
|
31
|
-
* Validates feature readiness before execution.
|
|
32
|
-
* Exits with code 0 (pass), 1 (blocker), or 2 (invalid PRD).
|
|
33
|
-
*/
|
|
34
|
-
export async function precheckCommand(options: PrecheckOptions): Promise<void> {
|
|
35
|
-
// Resolve project directory and feature
|
|
36
|
-
const resolved = resolveProject({
|
|
37
|
-
dir: options.dir,
|
|
38
|
-
feature: options.feature,
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// Determine feature name (from flag or config)
|
|
42
|
-
let featureName = options.feature;
|
|
43
|
-
if (!featureName) {
|
|
44
|
-
// Read from config.json
|
|
45
|
-
const configFile = Bun.file(resolved.configPath);
|
|
46
|
-
const config = await configFile.json();
|
|
47
|
-
featureName = config.feature;
|
|
48
|
-
|
|
49
|
-
if (!featureName) {
|
|
50
|
-
console.error(chalk.red("No feature specified. Use -f flag or set feature in config.json"));
|
|
51
|
-
process.exit(1);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Get feature directory
|
|
56
|
-
const naxDir = join(resolved.projectDir, "nax");
|
|
57
|
-
const featureDir = join(naxDir, "features", featureName);
|
|
58
|
-
const prdPath = join(featureDir, "prd.json");
|
|
59
|
-
|
|
60
|
-
// Validate feature directory exists
|
|
61
|
-
if (!existsSync(featureDir)) {
|
|
62
|
-
console.error(chalk.red(`Feature not found: ${featureName}`));
|
|
63
|
-
process.exit(1);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Validate prd.json exists
|
|
67
|
-
if (!existsSync(prdPath)) {
|
|
68
|
-
console.error(chalk.red(`Missing prd.json for feature: ${featureName}`));
|
|
69
|
-
console.error(chalk.dim(`Run: nax plan -f ${featureName} --from spec.md --auto`));
|
|
70
|
-
process.exit(EXIT_CODES.INVALID_PRD);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Load config and PRD
|
|
74
|
-
const config = await loadConfig(resolved.projectDir);
|
|
75
|
-
const prd = await loadPRD(prdPath);
|
|
76
|
-
|
|
77
|
-
// Run precheck
|
|
78
|
-
const format = options.json ? "json" : "human";
|
|
79
|
-
const result = await runPrecheck(config, prd, {
|
|
80
|
-
workdir: resolved.projectDir,
|
|
81
|
-
format,
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
// Exit with appropriate code
|
|
85
|
-
process.exit(result.exitCode);
|
|
86
|
-
}
|