fix: close CLI term gaps — workspace rejection, stale types, quiet, placebo, help
This commit is contained in:
@@ -26,16 +26,6 @@ import { runDocsChecks } from './checks/docs.js';
|
|||||||
|
|
||||||
import { renderJson } from '../../renderers/json.js';
|
import { renderJson } from '../../renderers/json.js';
|
||||||
|
|
||||||
// Deterministic string-to-seed hash (FNV-1a)
|
|
||||||
function hashStringToSeed(str: string): number {
|
|
||||||
let hash = 0x811c9dc5
|
|
||||||
for (let i = 0; i < str.length; i++) {
|
|
||||||
hash ^= str.charCodeAt(i)
|
|
||||||
hash = Math.imul(hash, 0x01000193)
|
|
||||||
}
|
|
||||||
return Math.abs(hash >>> 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Types
|
// Types
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -206,17 +196,6 @@ async function runPackageChecks(
|
|||||||
checks.push({ ...result, package: packageName });
|
checks.push({ ...result, package: packageName });
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. Determinism trust signal
|
|
||||||
const testSeed = hashStringToSeed(packageName + cwd);
|
|
||||||
checks.push({
|
|
||||||
name: 'determinism',
|
|
||||||
status: 'pass',
|
|
||||||
message: `Environment supports deterministic replay (test seed: ${testSeed})`,
|
|
||||||
detail: `Run with --seed ${testSeed} to reproduce the exact same test sequence`,
|
|
||||||
mode: 'all',
|
|
||||||
package: packageName,
|
|
||||||
});
|
|
||||||
|
|
||||||
return checks;
|
return checks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -622,7 +622,7 @@ function parseInitOptions(args: string[], ctx: CliContext): InitOptions {
|
|||||||
export async function handleInit(args: string[], ctx: CliContext): Promise<number> {
|
export async function handleInit(args: string[], ctx: CliContext): Promise<number> {
|
||||||
const result = await initHandler(args, ctx);
|
const result = await initHandler(args, ctx);
|
||||||
|
|
||||||
if (result.message) {
|
if (result.message && !ctx.options.quiet) {
|
||||||
console.log(result.message);
|
console.log(result.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -328,6 +328,20 @@ export async function handleObserve(
|
|||||||
checks: result.checks,
|
checks: result.checks,
|
||||||
message: result.message,
|
message: result.message,
|
||||||
}) + '\n');
|
}) + '\n');
|
||||||
|
} else if (format === 'json-summary') {
|
||||||
|
console.log(renderJson({
|
||||||
|
exitCode: result.exitCode,
|
||||||
|
checks: result.checks,
|
||||||
|
message: result.message,
|
||||||
|
}));
|
||||||
|
} else if (format === 'ndjson-summary') {
|
||||||
|
process.stdout.write(JSON.stringify({
|
||||||
|
type: 'run.completed',
|
||||||
|
command: 'observe',
|
||||||
|
exitCode: result.exitCode,
|
||||||
|
checks: result.checks,
|
||||||
|
message: result.message,
|
||||||
|
}) + '\n');
|
||||||
} else {
|
} else {
|
||||||
console.log(result.message);
|
console.log(result.message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ export interface QualifyOptions {
|
|||||||
changed?: boolean
|
changed?: boolean
|
||||||
config?: string
|
config?: string
|
||||||
cwd?: string
|
cwd?: string
|
||||||
format?: 'human' | 'json' | 'ndjson'
|
format?: 'human' | 'json' | 'ndjson' | 'json-summary' | 'ndjson-summary'
|
||||||
quiet?: boolean
|
quiet?: boolean
|
||||||
verbose?: boolean
|
verbose?: boolean
|
||||||
artifactDir?: string
|
artifactDir?: string
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export interface VerifyOptions {
|
|||||||
changed?: boolean
|
changed?: boolean
|
||||||
config?: string
|
config?: string
|
||||||
cwd?: string
|
cwd?: string
|
||||||
format?: 'human' | 'json' | 'ndjson'
|
format?: 'human' | 'json' | 'ndjson' | 'json-summary' | 'ndjson-summary'
|
||||||
quiet?: boolean
|
quiet?: boolean
|
||||||
verbose?: boolean
|
verbose?: boolean
|
||||||
artifactDir?: string
|
artifactDir?: string
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ function getCommandHelp(command: string): string {
|
|||||||
apophis init [options]
|
apophis init [options]
|
||||||
|
|
||||||
${pc.dim('Options:')}
|
${pc.dim('Options:')}
|
||||||
--preset <name> Preset name (e.g. safe-ci, full)
|
--preset, -p <name> Preset name (e.g. safe-ci, full)
|
||||||
--force Overwrite existing files
|
--force, -f Overwrite existing files
|
||||||
--noninteractive Skip all prompts, require explicit flags
|
--noninteractive Skip all prompts, require explicit flags
|
||||||
|
|
||||||
${pc.dim('Examples:')}
|
${pc.dim('Examples:')}
|
||||||
@@ -116,9 +116,11 @@ function getCommandHelp(command: string): string {
|
|||||||
|
|
||||||
${pc.dim('Options:')}
|
${pc.dim('Options:')}
|
||||||
--artifact <path> Path to failure artifact
|
--artifact <path> Path to failure artifact
|
||||||
|
--route <filter> Select failure by route pattern
|
||||||
|
|
||||||
${pc.dim('Examples:')}
|
${pc.dim('Examples:')}
|
||||||
apophis replay --artifact reports/apophis/failure-*.json
|
apophis replay --artifact reports/apophis/failure-*.json
|
||||||
|
apophis replay --artifact failure-1.json --route "POST /users"
|
||||||
`,
|
`,
|
||||||
doctor: `
|
doctor: `
|
||||||
${pc.bold('apophis doctor')} — Validate config, environment safety, docs/example correctness
|
${pc.bold('apophis doctor')} — Validate config, environment safety, docs/example correctness
|
||||||
@@ -377,8 +379,8 @@ export async function main(argv: string[] = process.argv.slice(2)): Promise<numb
|
|||||||
const commandSpecificFlags: Record<string, Set<string>> = {
|
const commandSpecificFlags: Record<string, Set<string>> = {
|
||||||
init: new Set(['--preset', '-p', '--force', '-f', '--noninteractive']),
|
init: new Set(['--preset', '-p', '--force', '-f', '--noninteractive']),
|
||||||
verify: new Set(['--profile', '--routes', '--seed', '--changed', '--workspace']),
|
verify: new Set(['--profile', '--routes', '--seed', '--changed', '--workspace']),
|
||||||
observe: new Set(['--profile', '--check-config', '--workspace']),
|
observe: new Set(['--profile', '--check-config']),
|
||||||
qualify: new Set(['--profile', '--seed', '--workspace', '--changed']),
|
qualify: new Set(['--profile', '--seed', '--changed']),
|
||||||
replay: new Set(['--artifact', '--route']),
|
replay: new Set(['--artifact', '--route']),
|
||||||
doctor: new Set(['--mode', '--strict', '--workspace']),
|
doctor: new Set(['--mode', '--strict', '--workspace']),
|
||||||
migrate: new Set(['--check', '--dry-run', '--write']),
|
migrate: new Set(['--check', '--dry-run', '--write']),
|
||||||
|
|||||||
Reference in New Issue
Block a user