retire root-level sol.py and media.py; install-time verify
- Move sol.py -> think/sol_cli.py and media.py -> think/media.py via git mv (rename-only; no content change).
- Drop [tool.setuptools] py-modules block from pyproject.toml; update console-script entry point to think.sol_cli:main. Existing packages.find include "think*" already covers the moved files.
- Update every import site: 6 production modules (think/retention.py, think/utils.py, think/importers/shared.py, observe/utils.py, observe/transcribe/main.py, apps/import/routes.py) plus 3 test modules (tests/test_sol.py, tests/test_heartbeat.py, tests/test_service.py). Update scripts/gate_agents_rename.py to track the new sol_cli.py path.
- Add .python-version-hash marker (cmp-guarded, driven by a FORCE prereq) as a prerequisite of .installed, so the editable install is rebuilt when the system Python minor version changes.
- Add an install-time smoke-verify on the phony `install` target: probe `from think.sol_cli import main` from /tmp using $(CURDIR)/$(VENV_BIN)/python; on failure, run one bounded `uv pip install -e . --no-deps` recovery and re-probe; if still broken, exit non-zero with a pointer to `make clean-install`. This lives on `install` (not inside `.installed`) so it fires on every `make install` invocation, which is what .pth-deletion recovery requires — a deliberate refinement of scope §5 to satisfy scope §6.
- New tests/test_install_verify.py (4 subprocess-based smoke tests; skip cleanly if .venv is absent): sol_cli import from /tmp, media import from /tmp, `.venv/bin/sol --version`, and editable-finder MAPPING has no 'sol'/'media' keys.
- Update active-layout doc mentions in AGENTS.md, docs/project-structure.md, docs/SOLCLI.md, docs/design/observer-actions.md, and the think/link/service.py docstring.
- .gitignore gains .python-version-hash.
Eliminates the structural fragility that caused Ramon's 2026-04-22 install failure (req_afbcvppi): the py-modules declaration combined with setuptools' with_suffix('.py') fallback + an interpreter-blind `.installed` marker meant that stale editable-finder mappings persisted silently across Python minor-version bumps. The editable install now registers cleanly, self-checks on install, and regenerates when the interpreter changes.