Skip to content

refactor(sdlc): extract RDLC commons, reparent AuthorityCase#67

Open
ryanklee wants to merge 1 commit into
mainfrom
agy/commons-extraction-20260615
Open

refactor(sdlc): extract RDLC commons, reparent AuthorityCase#67
ryanklee wants to merge 1 commit into
mainfrom
agy/commons-extraction-20260615

Conversation

@ryanklee

@ryanklee ryanklee commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Extracts risk_tier and evidence_ledger from sdlc to commons as per W2 spec. Leaves temporary shims in sdlc/ for backward compatibility. Reparents AuthorityCase to BaseGovernanceCase to remove duplicate fields and YAML parsing logic. Repoints rdlc modules (research_case.py, research_ledger.py) to use commons directly. Tightens the import-graph lint to ensure rdlc never runtime-imports sdlc. All tests pass (147 passed, 2 skipped).

Summary by CodeRabbit

Release Notes

  • New Features

    • Evidence ledger system for recording case stage transitions with audit trails and timestamps
    • Risk tier classification for case severity assessment (T0–T3 levels)
  • Refactor

    • Reorganized case handling infrastructure and classification logic across modules for better separation of concerns

Extract risk_tier and evidence_ledger from sdlc to commons as per W2 spec. Leave temporary shims in sdlc/ for backward compatibility. Reparent AuthorityCase to BaseGovernanceCase to remove duplicate fields and YAML parsing logic. Repoint rdlc modules (research_case.py, research_ledger.py) to use commons directly. Tighten the import-graph lint to ensure rdlc never runtime-imports sdlc. All tests pass (147 passed, 2 skipped).
@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.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

RiskTier and the evidence ledger implementation are moved from sdlc/ into new commons/ modules. The sdlc/risk_tier.py and sdlc/evidence_ledger.py files become thin re-export shims. AuthorityCase is refactored to inherit from BaseGovernanceCase with YAML parsing removed. rdlc/ modules switch to importing directly from commons/, and the CI import-graph test now asserts zero sdlc imports from rdlc/.

Changes

Promote shared primitives to commons and enforce clean import graph

Layer / File(s) Summary
New canonical commons implementations: RiskTier and EvidenceEntry
commons/risk_tier.py, commons/evidence_ledger.py
RiskTier IntEnum with four tiers, from_label(), and predicate methods (requires_six_lane_review, requires_axiom_scan). EvidenceEntry Pydantic model plus append_entry, read_entries, and record_transition JSONL helpers are defined here as the authoritative implementations.
Convert sdlc/ files to re-export shims
sdlc/risk_tier.py, sdlc/evidence_ledger.py
Both files drop their own implementations and each becomes a three-line shim that imports from commons and re-exports via __all__, preserving backward-compatible import paths for existing sdlc consumers.
AuthorityCase inherits from BaseGovernanceCase, YAML parsing removed
sdlc/authority_case.py
Import block removes BaseModel, datetime, Any, and YAML/frontmatter dependencies; adds BaseGovernanceCase. Class declaration changes to AuthorityCase(BaseGovernanceCase). from_yaml, from_file, and _extract_frontmatter are deleted from this module.
rdlc modules redirected to commons
rdlc/research_case.py, rdlc/research_ledger.py
RiskTier import switches from sdlc.risk_tier to commons.risk_tier; evidence ledger imports switch from sdlc.evidence_ledger to commons.evidence_ledger, completing removal of all rdlc runtime dependencies on sdlc.
CI import-graph invariant tightened; test suite updated
tests/rdlc/test_import_graph.py, tests/sdlc/test_authority_case.py
test_rdlc_runtime_sdlc_imports_are_only_sanctioned_primitives replaced by test_rdlc_does_not_import_sdlc() asserting zero sdlc imports. test_authority_case.py drops _extract_frontmatter import and its two tests; minor formatting changes to remaining tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • ryanklee/hapax-constitution#60: Directly related — introduces the same EvidenceEntry / evidence ledger and RiskTier APIs that this PR promotes from sdlc/ into commons/ and converts to shims.

Poem

🐰 Hop hop, the commons grow wide,
No longer in sdlc shall these structs hide!
RiskTier and EvidenceEntry now roam free,
Shims keep old imports from breaking, you see.
The import graph tightens, the tests all agree —
rdlc and sdlc? Strangers they'll be! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.77% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main refactoring work: extracting commons modules and reparenting AuthorityCase to a base class, matching the core changes shown in the summary.
Description check ✅ Passed The PR description adequately covers the main objectives, changes made, and test results, but lacks explicit testing details beyond the test count.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agy/commons-extraction-20260615

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 and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
rdlc/research_ledger.py (1)

16-21: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update stale interim-import documentation after ledger migration.

The import now correctly targets commons.evidence_ledger, but the module docstring still describes the ledger as living in sdlc/ pending extraction. Please align the text with the current architecture to avoid confusion.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rdlc/research_ledger.py` around lines 16 - 21, The module docstring in
rdlc/research_ledger.py still references the old location of the evidence ledger
in sdlc/ or describes it as pending extraction, but the imports now correctly
target commons.evidence_ledger. Update the module-level docstring at the top of
the file to accurately reflect the current architecture and remove outdated
references to the previous sdlc/ location or extraction status, ensuring the
documentation aligns with the actual import structure that now pulls from
commons.evidence_ledger.
🧹 Nitpick comments (2)
commons/evidence_ledger.py (1)

57-63: ⚡ Quick win

Stream ledger reads instead of loading the entire file into memory.

This path scales better for large JSONL ledgers and avoids unnecessary allocations.

Suggested change
-    entries = []
-    for line in path.read_text(encoding="utf-8").strip().splitlines():
+    entries = []
+    with path.open("r", encoding="utf-8") as f:
+        for line in f:
         if not line.strip():
             continue
         entry = EvidenceEntry.model_validate_json(line)
         if case_id is None or entry.case_id == case_id:
             entries.append(entry)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@commons/evidence_ledger.py` around lines 57 - 63, The code currently loads
the entire ledger file into memory with
path.read_text(encoding="utf-8").strip().splitlines() before iterating through
lines, which doesn't scale well for large JSONL files. Refactor this to stream
the file line by line instead: replace the read_text().strip().splitlines() call
with an open() context manager that reads the file with the specified encoding,
then iterate directly through the file object to process each line. This avoids
allocating memory for the entire file contents while maintaining the same
filtering logic for case_id matching and entry validation with
EvidenceEntry.model_validate_json().
sdlc/authority_case.py (1)

54-54: 💤 Low value

Consider removing duplicate model_config.

BaseGovernanceCase already defines model_config = {"extra": "allow"} (see commons/governance_case.py line 45). Pydantic inherits model config from parent classes, so this redeclaration is redundant and could lead to drift if the base class config changes.

♻️ Proposed fix
     consent_contract_required: bool | None = None
     consent_contract_reason: str | None = None
-
-    model_config = {"extra": "allow"}

     def parsed_stage(self) -> Stage:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sdlc/authority_case.py` at line 54, The AuthorityCase class contains a
redundant model_config definition that duplicates the one already inherited from
its parent class BaseGovernanceCase. Remove the model_config = {"extra":
"allow"} line from the AuthorityCase class in sdlc/authority_case.py, as
Pydantic will automatically inherit this configuration from the parent class,
and this inheritance approach prevents configuration drift if the base class
config changes in the future.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@rdlc/research_case.py`:
- Line 26: The module docstring at the top of the research_case.py file contains
an outdated note about a sanctioned interim `rdlc -> sdlc` dependency, but the
import statement now correctly imports `RiskTier` from `commons.risk_tier`
directly. Update or remove the dependency note in the module-level docstring to
reflect the actual import source and ensure the file-level documentation
contract matches the current code implementation.

---

Outside diff comments:
In `@rdlc/research_ledger.py`:
- Around line 16-21: The module docstring in rdlc/research_ledger.py still
references the old location of the evidence ledger in sdlc/ or describes it as
pending extraction, but the imports now correctly target
commons.evidence_ledger. Update the module-level docstring at the top of the
file to accurately reflect the current architecture and remove outdated
references to the previous sdlc/ location or extraction status, ensuring the
documentation aligns with the actual import structure that now pulls from
commons.evidence_ledger.

---

Nitpick comments:
In `@commons/evidence_ledger.py`:
- Around line 57-63: The code currently loads the entire ledger file into memory
with path.read_text(encoding="utf-8").strip().splitlines() before iterating
through lines, which doesn't scale well for large JSONL files. Refactor this to
stream the file line by line instead: replace the
read_text().strip().splitlines() call with an open() context manager that reads
the file with the specified encoding, then iterate directly through the file
object to process each line. This avoids allocating memory for the entire file
contents while maintaining the same filtering logic for case_id matching and
entry validation with EvidenceEntry.model_validate_json().

In `@sdlc/authority_case.py`:
- Line 54: The AuthorityCase class contains a redundant model_config definition
that duplicates the one already inherited from its parent class
BaseGovernanceCase. Remove the model_config = {"extra": "allow"} line from the
AuthorityCase class in sdlc/authority_case.py, as Pydantic will automatically
inherit this configuration from the parent class, and this inheritance approach
prevents configuration drift if the base class config changes in the future.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5efb0419-711d-42a2-b96f-ea1094ab18c5

📥 Commits

Reviewing files that changed from the base of the PR and between d2aa3f8 and 459fa6e.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • commons/evidence_ledger.py
  • commons/risk_tier.py
  • rdlc/research_case.py
  • rdlc/research_ledger.py
  • sdlc/authority_case.py
  • sdlc/evidence_ledger.py
  • sdlc/risk_tier.py
  • tests/rdlc/test_import_graph.py
  • tests/sdlc/test_authority_case.py

Comment thread rdlc/research_case.py
from pydantic import Field

from commons.governance_case import BaseGovernanceCase
from commons.risk_tier import RiskTier

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Synchronize the module docstring with the new import source.

RiskTier now comes from commons.risk_tier (Line 26), but the module docstring still states the sanctioned interim rdlc -> sdlc dependency. Please update/remove that note so the file-level contract matches the code.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rdlc/research_case.py` at line 26, The module docstring at the top of the
research_case.py file contains an outdated note about a sanctioned interim `rdlc
-> sdlc` dependency, but the import statement now correctly imports `RiskTier`
from `commons.risk_tier` directly. Update or remove the dependency note in the
module-level docstring to reflect the actual import source and ensure the
file-level documentation contract matches the current code implementation.

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.

1 participant