validate

package
v1.7.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 2, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package validate is the engine behind `dockyard validate` — the quality-gate verb (RFC §9.4).

It runs the project-level quality checks the RFC §9.4 taxonomy defines and reports them as a structured Report of Diagnostics, each carrying a Severity. A Blocker diagnostic is a build blocker — `dockyard validate` exits non-zero when the Report carries any. A Warning is reported but does not change the exit code.

The checks

Run performs, in order:

  • manifest — dockyard.app.yaml is schema-valid and structurally well-formed (delegated to internal/manifest, which checks required fields, enums, uniqueness, tool↔UI cross-references and Tasks-limit coherence);
  • schema — every generated <tool>_<side>.schema.json is present and is a valid, resolvable JSON Schema;
  • tool↔UI mapping — every tool that declares a ui:// resource maps to a real apps[] entry and vice versa, and each App's .svelte entry file exists on disk;
  • MIME — each App resource carries the single MVP Apps MIME type (text/html;profile=mcp-app) and a well-formed ui:// URI;
  • spec compliance — Apps/Tasks manifest constructs are checked against the vendored MCP specs in docs/specifications/, never a live host (CLAUDE.md §11);
  • UI states — the four-state page rule (CLAUDE.md §20): when a quality.* gate is opted in, the App's .svelte source is checked for the required loading / empty / error / permission state markers;
  • stale codegen — the generated schema and TypeScript on disk are compared byte-for-byte against a fresh regeneration (internal/codegen.CheckStale). Stale generated output is a build blocker (RFC §6.2, P1).
  • cross-codegen — the committed schema and the committed TypeScript on disk are cross-checked with internal/codegen.CrossCheck so a hand-edited `contracts.ts` that disagrees with the schema is a build blocker (RFC §6.2, P1). `validate` deliberately checks what is checked in, not a fresh regeneration; this gates a desync that, at the validate-standalone or `dockyard test` entrypoint, has not been rewritten by a regeneration step. (`dockyard build` runs a regeneration BEFORE invoking the validate gate, so at build time a hand-edited drift is repaired rather than reported — see D-113. Either way the build artifact upholds P1.)

Reusable seam

Run is exported so `dockyard build` (Phase 20) and `dockyard test` (Phase 21) invoke the same gate the `dockyard validate` verb wraps — the validation logic lives here, not in the CLI command. Run builds fresh state per call and holds no shared mutable state.

Index

Constants

This section is empty.

Variables

View Source
var ErrValidate = errors.New("dockyard/internal/validate: validation could not run")

ErrValidate is the sentinel wrapping a validate failure that is not itself a quality diagnostic — an I/O fault, a missing project, an internal error. A quality fault is a Diagnostic in the Report, never a returned error: Run returns a nil error and a Report carrying the faults. Callers branch with errors.Is(err, ErrValidate).

Functions

This section is empty.

Types

type Check

type Check string

Check identifies which RFC §9.4 check class produced a Diagnostic.

const (
	// CheckManifest — dockyard.app.yaml schema and structural validity.
	CheckManifest Check = "manifest"
	// CheckSchema — the generated JSON Schema artifacts.
	CheckSchema Check = "schema"
	// CheckMapping — tool↔UI resource mappings.
	CheckMapping Check = "tool-ui-mapping"
	// CheckMIME — UI resource MIME types.
	CheckMIME Check = "mime"
	// CheckSpec — MCP spec compliance against the vendored specs.
	CheckSpec Check = "spec-compliance"
	// CheckUIStates — the four-state page rule (CLAUDE.md §20).
	CheckUIStates Check = "ui-states"
	// CheckStaleCodegen — generated output drift from the Go contract structs.
	CheckStaleCodegen Check = "stale-codegen"
	// CheckFixtures — quality.require_fixtures: a UI-bearing tool must ship
	// inspector fixtures (D-168, D-169).
	CheckFixtures Check = "fixtures"
	// CheckContractTests — quality.require_contract_tests: the project must
	// carry a contract test (D-168).
	CheckContractTests Check = "contract-tests"
)

type Diagnostic

type Diagnostic struct {
	// Check is the RFC §9.4 class that produced this finding.
	Check Check
	// Severity is Blocker or Warning.
	Severity Severity
	// Message is the human-facing, actionable description.
	Message string
}

Diagnostic is one quality finding.

func (Diagnostic) String

func (d Diagnostic) String() string

String renders a Diagnostic as one actionable line.

type Options

type Options struct {
	// ProjectDir is the root of the Dockyard project — the directory holding
	// dockyard.app.yaml. Required.
	ProjectDir string
}

Options configures one validate run.

type Report

type Report struct {
	// Diagnostics is every finding, in check order then discovery order.
	Diagnostics []Diagnostic
}

Report is the structured outcome of a validate run: every Diagnostic across every check, plus the aggregate verdict. It is the value `dockyard build` (Phase 20) and `dockyard test` (Phase 21) consume to gate their own work.

func Run

func Run(opts Options) (*Report, error)

Run validates the Dockyard project rooted at opts.ProjectDir against the RFC §9.4 quality gates and returns a Report.

A non-nil error means validation could not be performed at all (a missing project, an I/O fault) — it wraps ErrValidate. A quality fault is never a returned error: it is a Diagnostic in the Report. The caller decides the exit code from Report.HasBlockers.

The manifest check runs first and is load-bearing: a manifest that will not load at all is reported as a Blocker and the remaining checks that need a loaded manifest are skipped (there is nothing coherent to check against).

Run builds fresh state per call and holds no shared mutable state.

func (*Report) Blockers

func (r *Report) Blockers() []Diagnostic

Blockers returns only the build-blocker diagnostics.

func (*Report) HasBlockers

func (r *Report) HasBlockers() bool

HasBlockers reports whether the Report carries any Blocker diagnostic — the exit-code seam: `dockyard validate` exits non-zero exactly when this is true.

func (*Report) Warnings

func (r *Report) Warnings() []Diagnostic

Warnings returns only the warning diagnostics.

type Severity

type Severity int

Severity classifies a Diagnostic. The taxonomy follows RFC §9.4.

const (
	// Blocker is a build blocker (RFC §9.4): an invalid manifest or schema, a
	// missing or mismatched ui:// resource, an invalid MIME, a spec violation,
	// or stale generated contracts. A Report carrying any Blocker forces a
	// non-zero `dockyard validate` exit.
	Blocker Severity = iota
	// Warning is a non-blocking quality signal (RFC §9.4): a UI payload routed
	// into content, a vague description, a missing graceful-degradation path.
	// It is reported but does not change the exit code.
	Warning
)

func (Severity) String

func (s Severity) String() string

String renders a Severity for output.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL