Skip to content

refactor: bounded extraction for mutation coverage hardening#384

Merged
cmbays merged 10 commits intomainfrom
worktree-rosy-twirling-petal
Mar 16, 2026
Merged

refactor: bounded extraction for mutation coverage hardening#384
cmbays merged 10 commits intomainfrom
worktree-rosy-twirling-petal

Conversation

@cmbays
Copy link
Owner

@cmbays cmbays commented Mar 16, 2026

Extract pure helpers from 4 hotspot files. Observability aggregator reaches 100% mutation score. Overall 70.65 to 71.23. Addresses #375.

Summary by CodeRabbit

  • New Features

    • Standardized command-line status symbols and JSON output behavior; improved agent confidence and observability reporting.
  • Tests

    • Added extensive unit tests for command helpers, cycle/session utilities, agent confidence, and observability logic.
  • Refactor

    • Extracted and centralized helper utilities for file/type checks, state transitions, and attribution to improve reliability and maintainability.

cmbays and others added 7 commits March 16, 2026 06:15
Extract `resolveRegistryDir` and `computeAverageConfidence` as exported
pure functions from the monolithic `compute()` method. Add 12 targeted
unit tests covering:
- agentDir vs katakaDir resolution (precedence, fallback, throw)
- average confidence arithmetic (empty, single, multi, boundary)
- load() throw path when no registry dir configured

Addresses #375 Phase 3 — bounded extraction for mutation coverage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove two dead-code guards that masked 6 surviving mutants:
- existsSync before mkdirSync({recursive:true}) is idempotent
- existsSync before JsonStore.read in load() has error handler fallback

Eliminates all 6 survivors by removing untestable redundant branches.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…m cooldown-session

Extract isJsonFile, isSynthesisPendingFile, hasFailedCaptures as pure
helpers with direct unit tests. Remove 3 redundant existsSync guards
in bridge-run loading where readBridgeRunMeta already handles missing
files via its own error handler.

Addresses #375 Phase 3 — cooldown-session bounded extraction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…Status from execute.ts

Move three pure business-logic functions out of CLI command wiring into
execute.helpers.ts with direct unit tests. Eliminates 4+ LogicalOperator
and ConditionalExpression mutation survivors in execute.ts.

Addresses #375 Phase 2 — execute helper extraction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ty aggregator

Extract run-directory listing and latest-run comparison as pure
exported functions. Remove redundant existsSync guard. Add tests
for directory filtering (files vs dirs) and multi-run latest tracking.

Addresses #375 Phase 3 — observability aggregator extraction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This guard is semantically meaningful — it distinguishes "file missing"
(undefined, triggers run.json fallback) from "file found but run not
in-progress" (null, no fallback). Removing it broke the
checkIncompleteRuns fallthrough to run.json for runs without bridge
metadata.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…m aggregator

Reduce cyclomatic complexity of computeStats by extracting agent
attribution check and observation counting as pure functions. Adds
direct unit tests for both. Targets CRAP strict threshold for
computeStats (CC 9 -> lower effective complexity).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector
Copy link

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, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai
Copy link

coderabbitai bot commented Mar 16, 2026

Warning

Rate limit exceeded

@cmbays has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 14 minutes and 18 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e4dee151-fa8c-43a0-bd06-7def75f33a5c

📥 Commits

Reviewing files that changed from the base of the PR and between f033274 and 461a494.

📒 Files selected for processing (6)
  • src/cli/commands/execute.helpers.test.ts
  • src/features/cycle-management/cooldown-session.helpers.ts
  • src/infrastructure/execution/session-bridge.helpers.test.ts
  • src/infrastructure/execution/session-bridge.helpers.ts
  • src/shared/lib/file-filters.test.ts
  • src/shared/lib/file-filters.ts
📝 Walkthrough

Walkthrough

Adds numerous small, pure helper functions and corresponding tests across CLI, cycle-management, kata-agent, and session-bridge modules; existing inline predicates/logic are replaced with these helpers and call sites updated accordingly.

Changes

Cohort / File(s) Summary
Execute Command Helpers
src/cli/commands/execute.helpers.ts, src/cli/commands/execute.helpers.test.ts, src/cli/commands/execute.ts
New helpers resolveJsonFlag, betStatusSymbol, resolveCompletionStatus added and used in execute.ts to replace inline JSON/ status logic; tests added for helpers. Note: duplicate helper definitions observed in helpers file.
Cooldown Session Helpers
src/features/cycle-management/cooldown-session.helpers.ts, src/features/cycle-management/cooldown-session.helpers.test.ts, src/features/cycle-management/cooldown-session.ts
Added isJsonFile, isSynthesisPendingFile, hasFailedCaptures; cooldown-session.ts refactored to use these predicates (file filtering, pending items, failed-capture checks); some pre-checks (existsSync) removed.
Kata Agent — Confidence
src/features/kata-agent/kata-agent-confidence-calculator.ts, src/features/kata-agent/kata-agent-confidence-calculator.test.ts
Added resolveRegistryDir and computeAverageConfidence; compute/load now use these helpers, directory creation simplified, unused existsSync removed; tests added for helper behaviors and edge cases.
Kata Agent — Observability Aggregator
src/features/kata-agent/kata-agent-observability-aggregator.ts, src/features/kata-agent/kata-agent-observability-aggregator.test.ts
Introduced isNewerRun, isAttributedToAgent, countObservationsByType, listRunDirectoryIds; aggregator refactored to use helpers for run discovery, attribution, recency, and counting; tests exercise new helpers and lastRun/lastActiveAt logic.
Session Bridge Helpers & Integration
src/infrastructure/execution/session-bridge.helpers.ts, src/infrastructure/execution/session-bridge.helpers.test.ts, src/infrastructure/execution/session-bridge.ts, src/infrastructure/execution/session-bridge.unit.test.ts
Added canTransitionCycleState, hasBridgeRunMetadataChanged, isJsonFile; session-bridge replaced inline JSON checks and transition/metadata comparisons with these helpers; tests updated to import helper directly.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰
Little paws tidy up the code,
Helpers hop down a cleaner road.
Tests applaud with tiny cheers,
Symbols, flags, and average peers.
I nibble bugs and stash new seeds.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'refactor: bounded extraction for mutation coverage hardening' accurately describes the main objective—extracting pure helper functions from hotspot files to improve mutation test coverage.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch worktree-rosy-twirling-petal
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Tip

You can disable sequence diagrams in the walkthrough.

Disable the reviews.sequence_diagrams setting to disable sequence diagrams in the walkthrough.

cmbays and others added 2 commits March 16, 2026 06:38
Create session-bridge.helpers.ts with canTransitionCycleState,
hasBridgeRunMetadataChanged, and isJsonFile. Wire into session-bridge.ts
replacing inline logic. Add 13 unit tests covering state transitions,
metadata change detection, and file filtering.

Addresses #375 Phase 3 — session-bridge bounded extraction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace prototype-hacking access to private canTransitionCycleState
with direct import from session-bridge.helpers.ts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
coderabbitai[bot]
coderabbitai bot previously requested changes Mar 16, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/cli/commands/execute.helpers.test.ts`:
- Around line 428-445: Add a focused test case to assert the precedence behavior
of resolveJsonFlag when local is explicitly false but global is true: call
resolveJsonFlag(false, true) and expect true; this ensures the function returns
true for the global flag even when local is false and prevents a boolean-mutant
survivor. Locate the resolveJsonFlag tests in execute.helpers.test.ts (the
existing describe('resolveJsonFlag') block) and add the new it(...) assertion
alongside the other cases to cover the local=false, global=true edge case.

In `@src/features/kata-agent/kata-agent-confidence-calculator.test.ts`:
- Around line 5-9: The import in the test uses a relative path for
KataAgentConfidenceCalculator, resolveRegistryDir, and computeAverageConfidence;
replace the relative import ("./kata-agent-confidence-calculator.js") with the
project path alias (e.g. `@features/kata-agent/kata-agent-confidence-calculator`)
so the named imports remain identical and consistent with the project's alias
convention.

In `@src/features/kata-agent/kata-agent-confidence-calculator.ts`:
- Line 9: Replace the relative import for the KataAgentObservabilityAggregator
with the project path alias: update the import of
KataAgentObservabilityAggregator in kata-agent-confidence-calculator.ts to use
'@features/kata-agent/kata-agent-observability-aggregator.js' (keeping the same
exported symbol name) so the file follows the project's import conventions.

In `@src/features/kata-agent/kata-agent-observability-aggregator.test.ts`:
- Around line 5-11: Replace the relative import of
KataAgentObservabilityAggregator, countObservationsByType, isAttributedToAgent,
isNewerRun, and listRunDirectoryIds from
'./kata-agent-observability-aggregator.js' with the project path alias for that
feature (e.g. the alias that maps to the features/kata-agent module) and omit
the explicit .js extension; update the import statement in
kata-agent-observability-aggregator.test.ts to use the path alias (so the same
named exports are imported via the alias), ensuring the alias is the one
configured in your tsconfig/paths or bundler.

In `@src/features/kata-agent/kata-agent-observability-aggregator.ts`:
- Around line 52-62: The function countObservationsByType manually increments
count inside the loop even though it always equals observations.length; change
the implementation to compute count = observations.length (keep the existing
for-loop to build byType) or remove the manual increment and set count after the
loop, updating the function return accordingly to avoid unnecessary mutation of
the count variable in countObservationsByType while preserving byType
aggregation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0dac2d9f-5520-416b-96d2-96be23d25414

📥 Commits

Reviewing files that changed from the base of the PR and between a024d85 and d56e409.

📒 Files selected for processing (10)
  • src/cli/commands/execute.helpers.test.ts
  • src/cli/commands/execute.helpers.ts
  • src/cli/commands/execute.ts
  • src/features/cycle-management/cooldown-session.helpers.test.ts
  • src/features/cycle-management/cooldown-session.helpers.ts
  • src/features/cycle-management/cooldown-session.ts
  • src/features/kata-agent/kata-agent-confidence-calculator.test.ts
  • src/features/kata-agent/kata-agent-confidence-calculator.ts
  • src/features/kata-agent/kata-agent-observability-aggregator.test.ts
  • src/features/kata-agent/kata-agent-observability-aggregator.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.ts: All types must be defined as Zod schemas using zod/v4 import path, not separate interface definitions
Use ESM-only format with .js extensions on all internal imports
Use path aliases for imports: @domain/, @infra/, @features/, @shared/, @cli/* instead of relative paths

Files:

  • src/features/kata-agent/kata-agent-confidence-calculator.test.ts
  • src/features/kata-agent/kata-agent-confidence-calculator.ts
  • src/features/cycle-management/cooldown-session.helpers.ts
  • src/features/cycle-management/cooldown-session.ts
  • src/features/kata-agent/kata-agent-observability-aggregator.test.ts
  • src/features/kata-agent/kata-agent-observability-aggregator.ts
  • src/cli/commands/execute.helpers.test.ts
  • src/features/cycle-management/cooldown-session.helpers.test.ts
  • src/cli/commands/execute.ts
  • src/cli/commands/execute.helpers.ts
src/**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Colocate test files with implementation files using *.test.ts naming convention

Files:

  • src/features/kata-agent/kata-agent-confidence-calculator.test.ts
  • src/features/kata-agent/kata-agent-observability-aggregator.test.ts
  • src/cli/commands/execute.helpers.test.ts
  • src/features/cycle-management/cooldown-session.helpers.test.ts
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
Repo: cmbays/kata PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-15T01:51:21.342Z
Learning: Focused mutation testing must be run for changed business logic or orchestration seams with meaningful survivors explicitly called out
Learnt from: CR
Repo: cmbays/kata PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-15T01:51:21.342Z
Learning: Run focused mutation testing on changed behavior-heavy modules
📚 Learning: 2026-03-15T01:51:21.342Z
Learnt from: CR
Repo: cmbays/kata PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-15T01:51:21.342Z
Learning: Applies to src/**/{cli,orchestrat}*.ts : Prefer extracting pure helpers from CLI/orchestration files before adding more direct tests to large side-effect-heavy modules

Applied to files:

  • src/features/kata-agent/kata-agent-confidence-calculator.test.ts
  • src/features/kata-agent/kata-agent-observability-aggregator.test.ts
  • src/features/kata-agent/kata-agent-observability-aggregator.ts
  • src/cli/commands/execute.helpers.test.ts
  • src/features/cycle-management/cooldown-session.helpers.test.ts
  • src/cli/commands/execute.ts
  • src/cli/commands/execute.helpers.ts
📚 Learning: 2026-03-15T01:51:21.342Z
Learnt from: CR
Repo: cmbays/kata PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-15T01:51:21.342Z
Learning: Applies to src/**/*.command.test.ts : Keep command-level tests focused on wiring and delegation; put parsing/formatting/selection behavior into direct unit tests

Applied to files:

  • src/cli/commands/execute.helpers.test.ts
  • src/features/cycle-management/cooldown-session.helpers.test.ts
📚 Learning: 2026-03-15T01:51:09.797Z
Learnt from: CR
Repo: cmbays/kata PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T01:51:09.797Z
Learning: Applies to src/**/*.test.ts : Colocate test files with implementation files using `*.test.ts` naming convention

Applied to files:

  • src/features/cycle-management/cooldown-session.helpers.test.ts
📚 Learning: 2026-03-15T01:51:21.342Z
Learnt from: CR
Repo: cmbays/kata PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-15T01:51:21.342Z
Learning: Run `npm run test:coverage:unit && npm run test:crap` after driving implementation with tests

Applied to files:

  • src/features/cycle-management/cooldown-session.helpers.test.ts
🔇 Additional comments (30)
src/features/cycle-management/cooldown-session.helpers.test.ts (1)

380-416: LGTM!

The new tests for isJsonFile, isSynthesisPendingFile, and hasFailedCaptures provide good coverage of typical inputs and edge cases (empty strings, wrong prefixes/suffixes, boundary values). Test file is properly colocated with implementation per coding guidelines.

src/features/cycle-management/cooldown-session.helpers.ts (1)

296-306: LGTM!

The three new pure helper functions are well-scoped and improve testability:

  • isJsonFile — simple suffix check
  • isSynthesisPendingFile — combined prefix/suffix check
  • hasFailedCaptures — numeric predicate

These extractions align with the learning to "prefer extracting pure helpers from CLI/orchestration files before adding more direct tests to large side-effect-heavy modules."

src/features/cycle-management/cooldown-session.ts (4)

56-58: LGTM!

New helper imports are correctly added and follow the ESM .js extension convention.


843-851: LGTM!

The refactor to use isSynthesisPendingFile as the filter predicate is clean and maintains the same behavior.


888-894: LGTM!

Clean refactor using isJsonFile as the filter predicate.


990-997: LGTM!

The refactor to use hasFailedCaptures(attempts.failed) correctly replaces the inline comparison while maintaining identical semantics.

src/features/kata-agent/kata-agent-observability-aggregator.ts (6)

1-6: LGTM!

Imports correctly use path aliases (@domain/*, @infra/*) with .js extensions as required by the coding guidelines.


11-35: LGTM!

The interface is well-documented with JSDoc comments explaining each field's purpose. Since this is an internally-constructed stats object (not parsed from external input), using a TypeScript interface here is reasonable.


41-43: LGTM!

Clean extraction of the recency comparison logic. Lexicographic comparison is valid for ISO 8601 date strings, and the strict inequality correctly handles equal timestamps.


45-50: LGTM!

Clear attribution logic with proper fallback from agentId to legacy katakaId. The nullish coalescing correctly handles the migration path between naming conventions.


64-72: LGTM!

Efficient implementation using withFileTypes for single-syscall directory listing. Error handling gracefully returns an empty array for missing directories, eliminating untestable branches in the caller.


108-158: LGTM!

Clean integration of the extracted helpers into computeStats. The helper calls are correctly placed:

  • listRunDirectoryIds for directory discovery
  • isAttributedToAgent for both run and observation filtering
  • isNewerRun for tracking the most recent run
  • countObservationsByType for aggregating observation counts

The lastActiveAt propagation at line 132 correctly captures the timestamp when a newer run is found.

src/features/kata-agent/kata-agent-observability-aggregator.test.ts (5)

21-53: LGTM!

Test helpers are well-structured with proper isolation using randomUUID() for unique directories. The factory functions provide sensible defaults with override capability.


59-219: LGTM!

Comprehensive test coverage for computeStats:

  • Edge cases: empty/nonexistent directories, non-matching attribution
  • Core functionality: run-level and stage-level observations, observation filtering
  • Tracking: lastRunId, lastRunCycleId, lastActiveAt selection
  • Aggregation: multiple runs with proper count accumulation

221-315: LGTM!

Good coverage of KnowledgeStore integration including the important edge case of archived learnings being excluded.


317-334: Minor overlap with existing test at lines 171-186.

Both test lastRunId/lastActiveAt tracking with similar scenarios. This is acceptable for mutation coverage hardening, but could be consolidated in future cleanup.


341-420: LGTM!

Excellent unit test coverage for the pure helpers:

  • isNewerRun: All boundary cases (undefined, later, earlier, equal timestamps)
  • isAttributedToAgent: All attribution scenarios including preference behavior
  • countObservationsByType: Empty, multiple types, single observation
  • listRunDirectoryIds: Directory filtering and nonexistent path handling

This aligns well with the PR objective of improving mutation coverage through extracted pure helpers. Based on learnings, "Prefer extracting pure helpers from CLI/orchestration files before adding more direct tests to large side-effect-heavy modules."

src/features/kata-agent/kata-agent-confidence-calculator.ts (4)

15-26: LGTM!

The resolveRegistryDir helper is clean with clear fallback semantics and an informative error message. The relevant code snippets confirm that callers (CooldownSession, agent.ts, cycle.ts) properly provide agentDir before invoking methods that use this helper.


28-35: LGTM!

The computeAverageConfidence helper correctly handles the empty array edge case and uses ReadonlyArray to communicate immutability intent. The arithmetic is straightforward and testable.


80-83: LGTM!

Good refactoring: mkdirSync with { recursive: true } is idempotent and eliminates the untestable existsSync branch while preserving correctness. Using the extracted helpers improves testability without changing behavior.


91-93: LGTM!

Consistent use of resolveRegistryDir in load() ensures the same resolution logic applies to both compute and load paths.

src/features/kata-agent/kata-agent-confidence-calculator.test.ts (4)

76-94: LGTM!

Excellent branch coverage for resolveRegistryDir: all four combinations of agentDir/katakaDir presence are tested, including the error case with exact message verification.


96-119: LGTM!

Solid test coverage for computeAverageConfidence with appropriate edge cases (empty, single, multiple, all-zero, all-one). Using toBeCloseTo for floating-point comparison is the right approach. Based on learnings, this aligns with the goal of focused mutation testing on changed business logic.


234-276: LGTM!

These tests comprehensively verify the agentDir vs katakaDir resolution behavior:

  • Priority given to agentDir when both are provided
  • agentDir works standalone without legacy katakaDir
  • Error thrown when neither is provided

The negative assertion on line 252 (expect(existsSync(...katakaDir...)).toBe(false)) is a good practice to confirm priority behavior.


316-348: LGTM!

Good coverage for load() with the new directory resolution. The test on lines 325-348 properly verifies that when both directories are provided, load() reads from agentDir (where compute() wrote the file).

src/cli/commands/execute.helpers.test.ts (2)

3-3: Import wiring is clean and guideline-compliant.

The new helper imports are correctly aliased and use ESM .js extension consistently.

As per coding guidelines: "Use ESM-only format with .js extensions on all internal imports" and "Use path aliases ... instead of relative paths".

Also applies to: 14-16


447-478: Helper test coverage is solid for status symbol and completion status branches.

Good extraction-level tests with explicit branch assertions and fallback behavior checks.

Based on learnings: "Prefer extracting pure helpers from CLI/orchestration files before adding more direct tests to large side-effect-heavy modules".

src/cli/commands/execute.helpers.ts (1)

313-326: Extracted helper implementations look correct and intentionally minimal.

These pure helpers are deterministic and align with their new unit tests and call sites.

src/cli/commands/execute.ts (2)

24-39: JSON output flag resolution is now consistently centralized.

Good replacement of duplicated boolean checks with a single helper across command paths.

Also applies to: 108-108, 195-195, 251-251, 273-273


149-150: Status/symbol helper adoption is coherent across text and JSON outputs.

Nice consolidation—this reduces drift between CLI display and machine-readable status fields.

Based on learnings: "Prefer extracting pure helpers from CLI/orchestration files before adding more direct tests to large side-effect-heavy modules".

Also applies to: 232-233, 239-239

Comment on lines +5 to +9
import {
KataAgentConfidenceCalculator,
resolveRegistryDir,
computeAverageConfidence,
} from './kata-agent-confidence-calculator.js';
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider using path alias for consistency.

The import uses a relative path while other imports in this file use path aliases. For consistency with project conventions, consider using the path alias.

Suggested fix
 import {
   KataAgentConfidenceCalculator,
   resolveRegistryDir,
   computeAverageConfidence,
-} from './kata-agent-confidence-calculator.js';
+} from '@features/kata-agent/kata-agent-confidence-calculator.js';

As per coding guidelines: "Use path aliases for imports: @domain/, @infra/, @features/, @shared/, @cli/* instead of relative paths"

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import {
KataAgentConfidenceCalculator,
resolveRegistryDir,
computeAverageConfidence,
} from './kata-agent-confidence-calculator.js';
import {
KataAgentConfidenceCalculator,
resolveRegistryDir,
computeAverageConfidence,
} from '@features/kata-agent/kata-agent-confidence-calculator.js';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/kata-agent/kata-agent-confidence-calculator.test.ts` around
lines 5 - 9, The import in the test uses a relative path for
KataAgentConfidenceCalculator, resolveRegistryDir, and computeAverageConfidence;
replace the relative import ("./kata-agent-confidence-calculator.js") with the
project path alias (e.g. `@features/kata-agent/kata-agent-confidence-calculator`)
so the named imports remain identical and consistent with the project's alias
convention.

@@ -8,6 +8,32 @@ import {
} from '@domain/types/kata-agent-confidence.js';
import { KataAgentObservabilityAggregator } from './kata-agent-observability-aggregator.js';
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Use path alias instead of relative import.

The import should use @features/kata-agent/kata-agent-observability-aggregator.js to comply with the project's import conventions. Other imports in this file correctly use path aliases.

Suggested fix
-import { KataAgentObservabilityAggregator } from './kata-agent-observability-aggregator.js';
+import { KataAgentObservabilityAggregator } from '@features/kata-agent/kata-agent-observability-aggregator.js';

As per coding guidelines: "Use path aliases for imports: @domain/, @infra/, @features/, @shared/, @cli/* instead of relative paths"

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { KataAgentObservabilityAggregator } from './kata-agent-observability-aggregator.js';
import { KataAgentObservabilityAggregator } from '@features/kata-agent/kata-agent-observability-aggregator.js';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/kata-agent/kata-agent-confidence-calculator.ts` at line 9,
Replace the relative import for the KataAgentObservabilityAggregator with the
project path alias: update the import of KataAgentObservabilityAggregator in
kata-agent-confidence-calculator.ts to use
'@features/kata-agent/kata-agent-observability-aggregator.js' (keeping the same
exported symbol name) so the file follows the project's import conventions.

Comment on lines +5 to +11
import {
KataAgentObservabilityAggregator,
countObservationsByType,
isAttributedToAgent,
isNewerRun,
listRunDirectoryIds,
} from './kata-agent-observability-aggregator.js';
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Use path alias instead of relative import.

As per coding guidelines, use path aliases instead of relative paths for internal imports.

♻️ Proposed fix
 import {
   KataAgentObservabilityAggregator,
   countObservationsByType,
   isAttributedToAgent,
   isNewerRun,
   listRunDirectoryIds,
-} from './kata-agent-observability-aggregator.js';
+} from '@features/kata-agent/kata-agent-observability-aggregator.js';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import {
KataAgentObservabilityAggregator,
countObservationsByType,
isAttributedToAgent,
isNewerRun,
listRunDirectoryIds,
} from './kata-agent-observability-aggregator.js';
import {
KataAgentObservabilityAggregator,
countObservationsByType,
isAttributedToAgent,
isNewerRun,
listRunDirectoryIds,
} from '@features/kata-agent/kata-agent-observability-aggregator.js';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/kata-agent/kata-agent-observability-aggregator.test.ts` around
lines 5 - 11, Replace the relative import of KataAgentObservabilityAggregator,
countObservationsByType, isAttributedToAgent, isNewerRun, and
listRunDirectoryIds from './kata-agent-observability-aggregator.js' with the
project path alias for that feature (e.g. the alias that maps to the
features/kata-agent module) and omit the explicit .js extension; update the
import statement in kata-agent-observability-aggregator.test.ts to use the path
alias (so the same named exports are imported via the alias), ensuring the alias
is the one configured in your tsconfig/paths or bundler.

Comment on lines +52 to +62
export function countObservationsByType(
observations: ReadonlyArray<{ type: string }>,
): { count: number; byType: Record<string, number> } {
const byType: Record<string, number> = {};
let count = 0;
for (const obs of observations) {
count++;
byType[obs.type] = (byType[obs.type] ?? 0) + 1;
}
return { count, byType };
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Minor simplification opportunity.

The count variable always equals observations.length, so the manual increment could be replaced. However, the explicit loop approach may be intentional for mutation coverage visibility.

♻️ Optional simplification
 export function countObservationsByType(
   observations: ReadonlyArray<{ type: string }>,
 ): { count: number; byType: Record<string, number> } {
   const byType: Record<string, number> = {};
-  let count = 0;
   for (const obs of observations) {
-    count++;
     byType[obs.type] = (byType[obs.type] ?? 0) + 1;
   }
-  return { count, byType };
+  return { count: observations.length, byType };
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/kata-agent/kata-agent-observability-aggregator.ts` around lines
52 - 62, The function countObservationsByType manually increments count inside
the loop even though it always equals observations.length; change the
implementation to compute count = observations.length (keep the existing
for-loop to build byType) or remove the manual increment and set count after the
loop, updating the function return accordingly to avoid unnecessary mutation of
the count variable in countObservationsByType while preserving byType
aggregation.

coderabbitai[bot]
coderabbitai bot previously requested changes Mar 16, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

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 (2)
src/infrastructure/execution/session-bridge.unit.test.ts (1)

191-198: 🧹 Nitpick | 🔵 Trivial

Consider removing duplicate test coverage.

This test case duplicates assertions that are already comprehensively covered in session-bridge.helpers.test.ts (lines 8-37). Since the helper is now a standalone export tested in its own file, this test adds no additional coverage value.

If the intent is to verify integration with SessionExecutionBridge, the test at lines 175-189 already covers that path by exercising updateCycleState which delegates to the helper.

🧹 Proposed removal
-  it('only allows adjacent forward cycle state transitions', () => {
-    expect(canTransitionCycleState('planning', 'active')).toBe(true);
-    expect(canTransitionCycleState('active', 'cooldown')).toBe(true);
-    expect(canTransitionCycleState('cooldown', 'complete')).toBe(true);
-    expect(canTransitionCycleState('planning', 'complete')).toBe(false);
-    expect(canTransitionCycleState('active', 'complete')).toBe(false);
-    expect(canTransitionCycleState('complete', 'planning')).toBe(false);
-  });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/infrastructure/execution/session-bridge.unit.test.ts` around lines 191 -
198, This test duplicates coverage for the canTransitionCycleState helper
already tested in session-bridge.helpers.test.ts; remove the redundant "only
allows adjacent forward cycle state transitions" test block from
session-bridge.unit.test.ts so coverage stays focused on SessionExecutionBridge
integration tests (keep the existing updateCycleState integration test that
exercises the helper indirectly); locate the duplicate by the test description
and references to canTransitionCycleState and delete that it(...) block.
src/infrastructure/execution/session-bridge.ts (1)

850-851: 🛠️ Refactor suggestion | 🟠 Major

Inconsistent: should use isJsonFile helper.

listBridgeRunsForCycle still uses inline f.endsWith('.json') while findCycleForBet (line 428) and loadCycle (line 445) use the extracted isJsonFile helper. For consistency and to fully realize the refactor goal, use the helper here as well.

♻️ Proposed fix
     return readdirSync(dir)
-      .filter((f) => f.endsWith('.json'))
+      .filter(isJsonFile)
       .map((f) => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/infrastructure/execution/session-bridge.ts` around lines 850 - 851, The
listBridgeRunsForCycle implementation is using an inline check
readdirSync(dir).filter((f) => f.endsWith('.json')) instead of the existing
isJsonFile helper; update listBridgeRunsForCycle to call isJsonFile(f) for the
filter, and ensure isJsonFile is in scope (import or reference the helper where
listBridgeRunsForCycle is defined) so the behavior matches findCycleForBet and
loadCycle.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/infrastructure/execution/session-bridge.helpers.ts`:
- Around line 16-24: The function hasBridgeRunMetadataChanged only compares
betName and cycleName but its name implies all metadata; either rename the
function to hasBridgeRunNamesChanged and update all call sites (and any exported
typings) accordingly, or keep the name and update the JSDoc comment to
explicitly state it only checks betName and cycleName; locate the symbol
hasBridgeRunMetadataChanged in this file and across imports/exports to rename or
document consistently.

---

Outside diff comments:
In `@src/infrastructure/execution/session-bridge.ts`:
- Around line 850-851: The listBridgeRunsForCycle implementation is using an
inline check readdirSync(dir).filter((f) => f.endsWith('.json')) instead of the
existing isJsonFile helper; update listBridgeRunsForCycle to call isJsonFile(f)
for the filter, and ensure isJsonFile is in scope (import or reference the
helper where listBridgeRunsForCycle is defined) so the behavior matches
findCycleForBet and loadCycle.

In `@src/infrastructure/execution/session-bridge.unit.test.ts`:
- Around line 191-198: This test duplicates coverage for the
canTransitionCycleState helper already tested in session-bridge.helpers.test.ts;
remove the redundant "only allows adjacent forward cycle state transitions" test
block from session-bridge.unit.test.ts so coverage stays focused on
SessionExecutionBridge integration tests (keep the existing updateCycleState
integration test that exercises the helper indirectly); locate the duplicate by
the test description and references to canTransitionCycleState and delete that
it(...) block.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: bf7a445f-38aa-436c-a9b4-43805a7b8782

📥 Commits

Reviewing files that changed from the base of the PR and between d56e409 and f033274.

📒 Files selected for processing (4)
  • src/infrastructure/execution/session-bridge.helpers.test.ts
  • src/infrastructure/execution/session-bridge.helpers.ts
  • src/infrastructure/execution/session-bridge.ts
  • src/infrastructure/execution/session-bridge.unit.test.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.ts: All types must be defined as Zod schemas using zod/v4 import path, not separate interface definitions
Use ESM-only format with .js extensions on all internal imports
Use path aliases for imports: @domain/, @infra/, @features/, @shared/, @cli/* instead of relative paths

Files:

  • src/infrastructure/execution/session-bridge.helpers.ts
  • src/infrastructure/execution/session-bridge.ts
  • src/infrastructure/execution/session-bridge.helpers.test.ts
  • src/infrastructure/execution/session-bridge.unit.test.ts
src/**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Colocate test files with implementation files using *.test.ts naming convention

Files:

  • src/infrastructure/execution/session-bridge.helpers.test.ts
  • src/infrastructure/execution/session-bridge.unit.test.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: cmbays/kata PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-15T01:51:21.342Z
Learning: Applies to src/**/{cli,orchestrat}*.ts : Prefer extracting pure helpers from CLI/orchestration files before adding more direct tests to large side-effect-heavy modules
📚 Learning: 2026-03-15T01:51:21.342Z
Learnt from: CR
Repo: cmbays/kata PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-15T01:51:21.342Z
Learning: Applies to src/**/{cli,orchestrat}*.ts : Prefer extracting pure helpers from CLI/orchestration files before adding more direct tests to large side-effect-heavy modules

Applied to files:

  • src/infrastructure/execution/session-bridge.helpers.ts
  • src/infrastructure/execution/session-bridge.helpers.test.ts
  • src/infrastructure/execution/session-bridge.unit.test.ts
📚 Learning: 2026-03-15T01:51:09.797Z
Learnt from: CR
Repo: cmbays/kata PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T01:51:09.797Z
Learning: Store persistent data as JSON files in `.kata/` directory using JsonStore with typed read/write against Zod schemas

Applied to files:

  • src/infrastructure/execution/session-bridge.ts
🔇 Additional comments (8)
src/infrastructure/execution/session-bridge.helpers.test.ts (1)

1-82: LGTM! Comprehensive test coverage for the extracted helpers.

The test suite covers valid forward transitions, skip transitions, backward transitions, same-state rejections, metadata change detection, and JSON file filtering edge cases. This aligns well with the PR goal of hardening mutation coverage.

src/infrastructure/execution/session-bridge.unit.test.ts (1)

11-11: LGTM!

The import follows ESM conventions with the .js extension.

src/infrastructure/execution/session-bridge.helpers.ts (2)

1-14: LGTM! Clean implementation of cycle state transitions.

The transition map correctly encodes the linear state machine planning → active → cooldown → complete. Using Partial<Record<CycleState, CycleState>> is appropriate since complete has no valid forward transition. The function safely returns false for any unmapped state.


26-31: LGTM!

Simple and effective filename filter.

src/infrastructure/execution/session-bridge.ts (4)

21-25: LGTM!

The helper imports follow ESM conventions and use the appropriate relative path with .js extension.


428-428: LGTM!

Good use of the extracted isJsonFile helper for JSON file filtering.


539-542: LGTM!

The private wrapper provides a clean delegation point while maintaining encapsulation. The comment clarifies the testability rationale.


651-651: LGTM!

Correct usage of hasBridgeRunMetadataChanged for detecting name changes that require metadata rewrites.

Comment on lines +16 to +24
/**
* Detect whether bridge-run metadata has changed vs its refreshed values.
*/
export function hasBridgeRunMetadataChanged(
current: { betName?: string; cycleName?: string },
refreshed: { betName?: string; cycleName?: string },
): boolean {
return refreshed.betName !== current.betName || refreshed.cycleName !== current.cycleName;
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Function name may be overly broad for its scope.

The function only compares betName and cycleName, but the name hasBridgeRunMetadataChanged suggests it checks all metadata fields. Per the BridgeRunMeta schema (see session-bridge.ts:38-64), metadata includes runId, status, completedAt, tokenUsage, agentId, etc.

Consider renaming to hasBridgeRunNamesChanged or documenting in the JSDoc that this specifically detects name changes (not all metadata changes).

📝 Suggested documentation improvement
 /**
- * Detect whether bridge-run metadata has changed vs its refreshed values.
+ * Detect whether bridge-run name fields (betName, cycleName) have changed.
+ * Used by refreshPreparedRunMeta to trigger metadata rewrites on rename.
  */
 export function hasBridgeRunMetadataChanged(
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/infrastructure/execution/session-bridge.helpers.ts` around lines 16 - 24,
The function hasBridgeRunMetadataChanged only compares betName and cycleName but
its name implies all metadata; either rename the function to
hasBridgeRunNamesChanged and update all call sites (and any exported typings)
accordingly, or keep the name and update the JSDoc comment to explicitly state
it only checks betName and cycleName; locate the symbol
hasBridgeRunMetadataChanged in this file and across imports/exports to rename or
document consistently.

Address CodeRabbit review feedback:
- Move isJsonFile to shared file-filters module (single source of truth)
- Re-export from session-bridge.helpers and cooldown-session.helpers
- Add explicit local=false,global=true test for resolveJsonFlag

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@cmbays cmbays dismissed stale reviews from coderabbitai[bot] and coderabbitai[bot] March 16, 2026 10:51

Addressed feedback: consolidated isJsonFile, added test

@cmbays cmbays merged commit e1432e2 into main Mar 16, 2026
1 of 3 checks passed
@cmbays cmbays deleted the worktree-rosy-twirling-petal branch March 16, 2026 10:51
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