What isn't the dev agent's moves to nisse-core, unchanged in behaviour, with its tests: canonical, render, render_anthropic, llm, catalog, probe, context, views, state, reconcile, worker, cancel, dump, transport, matrix, execution, testing, vault, memory, oplog, envfile and gitea (whole). - nisse_core.state.StateStore holds the tables every agent has; an agent's subclass adds its tables (version, migrations), roles and views. nisse_dev.state.StateStore adds the build VM blocks (v5). - views.project takes what each role is shown, rather than a fixed table. - Vault takes the agent's name (agent=), for provenance. - A test that nisse_core never imports an agent. - The loop, config, git, delegation, expert, tools and evals stay in nisse-dev until nisse-ops has a loop to share. Docs: the Development Plan marks M7.1 done and notes that Phase 6 waits on the agent host and Terraform; Architecture Part L names the package. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J5Utyfzw7gF7UhjRDEtjTk
23 lines
737 B
Python
23 lines
737 B
Python
"""Minimal .env loader (architecture L12: secrets from env/.env, nothing hardcoded).
|
|
|
|
Deliberately tiny: KEY=VALUE lines, comments and blanks ignored, existing
|
|
environment variables never overridden (real env wins over the file).
|
|
"""
|
|
|
|
import os
|
|
from collections.abc import MutableMapping
|
|
from pathlib import Path
|
|
|
|
|
|
def load_env_file(path: Path, env: MutableMapping[str, str] = os.environ) -> None:
|
|
if not path.exists():
|
|
return
|
|
for line in path.read_text().splitlines():
|
|
line = line.strip()
|
|
if not line or line.startswith("#") or "=" not in line:
|
|
continue
|
|
key, value = line.split("=", 1)
|
|
key = key.strip()
|
|
if key and key not in env:
|
|
env[key] = value.strip()
|