# Phase 1: Project Setup — Summary

## What Was Built

This phase established the installable Python package skeleton that all subsequent phases build on. It includes a Typer CLI with five placeholder commands, a configuration system that auto-creates `~/.unfamiliar/config.toml` on first run, and domain enums covering all investigation categories, mission states, and difficulty tiers from the requirements. The full directory tree for future subpackages (analysis, LLM, TUI, etc.) is scaffolded with docstrings.

## Key Decisions

1. **StrEnum backport for Python 3.10** — Inline `class StrEnum(str, Enum)` in `constants.py` rather than adding a `strenum` dependency. Keeps the dependency list clean for a single-file backport.
2. **tomli conditional dependency** — `tomllib` (stdlib 3.11+) with `tomli` fallback for 3.10, declared as a conditional dependency in `pyproject.toml`.
3. **Dynamic version via hatchling** — Version defined once in `__init__.py`, read by `pyproject.toml` via `[tool.hatch.version]`. Prevents version drift between the two files.
4. **API key permission model** — Config file keys are only read when file permissions are owner-only (mode 600). This is a security-first default, but trades off discoverability — users who set keys but forget `chmod` get no warning (noted for future improvement).
5. **Campaign directory naming** — `<repo-name>-<6-char-sha256-hash>` with suffix-based collision handling, bounded to 99 attempts before raising `ConfigError`.

## Complex Logic Explained

1. **API key resolution chain** (`config.py:resolve_api_key`) — Three-tier lookup: provider-specific env var (e.g., `ANTHROPIC_API_KEY`), then generic `UNFAMILIAR_API_KEY`, then config file. The config file tier only activates if `_has_strict_permissions` passes, which checks POSIX group/other bits are all zero. On Windows, config-file keys are never loaded (env vars only).

2. **Campaign directory collision handling** (`config.py:get_campaign_dir`) — First tries the unsuffixed name. If that directory exists, reads a `.repo_path` marker file to check ownership. If it's a different repo (hash collision), tries `-1` through `-99` suffixed variants. This is forward-looking — the marker file doesn't exist yet (created in Phase 2's data layer), so new campaigns always get the unsuffixed name.

## Connection to Previous Phases

This is Phase 1 — no prior phases. It provides the runnable skeleton, config system, and domain constants that Phase 2 (data layer) will build on. The enums in `constants.py` define the vocabulary for Pydantic models and SQLite schema in Phase 2. The `get_campaign_dir` function will be called by the repository layer to determine where campaign data is stored.
