esd-local-quality-runtime
v0.2.1
Published
ESD Local Quality Runtime — shared validation engine for VS Code, CLI, and CI
Maintainers
Readme
ESD Local Quality Runtime
Shared validation engine that runs identically in VS Code, CLI, and CI environments.
Features
- Quality Profiles: QUICK, STANDARD, RELEASE gates
- Evidence: JSON-LD format with integrity hashing
- CLI: Command-line interface for CI/CD
- VS Code: Extension adapter
- Extensible: Register custom checks
Installation
npm install -g esd-local-quality-runtimeUsage
# Run quick quality check
esd-quality quick
# Run standard quality check
esd-quality standard
# Run with JSON output (stdout carries only the JSON document; logs go to stderr)
esd-quality standard --json > evidence.json
# Same, writing the JSON document to a file
esd-quality standard --json --output evidence.json
# Run comprehensive release check
esd-quality releaseCLI options
| Option | Effect |
|--------|--------|
| <quick\|standard\|release> | Profile to run (default: standard) |
| --json | Emit the evidence document as JSON. stdout is reserved for the JSON payload, so > file always produces a valid file. All human-readable output moves to stderr. |
| --output <path> | Write the JSON evidence document to path instead of stdout. |
| --submit | Submit the evidence to the ESD Harness (requires ESD_HARNESS_URL and ESD_ACCESS_TOKEN). |
| --ci | Force CI mode (grouped output, GitHub Actions outputs). |
| --dry-run | Reserved. |
Fail-closed profiles
A profile is a governance commitment: it declares the checks a gate must run.
If a declared check is not registered — or is disabled — the engine reports
it as NOT_RUN and the gate does not pass. A check that never ran is never
evidence that a workspace is compliant.
⛔ Declared but not executed (the gate fails closed):
- coverage:threshold
- evidence:schemaCheck statuses
| Status | Meaning | Blocks the gate |
|--------|---------|-----------------|
| PASS | The check ran and found nothing wrong. | no |
| SKIP | The check ran and reported "not applicable to this project" (the tool is not configured, e.g. no Prettier config). Informational. | no |
| FAIL | The check ran and found problems. | yes |
| ERROR | The check ran and could not complete (the tool crashed, the config is broken). | yes |
| NOT_RUN | The check was declared by the profile but never executed. | yes |
A gate where nothing actually passed is not a pass either.
Every check declared by the QUICK, STANDARD and RELEASE profiles is
implemented and registered, so all three profiles are satisfiable. A check
that cannot be applied to the project at hand reports SKIP with the reason
(Prettier not configured in project, Project has no accessibility check
configured, ...), and the reason is part of the evidence.
What each profile runs
| Profile | Checks |
|---------|--------|
| QUICK | lint:quick, format:check, typecheck:basic, secrets:scan |
| STANDARD | lint:full, format:check, typecheck:full, test:unit, security:deps, coverage:threshold, evidence:schema, evidence:integrity |
| RELEASE | everything of STANDARD, plus security:audit, accessibility:a11y, performance:bundle, evidence:signature, evidence:attestation |
Configuration
The thresholds of a project live in .esd/config.json:
{
"thresholds": {
"coverage": { "lines": 80, "statements": 80, "functions": 80, "branches": 70 },
"bundle": { "max_size_kb": 5120 }
}
}The coverage thresholds are a floor: a project sets them to the coverage it
has today and raises them as it grows. A project that runs coverage without
emitting coverage/coverage-summary.json fails the check, because a coverage
that cannot be verified is not a coverage.
Signing and attestation
The evidence of every run carries an attestation: who stands behind the document and the hash of the content it refers to. When a signing key is configured, the document is also signed with ECDSA P-256 and the public key travels with it, so that anyone can verify the document without trusting the producer.
| Variable | Effect |
|----------|--------|
| ESD_EVIDENCE_SIGNING_KEY | The private key (PEM) that signs the evidence |
| ESD_EVIDENCE_SIGNING_KEY_FILE | The file that holds the private key |
| ESD_EVIDENCE_ATTESTOR | The identity that stands behind the evidence |
Evidence integrity
integrity.content_hash is a real SHA-256 over the canonical evidence content
(id, timestamp, profile, checks) and is validated by
EvidenceManager.validate(). The signature covers the same canonical content:
a signature that proved something else would prove nothing.
The trail of a project lives in .esd/. Every document of the trail is
validated against the schema and its hash is recomputed by the
evidence:schema and evidence:integrity checks. A document that was
altered fails the gate.
Quality Profiles
| Profile | Duration | Use Case | Checks | |---------|----------|----------|--------| | QUICK | < 5s | Pre-commit | lint, format, typecheck, secrets | | STANDARD | < 60s | PR/MR | + tests, dependency audit, coverage, evidence | | RELEASE | < 5min | Production | + full audit, accessibility, bundle size, signature, attestation |
Development
# Install dependencies
npm install
# Build
npm run build
# Test
npm test
# Test with coverage
npm run test:coverage
# Type check
npm run typecheck
# Lint
npm run lint
# Format
npx prettier --write .Running the gate on this repository
npm run build
node dist/cli/index.js standard
node dist/cli/index.js releaseThe STANDARD and RELEASE profiles of this repository pass. The
accessibility:a11y check reports SKIP: a command line runtime has no
interface to audit.
Releasing
The tag is the contract: a tag v0.2.1 publishes the version 0.2.1 of the
manifest, and nothing else. The workflow refuses to publish a tag that does
not match the manifest, because a published version cannot be replaced.
The authentication is OIDC, the trusted publishing of npm: the registry accepts the publish because the workflow that runs it is the one that the package declares as its publisher. There is no token in the repository, and there is nothing to rotate.
- Declare the publisher of the package, once, on npmjs.com:
https://www.npmjs.com/package/esd-local-quality-runtime/settings →
Trusted Publisher → GitHub Actions, with:
- Organization or user:
adsolucoestec - Repository:
esd-local-quality-runtime - Workflow filename:
publish.yml - Allowed actions: allow
npm publish
- Organization or user:
- Tag the version and push the tag:
git tag v0.2.1 && git push origin v0.2.1
The declaration is only valid for two days until the first publish proves it, so the tag goes out right after the declaration.
The workflow builds the package, runs the tests, publishes it, and reads the version back from the registry: a workflow that reports a success it did not have is worse than a workflow that fails.
Architecture
src/
├── engine/ # QualityEngine core
├── checks/ # Check implementations
│ ├── lint.ts # ESLint integration
│ ├── format.ts # Prettier validation
│ ├── typecheck.ts # TypeScript checking
│ ├── test.ts # Unit test execution
│ ├── security.ts # npm audit
│ ├── coverage.ts # Coverage thresholds
│ ├── release.ts # Bundle size, accessibility
│ ├── evidence.ts # Schema, integrity, signature, attestation
│ └── secrets.ts # Secret detection
├── evidence/ # Evidence management, schema, hashing, signature
├── adapters/ # CLI, VS Code, CI
├── config/ # Configuration loading
└── utils/ # UtilitiesEvidence Schema
Evidence is generated in JSON-LD format with integrity hashing:
{
"@context": "https://esd.adsolucoes.com.br/evidence/v1",
"@type": "QualityGateResult",
"id": "evidence-uuid",
"timestamp": "2026-10-21T00:00:00.000Z",
"profile": "standard",
"duration_ms": 12345,
"checks": [],
"artifacts": [],
"environment": {
"runtime": "cli",
"platform": "darwin",
"arch": "arm64",
"node_version": "v22.0.0",
"engine_version": "0.2.0"
},
"integrity": {
"content_hash": "9f86d081884c7d659a2feaa0c55ad015..."
},
"attestation": {
"attestor": "ci:adsolucoestec/esd-vscode-extension",
"attested_at": "2026-10-21T00:00:00.000Z",
"content_hash": "9f86d081884c7d659a2feaa0c55ad015...",
"profile": "standard"
}
}When a signing key is configured, the document also carries a signature
(ECDSA-P256, the public key and the signature in base64).
Artifacts
The artifacts are the files the checks really produced, with the SHA-256 of their content:
"artifacts": [
{
"type": "test-report",
"path": ".esd/reports/unit-tests.json",
"hash": "482c170ebb7c7d255cde81cce32217eef187efe5f28b94041e0c9d2ba20ae299",
"size_bytes": 148319
},
{
"type": "coverage-report",
"path": "coverage/coverage-summary.json",
"hash": "38b416c03a8c42c3e5efd3e9909cbb3804bf263540c1f15b4df076626df783d3",
"size_bytes": 15694
}
]A file that is not there is not in the evidence: the gate names an artifact
only when it exists, and the hash is the one of the bytes on the disk. The
report of the test run is written in .esd/reports/, the folder the runtime
already owns.
Status
| Increment | Description | Status | |-----------|-------------|--------| | I0 | Scaffold, engine core | ✅ Complete | | I1 | Check implementations | ✅ Complete | | I2 | CLI adapter, evidence management | ✅ Complete | | I3 | VS Code adapter | ✅ Complete | | I4 | Evidence submission | ✅ Complete | | I5 | CI/CD Integration | ✅ Complete |
See docs/WP-D_QUALITY_ENGINE_SPEC.md for full specification.
License
MIT
