@elench/testkit 0.1.90 → 0.1.91

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.
@@ -1,248 +0,0 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import { fileURLToPath } from "url";
4
- import { readContextContent } from "../context-resources.mjs";
5
-
6
- export function prepareAssistantBootstrap({
7
- productDir,
8
- inspectState,
9
- initialPrompt = null,
10
- } = {}) {
11
- const contextDir = path.join(productDir, ".testkit", "assistant");
12
- const binDir = path.join(contextDir, "bin");
13
- fs.mkdirSync(binDir, { recursive: true });
14
-
15
- const snapshot = inspectState?.getSnapshot?.() || {};
16
- const commandLogPath = path.join(contextDir, "commands.jsonl");
17
- const contextPath = path.join(contextDir, "context.md");
18
- const summaryPath = path.join(contextDir, "latest-run-summary.json");
19
- const selectionPath = path.join(contextDir, "current-selection.json");
20
- const commandsPath = path.join(contextDir, "commands.md");
21
- const focusedDetailPath = path.join(contextDir, "focused-detail.txt");
22
- const focusedLogsPath = path.join(contextDir, "focused-logs.txt");
23
- const focusedArtifactsPath = path.join(contextDir, "focused-artifacts.txt");
24
- const focusedSetupPath = path.join(contextDir, "focused-setup.txt");
25
- const wrapperPath = path.join(binDir, "testkit");
26
-
27
- const detailContent = readContextContent({ productDir, snapshot, mode: "detail", logTail: 12 });
28
- const logsContent = readContextContent({ productDir, snapshot, mode: "logs", logTail: 12 });
29
- const artifactsContent = readContextContent({ productDir, snapshot, mode: "artifacts", logTail: 12 });
30
- const setupContent = readContextContent({ productDir, snapshot, mode: "setup", logTail: 12 });
31
-
32
- writeJson(summaryPath, {
33
- summaryRows: snapshot.summaryData?.rows || [],
34
- phase: snapshot.phase || null,
35
- artifactPath: path.join(productDir, ".testkit", "results", "latest.json"),
36
- });
37
- writeJson(selectionPath, serializeSelection(snapshot.selectedEntry || null));
38
- fs.writeFileSync(commandsPath, buildCommandsMarkdown(), "utf8");
39
- fs.writeFileSync(focusedDetailPath, `${detailContent.lines.join("\n")}\n`, "utf8");
40
- fs.writeFileSync(focusedLogsPath, `${logsContent.lines.join("\n")}\n`, "utf8");
41
- fs.writeFileSync(focusedArtifactsPath, `${artifactsContent.lines.join("\n")}\n`, "utf8");
42
- fs.writeFileSync(focusedSetupPath, `${setupContent.lines.join("\n")}\n`, "utf8");
43
- fs.writeFileSync(contextPath, buildContextMarkdown(productDir, snapshot, {
44
- contextPath,
45
- summaryPath,
46
- selectionPath,
47
- commandsPath,
48
- commandLogPath,
49
- focusedDetailPath,
50
- focusedLogsPath,
51
- focusedArtifactsPath,
52
- focusedSetupPath,
53
- }), "utf8");
54
- fs.writeFileSync(wrapperPath, buildWrapperScript({
55
- cliPath: resolveCliPath(),
56
- commandLogPath,
57
- }), { encoding: "utf8", mode: 0o755 });
58
- fs.chmodSync(wrapperPath, 0o755);
59
-
60
- return {
61
- contextDir,
62
- contextPath,
63
- summaryPath,
64
- selectionPath,
65
- commandsPath,
66
- commandLogPath,
67
- focusedDetailPath,
68
- focusedLogsPath,
69
- focusedArtifactsPath,
70
- focusedSetupPath,
71
- binDir,
72
- env: {
73
- TESTKIT_ASSISTANT_CONTEXT_DIR: contextDir,
74
- TESTKIT_ASSISTANT_CONTEXT_PATH: contextPath,
75
- TESTKIT_ASSISTANT_COMMAND_LOG: commandLogPath,
76
- TESTKIT_NO_ASSISTANT_DEFAULT: "1",
77
- },
78
- prompt: buildStartupPrompt({ initialPrompt }),
79
- };
80
- }
81
-
82
- function resolveCliPath() {
83
- return path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "bin", "testkit.mjs");
84
- }
85
-
86
- function buildWrapperScript({ cliPath, commandLogPath } = {}) {
87
- return `#!/usr/bin/env node
88
- import { appendFileSync, mkdirSync } from "fs";
89
- import { dirname } from "path";
90
- import { spawnSync } from "child_process";
91
-
92
- const CLI_PATH = ${JSON.stringify(cliPath)};
93
- const COMMAND_LOG = ${JSON.stringify(commandLogPath)};
94
- const argv = process.argv.slice(2);
95
- const commandId = \`cmd-\${Date.now()}-\${Math.random().toString(36).slice(2, 10)}\`;
96
-
97
- function log(event) {
98
- try {
99
- mkdirSync(dirname(COMMAND_LOG), { recursive: true });
100
- appendFileSync(COMMAND_LOG, JSON.stringify({
101
- timestamp: new Date().toISOString(),
102
- ...event,
103
- }) + "\\n");
104
- } catch {
105
- // Ignore assistant command log failures.
106
- }
107
- }
108
-
109
- log({
110
- type: "command_start",
111
- command: "testkit",
112
- commandId,
113
- cwd: process.cwd(),
114
- argv,
115
- });
116
-
117
- const result = spawnSync(process.execPath, [CLI_PATH, ...argv], {
118
- cwd: process.cwd(),
119
- env: {
120
- ...process.env,
121
- TESTKIT_NO_ASSISTANT_DEFAULT: "1",
122
- TESTKIT_ASSISTANT_COMMAND_ID: commandId,
123
- TESTKIT_ASSISTANT_COMMAND_LOG: COMMAND_LOG,
124
- },
125
- stdio: "inherit",
126
- });
127
-
128
- log({
129
- type: "command_exit",
130
- command: "testkit",
131
- commandId,
132
- cwd: process.cwd(),
133
- argv,
134
- code: result.status ?? null,
135
- signal: result.signal ?? null,
136
- });
137
-
138
- if (result.error) {
139
- throw result.error;
140
- }
141
- process.exit(result.status ?? 0);
142
- `;
143
- }
144
-
145
- function buildStartupPrompt({ initialPrompt } = {}) {
146
- if (initialPrompt) {
147
- return [
148
- "You are operating inside a testkit-managed repository.",
149
- "Read .testkit/assistant/context.md before taking action.",
150
- "Use the local `testkit` command on PATH for runs, discovery, status, and doctor checks.",
151
- `User request: ${String(initialPrompt).trim()}`,
152
- ].join("\n");
153
- }
154
-
155
- return [
156
- "You are operating inside a testkit-managed repository.",
157
- "Read .testkit/assistant/context.md before taking action.",
158
- "Use the local `testkit` command on PATH for runs, discovery, status, and doctor checks.",
159
- "Respond with a brief readiness note and wait for the user's next request.",
160
- ].join("\n");
161
- }
162
-
163
- function buildContextMarkdown(productDir, snapshot, paths) {
164
- const rows = snapshot.summaryData?.rows || [];
165
- const selection = snapshot.selectedEntry;
166
- const lines = [
167
- "# Testkit Assistant Context",
168
- "",
169
- `- Product directory: ${productDir}`,
170
- `- Context file: ${paths.contextPath}`,
171
- `- Run summary JSON: ${paths.summaryPath}`,
172
- `- Current selection JSON: ${paths.selectionPath}`,
173
- `- Command reference: ${paths.commandsPath}`,
174
- `- Command log: ${paths.commandLogPath}`,
175
- `- Focused detail: ${paths.focusedDetailPath}`,
176
- `- Focused logs: ${paths.focusedLogsPath}`,
177
- `- Focused artifacts: ${paths.focusedArtifactsPath}`,
178
- `- Focused setup: ${paths.focusedSetupPath}`,
179
- "",
180
- "## Latest run summary",
181
- ];
182
-
183
- if (rows.length === 0) {
184
- lines.push("- No persisted run artifact is currently loaded.");
185
- } else {
186
- for (const [label, value] of rows) {
187
- lines.push(`- ${label}: ${value}`);
188
- }
189
- }
190
-
191
- lines.push("", "## Current selection");
192
- if (!selection) {
193
- lines.push("- No focused file or service.");
194
- } else {
195
- lines.push(`- Kind: ${selection.kind}`);
196
- if (selection.serviceName) lines.push(`- Service: ${selection.serviceName}`);
197
- if (selection.type) lines.push(`- Type: ${selection.type}`);
198
- if (selection.suiteName) lines.push(`- Suite: ${selection.suiteName}`);
199
- if (selection.filePath) lines.push(`- File: ${selection.filePath}`);
200
- if (selection.status) lines.push(`- Status: ${selection.status}`);
201
- }
202
-
203
- lines.push(
204
- "",
205
- "## Guidance",
206
- "- Use `testkit run --dir . --type <type>` to run suites.",
207
- "- Use `testkit status --dir .` to inspect local state.",
208
- "- Use `testkit discover --dir .` to inspect managed test coverage.",
209
- "- The `testkit` command on PATH is already wired to this local package.",
210
- "- Reuse the focused context text files under .testkit/assistant/ before rereading artifacts manually.",
211
- "- Avoid launching nested `testkit assistant` sessions from inside the provider.",
212
- ""
213
- );
214
-
215
- return lines.join("\n");
216
- }
217
-
218
- function buildCommandsMarkdown() {
219
- return [
220
- "# Testkit Commands",
221
- "",
222
- "- `testkit run --dir . --type int`",
223
- "- `testkit run --dir . --type e2e`",
224
- "- `testkit run --dir . --file path/to/file.testkit.ts`",
225
- "- `testkit discover --dir .`",
226
- "- `testkit status --dir .`",
227
- "- `testkit doctor --dir .`",
228
- "- `testkit destroy --dir .`",
229
- "",
230
- ].join("\n");
231
- }
232
-
233
- function serializeSelection(entry) {
234
- if (!entry) return null;
235
- return {
236
- kind: entry.kind || null,
237
- serviceName: entry.serviceName || null,
238
- type: entry.type || null,
239
- suiteName: entry.suiteName || null,
240
- filePath: entry.filePath || null,
241
- status: entry.status || null,
242
- label: entry.label || null,
243
- };
244
- }
245
-
246
- function writeJson(filePath, value) {
247
- fs.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf8");
248
- }
@@ -1,80 +0,0 @@
1
- import {
2
- applyReporterPlans,
3
- applyReporterRunSummary,
4
- applyReporterTaskFinished,
5
- applyReporterTaskStarted,
6
- } from "../tui/inspect-live-adapter.mjs";
7
- import { suiteSelectionType } from "../../runner/suite-selection.mjs";
8
-
9
- export function createAssistantRunReporter({ inspectState, onStatus } = {}) {
10
- return {
11
- reporter: {
12
- outputMode: "compact",
13
-
14
- setServicePlans(plans) {
15
- applyReporterPlans(inspectState, plans);
16
- onStatus?.("Planned run.");
17
- },
18
-
19
- setTotalFileCount(count) {
20
- inspectState.setTotalFileCount(count);
21
- },
22
-
23
- setRegressionCatalog(document) {
24
- inspectState.setRegressionCatalog(document);
25
- },
26
-
27
- serviceSkipped(config, reason) {
28
- inspectState.markServiceSkipped(config.name, reason);
29
- },
30
-
31
- plannedSkip(entry) {
32
- inspectState.markPlannedSkip(entry);
33
- },
34
-
35
- taskStarted(task) {
36
- const suiteKey = `${task.displayType || suiteSelectionType(task.type, task.framework)}:${task.suiteName}`;
37
- applyReporterTaskStarted(inspectState, task, suiteKey);
38
- },
39
-
40
- taskFinished(task, outcome) {
41
- applyReporterTaskFinished(inspectState, task, outcome);
42
- if (outcome.failed) {
43
- onStatus?.(`Failed ${task.file}`);
44
- }
45
- },
46
-
47
- runtimeError(task, message) {
48
- inspectState.markRuntimeError(task, message);
49
- },
50
-
51
- setupOperationFinished() {},
52
-
53
- phaseStarted(label) {
54
- inspectState.setPhase(label);
55
- onStatus?.(label);
56
- },
57
-
58
- toolchainResolved() {},
59
- localServiceStarting() {},
60
- writeLine() {},
61
- writeDebugLine() {},
62
- telemetry() {},
63
-
64
- runSummary(results, durationMs, regressionReport) {
65
- applyReporterRunSummary(inspectState, results, durationMs, regressionReport);
66
- onStatus?.("Run finished.");
67
- },
68
-
69
- error(message) {
70
- onStatus?.(String(message));
71
- },
72
- },
73
-
74
- finalize: Promise.resolve(),
75
-
76
- close() {
77
- // No long-lived UI resources to close.
78
- },
79
- };
80
- }