Skip to content

[ConfigManager] Specify the Experimental Configuration Namespace - #4097

Draft
bdchatham wants to merge 1 commit into
mainfrom
plt-exp-config-spec
Draft

[ConfigManager] Specify the Experimental Configuration Namespace#4097
bdchatham wants to merge 1 commit into
mainfrom
plt-exp-config-spec

Conversation

@bdchatham

Copy link
Copy Markdown
Contributor

Specify, plan and tasks for the [experimental] namespace. No code. Independent of
#4094 and #4096.

First specs/ and docs/adr/ in this repository, so it sets the shape as well as the
content.

What it decides

A binary has one place to put a setting today, and every key there is a commitment: the
schema counter versions the declared space, and changing a key in it is a migration the
binary performs. Paying that per knob is not viable, so a knob either goes unwritten or
the commitment happens by accident.

[experimental] is a second namespace, registered through one SDK verb, whose values
resolve and reach their readers like any other and which sits outside the schema
contract.

The decision the registry forced

I started from pass-through: experimental keys undeclared, installed verbatim, outside
the declared space entirely. That maps neatly onto "not part of the API contract", but
it does not let a package register one, which is what the config SDK has to support.

The registry then settled the shape. It refuses a section name carrying a dot, and says
why: "a dotted name declares keys inside another section's subtree, where the two
sections' defaults land in one map and whichever renders last silently wins."
So a
package cannot register experimental.evm through the section verbs. The verb has to
own the prefix and nest under it on the caller's behalf, with one owner per name making
that safe.

docs/adr/0001 records that, and records why a per-key marking was rejected: a reader
asks for a key by name and an operator writes that name into a file, so neither sees a
flag held in the registry. A prefix is visible in the file itself.

Two risks named rather than deferred

Regeneration drops the value. seid config generate derives its file from
app.toml and config.toml, and neither carries an experimental key. Under the
regenerate-on-every-start model a controller would discard every experimental value, the
node would revert to a registered default, and nothing would say so. EXP-17 and EXP-18
exist for that, and the plan puts the carry-forward in the minimum version rather than
after it.

Registration lands before any migration chain. A key can be written onto real nodes
with no chain to graduate it. Acceptable only while the namespace promises nothing,
which is why EXP-24 is stated now rather than when the chain arrives.

Shape

  • specs/experimental-config/spec.md — 24 criteria across 5 requirements, each in an
    EARS template with an ID. Three user stories, each with an independent test.
  • specs/experimental-config/plan.md — interfaces, the sequence, the risks, and which
    requirements the minimum version leaves to the migration chain.
  • specs/experimental-config/tasks.md — six slices that ship on their own, each naming
    the criteria its tests cover.
  • docs/adr/0001-experimental-configuration-is-a-namespace.md

Verification

vale specs/experimental-config/spec.md reports 0 errors and 19 warnings. The warnings
are sentence length and passive voice; the gate is errors.

That exit status alone would not tell you the criteria were checked, so I broke one:
stripping SHALL from EXP-1 produces EARS-CriterionShall error, and restoring it
clears. The rule ran.

Two notes on the gate rather than the content. AgenticWriting.Spec-AcceptanceCriteria
is enabled at [*.md] in the shared vale config rather than scoped to
[specs/**/spec.md], so it fires on plan.md, tasks.md and the ADR, none of which
carry acceptance criteria by design. Either a repo .vale.ini or a scoping change in
the shared style fixes it, and both are conventions worth deciding rather than my
picking one here.

Open question in the spec

Whether an experimental group answers per kind of node at all. It does in EXP-3, for
consistency with a section, and a group whose value does not vary answers the same for
each kind. The alternative is a plain value and no kind.

A binary has one place to put a setting today, which is the declared key
space, and every key there is a commitment: the schema counter versions that
space and changing a key in it is a migration. Paying that per knob is not
viable, so a knob either goes unwritten or the commitment happens by accident.

This specifies a second namespace under a reserved experimental prefix,
registered through one SDK verb. Values in it resolve and reach their readers
like any other, and they sit outside the schema contract.

Twenty-four criteria across five requirements, each in an EARS template with an
ID a test names. The plan marks which of them the minimum version delivers and
which belong to the migration chain, and the tasks cut it into six slices that
ship on their own.

An ADR records the decision the registry forced. A per-key marking was the
other shape and it fails on the reader's side, because a reader asks for a key
by name and an operator writes that name into a file, so neither sees a flag
held in the registry. The registry also refuses a section name carrying a dot,
which is why a package cannot register experimental.evm through the section
verbs and why the registry owns the prefix and nests under it.

Two risks are named rather than deferred. Regenerating sei.toml derives from
the legacy files, which carry no experimental key, so a controller regenerating
on every start discards every experimental value unless the carry-forward lands
with the namespace. And registration is available before any migration chain
exists, which is acceptable only while the namespace promises nothing.

First specs/ and docs/adr/ in this repository.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedSep 3, 2026, 10:06 PM

@codecov

codecov Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 60.30%. Comparing base (2153e61) to head (eb2c8bd).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4097      +/-   ##
==========================================
- Coverage   61.35%   60.30%   -1.06%     
==========================================
  Files        2187     2079     -108     
  Lines      191779   179231   -12548     
==========================================
- Hits       117673   108083    -9590     
+ Misses      62972    61062    -1910     
+ Partials    11134    10086    -1048     
Flag Coverage Δ
sei-db 69.80% <ø> (ø)
sei-db-state-db ?

Flags with carried forward coverage won't be shown. Click here to find out more.
see 108 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant