@nathapp/nax 0.50.2 → 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 +579 -373
- 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 -423
- 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 -135
- 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 -218
- 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 -217
- 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 -520
- package/src/config/schema-types.ts +0 -53
- package/src/config/schema.ts +0 -60
- package/src/config/schemas.ts +0 -425
- 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 -280
- 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 -140
- 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,285 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Config Display
|
|
3
|
-
*
|
|
4
|
-
* Format and display configuration with descriptions and explanations.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { existsSync } from "node:fs";
|
|
8
|
-
import { join } from "node:path";
|
|
9
|
-
import { findProjectDir, globalConfigPath } from "../config/loader";
|
|
10
|
-
import type { NaxConfig } from "../config/schema";
|
|
11
|
-
import { FIELD_DESCRIPTIONS } from "./config-descriptions";
|
|
12
|
-
import { deepDiffConfigs } from "./config-diff";
|
|
13
|
-
import { loadGlobalConfig, loadProjectConfig } from "./config-get";
|
|
14
|
-
|
|
15
|
-
export { FIELD_DESCRIPTIONS };
|
|
16
|
-
|
|
17
|
-
/** Options for config command */
|
|
18
|
-
export interface ConfigCommandOptions {
|
|
19
|
-
/** Show field explanations */
|
|
20
|
-
explain?: boolean;
|
|
21
|
-
/** Show only fields where project overrides global */
|
|
22
|
-
diff?: boolean;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Display effective configuration with optional explanations.
|
|
27
|
-
*
|
|
28
|
-
* @param config - Loaded configuration
|
|
29
|
-
* @param options - Command options
|
|
30
|
-
*/
|
|
31
|
-
export async function configCommand(config: NaxConfig, options: ConfigCommandOptions = {}): Promise<void> {
|
|
32
|
-
const { explain = false, diff = false } = options;
|
|
33
|
-
|
|
34
|
-
// Validate mutually exclusive flags
|
|
35
|
-
if (explain && diff) {
|
|
36
|
-
console.error("Error: --explain and --diff are mutually exclusive");
|
|
37
|
-
process.exit(1);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Determine sources
|
|
41
|
-
const sources = determineConfigSources();
|
|
42
|
-
|
|
43
|
-
if (diff) {
|
|
44
|
-
// Diff mode: show only fields where project overrides global
|
|
45
|
-
const projectConf = await loadProjectConfig();
|
|
46
|
-
|
|
47
|
-
if (!projectConf) {
|
|
48
|
-
console.log("No project config found — using global defaults");
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const globalConf = await loadGlobalConfig();
|
|
53
|
-
const diffs = deepDiffConfigs(globalConf, projectConf);
|
|
54
|
-
|
|
55
|
-
if (diffs.length === 0) {
|
|
56
|
-
console.log("No differences between project and global config");
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
console.log("# Config Differences (Project overrides Global)");
|
|
61
|
-
console.log();
|
|
62
|
-
console.log("─".repeat(80));
|
|
63
|
-
console.log(`${"Field".padEnd(40)}${"Project Value".padEnd(20)}Global Value`);
|
|
64
|
-
console.log("─".repeat(80));
|
|
65
|
-
|
|
66
|
-
for (const diff of diffs) {
|
|
67
|
-
const path = diff.path.padEnd(40);
|
|
68
|
-
const projectVal = formatValueForTable(diff.projectValue);
|
|
69
|
-
const globalVal = formatValueForTable(diff.globalValue);
|
|
70
|
-
|
|
71
|
-
console.log(`${path}${projectVal.padEnd(20)}${globalVal}`);
|
|
72
|
-
|
|
73
|
-
// Show description if available
|
|
74
|
-
const description = FIELD_DESCRIPTIONS[diff.path];
|
|
75
|
-
if (description) {
|
|
76
|
-
console.log(`${"".padEnd(40)}↳ ${description}`);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
console.log("─".repeat(80));
|
|
81
|
-
} else if (explain) {
|
|
82
|
-
console.log("# nax Configuration");
|
|
83
|
-
console.log("#");
|
|
84
|
-
console.log("# Resolution order: defaults → global → project → CLI overrides");
|
|
85
|
-
console.log(`# Global config: ${sources.global ? sources.global : "(not found)"}`);
|
|
86
|
-
console.log(`# Project config: ${sources.project ? sources.project : "(not found)"}`);
|
|
87
|
-
console.log();
|
|
88
|
-
|
|
89
|
-
// Recursively display config with descriptions
|
|
90
|
-
displayConfigWithDescriptions(config, [], sources);
|
|
91
|
-
} else {
|
|
92
|
-
// Default view: JSON with header showing config sources
|
|
93
|
-
console.log("// nax Configuration");
|
|
94
|
-
console.log("// Resolution order: defaults → global → project → CLI overrides");
|
|
95
|
-
console.log(`// Global config: ${sources.global ? sources.global : "(not found)"}`);
|
|
96
|
-
console.log(`// Project config: ${sources.project ? sources.project : "(not found)"}`);
|
|
97
|
-
console.log();
|
|
98
|
-
console.log(JSON.stringify(config, null, 2));
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Determine which config files are present.
|
|
104
|
-
*
|
|
105
|
-
* @returns Paths to global and project config files (null if not found)
|
|
106
|
-
*/
|
|
107
|
-
function determineConfigSources(): { global: string | null; project: string | null } {
|
|
108
|
-
const globalPath = globalConfigPath();
|
|
109
|
-
const projectDir = findProjectDir();
|
|
110
|
-
const projectPath = projectDir ? join(projectDir, "config.json") : null;
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
global: fileExists(globalPath) ? globalPath : null,
|
|
114
|
-
project: projectPath && fileExists(projectPath) ? projectPath : null,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Check if a file exists.
|
|
120
|
-
*
|
|
121
|
-
* @param path - File path to check
|
|
122
|
-
* @returns True if file exists, false otherwise
|
|
123
|
-
*/
|
|
124
|
-
function fileExists(path: string): boolean {
|
|
125
|
-
return existsSync(path);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Display configuration with descriptions and source annotations.
|
|
130
|
-
*
|
|
131
|
-
* @param obj - Configuration object or value
|
|
132
|
-
* @param path - Current path in config tree
|
|
133
|
-
* @param sources - Config source paths
|
|
134
|
-
* @param indent - Current indentation level
|
|
135
|
-
*/
|
|
136
|
-
function displayConfigWithDescriptions(
|
|
137
|
-
obj: unknown,
|
|
138
|
-
path: string[],
|
|
139
|
-
sources: { global: string | null; project: string | null },
|
|
140
|
-
indent = 0,
|
|
141
|
-
): void {
|
|
142
|
-
const indentStr = " ".repeat(indent);
|
|
143
|
-
const pathStr = path.join(".");
|
|
144
|
-
|
|
145
|
-
// Handle primitives and arrays
|
|
146
|
-
if (obj === null || obj === undefined || typeof obj !== "object" || Array.isArray(obj)) {
|
|
147
|
-
const description = FIELD_DESCRIPTIONS[pathStr];
|
|
148
|
-
const value = formatValue(obj);
|
|
149
|
-
|
|
150
|
-
if (description) {
|
|
151
|
-
console.log(`${indentStr}# ${description}`);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const key = path[path.length - 1] || "";
|
|
155
|
-
console.log(`${indentStr}${key}: ${value}`);
|
|
156
|
-
console.log();
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Handle objects
|
|
161
|
-
const entries = Object.entries(obj as Record<string, unknown>);
|
|
162
|
-
|
|
163
|
-
// Special handling for prompts section: always show overrides documentation
|
|
164
|
-
const objAsRecord = obj as Record<string, unknown>;
|
|
165
|
-
const isPromptsSection = path.join(".") === "prompts";
|
|
166
|
-
if (isPromptsSection && !objAsRecord.overrides) {
|
|
167
|
-
// Add prompts.overrides documentation even if not in config
|
|
168
|
-
const description = FIELD_DESCRIPTIONS["prompts.overrides"];
|
|
169
|
-
if (description) {
|
|
170
|
-
console.log(`${indentStr}# prompts.overrides: ${description}`);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// Show role examples
|
|
174
|
-
const roles = ["test-writer", "implementer", "verifier", "single-session"];
|
|
175
|
-
console.log(`${indentStr}overrides:`);
|
|
176
|
-
for (const role of roles) {
|
|
177
|
-
const roleDesc = FIELD_DESCRIPTIONS[`prompts.overrides.${role}`];
|
|
178
|
-
if (roleDesc) {
|
|
179
|
-
console.log(`${indentStr} # ${roleDesc}`);
|
|
180
|
-
// Extract the example path from description
|
|
181
|
-
const match = roleDesc.match(/e\.g\., "([^"]+)"/);
|
|
182
|
-
if (match) {
|
|
183
|
-
console.log(`${indentStr} # ${role}: "${match[1]}"`);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
console.log();
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
for (let i = 0; i < entries.length; i++) {
|
|
192
|
-
const [key, value] = entries[i];
|
|
193
|
-
const currentPath = [...path, key];
|
|
194
|
-
const currentPathStr = currentPath.join(".");
|
|
195
|
-
const description = FIELD_DESCRIPTIONS[currentPathStr];
|
|
196
|
-
|
|
197
|
-
// Display description comment if available
|
|
198
|
-
if (description) {
|
|
199
|
-
// Include path for direct subsections of key configuration sections
|
|
200
|
-
// (to improve clarity of important configs like multi-agent setup)
|
|
201
|
-
const pathParts = currentPathStr.split(".");
|
|
202
|
-
// Only show path for 2-level paths (e.g., "autoMode.enabled", "models.fast")
|
|
203
|
-
// to keep deeply nested descriptions concise
|
|
204
|
-
const isDirectSubsection = pathParts.length === 2;
|
|
205
|
-
const isKeySection = ["prompts", "autoMode", "models", "routing"].includes(pathParts[0]);
|
|
206
|
-
const shouldIncludePath = isKeySection && isDirectSubsection;
|
|
207
|
-
const comment = shouldIncludePath ? `${currentPathStr}: ${description}` : description;
|
|
208
|
-
console.log(`${indentStr}# ${comment}`);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// Handle nested objects
|
|
212
|
-
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
213
|
-
console.log(`${indentStr}${key}:`);
|
|
214
|
-
displayConfigWithDescriptions(value, currentPath, sources, indent + 1);
|
|
215
|
-
} else {
|
|
216
|
-
// Display value
|
|
217
|
-
const formattedValue = formatValue(value);
|
|
218
|
-
console.log(`${indentStr}${key}: ${formattedValue}`);
|
|
219
|
-
|
|
220
|
-
// Add blank line after each top-level section
|
|
221
|
-
if (indent === 0 && i < entries.length - 1) {
|
|
222
|
-
console.log();
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Format a config value for display.
|
|
230
|
-
*
|
|
231
|
-
* @param value - Value to format
|
|
232
|
-
* @returns Formatted string
|
|
233
|
-
*/
|
|
234
|
-
function formatValue(value: unknown): string {
|
|
235
|
-
if (value === null) return "null";
|
|
236
|
-
if (value === undefined) return "undefined";
|
|
237
|
-
if (typeof value === "string") return `"${value}"`;
|
|
238
|
-
if (typeof value === "boolean") return String(value);
|
|
239
|
-
if (typeof value === "number") return String(value);
|
|
240
|
-
if (Array.isArray(value)) {
|
|
241
|
-
if (value.length === 0) return "[]";
|
|
242
|
-
if (value.length <= 3) {
|
|
243
|
-
return `[${value.map((v) => formatValue(v)).join(", ")}]`;
|
|
244
|
-
}
|
|
245
|
-
return `[${value
|
|
246
|
-
.slice(0, 3)
|
|
247
|
-
.map((v) => formatValue(v))
|
|
248
|
-
.join(", ")}, ... (${value.length} items)]`;
|
|
249
|
-
}
|
|
250
|
-
if (typeof value === "object") {
|
|
251
|
-
return JSON.stringify(value);
|
|
252
|
-
}
|
|
253
|
-
return String(value);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Format a config value for table display (shorter format).
|
|
258
|
-
*
|
|
259
|
-
* @param value - Value to format
|
|
260
|
-
* @returns Formatted string (max ~18 chars)
|
|
261
|
-
*/
|
|
262
|
-
function formatValueForTable(value: unknown): string {
|
|
263
|
-
if (value === null) return "null";
|
|
264
|
-
if (value === undefined) return "undefined";
|
|
265
|
-
if (typeof value === "string") {
|
|
266
|
-
if (value.length > 15) {
|
|
267
|
-
return `"${value.slice(0, 12)}..."`;
|
|
268
|
-
}
|
|
269
|
-
return `"${value}"`;
|
|
270
|
-
}
|
|
271
|
-
if (typeof value === "boolean") return String(value);
|
|
272
|
-
if (typeof value === "number") return String(value);
|
|
273
|
-
if (Array.isArray(value)) {
|
|
274
|
-
if (value.length === 0) return "[]";
|
|
275
|
-
return `[...${value.length}]`;
|
|
276
|
-
}
|
|
277
|
-
if (typeof value === "object") {
|
|
278
|
-
const str = JSON.stringify(value);
|
|
279
|
-
if (str.length > 15) {
|
|
280
|
-
return "{...}";
|
|
281
|
-
}
|
|
282
|
-
return str;
|
|
283
|
-
}
|
|
284
|
-
return String(value);
|
|
285
|
-
}
|
package/src/cli/config-get.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Config Loading
|
|
3
|
-
*
|
|
4
|
-
* Load global and project configuration files.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { existsSync } from "node:fs";
|
|
8
|
-
import { join } from "node:path";
|
|
9
|
-
import { DEFAULT_CONFIG } from "../config/defaults";
|
|
10
|
-
import { findProjectDir, globalConfigPath } from "../config/loader";
|
|
11
|
-
import { deepMergeConfig } from "../config/merger";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Load and parse a JSON config file.
|
|
15
|
-
*
|
|
16
|
-
* @param path - Path to config file
|
|
17
|
-
* @returns Parsed config object or null if file doesn't exist
|
|
18
|
-
*/
|
|
19
|
-
export async function loadConfigFile(path: string): Promise<Record<string, unknown> | null> {
|
|
20
|
-
if (!existsSync(path)) return null;
|
|
21
|
-
try {
|
|
22
|
-
return await Bun.file(path).json();
|
|
23
|
-
} catch {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Load global config merged with defaults.
|
|
30
|
-
*
|
|
31
|
-
* @returns Global config object (defaults + global overrides)
|
|
32
|
-
*/
|
|
33
|
-
export async function loadGlobalConfig(): Promise<Record<string, unknown>> {
|
|
34
|
-
const globalPath = globalConfigPath();
|
|
35
|
-
const globalConf = await loadConfigFile(globalPath);
|
|
36
|
-
|
|
37
|
-
if (!globalConf) {
|
|
38
|
-
return structuredClone(DEFAULT_CONFIG as unknown as Record<string, unknown>);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return deepMergeConfig(structuredClone(DEFAULT_CONFIG as unknown as Record<string, unknown>), globalConf);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Load project config (raw, without defaults or global).
|
|
46
|
-
*
|
|
47
|
-
* @returns Project config object or null if not found
|
|
48
|
-
*/
|
|
49
|
-
export async function loadProjectConfig(): Promise<Record<string, unknown> | null> {
|
|
50
|
-
const projectDir = findProjectDir();
|
|
51
|
-
if (!projectDir) return null;
|
|
52
|
-
|
|
53
|
-
const projectPath = join(projectDir, "config.json");
|
|
54
|
-
return await loadConfigFile(projectPath);
|
|
55
|
-
}
|
package/src/cli/config.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Config Command
|
|
3
|
-
*
|
|
4
|
-
* Re-exports config display and loading utilities.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
// Display exports
|
|
8
|
-
export { configCommand, FIELD_DESCRIPTIONS, type ConfigCommandOptions } from "./config-display";
|
|
9
|
-
|
|
10
|
-
// Loading exports
|
|
11
|
-
export { loadConfigFile, loadGlobalConfig, loadProjectConfig } from "./config-get";
|
|
12
|
-
|
|
13
|
-
// Diff exports
|
|
14
|
-
export { deepDiffConfigs, deepEqual, type ConfigDiff } from "./config-diff";
|
package/src/cli/constitution.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Constitution CLI Command
|
|
3
|
-
*
|
|
4
|
-
* Generates agent-specific config files from nax/constitution.md.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/** Constitution generate options */
|
|
8
|
-
export interface ConstitutionGenerateOptions {
|
|
9
|
-
/** Path to constitution file (default: nax/constitution.md) */
|
|
10
|
-
constitution?: string;
|
|
11
|
-
/** Output directory (default: project root) */
|
|
12
|
-
output?: string;
|
|
13
|
-
/** Specific agent to generate for (default: all) */
|
|
14
|
-
agent?: string;
|
|
15
|
-
/** Dry run mode (don't write files) */
|
|
16
|
-
dryRun?: boolean;
|
|
17
|
-
}
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Diagnose Analysis
|
|
3
|
-
*
|
|
4
|
-
* Extracted from diagnose.ts: failure pattern detection, symptom descriptions,
|
|
5
|
-
* fix suggestions, and recommendation generation.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { NaxStatusFile } from "../execution/status-file";
|
|
9
|
-
import type { UserStory } from "../prd";
|
|
10
|
-
import type { PRD } from "../prd/types";
|
|
11
|
-
import type { DiagnosisReport, FailurePattern, StoryDiagnosis } from "./diagnose";
|
|
12
|
-
|
|
13
|
-
/** Detect failure pattern for a story */
|
|
14
|
-
export function detectFailurePattern(story: UserStory, prd: PRD, status: NaxStatusFile | null): FailurePattern {
|
|
15
|
-
if (
|
|
16
|
-
story.status === "passed" &&
|
|
17
|
-
story.priorErrors?.some((err) => err.toLowerCase().includes("greenfield-no-tests"))
|
|
18
|
-
) {
|
|
19
|
-
return "AUTO_RECOVERED";
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (story.status !== "failed" && story.status !== "blocked" && story.status !== "paused") {
|
|
23
|
-
return "UNKNOWN";
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
story.failureCategory === "greenfield-no-tests" ||
|
|
28
|
-
story.priorErrors?.some((err) => err.toLowerCase().includes("greenfield-no-tests"))
|
|
29
|
-
) {
|
|
30
|
-
return "GREENFIELD_TDD";
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const testFailingCount = story.priorErrors?.filter((err) => err.toLowerCase().includes("tests-failing")).length || 0;
|
|
34
|
-
if (testFailingCount >= 2) return "TEST_MISMATCH";
|
|
35
|
-
|
|
36
|
-
if (
|
|
37
|
-
story.priorErrors?.some((err) => err.toLowerCase().includes("precheck-failed")) ||
|
|
38
|
-
(status?.progress.blocked ?? 0) > 0
|
|
39
|
-
) {
|
|
40
|
-
return "ENVIRONMENTAL";
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (story.priorErrors?.some((err) => err.toLowerCase().includes("ratelimited"))) return "RATE_LIMITED";
|
|
44
|
-
if (story.failureCategory === "isolation-violation") return "ISOLATION_VIOLATION";
|
|
45
|
-
if (status?.run.status === "stalled") return "STALLED";
|
|
46
|
-
if (story.priorErrors?.some((err) => err.toLowerCase().includes("session-failure"))) return "SESSION_CRASH";
|
|
47
|
-
if (story.attempts > 3) return "MAX_TIERS_EXHAUSTED";
|
|
48
|
-
|
|
49
|
-
return "UNKNOWN";
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/** Get symptom description for a pattern */
|
|
53
|
-
export function getPatternSymptom(pattern: FailurePattern): string {
|
|
54
|
-
const symptoms: Record<FailurePattern, string> = {
|
|
55
|
-
GREENFIELD_TDD: "Story attempted in greenfield project with no existing tests",
|
|
56
|
-
TEST_MISMATCH: "Multiple test failures across attempts",
|
|
57
|
-
ENVIRONMENTAL: "Environment prechecks failed or blockers detected",
|
|
58
|
-
RATE_LIMITED: "API rate limit exceeded",
|
|
59
|
-
ISOLATION_VIOLATION: "Story modified files outside its scope",
|
|
60
|
-
MAX_TIERS_EXHAUSTED: "Story attempted at all configured model tiers without success",
|
|
61
|
-
SESSION_CRASH: "Agent session crashed without producing commits",
|
|
62
|
-
STALLED: "All stories blocked or paused -- no forward progress possible",
|
|
63
|
-
LOCK_STALE: "Lock file present but process is dead",
|
|
64
|
-
AUTO_RECOVERED: "Greenfield issue detected but S5 auto-recovery succeeded",
|
|
65
|
-
UNKNOWN: "Unknown failure pattern",
|
|
66
|
-
};
|
|
67
|
-
return symptoms[pattern] ?? "Unknown failure pattern";
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/** Get fix suggestion for a pattern */
|
|
71
|
-
export function getPatternFixSuggestion(pattern: FailurePattern, _story: UserStory): string {
|
|
72
|
-
const fixes: Record<FailurePattern, string> = {
|
|
73
|
-
GREENFIELD_TDD: "Add --greenfield flag or bootstrap with scaffolding tests first",
|
|
74
|
-
TEST_MISMATCH: "Review acceptance criteria; tests may be too strict or story underspecified",
|
|
75
|
-
ENVIRONMENTAL: "Fix precheck issues (deps, env, build) before re-running",
|
|
76
|
-
RATE_LIMITED: "Wait for rate limit to reset or increase tier limits",
|
|
77
|
-
ISOLATION_VIOLATION: "Narrow story scope or adjust expectedFiles to allow cross-file changes",
|
|
78
|
-
MAX_TIERS_EXHAUSTED: "Simplify story or split into smaller sub-stories",
|
|
79
|
-
SESSION_CRASH: "Check agent logs for crash details; may need manual intervention",
|
|
80
|
-
STALLED: "Resolve blocked stories or skip them to unblock dependencies",
|
|
81
|
-
LOCK_STALE: "Run: rm nax.lock",
|
|
82
|
-
AUTO_RECOVERED: "No action needed -- S5 successfully handled greenfield scenario",
|
|
83
|
-
UNKNOWN: "Review logs and prior errors for clues",
|
|
84
|
-
};
|
|
85
|
-
return fixes[pattern] ?? "Review logs and prior errors for clues";
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/** Generate recommendations based on diagnosis */
|
|
89
|
-
export function generateRecommendations(report: DiagnosisReport): string[] {
|
|
90
|
-
const recommendations: string[] = [];
|
|
91
|
-
|
|
92
|
-
if (report.lockCheck.lockPresent && report.lockCheck.pidAlive === false) {
|
|
93
|
-
recommendations.push(`Remove stale lock: ${report.lockCheck.fixCommand}`);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const criticalPatterns = report.failureAnalysis.filter((f) =>
|
|
97
|
-
["ENVIRONMENTAL", "STALLED", "SESSION_CRASH"].includes(f.pattern),
|
|
98
|
-
);
|
|
99
|
-
if (criticalPatterns.length > 0) {
|
|
100
|
-
recommendations.push(
|
|
101
|
-
`Fix ${criticalPatterns.length} critical blocker(s): ${criticalPatterns.map((f) => f.storyId).join(", ")}`,
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (report.failureAnalysis.some((f) => f.pattern === "RATE_LIMITED")) {
|
|
106
|
-
recommendations.push("Wait for rate limits to reset before re-running");
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (report.failureAnalysis.some((f) => f.pattern === "GREENFIELD_TDD")) {
|
|
110
|
-
recommendations.push("Consider adding --greenfield flag or bootstrap tests for greenfield stories");
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (report.runSummary.storiesFailed > 0 && recommendations.length === 0) {
|
|
114
|
-
recommendations.push(`Re-run with: nax run -f ${report.runSummary.feature}`);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (report.runSummary.storiesFailed === 0 && report.runSummary.storiesPending === 0) {
|
|
118
|
-
recommendations.push("All stories passed -- feature is complete!");
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return recommendations;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/** Diagnose each story and build story breakdown + failure analysis lists */
|
|
125
|
-
export function diagnoseStories(
|
|
126
|
-
prd: PRD,
|
|
127
|
-
status: NaxStatusFile | null,
|
|
128
|
-
): { storyBreakdown: StoryDiagnosis[]; failureAnalysis: StoryDiagnosis[] } {
|
|
129
|
-
const storyBreakdown: StoryDiagnosis[] = [];
|
|
130
|
-
const failureAnalysis: StoryDiagnosis[] = [];
|
|
131
|
-
|
|
132
|
-
for (const story of prd.userStories) {
|
|
133
|
-
const pattern = detectFailurePattern(story, prd, status);
|
|
134
|
-
const diagnosis: StoryDiagnosis = {
|
|
135
|
-
storyId: story.id,
|
|
136
|
-
title: story.title,
|
|
137
|
-
status: story.status,
|
|
138
|
-
attempts: story.attempts,
|
|
139
|
-
tier: story.routing?.modelTier,
|
|
140
|
-
strategy: story.routing?.testStrategy,
|
|
141
|
-
pattern,
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
storyBreakdown.push(diagnosis);
|
|
145
|
-
|
|
146
|
-
if (
|
|
147
|
-
story.status === "failed" ||
|
|
148
|
-
story.status === "blocked" ||
|
|
149
|
-
story.status === "paused" ||
|
|
150
|
-
pattern === "AUTO_RECOVERED"
|
|
151
|
-
) {
|
|
152
|
-
diagnosis.symptom = getPatternSymptom(pattern);
|
|
153
|
-
diagnosis.fixSuggestion = getPatternFixSuggestion(pattern, story);
|
|
154
|
-
failureAnalysis.push(diagnosis);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return { storyBreakdown, failureAnalysis };
|
|
159
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Diagnose Report Formatter
|
|
3
|
-
*
|
|
4
|
-
* Extracted from diagnose.ts: human-readable output formatting for the diagnosis report.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import chalk from "chalk";
|
|
8
|
-
import type { DiagnosisReport } from "./diagnose";
|
|
9
|
-
|
|
10
|
-
/** Format diagnosis report as human-readable text */
|
|
11
|
-
export function formatReport(report: DiagnosisReport, verbose: boolean): string {
|
|
12
|
-
const lines: string[] = [];
|
|
13
|
-
|
|
14
|
-
lines.push(chalk.bold(`\nDiagnosis Report: ${report.runSummary.feature}\n`));
|
|
15
|
-
|
|
16
|
-
if (!report.dataSources.eventsFound) {
|
|
17
|
-
lines.push(chalk.yellow("[WARN] events.jsonl not found -- diagnosis limited to PRD + git log\n"));
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Run Summary
|
|
21
|
-
lines.push(chalk.bold("Run Summary\n"));
|
|
22
|
-
if (report.runSummary.lastRunTime) {
|
|
23
|
-
lines.push(chalk.dim(` Last Run: ${report.runSummary.lastRunTime}`));
|
|
24
|
-
}
|
|
25
|
-
lines.push(chalk.dim(` Status: ${report.runSummary.status}`));
|
|
26
|
-
lines.push(chalk.green(` Passed: ${report.runSummary.storiesPassed}`));
|
|
27
|
-
lines.push(chalk.red(` Failed: ${report.runSummary.storiesFailed}`));
|
|
28
|
-
lines.push(chalk.dim(` Pending: ${report.runSummary.storiesPending}`));
|
|
29
|
-
if (report.runSummary.cost !== undefined) {
|
|
30
|
-
lines.push(chalk.dim(` Cost: $${report.runSummary.cost.toFixed(4)}`));
|
|
31
|
-
}
|
|
32
|
-
lines.push(chalk.dim(` Commits: ${report.runSummary.commitsProduced}`));
|
|
33
|
-
lines.push("");
|
|
34
|
-
|
|
35
|
-
// Story Breakdown (verbose only)
|
|
36
|
-
if (verbose && report.storyBreakdown.length > 0) {
|
|
37
|
-
lines.push(chalk.bold("Story Breakdown\n"));
|
|
38
|
-
for (const story of report.storyBreakdown) {
|
|
39
|
-
const icon = story.status === "passed" ? "[OK]" : story.status === "failed" ? "[FAIL]" : "[ ]";
|
|
40
|
-
const pattern = story.pattern !== "UNKNOWN" ? chalk.yellow(` [${story.pattern}]`) : "";
|
|
41
|
-
lines.push(` ${icon} ${story.storyId}: ${story.title}${pattern}`);
|
|
42
|
-
if (verbose && story.tier) {
|
|
43
|
-
lines.push(chalk.dim(` Tier: ${story.tier}, Strategy: ${story.strategy}, Attempts: ${story.attempts}`));
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
lines.push("");
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Failure Analysis
|
|
50
|
-
if (report.failureAnalysis.length > 0) {
|
|
51
|
-
lines.push(chalk.bold("Failure Analysis\n"));
|
|
52
|
-
for (const failure of report.failureAnalysis) {
|
|
53
|
-
const level = failure.pattern === "AUTO_RECOVERED" ? chalk.green("INFO") : chalk.red("ERROR");
|
|
54
|
-
lines.push(` ${level} ${failure.storyId}: ${failure.title}`);
|
|
55
|
-
lines.push(chalk.dim(` Pattern: ${failure.pattern}`));
|
|
56
|
-
if (failure.symptom) {
|
|
57
|
-
lines.push(chalk.dim(` Symptom: ${failure.symptom}`));
|
|
58
|
-
}
|
|
59
|
-
if (failure.fixSuggestion) {
|
|
60
|
-
lines.push(chalk.yellow(` Fix: ${failure.fixSuggestion}`));
|
|
61
|
-
}
|
|
62
|
-
lines.push("");
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Lock Check
|
|
67
|
-
lines.push(chalk.bold("Lock Check\n"));
|
|
68
|
-
if (!report.lockCheck.lockPresent) {
|
|
69
|
-
lines.push(chalk.dim(" No lock file present\n"));
|
|
70
|
-
} else if (report.lockCheck.pidAlive === false) {
|
|
71
|
-
lines.push(chalk.red(` [FAIL] Stale lock detected (PID ${report.lockCheck.pid} is dead)`));
|
|
72
|
-
lines.push(chalk.yellow(` Fix: ${report.lockCheck.fixCommand}\n`));
|
|
73
|
-
} else {
|
|
74
|
-
lines.push(chalk.green(` [OK] Active lock (PID ${report.lockCheck.pid})\n`));
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Recommendations
|
|
78
|
-
if (report.recommendations.length > 0) {
|
|
79
|
-
lines.push(chalk.bold("Recommendations\n"));
|
|
80
|
-
for (let i = 0; i < report.recommendations.length; i++) {
|
|
81
|
-
lines.push(` ${i + 1}. ${report.recommendations[i]}`);
|
|
82
|
-
}
|
|
83
|
-
lines.push("");
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return lines.join("\n");
|
|
87
|
-
}
|