Skip to content

feat(reconciliation): add evidence-derived run lifecycle command - #43

Draft
seonghobae wants to merge 111 commits into
fix/reconciliation-multi-match-conservationfrom
feat/reconciliation-run-lifecycle-transition
Draft

feat(reconciliation): add evidence-derived run lifecycle command#43
seonghobae wants to merge 111 commits into
fix/reconciliation-multi-match-conservationfrom
feat/reconciliation-run-lifecycle-transition

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Buyer outcome

Add the supported command that turns one reviewed reconciliation run into immutable reconciled evidence. It is tenant-scoped and idempotent, derives eligibility and exact book-to-bank evidence from PostgreSQL-owned facts, persists one transition command and outbox event atomically, and cannot post/reverse journals, close periods, select chart accounts, or alter accounting policy.

Exact current state — 2026-09-03

  • lifecycle head: aced5dd96eb5b6ee055073be1def7c9a0c00a542;
  • exact parent/base: #29@f58fb3d468088c5bc0fb5a6a2c366b019dd23387;
  • current maker-checker child: #47@7fab06bc6396ae756e7621f7a0c21c535d71a191;
  • child exact-head Accounting Foundation run: 33747860737, queued/non-passing;
  • state: open / Draft / mergeable / not merge-ready;
  • stack order: #29 -> #43 -> #47.

This branch adopted the protected-base change non-force and contains current parent ancestry. Predecessor checks/reviews are non-transferable.

Lifecycle authority

#43 owns shared reconciliation command identity, immutable reconciliation_run_transition_command, database-enforced reconciled transition, exact replay from retained transition provenance, and atomic reconciliation_run_reconciled outbox evidence. Its database snapshot authority reconstructs run/opening-command scope, retained statement balances/entries, assigned cash-book journal population, approved allocations, reviewed match/approval state and exception state; independently recomputes source capacities and exact book-to-bank arithmetic; and replaces caller-selected transition snapshot/population identities before transition hashing.

Child #47 composes maker-checker exception-resolution authority without replacing this monetary authority. Current #47 owns a test-first P1 investigation of the raw database lifecycle path: a backend can have a REPEATABLE READ snapshot established before the session-lock grant even though migration 0027 later proves both advisory locks are held. Commit be68779... contains the realistic PostgreSQL stale-pre-lock snapshot RED; exact child 7fab06bc... adds only test cleanup so an aborted RED transaction cannot mask the intended authority error while releasing its session lock. No production snapshot-freshness fix is claimed until this exact PostgreSQL RED executes and fails for the intended boundary.

The supported Python lifecycle path already takes the tenant/run session advisory lock, commits, then opens a fresh REPEATABLE READ transaction and reacquires the transaction lock. Any child repair must preserve that ordering and make the direct database authority boundary equally fail-closed rather than weakening database-owned snapshot/bridge controls.

External boundary

Billing and settlement/payment systems remain foreign evidence producers and cannot write AIS tables or claim statutory posting. Keyverse remains behind a provider-neutral identity/PDP boundary. Context Graph Contracts, Enterprise Architecture Core, contextual-orchestrator and other CWL foundations remain sibling authorities; mutable sibling PR heads, direct source imports and cross-service SQL are not runtime authority.

Merge boundary

Keep Draft. #47 must first observe and repair its current PostgreSQL RED, then pass one unchanged exact-head PostgreSQL/100%-coverage/repository-docstring/SAST/security/dependency/package/SBOM/provenance/reviewer/ruleset evidence set and integrate normally into #43. The changed #43 must then reacquire every applicable gate before integrating into #29. Do not self-approve, bypass, force-push, destructively rebase, transfer predecessor evidence, tag or release while any gate is non-passing.

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

조정 실행을 reconciled 상태로 전환하는 명명된 lifecycle command와 불변 증거를 추가했습니다. 데이터베이스가 상태 전이, 증거 동결, aggregate membership, reviewed-only supersession을 강제합니다. 관련 Python API, 마이그레이션, PostgreSQL 테스트, 문서, CI 러너 설정을 갱신했습니다.

Changes

조정 실행 라이프사이클

Layer / File(s) Summary
라이프사이클 데이터베이스 권위
database/migrations/0019_reconciliation_run_command_evidence.sql, database/migrations/0020_reconciliation_run_completion_evidence.sql, src/accounting_information_platform/migration_install.py
전환 명령 테이블과 트리거를 추가했습니다. run은 evaluating에서 시작하고 명명된 command로만 reconciled 상태가 됩니다. 전환 증거와 관련 evidence의 변경을 차단합니다. 기존 완료 마이그레이션과 별도 설치 경로를 제거했습니다.
라이프사이클 서비스와 공개 API
src/accounting_information_platform/reconciliation_lifecycle.py, src/accounting_information_platform/__init__.py
reconcile_reconciliation_run을 추가했습니다. 입력 검증, REPEATABLE READ, advisory lock, 멱등성 재생, review 상태 검증, bridge 해시, provenance 저장, 상태 변경, outbox 기록을 수행합니다. 기존 completion API를 공개 export에서 제거했습니다.
라이프사이클 검증
tests/test_reconciliation_lifecycle.py, tests/test_reconciliation_lifecycle_postgres.py, tests/test_reconciliation_lifecycle_aggregate_membership_postgres.py, tests/test_reconciliation_lifecycle_status_authority_postgres.py, tests/test_reconciliation_lifecycle_replay_contract.py, tests/test_reconciliation_lifecycle_currency_scope.py, tests/test_reconciliation_lifecycle_edge_cases.py, tests/test_reconciliation_lifecycle_initial_state_contract.py, tests/test_reconciliation_close_package_*.py, tests/test_reconciliation_run_api.py
정상 전환, 멱등성, provenance 재생, 상태 권위, 증거 동결, cross-run 재부모링 거부, 통화 범위, 입력 오류와 close-package 상태 조건을 검증합니다.
라이프사이클 계약 문서화
docs/adr/0060-reconciliation-run-lifecycle-authority.md, docs/adr/0061-reconciliation-evidence-aggregate-membership.md, docs/doctoring/2026-09-01-*, docs/product-technical-gap-baseline.md, tests/test_reconciliation_multi_match_documentation_contract.py
라이프사이클 권위, 동시성, aggregate membership, provenance, 증거 기준, 통합 조건을 문서화하고 문서 계약 테스트를 갱신했습니다.

매치 supersession 권한

Layer / File(s) Summary
reviewed-only supersession 가드
database/migrations/0016_reconciliation_approval_evidence.sql, database/migrations/0017_reconciliation_approval_lock_order.sql, tests/test_reconciliation_supersede_authority.py, docs/doctoring/2026-09-02-reconciliation-supersession-*.md
superseded 상태를 reviewed predecessor가 있는 UPDATE로 제한했습니다. 직접 INSERT와 proposed→superseded UPDATE를 PostgreSQL에서 거부합니다.

CI 실행 환경

Layer / File(s) Summary
CI 러너 이미지 고정
.github/workflows/ci.yml, tests/test_ci_contract.py
다섯 개 CI 작업의 runner를 ubuntu-24.04로 변경했습니다. workflow에 ubuntu-latest가 없고 모든 runs-on 값이 ubuntu-24.04인지 검증합니다.

Estimated code review effort: 5 (Critical) | ~120 minutes

Merge Risk: 🟡 Moderate · up to ab48a

This change can permanently mark a reviewed reconciliation run as reconciled and publish that outcome. The command accepts actor identity without demonstrated binding to the authenticated caller, and the production database-role boundary is not established, creating a risk of misleading provenance or broader-than-intended tenant and evidence access; the transition hash also depends on a database trigger without validating the returned value. Merge should wait for these authority and integrity safeguards or explicit owner acceptance.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant reconcile_reconciliation_run
  participant PostgreSQL
  participant Outbox
  Caller->>reconcile_reconciliation_run: reconcile command 제출
  reconcile_reconciliation_run->>PostgreSQL: REPEATABLE READ 및 advisory lock 획득
  reconcile_reconciliation_run->>PostgreSQL: review evidence와 bridge projection 검증
  reconcile_reconciliation_run->>PostgreSQL: transition command 저장
  PostgreSQL->>PostgreSQL: reconciled 상태 전이와 evidence freeze 검증
  reconcile_reconciliation_run->>Outbox: reconciliation_run_reconciled 기록
  reconcile_reconciliation_run-->>Caller: persisted receipt 반환
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 82.98% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 94 functions across 20 files. (11 skipped: …
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 증거 기반 reconciliation run lifecycle command 추가라는 주요 변경을 정확히 요약합니다. 변경 범위와 직접 관련되며 간결하고 명확합니다.
Full details: Docstring Coverage

Explanation

Docstring coverage is 82.98% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 94 functions across 20 files. (11 skipped: 11 unsupported.)

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/reconciliation-run-lifecycle-transition

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Contributor Author

@codex review

Re-review exact head 48a1857449303e754a928b98828d114ce7ca1669 against exact parent 843f0e3bbe10f3bb989292b5bdf9eeee35b0316d. The new RED→GREEN boundary is exception-resolution authority: a privileged raw open -> resolved rewrite must not authorize reconciliation, and PostgreSQL now rejects direct transition-command insertion whenever any exception row exists until a named durable resolution command is implemented. Verify the database trigger, public fail-closed path, real PostgreSQL regression, aggregate-membership contract, and any current-head regression; do not transfer predecessor findings.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Please review exact head 48a1857449303e754a928b98828d114ce7ca1669 against parent 843f0e3bbe10f3bb989292b5bdf9eeee35b0316d. Focus on the new database-owned fail-closed exception-resolution boundary (reconciliation_exception_resolution_command_required) and the real PostgreSQL direct-transition regression. Treat earlier review results as predecessor evidence.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

head='48a1857449303e754a928b98828d114ce7ca1669'
parent='843f0e3bbe10f3bb989292b5bdf9eeee35b0316d'

git cat-file -e "${head}^{commit}"
git cat-file -e "${parent}^{commit}"

echo '== EXACT COMMITS AND RELATIONSHIP =='
git show -s --format='head=%H%nparents=%P%nsubject=%s' "$head"
git show -s --format='parent=%H%nsubject=%s' "$parent"
git merge-base --is-ancestor "$parent" "$head" && echo 'parent-is-ancestor=yes' || echo 'parent-is-ancestor=no'

echo '== CHANGED PATHS =='
git diff --name-status "$parent" "$head"

echo '== CURRENT-HEAD CANDIDATE PATHS =='
git ls-tree -r --name-only "$head" | rg \
  '^(database/migrations/[0-9]{4}_.*reconciliation.*[.]sql|src/accounting_information_platform/reconciliation_(lifecycle|run)[.]py|tests/.*reconciliation.*(exception|lifecycle|postgres|authority).*[.]py)$' \
  | sort

echo '== EXCEPTION-RESOLUTION LANDMARKS =='
git grep -n -I -E \
  'reconciliation_exception_resolution_command_required|reconciliation_exception|resolution_status_code|transition_command|reconcile_reconciliation_run|outbox' \
  "$head" -- database/migrations src tests || true

echo '== EXACT DIFF: RELEVANT AREAS =='
git diff --unified=45 "$parent" "$head" -- \
  database/migrations \
  src/accounting_information_platform/reconciliation_lifecycle.py \
  src/accounting_information_platform/reconciliation_run.py \
  tests \
  | rg -n -C 12 \
  'reconciliation_exception_resolution_command_required|reconciliation_exception|resolution_status_code|transition_command|reconcile_reconciliation_run|outbox|postgres' || true

Length of output: 158099


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head='48a1857449303e754a928b98828d114ce7ca1669'

show() {
  local path="$1" start="$2" end="$3"
  printf '\n===== %s: Lines %s-%s =====\n' "$path" "$start" "$end"
  git show "${head}:${path}" | nl -ba | sed -n "${start},${end}p"
}

echo '== MIGRATION 0019: IDENTITY, AUTHORITY, HASH, AND STATUS TRIGGERS =='
show database/migrations/0019_reconciliation_run_command_evidence.sql 300 680

echo '== MIGRATION 0019: EVIDENCE-MUTATION GUARD =='
show database/migrations/0019_reconciliation_run_command_evidence.sql 680 790

echo '== APPLICATION LIFECYCLE: REVIEW-STATE VALIDATION AND WRITE ORDER =='
show src/accounting_information_platform/reconciliation_lifecycle.py 35 250
show src/accounting_information_platform/reconciliation_lifecycle.py 285 365

echo '== POSTGRESQL DIRECT-TRANSITION REGRESSION: COMPLETE TEST CLASS =='
git show "${head}:tests/test_reconciliation_lifecycle_aggregate_membership_postgres.py" |
  nl -ba |
  sed -n '1,245p'

echo '== MIGRATION DISCOVERY AND 0019 INSTALLATION =='
ast-grep outline src/accounting_information_platform/persistence.py \
  --items all --type function --match 'migration|foundation|schema' --view expanded
rg -n -C 8 \
  '0019_reconciliation_run_command_evidence|migration.*path|glob\(|iterdir\(|sorted\(|apply_foundation' \
  src/accounting_information_platform/persistence.py \
  src/accounting_information_platform/migration_install.py \
  tests/test_foundation_install_manifest_contract.py || true

Length of output: 1986


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head='48a1857449303e754a928b98828d114ce7ca1669'

show() {
  local path="$1" start="$2" end="$3"
  printf '\n===== %s: Lines %s-%s =====\n' "$path" "$start" "$end"
  git show "${head}:${path}" |
    awk -v start="$start" -v end="$end" \
      'NR >= start && NR <= end { printf "%6d  %s\n", NR, $0 }'
}

echo '== MIGRATION 0019: IDENTITY, AUTHORITY, HASH, AND STATUS TRIGGERS =='
show database/migrations/0019_reconciliation_run_command_evidence.sql 300 680

echo '== MIGRATION 0019: EVIDENCE-MUTATION GUARD =='
show database/migrations/0019_reconciliation_run_command_evidence.sql 680 790

echo '== APPLICATION LIFECYCLE: REVIEW-STATE VALIDATION AND WRITE ORDER =='
show src/accounting_information_platform/reconciliation_lifecycle.py 35 250
show src/accounting_information_platform/reconciliation_lifecycle.py 285 365

echo '== POSTGRESQL DIRECT-TRANSITION REGRESSION: COMPLETE TEST CLASS =='
git show "${head}:tests/test_reconciliation_lifecycle_aggregate_membership_postgres.py" |
  awk '{ printf "%6d  %s\n", NR, $0 }' |
  sed -n '1,245p'

echo '== MIGRATION DISCOVERY AND 0019 INSTALLATION =='
ast-grep outline src/accounting_information_platform/persistence.py \
  --items all --type function --match 'migration|foundation|schema' --view expanded || true
rg -n -C 8 \
  '0019_reconciliation_run_command_evidence|migration.*path|glob\(|iterdir\(|sorted\(|apply_foundation' \
  src/accounting_information_platform/persistence.py \
  src/accounting_information_platform/migration_install.py \
  tests/test_foundation_install_manifest_contract.py || true

Length of output: 99842


@seonghobae I found no actionable issue in the requested scope on exact head 48a1857449303e754a928b98828d114ce7ca1669.

  • Exact parent 843f0e3bbe10f3bb989292b5bdf9eeee35b0316d is an ancestor of the reviewed head.
  • Migration 0019 rejects transition-command insertion when any exception row exists for the run.
  • The database raises reconciliation_exception_resolution_command_required with SQLSTATE 23514.
  • This rule is fail-closed. A raw open to resolved or superseded rewrite cannot authorize reconciliation.
  • reconcile_reconciliation_run() also rejects every exception state before it builds the bridge, persists a transition command, updates the run status, or writes the outbox event.
  • The database trigger remains authoritative for direct SQL. The application validation provides the earlier buyer-actionable failure.
  • tests/test_reconciliation_lifecycle_aggregate_membership_postgres.py performs the raw status rewrite, verifies direct transition-command rejection by the database marker, and verifies rejection through the supported lifecycle command.
  • The canonical migration loader requires and applies migration 0019.

I used the existing exception-resolution authority learning during this review.

I did not execute repository tests in this sandbox. Fresh exact-head PostgreSQL and CI evidence is still required before merge readiness.


🧠 Learnings used
Learnt from: seonghobae
URL: https://github.com/ContextualWisdomLab/accounting-information-platform/pull/43

Timestamp: 2026-09-01T22:11:29.411Z
Learning: For PostgreSQL reconciliation lifecycle authority, `accounting_core.reconciliation_exception.resolution_status_code` must not change from `open` to `resolved` or `superseded` through raw SQL without durable, database-validated resolution evidence. `reconcile_reconciliation_run()` must validate that evidence rather than only reject exceptions with `resolution_status_code = 'open'`. This invariant is independent of deferred authenticated-principal and database-capability ownership paths.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

Child-state correction: current maker-checker child is exact #47@d50d9c1c10696db66a1261922dcb804a9f76d2a2 (tree 9e51ca9a3d7bac7479538b02f814a3ac86a74dd6). Exact Accounting Foundation 33576063371 and exact SAST/security/dependency checks are queued/non-passing. Besides the coherent-snapshot repair already tracked here, #47 now makes exception-resolution recorded_at database-owned in migration 0020 and rejects effective_at > recorded_at; real-PostgreSQL coverage includes both the public future-effective command and a direct-SQL caller attempting to forge future system time. Keep this parent unchanged until #47 has exact-head GREEN plus qualifying independent approval; after child integration all #43 evidence must be reacquired on the changed head.

@seonghobae seonghobae added the enhancement New feature or request label Sep 2, 2026 — with ChatGPT Codex Connector

Copy link
Copy Markdown
Contributor Author

Migration-sequence repair finding from the Period Close child review

Fresh stack inspection found that this PR introduces database/migrations/0019_reconciliation_run_database_snapshot_authority.sql while the parent history already contains 0019_reconciliation_run_command_evidence.sql. Both files are present on #43@aced5dd96eb5b6ee055073be1def7c9a0c00a542, and this PR's canonical installer applies the database-snapshot authority after the existing command-evidence migration. The two logical forward steps therefore have the same numeric migration prefix.

Treat this as a foundation prerequisite, not a close reason. Before #43 integrates, assign one unique monotonically ordered migration sequence to the #43-owned additions and update migration_install.py, migration-order/static/real-PostgreSQL tests, ADR/doctoring and operator/recovery evidence together. Because #47 and #53 currently add later unreleased migrations through 0034, repair the sequence at the canonical owner first, then non-force restack descendants and adapt their numbers/references. Do not rewrite protected/released history, force-push, destructively rebase, or make descendants invent independent numbering.

The duplicate is not merely cosmetic: filenames are operational migration identity in the checked-in chain, and downstream #52 already treats its own colliding reporting number as provisional pending reconciliation-stack integration. No current migration in this stack is an immutable AIP release, so the safe path remains owner repair -> descendant restack -> exact-head clean-install/upgrade/rollback evidence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

1 participant