ANTHROPIC_API_KEY is now the ONLY accepted credential. Through v0.1.0 the preflight cleared on CLAUDE_CODE_OAUTH_TOKEN, and run_s10 went further: an unset key printed "note: relying on the CLI's own credentials" and carried on. That note was not a warning, it was a decision - made silently, on the operator's behalf, about who pays. Both paths are gone; a run with no key refuses with exit 2 before anything is opened. Red first, both halves: _check_credentials refuses an OAuth-only env, and the run entrance is driven as a real subprocess with a deliberately missing bundle, so the credential refusal must win the race against the bundle error. Detach it and the process reaches navigate_bundle instead - a different exit code, no refusal line, the fallback back in the output. The positive control (key set) gets past the gate and fails on the bundle, so the gate is a gate and not a wall. 997 -> 1002, offline, no key in env. The SDK exception is now stated where a reader meets it, not implied: this framework runs on the Claude Agent SDK, which starts the Claude Code CLI it bundles as a subprocess. That is the SDK's intended use WITH an API key, and it is a deliberate, stated exception to the owner's rule that his own code never starts Claude Code. Rewriting to direct HTTP calls was weighed and declined - measuring what the Agent SDK offers is the point of D7. The repo is closed as a worked example. Two prose claims were corrected rather than left standing: run_s10.py is no longer byte-frozen (it carries exactly one change, and runs/s10/ is still the v0.1.0 run), and its two round() call sites moved 110->118, 130->138. The credential paragraph is prose under an existing heading, not a new section: test_readme_anchors_loadbearing.py pins 14 heading ids MEASURED on the published page and forbids re-deriving them. This order forbids push, so a new heading could not have been honestly re-measured. Version 0.1.1: pyproject.toml, uv.lock self-entry, CHANGELOG - 3 of 3. No version badge in README, no constant in src. v0.1.0 stands as released. Order 20260920T131502Z-7496226791-from-.claude. The older D7 mirroring order 20260913T053840Z-9473220509 is retired unexecuted: po closes at v1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2.1 KiB
2.1 KiB
Contributing to portfolio-optimiser-claude
Thank you for your interest in contributing! This document provides guidelines and instructions for contributing.
Code of Conduct
Please read and follow our Code of Conduct.
How to Contribute
Reporting Issues
- Check existing issues before creating a new one
- Provide clear reproduction steps
- Include relevant environment details (OS, Python version)
Submitting Changes
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes following the conventions below
- Run the test, lint, and type checks (see Development Setup) and ensure they pass
- Commit your changes using Conventional Commits
(
type(scope): description) - Push to your branch and open a Pull Request
Pull Request Guidelines
- Follow the existing code style (
ruffenforced) - Type hints everywhere;
mypy-clean where possible - Include tests for new functionality — this project uses load-bearing tests: a test that covers a seam must fail when that seam is detached, not merely pass while wired
- The deterministic validator is mandatory and blocking — never make it an optional plugin
- Keep PRs focused on a single change
- Update documentation as needed
Development Setup
Requires Python ≥ 3.10 and uv.
# Clone your fork
git clone https://git.fromaitochitta.com/open/portfolio-optimiser-claude.git
cd portfolio-optimiser-claude
# Install dependencies
uv sync
# Run tests (offline, no API key required)
uv run pytest
# Lint and format
uv run ruff check .
uv run ruff format --check .
# Type-check (strict)
uv run mypy src
Tests run offline without an API key. A live run requires your own ANTHROPIC_API_KEY — keep it
in your environment, never commit it. It is the only accepted credential: a consumer Claude Code
subscription is not supported and must not be used to pay for a run, so a CLAUDE_CODE_OAUTH_TOKEN
is refused by the preflight and by the run entrance.
Questions?
Feel free to open an issue for any questions about contributing.