Problem
pact-plugin/hooks/session_init.py is currently 1,142 lines, well above the 600-line file-size threshold. The breach is long-standing (predates PR #603), but each feature that touches the SessionStart directive surface (most recently the inbox-wake Tier-0 Arm directive in cycle 8) marginally worsens it.
Why It Matters
session_init.py is the central SessionStart hook — it owns:
- Project memory bootstrap (CLAUDE.md location resolution, managed structure migration)
- Pinned-context staleness checks
- Variable substitution context delivery (team_name / session_dir / plugin_root)
- Tier-0 directive emission (orchestrator routing, post-compaction recovery, watch-inbox arm-on-resume)
- pact-session-context.json maintenance
- Working-memory cleanup coordination
Every concern is independently load-bearing. Touching one risks regressions in the others, and the file is already past the point where a fresh contributor can reason about it as a single unit.
Constraints
- Tier-0 directive emit ordering matters. Any extraction MUST preserve the additionalContext concatenation order, since the LLM reads top-down and earlier directives establish framing for later ones.
- No behavior change. This is a pure refactor; existing tests must pass unchanged (or change only in import paths).
- Read-tracker budget awareness. session_init.py contributes to the 5-slot Tier-2 budget; extracted modules should be in
hooks/shared/ so they're not separately loaded.
Suggested Approach
Decompose by concern into hooks/session_init_modules/:
| Module |
Concern |
Approx Lines |
claude_md_bootstrap.py |
Location resolution, managed structure migration, file creation |
~250 |
pinned_context.py |
Staleness check, retrieval, formatting |
~150 |
variable_substitution.py |
team_name / session_dir / plugin_root resolution + delivery |
~120 |
tier0_directives.py |
Orchestrator routing, post-compaction recovery, watch-inbox arm |
~180 |
session_context_json.py |
pact-session-context.json read/write |
~100 |
session_init.py (entry) |
Stdin parsing, dispatch, additionalContext concat |
~150 |
Top-level session_init.py becomes a thin orchestrator that calls each concern in order and joins the additionalContext output.
Acceptance
Out of Scope
Origin
Surfaced repeatedly during PR #603 review cycles (most recently cycle 6 + cycle 8 closeout, 2026-04-30). Not in scope of any inbox-wake PR but blocks future features that need to touch SessionStart directive emission.
Problem
pact-plugin/hooks/session_init.pyis currently 1,142 lines, well above the 600-line file-size threshold. The breach is long-standing (predates PR #603), but each feature that touches the SessionStart directive surface (most recently the inbox-wake Tier-0 Arm directive in cycle 8) marginally worsens it.Why It Matters
session_init.pyis the central SessionStart hook — it owns:Every concern is independently load-bearing. Touching one risks regressions in the others, and the file is already past the point where a fresh contributor can reason about it as a single unit.
Constraints
hooks/shared/so they're not separately loaded.Suggested Approach
Decompose by concern into
hooks/session_init_modules/:claude_md_bootstrap.pypinned_context.pyvariable_substitution.pytier0_directives.pysession_context_json.pysession_init.py(entry)Top-level
session_init.pybecomes a thin orchestrator that calls each concern in order and joins the additionalContext output.Acceptance
session_init.py≤ 200 lines, focused on stdin → dispatch → emitOut of Scope
test_inbox_wake_lifecycle_emitter.pyis also at 673 lines — flag for a separate split (recommend file-per-finding-cluster).skills/orchestration/SKILL.md610-line breach (the load-bearing skill body) is a separate concern, blocked on Tier-1 durability tradeoffs (Post-boundary bootstrap re-invocation: unconditional SessionStart directive + hook consolidation #444).Origin
Surfaced repeatedly during PR #603 review cycles (most recently cycle 6 + cycle 8 closeout, 2026-04-30). Not in scope of any inbox-wake PR but blocks future features that need to touch SessionStart directive emission.