# Finance sprint execution discipline

For a read-only audit of an existing FinanceManager deployment, runtime paths, rollback readiness, and Tailscale Serve/Funnel exposure before release work, use `references/financemanager-deployment-tailscale-readonly-audit.md`.

For a sensitive, source-only sprint inventory spanning market/FX providers, snapshot models and migrations, scheduler/jobs/locking, TWR/MWR, versioned policy benchmarks, quantitative risk, and API/UI integration, use `references/read-only-finance-sprint-code-inventory.md`. It requires exact path/symbol tracing, canonical-vs-legacy separation, reuse-with-boundary-fix classification, and unchanged-tree/privacy verification.

For read-only classification of sensitive portfolio-source candidates and canonical-source selection, use `references/read-only-portfolio-source-inventory.md`. It defines a sanitized disclosure allowlist, snapshot-vs-transaction date semantics, position/cash counting, CSV locale-role inference, reconciliation grades, parser determinism, and date-alignment rules.

For focused audits of bulk quote collection and valuation completeness, use `references/market-provider-valuation-collection-audit.md`. It adds deterministic over-limit probes, holdings-aware selection checks, structured provider-error tracing, historical-capability and current-as-history counterexamples, `suspected_inactive` side-effect checks, and real pagination/retry/resume semantics.

## Verified progress claims
- A normal chat response ends foreground execution. Never say work continues after sending one unless a persistent executor is verified.
- When the user asks whether work is still active, answer immediately with the concrete current gate/finding and then make an actual progress tool call in the same response. Do not let a long silent verification loop look abandoned, and do not turn the liveness answer into a terminal status-only update.
- A background executor is reportable only after checking: actual child process, correct cwd and branch, external log path, and a new log line or worktree file change. A shell wrapper or a `running` status alone is not evidence.
- If liveness is disputed, inspect PID/children/cwd/cmdline/CPU/wait state/log mtime and worktree mtimes. If stalled, TERM only the identified process tree; preserve the diff. Use KILL only if TERM fails.

## Timeout provenance before stopping
- Elapsed wall-clock time, an intuition that a turn is “too long,” unfinished implementation, or ordinary test failures are never technical timeout evidence. Continue foreground tool execution until the requested package is verified or a real external event stops it.
- Report a technical timeout/blocker only when a tool, provider, gateway, or runtime emits a concrete timeout/cancel/error event with an exception, error code, or explicit cause.
- When provenance is disputed, inspect the stored session event sequence first: classify the alleged timeout text as `assistant`, `tool`, `system`, `cancelled`, or `error`; record only timestamps/event types and a redacted excerpt. A normal assistant message with successful tool activity immediately before it proves the model chose to stop—it does not prove a runtime timeout.
- Resolve the active gateway contract from the running process and installed source, not assumptions: check `agent.gateway_timeout`, its config-to-`HERMES_AGENT_TIMEOUT` bridge, gateway logs, and the inactivity-monitor code. Distinguish inactivity limits from wall-clock limits. Do not recommend changing a timeout unless its configured value and matching timeout event are both evidenced.
- Preserve an uncommitted sprint diff across interruption. On resumption verify only branch, HEAD, status, diff stat, and `git diff --check`; never reset, clean, stash, or create a replacement worktree when the existing diff is the agreed source of truth.

## Bounded package execution
- Split a large sprint into explicit implementation and closeout packages only when the user requests that boundary. Within each package, continue through all specified focused tests and static gates; a status report is terminal only after those gates pass or a genuine evidenced external blocker occurs.
- Do not start extra workers after a user limits worker count. A recovery worker requires explicit permission.

## Request-based financial write contracts
- Preview stays storage-free and returns both a payload-bound preview identifier and a unique confirmation/request identifier.
- Idempotency binds the request identifier to the canonical payload hash: same key plus same payload returns the same committed version; same key plus changed preview/payload fails closed; a new key may intentionally commit the same content as a new version. Test A → B → A as versions 1, 2, 3 with correct predecessor links and exactly one active row.
- Keep activation, version assignment, audit creation, policy insert, and allocation inserts in one immediate transaction. The `IntegrityError` recovery path must re-query by request identifier and compare payload hash; never fall back to content fingerprint lookup.
- Add nullable request-id/payload-hash columns for legacy rows, a partial unique index for non-null request IDs, and immutability protection for newly stored request identity. Prove migration on both an empty DB and a synthetic pre-upgrade schema while preserving old rows unchanged.
- Audit details use an exact allowlist. Parse stored JSON and compare the exact key set; do not rely on substring assertions. Keep the entity identifier in `entity_id`, never duplicate full financial policy content, request IDs, preview IDs, or hashes into audit details.

## Migration regression
- A migration-version bump changes a cross-suite contract. Locate and update intentional schema-version expectations **across the entire repository**, not only the feature tests, then run every matched test file before the full suite. Shared DB helpers can turn one stale assertion into many failures.
- Inspect the CI workflow before opening the PR for exact collected-test-count gates and migration labels. Run `pytest --collect-only -q` after all test edits and reconcile the expected count before the one intended full CI run.
- Do not hide new scenarios inside an unrelated existing test merely to preserve a hard-coded count. Update the gate transparently; if the available GitHub credential cannot modify workflow files, stop before push and request a credential with workflow scope.
- A failed CI is still a CI execution. Never describe a corrected rerun as the single run. If a rerun becomes necessary, report both runs accurately and explain the preflight miss.
- Once a PR branch is published, fix CI with an additive commit and normal push. Do not amend/force-push published history merely to preserve a one-commit narrative; history rewrite requires explicit approval.
- Stage every intended file—including any deliberate `git add -f`—before the final repository-safety scan. Adding an ignored JSON/CSV or other file after scanning invalidates the scan; rerun it against the exact staged candidate.
- Before PR creation, verify: repo-wide schema-version search is clean, exact collection count matches CI, workflow changes are pushable with current credentials, migration-copy gate passes, and the branch contains no workflow-file churn that a restricted token will reject.
- For API-based CI diagnosis, resolve and query the full 40-character head SHA, then inspect Actions run → jobs → failed job log. Follow the log endpoint's signed redirect without forwarding the GitHub Authorization header to object storage. Short SHAs or PR merge-state labels alone are not adequate diagnosis.
- Additive compatibility helpers still require explicit tests against a synthetic prior schema; `CREATE TABLE IF NOT EXISTS` alone is not an upgrade proof.

## Daily market/FX analytics
- For confirmed-position boundaries, multi-account valuation, Decimal/SQLite pitfalls, holiday source dates, benchmark basis consistency, TWR-based risk, GET immutability, and controlled production-run sentinels, use `references/daily-market-fx-benchmark-risk-contract.md`.
