Skip to content

refactor: decompose append.py and effects.py by semantic concern (BTND-07-004) - #2282

Open
sei-ahouseholder wants to merge 2 commits into
mainfrom
plan/2269-btnd07-decomposition-churn
Open

refactor: decompose append.py and effects.py by semantic concern (BTND-07-004)#2282
sei-ahouseholder wants to merge 2 commits into
mainfrom
plan/2269-btnd07-decomposition-churn

Conversation

@sei-ahouseholder

Copy link
Copy Markdown
Contributor

Summary

  • append.py (499 lines, 7 classes) → append/ subpackage: conditions.py (4 guard nodes + _has_status_in_participant helper), actions.py (3 mutating nodes), __init__.py (re-exports all 7 public names)
  • effects.py (495 lines, 4 classes) → 4 per-class files (participant_status_effect.py, note_effect.py, invite_accept_effect.py, close_case_effect.py) + _helpers.py (_LedgerEffectNode base + _extract_id_from_field) extracting shared DRY pattern
  • All importers updated in-place; no backward-compatibility shims
  • Test structure mirrored; adds TestCheckParticipantRMNotClosedNode (previously untested) and tests for the 3 previously untested effects.py nodes

What changed

Before After
status/nodes/append.py (499 lines) status/nodes/append/conditions.py + actions.py + __init__.py
sync/nodes/effects.py (495 lines) _helpers.py + 4 per-class files
test_append.py append/conftest.py + test_conditions.py + test_actions.py
test_effects.py 4 per-class test files

DRY extractions

  • _LedgerEffectNode base class extracted from the 4 effects.py nodes — all had identical setup() (register activity blackboard key) and _require_log_entry call pattern
  • _has_status_in_participant() helper in append/conditions.py
  • _extract_id_from_field() moved from effects.py to _helpers.py

Out of scope — 5 other near-limit modules

replay.py (498), suggest_actor/emit.py (498), deploy_fix.py (497), embargo/nodes/lifecycle.py (494), conditions.py (488).

Test plan

  • uv run pytest test/core/behaviors/status/nodes/append/ — 18 passed
  • uv run pytest test/core/behaviors/sync/nodes/test_*_effect.py — 13 passed
  • uv run pytest test/core/ test/wire/ test/adapters/ — all passed
  • uv run flake8 — clean
  • uv run pyright on all new/modified files — 0 errors

Closes #2269

🤖 Generated with Claude Code

…D-07-004)

Resolves CONCERN-2269. Both modules were at the 500-line ceiling, causing
any unrelated edit to require an in-band decomposition.

## status/nodes: append.py → append/ subpackage

- Delete append.py (499 lines, 7 classes)
- Create append/__init__.py — re-exports all 7 public names
- Create append/conditions.py — 4 guard nodes + _has_status_in_participant helper
  (SkipIfIdempotentNode, CheckStatusNotAlreadyAppendedNode,
   ValidateRMTransitionNode, CheckParticipantRMNotClosedNode)
- Create append/actions.py — 3 mutating action nodes
  (LoadParticipantNode, ResolveAndPersistStatusObjectNode,
   AppendStatusAndSaveParticipantNode)
- Mirror test structure: test_append.py → append/conftest.py +
  test_conditions.py + test_actions.py; add TestCheckParticipantRMNotClosedNode
  (was missing from the original test file)

## sync/nodes: effects.py → per-class files + _helpers.py

- Delete effects.py (495 lines, 4 classes + helper)
- Create _helpers.py — _extract_id_from_field + _LedgerEffectNode base class
  (DRY: all 4 effect nodes had identical setup() + _require_log_entry pattern)
- Create participant_status_effect.py, note_effect.py,
  invite_accept_effect.py, close_case_effect.py — one file per class
- Update offer_report_effect.py, ownership_effects.py — import
  _extract_id_from_field from _helpers instead of deleted effects.py
- Update sync/nodes/__init__.py — 4 separate per-class imports
- Mirror test structure: test_effects.py → test_participant_status_effect.py +
  test_note_effect.py + test_invite_accept_effect.py + test_close_case_effect.py;
  adds tests for the 3 previously untested effect nodes
- Update notes/structured-logging.md — reference updated to close_case_effect.py

Note: 5 other modules are approaching the 500-line ceiling
(replay.py 498, suggest_actor/emit.py 498, deploy_fix.py 497,
embargo/nodes/lifecycle.py 494, conditions.py 488) — tracked as future work.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…position eliminates BTND-07-004 churn

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

@sei-ahouseholder sei-ahouseholder left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Triage: #2282 — refactor: decompose append.py and effects.py by semantic concern (BTND-07-004)

Linked issues: #2269 (BTND-07-004's 500-line ceiling is forcing unrelated decomposition churn — append.py and effects.py both at the limit)
Changed files: 22 files — core/behaviors/status, core/behaviors/sync
CI status: ⚠️ unit tests ✅ passing · demo integration ❌ pre-existing failures on main (engage_case event type — unrelated to this PR)
Merge state: ❌ CONFLICTING (DIRTY)
Base branch: main
Needs integration tests: yes


Findings

# Phase Severity Description Outcome
phase12-merge-conflict-0 merge-state ❌ FAIL Branch has conflicts with main — cannot merge until resolved fix-now
phase3-closes-not-at-top-0 pr-body-format ⚠️ IMPROVE Closes #2269 is at the bottom of the PR body; must be the first line before any ## header (pr-body-guide.md) fix-now
phase9-stale-docstring-ref-0 notes-docs-currency ⚠️ IMPROVE leave.py:22 docstring still references deleted sync.nodes.effects.ApplyCloseCaseFromLedgerNode; correct path is sync.nodes.close_case_effect.ApplyCloseCaseFromLedgerNode fix-now

Total: 1 FAIL · 2 IMPROVE · 0 NEW-ISSUE


Notes

  • BTND-07 structure test: 93/93 passed. All new modules are ≤ 329 lines. ✓
  • __init__.py re-exports all 7 public names from append/ subpackage. ✓
  • sync/nodes/__init__.py re-exports all effect node names from per-class files. ✓
  • No backward-compatibility shims (per doctrine). ✓
  • notes/structured-logging.md updated to reference close_case_effect.py. ✓
  • No ADR warranted — pure structural decomposition, no architectural change. ✓
  • Demo CI failures (engage_case event type missing in fvcv-handoff, fcvcv, fcv-reject, fv) are pre-existing on all recent main runs and are unrelated to this PR.

Triage artifact: .claude/pr-2282-triage.json
Next step: /pr-execute will resolve the merge conflict, move the Closes line, and fix the stale docstring.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BTND-07-004's 500-line ceiling is forcing unrelated decomposition churn — append.py and effects.py both at the limit

2 participants