Onboarding + make M15 gate catch the plant + M17 override (#6,#17,#18,#19,#29) (#58)

Co-authored-by: claude <claude@jpaul.io>
Co-committed-by: claude <claude@jpaul.io>
This commit was merged in pull request #58.
This commit is contained in:
2026-06-22 15:48:40 -04:00
committed by Claude (agent)
parent 06b9f8f308
commit a6a3cfdc50
5 changed files with 112 additions and 20 deletions
@@ -332,7 +332,9 @@ config per environment.
> *"Refactor `sync.py` so it reads `TASKS_API_KEY` and `APP_ENV` from environment variables
> instead of hardcoding them. Pick the backend URL from `APP_ENV` (dev/staging/prod). Fail loudly
> with a clear message if `TASKS_API_KEY` is missing. Don't add any third-party dependency — load
> the `.env` file with a few lines of plain Python."*
> the `.env` file with a few lines of plain Python, and make sure the loader does **not**
> overwrite a variable that's already set in the environment, so a value passed on the command
> line still wins."*
You're looking for a result shaped like this (read the diff before you accept it):
@@ -372,6 +374,15 @@ config per environment.
grep -n "sk-live" sync.py # should print nothing
```
**Why `setdefault` and not plain assignment?** The loader uses `os.environ.setdefault(key, value)`,
which sets a variable *only if it isn't already set*. That precedence is load-bearing: a value the
environment already supplies — like an `APP_ENV` you pass on the command line — wins over the
`.env` file. A loader that writes `os.environ[key] = value` instead **clobbers** anything already
there, so the file silently overrides your command line and Part D's override demo does nothing.
This matches the real-world dotenv default (`override=False`): the file fills in gaps, it doesn't
stomp on what's already in the environment. If the AI hands you plain assignment, that's the
correction to make.
### Part D — Run it from the environment
5. Run it reading from your `.env`:
@@ -395,7 +406,9 @@ config per environment.
```
Watch the backend URL change with `APP_ENV` while the source never does. That's config in the
environment.
environment. **If the URL *doesn't* change, your loader is clobbering variables that were already
set** — it's using `os.environ[key] = value` where it needs `os.environ.setdefault(...)` (see
Part C). Fix the loader so the command line wins, and the override takes effect.
### Part E — Commit, and verify the secret didn't tag along