feat(#179): canonicalize watcher wings at parse boundary (5th + final) - #188
Merged
Conversation
Fifth and final write surface for #179. The watcher isn't an HTTP endpoint so it can't take a pydantic body — but the same architectural goal applies: canonicalize wing at the *input* boundary so all downstream code can trust the WatchTarget is canonical. Pre-#179: parse_watch_dirs ran ``normalize_wing_name`` only on path-derived wings (when env entry was bare ``path`` with no ``=wing``). Explicit ``path=Wing_Name`` env entries were passed through verbatim, and a defensive ``_normalize_wing_slug`` ran later in _internal_mine before subprocess spawn. Post-#179: parse_watch_dirs normalizes both branches (path-derived AND explicit) through normalize_wing_name. WatchTargets always carry canonical slugs. The use-time normalize in _internal_mine drops to a comment explaining the new invariant. Test added: ``Palace_Daemon`` and ``palace_daemon`` env entries produce identical WatchTarget.wing values ("palace_daemon"). Was the shape of the pre-#175/#178 bug class — mixed-case writes paired with canonical reads producing empty result sets. This closes the wing-canonicalization migration that began with #172. All 11 wing/room-accepting sites in palace-daemon now canonicalize at the input boundary: Read side (#180): GET /search, GET /list, GET /search/fast — FastAPI Depends() Write body (#181, #182, #183, #184, #186, #187): POST /search/keyword, POST /search/hybrid, POST /search/age-fused, POST /backfill-age, POST /silent-save, POST /mine, POST /memory — pydantic body models in search_models.py Internal env (this PR): PALACE_WATCH_DIRS via watcher.parse_watch_dirs Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
jphein
added a commit
that referenced
this pull request
May 29, 2026
…s incident #179 closed — wing/room canonicalization now structural across all 11 surfaces (#180→#188). Documents the #187 validate_default regression and the #185 stale-deploy incident (dead Syncthing on familiar let deploy.sh restart on stale source while reporting success). Reorders open work: #185 promoted to "actionable, unblocked" as the smallest next item. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fifth and final write surface for #179. The watcher isn't an HTTP endpoint so the pydantic-body approach doesn't apply directly — but the same architectural goal does: canonicalize at the input boundary so all downstream code can trust the WatchTarget.
Pre-#179:
parse_watch_dirsrannormalize_wing_nameonly on path-derived wings; explicitpath=Wing_Nameenv entries flowed through verbatim and were normalized later in_internal_mineat use-time.Post-#179:
parse_watch_dirsnormalizes both branches. WatchTargets always carry canonical slugs. The use-time normalize in_internal_minedrops to a comment explaining the new invariant.Test added:
Palace_Daemonandpalace_daemonenv entries produce identical WatchTarget.wing values. This was the shape of the pre-#175/#178 bug class.This closes the wing-canonicalization migration that began with #172. All 11 wing/room-accepting sites in palace-daemon now canonicalize at the input boundary:
Depends()