Files
deepseek-harness/docs/rfc/implemented/simplification/2026-07-04-drop-unconsumed-web-observation-surface.md
T
Tianyi Cui e6fad266a6 docs(rfc): define and enforce a uniform RFC format; adopt it across the corpus
Define the in-file RFC contract in docs/rfc/README.md § The file format:
the header block (`# RFC: <title>` plus a dateless Status enum
cross-checked against the lifecycle folder), the per-lifecycle body
skeleton (a Problem opener everywhere; Proposal/Alternatives considered/
Acceptance criteria/Risks in proposed/; present-tense Decision/
Consequences with proposal-era headings banned in implemented/; the
frozen proposal shape in rejected/), and a mandatory Alternatives
considered section with a date-fenced grandfather comment for pre-format
RFCs whose alternatives are not reconstructible from the record.

Enforce it with a new doc-sync gate, scripts/verify-rfc-format.ts, and
normalize all 112 RFCs to it: ~15 Status-line spellings collapse to the
enum, 29 Context openers become Problem, the 39 legacy-format XXX debt
markers are resolved and banned from reappearing, proposal-era sections
in implemented RFCs are rewritten to shipped reality (including the
web/fs/subagent seam RFCs' migration plans and test checklists, closing
the doc-tiers deferred-work item on the web seam), every RFC gains an
Alternatives considered section or the grandfather comment, and the
bilingual pair is re-mirrored and re-recorded.

Move the generated index tables out of README.md into a fully generated
docs/rfc/INDEX.md — gen-rfc-index now writes the whole file, and
verify-rfc-classification checks its freshness and rejects index-shaped
rows in the curated README — which makes room for the format contract to
live in the README front door instead of a separate FORMAT.md.

The decision record, and the first RFC written in the new format, is
docs/rfc/implemented/process/2026-07-05-uniform-rfc-format.md.
2026-07-05 22:58:25 +08:00

4.8 KiB

RFC: Drop the unconsumed web observation surface — the providers-change event and the status methods

Status: implemented

Problem

WebService exposes an observation surface no production code observes:

  • web/providers-change (packages/web/web/src/index.ts) is declared and emitted on every provider registration and disposal, and each registration effect's rollback yield is ordered BEFORE the emit solely so a throwing change listener unwinds the registration. No listener exists outside the package's own two unit tests (one of which exists to pin that rollback ordering).
  • searchStatus() / fetchStatus() and the WebCapabilityStatus union (same package) have zero production callers: dsh-tool-web executes directly through ctx.web.search()/fetch() and surfaces unavailability as the structured WebError codes the seam throws at execution time (packages/web/tool-web/src/search.ts, packages/web/tool-web/src/fetch.ts); the only status callers are the web packages' own tests. The prose in packages/web/tool-web/README.md and architecture.md claims the tool "reads only the aggregated searchStatus()/fetchStatus()" — drift that survives only because nothing checks prose against call sites.

The seam's own design starves both surfaces of consumers: tool registration follows product ENABLEMENT, not provider availability (packages/web/tool-web/src/index.ts), and provider selection resolves at execution time, never cached — so there is no cache to invalidate, no registration set to recompute, and no caller that needs an availability probe distinct from executing and routing the structured error. HMR cleanup is carried by the effect disposers themselves.

This mirrors drop the unconsumed llm/adapter-change event, which removed the same notification shape, the same rollback-before-emit machinery, and the same listener-throw test from LlmService. That RFC's keep/cut criterion — keep tools/change for its plausible user-facing tool-list consumer, cut the boot-time backend-registry signal — puts a web-provider registry squarely on the cut side; the status methods are the same judgment applied to a pull surface instead of a push one.

Decision

The event declaration, both emits, and the rollback-before-emit ordering are deleted (the plain ctx.effect disposer carries HMR cleanup). searchStatus()/fetchStatus()/WebCapabilityStatus are deleted — the provider-private status() stays, since it feeds execution-time selection. The listener-throw rollback test that existed solely for the removed event is gone, and the emission assertions and every status-based assertion are rewritten onto the behavior a real caller observes: a successful search()/fetch(), or the structured WebError codes for unavailable/ambiguous/misconfigured provider sets. The cordis catalog is regenerated; packages/web/web/README.md, packages/web/tool-web/README.md (the drifted reads-status sentence), web.md, and the web paragraph in architecture.md describe the shipped contract; the web capability seam RFC's facts (it specified the event and the status aggregation) are amended per implemented/AGENTS.md.

Alternatives considered

Why not keep it?

The web seam RFC specified both deliberately — the event as a minimal HMR-visibility signal, the status methods as the tool's aggregated diagnostics — and a future provider-status panel is imaginable. But the same RFC's other choices starved them: derived-on-call selection and enablement-based registration leave no consumer that CAN need either, the shipped tool demonstrates the real pattern (execute and route the structured error), and the drifted README sentence shows the promised consumer never materialized. Per AGENTS.md "RFCs are proposals, not golden truth", these are the parts of that proposal the code has since shown to over-reach; a future observer reintroduces the smallest signal or query it actually consumes, shaped by that consumer.

Verification

No providers-change, searchStatus, fetchStatus, or WebCapabilityStatus spelling survives outside RFC history; the catalog is fresh (verify-cordis-catalog green); registration/disposal HMR-safety tests prove cleanup through execution behavior; and the tool-web README plus the architecture paragraph describe the execution-time error-routing contract the tool actually has.

Consequences

A future provider-picker UI or diagnostics panel that wants change notifications or a status query re-adds the smallest surface it consumes; the identical judgment, and its reversal condition, is already recorded on the llm precedent.