mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
* feat(cli): od lint — CLI half of the live artifact linter POST /api/artifacts/lint has been reachable by the web layer since the linter landed, but had no SUBCOMMAND_MAP entry, leaving it invisible to external agents in violation of the dual-track rule. Adds the shared DTO in contracts and a runLint mirroring runExport's flag shape (stdin via '-', --json envelope, --fail-on threshold, exit 1 on findings at/above). * address review: contracts as producer authority, cli-lint entrypoint spec, root-help discoverability - lint-artifact.ts now imports ArtifactLintFinding/ArtifactLintSeverity from @open-design/contracts and aliases the legacy exported names to them, so lintArtifact() is typed by the shared contract and a producer change that breaks the wire shape fails compilation instead of drifting behind the CLI's consumer-side assertion. The lint route types its request/response against LintArtifactRequest/Response. - New tests/cli-lint.test.ts on the cli-templates/cli-deploy stub-server harness: file + stdin input, all four --fail-on thresholds, clean and finding responses, human/--json/--agent-message output, usage errors (unknown flag, bad threshold, missing/empty file), HTTP failure (structured exit 64), unreachable daemon (exit 3), and root-help presence. 12 specs. - printRootHelp() lists od lint beside od export with its headless/ threshold purpose. --------- Co-authored-by: Cruz Morales <273886418+DojoGenesis@users.noreply.github.com>
54 lines
1.6 KiB
TypeScript
54 lines
1.6 KiB
TypeScript
// Artifact lint — the anti-slop linter's wire contract.
|
|
//
|
|
// The daemon has served POST /api/artifacts/lint (and returned the same
|
|
// findings inline from POST /api/artifacts/save) since the linter landed,
|
|
// but the shape only ever existed as a private type in
|
|
// apps/daemon/src/lint-artifact.ts. This file makes it a shared DTO so the
|
|
// CLI (`od lint`) and web surfaces parse one contract instead of
|
|
// re-declaring the daemon's internals.
|
|
|
|
export type ArtifactLintSeverity = 'P0' | 'P1' | 'P2';
|
|
|
|
export interface ArtifactLintFinding {
|
|
severity: ArtifactLintSeverity;
|
|
/** Stable rule id, e.g. `purple-gradient`, `invented-metric`. */
|
|
id: string;
|
|
message: string;
|
|
/** Actionable remediation, phrased for the generating agent. */
|
|
fix: string;
|
|
/** Offending excerpt when the rule can isolate one. */
|
|
snippet?: string;
|
|
}
|
|
|
|
export interface LintArtifactRequest {
|
|
html: string;
|
|
}
|
|
|
|
export interface LintArtifactResponse {
|
|
findings: ArtifactLintFinding[];
|
|
/**
|
|
* Findings pre-rendered as an `<artifact-lint>` block, formatted to be
|
|
* spliced into the generating agent's next turn for self-correction.
|
|
*/
|
|
agentMessage: string;
|
|
}
|
|
|
|
/** Severity threshold for `od lint`'s exit code. `none` never fails. */
|
|
export type LintFailOn = 'p0' | 'p1' | 'p2' | 'none';
|
|
|
|
export interface LintArtifactCliCounts {
|
|
p0: number;
|
|
p1: number;
|
|
p2: number;
|
|
}
|
|
|
|
/** Machine envelope printed by `od lint --json`. */
|
|
export interface LintArtifactCliResultEnvelope {
|
|
ok: boolean;
|
|
file: string;
|
|
failOn: LintFailOn;
|
|
counts: LintArtifactCliCounts;
|
|
findings: ArtifactLintFinding[];
|
|
agentMessage: string;
|
|
}
|