Add ProofLine criteria documentation and Strategy Catalog v1 implementation

- Add acceptance criteria documentation (AC-0013 through AC-0023)
- Add Line-0003 discovery documentation
- Implement Strategy Catalog v1 with new database migration
- Update portfolio API endpoints and schemas
- Refactor strategy and portfolio services
- Add strategy management CLI commands
- Update domain models with strategy catalog support
- Add comprehensive tests for v1 strategies
- Update design documentation (data model, interfaces, runtime flows)
This commit is contained in:
2026-08-15 11:18:31 +09:00
parent 5fc389dea8
commit 6e02d92282
48 changed files with 2114 additions and 393 deletions
+25 -1
View File
@@ -102,6 +102,28 @@
- Only `status="active"` assets can be referenced when creating a new portfolio.
- Deactivated assets do not affect existing portfolios; only new creation is blocked.
## Entity: `StrategySet`
- Purpose: stable, reusable strategy catalog entry selected by portfolio mutations through its ID
- Source of Truth: `strategy_sets`; migration `20260814_0029` adds lifecycle and revision fields and seeds/reuses the canonical `target_value` / `{}` entry
- Lifecycle: active → updated with monotonically increasing revision → optionally inactive → deleted only when unreferenced
### Key Fields
- id :: text :: stable strategy ID; never changes during PATCH
- name/config :: text :: strategy identity/configuration pair; unique together
- nick :: text :: unique derived display key (`name:sha1(config)[:12]`), recomputed from the latest row state under the PATCH row lock
- status :: text :: `active` or `inactive`; inactive entries remain valid historical references but cannot be newly assigned
- revision :: integer :: starts at 1 and increments once per effective mutation; no-op PATCH does not increment
- created_at/updated_at :: timestamptz :: creation and last effective mutation timestamps
### Relationships and Deletion
- `portfolios.active_strategy_id` and entries in `portfolios.avabile_strategies` reference strategy IDs.
- New selection uses a strategy `FOR SHARE` lock in the same transaction as portfolio persistence; PATCH/DELETE use `FOR UPDATE` so concurrent mutation, inactivation, and deletion serialize.
- Deletion is rejected while either reference form exists. The reference check and delete share one transaction, preventing check-then-delete orphan races. Inactivation does not rewrite existing portfolio references.
- Trade snapshot persistence does not write either strategy-selection column. Strategy selection is owned only by portfolio create/update paths, so stale BUY/SELL state cannot resurrect a deleted strategy reference.
## Entity: `Portfolio`
- Purpose: represent an owned investment portfolio with balances, strategy references, tags, comments, and trading history
@@ -116,7 +138,8 @@
- symbol :: text :: display symbol populated via JOIN on assets (read-only, not stored in portfolios)
- status :: text :: `"enabled"` (active, default) | `"disabled"` (soft-deleted); set to `"disabled"` by `DELETE /v1/portfolios/{id}`; only `status` can be mutated on a disabled portfolio (restoration via PATCH); all other writes → HTTP 409
- owner_user_id :: text|null :: owning user reference for attribution and authorization
- active_strategy_id :: text|null :: currently selected strategy-set reference
- active_strategy_id :: text|null :: currently selected stable strategy-catalog ID; create requires an active strategy and update may select another active strategy
- strategy_revision :: integer|null :: read-only revision joined from the currently referenced StrategySet; subsequent API reads expose the latest committed shared config revision
- cash_balance :: double precision :: current cash snapshot after the latest ledger event
- asset_quantity :: double precision :: current holdings snapshot after the latest ledger event
- managed_by_daemon_id :: text|null :: soft reference to daemons.id; controls daemon-scoped API access; NULL = unassigned (fail-closed for ledger writes and asset listing); set to NULL on soft delete; added by migration 20260513_0016
@@ -333,6 +356,7 @@
- Alembic revisions in migrations/versions/ are the ordered schema history for persistent environments.
- app/repositories/postgres.py includes ensure_schema() for bootstrap safety, but long-term schema evolution should run through Alembic.
- Current Alembic head is `20260814_0029`; its strategy columns, default seed, and constraints are guarded for ensure_schema-first and repeatable execution.
- Comments, tags, auth tokens, and ledger rows are normalized into dedicated tables keyed to users or portfolios.
## Current Gaps / Planned Changes