This file is the contract every contributor — human or AI — works under. It is intentionally short and absolute. If a rule here conflicts with a request, the rule wins; surface the conflict instead of working around it.
This repository is a thin-scoped, standards-compliant DNS-SD library. The goal is not to grow it — the goal is to converge it to a small, elegant, battle-tested fixed point and then stop touching it. Success looks like a package that barely needs to change: hundreds of independent agents, given the same task, all land in the same place because "correct" is machine-checkable and the surface is frozen.
Read this whole file before making changes.
Your job is to move the codebase toward a fixed point, never to churn it.
Before any change, ask: does this move a metric the ratchets track, fix a
spec-cited defect, or close a gap in docs/convergence.md's target? If not,
do not make it. A green build with no ratchet improvable is done — there is
nothing left to do, and inventing work is a defect.
Correctness is not a matter of opinion or review taste. A change is complete iff the full check is green under both runtimes:
# Deno
deno fmt --check && deno lint && deno task check && deno task test
deno task check:docs # JSDoc completeness (deno doc --lint)
deno task check:api # public API surface unchanged (or intentionally re-baselined)
# Node
npm run typecheck && npm run build && npm run test:nodeNever ask a human "is this okay?" for anything the oracle can answer. Run the oracle. If it is green and no ratchet can be improved, ship it. If it is red, you are not done.
The public API — everything exported from @momics/dns-sd-shared and re-exported
by the runtime packages — is a contract, captured as a golden snapshot in
packages/dns-sd-shared/api/.
- You may not add, rename, remove, or widen a public export (new function, new option field, broader type) without an explicit, human-approved reason.
- Any change to the surface makes
deno task check:apifail. That failure is a stop sign, not a chore: re-baseline (deno task snapshot:api) only when the change was deliberate and belongs inCHANGELOG.md. - Internal refactors that do not touch the snapshot are always welcome.
See docs/api-design.md for what "good" looks like here (WHATWG-level: small,
orthogonal primitives, AbortSignal, async iterators, no options-bag creep).
This library will not:
- Ship native dependencies or native addons. The core is pure TypeScript.
- Implement DNS beyond what mDNS / DNS-SD (RFC 1035 / 6762 / 6763) requires. No unicast DNS resolver, no DNSSEC, no DoH/DoT, no arbitrary record types beyond those DNS-SD needs (A, AAAA, PTR, SRV, TXT, NSEC).
- Grow runtime-specific feature flags or configuration knobs "just in case".
Every option must earn its place against
docs/api-design.md. - Add I/O to
@momics/dns-sd-shared. It stays runtime-agnostic; I/O lives in the per-runtime packages behind theDatagramTransport/DnsSdAdapterseams. - Depend on a framework, a DI container, or a logging library.
If a task asks for any of the above, stop and say so.
Everything that can silently regress has a floor that only moves in the good direction, enforced in CI. Never lower a ratchet to make a build pass.
| Ratchet | Enforced by | Rule |
|---|---|---|
| Public API surface | deno task check:api |
No change without a re-baseline + changelog |
| JSDoc completeness | deno task check:docs (deno doc --lint) |
Every public symbol documented; zero lint errors |
| Type-level API shape | deno task check / npm run typecheck |
Public API type-shape assertions hold (test/api.type-test.ts) |
| Types | tsc --noEmit (both strict) |
Zero errors; no new any / @ts-ignore/@ts-expect-error in src/ |
| Format & lint | deno fmt --check, deno lint |
Zero diffs, zero warnings |
| Cross-runtime tests | deno task test, npm run test:node |
The same suite passes under Deno and Node |
| Golden wire vectors | deno task test / npm run test:node |
Real-captured + spec-derived DNS-SD packets decode to the pinned structure (byte-exact for canonical vectors) |
| Mutation score | npm run test:mutation (Stryker, nightly + on main) |
Score stays ≥ the committed floor (thresholds.break); ratchet the floor up as it improves, never down |
| Performance | deno task perf:gate |
Hot-path timings stay within budget of bench/perf-baseline.json; re-baseline deliberately (deno task perf:baseline) |
| Bundle size | npm run size (size-limit) |
Published entrypoints stay under the committed byte limits |
| Executable docs | deno task check:docs-examples |
Every non-no-check README example type-checks against the real public API |
New ratchets are added the way docs/convergence.md describes — a metric, a
committed baseline, and a CI gate — never as informal review preference.
Do not argue style. Formatting is whatever deno fmt produces; lint is whatever
deno lint accepts. Naming, ordering, and layout follow the existing files.
There is nothing to discuss here — run the formatter and move on. Time spent
"cleaning up" code the formatter already blesses is churn (see §1).
- Every exported symbol carries JSDoc. This is enforced (
check:docs), not optional. Match the terse, precise, RFC-citing style already insrc/. - The
README.mdof each package is the human contract; keep its code examples correct — they are expected to compile against the real API. - User-visible changes are recorded in
CHANGELOG.md. - Prefer improving a JSDoc block or a README over adding prose files.
- Read this file,
docs/convergence.md, and the relevantsrc/+ tests. - Establish baseline: run the oracle (§2). It must already be green.
- Make the smallest change that fully addresses the task. Add or update tests first when fixing a bug — reproduce, then fix.
- If you touched the public surface, decide deliberately: revert it, or
re-baseline the snapshot and add a
CHANGELOG.mdentry. - Run the oracle again. All of it. Both runtimes.
- Stop. Do not gold-plate. Do not open adjacent scope.
| Failure mode | Guard |
|---|---|
| Churning style / re-formatting blessed code | deno fmt/deno lint — nothing to debate (§6) |
| Gaming coverage with assertion-free tests | Spec-cited conformance + property tests (see docs/testing-strategy.md) |
| Scope creep / new options | Frozen API + non-goals + check:api (§3, §4) |
| Silent behavior drift | Golden wire vectors + API snapshot |
| "Is this okay?" approval loops | The oracle is the only authority (§2) |
| Endless refactoring of a stable surface | The Prime Directive: no metric to move ⇒ stop (§1) |
| Undocumented public code | check:docs JSDoc gate (§7) |
If you are an AI agent: you have everything you need to self-verify. Do not ask for permission the oracle can grant. Converge, verify, stop.