From 9b4f93351aa9800799f0867e379d702c36d0dfe1 Mon Sep 17 00:00:00 2001 From: thodson-usgs Date: Tue, 1 Sep 2026 13:21:44 -0500 Subject: [PATCH 1/5] docs: separate the terms we own from the terms the services own Review of #396 found `CONTEXT.md` using *tier* in its own prose without defining it. The word was there before that record was written; recording each explanation once made the gap visible rather than creating it. Fixing the one word would have left the reason it got there. The glossary is one flat list, and every place the code disagrees with it is filed under *Known legacy names* -- a heading whose framing is that the disagreement is debt. For most of the glossary that is right. For a few terms it is wrong, and being wrong about those has produced the same argument repeatedly: may a docstring say *site*, may `service=` name a collection, is prose about NWIS bound by a word taken from the Water Data API. The two sets differ in who has authority over them. *chunk*, *page*, *fan-out*, *plan*, *interruption*, *dialect*, *leaf* appear in no USGS API's vocabulary. They were invented here for machinery this package owns. Nothing outside constrains them, so spelling one of them three ways -- the resolution chain's layers have been a source, a tier and a rung -- is an inconsistency that can be removed by deciding, and should be. *monitoring location* and *collection* are not like that. The services name those things and disagree: `site_no` in NWIS, `Station` in WQP, `monitoring_location_id` in Water Data, a `sites` collection in NGWMN. No decision here reconciles them. A caller who read WQP's documentation looks for `Station`; an adapter that renamed it would be harder to use, and the parameter is public surface besides. One rule over both forces a choice between losing the glossary, and with it the vocabulary that lets transport and the OGC engine be written once, or enforcing it onto every adapter's public surface. So: ADR 0013 records the split. Core terms take one spelling everywhere, identifiers included, and a second spelling is a defect. Domain terms fix one word for prose while each adapter keeps its service's spelling in its parameters -- which is the adapter doing its job, not debt. `CONTEXT.md` follows. The preamble names the two kinds. *Monitoring location* and *collection* carry their per-service spellings in their own entries rather than as exceptions at the end. *Known legacy names* keeps only core-term spellings. And the package-wide **source** is called that, in the sentence that had called it a tier. This also settles what #400 is. Renaming the configuration chain's `tier` to `source` looked discretionary while the glossary bound only prose; the chain is core machinery, so one spelling binds its identifiers too. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01JAEQqs7XzQHGQQi2KakuXD --- CONTEXT.md | 63 ++++++-- .../decisions/0013-core-and-domain-terms.rst | 147 ++++++++++++++++++ docs/source/architecture/decisions/index.rst | 1 + 3 files changed, 194 insertions(+), 17 deletions(-) create mode 100644 docs/source/architecture/decisions/0013-core-and-domain-terms.rst diff --git a/CONTEXT.md b/CONTEXT.md index eda9288d..3e33eb5f 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -5,8 +5,24 @@ specification: it fixes what words mean so that code, docstrings, ADRs, and conversation use them the same way. Architectural decisions live in `docs/source/architecture/decisions/`. -When a term here conflicts with a name in the code, the term wins and the name -is legacy. Legacy names are listed below. +Two kinds of term live here, and they carry different obligations (ADR 0013). + +**Core terms** are ours. The package invented them and no service has a claim on +them — *chunk*, *page*, *fan-out*, *source*, *dialect*, *leaf*. One spelling, +everywhere it appears: prose, identifiers, tests. Where a core term conflicts +with a name in the code the term wins and the name is legacy, listed at the end. +A second spelling is a defect, not a variation. + +**Domain terms** belong to the services, which name the same thing differently +and will not be reconciled. For these the glossary fixes one word for *prose*, +so that documents about the package read consistently. It does not fix the wire +or an adapter's public surface: each adapter keeps its own service's spelling in +its parameters. Such an entry names the per-service spellings itself; those are +not legacy names. + +A word carrying a package-wide meaning is defined here before this document +uses it. Naming one only to say what an ADR calls it is a cross-reference, +not a use. ## Retrieval @@ -102,13 +118,24 @@ collections. The distinction matters because the OGC machinery is shared: the same code path retrieves a Water Data collection and an NGWMN one, and only the service differs. +*Domain term.* Water Data and NGWMN say `collection`; legacy NWIS says +`service=` (`'dv'`, `'peaks'`); WQP names its collections as profiles +(`Result`, `Station`, `Activity`). Those parameters are frozen public surface +and keep their spelling. Prose says *collection*, including prose about the +adapters that spell it otherwise. + **Collection family** — A group of collections sharing a shape and therefore a getter signature. Their getters deliberately resemble one another; the resemblance is the public contract, not duplication to be removed. -**Monitoring location** — A place where measurements are recorded. The canonical -term. Legacy: the deprecated NWIS getters and the WQP profiles call this a -*site*, and their parameters keep that spelling. +**Monitoring location** — A place where measurements are recorded. + +*Domain term.* The services disagree, and each adapter keeps its own service's +spelling in its parameters: NWIS `site_no` and `sites=`, WQP `Station` and +`siteid`, Water Data `monitoring_location_id`, NGWMN's `sites` collection. Where +a service names a thing `site-types` or `site_type_code`, that is its vocabulary +and is reproduced rather than translated. Prose that is not about one particular +adapter says *monitoring location*. **Metadata** — The second half of every getter's return: the request URL, the elapsed time, and the response headers. Describes the *retrieval*, not the data. @@ -149,7 +176,7 @@ count, the progress line, the stall timeout. Set once, honored everywhere. **Adapter-scoped setting** — A setting named under one adapter, applying to that adapter and no other. It overrides the package-wide value for that adapter -alone; it does not replace the package-wide tier. An adapter rejects a setting +alone; it does not replace the package-wide source. An adapter rejects a setting it has no use for, rather than accepting and ignoring it. The scope is the *adapter*, not the service and not the host, because the @@ -162,8 +189,10 @@ Credentials are host-scoped; tunables are adapter-scoped. categories: a `configure()` block, the environment, the file, the built-in default. The order is resolved per setting rather than per source: a value supplied for one setting does not displace another setting's value from a lower -source. ADR 0010 calls a source a *tier* and ADR 0011 a *rung*; both are this -term, and the accepted records keep their own wording. +source. + +*Core term.* ADR 0010 calls a source a *tier* and ADR 0011 a *rung*; both are +this term, and those accepted records keep their own wording. **Origin label** — The exact thing a value came from, at finer grain than its source: `$API_USGS_RETRIES`, a path to the config file, the profile a caller @@ -171,9 +200,10 @@ selected. What `show_configuration()` prints beside each value, and what a parser names when it rejects one. A source is the category; an origin label is the instance within it. -The code carries both, and spells them the other way around: `_resolve` returns -its origin label under the name `source` and its source under the name `tier`. -Prose uses the terms above. +*Core terms.* The configuration chain is shared machinery, so one spelling binds +its identifiers as well as its prose. `_resolve` currently returns the origin +label under the name `source` and the source under the name `tier`; that is a +defect being corrected, not a second spelling to work around. **Selection** — Naming which profile an adapter should use. Done in code; a profile is never selected by the environment or implied by the file, so the @@ -234,7 +264,11 @@ and is not public API. ## Known legacy names -Recorded so they are not mistaken for the canonical term, and not re-litigated: +Core-term spellings recorded so they are not mistaken for drift, and not +re-litigated: frozen misnamings, permanent aliases, and names that agree with +this glossary by more than luck. A domain term at an adapter's surface is not a +legacy name and is not listed here; it belongs with that term's own entry +(ADR 0013). - `completed_chunks` / `total_chunks` on interruptions, and `set_chunks()` / `start_chunk()` on the progress reporter, count chunks as defined above and @@ -249,11 +283,6 @@ Recorded so they are not mistaken for the canonical term, and not re-litigated: compatibility path. Like `ChunkInterrupted`, both spellings are correct. - `utils.query` is one *request*, not a query as defined above. It is a frozen public path (`dataretrieval.utils.query`) and predates this glossary. -- `site` appears in deprecated NWIS and WQP parameter names where *monitoring - location* is meant. These are frozen public surfaces and will not be renamed. - Where the Water Data API itself names a thing `site-types` or - `site_type_code`, that is the service's vocabulary and is reproduced - faithfully rather than translated. - `service` named a collection throughout the OGC machinery. Resolved: the OGC internals, the Water Data wrappers, and all eleven typed getters now say `collection`; `waterdata.get_cql` takes `collection`; and the type alias is diff --git a/docs/source/architecture/decisions/0013-core-and-domain-terms.rst b/docs/source/architecture/decisions/0013-core-and-domain-terms.rst new file mode 100644 index 00000000..e055b5ea --- /dev/null +++ b/docs/source/architecture/decisions/0013-core-and-domain-terms.rst @@ -0,0 +1,147 @@ +ADR 0013: Distinguish the terms we own from the terms the services own +====================================================================== + +Status +------ + +Accepted + +Context +------- + +``CONTEXT.md`` is one flat glossary. Every term in it reads as equally binding, +and every place the code disagrees is filed under *Known legacy names* -- a +list whose framing is that the disagreement is debt, tolerated until someone +gets to it. + +For most of the glossary that framing is right. But it is wrong for a small set +of terms, and being wrong about those has produced the same review argument +repeatedly: whether a docstring may say *site*, whether ``service=`` may name a +collection, whether prose about NWIS is bound by a word chosen from the Water +Data API. + +The two sets behave differently because their authority differs. + +Terms like *chunk*, *page*, *fan-out*, *plan*, *interruption*, *dialect* and +*leaf* appear nowhere in any USGS API's vocabulary. They were invented here to +describe machinery this package owns. Nothing external constrains them, so when +the package spells one of them three ways -- the resolution chain's layers have +been a *source*, a *tier* and a *rung* -- that is simply an inconsistency, and +one that can be removed by deciding. + +Terms like *monitoring location* and *collection* are different. The services +name those things, and they do not agree with each other: + +.. list-table:: + :header-rows: 1 + + * - Concept + - NWIS + - WQP + - Water Data + - NGWMN + * - a place where measurements are recorded + - ``site_no``, ``sites=`` + - ``Station``, ``siteid`` + - ``monitoring_location_id`` + - the ``sites`` collection + * - a named set of records + - ``service=`` + - ``Result``, ``Station`` + - ``collection`` + - ``collection`` + +No decision here makes those agree. A caller who has read the WQP +documentation looks for ``Station``; one reading Water Data's looks for +``monitoring_location_id``. An adapter that renamed either would be harder to +use, not easier, and the parameter names are public surface besides. + +Treating both sets under one rule forces a choice between two bad options: +abandon the glossary, and the shared modules lose the vocabulary that lets them +be shared; or enforce it everywhere, and every adapter's public surface drifts +from the API it wraps. + +Decision +-------- + +The glossary holds two kinds of term, and they carry different obligations. + +**Core terms are ours.** The package invented them and no service has a claim +on them: everything under *Retrieval*, *Failure and resumption*, *Configuration* +and *Boundaries*, plus *Collection family* and *Metadata*. One spelling, +enforced everywhere it appears -- prose, identifiers, tests. A second spelling +of a core term is a defect, not a variation, and is fixed rather than recorded. +This is what makes the lower-level modules shareable: transport, configuration +and the OGC engine can be written once because the words they are written in +answer to nothing outside this package. + +**Domain terms belong to the services.** *Monitoring location* and *collection* +name things the services define and spell differently. For these the glossary +chooses one term for **prose**, so that documents about the package are +internally consistent. It does not choose for the wire, and it does not choose +for an adapter's public surface: each adapter keeps its own service's spelling +in its parameters, and reproduces that service's vocabulary faithfully where it +appears in returned data. + +An adapter is where the two meet. Its public surface speaks its service's +language; what it hands to the shared modules speaks the core's. The +translation is the adapter's job, and a divergence at that boundary is the +design working rather than debt. + +Two rules follow: + +- **A term the glossary does not define is not used in the glossary.** A word + that earns a place in ``CONTEXT.md``'s prose earns an entry. Naming a term + only to say what an ADR calls it is a cross-reference, not a definition, and + does not license using the word elsewhere. +- **Only core misnamings are legacy.** *Known legacy names* records a core term + the code spells wrongly and cannot be renamed. A domain term at an adapter's + surface is not a legacy name; it is that adapter speaking its service's + language, and belongs with the term's own entry. + +Consequences +------------ + +- The recurring question -- may this docstring say *site*? -- has an answer that + does not depend on who is reviewing. In ``nwis`` it may, because that is the + spelling its service and its parameters use. In ``transport`` it may not, + because nothing there is about NWIS. +- Enforcement splits. A core term can be checked mechanically, since one + spelling is correct everywhere. A domain term cannot: the correct spelling + depends on which adapter the prose is about, so it stays a review judgement. +- *Known legacy names* becomes shorter and means something narrower. The entries + it loses are not resolved; they move to the term they belong to, as part of + its definition rather than a list of exceptions. +- A glossary entry now carries an obligation to say which kind it is. That is a + small cost per term and the reason the distinction is usable at all. +- The package's own inconsistencies in core vocabulary become defects with a + deadline rather than curiosities. The resolution chain's layers are the + standing example. + +Compliance +---------- + +``CONTEXT.md`` marks each domain term as such and names the per-service +spellings in the entry itself, so a reader who needs to know whether a word is +negotiable can see it without asking. + +The mechanical part is that the glossary must define what it uses: +``tests/architecture_test.py`` asserts every ``ADR NNNN`` citation resolves, and +the same file is where a check that ``CONTEXT.md`` defines its own vocabulary +would go. None is proposed yet -- a word-list check over prose has a poor +precision record in this repository, and the failure it would catch is one a +reader notices immediately. + +Whether a given adapter docstring should say *site* or *monitoring location* +remains a review judgement, and is meant to. + +Notes +----- + +Prompted by review of :doc:`0000-documenting-decisions`, where a reviewer found +``CONTEXT.md`` using *tier* in its own prose without defining it. The word was +already there before that record was written; recording each explanation once +made the gap visible rather than creating it. + +The per-service spellings in the table above were read from the adapters on +2026-09-01. diff --git a/docs/source/architecture/decisions/index.rst b/docs/source/architecture/decisions/index.rst index a5978707..29825505 100644 --- a/docs/source/architecture/decisions/index.rst +++ b/docs/source/architecture/decisions/index.rst @@ -31,4 +31,5 @@ belong here rather than in a docstring, an inline comment, or a commit message. 0010-adapter-scoped-settings 0011-configuration-profiles 0012-deprecation-horizons + 0013-core-and-domain-terms template From 57adda765b61a100e9863235d48a4966b7fa6af8 Mon Sep 17 00:00:00 2001 From: thodson-usgs Date: Tue, 1 Sep 2026 14:17:28 -0500 Subject: [PATCH 2/5] docs: read tier and rung as the records wrote them The glossary's Source entry claimed ADR 0010 calls a source a tier and ADR 0011 a rung. Neither is true. ADR 0009 and 0010 already say source -- source-major precedence is 0010's own phrase. 0010's tier names a different axis, the scope: the top-level tier that survives, the deferred gateway tier. 0011's rung is one position of its seven-rung ladder, where sources and scopes interleave. The code's tier-for-source identifiers misapplied 0010's scope word, and the glossary projected that confusion back onto the records; ADR 0013's standing example repeated it. Correcting the history also surfaced what was missing: Scope had no entry, though ADR 0010's whole subject is scoping, and the axis mixup is exactly the confusion a definition prevents. The Adapter-scoped setting entry carried the same error in the other direction -- "does not replace the package-wide source" named a scope level a source -- so the sentence now names the value rather than either axis. Also from this pass: portal is defined as the human-facing site fronting a service rather than left as an undefined near-synonym (CONTRIBUTING now says service where it meant the module split); the stall-timeout bullet no longer invites new prose to use either spelling; Facade is grounded in the design pattern it is named for; and the Source entry points NLDI's data_source at the domain-term rule. The preamble's define-before-use rule is restated without the ordering claim two mutually-referencing axes cannot satisfy. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01JAEQqs7XzQHGQQi2KakuXD --- CONTEXT.md | 41 ++++++++++++++----- CONTRIBUTING.md | 2 +- .../decisions/0013-core-and-domain-terms.rst | 10 ++--- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index 3e33eb5f..354b3e61 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -20,8 +20,9 @@ or an adapter's public surface: each adapter keeps its own service's spelling in its parameters. Such an entry names the per-service spellings itself; those are not legacy names. -A word carrying a package-wide meaning is defined here before this document -uses it. Naming one only to say what an ADR calls it is a cross-reference, +A word carrying a package-wide meaning has an entry here, and one entry may +name another; what no entry may do is lean on a word this document leaves +undefined. Naming a word only to say what an ADR calls it is a cross-reference, not a use. ## Retrieval @@ -84,6 +85,10 @@ the start. Each is an external system this package retrieves from. They are separate services with separate conventions, not one API with modes. +A **portal** is the human-facing site fronting one or more services — +`waterdata.usgs.gov`, `waterqualitydata.us`. The package talks to services; the +user guide points people at portals. The two words are not interchangeable. + **Water Data** — The modern USGS API at `api.waterdata.usgs.gov`, covering monitoring locations, time series, field measurements, samples, ratings, and statistics. The package's primary target. @@ -171,12 +176,18 @@ A public keyword is not automatically a setting. `ssl_check` is a getter argument on four adapters and resolves through no chain at all; the settings are the roster the configuration system knows. +**Scope** — How much of the package a setting's value applies to: the whole +package, or one adapter. Orthogonal to source: the scope says who a value is +for, the source says where it came from, and precedence orders sources first, +scopes within them. ADR 0010's word for a scope level is *tier* — the top-level +tier that survives, the host or gateway tier it defers. + **Package-wide setting** — A setting that applies to every adapter: the retry count, the progress line, the stall timeout. Set once, honored everywhere. **Adapter-scoped setting** — A setting named under one adapter, applying to that adapter and no other. It overrides the package-wide value for that adapter -alone; it does not replace the package-wide source. An adapter rejects a setting +alone, leaving that value standing for every other adapter. An adapter rejects a setting it has no use for, rather than accepting and ignoring it. The scope is the *adapter*, not the service and not the host, because the @@ -191,8 +202,14 @@ default. The order is resolved per setting rather than per source: a value supplied for one setting does not displace another setting's value from a lower source. -*Core term.* ADR 0010 calls a source a *tier* and ADR 0011 a *rung*; both are -this term, and those accepted records keep their own wording. +*Core term.* The accepted records already say it: ADR 0009 resolves settings +by source, and ADR 0010 keeps precedence *source-major*. ADR 0010's *tier* is a +different axis — the scope — and ADR 0011's *rungs* are positions of its merged +precedence ladder, where sources and scopes interleave. Neither is a second +spelling of this term, and the records keep their own wording. + +An external system is a *service*, never a source. NLDI's `data_source` +parameters are that service's own vocabulary, reproduced like `site-types`. **Origin label** — The exact thing a value came from, at finer grain than its source: `$API_USGS_RETRIES`, a path to the config file, the profile a caller @@ -201,9 +218,10 @@ parser names when it rejects one. A source is the category; an origin label is the instance within it. *Core terms.* The configuration chain is shared machinery, so one spelling binds -its identifiers as well as its prose. `_resolve` currently returns the origin -label under the name `source` and the source under the name `tier`; that is a -defect being corrected, not a second spelling to work around. +its identifiers as well as its prose. Where the chain's identifiers have said +`tier` for the source and `source` for the origin label, that is a defect to +correct — ADR 0010's scope word misapplied to a different axis — not a second +spelling to work around. **Selection** — Naming which profile an adapter should use. Done in code; a profile is never selected by the environment or implied by the file, so the @@ -251,7 +269,7 @@ these and `.importlinter`. **Facade** — A module that re-exports a subsystem's public surface and contains no logic of its own, so callers depend on a stable name rather than on internal -layout. +layout. The name is the structural design pattern's, not a coinage. **Leaf** — A module with no dependencies inside the package beyond other leaves, holding one general mechanism so that anything may use it without acquiring the @@ -277,8 +295,9 @@ legacy name and is not listed here; it belongs with that term's own entry - `ChunkInterrupted` is a permanent alias of `FanOutInterrupted` — the same class object under the name it was first published as. Both spellings are correct; neither is scheduled for removal. -- *No-progress budget* is ADR 0006's name for the **stall timeout**. Both - spellings are current; the setting is `stall_timeout`. +- *No-progress budget* is ADR 0006's name for the **stall timeout**. The + record keeps its wording; prose outside it says *stall timeout*, and the + setting is `stall_timeout`. - `ChunkedCall` is a permanent alias of `FanOut`, published on the OGC compatibility path. Like `ChunkInterrupted`, both spellings are correct. - `utils.query` is one *request*, not a query as defined above. It is a frozen diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a16ef5d4..7c2b7cbf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -244,7 +244,7 @@ link checking. * Follow the [PEP8 style guidelines](https://peps.python.org/pep-0008/). * The public interface should emphasize functions over classes; classes can and should be used internally and in tests. -* Group public download functions by data portal. For example, modern Water +* Group public download functions by service. For example, modern Water Data functions belong in `dataretrieval.waterdata`; legacy NWIS functions remain quarantined in `dataretrieval.nwis` during deprecation. * Treat a change to a service's documented return shape or metadata type as a diff --git a/docs/source/architecture/decisions/0013-core-and-domain-terms.rst b/docs/source/architecture/decisions/0013-core-and-domain-terms.rst index e055b5ea..8e5d1158 100644 --- a/docs/source/architecture/decisions/0013-core-and-domain-terms.rst +++ b/docs/source/architecture/decisions/0013-core-and-domain-terms.rst @@ -25,9 +25,9 @@ The two sets behave differently because their authority differs. Terms like *chunk*, *page*, *fan-out*, *plan*, *interruption*, *dialect* and *leaf* appear nowhere in any USGS API's vocabulary. They were invented here to describe machinery this package owns. Nothing external constrains them, so when -the package spells one of them three ways -- the resolution chain's layers have -been a *source*, a *tier* and a *rung* -- that is simply an inconsistency, and -one that can be removed by deciding. +the package spells one of them two ways -- the resolution chain's code said +*tier* for what its founding records, ADRs 0009 and 0010, call a *source* -- +that is simply an inconsistency, and one that can be removed by deciding. Terms like *monitoring location* and *collection* are different. The services name those things, and they do not agree with each other: @@ -115,8 +115,8 @@ Consequences - A glossary entry now carries an obligation to say which kind it is. That is a small cost per term and the reason the distinction is usable at all. - The package's own inconsistencies in core vocabulary become defects with a - deadline rather than curiosities. The resolution chain's layers are the - standing example. + deadline rather than curiosities. The resolution chain's ``tier``-for-*source* + identifiers are the standing example. Compliance ---------- From c35df5acfde3b5e14c295a0538dbf3ac5e1d70ab Mon Sep 17 00:00:00 2001 From: thodson-usgs Date: Tue, 1 Sep 2026 14:20:14 -0500 Subject: [PATCH 3/5] docs: give the precedence ladder and its rungs an entry ADR 0011, the user guide, and the configuration tests' comments all say rung; a word in use across three venues has earned its definition. With rung defined, the user guide's one "tiers below" was a second spelling of it and now reads "rungs below". Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01JAEQqs7XzQHGQQi2KakuXD --- CONTEXT.md | 6 ++++++ docs/source/userguide/configuration.rst | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CONTEXT.md b/CONTEXT.md index 354b3e61..9cf28efb 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -223,6 +223,12 @@ its identifiers as well as its prose. Where the chain's identifiers have said correct — ADR 0010's scope word misapplied to a different axis — not a second spelling to work around. +**Precedence ladder** — The one linear order resolution walks, highest first: +sources in their order and, within each source, scopes. Each position is a +**rung**; ADR 0011 states the ladder in seven. A rung is finer than a source — +one source can span several rungs — so prose that means a whole category says +*source*, reserving *rung* for when the position itself matters. + **Selection** — Naming which profile an adapter should use. Done in code; a profile is never selected by the environment or implied by the file, so the set of profiles in a file is inert until something asks for one. diff --git a/docs/source/userguide/configuration.rst b/docs/source/userguide/configuration.rst index 85472629..c2dcafa6 100644 --- a/docs/source/userguide/configuration.rst +++ b/docs/source/userguide/configuration.rst @@ -316,7 +316,7 @@ So one file can hold an overnight bulk shape beside a polite daytime one, and name as many of each as an adapter has uses for. A named profile states only what differs: everything it does not name still -comes from the adapter's default profile, the package-wide keys, and the tiers +comes from the adapter's default profile, the package-wide keys, and the rungs below — per setting. ``load`` reads the table and hands you a configuration object, so a name the From af526c6d6678860de1d43c413d945e50cd752502 Mon Sep 17 00:00:00 2001 From: thodson-usgs Date: Tue, 1 Sep 2026 14:26:30 -0500 Subject: [PATCH 4/5] docs: drop the portal entry; group by service in the interface view Defining *portal* as the human-facing site created three problems it did not solve. The word already carries three unrelated senses here: WQP's proper name (the Water Quality Portal), anyio's blocking portal in transport/fanout.py, and the user guide's page title for a table of websites. The new definition made five existing wqp.py docstrings violations -- "the portal serves the legacy and WQX3 interfaces from one root" is about the service, and reads naturally precisely because that service is named Portal. A glossary entry that manufactures violations in correct prose is not carrying its weight. The CONTRIBUTING change it came with stands on its own: modules are grouped by service, which is what the Services section enumerates, and "data portal" maps to neither the modules nor the portal table cleanly. The architecture interface view said the same thing and now matches. ADR 0001 keeps its wording, being accepted. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01JAEQqs7XzQHGQQi2KakuXD --- CONTEXT.md | 4 ---- docs/source/architecture/index.rst | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index 9cf28efb..f89fb2c4 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -85,10 +85,6 @@ the start. Each is an external system this package retrieves from. They are separate services with separate conventions, not one API with modes. -A **portal** is the human-facing site fronting one or more services — -`waterdata.usgs.gov`, `waterqualitydata.us`. The package talks to services; the -user guide points people at portals. The two words are not interchangeable. - **Water Data** — The modern USGS API at `api.waterdata.usgs.gov`, covering monitoring locations, time series, field measurements, samples, ratings, and statistics. The package's primary target. diff --git a/docs/source/architecture/index.rst b/docs/source/architecture/index.rst index 85fa47e8..4e3983ff 100644 --- a/docs/source/architecture/index.rst +++ b/docs/source/architecture/index.rst @@ -202,8 +202,7 @@ than be forbidden, and full-graph cycle detection (see ADR 0003). Interface view -------------- -The primary API is a collection of synchronous functions grouped by data -portal. Most tabular download functions return ``(DataFrame, metadata)``. +The primary API is a collection of synchronous functions grouped by service. Most tabular download functions return ``(DataFrame, metadata)``. NLDI and StreamStats retain service-specific geospatial or response-object contracts. From 6411f63a4a5bdae0986c753c28960c770febf260 Mon Sep 17 00:00:00 2001 From: thodson-usgs Date: Tue, 1 Sep 2026 14:34:44 -0500 Subject: [PATCH 5/5] docs: state ADR 0013's split where agents actually read it AGENTS.md's first bullet said "when a term there conflicts with a name in the code, the term wins" -- the rule in its pre-0013 absolute form. That sentence is load-bearing: it is the entry point every agent and contributor reads before writing anything, and read literally it licenses renaming an adapter's public parameters to match the glossary. It did exactly that here, producing a rename that had to be reverted. ADR 0013 splits the rule, so the bullet now does too: a core term binds identifiers, a domain term binds prose only and each adapter keeps its service's spelling. The two examples are the ones reviewers keep asking about. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01JAEQqs7XzQHGQQi2KakuXD --- AGENTS.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 8a19b7b4..b0c9006f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,8 +4,14 @@ - **`CONTEXT.md` is the shared vocabulary** — getter, query, chunk, plan, fan-out, page, adapter, facade, leaf, transport, collection, profile, effective configuration, and the legacy names that are deliberately not renamed. Read it - before writing code, docstrings, or commit messages; when a term there - conflicts with a name in the code, the term wins. + before writing code, docstrings, or commit messages. Two kinds of term live + there and they bind differently (ADR 0013). A **core** term is ours and takes + one spelling everywhere *including identifiers*, so a name in the code that + conflicts with it is a defect. A **domain** term -- *monitoring location*, + *collection* -- is fixed for prose only: each adapter keeps its own service's + spelling in its parameters, so `nwis.get_record(service="dv")` and WQP's + `Station` are that service's language rather than drift. Each entry states + which kind it is. - Architectural decisions and their rationale: `docs/source/architecture/decisions/` (ADRs, referenced by number throughout the code and by `.importlinter`). - Contributor workflow, style, and the quality gates in detail: `CONTRIBUTING.md`.