@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,135 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Events Writer Subscriber
|
|
3
|
-
*
|
|
4
|
-
* Appends one JSON line per pipeline lifecycle event to
|
|
5
|
-
* ~/.nax/events/<project>/events.jsonl. Provides a machine-readable
|
|
6
|
-
* signal that nax exited gracefully (run:completed → event=on-complete),
|
|
7
|
-
* fixing watchdog false crash reports.
|
|
8
|
-
*
|
|
9
|
-
* Design:
|
|
10
|
-
* - Best-effort: all writes are wrapped in try/catch; never throws or blocks
|
|
11
|
-
* - Directory is created on first write via mkdir recursive
|
|
12
|
-
* - Returns UnsubscribeFn matching wireHooks/wireReporters pattern
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { appendFile, mkdir } from "node:fs/promises";
|
|
16
|
-
import { homedir } from "node:os";
|
|
17
|
-
import { basename, join } from "node:path";
|
|
18
|
-
import { getSafeLogger } from "../../logger";
|
|
19
|
-
import type { PipelineEventBus } from "../event-bus";
|
|
20
|
-
import type { UnsubscribeFn } from "./hooks";
|
|
21
|
-
|
|
22
|
-
interface EventLine {
|
|
23
|
-
ts: string;
|
|
24
|
-
event: string;
|
|
25
|
-
runId: string;
|
|
26
|
-
feature: string;
|
|
27
|
-
project: string;
|
|
28
|
-
storyId?: string;
|
|
29
|
-
data?: object;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Wire events file writer to the pipeline event bus.
|
|
34
|
-
*
|
|
35
|
-
* Listens to run:started, story:started, story:completed, story:failed,
|
|
36
|
-
* run:completed, run:paused and appends one JSONL entry per event.
|
|
37
|
-
*
|
|
38
|
-
* @param bus - The pipeline event bus
|
|
39
|
-
* @param feature - Feature name
|
|
40
|
-
* @param runId - Current run ID
|
|
41
|
-
* @param workdir - Working directory (project name derived via basename)
|
|
42
|
-
* @returns Unsubscribe function
|
|
43
|
-
*/
|
|
44
|
-
export function wireEventsWriter(
|
|
45
|
-
bus: PipelineEventBus,
|
|
46
|
-
feature: string,
|
|
47
|
-
runId: string,
|
|
48
|
-
workdir: string,
|
|
49
|
-
): UnsubscribeFn {
|
|
50
|
-
const logger = getSafeLogger();
|
|
51
|
-
const project = basename(workdir);
|
|
52
|
-
const eventsDir = join(homedir(), ".nax", "events", project);
|
|
53
|
-
const eventsFile = join(eventsDir, "events.jsonl");
|
|
54
|
-
let dirReady = false;
|
|
55
|
-
|
|
56
|
-
const write = (line: EventLine): void => {
|
|
57
|
-
(async () => {
|
|
58
|
-
try {
|
|
59
|
-
if (!dirReady) {
|
|
60
|
-
await mkdir(eventsDir, { recursive: true });
|
|
61
|
-
dirReady = true;
|
|
62
|
-
}
|
|
63
|
-
await appendFile(eventsFile, `${JSON.stringify(line)}\n`);
|
|
64
|
-
} catch (err) {
|
|
65
|
-
logger?.warn("events-writer", "Failed to write event line (non-fatal)", {
|
|
66
|
-
event: line.event,
|
|
67
|
-
error: String(err),
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
})();
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const unsubs: UnsubscribeFn[] = [];
|
|
74
|
-
|
|
75
|
-
unsubs.push(
|
|
76
|
-
bus.on("run:started", (_ev) => {
|
|
77
|
-
write({ ts: new Date().toISOString(), event: "run:started", runId, feature, project });
|
|
78
|
-
}),
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
unsubs.push(
|
|
82
|
-
bus.on("story:started", (ev) => {
|
|
83
|
-
write({ ts: new Date().toISOString(), event: "story:started", runId, feature, project, storyId: ev.storyId });
|
|
84
|
-
}),
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
unsubs.push(
|
|
88
|
-
bus.on("story:completed", (ev) => {
|
|
89
|
-
write({ ts: new Date().toISOString(), event: "story:completed", runId, feature, project, storyId: ev.storyId });
|
|
90
|
-
}),
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
unsubs.push(
|
|
94
|
-
bus.on("story:decomposed", (ev) => {
|
|
95
|
-
write({
|
|
96
|
-
ts: new Date().toISOString(),
|
|
97
|
-
event: "story:decomposed",
|
|
98
|
-
runId,
|
|
99
|
-
feature,
|
|
100
|
-
project,
|
|
101
|
-
storyId: ev.storyId,
|
|
102
|
-
data: { subStoryCount: ev.subStoryCount },
|
|
103
|
-
});
|
|
104
|
-
}),
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
unsubs.push(
|
|
108
|
-
bus.on("story:failed", (ev) => {
|
|
109
|
-
write({ ts: new Date().toISOString(), event: "story:failed", runId, feature, project, storyId: ev.storyId });
|
|
110
|
-
}),
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
unsubs.push(
|
|
114
|
-
bus.on("run:completed", (_ev) => {
|
|
115
|
-
write({ ts: new Date().toISOString(), event: "on-complete", runId, feature, project });
|
|
116
|
-
}),
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
unsubs.push(
|
|
120
|
-
bus.on("run:paused", (ev) => {
|
|
121
|
-
write({
|
|
122
|
-
ts: new Date().toISOString(),
|
|
123
|
-
event: "run:paused",
|
|
124
|
-
runId,
|
|
125
|
-
feature,
|
|
126
|
-
project,
|
|
127
|
-
...(ev.storyId !== undefined && { storyId: ev.storyId }),
|
|
128
|
-
});
|
|
129
|
-
}),
|
|
130
|
-
);
|
|
131
|
-
|
|
132
|
-
return () => {
|
|
133
|
-
for (const u of unsubs) u();
|
|
134
|
-
};
|
|
135
|
-
}
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
// RE-ARCH: keep
|
|
2
|
-
/**
|
|
3
|
-
* Hooks Subscriber (ADR-005, Phase 3 US-P3-001)
|
|
4
|
-
*
|
|
5
|
-
* Maps pipeline events to nax lifecycle hooks (on-start, on-story-start,
|
|
6
|
-
* on-story-complete, on-story-fail, on-pause, on-complete).
|
|
7
|
-
*
|
|
8
|
-
* Design:
|
|
9
|
-
* - All hook calls are fire-and-forget (matching prior fireHook behavior)
|
|
10
|
-
* - Errors in hooks are logged, never rethrown
|
|
11
|
-
* - Returns unsubscribe function for cleanup
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { hookCtx } from "../../execution/story-context";
|
|
15
|
-
import { type LoadedHooksConfig, fireHook } from "../../hooks";
|
|
16
|
-
import { getSafeLogger } from "../../logger";
|
|
17
|
-
import type { PipelineEventBus } from "../event-bus";
|
|
18
|
-
|
|
19
|
-
export type UnsubscribeFn = () => void;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Wire pipeline lifecycle hooks to the event bus.
|
|
23
|
-
*
|
|
24
|
-
* @param bus - The pipeline event bus
|
|
25
|
-
* @param hooks - Loaded hooks config (from nax.config)
|
|
26
|
-
* @param workdir - Working directory for hook script execution
|
|
27
|
-
* @param feature - Feature name (for hook context payload)
|
|
28
|
-
* @returns Unsubscribe function (call to remove all subscriptions)
|
|
29
|
-
*/
|
|
30
|
-
export function wireHooks(
|
|
31
|
-
bus: PipelineEventBus,
|
|
32
|
-
hooks: LoadedHooksConfig,
|
|
33
|
-
workdir: string,
|
|
34
|
-
feature: string,
|
|
35
|
-
): UnsubscribeFn {
|
|
36
|
-
const logger = getSafeLogger();
|
|
37
|
-
|
|
38
|
-
const safe = (name: string, fn: () => Promise<void>) => {
|
|
39
|
-
fn().catch((err) => logger?.warn("hooks-subscriber", `Hook "${name}" failed`, { error: String(err) }));
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const unsubs: UnsubscribeFn[] = [];
|
|
43
|
-
|
|
44
|
-
// run:started → on-start
|
|
45
|
-
unsubs.push(
|
|
46
|
-
bus.on("run:started", (ev) => {
|
|
47
|
-
safe("on-start", () => fireHook(hooks, "on-start", hookCtx(feature, { status: "running" }), workdir));
|
|
48
|
-
}),
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
// story:started → on-story-start
|
|
52
|
-
unsubs.push(
|
|
53
|
-
bus.on("story:started", (ev) => {
|
|
54
|
-
safe("on-story-start", () =>
|
|
55
|
-
fireHook(
|
|
56
|
-
hooks,
|
|
57
|
-
"on-story-start",
|
|
58
|
-
hookCtx(feature, { storyId: ev.storyId, model: ev.modelTier, agent: ev.agent }),
|
|
59
|
-
workdir,
|
|
60
|
-
),
|
|
61
|
-
);
|
|
62
|
-
}),
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
// story:completed → on-story-complete
|
|
66
|
-
unsubs.push(
|
|
67
|
-
bus.on("story:completed", (ev) => {
|
|
68
|
-
safe("on-story-complete", () =>
|
|
69
|
-
fireHook(
|
|
70
|
-
hooks,
|
|
71
|
-
"on-story-complete",
|
|
72
|
-
hookCtx(feature, { storyId: ev.storyId, status: "passed", cost: ev.cost }),
|
|
73
|
-
workdir,
|
|
74
|
-
),
|
|
75
|
-
);
|
|
76
|
-
}),
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
// story:decomposed → on-story-complete (status: "decomposed")
|
|
80
|
-
unsubs.push(
|
|
81
|
-
bus.on("story:decomposed", (ev) => {
|
|
82
|
-
safe("on-story-complete (decomposed)", () =>
|
|
83
|
-
fireHook(
|
|
84
|
-
hooks,
|
|
85
|
-
"on-story-complete",
|
|
86
|
-
hookCtx(feature, { storyId: ev.storyId, status: "decomposed", subStoryCount: ev.subStoryCount }),
|
|
87
|
-
workdir,
|
|
88
|
-
),
|
|
89
|
-
);
|
|
90
|
-
}),
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
// story:failed → on-story-fail
|
|
94
|
-
unsubs.push(
|
|
95
|
-
bus.on("story:failed", (ev) => {
|
|
96
|
-
safe("on-story-fail", () =>
|
|
97
|
-
fireHook(
|
|
98
|
-
hooks,
|
|
99
|
-
"on-story-fail",
|
|
100
|
-
hookCtx(feature, { storyId: ev.storyId, status: "failed", reason: ev.reason }),
|
|
101
|
-
workdir,
|
|
102
|
-
),
|
|
103
|
-
);
|
|
104
|
-
}),
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
// story:paused → on-pause
|
|
108
|
-
unsubs.push(
|
|
109
|
-
bus.on("story:paused", (ev) => {
|
|
110
|
-
safe("on-pause (story)", () =>
|
|
111
|
-
fireHook(
|
|
112
|
-
hooks,
|
|
113
|
-
"on-pause",
|
|
114
|
-
hookCtx(feature, { storyId: ev.storyId, reason: ev.reason, cost: ev.cost }),
|
|
115
|
-
workdir,
|
|
116
|
-
),
|
|
117
|
-
);
|
|
118
|
-
}),
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
// run:paused → on-pause
|
|
122
|
-
unsubs.push(
|
|
123
|
-
bus.on("run:paused", (ev) => {
|
|
124
|
-
safe("on-pause (run)", () =>
|
|
125
|
-
fireHook(
|
|
126
|
-
hooks,
|
|
127
|
-
"on-pause",
|
|
128
|
-
hookCtx(feature, { storyId: ev.storyId, reason: ev.reason, cost: ev.cost }),
|
|
129
|
-
workdir,
|
|
130
|
-
),
|
|
131
|
-
);
|
|
132
|
-
}),
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
// run:completed → on-complete
|
|
136
|
-
unsubs.push(
|
|
137
|
-
bus.on("run:completed", (ev) => {
|
|
138
|
-
safe("on-complete", () =>
|
|
139
|
-
fireHook(hooks, "on-complete", hookCtx(feature, { status: "complete", cost: ev.totalCost ?? 0 }), workdir),
|
|
140
|
-
);
|
|
141
|
-
}),
|
|
142
|
-
);
|
|
143
|
-
|
|
144
|
-
// run:resumed → on-resume
|
|
145
|
-
unsubs.push(
|
|
146
|
-
bus.on("run:resumed", (ev) => {
|
|
147
|
-
safe("on-resume", () => fireHook(hooks, "on-resume", hookCtx(feature, { status: "running" }), workdir));
|
|
148
|
-
}),
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
// story:completed → on-session-end (passed)
|
|
152
|
-
unsubs.push(
|
|
153
|
-
bus.on("story:completed", (ev) => {
|
|
154
|
-
safe("on-session-end (completed)", () =>
|
|
155
|
-
fireHook(hooks, "on-session-end", hookCtx(feature, { storyId: ev.storyId, status: "passed" }), workdir),
|
|
156
|
-
);
|
|
157
|
-
}),
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
// story:failed → on-session-end (failed)
|
|
161
|
-
unsubs.push(
|
|
162
|
-
bus.on("story:failed", (ev) => {
|
|
163
|
-
safe("on-session-end (failed)", () =>
|
|
164
|
-
fireHook(hooks, "on-session-end", hookCtx(feature, { storyId: ev.storyId, status: "failed" }), workdir),
|
|
165
|
-
);
|
|
166
|
-
}),
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
// run:errored → on-error
|
|
170
|
-
unsubs.push(
|
|
171
|
-
bus.on("run:errored", (ev) => {
|
|
172
|
-
safe("on-error", () => fireHook(hooks, "on-error", hookCtx(feature, { reason: ev.reason }), workdir));
|
|
173
|
-
}),
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
return () => {
|
|
177
|
-
for (const u of unsubs) u();
|
|
178
|
-
};
|
|
179
|
-
}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
// RE-ARCH: keep
|
|
2
|
-
/**
|
|
3
|
-
* Interaction Subscriber (ADR-005, Phase 3 US-P3-003)
|
|
4
|
-
*
|
|
5
|
-
* Maps pipeline events to interaction trigger calls.
|
|
6
|
-
* Currently handles:
|
|
7
|
-
* - human-review:requested → executeTrigger("human-review")
|
|
8
|
-
*
|
|
9
|
-
* Future triggers (story-ambiguity, merge-conflict, etc.) can be added
|
|
10
|
-
* by subscribing to the appropriate events.
|
|
11
|
-
*
|
|
12
|
-
* Design:
|
|
13
|
-
* - Interaction triggers MAY block (await user response) — uses emitAsync where needed
|
|
14
|
-
* - Errors are caught and logged; never rethrown to avoid blocking the pipeline
|
|
15
|
-
* - Returns unsubscribe function for cleanup
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import type { NaxConfig } from "../../config";
|
|
19
|
-
import type { InteractionChain } from "../../interaction/chain";
|
|
20
|
-
import { executeTrigger, isTriggerEnabled } from "../../interaction/triggers";
|
|
21
|
-
import { getSafeLogger } from "../../logger";
|
|
22
|
-
import type { PipelineEventBus, StoryFailedEvent } from "../event-bus";
|
|
23
|
-
import type { UnsubscribeFn } from "./hooks";
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Wire interaction triggers to the event bus.
|
|
27
|
-
*
|
|
28
|
-
* @param bus - The pipeline event bus
|
|
29
|
-
* @param interactionChain - The active interaction chain (may be null)
|
|
30
|
-
* @param config - Nax config (for isTriggerEnabled checks)
|
|
31
|
-
* @returns Unsubscribe function
|
|
32
|
-
*/
|
|
33
|
-
export function wireInteraction(
|
|
34
|
-
bus: PipelineEventBus,
|
|
35
|
-
interactionChain: InteractionChain | null | undefined,
|
|
36
|
-
config: NaxConfig,
|
|
37
|
-
): UnsubscribeFn {
|
|
38
|
-
const logger = getSafeLogger();
|
|
39
|
-
const unsubs: UnsubscribeFn[] = [];
|
|
40
|
-
|
|
41
|
-
// human-review:requested → executeTrigger("human-review")
|
|
42
|
-
if (interactionChain && isTriggerEnabled("human-review", config)) {
|
|
43
|
-
unsubs.push(
|
|
44
|
-
bus.on("human-review:requested", (ev) => {
|
|
45
|
-
executeTrigger(
|
|
46
|
-
"human-review",
|
|
47
|
-
{
|
|
48
|
-
featureName: ev.feature ?? "",
|
|
49
|
-
storyId: ev.storyId,
|
|
50
|
-
iteration: ev.attempts ?? 0,
|
|
51
|
-
reason: ev.reason,
|
|
52
|
-
},
|
|
53
|
-
config,
|
|
54
|
-
interactionChain,
|
|
55
|
-
).catch((err) => {
|
|
56
|
-
logger?.warn("interaction-subscriber", "human-review trigger failed", {
|
|
57
|
-
storyId: ev.storyId,
|
|
58
|
-
error: String(err),
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
}),
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// story:failed (countsTowardEscalation=true) → executeTrigger("max-retries")
|
|
66
|
-
if (interactionChain && isTriggerEnabled("max-retries", config)) {
|
|
67
|
-
unsubs.push(
|
|
68
|
-
bus.on("story:failed", (ev: StoryFailedEvent) => {
|
|
69
|
-
if (!ev.countsTowardEscalation) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
executeTrigger(
|
|
74
|
-
"max-retries",
|
|
75
|
-
{
|
|
76
|
-
featureName: ev.feature ?? "",
|
|
77
|
-
storyId: ev.storyId,
|
|
78
|
-
iteration: ev.attempts ?? 0,
|
|
79
|
-
},
|
|
80
|
-
config,
|
|
81
|
-
interactionChain,
|
|
82
|
-
)
|
|
83
|
-
.then((response) => {
|
|
84
|
-
if (response.action === "abort") {
|
|
85
|
-
logger?.warn("interaction-subscriber", "max-retries abort requested", {
|
|
86
|
-
storyId: ev.storyId,
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
})
|
|
90
|
-
.catch((err) => {
|
|
91
|
-
logger?.warn("interaction-subscriber", "max-retries trigger failed", {
|
|
92
|
-
storyId: ev.storyId,
|
|
93
|
-
error: String(err),
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
}),
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return () => {
|
|
101
|
-
for (const u of unsubs) u();
|
|
102
|
-
};
|
|
103
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Registry Writer Subscriber
|
|
3
|
-
*
|
|
4
|
-
* Creates ~/.nax/runs/<project>-<feature>-<runId>/meta.json on run:started.
|
|
5
|
-
* Provides a persistent record of each run with paths for status and events.
|
|
6
|
-
*
|
|
7
|
-
* Design:
|
|
8
|
-
* - Best-effort: all writes wrapped in try/catch; never throws or blocks
|
|
9
|
-
* - Directory created on first write via mkdir recursive
|
|
10
|
-
* - Written once on run:started, never updated
|
|
11
|
-
* - Returns UnsubscribeFn matching wireHooks/wireEventsWriter pattern
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
15
|
-
import { homedir } from "node:os";
|
|
16
|
-
import { basename, join } from "node:path";
|
|
17
|
-
import { getSafeLogger } from "../../logger";
|
|
18
|
-
import type { PipelineEventBus } from "../event-bus";
|
|
19
|
-
import type { UnsubscribeFn } from "./hooks";
|
|
20
|
-
|
|
21
|
-
export interface MetaJson {
|
|
22
|
-
runId: string;
|
|
23
|
-
project: string;
|
|
24
|
-
feature: string;
|
|
25
|
-
workdir: string;
|
|
26
|
-
statusPath: string;
|
|
27
|
-
eventsDir: string;
|
|
28
|
-
registeredAt: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Wire registry writer to the pipeline event bus.
|
|
33
|
-
*
|
|
34
|
-
* Listens to run:started and writes meta.json to
|
|
35
|
-
* ~/.nax/runs/<project>-<feature>-<runId>/meta.json.
|
|
36
|
-
*
|
|
37
|
-
* @param bus - The pipeline event bus
|
|
38
|
-
* @param feature - Feature name
|
|
39
|
-
* @param runId - Current run ID
|
|
40
|
-
* @param workdir - Working directory (project name derived via basename)
|
|
41
|
-
* @returns Unsubscribe function
|
|
42
|
-
*/
|
|
43
|
-
export function wireRegistry(bus: PipelineEventBus, feature: string, runId: string, workdir: string): UnsubscribeFn {
|
|
44
|
-
const logger = getSafeLogger();
|
|
45
|
-
const project = basename(workdir);
|
|
46
|
-
const runDir = join(homedir(), ".nax", "runs", `${project}-${feature}-${runId}`);
|
|
47
|
-
const metaFile = join(runDir, "meta.json");
|
|
48
|
-
|
|
49
|
-
const unsub = bus.on("run:started", (_ev) => {
|
|
50
|
-
(async () => {
|
|
51
|
-
try {
|
|
52
|
-
await mkdir(runDir, { recursive: true });
|
|
53
|
-
const meta: MetaJson = {
|
|
54
|
-
runId,
|
|
55
|
-
project,
|
|
56
|
-
feature,
|
|
57
|
-
workdir,
|
|
58
|
-
statusPath: join(workdir, "nax", "features", feature, "status.json"),
|
|
59
|
-
eventsDir: join(workdir, "nax", "features", feature, "runs"),
|
|
60
|
-
registeredAt: new Date().toISOString(),
|
|
61
|
-
};
|
|
62
|
-
await writeFile(metaFile, JSON.stringify(meta, null, 2));
|
|
63
|
-
} catch (err) {
|
|
64
|
-
logger?.warn("registry-writer", "Failed to write meta.json (non-fatal)", {
|
|
65
|
-
path: metaFile,
|
|
66
|
-
error: String(err),
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
})();
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
return unsub;
|
|
73
|
-
}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
// RE-ARCH: keep
|
|
2
|
-
/**
|
|
3
|
-
* Reporters Subscriber (ADR-005, Phase 3 US-P3-002)
|
|
4
|
-
*
|
|
5
|
-
* Maps pipeline events to IReporter plugin methods
|
|
6
|
-
* (onRunStart, onStoryComplete, onRunEnd).
|
|
7
|
-
*
|
|
8
|
-
* Design:
|
|
9
|
-
* - Each reporter call is fire-and-forget
|
|
10
|
-
* - Errors in individual reporters are caught and logged
|
|
11
|
-
* - Returns unsubscribe function for cleanup
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { getSafeLogger } from "../../logger";
|
|
15
|
-
import type { PluginRegistry } from "../../plugins";
|
|
16
|
-
import type { PipelineEventBus } from "../event-bus";
|
|
17
|
-
import type { UnsubscribeFn } from "./hooks";
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Wire reporter plugin lifecycle events to the event bus.
|
|
21
|
-
*
|
|
22
|
-
* @param bus - The pipeline event bus
|
|
23
|
-
* @param pluginRegistry - Plugin registry exposing getReporters()
|
|
24
|
-
* @param runId - Current run ID (for reporter events)
|
|
25
|
-
* @param startTime - Run start timestamp in ms (for duration calculation)
|
|
26
|
-
* @returns Unsubscribe function
|
|
27
|
-
*/
|
|
28
|
-
export function wireReporters(
|
|
29
|
-
bus: PipelineEventBus,
|
|
30
|
-
pluginRegistry: PluginRegistry,
|
|
31
|
-
runId: string,
|
|
32
|
-
startTime: number,
|
|
33
|
-
): UnsubscribeFn {
|
|
34
|
-
const logger = getSafeLogger();
|
|
35
|
-
|
|
36
|
-
const safe = (name: string, fn: () => Promise<void>) => {
|
|
37
|
-
fn().catch((err) => logger?.warn("reporters-subscriber", `Reporter "${name}" error`, { error: String(err) }));
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const unsubs: UnsubscribeFn[] = [];
|
|
41
|
-
|
|
42
|
-
// run:started → reporter.onRunStart
|
|
43
|
-
unsubs.push(
|
|
44
|
-
bus.on("run:started", (ev) => {
|
|
45
|
-
safe("onRunStart", async () => {
|
|
46
|
-
const reporters = pluginRegistry.getReporters();
|
|
47
|
-
for (const r of reporters) {
|
|
48
|
-
if (r.onRunStart) {
|
|
49
|
-
try {
|
|
50
|
-
await r.onRunStart({
|
|
51
|
-
runId,
|
|
52
|
-
feature: ev.feature,
|
|
53
|
-
totalStories: ev.totalStories,
|
|
54
|
-
startTime: new Date(startTime).toISOString(),
|
|
55
|
-
});
|
|
56
|
-
} catch (err) {
|
|
57
|
-
logger?.warn("plugins", `Reporter '${r.name}' onRunStart failed`, { error: err });
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
}),
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
// story:completed → reporter.onStoryComplete(status: "completed")
|
|
66
|
-
unsubs.push(
|
|
67
|
-
bus.on("story:completed", (ev) => {
|
|
68
|
-
safe("onStoryComplete(completed)", async () => {
|
|
69
|
-
const reporters = pluginRegistry.getReporters();
|
|
70
|
-
for (const r of reporters) {
|
|
71
|
-
if (r.onStoryComplete) {
|
|
72
|
-
try {
|
|
73
|
-
await r.onStoryComplete({
|
|
74
|
-
runId,
|
|
75
|
-
storyId: ev.storyId,
|
|
76
|
-
status: "completed",
|
|
77
|
-
runElapsedMs: ev.runElapsedMs,
|
|
78
|
-
cost: ev.cost ?? 0,
|
|
79
|
-
tier: ev.modelTier ?? "balanced",
|
|
80
|
-
testStrategy: ev.testStrategy ?? "test-after",
|
|
81
|
-
});
|
|
82
|
-
} catch (err) {
|
|
83
|
-
logger?.warn("plugins", `Reporter '${r.name}' onStoryComplete failed`, { error: err });
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
}),
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
// story:failed → reporter.onStoryComplete(status: "failed")
|
|
92
|
-
unsubs.push(
|
|
93
|
-
bus.on("story:failed", (ev) => {
|
|
94
|
-
safe("onStoryComplete(failed)", async () => {
|
|
95
|
-
const reporters = pluginRegistry.getReporters();
|
|
96
|
-
for (const r of reporters) {
|
|
97
|
-
if (r.onStoryComplete) {
|
|
98
|
-
try {
|
|
99
|
-
await r.onStoryComplete({
|
|
100
|
-
runId,
|
|
101
|
-
storyId: ev.storyId,
|
|
102
|
-
status: "failed",
|
|
103
|
-
runElapsedMs: Date.now() - startTime,
|
|
104
|
-
cost: 0,
|
|
105
|
-
tier: "balanced",
|
|
106
|
-
testStrategy: "test-after",
|
|
107
|
-
});
|
|
108
|
-
} catch (err) {
|
|
109
|
-
logger?.warn("plugins", `Reporter '${r.name}' onStoryComplete failed`, { error: err });
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
}),
|
|
115
|
-
);
|
|
116
|
-
|
|
117
|
-
// story:paused → reporter.onStoryComplete(status: "paused")
|
|
118
|
-
unsubs.push(
|
|
119
|
-
bus.on("story:paused", (ev) => {
|
|
120
|
-
safe("onStoryComplete(paused)", async () => {
|
|
121
|
-
const reporters = pluginRegistry.getReporters();
|
|
122
|
-
for (const r of reporters) {
|
|
123
|
-
if (r.onStoryComplete) {
|
|
124
|
-
try {
|
|
125
|
-
await r.onStoryComplete({
|
|
126
|
-
runId,
|
|
127
|
-
storyId: ev.storyId,
|
|
128
|
-
status: "paused",
|
|
129
|
-
runElapsedMs: Date.now() - startTime,
|
|
130
|
-
cost: 0,
|
|
131
|
-
tier: "balanced",
|
|
132
|
-
testStrategy: "test-after",
|
|
133
|
-
});
|
|
134
|
-
} catch (err) {
|
|
135
|
-
logger?.warn("plugins", `Reporter '${r.name}' onStoryComplete failed`, { error: err });
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
}),
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
// run:completed → reporter.onRunEnd
|
|
144
|
-
unsubs.push(
|
|
145
|
-
bus.on("run:completed", (ev) => {
|
|
146
|
-
safe("onRunEnd", async () => {
|
|
147
|
-
const reporters = pluginRegistry.getReporters();
|
|
148
|
-
for (const r of reporters) {
|
|
149
|
-
if (r.onRunEnd) {
|
|
150
|
-
try {
|
|
151
|
-
await r.onRunEnd({
|
|
152
|
-
runId,
|
|
153
|
-
totalDurationMs: Date.now() - startTime,
|
|
154
|
-
totalCost: ev.totalCost ?? 0,
|
|
155
|
-
storySummary: {
|
|
156
|
-
completed: ev.passedStories,
|
|
157
|
-
failed: ev.failedStories,
|
|
158
|
-
skipped: 0,
|
|
159
|
-
paused: 0,
|
|
160
|
-
},
|
|
161
|
-
});
|
|
162
|
-
} catch (err) {
|
|
163
|
-
logger?.warn("plugins", `Reporter '${r.name}' onRunEnd failed`, { error: err });
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
}),
|
|
169
|
-
);
|
|
170
|
-
|
|
171
|
-
return () => {
|
|
172
|
-
for (const u of unsubs) u();
|
|
173
|
-
};
|
|
174
|
-
}
|