# Phase 9: Timing Profiles - Context

**Gathered:** 2026-04-13
**Status:** Ready for planning

<domain>
## Phase Boundary

Per-project named timing profiles storing capture timing parameters (interval_ms, max_frames, duration_ms, jpeg_quality) and diagnostic flags. Agents define timing presets once and reference them by name in future `start_capture` calls. New MCP tools: `save_timing_profile`, `list_timing_profiles`, `delete_timing_profile`. Profiles persisted to the same project-local JSON file as screenshot profiles (under the `"timing"` top-level key).

</domain>

<decisions>
## Implementation Decisions

### Profile Storage (carried from Phase 8)
- **D-01:** Timing profiles stored in the same JSON file as screenshot profiles, under the `"timing"` top-level key (`{ "screenshot": { ... }, "timing": { ... } }`). File path from `SCREEN_TIMELAPSE_PROFILES_PATH` env var, defaulting to `.screen-timelapse/profiles.json`.
- **D-02:** Save with existing name overwrites silently (same as screenshot profiles).
- **D-03:** Profile names case-insensitive, slugified for storage key, display name preserved in `display_name` field (same as screenshot profiles).

### Profile Contents
- **D-04:** A timing profile stores: `name` (string key), `display_name` (original casing), `interval_ms` (number, min 100), `max_frames` (number, min 1, max 50), `duration_ms` (optional number, min 100), `jpeg_quality` (number, 1-100, default 80), `delta_highlight` (boolean, default false), `compress_idle` (boolean, default false), `gif_export` (boolean, default false), `description` (optional string), `created_at` (ISO timestamp), `updated_at` (ISO timestamp).
- **D-05:** Diagnostic flags (`delta_highlight`, `compress_idle`, `gif_export`) are included in timing profiles because they control _how_ a capture session runs, not _what_ it captures. An agent creating a "debug-flicker" preset naturally wants delta highlighting baked in. These flags are optional and default to false — a pure timing-only profile just omits them.
- **D-06:** All timing parameters are optional in a profile. A profile can store just `interval_ms` and `gif_export: true`, and the remaining params fall back to `start_capture` defaults at resolution time. This enables partial presets like "fast" (just interval) or "gif-debug" (just gif + delta flags).

### Tool Interface Design
- **D-07:** Three new MCP tools mirroring the Phase 8 pattern:
  - `save_timing_profile` — upsert a named timing profile. Required: `name`. Optional: `interval_ms`, `max_frames`, `duration_ms`, `jpeg_quality`, `delta_highlight`, `compress_idle`, `gif_export`, `description`. Returns the saved profile object.
  - `list_timing_profiles` — list all saved timing profiles. No required params. Returns array of profile objects with name, parameter summary, description, and timestamps.
  - `delete_timing_profile` — delete by name. Required: `name`. Returns success/not-found status.
- **D-08:** `save_timing_profile` accepts the same parameter names as `start_capture` (snake_case: `interval_ms`, `max_frames`, `duration_ms`, `jpeg_quality`, `delta_highlight`, `compress_idle`, `gif_export`). Zero translation between tools.
- **D-09:** Validation: `save_timing_profile` validates ranges match `start_capture` constraints (interval_ms >= 100, max_frames 1-50, jpeg_quality 1-100, duration_ms >= 100). A profile with zero timing parameters is valid (description-only or flags-only profile).

### Profile Resolution (start_capture integration)
- **D-10:** `start_capture` gains an optional `timing_profile` parameter (string). When provided, the tool loads the named profile and uses its timing/diagnostic parameters as the base. Inline parameters override the profile (same merge semantics as screenshot profiles — Phase 8 D-10/D-11).
- **D-11:** Both `screenshot_profile` and `timing_profile` can be specified together. Resolution order: timing profile base → screenshot profile base → inline params override. This lets agents say "use my 'sidebar' screenshot profile with 'fast-scan' timing."
- **D-12:** If the named timing profile doesn't exist, `start_capture` returns a structured error immediately (no capture attempted). Error includes list of available timing profile names.

### Preset/Template Profiles
- **D-13:** The system ships with built-in timing presets that are available without any prior `save_timing_profile` call. These are NOT persisted to the user's profiles file — they're hardcoded defaults:
  - `"quick-glance"` — `interval_ms: 500, max_frames: 6` — fast 3-second snapshot burst for checking if something is happening
  - `"steady-watch"` — `interval_ms: 2000, max_frames: 20, duration_ms: 40000` — 40-second watch at 2s intervals for observing gradual changes
  - `"debug-flicker"` — `interval_ms: 200, max_frames: 30, delta_highlight: true` — rapid capture with delta highlighting for diagnosing visual flicker
  - `"slow-monitor"` — `interval_ms: 5000, max_frames: 50, duration_ms: 300000, compress_idle: true` — 5-minute idle-compressed monitor for long-running processes
- **D-14:** Built-in presets are listed alongside user profiles in `list_timing_profiles` output, tagged with `"builtin": true` so agents can distinguish them. User profiles can shadow built-in names — if a user saves a profile named "quick-glance", their version takes priority.
- **D-15:** Built-in presets make the tool immediately useful without setup. An agent's first capture can be `start_capture({ target: "desktop", timing_profile: "quick-glance" })` with zero prior configuration.

### Additional Agent-Power Features
- **D-16:** `save_timing_profile` supports `capture_from_current` mode (same as Phase 8 D-13): if `source_session` is provided, timing parameters are auto-populated from that session's config. Agent says "save the timing I just used as a profile."
- **D-17:** `list_timing_profiles` returns a `parameter_summary` string per profile — a human-readable one-liner like "every 500ms, max 6 frames" or "every 2s for 40s, idle-compressed". Helps agents pick profiles without parsing raw numbers.

### Claude's Discretion
- Internal JSON structure and field ordering
- Error message wording
- Whether built-in presets are defined in a separate module or inline
- `list_timing_profiles` sort order (alphabetical, recent-first, builtins-first — whatever reads best)
- Whether to create a shared `ProfileManager` base class or keep screenshot/timing profile logic in separate modules (code organization)

</decisions>

<canonical_refs>
## Canonical References

**Downstream agents MUST read these before planning or implementing.**

No external specs — requirements fully captured in decisions above.

### Codebase References
- `src/types.ts` — `CaptureConfig` interface defines timing parameters (`intervalMs`, `maxFrames`, `durationMs`, `jpegQuality`) and diagnostic flags (`deltaHighlight`, `compressIdle`, `gifExport`); `StartCaptureInputSchema` defines snake_case MCP tool params with validation ranges
- `src/server.ts` — Existing `registerTool` pattern; `start_capture` tool to extend with `timing_profile` param (alongside Phase 8's `screenshot_profile` param)
- `src/capture/scheduler.ts` — Uses `maxFrames` and `durationMs` for capture limits; timing profile values feed into this

### Phase 8 Cross-References
- `.planning/phases/08-screenshot-profiles/08-CONTEXT.md` — Storage model (D-01, D-02), naming conventions (D-06), overwrite semantics (D-03), `capture_from_current` pattern (D-13), merge semantics (D-10, D-11)

</canonical_refs>

<code_context>
## Existing Code Insights

### Reusable Assets
- `CaptureConfig` in `types.ts`: Timing fields (`intervalMs`, `maxFrames`, `durationMs`, `jpegQuality`) and diagnostic flags (`deltaHighlight`, `compressIdle`, `gifExport`) already defined — profile storage mirrors this structure.
- `StartCaptureInputSchema` in `types.ts`: Zod schema with snake_case names and validation ranges — timing profile validation should match exactly.
- Phase 8's profile storage module (once built): File I/O, slugification, name resolution — all reusable for timing profiles since they share the same JSON file.

### Established Patterns
- **Zod schemas for tool input**: All tools use zod. New timing profile tools follow the same pattern.
- **Snake_case tool params**: MCP interface uses `interval_ms`, `max_frames`, etc. Timing profile tools must match.
- **SessionManager singleton**: Profile storage follows same singleton pattern.

### Integration Points
- `start_capture` tool in `server.ts`: Needs `timing_profile` optional param added (alongside Phase 8's `screenshot_profile` param — both land in Phase 10)
- Profile JSON file: Timing profiles share the file with screenshot profiles under `"timing"` key
- Phase 8's profile storage module: Timing profiles reuse the same file I/O layer

</code_context>

<specifics>
## Specific Ideas

- **User directive for all v1.2 phases:** Full creative discretion granted — Claude should ideate, decide, and introduce features that maximize tool power and flexibility for agent consumers.
- **Built-in presets rationale:** Agents often don't know what timing parameters to use. Presets like "quick-glance" and "debug-flicker" give agents a vocabulary for common capture scenarios, making the tool immediately useful without trial-and-error parameter tuning.

</specifics>

<deferred>
## Deferred Ideas

- **Profile composition/inheritance**: A timing profile that extends another (e.g., "debug-flicker-gif" extends "debug-flicker" + adds gif_export). Over-engineering — agents can just save a new profile with the desired combination.
- **Profile validation against active monitors**: Checking if timing params are realistic for the system's capabilities (e.g., 100ms interval on a slow machine). Better handled at capture time, not profile save time.

None — discussion stayed within phase scope.

</deferred>

---

*Phase: 09-timing-profiles*
*Context gathered: 2026-04-13*
