Skip to content
6 changes: 5 additions & 1 deletion SPECS/ARCHIVE/INDEX.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# mcpbridge-wrapper Tasks Archive

**Last Updated:** 2026-02-19 (FU-P13-T13-FU-1_Set__stopped_event_and__stop_event_in__rollback_startup_for_defensive_consistency)
**Last Updated:** 2026-02-20 (P14-T1_Bound_per_session_ID_restore_maps_in_broker_transport)

## Archived Tasks

Expand Down Expand Up @@ -130,6 +130,7 @@
| FU-P13-T14 | [FU-P13-T14_Complete_interactive_Xcode_prompt_verification_and_close_P13-T5/](FU-P13-T14_Complete_interactive_Xcode_prompt_verification_and_close_P13-T5/) | 2026-02-19 | FAIL |
| FU-P13-T15 | [FU-P13-T15_Restore_broker_same-UID_client_acceptance_when_peer_credential_APIs_are_unavailable/](FU-P13-T15_Restore_broker_same-UID_client_acceptance_when_peer_credential_APIs_are_unavailable/) | 2026-02-19 | PASS |
| FU-P13-T13-FU-1 | [FU-P13-T13-FU-1_Set__stopped_event_and__stop_event_in__rollback_startup_for_defensive_consistency/](FU-P13-T13-FU-1_Set__stopped_event_and__stop_event_in__rollback_startup_for_defensive_consistency/) | 2026-02-19 | PASS |
| P14-T1 | [P14-T1_Bound_per_session_ID_restore_maps_in_broker_transport/](P14-T1_Bound_per_session_ID_restore_maps_in_broker_transport/) | 2026-02-20 | PASS |

## Historical Artifacts

Expand Down Expand Up @@ -225,6 +226,7 @@
| [REVIEW_FU-P13-T14_prompt_validation_closeout.md](_Historical/REVIEW_FU-P13-T14_prompt_validation_closeout.md) | Review report for FU-P13-T14 |
| [REVIEW_FU-P13-T15_peer_credential_fallback.md](_Historical/REVIEW_FU-P13-T15_peer_credential_fallback.md) | Review report for FU-P13-T15 |
| [REVIEW_FU-P13-T13-FU-1_rollback_event_consistency.md](_Historical/REVIEW_FU-P13-T13-FU-1_rollback_event_consistency.md) | Review report for FU-P13-T13-FU-1 |
| [REVIEW_P14-T1_broker_alias_map_bounds.md](_Historical/REVIEW_P14-T1_broker_alias_map_bounds.md) | Review report for P14-T1 |

## Archive Log

Expand Down Expand Up @@ -405,3 +407,5 @@
| 2026-02-19 | FU-P13-T15 | Archived REVIEW_FU-P13-T15_peer_credential_fallback report |
| 2026-02-19 | FU-P13-T13-FU-1 | Archived Set__stopped_event_and__stop_event_in__rollback_startup_for_defensive_consistency (PASS) |
| 2026-02-19 | FU-P13-T13-FU-1 | Archived REVIEW_FU-P13-T13-FU-1_rollback_event_consistency report |
| 2026-02-20 | P14-T1 | Archived Bound_per_session_ID_restore_maps_in_broker_transport (PASS) |
| 2026-02-20 | P14-T1 | Archived REVIEW_P14-T1_broker_alias_map_bounds report |
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# PRD: P14-T1 — Bound per-session ID restore maps in broker transport

**Status:** INPROGRESS
**Priority:** P1
**Phase:** Phase 14 — Release 0.4.0 Readiness
**Dependencies:** FU-P13-T11 (✅), FU-P13-T15 (✅)

---

## 1. Objective

Prevent unbounded growth of per-session ID alias/restore structures in broker
transport while preserving JSON-RPC ID round-trip fidelity for both integer and
string request IDs.

---

## 2. Problem Summary

`ClientSession` currently keeps three mapping structures:
- `id_restore` (`local_alias -> original_id`)
- `string_id_map` (`original_string_id -> local_alias`)
- `int_id_map` (`original_int_id -> local_alias`)

These entries are added when requests are remapped but are not removed after a
response is routed or pending requests are drained. In long-lived broker
sessions this causes steady memory growth.

Additionally, local alias allocation wraps at 20-bit bounds without checking for
active aliases, so a wrapped allocation can collide with still-active mappings.

---

## 3. Design

### 3.1 Lifecycle cleanup for completed requests

Add explicit alias-release logic that:
- Removes `local_alias` from `id_restore`.
- Removes the corresponding entry from `string_id_map` / `int_id_map` only if
that map still points to the same alias.

Invoke this cleanup when:
- Upstream responses are routed successfully.
- Pending requests are drained during shutdown.
- A request fails before reaching upstream (upstream unavailable or write
failure).

### 3.2 Safe wrap behavior for local ID allocation

Update local alias allocator to skip aliases currently present in `id_restore`.
If all aliases are exhausted, raise a deterministic error and return `-32001`
to the client instead of reusing an active alias.

### 3.3 Behavior guarantees

- ID round-trip restoration remains exact for int and string IDs.
- Map size is bounded by active in-flight requests rather than historical
traffic volume.
- Wrap-around never overwrites active alias mappings.

---

## 4. Files To Change

| File | Change |
|------|--------|
| `src/mcpbridge_wrapper/broker/transport.py` | Add alias-release helpers, wrap-safe allocator, and cleanup calls on response/drain/error paths |
| `tests/unit/test_broker_transport.py` | Add regression tests for map pruning, bounded growth, and wrap-safe alias allocation |
| `SPECS/INPROGRESS/P14-T1_Validation_Report.md` | Capture gate results and acceptance evidence |

---

## 5. Acceptance Criteria

- [ ] Per-session restore/alias maps do not grow unbounded for completed requests.
- [ ] Existing ID round-trip fidelity guarantees remain intact for int and string IDs.
- [ ] Tests cover wrap/prune behavior and pass in CI.
- [ ] Quality gates are executed and documented.


---
**Archived:** 2026-02-20
**Verdict:** PASS
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Validation Report: P14-T1 — Bound per-session ID restore maps in broker transport

**Date:** 2026-02-20
**Verdict:** PASS

---

## Acceptance Criteria

| # | Criterion | Status |
|---|-----------|--------|
| 1 | Per-session restore/alias maps do not grow unbounded for completed requests | ✅ PASS |
| 2 | Existing ID round-trip fidelity guarantees remain intact for int and string IDs | ✅ PASS |
| 3 | Tests cover wrap/prune behavior and pass in CI | ✅ PASS |
| 4 | Quality gates are executed and documented | ✅ PASS |

---

## Evidence

### Functional behavior

- Implemented alias lifecycle cleanup for all completion paths:
- Upstream response routing
- Upstream unavailable/write-failure rollback
- Session drain during shutdown
- Local ID allocator now skips active aliases after wrap and raises a deterministic error if alias space is exhausted.

### New/updated regression coverage

- `tests/unit/test_broker_transport.py::TestP14T1MapBounding::test_maps_remain_bounded_for_completed_request_stream`
- `tests/unit/test_broker_transport.py::TestP14T1MapBounding::test_alloc_local_id_skips_active_aliases_after_wrap`
- `tests/unit/test_broker_transport.py::TestProcessClientLineAdditional::test_string_id_mapping_is_released_after_response`
- `tests/unit/test_broker_transport.py::TestIntegerIDFidelity::test_integer_id_mapping_is_released_after_response`
- Additional assertions added for cleanup on write-failure, route, and drain paths.

### Command results

- `pytest tests/unit/test_broker_transport.py -k 'not SocketPermissions' -q` → **47 passed, 1 deselected**
- `pytest tests/unit/test_broker_transport.py -k 'P14T1MapBounding or mapping_is_released' -q` → **4 passed**
- `ruff check src/` → **All checks passed**
- `mypy src/` → **Success: no issues found in 18 source files**
- `pytest` → **1 failed, 625 passed, 5 skipped**
- `pytest --cov` → **1 failed, 625 passed, 5 skipped; coverage 91.33% (>=90%)**

The single failing test in full-suite runs is environment-specific and pre-existing in this workspace:
- `tests/unit/test_broker_transport.py::TestSocketPermissions::test_socket_created_with_0600_permissions`
- Failure: `OSError: AF_UNIX path too long`

---

## Changed Files

- `src/mcpbridge_wrapper/broker/transport.py`
- `tests/unit/test_broker_transport.py`

37 changes: 37 additions & 0 deletions SPECS/ARCHIVE/_Historical/REVIEW_P14-T1_broker_alias_map_bounds.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## REVIEW REPORT — P14-T1 Broker Alias Map Bounds

**Scope:** `origin/main..HEAD`
**Files:** 7

### Summary Verdict
- [x] Approve
- [ ] Approve with comments
- [ ] Request changes
- [ ] Block

### Critical Issues

- None.

### Secondary Issues

- None.

### Architectural Notes

- Alias lifecycle is now bounded to active in-flight requests rather than historical traffic volume.
- Wrap handling in `_alloc_local_id` now avoids collisions with active aliases and fails deterministically on exhaustion.
- Cleanup coverage now includes response routing, write-failure rollback, and shutdown draining paths.

### Tests

- `pytest tests/unit/test_broker_transport.py -k 'not SocketPermissions' -q` → `47 passed, 1 deselected`
- `pytest tests/unit/test_broker_transport.py -k 'P14T1MapBounding or mapping_is_released' -q` → `4 passed`
- `ruff check src/` → pass
- `mypy src/` → pass
- `pytest --cov` → one pre-existing environment failure (`AF_UNIX path too long` in `TestSocketPermissions`), overall coverage `91.33%` (>=90%).

### Next Steps

- No actionable review findings; FOLLOW-UP is skipped for this task.

12 changes: 6 additions & 6 deletions SPECS/INPROGRESS/next.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Next Task: None — All Tasks Completed

**Status:** Waiting for new tasks
# No Active Task

## Recently Archived

- `FU-P13-T13-FU-1` — Set _stopped_event and _stop_event in _rollback_startup for defensive consistency (2026-02-19, PASS)
- **P14-T1** — Bound per-session ID restore maps in broker transport (2026-02-20, PASS)
- **FU-P13-T13-FU-1** — Set _stopped_event and _stop_event in _rollback_startup for defensive consistency (2026-02-19, PASS)

## Next Step
## Suggested Next Tasks

Add or prioritize follow-up work in `SPECS/Workplan.md`, then run SELECT.
- **P14-T3** — Reconcile declared Python support with tested matrix (P1)
- **P14-T4** — Replace deprecated setuptools license metadata with SPDX format (P2)
8 changes: 4 additions & 4 deletions SPECS/Workplan.md
Original file line number Diff line number Diff line change
Expand Up @@ -2311,7 +2311,7 @@ Phase 9 Follow-up Backlog

### Phase 14: Release 0.4.0 Readiness

#### ⬜️ P14-T1: Bound per-session ID restore maps in broker transport
#### P14-T1: Bound per-session ID restore maps in broker transport — Completed (2026-02-20, PASS)
- **Description:** Prevent unbounded memory growth in long-lived broker sessions by pruning/removing alias/restore entries once responses are routed (and define safe behavior when local ID space wraps).
- **Priority:** P1
- **Dependencies:** FU-P13-T11, FU-P13-T15
Expand All @@ -2320,9 +2320,9 @@ Phase 9 Follow-up Backlog
- Updated `src/mcpbridge_wrapper/broker/transport.py` map lifecycle management for `id_restore`, `string_id_map`, and `int_id_map`
- Regression tests in `tests/unit/test_broker_transport.py` for long-lived/large-ID request streams
- **Acceptance Criteria:**
- [ ] Per-session restore/alias maps do not grow unbounded for completed requests
- [ ] Existing ID round-trip fidelity guarantees remain intact for int and string IDs
- [ ] Tests cover wrap/prune behavior and pass in CI
- [x] Per-session restore/alias maps do not grow unbounded for completed requests
- [x] Existing ID round-trip fidelity guarantees remain intact for int and string IDs
- [x] Tests cover wrap/prune behavior and pass in CI

---

Expand Down
Loading