Skip to content

Restructure reflect as a proper Python package with pyproject.toml - #11

Draft
codeyogi911 wants to merge 7 commits into
mainfrom
claude/apply-agents-cli-patterns-Ymvpb
Draft

Restructure reflect as a proper Python package with pyproject.toml#11
codeyogi911 wants to merge 7 commits into
mainfrom
claude/apply-agents-cli-patterns-Ymvpb

Conversation

@codeyogi911

Copy link
Copy Markdown
Owner

Summary

Restructure reflect from a shell-script-based CLI into a proper Python package with standard packaging infrastructure. This enables distribution via PyPI, installation via uv tool install / pip install, and proper dependency management.

Key Changes

  • Package structure: Move all Python modules from lib/ to src/reflect/ following PEP 420 conventions
  • Packaging: Add pyproject.toml with hatchling build backend, console script entry point (reflect = reflect.cli:main), and dependency declarations
  • Import paths: Update all relative imports from from lib.X import to from .X import (intra-package imports)
  • CLI entry point: Refactor cli.py to export build_parser() and main(argv=None) for programmatic use; remove sys.path manipulation
  • Version management: Move version string to src/reflect/_version.py and reference via tool.hatch.version
  • Module initialization: Add __init__.py and __main__.py to enable python -m reflect
  • Exit codes: Introduce exit_codes.py module with named constants (OK, USER_ERROR, ENV_ERROR)
  • Code quality:
    • Add --dry-run flag to reflect init for safe preview of filesystem changes
    • Improve formatting consistency (ruff format + isort-style import ordering)
    • Add type hints to test fixtures and new modules
  • Testing: Add comprehensive test suite (tests/test_cli.py, test_format.py, test_wiki.py, test_exit_codes.py, conftest.py)
  • Documentation:
    • Add docs/spec.md (v5.0.0 specification for .reflect/ format)
    • Add docs/roadmap.md (phases 1–3 for universal read path, harness ecosystem, trust/provenance)
    • Add docs/configuration.md, docs/install.md, docs/skill.md, docs/commands.md, docs/index.md
    • Add mkdocs configuration and GitHub Pages deployment workflow
    • Add mkdocs hook for auto-generating CLI reference from parser
  • CI/CD:
    • Expand GitHub Actions: add lint (ruff, mypy), test (3.11–3.13), and docs build/deploy workflows
    • Remove old tarball-based release workflow; rely on PyPI via hatchling
  • Installation: Replace install.sh with standard package installation methods (uv, pip, pipx)
  • Skill & hooks: Move to src/reflect/_data/ and update SKILL.md with "When to use" / "When NOT to use" guidance

Notable Implementation Details

  • No external dependencies: reflect remains zero-dependency (subprocess, pathlib, json, yaml-lite parsing only)
  • Dry-run mode: reflect init --dry-run previews all filesystem changes without modifying disk
  • Backward compatibility: Existing .reflect/ repos continue to work; migration path for old harness/format.yaml
  • Import safety: All relative imports use dot notation; no sys.path manipulation in installed package
  • Test isolation: conftest.py provides tmp_repo fixture for safe subprocess testing in temporary git repos

https://claude.ai/code/session_01Kh1P8oy4huJcEEWnBrJK4X

claude added 7 commits April 24, 2026 23:06
…/reflect/)

Adopts google/agents-cli packaging conventions.

- Replace install.sh + symlink model with pyproject.toml + uv.
- Install via `uv tool install reflect-cli` / `uvx reflect` / `pip install reflect-cli`.
- Move lib/*.py → src/reflect/*.py; convert absolute `from lib.X` imports to
  relative `from .X` imports. Rename version.py → _version.py (hatch-managed).
- Extract CLI dispatch from the root `reflect` script into src/reflect/cli.py.
  Add __main__.py for `python -m reflect`. Console script: reflect = reflect.cli:main.
- Move templates/, skill/, hooks/ into src/reflect/_data/ as package data;
  init.py resolves via Path(__file__).parent / "_data" (works in editable and
  installed modes).
- Rewrite cmd_upgrade to use `uv tool upgrade reflect-cli` instead of the
  obsolete curl-install.sh pipeline.
- Replace release.yml with `uv build` + GitHub Release upload.
- Update README install section, CLAUDE.md structure, smoke.sh to invoke the
  installed console script (`uv run reflect …`).

Verified: `uv run reflect --help`, `reflect init --no-wiki`, `reflect status`,
scripts/smoke.sh all green.

https://claude.ai/code/session_01Kh1P8oy4huJcEEWnBrJK4X
… __init__.py

The Phase 1 rename commit moved lib/ → src/reflect/ but the post-move edits
that converted `from lib.X` → `from .X` (and the new __init__.py exporting
__version__) were not staged. Without these, import-time the package fails
because `lib` no longer exists. The editable install picked up the working
tree, which is why the smoke test passed despite the missing diff in the
previous commit.

Files touched: __init__.py, context.py, evidence.py, improve.py, ingest.py,
init.py, lint.py.

https://claude.ai/code/session_01Kh1P8oy4huJcEEWnBrJK4X
…shooting

Adopts agents-cli's narrative-first skill documentation style without
fragmenting reflect's single-skill router (which already uses the idiomatic
Claude Code $ARGUMENTS dispatch).

- Add top-level "When to use this skill" / "When NOT to use this skill"
  sections so Claude Code can decide whether to invoke /reflect at all.
- Restructure each Command section with its own "When to use" / "When NOT
  to use" / "Common failures" sub-sections (Ingest, Lint, Search, Status,
  Sessions, Timeline, Improve, Metrics, Init & Upgrade).
- Document the new --dry-run flag for ingest (added in Phase 3).
- Update the source-of-truth path note to point at the new package data
  location: src/reflect/_data/skill/SKILL.md.

https://claude.ai/code/session_01Kh1P8oy4huJcEEWnBrJK4X
Adopts the agents-cli safety-flag convention without disrupting existing
behavior.

- Add --dry-run to `reflect ingest`: still runs the triage subagent so the
  user sees the plan, then exits without writing pages, updating log.md,
  refreshing index.md, re-indexing qmd, or advancing .last_run.
- Add --dry-run to `reflect init`: prints every filesystem operation it
  would perform (template copies, wiki dir creation, qmd registration, skill
  install, agent install, CLAUDE.md scaffold) without touching disk.
- Add --dry-run to `reflect upgrade`: previews the format.yaml diff path,
  config.yaml addition, and skill/agent reinstalls without writing.
- Plumb dry_run through helpers: _install_skill(dry_run), _wire_agents(dry_run).
- New src/reflect/exit_codes.py module documenting the 0/1/2/3 convention
  (success / user error / env error / upstream error) for use in new code.
  Existing returns are left as-is to keep the diff minimal.

Skipped --auto-approve: there are no interactive prompts to bypass; the
existing init/upgrade flow only no-ops when files already exist. Adding the
flag without a use case would be dead code.

Verified: `reflect init --dry-run --no-wiki` makes no fs changes; smoke test
still passes; --help shows new flag with example.

https://claude.ai/code/session_01Kh1P8oy4huJcEEWnBrJK4X
- Configure ruff: select E/F/I/UP/B/SIM/RUF; ignore line-length, E741, B008,
  SIM105/108, RUF001/RUF003 (em-dash false-positives in user-facing strings).
- Apply `ruff format` across src/reflect and tests; clear all remaining
  warnings (F841 unused vars, B904 raise-from, B007 unused loop var, RUF005
  list-spread, RUF059 unpacked unused). 0 issues.
- Add tests/ with conftest.py (tmp_repo fixture that initializes a throwaway
  git repo with GPG signing disabled). Tests:
    * test_cli.py — version flag, --help lists subcommands, dispatch table
      contains all expected commands, init --dry-run is non-mutating, search
      requires a query, metrics emits valid JSON.
    * test_wiki.py — slugify edge cases, parse_frontmatter roundtrip, write→
      read page roundtrip.
    * test_format.py — load_format default fallback (and isolation from the
      DEFAULT_FORMAT singleton), user-override parsing, entry_fields, comments.
    * test_exit_codes.py — codes are distinct, OK == 0.
- Fix latent bug exposed by tests: load_format used dict.copy() (shallow), so
  mutating the returned `sections` list bled into DEFAULT_FORMAT. Switched to
  copy.deepcopy.
- Configure mypy permissively (strict=false, ignore_missing_imports) — covers
  20 source files clean.

All 20 tests pass; ruff check + ruff format check + mypy all green.

https://claude.ai/code/session_01Kh1P8oy4huJcEEWnBrJK4X
- mkdocs.yml at repo root: Material theme (light/dark toggle), instant
  navigation, code-copy, edit-on-github links, search suggestions.
- docs/hooks/cli_reference.py: mkdocs hook that introspects build_parser()
  from src/reflect/cli.py and injects `reflect --help` plus every subcommand's
  --help into commands.md at build time. Mirrors agents-cli's hook pattern but
  auto-generates from argparse instead of SKILL frontmatter (we have both;
  argparse is more authoritative for flags).
- docs/index.md, install.md, configuration.md, skill.md: hand-written
  guides covering the user-visible surface.
- docs/commands.md: contains a single `{{ cli_reference }}` placeholder; the
  hook expands it.
- docs/spec.md, docs/roadmap.md: copies of the root SPEC.md / ROADMAP.md so
  the docs site is self-contained.
- exclude_docs filters out docs/badges (shields.io endpoints, not docs).
- .gitignore: add Python build/test/lint cache dirs and mkdocs site/ output.

Verified: `uv run mkdocs build --strict` succeeds; the rendered commands page
contains expanded help text for all 11 subcommands.

https://claude.ai/code/session_01Kh1P8oy4huJcEEWnBrJK4X
Replace the old smoke-only CI with a multi-job pipeline; add a docs deploy
workflow.

ci.yml — three jobs:
- lint: ruff check + ruff format --check + mypy on src/reflect.
- test: pytest with coverage on Python 3.11 / 3.12 / 3.13 (matrix).
- smoke: scripts/smoke.sh (depends on lint + test passing first).

All jobs use astral-sh/setup-uv@v3 with caching enabled. uv resolves the
dev/docs extras from pyproject.toml; no separate requirements files.

docs.yml — build + deploy:
- Builds the mkdocs-material site with --strict on every push to main.
- Uploads as a Pages artifact and deploys via actions/deploy-pages@v4.
- Uses concurrency group docs-<ref> with cancel-in-progress: false so
  in-flight deploys finish even if a newer commit lands.
- Requires `pages: write` and `id-token: write`; assumes GitHub Pages is
  configured to deploy from Actions in repo settings.

Verified locally: ruff check, ruff format check, mypy, pytest (20 passing),
and mkdocs build --strict all green.

https://claude.ai/code/session_01Kh1P8oy4huJcEEWnBrJK4X
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants