domain-finder is a Go CLI project for scanning ICANN CZDS zone files and
building toward high-scale domain availability checks.
The repository currently uses stem-based matching across loaded zones:
- a thin CLI entrypoint at
cmd/domain-finder internal/zonefilefor opening files and detecting gzip by content- streaming line-by-line zone reading
internal/indexfor exact-match named-zone indexing and deterministic lookupinternal/backendfor backend-neutral file and PostgreSQL exact-match lookupsinternal/candidatesfor stem loading, normalization, merge, and dedupeinternal/configfor YAML config loading with CLI/env/local/base/default precedenceinternal/matchfor stable per-stem classification across loaded zonesinternal/openaifor batch stem generation through the OpenAI APIinternal/reportfor filtering and summary statisticsinternal/outputfor deterministic durable text and JSONL renderinginternal/termuifor Bubble Tea–based interactive rendering onstderr- a CLI workflow that loads named zones, ingests stems from flags, files,
and/or stdin, composes
<stem>.<zone>internally, and reports per-zone presence or absence for each stem
Tests intentionally use small deterministic fixtures. They do not depend on
full .com or .net CZDS zone files.
Interactive Bubble Tea search with strong hits shown durably:
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-interactive \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-candidate example \
-candidate missingInteractive search that also keeps partial hits visible:
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-interactive \
-interactive-show-partials \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-candidate example \
-candidate missingDeterministic non-interactive text output:
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-no-interactive \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-candidate example \
-candidate missingPrompt-contract dry run without any API call:
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-generate "industrial infrastructure names" \
-generate-dry-run \
-generate-dry-run-format json \
-generate-quality-profile industrial \
-generate-avoid-prefixes "dev,neo" \
-generate-avoid-suffixes "io,ia,ora,iva,ara"Machine-readable run artifacts:
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-no-interactive \
-audit-log run.jsonl \
-run-summary run-summary.json \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-candidate example \
-candidate missing- Candidate inputs are stems such as
example,missing, ormy-brand - Loaded zones determine which FQDNs are tested
- For loaded zones
comandnet, candidateexamplechecks:example.comexample.net
- Zone indexes still store normalized FQDN owner names from the zone files
-backend filekeeps the existing zone-file lookup behavior-backend postgreschecks exact stem presence against PostgreSQL Domain Miner data- The result model stays stem-based and backend-neutral
- File backend:
-zone com=path/to/com.zone-zone net=path/to/net.zone
- PostgreSQL backend:
-zone com-zone net
- Query shape uses
SELECT EXISTS (...) - Exact match keys:
zone_file = <zone>name = <stem>
- Assumed schema:
- table
dm.zone_records - columns
zone_file,name
- table
- Plain text, one stem per line
- Blank lines are ignored
- Lines beginning with
#are ignored as comments - Remaining lines are treated as raw candidate stems
- Repeated
-candidateflags are read first -candidate-fileentries are read second-candidate-stdinentries are read third- Stems are normalized and deduplicated while preserving first-seen order
- Invalid stems are rejected with a clear error
- Optional config files:
domain-finder.yamldomain-finder.local.yaml
- Config precedence:
- CLI flags
- environment variables
domain-finder.local.yamldomain-finder.yaml- built-in defaults
OPENAI_API_KEYis the primary secret sourcePG_DSNcan provide the PostgreSQL connection stringdomain-finder.local.yamlmay contain a local fallbackopenai.api_keydomain-finder.yamlmust not contain API keysdomain-finder.local.yamlis ignored by git
Committed example config lives at domain-finder.yaml.example.
-generate "prompt text"requests OpenAI-generated stems-generate-countsets the total requested stem count-generate-batch-sizesets the per-request batch size-generate-adaptive-refillshrinks effective batch size after repeated underfilled batches-generate-min-batch-sizesets the minimum effective batch size for adaptive refill-generate-modeloverrides the configured OpenAI model-generate-styleadds reusable style guidance such asinvented SaaSordeveloper tool-generate-quality-profile industrial|offapplies a generated-only quality filter after validation and lexical bans-generate-phonetic-quality normal|strictcontrols how aggressively the generated-only scoring stage screens stems-generate-min-lengthrequires generated stems to be at leastNletters long-generate-min-scorerequires generated stems to clear an internal score before lookup-generate-max-lengthprefers stems with no more thanNletters-generate-max-syllablesprefers shorter, simpler-sounding stems-generate-prefixprefers stems that start with specific text-generate-suffixprefers stems that end with specific text-generate-avoid-substringshard-bans low-value lexical families from generated stems-generate-avoid-prefixeshard-bans generated stems that start with certain prefixes-generate-avoid-suffixeshard-bans generated stems that end with certain suffixes-generate-max-cost-usdstops generation once cumulative estimated spend reaches the configured USD cap-generate-target-available-hitsstops generation once enough candidates are available in at least one requested zone-generate-target-strong-hitsstops generation once enough all-zone strong hits have been found-generate-max-stall-batchesstops generation after too many consecutive no-progress batches-generate-dry-runprints the fully resolved generation contract and exits before any OpenAI call-generate-dry-run-format text|jsonchooses human-readable or machine-readable inspection output-audit-log <path>writes one audit JSONL record per checked stem-run-summary <path>writes one machine-readable JSON summary object for the rungenerate.max_attemptsbounds how many attempts each batch gets to satisfy its targetgenerate.retry_countbounds transient API retries inside one attempt- Generated values are treated as stems, not FQDNs
- Generated batches are normalized and deduped through
internal/candidates - Manual, file, stdin, and generated stems can all be used together
- Matching still composes
<stem>.<zone>internally - When the OpenAI response includes
usage, text-mode generation runs show compact token and estimated-cost telemetry
- Prompt constraints steer the OpenAI request; they do not guarantee compliance
internal/openainow owns a dedicated prompt builder for the generation contract- Generated values still pass through the normal stem validation and dedupe pipeline
- Invalid outputs such as FQDNs, spaces, punctuation, duplicates, or empty strings are still rejected after generation
avoid_substringsis stronger than prompt guidance alone:- it is rendered into the prompt contract as an explicit negative rule
- generated stems containing banned substrings are also hard-rejected after generation
avoid_prefixesandavoid_suffixesextend that same generated-only hard-rejection policy:- both are rendered into the prompt contract as explicit negative rules
- generated stems starting with banned prefixes or ending with banned suffixes are rejected before lookup
min_lengthfollows that same generated-only pattern:- it is rendered into the prompt contract as a minimum-length rule
- generated stems shorter than the configured minimum are hard-rejected after normalization
- run-level diagnostics report these rejections as
too_short
- generated runs now also pass through
internal/namescoreafter normalization and before lexical bans:phoneticscoring rejects names with too many syllables, oversized consonant clusters, or overly long vowel-free spansstructuralscoring favors 6-10 character stems and rejects startup-style endings plus obvious low-value tech fragmentsbrandscoring rewards industrial or structural concepts such asvector,crux,forge, oratlas- stems below the configured minimum score are hard-rejected before lookup
-generate-phonetic-quality strictraises the effective score floor to at least70- diagnostics now include
score_rejected,phonetic_rejected,structural_rejected, and compact score-bucket counts
generate.quality_profileis a generated-only taste filter:industrialnow more aggressively favors stronger, harder-edged infrastructure-like name shapes- compact 5-7 letter forms, denser consonant structure, stronger consonant anchors, and harder endings score positively
- soft pharma/startup-mush patterns such as soft open endings, mushy CV alternation, and weak consonant weight are rejected more aggressively
- manual CLI, file, and stdin stems are not filtered by this profile
- generated runs also use a lightweight family-diversity guard:
- accepted stems are limited per crude family signature so one naming basin does not dominate the run
- this is deterministic, explainable, and generated-only
- family rejections appear in diagnostics as
family_rejected
-generate-dry-runuses the same resolved config and prompt builder, but does not require an API key and does not touch the network
- Generation can now stop on any configured stop condition:
- accepted-count target
- estimated cost cap
- available-hit target
- strong-hit target
- stall limit
- The default fallback still uses
-generate-countas the accepted-count stop condition - If additional stop controls are configured, the run ends when any configured condition is reached first
-generate-max-cost-usduses cumulative estimated spend from OpenAIusageplus the repo pricing table- Cost-cap runs require known pricing for the selected model
- if pricing is unavailable, the run fails clearly instead of silently ignoring the cap
-generate-target-available-hitsuses a broader availability definition:- stems with result state
partialorall - this means available in at least one requested zone
- taken stems do not count
- stems with result state
-generate-target-strong-hitstracks the strongest current result class:- stems absent across all requested zones
- the same
all ✓semantics shown in the interactive table
-generate-max-stall-batchesuses a simple, explicit stall definition:- consecutive batches with zero newly accepted generated stems
- and zero increase in strong all-zone hits
- Batch status lines now show compact progress such as:
available 37/100strong 3/25stall 2/8cost $0.18/1.00
- At the end of a generation run, text mode prints a compact
generation stopblock explaining which condition ended the run - The run-summary artifact also records:
- configured stop-condition settings
- actual stop reason at run end
-generate-adaptive-refillis an opt-in sparse-search policy for longer generation runs- When enabled:
- generation starts at the configured
batch_size - repeated underfilled batches shrink the effective batch size for later batches
- the first version uses a simple one-way shrink for the run
- after 2 consecutive underfilled batches, the effective batch size is cut in half
- it will not shrink below
-generate-min-batch-size
- generation starts at the configured
- Recovery is intentionally simple in v1:
- batch size does not grow back during the same run
- Adaptive refill only changes request sizing
- it does not change acceptance logic
- it does not change lookup semantics
- it does not change stop-condition semantics
- When enabled, status lines show the active effective batch size:
effective_batch 8batch_size 8->4
- The run summary records:
- whether adaptive refill was enabled
- the configured minimum batch size
- the final effective batch size
-generate-dry-runis an inspection mode for prompt tuning- It prints the resolved model, generation counts, retry policy, quality profile, theme, style, structural constraints, and the final prompt-builder output
- It also prints the resolved generated-name scoring policy such as
phonetic_qualityandmin_score - It also prints the resolved stop-condition policy such as cost cap, strong-hit target, and stall limit
- It also prints adaptive-refill policy such as whether it is enabled and the minimum batch size
-generate-dry-run-format textkeeps the current readable inspection block-generate-dry-run-format jsonemits a stable JSON contract for diffing, archiving, and tooling- It exits before backend loading, OpenAI client creation, or any network call
- It is intended for prompt-contract inspection, not candidate lookup
- Each requested batch now has a bounded fulfillment policy:
- request the batch target
- normalize and dedupe through the existing stem pipeline
- if too few usable new stems survive, try again for the remainder
- if refill attempts are exhausted, keep any accepted stems, record the batch as underfilled, and continue to the next batch
- Transient OpenAI failures such as rate limits or server errors are retried a bounded number of times
- Poor model output such as duplicates, FQDNs, punctuation, empty values, or noisy text is treated as degraded batch quality rather than silently corrupting the candidate pipeline
- Generated stems containing banned substrings are rejected before lookup and counted as unusable batch output
- Generated stems hitting banned prefixes or banned suffixes are also rejected before lookup
- Generated stems below the configured phonetic/structural/brand score are also rejected before lookup
- Generated stems can also be rejected by the configured quality profile before lookup, and those rejections are counted separately in generation progress
- Interactive and text-mode generation runs emit concise stderr status lines showing batch requests, accepted/rejected counts, retries, and completion/failure
- Underfilled batches are now diagnostic, not fatal:
- batch status lines can append
underfilled N - the run keeps going until an actual stop condition ends it
- batch status lines can append
- At the end of a generation run, text-mode runs also print a compact
generation diagnosticsblock summarizing dominant rejection categories across the whole run - Those same runs also print a compact
generation underfillblock when any batches finished short - The same text-mode runs now also print a compact
generation usageblock with:- model
- input/output token totals
- cached input token totals when available
- estimated cost from the repo's built-in pricing table
- Batch status lines include compact last-call and cumulative estimated cost when pricing is known
- If the API omits
usage, the run continues and the usage summary reportsusage: unavailable - If the configured model is not in the built-in pricing table, token totals are still shown when available but cost is reported as
pricing unavailable - JSONL mode stays machine-readable and does not emit live generation progress
- After a real generation run in text mode,
domain-finderprints a compact run-level diagnostics block onstderr - This summary aggregates generated-stem rejection signals across the run, including:
too_shortscore_rejectedphonetic_rejectedstructural_rejectedbanned_substringbanned_prefixbanned_suffixquality.<reason>family_rejectedinvalidduplicates
- It also includes a compact score distribution such as
score.30-49orscore.70-84 - Quality reasons reuse the same explainable categories used by the generated quality filter, such as
quality.pharma_like_suffixorquality.soft_open_ending - The goal is operator tuning:
- identify which failure families are dominating
- adjust prompts, lexical bans, or the active quality profile accordingly
- This diagnostics summary is separate from:
- deterministic text result output
- JSONL result output
- the audit log
-audit-log <path>creates or truncates a JSONL file for the run- The audit log is separate from:
- the interactive stderr tape
- deterministic text output
- JSONL result output
- It records every checked stem, including stems that were:
- filtered out of the interactive table
- suppressed by
-interactive-hide-taken
- Each record includes:
stembackendrequested_zones- per-zone
availableresults state(all,partial,taken)report_emittedinteractive_emitted
- This is the durable machine-readable truth of what was checked during the run
-run-summary <path>creates or truncates one JSON file for the run- The run summary is separate from:
- the per-stem audit log
- the interactive stderr tape
- deterministic text or JSONL result output
- It captures run-level context and outcomes, including:
- backend
- requested zones
- filter mode
- whether interactive mode was used
- final checked/emitted/strong-hit counts
- generation settings when generation was used
- configured stop-condition settings and final stop reason when generation was used
- adaptive-refill settings and final effective batch size when generation was used
- generated scoring settings such as
phonetic_qualityandmin_score - underfilled-batch totals when generation was used
- generation token totals and estimated cost when usage data was available
- aggregated generation diagnostics, rejection categories, and score-bucket distribution
- Use it when you want one stable artifact per run for diffing, archiving, or comparing prompt/profile changes over time
- Token telemetry is grounded in actual OpenAI API
usagefields when the response includes them - The tool tracks:
- input tokens
- output tokens
- cached input tokens from
usage.prompt_tokens_details.cached_tokenswhen present
- Cost is an estimate, not a bill:
- it uses the repo's explicit model pricing table
- unknown model pricing is not guessed
- current pricing assumptions should be updated when the official pricing page changes
- This telemetry appears in:
- compact generation status lines during the run
- the end-of-run
generation usageblock - the JSON run-summary artifact
- Interactive console is enabled only for
textmode whenstderris a TTY - Real TTY interactive runs now use Bubble Tea for stable terminal rendering
-interactiveforces the interactive console on-no-interactiveforces the deterministic fallback report path-interactive-hide-takensuppresses durabletakenrows in the interactive compact table only-interactive-show-partialskeeps partial available-zone hits as durable rows in interactive mode-colorforces ANSI styling in interactive mode-no-colordisables ANSI styling in interactive modejsonlmode never uses the interactive console
- Prints a small startup header showing loaded zones, candidate count, and filter
- Uses a Bubble Tea–managed live status area while checking and generating
- Shows one reusable live status line instead of ad hoc carriage-return composition
- Uses that single live line for low-value batch chatter such as:
- batch requests
- accepted 0
- duplicate-only or no-progress refill attempts
- adaptive refill/effective batch-size updates
- Prints durable rows only for meaningful candidate discoveries
- Uses a compact table layout tuned for scanability
- Header columns are:
stem: the stem being evaluatedavailable_zones: which requested zones are currently available for that stemresult: compact status semantics
- Durable rows use explicit status language:
all ✓means all requested zones are available for that stempartialmeans only some requested zones are availabletakenmeans none of the requested zones are available
- By default, interactive mode keeps durable output focused on strongest all-zone hits
-interactive-show-partialsadds partial hits back as durable rows- Strongest all-zone hits stay visually strongest with the success marker and optional ANSI styling
-interactive-hide-takenonly suppresses durabletakenrows on the interactive tape- It does not change matching, filtering, non-interactive text output, or JSONL output
- End-of-run summaries remain durable:
- generation diagnostics
- generation usage
- generation underfill
- generation stop
- final checked/emitted/strong line
- Leaves the terminal in a clean state on normal completion without fragment collisions
- Interactive text mode:
- compact streaming table on
stderr - no detailed durable result blocks on
stdout - if
-outis used, the full deterministic report still goes to the file - if
-audit-logis used, every checked stem is still recorded in JSONL even if the row is not shown on the interactive tape
- compact streaming table on
- Non-interactive text mode:
- deterministic text report on
stdout, or in-out - no interactive terminal rendering
- deterministic text report on
- JSONL mode:
- deterministic JSON Lines on
stdout, or in-out - no interactive terminal rendering
- deterministic JSON Lines on
Stem-based CLI input:
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-backend file \
-no-interactive \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-candidate example \
-candidate missingStem-based candidate-file input:
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-backend file \
-interactive \
-filter absent-in-all \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-candidate-file testdata/small/candidates.txtStem-based stdin input:
printf 'missing\nexample\n' | \
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-backend file \
-no-interactive \
-candidate-stdin \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.sliceInteractive console with stems:
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-backend file \
-interactive \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-candidate example \
-candidate missingInteractive console with taken rows suppressed:
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-backend file \
-interactive \
-interactive-hide-taken \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-candidate example \
-candidate missingInteractive console with partials kept durably:
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-backend file \
-interactive \
-interactive-show-partials \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-candidate example \
-candidate missingInteractive mode with audit logging:
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-backend file \
-interactive \
-interactive-hide-taken \
-audit-log run.jsonl \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-candidate example \
-candidate missingManual run with a machine-readable run summary:
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-backend file \
-no-interactive \
-run-summary run-summary.json \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-candidate example \
-candidate missingNon-interactive mode with audit logging:
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-backend file \
-no-interactive \
-audit-log run.jsonl \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-candidate example \
-candidate missingInteractive console with strong-hit styling:
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-backend file \
-interactive \
-color \
-filter absent-in-all \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-candidate missingYAML-configured generation with manual stems:
cp domain-finder.yaml.example domain-finder.yaml
export OPENAI_API_KEY=your-key-here
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-backend file \
-interactive \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-candidate missing \
-generate "short invented SaaS brand stems" \
-generate-count 6 \
-generate-batch-size 3Constrained generation with prompt builder guidance:
export OPENAI_API_KEY=your-key-here
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-backend file \
-interactive \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-generate "short product name stems" \
-generate-quality-profile industrial \
-generate-style "developer tool" \
-generate-count 8 \
-generate-batch-size 4 \
-generate-max-length 12 \
-generate-max-syllables 3 \
-generate-prefix dev \
-generate-suffix ioConstrained generation with hard lexical bans:
export OPENAI_API_KEY=your-key-here
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-backend file \
-interactive \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-generate "short product name stems" \
-generate-quality-profile industrial \
-generate-style "developer tool" \
-generate-count 8 \
-generate-batch-size 4 \
-generate-max-length 12 \
-generate-max-syllables 3 \
-generate-suffix io \
-generate-avoid-substrings "dev,code,stack,cloud,sync,ops,grid,craft,build,tool,lab,forge,flow" \
-generate-avoid-prefixes "dev,neo" \
-generate-avoid-suffixes "io,ia,ora,iva,ara"Budget-shaped exploratory generation:
export OPENAI_API_KEY=your-key-here
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-backend file \
-interactive \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-generate "industrial infrastructure names" \
-generate-quality-profile industrial \
-generate-count 200 \
-generate-max-cost-usd 1.00 \
-generate-target-strong-hits 25 \
-generate-max-stall-batches 8Adaptive refill for sparse late-run search:
export OPENAI_API_KEY=your-key-here
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-backend file \
-interactive \
-zone com=testdata/small/com.zone \
-zone net=testdata/small/net.zone.slice \
-generate "industrial infrastructure names" \
-generate-count 200 \
-generate-adaptive-refill \
-generate-min-batch-size 2 \
-generate-max-stall-batches 8Dry-run prompt inspection without spending API calls:
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-generate "short product name stems" \
-generate-dry-run \
-generate-quality-profile industrial \
-generate-style "developer tool" \
-generate-max-length 12 \
-generate-max-syllables 3 \
-generate-prefix dev \
-generate-suffix io \
-generate-adaptive-refill \
-generate-min-batch-size 2 \
-generate-max-cost-usd 1.00 \
-generate-target-strong-hits 25 \
-generate-max-stall-batches 8Machine-readable dry-run contract:
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-generate "short product name stems" \
-generate-dry-run \
-generate-dry-run-format json \
-generate-quality-profile industrial \
-generate-style "developer tool" \
-generate-max-length 12 \
-generate-max-syllables 3 \
-generate-prefix dev \
-generate-suffix io \
-generate-max-cost-usd 1.00 \
-generate-target-strong-hits 25 \
-generate-max-stall-batches 8Typical operator feedback during generation:
generation: batch 1 attempt 1 requesting 3 stemsgeneration: batch 1 attempt 1 accepted 2, invalid 1, banned 0, quality_rejected 1, duplicates 0, need 1 more | strong 1/25 | stall 0/8 | cost $0.03/1.00generation: batch 9 attempt 1 requesting 2 stems | batch_size 8->2generation diagnosticsbanned_prefix: 3banned_suffix: 4quality.pharma_like_suffix: 4family_rejected: 2duplicates: 2generation: retrying batch 1 attempt 2 (1/2) after transient errorgeneration: complete, accepted 6 stems | total $0.18 | stop strong-hit target reachedgeneration stopreason: strong-hit target reachedstrong_hits: 25/25stall_batches: 0/8estimated_cost_usd: $0.18/1.00
Example generation tuning in YAML:
generate:
count: 20
batch_size: 10
adaptive_refill: true
min_batch_size: 2
max_attempts: 3
retry_count: 2
max_cost_usd: 1.00
target_strong_hits: 25
max_stall_batches: 8
quality_profile: industrial
max_length: 10
max_syllables: 3
prefix: ""
suffix: ""
style: industrial infrastructure naming
avoid_substrings: dev,code,stack,cloud,sync,ops,grid,craft,build,tool,lab,forge,flow
avoid_prefixes: dev,neo
avoid_suffixes: io,ia,ora,iva,araThe run summary JSON complements the audit log:
- audit log: one JSONL record per checked stem
- run summary: one JSON object per run
PostgreSQL backend example:
export PG_DSN='postgres://user:pass@localhost:5432/domainminer'
env GOCACHE=/tmp/domain-finder-gocache \
go run ./cmd/domain-finder \
-backend postgres \
-no-interactive \
-zone com \
-zone net \
-candidate example \
-candidate missingThis still reports only exact presence or absence in loaded zone files. It is not a registrar availability check. OpenAI generation produces candidate stems only; it does not check registrar or DNS availability.