Port PraisonAI gate scripts with gate-config.js for PraisonAIUI paths,
single-package release preflight, pipeline label sync, Opus merge gate,
CI failure Claude trigger, pypi-auto patch releases, and review-chain hooks.
Gap 1: card DTO now carries tenant, created_at, comment_count and child
progress; cardElement renders dense chrome (checkbox, status dot, id,
priority badge, tenant chip, assignee, age, comment count, progress pill).
Gap 2: new POST /api/kanban/tasks/{id}/comments route plus add_comment on
the store protocol; drawer is now editable (title/assignee/priority),
markdown-rendered (XSS-safe), shows a comment thread with Enter-to-submit
and run/event history rows.
Gap 3: SSE consumer refetches on a 300ms debounce, the open drawer
live-refreshes on events for its task, and destructive moves/delete prompt
for confirmation.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
Gateway _channel_tasks may be a dict or a list depending on SDK version;
calling .append() on a dict raised 'dict' object has no attribute 'append'
during auto-start. Register defensively for both shapes and never let a
gateway bookkeeping failure abort an already-started bot.
Also force running=False whenever start_error is set (in _sync_running_status
and the auto-start failure paths) so the API no longer reports running=true
alongside an error, and log full tracebacks via logger.exception.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
buildDashboard() called root.insertBefore(shellHeader, main) before main was
a child of root, throwing NotFoundError and aborting the dashboard plugin
init, which blocked Ctrl+K and the browser chat input. Append main to root
first so it is a valid reference node for the guarded header insert.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
Centralise PraisonAIUI scope and phase text in workflow env vars and
require Claude to evaluate genuine UI value, correct layering vs
praisonaiagents, and reject scope creep before approving PRs.
Co-authored-by: Cursor <[email protected]>
Run provider.health() concurrently with feature checks under a single
bounded gather instead of awaiting the provider first, and cache the deep
health payload for a short TTL so repeat probes stay fast.
Co-authored-by: praisonai-triage-agent[bot] <praisonai-triage-agent[bot]@users.noreply.github.com>
Completes C-01 parity for the dashboard presentation plane. PR #145 shipped
SessionSearch in React layouts only, so the primary ops example
(15-dashboard-test, style="dashboard") never mounted React and Ctrl+K did
nothing. This adds a vanilla-JS command palette to dashboard.js (Ctrl+K /
Cmd+K toggle, debounced filter, arrow-key nav, Enter/click select, Esc close)
backed by GET /sessions, and wires chat.js to load the chosen session via an
aiui:session-select event.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
Main pushes bypassed the 12h cooldown and concurrent merge runs each
posted @claude for every open DIRTY PR. Apply cooldown always, skip when
claude-conflict-pending label exists, cancel stale scans, and sync fork
handling plus FINAL review gate from PraisonAI.
Co-authored-by: Cursor <[email protected]>
Implements B-08 (MCP manager) and B-02 (command palette) from the OpenClaw
Control UI parity umbrella. MCP view lists/connects/disconnects servers via
the existing /api/mcp/* routes; command palette navigates pages via Ctrl+K.
Co-authored-by: Mervin Praison <[email protected]>
Legacy /health ran sequential per-feature health checks (~2.8s with 42
features). Parallelize with asyncio.gather + 0.5s per-feature timeout
matching /health/ready, and short-circuit ?deep=false to liveness.
Migrate CLI health-check/doctor status to /health/live and provider
status to /health/ready?deep=false. Update K8s/Docker probe docs to
/health/live.
Co-authored-by: Mervin Praison <[email protected]>
Register a dedicated GET /api/provider/health handler before the SPA
catch-all so API clients receive JSON instead of dashboard HTML. Unmatched
/api/* paths now return a JSON 404 in both the static-mount fallback and the
path:path catch-all. Docs updated to match the implementation schema.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
Path.write_text/open default to the locale encoding (cp1252 on
Windows), causing UnicodeEncodeError when compiled HTML/JSON/CSS
contains non-ASCII content such as the U+2728 sparkle from docs.
Add explicit encoding="utf-8" to every text write in the build
and config pipeline.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
Updated the project version in `pyproject.toml` and `uv.lock`.
Changed dependency versions for `praisonai` and `praisonaiagents`
to their latest compatible versions, ensuring better stability and features.
Address Gemini reviewer feedback on the inconsistent hard-coded ASCII
replacements. Introduce _supports_unicode()/_icon() helpers that keep the
rich emoji UI on UTF-aware terminals (macOS/Linux/Windows Terminal) and
degrade to ASCII only on legacy code pages (cp1252/cp437), so output is
both crash-safe and free of UX regressions.
Co-authored-by: Mervin Praison <[email protected]>
The /api/provider endpoint flattens provider.health() into the top-level
response via info.update(health_data), so there is no nested "health"
object. The previous extractor read data.get("health") which was always
None, forcing status to "unknown" and the Gateway check to always "warn".
Read status/provider directly from the top-level dict.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Mervin Praison <[email protected]>
- useSessionSearch: add `enabled` param so global Ctrl+K is only
intercepted when the palette is rendered; case-insensitive key check
- ChatLayout: only enable the shortcut in fullscreen mode
- AgentUILayout: pass currentSessionId/onSessionChange to ChatArea so
session selection is functional
- SessionSearch: guard async fetch with an active flag, hoist date
objects out of the reduce loop, use a div for the loading state
(CommandEmpty only renders post-filter)
- tests: patch async _datastore with AsyncMock and build the app via
create_app() so the /sessions endpoint tests actually run
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Mervin Praison <[email protected]>