@qa-ai-stlc/cli 0.1.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/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # @qa-ai-stlc/cli
2
+
3
+ The `qa` command: a thin client over `@qa-ai-stlc/core` for CI and humans. `qa init` creates the
4
+ `.qa/` store and a starting `config.yaml`; `qa doctor` checks Node, browsers, identities and
5
+ environment reachability before a run. Every command supports `--json` for machine-readable
6
+ output and exits non-zero on failure.
7
+
8
+ Part of [QA-AI-STLC](https://github.com/Klim-101/QA-AI-STLC). See the repository root for
9
+ license, contributing and security information.
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=qa.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qa.d.ts","sourceRoot":"","sources":["../../src/bin/qa.ts"],"names":[],"mappings":""}
package/dist/bin/qa.js ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ // Copyright The QA-AI-STLC Authors
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import { processIO } from '../cli-io.js';
5
+ import { runCli } from '../cli.js';
6
+ // The one place `process.exit` is allowed (AGENTS.md 5.4); `runCli` itself only returns a code.
7
+ const exitCode = await runCli(process.argv.slice(2), { io: processIO });
8
+ process.exit(exitCode);
9
+ //# sourceMappingURL=qa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qa.js","sourceRoot":"","sources":["../../src/bin/qa.ts"],"names":[],"mappings":";AACA,mCAAmC;AACnC,sCAAsC;AAEtC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,gGAAgG;AAChG,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;AACxE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Where a command sends its output, injected so every command is testable without touching real
3
+ * process streams (AGENTS.md 5.3). `stdout` carries human or `--json` output; `stderr` carries
4
+ * diagnostics (AGENTS.md 5.8).
5
+ */
6
+ export interface CliIO {
7
+ stdout(line: string): void;
8
+ stderr(line: string): void;
9
+ }
10
+ export declare const processIO: CliIO;
11
+ //# sourceMappingURL=cli-io.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-io.d.ts","sourceRoot":"","sources":["../src/cli-io.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,WAAW,KAAK;IACpB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,eAAO,MAAM,SAAS,EAAE,KAOvB,CAAC"}
package/dist/cli-io.js ADDED
@@ -0,0 +1,11 @@
1
+ // Copyright The QA-AI-STLC Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ export const processIO = {
4
+ stdout: (line) => {
5
+ process.stdout.write(`${line}\n`);
6
+ },
7
+ stderr: (line) => {
8
+ process.stderr.write(`${line}\n`);
9
+ },
10
+ };
11
+ //# sourceMappingURL=cli-io.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-io.js","sourceRoot":"","sources":["../src/cli-io.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAYtC,MAAM,CAAC,MAAM,SAAS,GAAU;IAC9B,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;IACpC,CAAC;IACD,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;IACpC,CAAC;CACF,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import type { CliIO } from './cli-io.js';
2
+ import { type CreateCommandContextOptions } from './command-context.js';
3
+ export type RunCliDependencies = Omit<CreateCommandContextOptions, 'projectRoot' | 'json'> & {
4
+ readonly io: CliIO;
5
+ readonly projectRoot?: string;
6
+ };
7
+ /**
8
+ * Parses argv and dispatches to a command, returning the process exit code (AGENTS.md 5.4:
9
+ * `process.exit` itself belongs only in the bin entry point). Never throws: an unexpected error
10
+ * is reported on `stderr` and turned into `EXIT_FAILURE` instead of an uncaught stack trace.
11
+ */
12
+ export declare function runCli(argv: readonly string[], dependencies: RunCliDependencies): Promise<number>;
13
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAwB,KAAK,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAK9F,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,2BAA2B,EAAE,aAAa,GAAG,MAAM,CAAC,GAAG;IAC3F,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAmBF;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,YAAY,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BvG"}
package/dist/cli.js ADDED
@@ -0,0 +1,133 @@
1
+ // Copyright The QA-AI-STLC Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { createRequire } from 'node:module';
4
+ import { parseArgs } from 'node:util';
5
+ import { QaError } from '@qa-ai-stlc/core';
6
+ import { createCommandContext } from './command-context.js';
7
+ import { runDoctor } from './commands/doctor.js';
8
+ import { runInit } from './commands/init.js';
9
+ import { EXIT_FAILURE, EXIT_SUCCESS, EXIT_USAGE } from './exit-codes.js';
10
+ const USAGE = `Usage: qa <command> [options]
11
+
12
+ Commands:
13
+ init Create the .qa/ store and a starting config.yaml
14
+ doctor Check Node, browsers, identities and environment reachability
15
+
16
+ Global options:
17
+ --json Print machine-readable JSON instead of human text
18
+ -h, --help Show this help
19
+ --version Show the CLI version`;
20
+ function readCliVersion() {
21
+ const require = createRequire(import.meta.url);
22
+ const packageJson = require('../package.json');
23
+ return packageJson.version;
24
+ }
25
+ /**
26
+ * Parses argv and dispatches to a command, returning the process exit code (AGENTS.md 5.4:
27
+ * `process.exit` itself belongs only in the bin entry point). Never throws: an unexpected error
28
+ * is reported on `stderr` and turned into `EXIT_FAILURE` instead of an uncaught stack trace.
29
+ */
30
+ export async function runCli(argv, dependencies) {
31
+ const { io } = dependencies;
32
+ const [command, ...rest] = argv;
33
+ if (command === undefined || command === '--help' || command === '-h') {
34
+ io.stdout(USAGE);
35
+ return command === undefined ? EXIT_USAGE : EXIT_SUCCESS;
36
+ }
37
+ if (command === '--version') {
38
+ io.stdout(readCliVersion());
39
+ return EXIT_SUCCESS;
40
+ }
41
+ try {
42
+ switch (command) {
43
+ case 'init':
44
+ return await dispatchInit(rest, dependencies);
45
+ case 'doctor':
46
+ return await dispatchDoctor(rest, dependencies);
47
+ default:
48
+ io.stderr(`Unknown command "${command}".\n\n${USAGE}`);
49
+ return EXIT_USAGE;
50
+ }
51
+ }
52
+ catch (error) {
53
+ return reportError(io, error);
54
+ }
55
+ }
56
+ function isParseArgsError(error) {
57
+ return (error instanceof Error &&
58
+ 'code' in error &&
59
+ typeof error.code === 'string' &&
60
+ error.code.startsWith('ERR_PARSE_ARGS'));
61
+ }
62
+ function reportError(io, error) {
63
+ if (isParseArgsError(error)) {
64
+ io.stderr(`error: ${error.message}\n\n${USAGE}`);
65
+ return EXIT_USAGE;
66
+ }
67
+ if (error instanceof QaError) {
68
+ io.stderr(`error: ${error.message}`);
69
+ if (error.remediation !== undefined) {
70
+ io.stderr(error.remediation);
71
+ }
72
+ return EXIT_FAILURE;
73
+ }
74
+ io.stderr(`error: ${error instanceof Error ? error.message : String(error)}`);
75
+ return EXIT_FAILURE;
76
+ }
77
+ function parseCommandArgs(rest, options) {
78
+ const { values } = parseArgs({ args: [...rest], options, allowPositionals: false, strict: true });
79
+ return values;
80
+ }
81
+ async function dispatchInit(rest, dependencies) {
82
+ const values = parseCommandArgs(rest, {
83
+ json: { type: 'boolean', default: false },
84
+ force: { type: 'boolean', default: false },
85
+ });
86
+ const json = values.json === true;
87
+ const context = createCommandContext({
88
+ ...dependencies,
89
+ projectRoot: dependencies.projectRoot ?? process.cwd(),
90
+ json,
91
+ });
92
+ const result = await runInit(context, { force: values.force === true });
93
+ printResult(context.io, json, 'init', result, formatInitResult(result));
94
+ return EXIT_SUCCESS;
95
+ }
96
+ async function dispatchDoctor(rest, dependencies) {
97
+ const values = parseCommandArgs(rest, {
98
+ json: { type: 'boolean', default: false },
99
+ fix: { type: 'boolean', default: false },
100
+ });
101
+ const json = values.json === true;
102
+ const context = createCommandContext({
103
+ ...dependencies,
104
+ projectRoot: dependencies.projectRoot ?? process.cwd(),
105
+ json,
106
+ });
107
+ const report = await runDoctor(context, { fix: values.fix === true });
108
+ printResult(context.io, json, 'doctor', report, formatDoctorReport(report));
109
+ return report.ok ? EXIT_SUCCESS : EXIT_FAILURE;
110
+ }
111
+ function printResult(io, json, command, data, humanLines) {
112
+ if (json) {
113
+ io.stdout(JSON.stringify({ command, data }));
114
+ return;
115
+ }
116
+ for (const line of humanLines) {
117
+ io.stdout(line);
118
+ }
119
+ }
120
+ function formatInitResult(result) {
121
+ if (result.alreadyInitialized && result.created.length === 0) {
122
+ return [`${result.qaDir} already initialized; nothing to do.`];
123
+ }
124
+ return [`Initialized ${result.qaDir}`, ...result.created.map((file) => ` wrote ${file}`)];
125
+ }
126
+ function formatDoctorReport(report) {
127
+ return report.checks.map((check) => {
128
+ const marker = check.status === 'pass' ? 'PASS' : 'FAIL';
129
+ const remediation = check.remediation !== undefined ? ` — ${check.remediation}` : '';
130
+ return `[${marker}] ${check.name}: ${check.message}${remediation}`;
131
+ });
132
+ }
133
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { type Clock, type FileSystem, type HttpClient, type Logger, type ProcessRunner } from '@qa-ai-stlc/core';
2
+ import type { CliIO } from './cli-io.js';
3
+ /**
4
+ * Everything a command needs, injected so commands are testable without real I/O, a real clock
5
+ * or a real child process (AGENTS.md 5.3). `runCli` builds one context per invocation from the
6
+ * real Node adapters; tests build one from fakes.
7
+ */
8
+ export interface CommandContext {
9
+ readonly projectRoot: string;
10
+ readonly io: CliIO;
11
+ readonly json: boolean;
12
+ readonly fs: FileSystem;
13
+ readonly clock: Clock;
14
+ readonly logger: Logger;
15
+ readonly processRunner: ProcessRunner;
16
+ readonly httpClient: HttpClient;
17
+ readonly env: Readonly<Record<string, string | undefined>>;
18
+ }
19
+ export interface CreateCommandContextOptions {
20
+ readonly projectRoot: string;
21
+ readonly io: CliIO;
22
+ readonly json?: boolean;
23
+ readonly fs?: FileSystem;
24
+ readonly clock?: Clock;
25
+ readonly logger?: Logger;
26
+ readonly processRunner?: ProcessRunner;
27
+ readonly httpClient?: HttpClient;
28
+ readonly env?: Readonly<Record<string, string | undefined>>;
29
+ }
30
+ export declare function createCommandContext(options: CreateCommandContextOptions): CommandContext;
31
+ //# sourceMappingURL=command-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-context.d.ts","sourceRoot":"","sources":["../src/command-context.ts"],"names":[],"mappings":"AAGA,OAAO,EAML,KAAK,KAAK,EACV,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,MAAM,EACX,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;CAC7D;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,GAAG,cAAc,CAYzF"}
@@ -0,0 +1,17 @@
1
+ // Copyright The QA-AI-STLC Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { fetchHttpClient, nodeFileSystem, nodeProcessRunner, noopLogger, systemClock, } from '@qa-ai-stlc/core';
4
+ export function createCommandContext(options) {
5
+ return {
6
+ projectRoot: options.projectRoot,
7
+ io: options.io,
8
+ json: options.json ?? false,
9
+ fs: options.fs ?? nodeFileSystem,
10
+ clock: options.clock ?? systemClock,
11
+ logger: options.logger ?? noopLogger,
12
+ processRunner: options.processRunner ?? nodeProcessRunner,
13
+ httpClient: options.httpClient ?? fetchHttpClient,
14
+ env: options.env ?? process.env,
15
+ };
16
+ }
17
+ //# sourceMappingURL=command-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-context.js","sourceRoot":"","sources":["../src/command-context.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,OAAO,EACL,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,UAAU,EACV,WAAW,GAMZ,MAAM,kBAAkB,CAAC;AAgC1B,MAAM,UAAU,oBAAoB,CAAC,OAAoC;IACvE,OAAO;QACL,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,KAAK;QAC3B,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,cAAc;QAChC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,WAAW;QACnC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,UAAU;QACpC,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,iBAAiB;QACzD,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,eAAe;QACjD,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG;KAChC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { type DoctorCheckResult } from '@qa-ai-stlc/core';
2
+ import type { CommandContext } from '../command-context.js';
3
+ export interface DoctorOptions {
4
+ readonly fix?: boolean;
5
+ }
6
+ export interface DoctorReport {
7
+ readonly ok: boolean;
8
+ readonly checks: readonly DoctorCheckResult[];
9
+ }
10
+ /**
11
+ * `qa doctor`: Node version, browser binaries, and, once a `config.yaml` exists, every
12
+ * identity's secret and every environment's reachability (ADR-004). `--fix` installs missing
13
+ * browsers through Playwright's own installer before reporting their final state.
14
+ */
15
+ export declare function runDoctor(context: CommandContext, options?: DoctorOptions): Promise<DoctorReport>;
16
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAGA,OAAO,EAUL,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,SAAS,iBAAiB,EAAE,CAAC;CAC/C;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAe3G"}
@@ -0,0 +1,63 @@
1
+ // Copyright The QA-AI-STLC Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { QaError, QaStore, SUPPORTED_BROWSERS, checkBaseUrlReachable, checkBrowserInstalled, checkIdentitiesPresent, checkNodeVersion, installBrowsers, loadConfig, } from '@qa-ai-stlc/core';
4
+ /**
5
+ * `qa doctor`: Node version, browser binaries, and, once a `config.yaml` exists, every
6
+ * identity's secret and every environment's reachability (ADR-004). `--fix` installs missing
7
+ * browsers through Playwright's own installer before reporting their final state.
8
+ */
9
+ export async function runDoctor(context, options = {}) {
10
+ const store = new QaStore({ projectRoot: context.projectRoot, fs: context.fs });
11
+ let checks = [checkNodeVersion()];
12
+ for (const browser of SUPPORTED_BROWSERS) {
13
+ checks.push(await checkBrowserInstalled(context.fs, browser));
14
+ }
15
+ if (options.fix === true) {
16
+ checks = await fixMissingBrowsers(context, checks);
17
+ }
18
+ checks = [...checks, ...(await runConfigChecks(context, store))];
19
+ return { ok: checks.every((check) => check.status === 'pass'), checks };
20
+ }
21
+ async function fixMissingBrowsers(context, checks) {
22
+ const missing = SUPPORTED_BROWSERS.filter((browser) => checks.some((check) => check.name === `browser:${browser}` && check.status === 'fail'));
23
+ if (missing.length === 0) {
24
+ return [...checks];
25
+ }
26
+ const installResult = await installBrowsers(context.processRunner, missing);
27
+ const rechecked = new Map(await Promise.all(missing.map(async (browser) => [
28
+ `browser:${browser}`,
29
+ await checkBrowserInstalled(context.fs, browser),
30
+ ])));
31
+ return [...checks.map((check) => rechecked.get(check.name) ?? check), installResult];
32
+ }
33
+ async function runConfigChecks(context, store) {
34
+ let config;
35
+ try {
36
+ config = await loadConfig(store);
37
+ }
38
+ catch (error) {
39
+ if (error instanceof QaError) {
40
+ // Every QaError `loadConfig` throws (CONFIG_MISSING, CONFIG_MALFORMED, CONFIG_INVALID)
41
+ // sets a remediation; the cast documents that invariant instead of a defensive branch no
42
+ // config-loader failure can actually exercise. A `!` assertion reads more naturally here,
43
+ // but AGENTS.md 5.2 restricts those to tests.
44
+ return [
45
+ {
46
+ name: 'config',
47
+ status: 'fail',
48
+ message: error.message,
49
+ // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style
50
+ remediation: error.remediation,
51
+ },
52
+ ];
53
+ }
54
+ throw error;
55
+ }
56
+ const identityChecks = checkIdentitiesPresent(config.identities, context.env);
57
+ const environmentChecks = await Promise.all(Object.entries(config.environments).map(async ([name, environment]) => {
58
+ const result = await checkBaseUrlReachable(environment.baseUrl, { httpClient: context.httpClient });
59
+ return { ...result, name: `environment:${name}` };
60
+ }));
61
+ return [...identityChecks, ...environmentChecks];
62
+ }
63
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { CommandContext } from '../command-context.js';
2
+ export interface InitOptions {
3
+ readonly force?: boolean;
4
+ }
5
+ export interface InitResult {
6
+ readonly qaDir: string;
7
+ readonly created: readonly string[];
8
+ readonly alreadyInitialized: boolean;
9
+ }
10
+ /**
11
+ * `qa init`: creates the documented `.qa/` layout (development plan section 3.2), a starting
12
+ * `config.yaml` with every testing type `undecided`, and a `.gitignore` for the runtime-only
13
+ * subdirectories. Never overwrites an existing `config.yaml` unless `force` is set, so a second
14
+ * run is safe.
15
+ */
16
+ export declare function runInit(context: CommandContext, options?: InitOptions): Promise<InitResult>;
17
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;CACtC;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,CAsBrG"}
@@ -0,0 +1,31 @@
1
+ // Copyright The QA-AI-STLC Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { QaStore } from '@qa-ai-stlc/core';
4
+ import { CONFIG_TEMPLATE, QA_GITIGNORE } from '../config-template.js';
5
+ /**
6
+ * `qa init`: creates the documented `.qa/` layout (development plan section 3.2), a starting
7
+ * `config.yaml` with every testing type `undecided`, and a `.gitignore` for the runtime-only
8
+ * subdirectories. Never overwrites an existing `config.yaml` unless `force` is set, so a second
9
+ * run is safe.
10
+ */
11
+ export async function runInit(context, options = {}) {
12
+ const store = new QaStore({ projectRoot: context.projectRoot, fs: context.fs });
13
+ const configExisted = await store.pathExists('config.yaml');
14
+ await store.ensureLayout();
15
+ const created = [];
16
+ if (!configExisted || options.force === true) {
17
+ await store.writeText('config.yaml', CONFIG_TEMPLATE);
18
+ created.push('config.yaml');
19
+ }
20
+ const gitignoreExisted = await store.pathExists('.gitignore');
21
+ if (!gitignoreExisted || options.force === true) {
22
+ await store.writeText('.gitignore', QA_GITIGNORE);
23
+ created.push('.gitignore');
24
+ }
25
+ return {
26
+ qaDir: store.qaDir,
27
+ created,
28
+ alreadyInitialized: configExisted && options.force !== true,
29
+ };
30
+ }
31
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAYtE;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAuB,EAAE,UAAuB,EAAE;IAC9E,MAAM,KAAK,GAAG,IAAI,OAAO,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAChF,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IAC5D,MAAM,KAAK,CAAC,YAAY,EAAE,CAAC;IAE3B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,aAAa,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QAC7C,MAAM,KAAK,CAAC,SAAS,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC9B,CAAC;IAED,MAAM,gBAAgB,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;IAC9D,IAAI,CAAC,gBAAgB,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,MAAM,KAAK,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,OAAO;QACP,kBAAkB,EAAE,aAAa,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI;KAC5D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare const CONFIG_TEMPLATE: string;
2
+ export declare const QA_GITIGNORE = "# Generated by \"qa init\".\n/runs/\n/evidence/\n/auth/\n";
3
+ //# sourceMappingURL=config-template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-template.d.ts","sourceRoot":"","sources":["../src/config-template.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,eAAe,QA2B3B,CAAC;AAIF,eAAO,MAAM,YAAY,8DAIxB,CAAC"}
@@ -0,0 +1,43 @@
1
+ // Copyright The QA-AI-STLC Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { SCHEMA_VERSION } from '@qa-ai-stlc/schemas';
4
+ // A safe starting point every "qa init" writes: every testing type starts "undecided" (the
5
+ // testing-scope survey that turns these into real decisions is P1-18), and `environments` /
6
+ // `identities` start empty so the file validates against `ConfigSchema` before the operator has
7
+ // configured anything (development plan section 3.2, 3.3).
8
+ export const CONFIG_TEMPLATE = `# QA-AI-STLC project configuration. Generated by "qa init".
9
+ schemaVersion: ${String(SCHEMA_VERSION)}
10
+
11
+ # Web E2E, API, accessibility and security testing are decided independently. An "undecided"
12
+ # type blocks "qa scope" and every later phase until you change it here.
13
+ testing:
14
+ e2e: undecided
15
+ api: undecided
16
+ a11y: undecided
17
+ security: undecided
18
+
19
+ environments: {}
20
+
21
+ identities: {}
22
+
23
+ data:
24
+ strategy: manual
25
+ ownerMarker: qa-ai-stlc
26
+
27
+ selectors:
28
+ policy: playwright-default
29
+ testIdAttribute: data-testid
30
+
31
+ agents:
32
+ parallelism: 1
33
+ spokeTimeoutSeconds: 60
34
+ retries: 1
35
+ `;
36
+ // Runtime-only subdirectories (development plan section 3.2): everything else under `.qa/` is
37
+ // meant to be committed.
38
+ export const QA_GITIGNORE = `# Generated by "qa init".
39
+ /runs/
40
+ /evidence/
41
+ /auth/
42
+ `;
43
+ //# sourceMappingURL=config-template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-template.js","sourceRoot":"","sources":["../src/config-template.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,2FAA2F;AAC3F,4FAA4F;AAC5F,gGAAgG;AAChG,2DAA2D;AAC3D,MAAM,CAAC,MAAM,eAAe,GAAG;iBACd,MAAM,CAAC,cAAc,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BtC,CAAC;AAEF,8FAA8F;AAC9F,yBAAyB;AACzB,MAAM,CAAC,MAAM,YAAY,GAAG;;;;CAI3B,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const EXIT_SUCCESS = 0;
2
+ export declare const EXIT_FAILURE = 1;
3
+ export declare const EXIT_USAGE = 2;
4
+ //# sourceMappingURL=exit-codes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-codes.d.ts","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,eAAO,MAAM,UAAU,IAAI,CAAC"}
@@ -0,0 +1,6 @@
1
+ // Copyright The QA-AI-STLC Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ export const EXIT_SUCCESS = 0;
4
+ export const EXIT_FAILURE = 1;
5
+ export const EXIT_USAGE = 2;
6
+ //# sourceMappingURL=exit-codes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-codes.js","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAC9B,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAC9B,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ export * from './cli.js';
2
+ export * from './cli-io.js';
3
+ export * from './command-context.js';
4
+ export * from './exit-codes.js';
5
+ export * from './commands/init.js';
6
+ export * from './commands/doctor.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ // Copyright The QA-AI-STLC Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ export * from './cli.js';
4
+ export * from './cli-io.js';
5
+ export * from './command-context.js';
6
+ export * from './exit-codes.js';
7
+ export * from './commands/init.js';
8
+ export * from './commands/doctor.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@qa-ai-stlc/cli",
3
+ "version": "0.1.0",
4
+ "description": "The qa command: init, doctor and every deterministic engine operation exposed for CI and humans.",
5
+ "type": "module",
6
+ "license": "Apache-2.0",
7
+ "homepage": "https://github.com/Klim-101/QA-AI-STLC/tree/main/packages/cli#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/Klim-101/QA-AI-STLC.git",
11
+ "directory": "packages/cli"
12
+ },
13
+ "bugs": "https://github.com/Klim-101/QA-AI-STLC/issues",
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "bin": {
18
+ "qa": "./dist/bin/qa.js"
19
+ },
20
+ "exports": {
21
+ ".": "./dist/index.js"
22
+ },
23
+ "scripts": {
24
+ "pretypecheck": "npm run build --workspace @qa-ai-stlc/schemas --workspace @qa-ai-stlc/core --workspace @qa-ai-stlc/test-utils",
25
+ "typecheck": "tsc --noEmit -p .",
26
+ "pretest": "npm run build --workspace @qa-ai-stlc/schemas --workspace @qa-ai-stlc/core --workspace @qa-ai-stlc/test-utils",
27
+ "test": "vitest run",
28
+ "pretest:coverage": "npm run build --workspace @qa-ai-stlc/schemas --workspace @qa-ai-stlc/core --workspace @qa-ai-stlc/test-utils",
29
+ "test:coverage": "vitest run --coverage",
30
+ "build": "tsc -b tsconfig.build.json",
31
+ "clean": "node ../../scripts/clean-dir.mjs dist"
32
+ },
33
+ "dependencies": {
34
+ "@qa-ai-stlc/core": "0.0.0",
35
+ "@qa-ai-stlc/schemas": "0.0.0",
36
+ "yaml": "2.9.1"
37
+ },
38
+ "devDependencies": {
39
+ "@qa-ai-stlc/test-utils": "0.0.0"
40
+ }
41
+ }