Skip to content

refactor(v1.5-B): generic-noun pass — concept-leak ratchet 156 → 39#8

Merged
aksOps merged 3 commits into
mainfrom
refactor/v1.5-B-generic-noun-pass
May 14, 2026
Merged

refactor(v1.5-B): generic-noun pass — concept-leak ratchet 156 → 39#8
aksOps merged 3 commits into
mainfrom
refactor/v1.5-B-generic-noun-pass

Conversation

@aksOps
Copy link
Copy Markdown
Contributor

@aksOps aksOps commented May 14, 2026

Summary

The framework's leak ratchet (incident / severity / reporter tokens in src/runtime/) sat at 156 after PR #6, conflating the framework's generic Session model with the example incident-management app's domain vocabulary. This blocked the "drop a folder under examples/<new_app>/ and go" promise that v1.1's framework-decoupling milestone started.

This pass drops the ratchet to 39 (target was <50). No functional change — every edit is one of:

  • pure rename of a local variable / param / private method
  • docstring rewrite
  • exception-message text change
  • internal-only dict-key rename (private to one module)

No public API surface, no schema column, no persisted JSON key was renamed.

Metric Before After
Concept-leak ratchet 156 39
Tests passing 1258 1258
Coverage 87.05% 87.04%
ruff clean clean

Changes

1. Tokenize-based identifier renames

incident local-variable / param-name → session in graph.py, responsive.py, supervisor.py, dedup.py, session_store.py, history_store.py. Driven by an AST-aware rename (only NAME tokens — strings/comments/attribute paths untouched). ~95 tokens removed.

In SessionStore.save, the framework incident rename collided with the inner with SqlSession(self.engine) as session: line. The SqlSession alias is renamed to db_session in that one scope so the framework session reference inside the block resolves correctly.

2. Docstring + exception-message rewrites (10 files)

Every docstring that referred to "the incident" generically now refers to "the session". Remaining incident-management mentions specifically label the example app and are kept.

SessionStore.save raises ValueError("Invalid session id …") instead of "Invalid incident id …". Tests updated to match.

3. Internal dict-key rename in HistoryStore

The private similarity-search return shape now uses {"session": <model>, ...} instead of {"incident": <model>, ...}. This dict never crosses a process boundary; private contract between two methods in the same module.

Intentionally NOT renamed (the residual 39)

Token Reason
severity, reporter_id, reporter_team SQLAlchemy columns on IncidentRow Renaming requires a schema migration.
Legacy /incidents/* URL routes in api.py Public API surface deprecated by v1.4 but not removed.
reporter_id / reporter_team deprecated kwargs on start_session Back-compat aliases for callers that haven't migrated to the submitter dict yet.
Default dedup LLM prompt + [INCIDENT A] / [INCIDENT B] labels Changing them alters what the model sees → functional change.
Example-app references in dedup defaults / docstring callouts Explicitly point at the incident-management example.

Test plan

  • uv run ruff check src/ tests/ — clean
  • uv run pytest -x — 1258 passed, 7 skipped (unchanged)
  • uv run pytest --cov=src/runtime --cov-fail-under=85 — 87.04%
  • tests/test_genericity_ratchet.py BASELINE_TOTAL bumped 156 → 39 with rationale entry inline
  • dist bundles regenerated

🤖 Generated with Claude Code

aksOps added 3 commits May 14, 2026 13:17
The framework's leak ratchet (incident/severity/reporter tokens in
src/runtime/) sat at 156 after PR #6. The remaining tokens conflated
the framework's generic Session model with the example
incident-management app's domain vocabulary, blocking the "drop a
folder under examples/<new_app>/ and go" promise that v1.1's
framework-decoupling milestone started.

This pass drops the ratchet to 39 in three classes of change. **No
functional change** — every edit is either a pure rename of a local
variable / private name, a docstring rewrite, or an exception-message
text change. No public API surface, no schema column, no persisted
JSON key was renamed.

1) Tokenize-based identifier renames (src/runtime/):
   - `incident` local-variable / param-name -> `session` in graph.py,
     responsive.py, supervisor.py, dedup.py, session_store.py,
     history_store.py. Driven by an AST-aware rename helper (only
     touches NAME tokens — strings/comments/attribute paths
     untouched). ~95 tokens removed.
   - In `SessionStore.save`, the framework `incident` rename collided
     with the inner `with SqlSession(self.engine) as session:` line.
     The SqlSession alias is renamed to `db_session` in that one
     scope so the framework `session` reference inside the block
     resolves correctly. Mirror change is not needed in the seven
     other SqlSession blocks because none of them reference a
     framework Session inside the with-block body.

2) Docstring + exception-message rewrites (10 files):
   - Every docstring that referred to "the incident" generically now
     refers to "the session". The few remaining `incident-management`
     mentions specifically label the example app and are kept.
   - `SessionStore.save` raises `ValueError("Invalid session id …")`
     instead of `"Invalid incident id …"`. Tests updated to match.

3) Internal dict-key rename in HistoryStore:
   - The private similarity-search return shape now uses
     `{"session": <model>, ...}` instead of `{"incident": <model>, ...}`.
     This dict never crosses a process boundary; it's a private
     contract between two methods in the same module.

What was intentionally NOT renamed (the residual 39):
   - SQLAlchemy columns `severity`, `reporter_id`, `reporter_team` on
     `IncidentRow` — renaming requires a schema migration.
   - Legacy `/incidents/*` URL routes in api.py — public API surface
     deprecated by v1.4 but not removed.
   - `reporter_id` / `reporter_team` deprecated kwargs on
     `Orchestrator.start_session` / `OrchestratorService.start_session`
     — back-compat aliases for callers that haven't migrated to the
     `submitter` dict yet.
   - The two-stage dedup default LLM prompt (`"You are deduplicating
     incident reports for an SRE platform."`) and the `[INCIDENT A]`
     / `[INCIDENT B]` labels — changing them alters what the model
     sees, which is a functional change.
   - Example-app references in dedup default config and a few
     docstring callouts that explicitly point at the
     incident-management example.

Tests + ratchet:
   - 1258 pytest passes (was 1258), ruff clean, coverage 87.04%.
   - test_genericity_ratchet.py BASELINE_TOTAL bumped down from 156
     to 39 with rationale entry inline.
   - tests/test_graph_helpers.py: 1 kwarg rename to match the
     renamed `_record_success_run(*, session=…)` signature.
   - tests/test_incident_store.py: 3 ValueError-match strings
     updated to "Invalid session id" to match the new exception
     message text.
Bundles dist/app.py + dist/apps/{code-review,incident-management}.py
in line with the src/runtime renames + docstring rewrites from the
preceding commit. No bundle-only edits.
The v1.5-B rename made ``runtime/agents/responsive.py`` and
``runtime/graph.py:make_agent_node`` more textually similar (their
local-variable names now match). Sonar's CPD detector flagged the
already-existing mirror as 15.4% new-code duplication, tripping the
PR #8 quality gate.

The two factories mirror by design — ``_build_agent_nodes``
dispatches to either based on ``skill.kind``. Add ``responsive.py``
to ``sonar.cpd.exclusions`` next to the gateway sync/async mirror,
which is the same pattern already documented inline.
@sonarqubecloud
Copy link
Copy Markdown

@aksOps aksOps merged commit 25e363c into main May 14, 2026
8 checks passed
@aksOps aksOps deleted the refactor/v1.5-B-generic-noun-pass branch May 14, 2026 13:31
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