set -euo pipefail
cd /home/agent/.hermes/repos/FinanceManager
PYTHONPATH=src python - <<'PY'
import json
from decimal import Decimal
from jarvis_finance.config.settings import load_settings
from jarvis_finance.storage.database import connect
from jarvis_finance.storage.migrations import apply_migrations
from jarvis_finance.ledger.positions import calculate_positions
from jarvis_finance.dashboard import data as dashboard_data
conn=connect(load_settings().db_path); apply_migrations(conn)
rows=conn.execute("""
SELECT t.transaction_id, t.transaction_type, t.source_type, t.source_id, t.row_hash, t.instrument_id, t.account_id, t.quantity, t.quality_status, t.fx_status,
       ep.execution_plan_id, ep.review_item_id, ep.execution_status, ri.review_status
FROM transactions t
LEFT JOIN broker_import_execution_plans ep ON ep.execution_plan_id=t.source_id OR ep.transaction_id=t.transaction_id
LEFT JOIN broker_import_review_items ri ON ri.review_item_id=ep.review_item_id
WHERE t.source_type='broker_import_reviewed_snapshot' AND t.transaction_type='initial_position_snapshot'
""").fetchall()
parseable=0
for r in rows:
    Decimal(str(r['quantity'])); parseable += 1
positions=calculate_positions(conn)
position_warnings=[]
for pos in positions.positions.values():
    position_warnings.extend(pos.quality_warnings)
alerts=conn.execute("SELECT rule_id, COUNT(*) n FROM alerts GROUP BY rule_id ORDER BY rule_id").fetchall()
summary={
 'tw_initial_snapshot_transactions': len(rows),
 'qty_decimal_parseable': parseable,
 'execution_imported': sum(1 for r in rows if r['execution_status']=='imported'),
 'review_imported': sum(1 for r in rows if r['review_status']=='imported'),
 'quality_warning_or_incomplete': sum(1 for r in rows if r['quality_status'] in ('warning','incomplete')),
 'positions_calculated': len(positions.positions),
 'dashboard_positions_count': len(dashboard_data.get_positions(conn)),
 'position_warning_rules': sorted(set(position_warnings)),
 'total_return_precise_count': sum(1 for p in positions.positions.values() if p.total_return_chf is not None),
 'open_alerts_by_rule': [dict(a) for a in alerts],
 'execution_status_counts': [dict(r) for r in conn.execute("SELECT execution_status, COUNT(*) n FROM broker_import_execution_plans GROUP BY execution_status ORDER BY execution_status").fetchall()],
 'remaining_ready_planned_payloads': conn.execute("SELECT COUNT(*) n FROM broker_import_execution_plans WHERE source_platform='True Wealth' AND payload_status='ready' AND execution_status='planned'").fetchone()['n'],
 'audit_import_events': conn.execute("SELECT COUNT(*) n FROM audit_log WHERE action IN ('execute_mini_import','mark_review_item_imported')").fetchone()['n'],
 'void_audit_events': conn.execute("SELECT COUNT(*) n FROM audit_log WHERE action='void_transaction'").fetchone()['n'],
}
print(json.dumps(summary, sort_keys=True))
PY
PYTHONPATH=src python -m compileall -q src tests
PYTHONPATH=src pytest -q
rm -rf .pytest_cache src/jarvis_finance/**/__pycache__ tests/**/__pycache__
PYTHONPATH=src python -m jarvis_finance.cli.main git-safety-scan .
git status --short --branch


terminal

Output:
{"audit_import_events": 4, "dashboard_positions_count": 2, "execution_imported": 2, "execution_status_counts": [{"execution_status": "imported", "n": 2}, {"execution_status": "planned", "n": 1}], "open_alerts_by_rule": [{"n": 14, "rule_id": "crypto_price_stale"}, {"n": 2, "rule_id": "missing_fx"}, {"n": 2, "rule_id": "missing_market_price"}], "position_warning_rules": ["missing_fx", "missing_market_price"], "positions_calculated": 2, "qty_decimal_parseable": 2, "quality_warning_or_incomplete": 2, "remaining_ready_planned_payloads": 1, "review_imported": 2, "total_return_precise_count": 0, "tw_initial_snapshot_transactions": 2, "void_audit_events": 0}
........................................................................ [ 45%]
........................................................................ [ 90%]
................                                                         [100%]
160 passed in 7.41s
GIT_SAFETY_OK
## main...origin/main
 M src/jarvis_finance/ledger/cash.py
 M src/jarvis_finance/ledger/positions.py
 M src/jarvis_finance/storage/migrations.py
 M tests/unit/test_runtime_backup.py
 M tests/unit/test_schema.py
?? src/jarvis_finance/imports/execution.py
?? src/jarvis_finance/ledger/corrections.py
?? tests/unit/test_import_execution_and_corrections.py


set -euo pipefail
cd /home/agent/.hermes/repos/FinanceManager
git add src/jarvis_finance/storage/migrations.py src/jarvis_finance/ledger/positions.py src/jarvis_finance/ledger/cash.py src/jarvis_finance/imports/execution.py src/jarvis_finance/ledger/corrections.py tests/unit/test_schema.py tests/unit/test_runtime_backup.py tests/unit/test_import_execution_and_corrections.py
git commit -m "feat: harden broker mini-import corrections"
PYTHONPATH=src python -m compileall -q src tests
PYTHONPATH=src pytest -q
rm -rf .pytest_cache src/jarvis_finance/**/__pycache__ tests/**/__pycache__
PYTHONPATH=src python -m jarvis_finance.cli.main git-safety-scan .
git status --short --branch


Output:
[main 374fdd5] feat: harden broker mini-import corrections
 8 files changed, 365 insertions(+), 6 deletions(-)
 create mode 100644 src/jarvis_finance/imports/execution.py
 create mode 100644 src/jarvis_finance/ledger/corrections.py
 create mode 100644 tests/unit/test_import_execution_and_corrections.py
........................................................................ [ 45%]
........................................................................ [ 90%]
................                                                         [100%]
160 passed in 7.41s
GIT_SAFETY_OK
## main...origin/main [voraus 1]


set -euo pipefail
cd /home/agent/.hermes/repos/FinanceManager
python - <<'PY'
import re, subprocess, sys
from pathlib import Path
repo=Path('/home/agent/.hermes/repos/FinanceManager')
text=Path('/home/agent/jarvis_runtime/finance-system/secrets/Github_token_FinanceManager.csv').read_text()
m=re.search(r'(github_pat_[A-Za-z0-9_]+|ghp_[A-Za-z0-9_]+|gho_[A-Za-z0-9_]+)', text)
if not m:
    print('TOKEN_PARSE=failed'); sys.exit(12)
token=m.group(1); auth_url=f'https://{token}@github.com/Gamexgit/FinanceManager.git'
def run(args, check=True): return subprocess.run(args, cwd=repo, text=True, capture_output=True, check=check)
try:
    run(['git','fetch',auth_url,'main:refs/remotes/origin/main','--quiet'])
    local=run(['git','rev-parse','HEAD']).stdout.strip(); origin=run(['git','rev-parse','origin/main']).stdout.strip(); base=run(['git','merge-base','HEAD','origin/main']).stdout.strip()
    print('REMOTE_BEFORE='+origin[:7]); print('LOCAL_HEAD='+local[:7])
    if origin != base:
        print('REMOTE_HAS_NEW_COMMITS=yes'); sys.exit(3)
    push=run(['git','push',auth_url,'main:main'], check=False)
    if push.returncode:
        print('PUSH=failed'); print((push.stderr or push.stdout).replace(token,'[REDACTED]')[-1000:]); sys.exit(push.returncode)
    run(['git','fetch',auth_url,'main:refs/remotes/origin/main','--quiet'])
    print('PUSH=success'); print('REMOTE_AFTER='+run(['git','rev-parse','--short','origin/main']).stdout.strip())
finally:
    token=None; auth_url=None
PY
PYTHONPATH=src python -m jarvis_finance.cli.main git-safety-scan .
git status --short --branch


Output:
REMOTE_BEFORE=48562fe
LOCAL_HEAD=374fdd5
PUSH=success
REMOTE_AFTER=374fdd5
GIT_SAFETY_OK
## main...origin/main


cd /home/agent/.hermes/repos/FinanceManager && PYTHONPATH=src python - <<'PY'
import json
from jarvis_finance.config.settings import load_settings
from jarvis_finance.storage.database import connect
from jarvis_finance.storage.migrations import apply_migrations
conn=connect(load_settings().db_path); apply_migrations(conn)
print(json.dumps({
 'schema_version': conn.execute('SELECT MAX(version) v FROM schema_migrations').fetchone()['v'],
 'tw_initial_snapshots': conn.execute("SELECT COUNT(*) n FROM transactions WHERE source_type='broker_import_reviewed_snapshot' AND transaction_type='initial_position_snapshot'").fetchone()['n'],
 'remaining_ready_planned': conn.execute("SELECT COUNT(*) n FROM broker_import_execution_plans WHERE source_platform='True Wealth' AND payload_status='ready' AND execution_status='planned'").fetchone()['n'],
 'review_imported': conn.execute("SELECT COUNT(*) n FROM broker_import_review_items WHERE source_platform='True Wealth' AND review_status='imported'").fetchone()['n'],
 'positions_snapshot': conn.execute('SELECT COUNT(*) n FROM positions_snapshot').fetchone()['n'],
 'cash_balances': conn.execute('SELECT COUNT(*) n FROM cash_balances').fetchone()['n'],
 'alerts': [dict(r) for r in conn.execute('SELECT rule_id, COUNT(*) n FROM alerts GROUP BY rule_id ORDER BY rule_id').fetchall()],
}, sort_keys=True))
PY
git rev-parse --short HEAD
git status --short --branch


Output:
{"alerts": [{"n": 14, "rule_id": "crypto_price_stale"}, {"n": 2, "rule_id": "missing_fx"}, {"n": 2, "rule_id": "missing_market_price"}], "cash_balances": 0, "positions_snapshot": 0, "remaining_ready_planned": 1, "review_imported": 2, "schema_version": 8, "tw_initial_snapshots": 2}
374fdd5
## main...origin/main


todo

Compile/pytest/Git-Safety/Git Status, commit+push bei Codeänderungen


Import Regression und Position/Data Quality Check aggregiert prüfen

Safe Correction/Void Datenmodell+Service+Tests implementieren

Backup/Restore Regression auf Test-DB prüfen

Optional zweiten Mini-Import genau 1 Item nach Regression durchführen


Phase B6c ist abgeschlossen, Sir.

## Kurzfazit

- Regression Check bestanden: **ja**
- Re-Import-Schutz bestätigt: **ja**
- Safe Correction / Void implementiert: **ja**
- Backup/Restore Regression bestanden: **ja**
- Zweiter Mini-Import durchgeführt: **ja**
- Produktive True-Wealth Initial-Snapshot-Transaktionen nachher: **2**
- Remaining ready planned True-Wealth Items: **1**
- Direkte `positions_snapshot` Writes: **0**
- Cash-Snapshots: **0**
- Tests: **160 passed**
- Git-Safety: **GIT_SAFETY_OK**
- Commit: `374fdd5`
- Push Status: **success**
- Git Status: **clean**, `main...origin/main`

Keine echten Mengen, Werte, Kontostände oder sensitiven Dateiinhalte wurden ausgegeben.

---

## 1. Import Regression Check

Geprüft für den bestehenden B6b Mini-Import:

- genau 1 produktive Transaktion aus B6b initial vorhanden: **ja**
- `transaction_type = initial_position_snapshot`: **ja**
- `source_type = broker_import_reviewed_snapshot`: **ja**
- linked `execution_plan_id` vorhanden: **ja**
- linked `review_item_id` vorhanden: **ja**
- `instrument_id` vorhanden: **ja**
- `account_id` vorhanden: **ja**
- `quantity` vorhanden: **ja**
- `quantity` Decimal-parsebar: **ja**
- keine Float-Konvertierung: **ja**
- `quality_status` warning/incomplete bei fehlender FX/Cost Basis: **ja**
- Audit-Log vorhanden: **ja**
- Execution Plan Status: **imported**
- Review Item Status: **imported**

Re-Import-Schutz:

- dieselbe `execution_plan_id` wird blockiert: **ja**
- dieselbe `row_hash` wird blockiert: **ja**
- zusätzliche Tests dafür ergänzt: **ja**

---

## 2. Position Calculation Check

Geprüft:

- Position kann aus Ledger berechnet werden: **ja**
- berechnete Position erscheint auf Portfolio/Equity-Seite: **ja**
- Dashboard/Equity erkennt Ledger-Positionen: **ja**
- keine direkte Snapshot-Wahrheit geschrieben: **ja**
- Total Return wird bei fehlender FX/Market Data nicht präzise behauptet: **ja**

Data Quality Flags nach B6c:

- `missing_fx`: **2**
- `missing_market_price`: **2**
- `cost_basis_uncertain`: im Execution-Plan/Import-Payload geführt
- `snapshot_only`: im Execution-Plan/Import-Payload geführt
- alte Crypto-Preis-Warnings bestehen weiterhin: **14 stale crypto price Alerts**

Wichtig: Die Ledger-Positionen existieren, aber Performance/Total Return bleibt bewusst unvollständig. Kein finanzmathematisches Wunschdenken, how disappointing.

---

## 3. Safe Correction / Reversal

Implementiert:

### `void_transaction`

- markiert Transaktion als voided/storniert
- löscht **nicht** physisch
- erfordert Notiz
- schreibt Audit-Log
- erzeugt Data-Quality Alert `voided_transaction`
- Position-/Cash-Berechnung ignoriert `is_voided = 1`

Neue Felder in `transactions`:

- `is_voided`
- `voided_at`
- `void_reason`
- `voided_by`
- `correction_of_transaction_id`
- `correction_reason`

### `correction_transaction`

Vorbereitet über Audit-Link:

- neue Korrekturtransaktion bleibt separat
- alte Transaktion bleibt historisch sichtbar
- neue Transaktion kann mit alter Transaktion verknüpft werden
- Audit-Log Pflicht
- Notiz Pflicht

Physisches Löschen produktiver Transaktionen: **nicht erlaubt / nicht implementiert**

Schema-Version danach: **8**

---

## 4. Backup/Restore Regression

Durchgeführt:

- Backup nach Mini-Import erzeugt: **ja**
- `verify-backup` funktioniert: **ja**
- Checksum OK: **ja**
- Restore auf separate Test-DB funktioniert: **ja**
- produktive DB wurde dabei nicht überschrieben: **ja**
- Git-Safety danach OK: **ja**

Zusätzlich Test ergänzt:

- Restore auf separate Test-DB verändert produktive DB nicht.

---

## 5. Zweiter Mini-Import

Nach erfolgreicher Regression wurde genau **1** weiteres remaining True-Wealth-ready Item importiert.

Bedingungen erfüllt:

- vorher Backup: **ja**
- Backup verifiziert: **ja**
- genau 1 Position importiert: **ja**
- keine Massenübernahme: **ja**
- Audit vorhanden: **ja**
- Execution Plan vorhanden: **ja**
- anderes ready Item unverändert: **ja**
- keine echten Werte/Mengen im Chat: **ja**
- Git-Safety danach OK: **ja**

Status nach zweitem Mini-Import:

- produktive True-Wealth Initial-Snapshot-Transaktionen: **2**
- Execution Plans:
  - imported: **2**
  - planned/ready: **1**
- Review Items:
  - imported: **2**
  - remaining ready/resolved: **1**
- `positions_snapshot`: **0**
- `cash_balances`: **0**

---

## 6. Tests ergänzt

Neu/erweitert getestet:

- Re-Import derselben `execution_plan_id` wird blockiert
- Re-Import derselben `row_hash` wird blockiert
- `void_transaction` braucht Notiz
- `void_transaction` schreibt Audit
- voided transaction wird nicht als aktive Position gezählt
- correction transaction erzeugt Audit-Link
- Initial Snapshot mit missing FX bleibt warning/incomplete
- Portfolio-Berechnung zeigt keine Scheingenauigkeit / kein Fake Total Return
- Backup nach Import / Restore auf Test-DB
- Schema enthält Void-/Correction-Felder

Teststand:

- vorher: **155**
- nachher: **160**
- Ergebnis: **160 passed**

---

## Codeänderungen

Geändert / neu:

- `src/jarvis_finance/storage/migrations.py`
  - Migration `008_transaction_void_corrections`
- `src/jarvis_finance/ledger/positions.py`
  - voided transactions werden ignoriert
- `src/jarvis_finance/ledger/cash.py`
  - voided transactions werden ignoriert
- `src/jarvis_finance/imports/execution.py`
  - kontrollierte Execution-Plan-Import-Funktion
  - Re-Import-Schutz
- `src/jarvis_finance/ledger/corrections.py`
  - `void_transaction`
  - `record_correction_audit`
- `tests/unit/test_import_execution_and_corrections.py`
- `tests/unit/test_runtime_backup.py`
- `tests/unit/test_schema.py`

Commit:

- `374fdd5` — `feat: harden broker mini-import corrections`

Push:

- **success**
- Remote HEAD: `374fdd5`

---

## Abschlussstatus

- Compile: **OK**
- pytest: **160 passed**
- Git-Safety: **GIT_SAFETY_OK**
- Git Status: **clean**
- Branch: `main...origin/main`

## Nächste Empfehlung

Noch **kein Massenimport**.

Nächster sinnvoller Schritt:

1. Das letzte remaining True-Wealth-ready Item als **dritten Einzel-Mini-Import** durchführen.
2. Danach eine kleine Review-Phase:
   - importierte 3 Ledger-Positionen aggregiert prüfen
   - Data Quality Center konsolidieren
   - Manual Review Queue Status finalisieren
3. Erst danach entscheiden, ob weitere True-Wealth-Items gemappt/importiert werden oder ob zuerst FX/Cost-Basis-Modell verbessert wird.

Kurz: B6c hat den Airbag eingebaut, bevor wir schneller fahren. Sehr vernünftig.