---
issue: 13
issue_title: "Consolidate duplicate session_start handlers in index.ts"
---

# Consolidate duplicate session_start handlers

## Problem Statement

`src/index.ts` registers two `session_start` event handlers (lines ~1566 and ~1584) that perform identical setup work.
The only difference is that the first handler also logs a `lifecycle.reload` debug entry when `event.reason === "reload"`.
Every startup side effect therefore runs **twice** per session start, and contributors must remember to update both handlers or behaviour silently diverges.
This is documented as a known caveat in `AGENTS.md` under "Runtime Caveats".

## Goals

- Merge the two `session_start` handlers into a single handler that preserves the `lifecycle.reload` debug log branch.
- Ensure startup side effects execute exactly once per session start.
- Remove the "Runtime Caveats" note from `AGENTS.md` since the workaround is no longer needed.

## Non-Goals

- Refactoring other event handlers (`resources_discover`, `agent_start`, etc.) — out of scope.
- Extracting the shared setup into a named helper function — nice-to-have but not required by the issue; defer unless the single handler is unwieldy.

## Background

- **Origin:** discovered during the #6 retro (`docs/retro/0006-log-resolved-config-paths.md`), where `logResolvedConfigPaths()` had to be added to both handlers.
- **Permission surface:** none — this is a pure lifecycle/startup concern with no policy semantics.
- **Affected file:** `src/index.ts` only (plus `AGENTS.md` docs).

The two handlers currently share these calls:

```typescript
runtimeContext = ctx;
refreshExtensionConfig(ctx);
permissionManager = createPermissionManagerForCwd(ctx.cwd);
invalidateAgentStartCache();
lastKnownActiveAgentName = getActiveAgentName(ctx);
startForwardedPermissionPolling(ctx);
logResolvedConfigPaths();
```

Handler 1 additionally includes:

```typescript
if (event.reason === "reload") {
  writeDebugLog("lifecycle.reload", {
    triggeredBy: "session_start",
    reason: event.reason,
    cwd: ctx.cwd,
  });
}
```

Handler 2 has no unique logic.

## Design Overview

Delete the second `pi.on("session_start", ...)` block entirely.
The first handler already contains every statement from the second plus the reload branch — no merging of logic is needed, only deletion of the duplicate.

No types, schemas, or config surfaces change.

## Module-Level Changes

| File           | Change                                                                           |
| -------------- | -------------------------------------------------------------------------------- |
| `src/index.ts` | Remove the second `session_start` handler (currently lines ~1584–1592).          |
| `AGENTS.md`    | Remove the "Runtime Caveats" section that documents the dual-handler workaround. |

## TDD Order

1. **Red → Green:** add a test (or manual verification script) that asserts `session_start` side effects run exactly once per event.
   Surface: integration/event lifecycle.
   Commit: `test: verify session_start side effects run once`

2. **Green → Refactor:** delete the duplicate handler in `src/index.ts`.
   Commit: `fix: consolidate duplicate session_start handlers (#13)`

3. **Docs:** remove the "Runtime Caveats" section from `AGENTS.md`.
   Commit: `docs: remove dual-handler caveat from AGENTS.md (#13)`

## Risks and Mitigations

| Risk                                              | Mitigation                                                                                                                                                                                       |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Could this silently weaken a permission?          | No — no permission decisions are made in the `session_start` handler; it only initialises the `PermissionManager` and caches. Running setup once is strictly more correct than running it twice. |
| Removing the wrong handler loses the reload log   | The plan explicitly keeps handler 1 (which contains the reload branch) and deletes handler 2 (which is a strict subset). Review the diff to confirm.                                             |
| Future contributors re-introduce a second handler | The `AGENTS.md` caveat removal eliminates the "keep both in sync" instruction, so there is no longer guidance that implies two handlers are expected.                                            |

## Open Questions

- **Extract a named helper?**
  If future issues add more `session_start` work, extracting `initializeSession(event, ctx)` would improve readability.
  Defer unless the single handler grows beyond ~15 lines.
