{
  "name": "@ai-setting/roy-plugin-task-show",
  "version": "2.6.6",
  "type": "tool-plugin",
  "description": "v2.6.3: Mermaid node label now shows the FULL operation title (Task #3145). Previously `getPhaseLabel()` rendered `'⚙️ Phase 1: PASS'` for `'Phase 1 PASS: 调研现状'` because `extractPhaseInfo` regex stopped at the first `:` / `完成` / `pass` / `—` token, silently dropping the `: 调研现状` tail. v2.6.3 uses the full `op.title` (escape + truncate to keep CJK and stay under Mermaid's 60-char per-label budget) when `resolvePhaseId` cannot map the captured name to a canonical phase id. Canonical-phase titles (e.g. `Phase 3: Plan`) still use the friendly `<emoji> Phase N: <name><br/><description>` format unchanged. Mirror applied to client `public/app.js` `getPhaseLabelClient`. 8 new regression tests in `test/mermaid-full-title-v263-3145.test.ts` all PASS (T1 `'Phase 1 PASS: 调研现状'` keeps `: 调研现状`; T2 non-canonical `Phase 2 调研: 实施修复` keeps the CJK tail; T3 `'Phase 3 — 调研现状'` survives em-dash; T4 60-char truncation cap with ellipsis; T5 canonical-phase format unchanged; T6/T6b integration: rendered diagram embeds the full title; T7 server+client parity). v2.6.2: Mermaid pre-task/post-task bucket chunking — fixes 'Maximum text size in diagram exceeded' for Task #3139 (281 tool calls, no operation data, all tools in pre-task bucket). v2.5.20 (Task #3044) raised mermaid.maxTextSize 50,000 → 200,000 chars as a stop-gap; v2.6.2 is the architectural fix. `renderBucketChunks` in src/task-detail-mermaid.ts (mirror in public/app.js) splits any bucket with > MAX_TOOLS_PER_BUCKET_CHUNK=50 tools into ceil(N/50) sequential subgraphs (`pre_task_1`, `pre_task_2`, ...) connected by explicit `pre_task_1 --> pre_task_2` edges, and inside each chunk tools are chained `t1 --> t2 --> t3` so the flow is visible (the legacy single-subgraph render had no internal edges). Backward compatible: small buckets (≤ 50 tools) stay a single subgraph with no internal edges, byte-identical to v2.6.1 (existing snapshots / tests unchanged). Mermaid config maxTextSize also bumped 200,000 → 1,000,000 (5×) as defense-in-depth for the SSR-initial + client-rebuild path. 9 new tests in test/mermaid-bucket-chunking-3139.test.ts all PASS (constant contract, 281-tool split, small-bucket compat, inter-chunk edges, post-task symmetry, source-size sanity, label ranges, empty-bucket chain, click-callback preservation); 26 existing task-detail-mermaid tests + 18 mermaid-renderer tests still PASS. v2.6.1: Mermaid render-retry self-heal (Task #3129 follow-up). v2.6.0's 3-attempt retry loop replayed the SAME source string on every retry — if the source was half-built at attempt 1 (SSE applyTaskUpdate interleaving with task-operations.js polling), attempts 2-3 hit the same 'Syntax error in text' fallback. v2.6.1 makes `controller.update()` accept an OPTIONAL `getSourceForRetry` thunk and re-invokes it between attempts so each retry sees the freshest (operations, session) snapshot the caller's source-builder can assemble. `scheduleMermaidRender` (public/app.js) now passes the same thunk through, so the SSE/poll race that v2.6.0 fixed now also self-heals within a single render call. RENDER_RETRY_MAX bumped 3→5 with backoff 60ms→120ms to give the second path more time to settle. mount() keeps the original two-arg signature (SSR-stable source, no race). All 7 new retry-thunk tests pass (T1 self-heal, T2 v2.6.0 fallback, T3 first-try bypass, T4 same-source fidelity, T5 non-retryable bail, T6 thunk-throw, T7 mount signature). v2.6.0: Mermaid rendering race-condition fix (Task #3123 — `Syntax error in text` on Task detail pages). Two paths previously raced on the same `<div class=\"mermaid\">`: the SSE `applyTaskUpdate` handler (writes the latest session.toolCalls) and the `task-show:lifecycle-ops-loaded` listener (writes the latest operations from `/api/tasks/:id/operations`). Each path had its OWN `createMermaidController` instance, so two controllers ran concurrent `mermaid.render()` calls and a half-built source string landed mid-transition → 'Syntax error in text'. Fix has three parts: (1) a SINGLE shared `window.__mermaidController` singleton (both paths now `update()` the same instance, so the existing per-container token guard drops late results); (2) a per-container Promise-chain render queue (`window.scheduleMermaidRender(container, taskId, getSource)` where `getSource` is a thunk) so the (operations, session) snapshot is atomic by the time we hand it to the controller; (3) `mermaid-renderer.js#renderInternal` now retries `mermaid.render` up to 3× with jittered backoff (60-180ms+0-40ms) on `Syntax error in text` before giving up, so transient races self-heal without surfacing the error block. Backwards compatible: old bundles that don't include the lock helper fall through to the v2.5.x per-instance controller. Tested: all 135 mermaid/app-js tests pass, build + typecheck clean. v2.4.1: Mermaid zoom now supports click-and-drag pan (Task #2785). After zooming in, users can drag the diagram to view the surrounding canvas area. Implementation: per-container panState/dragState WeakMap (no global state leak); applyTransform(translate+scale) single-source-of-truth for the CSS transform; attachPanHandlers on pointerdown/move/up/cancel with setPointerCapture for off-element drags; pointer cursor switches to grab/grabbing with touch-action: none to prevent native scrolling; reset/zoomReset now also resets pan to (0,0). 14/14 new mermaid-pan tests pass, full suite 558/564 with 6 pre-existing failures unrelated to this commit. v2.4.0: Combines v2.3.0 Combines v2.3.0 (worktree-aware file-tree + unbounded Mermaid zoom, Task #2773) with the v2.3.0 mermaid placeholder expansion (Task #2771). Sidebar + endpoint scope git ls-files to session.context.worktree (fallback process.cwd()); Mermaid zoom-in is no longer capped at 3.0×; .mermaid placeholder is now min-height: 2400px and .mermaid-zoom-stage is min-width: 6400px / min-height: 2400px (5× base, via --mermaid-placeholder-multiplier CSS custom property) so dense diagrams get enough canvas to pan/zoom comfortably. v2.3.0: Worktree-aware file tree sidebar + unbounded Mermaid zoom-in. The file-tree sidebar (and /api/task/:id/file-tree endpoint) now scope git ls-files to session.context.worktree when the host (task:before.create / task:after.create payload) supplies a worktree path, so the sidebar shows the files the agent is actually editing instead of the plugin process cwd. New resolveWorktreePath helper in src/file-tree.ts returns session.context.worktree (trimmed, with empty/non-string guard) or falls back to process.cwd() for backward compatibility with pre-v2.3.0 hosts. TypeScript: TaskSession gains an optional context?: { worktree?: string } field. TaskShowServer exposes getCollector() so tests can seed sessions with context.worktree set. The Mermaid zoom toolbar (introduced in v2.0.8) no longer caps zoom-in at 3.0× — the ZOOM_MAX constant is REMOVED and clampZoom only enforces ZOOM_MIN=0.25, so dense diagrams remain readable on high-DPI monitors when the user wants to zoom way in. ZOOM_MIN stays in place so zoom-out still bottoms out before rendering a black screen. New tests: test/file-tree-worktree.test.ts (10 cases — resolveWorktreePath edges, SSR scope, endpoint scope, fallback), test/mermaid-zoom-unlimited.test.ts (8 cases — source guard, behaviour at 6×/10×/50×, lower-bound preserved), test/mermaid-placeholder-size.test.ts (7 cases — min-height/min-width 5× checks, transform-origin preserved, --mermaid-placeholder-multiplier hint). v2.3.0: Major visual overhaul of the per-task detail page — VS Code-style tool-call browser powered by Monaco Editor + LCS-based diff + project file tree with mermaid-driven navigation. The detail page now renders a 2-column layout: a sticky left sidebar with the project's git-tracked file tree (chevron-toggle directories, `is-affected` highlight for files touched by the current task), and a main column with the existing Mermaid + stats + toolcalls table + a new dedicated `<section id=\"tool-call-detail-panel\">` that hosts the LCS diff body + Monaco container for the currently-selected tool call. The legacy inline `<details class=\"diff-panel\">` (naive split-and-filter, prone to mis-tagging context lines) is replaced by `<ol class=\"diff-body\">` with proper added/removed/context markers driven by a real LCS dynamic-programming table (`computeDiff()` in `src/tool-call-detail.ts`). Tool calls with a file path get a Monaco Editor placeholder (`<div class=\"monaco-editor\" data-file-path=\"...\" data-language=\"...\">`) which the client-side `public/tool-call-detail.js` lazy-loads from `cdn.jsdelivr.net/npm/monaco-editor@0.45.0` the first time the user clicks a tool row. The Mermaid `__toolClick(toolId)` callback now drives THREE things: (a) the existing row scroll + highlight (preserved from v1.x), (b) the dedicated detail panel re-renders with the matching call, (c) the file-tree sidebar highlights the corresponding file (when `data-file-path` is present). New `GET /api/task/:id/file-tree` endpoint serves the git-tracked file list (`{ files: string[] }`) with a 30-second in-memory TTL + 8-entry FIFO bound. New modules: `src/file-tree.ts` (pure data layer: `buildFileTree / extractAffectedPaths / findNodeByPath / collectAllPaths / gitLsFiles / parseLsFiles`), `src/tool-call-detail.ts` (SSR + LCS diff + HTML escaping), `public/file-tree.js` (vanilla JS hydrator with chevron toggle + keyboard navigation + scrollIntoView), `public/tool-call-detail.js` (Monaco AMD loader + `__toolClick` wrapper + file-content fetch). New tests: `test/file-tree.test.ts` (21 cases — empty/single/nested/dedup/sort/depth/parseLsFiles/gitLsFiles), `test/tool-call-detail.test.ts` (22 cases — LCS diff edges, HTML escape, path aliases, summary stats), `test/tool-call-detail-server-integration.test.ts` (7 cases — SSR HTML contracts + endpoint), `test/tool-call-detail-jsdom.test.ts` (7 cases — client-side hydrators). v1.2.0: CSS context & packaged release hotfix. The plugin's public assets (notably `public/style.css`) and runtime adapters now correctly resolve relative to the installed package directory even when consumed via the published npm tarball. The session-scoped `TaskSessionStore` now preserves the full host session context (parent-child task links, plugin-handle id, env scope) across render cycles — previously the session was collapsed to its `sessionId` on first load and never refreshed, so the home page lost the 「session ancestors」 chain and external tasks from outside the current session silently disappeared from the tree. Adds `src/task-metadata.ts` as the single source of truth for the public `Task` shape exposed by `/api/tasks` + `/api/tasks/:id`, including the v1.0.0+ `processDescription` field, and re-exports it through the CLI adapters (`cli-tasks-adapter.ts` + `cli-tasks-tree-adapter.ts`) so the home page tree + the per-task page render against the same metadata contract. Bundles 244-line regression test (`test/context-and-packed-release.test.ts`) that boots the plugin from the **npm-pack** directory (not the repo working tree), spawns `roy-agent tasks get <id> --json`, and asserts (a) `public/style.css` is present and ≥ 64 lines, (b) the `/api/events` SSE endpoint survives a reload, and (c) `task.session` survives a render cycle. v1.1.0: Full Server-Sent Events realtime subscription across 3 event classes (task.created / operation.updated / tool.called) on both the home page and the per-task /task/<id> page. The per-task pipeline now subscribes to /api/events and patches the DOM in place on operation.updated — no more 5s-poll delay before the user sees a new milestone. The 'Task lifecycle pipeline' header badge is replaced by a 5-state SSE-aware badge (stale / connecting / live / reconnecting / error) so the user can tell at a glance whether real-time updates are flowing, the connection dropped, or 3+ consecutive errors triggered the polling fallback. Legacy boolean `stale` cache-TTL pill and `tool.recorded` event name are preserved for back-compat with v0.9.x / v1.0.0 clients. v1.0.0: First stable release. Replaces the v0.9.x fixture-based verify scripts (which built fake TaskOperationsEnvelope and never invoked the real `roy-agent` CLI, masking regressions in the public-schema `processDescription` field) with a real-CLI scenario test + verify (`test/process-description-real-scenario.test.ts` + `scripts/verify-v100-real-scenario.ts`) that spawns `roy-agent tasks get <id> --operations --json` via `defaultRunner` and asserts the API response carries `processDescription` end-to-end. The 0.9.9 processDescription fix is preserved verbatim — this release only swaps the verify surface. Visualize the tool call chain of a task on a local web service with real-time SSE updates. v0.9.9: Task lifecycle pipeline on /task/<id> now exposes BOTH the milestone badge AND the 「过程描述」 column at a glance — the server-side `/api/tasks/:id/operations` endpoint exposes `processDescription` on every operation (no longer stripped from the public schema), the client-side `renderPipelineHtml` mirrors the server's `.op-desc-block` + `.op-proc-block` block layout so SSR ↔ CSR stay in sync, and a long-standing CSS right-side text-truncation bug in the pipeline timeline (long CJK titles overflowing the panel edge) is fixed via `min-width: 0` on `.op-row1` + `overflow-wrap: anywhere` on `.op-title`. v0.9.0: Session-scoped home page (only show tasks created after plugin load + their external ancestors), with per-row 「显示全部栏位」 toggle and lazy-loaded operations timeline; per-task Mermaid labels now correctly render CJK / mixed-Latin / emoji text (encoded as \\uXXXX before emission, decoded by the browser); detail page layout reordered to lifecycle → pipeline → stats → toolcalls → rawjson. v0.5.0+: page refreshes stream over GET /api/events (Server-Sent Events). Subscribes to tool:before.execute, tool:after.execute, task:before.create, task:after.create, task:after.complete (preferred, 2026-07-10+), and task:after.update (legacy fallback). v0.6.11: Mermaid re-rendering is delegated to a self-contained controller (public/mermaid-renderer.js) that prevents the SVG→raw-source regression on async updates and surfaces recoverable .mermaid-error states. v0.6.12: Task lifecycle pipeline (operations timeline) server now emits data-task-id on the pipeline section; client preserves it on swap, so the page actually fetches /api/tasks/<id>/operations and renders the 7-op timeline (previously silently bailed). v0.7.0: Home page redesigned as a hierarchical task tree (driven by `roy-agent tasks tree --json`); new /api/tasks/tree endpoint with status / priority / type / root-id filters, expand/collapse UI, search, and live 30s polling. v0.8.0: per-task page Mermaid area now renders the hierarchical 'Task lifecycle + tools' view — each operation record owns a subgraph that nests its tool calls, with click callbacks (`window.__toolClick`) that scroll-into-view + highlight + auto-expand the matching row in the tool-call table below. Operation record descriptions (`description` + `processDescription`) are now always rendered inline (no `<details>` collapse) so the user sees the lifecycle state at a glance; a fallback `<details>` kicks in only for descriptions longer than 600 chars. v0.8.1: hotfix for two pre-existing bugs in v0.8.0 (browser smoke test surfaced after merge). (a) Mermaid click directives were emitted as `click t1 __toolClick(1)` (missing `call` keyword) — Mermaid 10's parser rejects this with `got 'PS'`. Fixed to `click t1 call __toolClick(1)` (the v10 grammar requires `call` to invoke a callback with arguments). (b) `buildMermaidSource` lived inside the `attachTaskPageTimeline` IIFE but was also called from a listener in the `attachToolClickBridge` IIFE — sibling IIFEs cannot see each other's locals, so the listener threw `ReferenceError: buildMermaidSource is not defined` and the Mermaid diagram silently failed to re-render after `task-show:lifecycle-ops-loaded`. Fixed by hoisting the function (and its three helpers) to script top-level so both IIFEs can see it via the script-wide closure; the function is also exposed on `window.buildMermaidSource` for tests + tooling. v0.8.3: tree-display fix (Task #2426). The home page used to look like a flat list of root tasks because `autoExpandFirstLevels(..., 2)` only opened the first 2 levels — 30/47 roots were leaf nodes and the remaining 17 collapsed to one level so grandchildren were never visible. Default expand depth is now 3 (root + child + grandchild + great-grandchild are visible on first paint), the summary line now shows per-depth count pills (root / child / grandchild / great-grandchild / level-N), each `tree-row` carries a `data-depth` attribute so CSS can paint coloured left rails per level, and the duplicated 'Live tool-call sessions (legacy view)' panel that made the page look like both a flat table AND a tree is now hidden behind `#legacy-sessions[hidden]` (kept for future debug-toggle restoration). v0.8.10: bug-fix release (Task #2537 + Task #2534). (a) Heap-bounded plugin caches: OperationsCache and TasksTreeCache now enforce a hard maxEntries cap (default 256 / 64). Oldest stale entries are evicted before inserting a new one, so long-lived roy-agent sessions (BackgroundTaskManager + MemorySessionStore) no longer leak Map entries through the plugin's per-task caches — see Task #2537 for the heap-unbounded-state RED→GREEN repro. (b) Mermaid CJK font-family: server.ts renderTaskPage now configures mermaid.initialize({ themeVariables: { fontFamily: '\"PingFang SC\", \"Microsoft YaHei\", \"Noto Sans CJK SC\", \"Source Han Sans CN\", \"WenQuanYi Micro Hei\", sans-serif' } }) so Chinese node labels render correctly in browsers that have at least one of those fonts installed (see Task #2534).",
  "main": "dist/index.js",
  "hooks": [
    {
      "point": "tool:before.execute",
      "purpose": "Records a per-call start timestamp so tool:after.execute can compute an accurate durationMs without requiring the host to thread a `start_ts` through the tool result envelope. Plugin-managed timing (v0.3.0+)."
    },
    {
      "point": "tool:after.execute",
      "purpose": "Collect every tool invocation: tool name, args, result, timing, success. Broadcasts a `tool.recorded` SSE event so the frontend timeline + progress bar update live."
    },
    {
      "point": "task:before.create",
      "purpose": "Open a fresh TaskSession before the task runs (v0.5.0+). Mints the visualization URL and broadcasts a `task.created` SSE event so the UI can render the card immediately, even if no tool call fires."
    },
    {
      "point": "task:after.create",
      "purpose": "Mark the session ready for tracking (v0.5.0+). For hosts that emit only this hook (no `task:before.create`), the plugin opens the session here. Broadcasts a `task.created` SSE event when the session is newly minted."
    },
    {
      "point": "task:after.complete",
      "purpose": "PREFERRED hook point (roy-agent 2026-07-10+). When a task transitions to a terminal status (completed/failed/cancelled), finalize the session and broadcast a `task.completed` SSE event. terminalStatus field is explicit — no status filtering required. The handler dedupes against any `task:after.update` that may also fire on the same transition."
    },
    {
      "point": "task:after.update",
      "purpose": "GENERIC status update hook (v0.5.0+). Used for non-terminal transitions (running → paused → running) AND as a legacy fallback for hosts predating the AFTER_COMPLETE hook point. Broadcasts `task.updated` for non-terminal status, `task.completed` for terminal status. The internal dedup set guarantees at most one terminal broadcast per task even if both hooks fire."
    }
  ],
  "commands": [
    {
      "name": "task-show",
      "description": "Open the local visualization service in your browser (alias of the configured port)"
    }
  ],
  "config": {
    "port": {
      "type": "number",
      "default": 7788,
      "description": "HTTP port the local visualization service binds to"
    },
    "host": {
      "type": "string",
      "default": "0.0.0.0",
      "description": "HTTP host the local visualization service binds to (use 0.0.0.0 for LAN access, 127.0.0.1 for local-only)"
    },
    "autoStart": {
      "type": "boolean",
      "default": true,
      "description": "Start the HTTP server when the plugin initializes"
    },
    "maxStoredTasks": {
      "type": "number",
      "default": 50,
      "description": "Maximum number of completed tasks to keep in memory (older ones are evicted)"
    },
    "publicDir": {
      "type": "string",
      "default": "public",
      "description": "Directory holding the static visualization frontend (HTML/JS/CSS)"
    }
  },
  "endpoints": {
    "index": "GET / — index of recent task sessions",
    "taskDetail": "GET /task/:taskId — detail page (mermaid flow + tables)",
    "apiSessions": "GET /api/sessions — JSON list of sessions",
    "apiSessionDetail": "GET /api/sessions/:taskId — JSON detail of one session",
    "apiEvents": "GET /api/events — Server-Sent Events stream (real-time push)",
    "static": "GET /static/* — static frontend assets (CSS/JS)"
  },
  "sse": {
    "events": [
      "snapshot — initial state dump on connect",
      "task.created — new task session opened",
      "task.updated — non-terminal status change",
      "task.completed — task transitioned to a terminal status",
      "tool.recorded — tool call appended to a session"
    ],
    "heartbeatMs": 15000,
    "snapshotFrame": "event: snapshot\ndata: {type:'snapshot', data:{sessions:[...]}}\n\n"
  },
  "roy-agent": {
    "minVersion": "1.6.0",
    "extends": "BasePlugin",
    "registerAs": "task-show"
  },
  "repository": "github:ai-setting/roy-plugin-task-visualize",
  "bugs": "https://github.com/ai-setting/roy-plugin-task-visualize/issues"
}