Skip to content

Config & docs hygiene sweep: remove dead config and fix misleading docs#165

Merged
max-tet merged 7 commits into
mainfrom
fix/clayde/config-docs-hygiene
Jul 17, 2026
Merged

Config & docs hygiene sweep: remove dead config and fix misleading docs#165
max-tet merged 7 commits into
mainfrom
fix/clayde/config-docs-hygiene

Conversation

@ClaydeCode

Copy link
Copy Markdown
Contributor

Closes #128.

One mechanical sweep removing dead config and correcting docs that contradict the code. Each item was verified against the code before being touched, and the two runtime bugs were reproduced before and after the fix.

What changed

Dead CONFIG env var removed (README, both justfile run-dev recipes, CI test.yml, tests/conftest.py). Nothing has read it since e2c06a7 swapped gconf for pydantic-settings; the justfile/CI values additionally named .yml files that no longer exist. The README now describes the real mechanism (config.toml + optional local_config.toml overlay + FREESHARD_* env, CWD-relative).

justfile run-dev-for-freeshard-controller pointed at production. FREESHARD_FREESHARD_CONTROLLER_BASE_URL is one underscore short of the __ nested delimiter, so pydantic-settings silently ignored it and the recipe talked to https://controller.freeshard.net. Same bug class as the 5de2998 incident. Reproduced both ways:

FREESHARD_FREESHARD_CONTROLLER_BASE_URL=...  -> https://controller.freeshard.net   # inert
FREESHARD_FREESHARD_CONTROLLER__BASE_URL=... -> http://127.0.0.1:8080              # lands

DISABLE_SSL could crash boot. It was interpolated bare, so a self-hoster omitting the line from .env passed an empty string and Settings() raised bool_parsing at startup. Now ${DISABLE_SSL:-false}; docker compose config renders false when unset and still honours an explicit true.

Two dead config options removed: services.backup.included_globs (never wired into the rclone command) and the [portal_controller] section (zero consumers — portal_controller.py reads freeshard_controller.base_url). Note the naming trap survives deliberately: the portal_controller.py module is live.

agents.md said Ed25519; the code is RSA-4096 with PSS padding (service/crypto.py), and both peer auth and controller calls use HTTP Message Signatures with RSA_PSS_SHA512. Three claims corrected; zero Ed25519 left in the repo.

README's API-doc link. Worth a note: the issue called it dead, but it still returns HTTP 200 — it serves a Redoc render of a 0.30.6 spec titled "Portal Core" while the repo is at 0.40.0. So the falsehood was "of the latest stable release", not a 404. Replaced with a pointer to /redoc, /docs and /openapi.json, which always match the running version.

Skill library de-staled (last commit). Nine SKILL.md files documented these as live findings; left alone they would now teach the opposite of the truth. Two rows even carried their own retirement condition and had met it (docs-and-positioning said "empty means FIXED; delete row 1"; config-and-flags recommended exactly the ${DISABLE_SSL:-false} written here). Durable lessons are kept and reframed as history; the specific "still broken" claims are gone.

Verification

  • 173 passed (full suite), just cleanup clean, ruff clean.
  • One test is deselected, not fixed: test_app_lifecycle.py::test_app_starts_and_stops needs to bind host port 80, which this dev VM's own Traefik holds (Bind for 0.0.0.0:80 failed: port is already allocated). It fails identically on unmodified main — I confirmed that in a clean worktree at the branch point, so it is environmental and not a regression from this PR. CI has port 80 free.

Deliberately not done (two findings for you, not fixed here)

  1. uv.lock is drifted on main: it pins shard-core==0.39.5 while pyproject.toml says 0.40.0, so any uv run rewrites the lock and dirties the tree. uv sync --frozen does not fail on it, so CI is unaffected. It predates this branch and looks like a 0.40.0 bump that landed before 2f4e134 taught set-version to keep the lock in sync. Left out of this PR as unrelated — worth its own one-line commit.
  2. .serena/ is untracked and not gitignored. The serena MCP writes it into the repo, and my first git add -A swept it into a commit; I stripped it back out of history. Any bulk-commit recipe will sweep it again. A .gitignore line would fix it, but that's your tooling choice, so I've only flagged it.

Recommended reading order

  1. shard_core/settings.py, config.toml — the dead options
  2. docker-compose.yml, justfile, .github/workflows/test.yml, tests/conftest.py — the env-var fixes
  3. README.md, agents.md — the doc corrections
  4. .claude/skills/** — the de-staling sweep (largest diff, lowest risk; read last)

🤖 Generated with Claude Code

The CONFIG env var is a leftover of the gconf loader that e2c06a7 replaced
with pydantic-settings. Nothing reads it: config.toml is always loaded and
local_config.toml overlays it whenever the file is present in the working
directory. The justfile and CI values were doubly misleading because they
named .yml files that have not existed since the TOML migration.

Drop it from both run-dev recipes, the test workflow, and tests/conftest.py,
and describe the actual loading mechanism in the README.
…ntroller

pydantic-settings uses "__" as the nested delimiter, so
FREESHARD_FREESHARD_CONTROLLER_BASE_URL never matched and was silently
ignored: the recipe fell back to config.toml and talked to the production
controller at https://controller.freeshard.net. Same bug class as 5de2998.

Verified with:
  FREESHARD_FREESHARD_CONTROLLER__BASE_URL=http://127.0.0.1:8080 \
    python -c "from shard_core.settings import Settings; \
               print(Settings().freeshard_controller.base_url)"
which prints the production URL before the change and the local one after.
DISABLE_SSL was interpolated without a default or a :? guard, so a
self-hoster who omits the line from .env passed an empty string to
FREESHARD_TRAEFIK__DISABLE_SSL, and Settings() failed at startup with
"Input should be a valid boolean ... input_value=''".

false matches both the field default and the documented .env.template value,
so an unset var now behaves like an absent one. Verified with docker compose
config: the var renders as "false" when unset and still honours an explicit
DISABLE_SSL=true.
Both parse fine and do nothing, which makes them look load-bearing:

- [portal_controller] base_url survived the portal -> freeshard-controller
  migration; service/portal_controller.py reads
  freeshard_controller.base_url, and nothing reads settings().portal_controller.
- services.backup.included_globs was never wired into the rclone command;
  service/backup.py syncs the directories list only.

Removing them keeps the config surface honest about what actually changes
behavior. Settings() still loads and backup keeps syncing core and user_data.
The shard has never used Ed25519. service/crypto.py generates RSA-4096 keys
and signs with PSS padding, and both peer auth (service/peer.py) and
controller calls (service/signed_call.py) use HTTP Message Signatures with
RSA_PSS_SHA512.
…own docs

The link advertised "the latest stable release" but pointed at the abandoned
GitLab pages of the pre-rename portal_core project, which still serve a 0.30.6
spec titled "Portal Core" while the repo is at 0.40.0.

The app already serves Redoc at /redoc, Swagger at /docs and the schema at
/openapi.json, so pointing there always matches the running version and cannot
go stale again.
The skill library documented all six items as live problems, in some places
with a recorded reproduction. Left alone it would now teach the opposite of
the truth: nine SKILL.md files told agents that CONFIG is set-but-dead, that
the justfile recipe silently talks to production, that an unset DISABLE_SSL
crashes boot, that two dead config options are still parsed, and that
agents.md claims Ed25519.

Two rows carried their own retirement condition and had met it:
docs-and-positioning said "empty means FIXED; delete row 1", and
config-and-flags recommended exactly the ${DISABLE_SSL:-false} this PR wrote.

Where the finding taught something durable, the lesson is kept and the
specifics moved to history: the env-delimiter trap now leads with the
verify-one-liner, the compose trap generalises to any unguarded ${VAR}, and
the dead-config table becomes a record of what was removed plus the rule that
an option is only real if something reads it.

Line-number drift in file:line references is deliberately not chased; each
skill's drift table already says to re-verify those by grep, and much of the
drift predates this branch.
@ClaydeCode
ClaydeCode requested a review from max-tet July 15, 2026 01:48
@max-tet
max-tet merged commit 2a60f86 into main Jul 17, 2026
7 checks passed
@max-tet
max-tet deleted the fix/clayde/config-docs-hygiene branch July 17, 2026 20:43
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.

Config & docs hygiene sweep: remove dead config and fix misleading docs

2 participants