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 ¶
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 ¶
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 ¶
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 )