# 0.39.x Creature Comforts

**Status**: Drafted 2026-05-25 — the workweek polish cycle following the 0.39.0 public release.
**Owner**: Rosson + pod-leader
**Window**: Post-0.39.0 ship through the end of the workweek (~5 working days)
**Ships as**: 0.39.1, 0.39.2, ... as individual items land. Could roll into 0.39.5 or similar if items batch up.
**Goal**: address creature comforts users have been requesting; validate the new infrastructure under real use; ship small wins fast.

---

## tl;dr

After the 0.39.0 public release (post-Phase-2.5d), the workweek shifts focus from architecture cleanup to user-facing polish. **Seven** items requested by users, ranging from small UI defaults to harder reliability work. No new architectural primitives — each item is a focused fix or feature on the now-stable 0.39.0 foundation.

The 0.39.x cycle is explicitly NOT the 0.40.0 cycle (Phase 2.6 + Phase 3 — tunnel decision + contract hardening). Those resume after the workweek when the team has bandwidth for the bigger architectural moves.

**Special note on items #5 + #7**: together they reshape how AI agents discover K2SO. Item #5 makes the auto-written AGENT.md / SKILL.md system optional (less file management forced on users); item #7 publishes a standalone K2SO Skill that agents can self-load on demand. Even if a user disables AGENT.md, agents can still learn K2SO via the published skill. Two independent discovery paths, no forced file management.

---

## Items (7)

### 1. Custom agents no longer pinned by default — **small**

**User pain**: When a user picks Custom Agent mode for a workspace, K2SO auto-pins the agent's chat in the tab bar. Some users don't want that pin — it clutters the tab bar with chats they're not actively using.

**Scope**:
- Change the default behavior in workspace creation / agent-mode-switch flow so Custom Agent doesn't auto-pin a chat
- User can still manually pin from the tab bar context menu / Settings
- Existing workspaces with already-pinned Custom Agent chats stay pinned (no migration to unpin)

**Implementation surface**:
- Likely in `crates/k2so-core/src/agents/commands.rs::create` (or wherever agent-mode-set logic lives — post-Phase-2.5d this moves to `workspace/agent.rs`)
- Or in the React layer where the tab bar's pinned-chat list is initialized for new workspaces
- One-line behavior change + maybe a settings flag if we want it user-toggleable

**Tests**:
- Create a new workspace in Custom Agent mode; verify no pinned chat is auto-created
- Existing workspaces: open a workspace that had a Custom Agent + pinned chat pre-upgrade; verify the pin persists

**Out of scope**: changing default pinning behavior for OTHER agent modes (K2SO Agent, Workspace Manager). This item is custom-only.

---

### 2. Option to pin HTML files to be rendered — **medium**

**User pain**: Users want to pin HTML files (dashboards, generated reports, documentation) in their workspace and have K2SO render them inline rather than just showing the source.

**Scope**:
- Add ability to pin an HTML file from the file tree (right-click → "Pin as rendered HTML")
- Pinned HTML files render as an iframe or sandboxed webview in the tab bar
- File watcher updates the rendered view when the source HTML changes
- User can unpin via context menu
- Persistence: pinned HTML files stored in workspace settings (per-workspace list)

**Implementation surface**:
- New tab type in renderer: `PinnedHtmlPane`
- File watcher subscription in the daemon (or use existing fs watcher infrastructure)
- Storage: probably extend `workspace_tab_sessions` table or add a `pinned_html_files` column to `projects`
- New Tauri command: `pin_html_file(project_path, file_path)` + `unpin_html_file(...)`
- Sandboxing: iframe with `sandbox="allow-scripts"` minimum; consider whether to allow same-origin, network, etc.

**Tests**:
- Pin a simple `<h1>Hello</h1>` file → verify it renders
- Edit the file externally → verify the rendered view updates
- Unpin → verify it's removed from the tab bar
- Restart the app → verify pinned HTML survives restart

**Security note**: rendering arbitrary HTML from the workspace is a real attack surface. Document the threat model + use a sandboxed iframe. Don't allow privileged Tauri APIs from the iframe content.

**Out of scope**: rendering Markdown, PDF, or other non-HTML formats (those already have viewers); arbitrary URL pinning (only local file paths).

---

### 3. Pinned chat + pinned inbox shown by default even when agent mode is off — **small**

**User pain**: When a workspace has `agent_mode = 'off'`, the pinned chat tab and pinned inbox tab might be hidden. Users want quick access to those regardless of agent mode — even an "off" workspace can have prior chat history they want to reference + an inbox that might have items from other workspaces (cross-workspace `msg --inbox` delivery).

**Scope**:
- Pinned chat tab: render at the top of the tab bar even when `agent_mode === 'off'`. Clicking spawns a fresh Claude session (or whatever the workspace's default agent CLI tool is) if no session exists; otherwise resumes.
- Pinned inbox tab: render at the top of the tab bar even when `agent_mode === 'off'`. Shows whatever's in `.k2so/inbox/`.
- This DIFFERS from Phase 2.5b's Skills section work — that was the Settings page rendering Skills regardless of mode. This is the tab bar rendering pinned chat + inbox regardless of mode.

**Implementation surface**:
- React layer: the `TabBar.tsx` component (or whatever renders the tab bar)
- Likely a conditional render that currently includes `agentMode !== 'off'` — relax it
- Probably need to update `tabs.ts` store's initialization logic too

**Tests**:
- Set a workspace to `agent_mode: off` → verify pinned chat + pinned inbox tabs visible
- Click pinned chat → verify Claude (or default agent) spawns
- Click pinned inbox → verify inbox renders with content
- Switch to other modes → verify behavior stays consistent

**Out of scope**: changing the OTHER tabs that are mode-gated (the workspace manager block in Settings, etc.). This is tab-bar specific.

---

### 4. Terminal session resilience + dormancy notifications — **hard**

**User pain**: Active Cmd+T terminal sessions can get into bad states (PTY hang, network/SSH timeout, agent goes idle for too long). Users want:
- Better resilience so sessions don't die unnecessarily
- Notifications when a session has gone dormant (no output / no activity for X minutes)

**Scope** (split into sub-items):

**4a. Resilience for active terminal sessions**:
- Audit current PTY lifecycle in `crates/k2so-core/src/terminal/daemon_pty.rs` and the v2 session map (`crates/k2so-daemon/src/v2_session_map.rs`)
- Identify failure modes: PTY EOF, signal interrupts, daemon restart, network disconnect, OOM
- Add reconnect / restart logic where appropriate (today's `keepDaemonOnQuit` covers the Tauri-quit case; need broader coverage)
- Surface failure types to the renderer so the UI can offer "Reconnect" / "Restart this session" affordances

**4b. Notifications on dormant sessions**:
- Track "last output" or "last user input" timestamp per active terminal session
- Configurable threshold (default: 30 min? 1 hour? per-user setting)
- When threshold exceeded, emit a notification:
  - Desktop notification (via Tauri's notification API)
  - UI badge / indicator on the dormant tab
- User can dismiss / configure threshold / disable per-session

**Implementation surface**:
- Daemon-side: add idle-time tracking to v2 session map; add a daemon-events emit for "session dormant" when threshold crossed
- Renderer: subscribe to dormant events; show notification + tab badge
- Settings: new section for "Idle timeout" / "Dormancy notifications" preferences

**Tests**:
- Spawn a terminal, run `sleep 3600`, verify no dormancy notification within the active window
- Spawn a terminal, leave idle for X+1 minutes (mock the timer), verify notification fires
- Force-kill a PTY process; verify the resilience layer offers a reconnect path

**Why hard**: PTY lifecycle is the architectural keystone (per the Phase 2.5 smoke checklist Unit 3 — "Terminal PTY survives Tauri quit" was the critical test). Touching this code carries regression risk. Plus the cross-cutting notification system is real work.

**Out of scope**: SSH-specific reconnect logic (treat SSH sessions like any other terminal); auto-restart of crashed processes (only the PTY itself, not what's running inside it).

---

### 5. Make the canonical AGENT.md feature optional — **medium, but lots of thinking**

**User pain**: K2SO writes a canonical AGENT.md (or SKILL.md post-Phase-2.1) into each workspace's `.k2so/` tree, regenerates it on every wake, and fans it out to harness-discovery files (`./CLAUDE.md`, `./AGENTS.md`, `./AGENTS.md`, `./.cursor/rules/`, `./.gemini/...`, etc.). The auto-regen + harness fan-out workflow is intimidating to new users — they see K2SO writing files into their workspace and worry about overwriting their existing instructions, conflicts with `.gitignore`, or the magic of "what is K2SO doing?"

**Scope** (heavy on design):

This needs a **design conversation** before implementation. Key questions:
- Should the auto-regen be **opt-in** (new workspaces default to OFF; user enables in Settings if they want it) OR **opt-out** (default ON; user disables if they don't want it)?
- If opt-in, what fallback context does the agent get if there's no SKILL.md? (Probably just the workspace name + `PROJECT.md` if present.)
- Should the harness fan-out be **separately togglable** from the SKILL.md regen itself? (User might want SKILL.md generated but NOT fanned out to CLAUDE.md / AGENTS.md / etc.)
- What's the UX for surfacing "your workspace has these files; K2SO can manage them — do you want to?" — a first-launch wizard? A Settings panel? Both?
- If the user disables K2SO's SKILL.md management, what happens to existing managed files? (Trash them via safe_delete? Leave them?)

**Implementation surface (after design)**:
- New per-workspace setting: `skill_md_managed: bool` (and probably `harness_fanout_enabled: bool`)
- Conditionalize the regen calls in `workspace/skill_writer.rs` (post-Phase-2.5d) based on the setting
- UI: new section in workspace settings + onboarding step
- Migration: existing workspaces default to current behavior (managed = true) so we don't break anyone

**Tests**:
- Disable `skill_md_managed` → verify SKILL.md regen doesn't fire
- Disable `harness_fanout_enabled` while keeping skill_md_managed → verify SKILL.md still written but CLAUDE.md etc. NOT fanned out
- Re-enable → verify files get regenerated next wake

**Why "lots of thinking"**: the SKILL.md / canonical AGENT.md system is core to how K2SO bridges to CLI LLM tools. Making it optional changes how users interact with the product. Need to think through how the agent operates when SKILL.md is absent, what UX surfaces the choice clearly, and how to gracefully handle the off state.

**Out of scope**: removing the SKILL.md system entirely (only making it optional); changing what GOES INTO SKILL.md when it IS enabled.

---

### 7. Publish a K2SO Skill that platforms can self-load — **medium, complements #5**

**User pain**: Even if the canonical AGENT.md / SKILL.md system (item #5) is made optional, agents (Claude, Cursor, Codex, Gemini CLI, etc.) still need to know HOW to interact with K2SO — how to read the inbox, how to checkin, how to send cross-workspace messages, how to compose work items, etc. Today's discovery mechanism is the AGENT.md fanout itself; if a user disables that, agents lose discoverability.

**The play**: distribute a **K2SO Skill** — a standalone document that describes the K2SO surface in a format platforms can self-install / self-load. Claude has "Skills" (Claude's pluggable capability system); other platforms (Cursor, Codex, Gemini CLI) have analogous extension points. The K2SO Skill lives independently of the per-workspace AGENT.md and can be discovered/loaded ON DEMAND by an agent that wants to interact with K2SO.

**Why this is the right play**: complements #5 perfectly. AGENT.md becomes optional (no auto-write into workspace files); agents still learn K2SO via the published Skill they can load themselves. Two independent discovery paths, no forced file management.

**Scope**:
- **Author the K2SO Skill content**: a markdown / structured doc that covers the K2SO CLI surface (inbox, msg, checkin, workspace verbs, skills, heartbeat — the daily-tier verbs from Phase 2.1's A25 taxonomy). Include code examples, mental models (workspace==agent, inbox-as-email, skills-as-docs), and idiomatic patterns.
- **Choose the format**: most likely a Claude Skills-compatible format (markdown + frontmatter) so Claude users get first-class support. Document how Cursor / Gemini CLI / Codex users can adapt it. ChatGPT / OpenAI Custom GPT format as a stretch.
- **Decide the distribution mechanism**:
  - **GitHub** — public repo for the skill at e.g. `github.com/Alakazam-211/k2so-skill` (or similar)
  - **K2SO website / k2.dev domain** — a documentation page that explains how to install the skill in each platform
  - **Embedded in the .app** — accessible via a Settings panel "Copy K2SO Skill to clipboard" or "Open install instructions for [platform]"
  - **Probably ALL THREE** — different users find different paths
- **Tag the skill version** — agents loading the skill should know what K2SO version it documents
- **Surface in product**: a Settings → Integrations → "K2SO Skill" section that points at the skill + install instructions per platform

**Implementation surface**:
- New markdown source at `.k2so/skill-source/k2so-skill.md` (or a dedicated repo)
- Generator script that bakes the skill into a known shipped location (maybe `target/release/bundle/macos/K2SO.app/Contents/Resources/k2so-skill.md`)
- Settings UI section in React renderer
- Tauri command to copy skill content to clipboard / open install URL
- Documentation / website page

**Tests**:
- Load the K2SO Skill in a fresh Claude session (no AGENT.md present in the workspace); verify Claude can answer basic K2SO questions ("how do I message another workspace?") correctly
- Load in Cursor / Gemini / Codex sessions; verify equivalent behavior
- Test on a workspace with AGENT.md DISABLED (item #5) — verify the skill is the agent's primary discovery path

**Open design questions**:
- Should the skill be auto-installed when an agent first connects to a K2SO workspace? Or always opt-in?
- Should the skill content live in the same repo as K2SO (versioned together) or in a separate skill repo (independent release cycle)?
- For platforms without a "skill" concept, what's the fallback? (E.g., a generated `.cursor/rules/k2so.mdc` file that's smaller than the canonical AGENT.md but covers the K2SO basics)
- How does the skill stay in sync with K2SO version changes? Manual updates? CI-generated from the daily-tier verb help text?

**Why medium**: content authoring is real work (probably 1-2 days of writing + iteration). Distribution mechanism + Settings UI is straightforward. Per-platform adaptation might surface format gotchas.

**Out of scope**:
- Building a custom skill server / marketplace — use existing platform mechanisms
- Pre-installing the skill into users' Claude / Cursor accounts — they install it themselves
- Versioning protocol for skill backwards-compat (defer to Phase 3 if needed)

---

### 6. Verify K2SO works well without git enabled per workspace — **untested**

**User pain**: K2SO assumes workspaces have git initialized. Some users want to use K2SO with non-git directories (e.g., a documentation folder, a project that uses Mercurial, or a directory that's intentionally not version-controlled).

**Scope**:
- **Investigation first** (likely a research subagent pass):
  - Grep daemon + core for `git2` / `Repository::open` / `git status` / `is_git_repo` calls
  - Identify which code paths assume a git repo exists
  - List which features actually need git (worktrees, commit, diff) vs which don't (terminal, inbox, skills, heartbeats, etc.)
- **Then implementation**:
  - Gracefully handle "not a git repo" — operations that need git should error with a clear message; operations that don't need git should work as if git wasn't a concept
  - Settings UI / onboarding: detect that a workspace isn't git-initialized and either offer "Initialize git here" OR set per-workspace flag "non-git workspace"
  - Worktree-related features (delegate, review queue) need to gracefully no-op or be hidden when git is absent

**Implementation surface**:
- `crates/k2so-core/src/git/` or wherever git operations live
- Settings: per-workspace `git_enabled: bool` (or detect from filesystem)
- UI: hide / disable git-dependent affordances in non-git workspaces

**Tests**:
- Create a workspace in a non-git directory → verify K2SO works for the non-git features
- Try to use a git-dependent feature (worktrees, commit) → verify clear error message
- Initialize git in that workspace → verify K2SO picks it up + git features become available

**Why "never tested"**: K2SO has always been used in git workspaces. No one knows how many code paths assume git. The investigation will reveal scope.

**Out of scope**: supporting Mercurial / SVN / other VCS specifically; this is just about gracefully handling "no VCS at all."

---

## Suggested sequencing

The items aren't strictly sequential. Recommended order based on size, dependency, and #5/#7 coupling:

```
Day 1-2 (start with small wins):
  - Item 1: Custom agents no longer pinned by default
  - Item 3: Pinned chat + inbox visible when agent mode is off
  - Item 6 investigation (research subagent to map git dependencies)
  - Item 7 content draft started (skill authoring is the long pole — start early)

Day 2-3 (medium items):
  - Item 5 design conversation (user + pod-leader decide questions)
  - Item 7 content review + format finalization
  - Item 5 + #7 ship together (they complement each other; ship as a coordinated 0.39.x release)
  - Item 6 implementation (after investigation; scope clarifies)
  - Item 2: Pin HTML files (parallelizable with 5/6/7)

Day 4-5 (hard item):
  - Item 4a: Terminal session resilience
  - Item 4b: Dormancy notifications
  - Final smoke pass on 0.39.x cumulative changes
```

Items can ship individually (0.39.1, 0.39.2, etc.) or batch into 0.39.5 if multiple complete together. **Items #5 and #7 should ship together** if possible — they're complementary AGENT.md / skill-discovery work.

---

## Tests + validation per item

Each item lands its own commit(s) and includes:
- Per-item unit/integration tests as listed above
- Manual smoke through the dev or production .app
- No regression of existing tests: `cargo test --release --workspace`, `bun run typecheck`, `bash tests/cli/*.sh` all stay at baseline (whatever 0.39.0 final baseline is) or grow.

**Release notes**: each item gets a one-line entry in `release-notes-0.39.<N>.md`.

---

## Hard rules (CRITICAL — same as other phases)

1. **Build only from worktree's `target/`** — no production touches.
2. **`safe_delete::trash` if you delete a folder** — per memory `feedback_recycle_bin_tests`.
3. **No `--no-verify`, `--amend`, `Co-Authored-By` lines.** Per memory `feedback_commit_attribution`.
4. **Do NOT manually touch version strings** in `package.json`, `tauri.conf.json`, or any `Cargo.toml`. Per memory `feedback_no_version_bump` — the release script handles version bumps in lockstep.
5. **Daemon-first** — logic in `k2so-core`, thin wrappers in CLI/Tauri. Per memory `feedback_daemon_first`.
6. **Tests fail loudly.** Per memory `feedback_test_discipline`.
7. **Inline POST method-gate** on any new daemon POST routes. Per memory `feedback_post_only_route_guards`.

---

## Definition of done (cycle)

The 0.39.x cycle is "done" when:
1. ✅ All 7 items either ship OR are explicitly deferred to 0.40.x with a Phase-3-or-later rationale
2. ✅ Each shipped item has tests, release notes, and a smoke pass through the production .app
3. ✅ No regressions of the 0.39.0 baselines (cargo, typecheck, shell tests)
4. ✅ The Secure Tunnel Monetization Roadmap is updated to reflect what shipped vs deferred

After 0.39.x closes, **Phase 2.6 (tunnel decision) launches** — the start of the 0.40.x cycle.

---

## Out of scope (explicit non-goals for 0.39.x)

- **Anything in Phase 2.6 / Phase 3 territory** — tunnel-provider decision, OpenAPI codegen, Mobile Companion contract update, K2SO Connect, typed router, etc. Those wait for 0.40.x.
- **Major refactors** — no more module reorgs (Phase 2.5d closes that chapter).
- **New monetization plumbing** — Stripe, billing, subdomain provisioning all wait for Phase 4 (post-0.40.0).
- **K2SO → K2 product rebrand** — `k2.dev` is owned but trademark posture isn't cleared. Defer until trademark search lands.
- **Net-new agent integration features** beyond what's listed here. The 6 items are the cycle.

---

## References

- `.k2so/prds/secure-tunnel-monetization-roadmap.md` — master roadmap; this PRD is the 0.39.x cycle scope
- `.k2so/prds/phase-2.5d-workspace-commands-split.md` — Phase 2.5d (precedes 0.39.0 release)
- `.k2so/prds/phase-2.6-tunnel-decision.md` — Phase 2.6 (launches AFTER 0.39.x closes)
- Memory `feedback_no_version_bump` — release script owns version bumps
- Memory `reference_build_sign_notarize` — release ceremony workflow
- User direction (2026-05-25, post-Phase-2.5d-launch): 6-item creature comforts list for the workweek
