Skip to content
SQA Cockpit

ADR-0046 — SUT identifiers mirror snappy's engine names verbatim

ADRsUpdated 5 min readEdit on GitHub ↗
5 sections··

ADR-0046 — SUT identifiers mirror snappy's engine names verbatim #

  • Status: Accepted
  • Date: 2026-05-19
  • Deciders: Natan
  • Source: 2026-05-19 session-close discussion about how to name SQA's

three SUTs. The first SUT was historically called snappy.domain-activation — a local SQA paraphrase. With PRD-08 (WebCrawlEngine coverage) and PRD-09 (DataExtractionEngine coverage) about to land, the question of how to name the second and third SUTs forced the deeper question: what's the contract anchor that ties SQA's verification surface to snappy's source-of-truth?

Context

Context #

Snappy's architecture (per apps/snappy-api/docs/reference/system-overview.md) is built around three named engines that move data across three namespaces:

Snappy engineTransformation
DomainDiscoveryEngineRaw Web → Structured Archive (domain-level)
WebCrawlEngineStructured Archive (URLs) → Structured Archive (snapshots)
DataExtractionEngineStructured Archive (snapshots) → Data Collections

SQA's three SUT surfaces map 1:1 to these engines. Until now SQA called the first surface snappy.domain-activation — a local paraphrase. The paraphrase introduces a translation layer that has to be kept in sync with snappy's vocabulary, and the translation breaks down at the engine boundary (activation is one workflow inside DomainDiscoveryEngine, not the engine itself).

Two related conventions are already in force:

  • ADR-0021 mandates kebab-case filenames + directory casing for

sortability and the leading-numeric-prefix convention.

  • DOC-STD §3.5 (Rule 50, ratified in 00d8e00) says pinned

external references KEEP — when code points outward to a more durable artifact, use the artifact's name verbatim rather than paraphrasing.

These two conventions intersect at the SUT identifier: ADR-0021 wants kebab-case on the filesystem; DOC-STD §3.5 wants verbatim snappy names in the contract identifier.

Decision

Decision #

SUT identifiers in code, doc prose, tracker rows, hardening-run entries, gap logs, and emitted events use snappy's engine names verbatim (DomainDiscoveryEngine, WebCrawlEngine, DataExtractionEngine). PascalCase preserved.

Filesystem layout stays kebab-case per ADR-0021. SUT directories are named after the engine in kebab-case: src/systems/snappy/domain-discovery-engine/ etc. Files inside are named after the scenario/workflow they verify, also kebab-case.

Each SUT's main file exports a SUT constant carrying the verbatim engine name. The constant is the contract anchor; the directory name is a filesystem affordance.

typescript
// src/systems/snappy/domain-discovery-engine/activation.ts
export const SUT = "DomainDiscoveryEngine";

Tracker rows, contract docs, and emitted events read the SUT constant. They never paraphrase.

The three SUTs after this ADR #

SUT identifierDirectoryScenarios
DomainDiscoveryEnginesrc/systems/snappy/domain-discovery-engine/activation.ts (today's contract)
WebCrawlEnginesrc/systems/snappy/web-crawl-engine/crawl-url-via-enqueue.ts (PRD-08)
DataExtractionEnginesrc/systems/snappy/data-extraction-engine/auto-extract.ts (PRD-09)

What "verbatim" means in practice #

  • Code: SUT = "DomainDiscoveryEngine", system: "DomainDiscoveryEngine"

in emitted events, sut: "DomainDiscoveryEngine" in run metadata.

  • Doc prose: "the DomainDiscoveryEngine contract verifies …".

Not "the domain-activation contract", not "the discovery engine".

  • Tracker rows: "Sweep #N against DomainDiscoveryEngine …".
  • Hardening-run entries: same.
  • PRD file headings: "PRD-08 — WebCrawlEngine

crawl-url-via-enqueue scenario".

Carve-outs (what stays paraphrased) #

  • Scenario / workflow names (activation, crawl-url-via-enqueue,

auto-extract) are SQA-side identifiers for a specific contract-pinned flow inside an engine. They may or may not match a snappy file name; the matching is documented in the contract doc's "Files" section, not implied by name alone.

  • Directory names stay kebab-case per ADR-0021. The translation

is one-step and grep-able: domain-discovery-engine/DomainDiscoveryEngine. The directory listing remains sort-correct under ls, find, and IDE file trees.

  • Probe / verifier internal names follow their own naming

rules (kebab-case files, camelCase exports). They are not contract anchors.

Consequences

Consequences #

Positive #

  • One grep finds every SUT reference. Mechanical refactors

when snappy renames an engine. No translation table.

  • No vocabulary drift. Operator standups, snappy team

references, and SQA reports use the same words.

  • PRD-08 / PRD-09 inherit the convention. Both PRDs will use

WebCrawlEngine / DataExtractionEngine verbatim from authorship forward; no post-hoc rename when the SUT lands.

  • DOC-STD §3.5 + ADR-0021 are both satisfied. The filesystem

stays kebab-conformant; the contract identifier stays verbatim.

Negative #

  • One-time rename cost. Existing references to

snappy.domain-activation (in tracker prose, PRD-10 retrospective, hardening-run.md historical entries, CHANGELOG.md historical entries, the runner src/systems/snappy/domain-activation.ts itself, ~30 test imports) all need updating.

  • Naming heterogeneity at the engine vs scenario layer.

DomainDiscoveryEngine (PascalCase verbatim) and activation (kebab-case scenario name) live side by side. Readers have to understand the two-layer convention. Mitigated by the SUT = "…" constant being the only contract anchor — scenario names are subordinate identifiers.

Neutral #

  • History stays as-was. Historical hardening-run.md entries

describing pre-this-ADR sweeps as domain-activation are legitimate — they reference the SUT identifier at that point in time. New entries use the verbatim name. The migration commit is the timestamp boundary.

Alternatives considered

Alternatives considered #

  • PascalCase directories (supersede ADR-0021 for this carve-out).

Rejected. ADR-0021 has a real reason (filesystem sortability + the leading-numeric-prefix convention) that's not specific to SQA's SUT layout. The filesystem stays kebab; the verbatim binding lives at the identifier layer.

  • Keep paraphrasing forever (snappy.domain-activation,

snappy.web-crawl, snappy.data-extraction). Rejected. The paraphrase has to be kept in sync with snappy's vocabulary, and the translation breaks down at the engine vs workflow boundary. The cost of the rename is bounded; the cost of carrying a translation forever is not.

  • **Hybrid (some engines verbatim, some paraphrased depending on

fit).** Rejected. Inconsistent vocabulary is worse than either consistent choice. If verbatim works for DomainDiscoveryEngine it works for all three.

See also

See also #

directory casing rules (kebab-case mandate).

Rule 50 — pinned external references stay verbatim (DOC-STD §3.5).

(lib ← components ← systems) that bounds the rename's blast radius to the systems/ tree.

  • apps/snappy-api/docs/reference/system-overview.md

§3 — snappy's source-of-truth definition of the three engines.

Was this page helpful?