Skip to content

Releases: atomantic/PortOS

v1.44.1

22 Apr 14:41

Choose a tag to compare

Release v1.44.1

Released: 2026-04-22

Note: This version supersedes v1.44.0, which was deleted after shipping with a server-boot crash (see "Hotfix" below). All v1.44.0 content is included here.

Hotfix (v1.44.1)

  • Server crashed on boot with TypeError: Cannot read properties of undefined (reading 'catch')server/index.js:303 chained .catch() onto agentActionExecutor.init(), but that init() is synchronous and returns undefined. The .catch call threw at module load, crashing portos-server immediately after PM2 started it. Introduced during the v1.44.0 cycle and shipped because the release pipeline had no step that actually booted server/index.js — unit tests (vitest) import service modules in isolation and never execute the top-level initialization in index.js, and npm run build only builds the client. Dropped the .catch since init() is sync; added a new npm run smoke step (scripts/smoke-boot.js) that spawns server/index.js in a child process and fails if it exits within a 4 s boot window, so any similar top-level init crash blocks future releases instead of shipping.

Added

  • Universal Xcode deploy.sh template — auto-detects schemes, defaults to every available platform — the deploy script generator PortOS installs into Xcode projects (generateDeployScript in server/services/xcodeScripts.js) now produces a single universal template that auto-detects available schemes (trying both TargetName/TargetName macOS/TargetName_Watch and TargetName_iOS/TargetName_macOS/TargetName_watchOS candidates) so one template works across all naming conventions. The default (./deploy.sh with no flags) now fans out to every platform the project has a scheme for, keeping iOS + macOS + watchOS build numbers in lockstep on App Store Connect — previously it defaulted to iOS only and required --all to ship every platform. Serial uploads with a 60s inter-upload delay (via a shared helper that correctly sleeps between every successful upload in iOS↔macOS↔watchOS chains, not just before macOS). New build-number rollback trap: if any step after the build-number bump fails, the trap restores project.yml and project.pbxproj to their byte-exact pre-bump state, so a failed upload doesn't permanently consume a build number committed to main. --transport DAV on iOS/watchOS uploads for more reliable multipart handling. Shared exportOptions.plist across platforms (was duplicated three times). Explicit --ios/--macos/--watch flags hard-error on missing schemes; --all and the default silently skip missing ones. Existing per-project deploy.sh files are NEVER overwritten by installScripts — this new template only lands when installing into projects that don't already have one. scaffoldXcode.js README snippet updated to reflect the new defaults.

  • Opt-in HTTPS for managed apps via PortOS "Upgrade to TLS" action — PortOS's own HTTPS+loopback-HTTP setup (previously inlined in server/index.js) is now a zero-dep helper module at lib/tailscale-https.js exporting createTailscaleServers, watchCertReload, and hasTailscaleCert. PortOS itself now uses the helper (dogfood). App schema gains an optional tlsPort field — when set, the Launch button on the app grid and detail view opens https://<host>:<tlsPort>/ as the primary action (with plain HTTP demoted to a muted secondary button, and Dev UI still reachable when devUiPort is set). The PortOS baseline app auto-reflects tlsPort: PORTS.API whenever a cert is present on disk, so the Launch button targets the correct scheme out of the box. New app-manager action Edit → Upgrade to TLS: pick a TLS port (defaults to uiPort + 1000), PortOS copies lib/tailscale-https.js into the target app's repo at <repoPath>/lib/tailscale-https.js and records the tlsPort in apps.json; backend refuses overwrite unless the user clicks the "Overwrite existing" button that surfaces on collision. The response returns a preformatted snippet (with a copy button) showing how to wire the helper into the app's server entry — the wire-up is deliberately left to the user to avoid mis-patching arbitrary server files. The helper is zero-dep by design: apps that adopt it stay self-contained and runnable without PortOS. To share the single Tailscale Let's Encrypt cert across apps, each app points CERT_DIR at (or symlinks) data/certs in the PortOS install. New backend route POST /api/apps/:id/upgrade-tls { tlsPort, force } (409 ALREADY_EXISTS when a helper already lives in the target). Client launch URLs consolidated into client/src/services/appUrls.js (getLaunchUrls, getPrimaryLaunchUrl) so tile and detail views build URLs through one function. apiCore.request() now enriches thrown errors with err.code + err.status so callers can branch on server error codes.

  • Cyber Muse CoS avatar — GLB-backed holographic head — new muse option in Settings → CoS → Appearance. Rather than assembling sphere primitives into a face (uncanny) or displacing a sphere point cloud (unreadable silhouette), the avatar loads a user-supplied data/avatar/model.glb through a new /api/avatar/model.glb route (server/routes/avatar.js, HEAD + GET, 404 when missing, model/gltf-binary when present) and renders it with a holographic material treatment: dark base + state-colored emissive glow that pulses per CoS state (sleeping/thinking/coding/investigating/ideating) and sync-bobs when the CoS is speaking. Bounding-box auto-fit means any model scale/origin works — drop in a ~4MB Ready Player Me export, a Sketchfab head bust, or a Mixamo-rigged character and it centers + sizes itself. When no GLB is present, renders a clean empty-state card pointing at the target path. Piggybacks on useGLTF (drei) and reuses the existing Sparkles/halo/ground-glow chrome. Zod enum for avatarStyle gained 'muse' in server/routes/cosStatusRoutes.js.

  • Loopback HTTP mirror on port 5553 when HTTPS is active — Tailscale's Let's Encrypt cert only covers <machine>.<tailnet>.ts.net, so https://localhost:5555 always tripped a cert warning. When HTTPS is active the server now also spins up a plain HTTP listener bound to 127.0.0.1:5553 that attaches to the same Express app and Socket.IO instance — http://localhost:5553 works without cert warnings and Chrome still treats it as a secure context (so getUserMedia / mic access continues to work). Override the port via PORTOS_HTTP_PORT. Documented in docs/PORTS.md.

  • Voice agent — universal accessibility-mode DOM driving — the voice Chief-of-Staff can now navigate to any page and operate any control by voice. New ui_navigate tool with a 100+ entry named-page enum ("take me to tasks" / "chief of staff agents" / "calendar" all route correctly instead of defaulting to Daily Log). New accessibility layer: a client-side DOM indexer (client/src/services/domIndex.js) walks <main> for interactable elements (tabs, buttons, links, inputs, selects, textareas, checkboxes, radios), resolves labels via the standard aria → <label for> → wrapping label → text → placeholder → title chain, stamps stable data-voice-ref refs, and caps at 200 elements. useVoiceUiSync hook (debounced MutationObserver scoped to <main>, change-detection via content signature) pushes the index to the server whenever it actually changes. Server stores the index on per-socket state and — for UI-driving user turns (verb-gated by regex to keep the 80% of turns that don't need it cheap) — injects a compact page summary into the LLM's system prompt. New tools: ui_click (tab/button/link by label with optional kind hint), ui_fill (text inputs + textareas, uses React-safe native value setter so onChange fires), ui_select (dropdowns with fuzzy option matching), ui_check (checkboxes + radios), ui_list_interactables (deep-dive fallback). Misses return a helpful available list to the LLM so it can self-correct instead of silently failing. In-turn chained flows: after a ui_* action fires, the server pauses briefly for the client to push the post-action DOM index, then attaches the fresh summary to the tool result — so multi-step flows like "create a task named Foo with description Bar" can complete in a single turn (ui_click New Task → see the modal → ui_fill Name → ui_fill Description → ui_click Save).

  • Per-peer DNS override on the Instances page — peer cards now expose an "edit host" control that lets you swap the raw Tailscale IP (http://100.83.147.46:5555) for a trusted HTTPS DNS name (https://void.taile8179.ts.net:5555). Once set, the server's probe, socket relay, sync orchestrator, and query proxy all route through https://<host> instead of http://<ip> — so app links in PeerAppsList also upgrade to HTTPS automatically. New GET /api/instances/tailnet-suffix endpoint shells out to the local tailscale status --json and returns the MagicDNS suffix + the full peer map, which the Instances UI uses to auto-suggest DNS names: match by Tailscale IP first (authoritative), fall back to <peer.hostname>.<suffix> composition. The UI's "use <suggested>" button applies the suggestion in one click. updatePeer now accepts an optional host field (validated as a DNS name; empty string clears); invalid hosts return 400 instead of silent no-ops. addPeer also accepts host for direct-DNS registration. Vite dev proxy auto-detects data/certs/cert.pem and flips its target to https://localhost:5555 with secure: false when HTTPS is active, fixing "socket hang up" errors in dev mode. 44 tests (3 new) cover valid/invalid/cleared host handling.

  • HTTPS with auto-renewing Let's Encrypt cert via Tailscale (self-signed fallback) — Chrome refuses getUserMedia (mic) access over plain HTTP on a 100.x.x.x Tailscale IP because the origin isn't a secure context. New scripts/setup-cert.js prefers a real Let's Encrypt cert via tailscale cert <machine>.<tailnet>.ts.net (Tailscale...

Read more

v1.43.0

14 Apr 19:58
e076315

Choose a tag to compare

Release v1.43.0

Released: 2026-04-14

Added

  • Test coverage for 7 previously untested modules: commandSecurity, httpClient, platform, memoryBM25, notifications, search, and taskSchedule — 171 new tests covering command validation, output redaction, HTTP client factory, BM25 memory indexing, notification CRUD, fan-out search, and task scheduling logic
  • Xcode Multi-Platform template — new "Xcode Multi-Platform" app template scaffolds a SwiftUI project with iOS, macOS, and watchOS targets via XcodeGen
    • Generic deploy.sh with --ios, --macos, --watch, --all flags for TestFlight deployment
    • Generic take_screenshots.sh and take_screenshots_macos.sh for App Store screenshot automation
    • UI test target with ScreenshotTests.swift stubs for XCUITest-based screenshot capture
    • Shared module for cross-platform code, macOS entitlements, watchOS companion app
  • Xcode script health check — PortOS now detects missing management scripts (deploy, screenshots) in Xcode-managed apps and surfaces a banner in the app detail overview with one-click install
  • Deploy panel now includes --watch (watchOS) flag option
  • Obsidian Notes Manager in Brain section — browse, search, edit, and create notes in Obsidian vaults synced via iCloud
    • Auto-detects Obsidian vaults from iCloud directory
    • Vault browser with folder tree, search, tags panel, and markdown preview with wikilink navigation
    • Inline note editor with Cmd+S save, backlinks panel, and frontmatter properties view
    • Full-text search with context snippets and relevance ranking
    • Link graph endpoint for vault-wide wikilink visualization
  • LLM Wiki — a dedicated Wiki page for managing an LLM-maintained knowledge base in Obsidian
    • Overview tab with page-type stats (sources, entities, concepts, comparisons, synthesis, queries), recent activity feed, and health report display
    • Browse tab with folder-tree navigation for both wiki pages and raw sources, inline note viewer/editor with metadata sidebar (frontmatter, tags, wikilinks, backlinks)
    • Full-text search tab with relevance ranking, context snippets, and one-click navigation to results
    • Interactive knowledge graph tab with color-coded node clusters by page type, zoom/pan, and click-to-navigate
    • Activity log tab parsing the wiki's chronological log into a structured timeline
    • Wiki schema (WIKI.md) defining page types, frontmatter conventions, and ingest/query/lint workflows
    • Weekly CoS maintenance job (job-wiki-maintenance) that audits the wiki for contradictions, orphans, missing cross-references, outdated claims, and generates a lint report
    • Obsidian attachment folder auto-configured to raw/assets/ for Web Clipper image downloads
  • Disk usage monitoring on dashboard — system health endpoint now reports root filesystem disk usage (total/used/free/percent) with warning at 85% and critical alert at 95%; SystemHealthWidget displays a new Disk card with progress bar alongside Memory, CPU, Processes, and Apps
  • CyberCity v2 improvement plan — 19 concrete ideas across 3 effort tiers for transforming CyberCity from decorative scene to living systems dashboard, including system health atmosphere, productivity district, goal monuments, chronotype energy overlay, and knowledge district

Fixed

  • Simplify agent summary visibility — completed agents that ran with /simplify now extract and display a separate "Task Summary" showing what the agent accomplished, so the original work summary is no longer buried under the simplify review output

  • Memory dedup — duplicate approval requests — memory extractor now checks existing active and pending memories (via vector similarity + text prefix matching) before proposing new ones, and the LLM classification prompt now includes existing memories so it avoids re-proposing semantically equivalent knowledge

  • Xcode deploy.sh template — altool upload check false-positive — generated deploy scripts grepped altool output for plain ERROR: to detect upload failures, but altool's multipart uploader logs every transient retry as ERROR: [ContentDelivery.Uploader.X] WILL RETRY PART N. Checksums do not match. On flaky/slow networks the script killed deploys mid-recovery. Switched to Apple's definitive failure markers only: UPLOAD FAILED|Validation failed \(|ERROR ITMS-|product-errors. Affects iOS, macOS, and watchOS upload sections in xcodeScripts.js.

  • Submodule status API (/api/git/submodules/status) always returned empty array — stdout.trim() was stripping the leading space status character from git submodule status output, causing the regex parser to fail

  • CoS agents page crash: pipe characters (|) in task descriptions triggered infinite loop in markdown parser — non-table pipes now treated as normal text with safety fallback

  • CoS agents API returned full output arrays (600KB+) for all agents in listing — output now stripped from listing response and loaded on demand

  • Resume Agent modal not dismissing — clicking "Queue Resume Task" successfully queued the task but left the modal open; modal now closes on successful submit

  • Pending task edit form unresponsive — save/cancel buttons on the edit form for pending tasks did not respond to taps; dnd-kit's sortable wrapper interfered with pointer events inside sortable items. Sorting is now disabled while editing, pointer events are stopped from propagating through the edit form, and button touch targets are enlarged to 40px minimum height

  • Broken worktree detection — worktree cleanup now verifies rev-parse --show-toplevel matches the expected worktree path before trusting git status; prevents broken worktrees (missing .git file) from resolving to a parent repo and incorrectly blocking removal

  • Agent prompt missing commit step — agent instructions now explicitly include "commit and push" in the numbered steps and the simplify section reinforces committing after review, preventing agents from completing work without pushing changes

  • Memory classifier — LM Studio no-model-loaded failures — memory classification calls to LM Studio failed with 400 "No models loaded" when the server had no model in memory. The classifier now discovers downloaded LLMs via GET /api/v0/models, auto-loads the configured model (or first available LLM) via POST /api/v1/models/load, and retries with the actually-loaded model id — mirroring the existing embedding auto-load path in memoryEmbeddings.js

  • Browser CDP downloads reverting to ~/DownloadsBrowser.setDownloadBehavior is DevTools-session-scoped in Chrome: the instant the WebSocket that issued the command closes, Chrome tears down the session's BrowserHandler and the download directory reverts to the profile default. The previous implementation opened a WS, sent the command, and closed it immediately after the ack — so the managed download dir was only in effect for milliseconds and real downloads landed in ~/Downloads. browser/server.js now keeps a persistent keep-alive WebSocket open for the lifetime of the process, with automatic reconnect if Chrome restarts, proper error detection on the command response, and clean teardown on shutdown

  • Wordplay trainer scored every answer against the first prompt — Double Meaning, Idiom Twist, and other POST LLM drills that score one response at a time were always looking up challenges by array index 0. A user answering prompt #2 ("spring") would get feedback evaluating it against prompt #1's word ("crane"). Client now sends questionIndex with each response; server scorers (both local and LLM-based) use r.questionIndex ?? i so the correct challenge is paired with each answer

Full Changelog

Full Diff: v1.42.0...v1.43.0

v1.42.0

05 Apr 00:56
7a2dbd2

Choose a tag to compare

Release v1.42.0

Released: 2026-04-04

Added

  • Submodules management page under Dev Tools — view status, check for updates, and update individual or all git submodules from the dashboard
  • Update scripts (update.sh, update.ps1) now auto-update submodules (including slash-do) during PortOS updates
  • CoS route test coverage — 170 new tests across 6 test files covering templates, learning, schedule, jobs, insights, and missing gaps in task/agent/report routes (83-100% route coverage, up from ~12%)
  • Slash-do agent operations panel on app detail Overview tab — buttons for /do:push, /do:review, /do:release, /do:better, and /do:better-swift that queue CoS agent tasks with the full command instructions
  • Multi-line task context now renders as a dedicated ### Task Context section in agent prompts instead of inline
  • Enter key submits the task add form (Shift+Enter for newline)

Changed

  • PM2 file watch restart delay set to 5 minutes to prevent rapid restarts during development
  • Triggering agent operations (do:push, do:review, etc.) from the app overview page now navigates to the CoS agents page so the user can watch the agent run

Fixed

  • Branch actions on mobile — delete/merge confirmations now wrap to a separate row instead of overlapping, added 40px touch targets to all buttons, header controls wrap gracefully, commit dates hidden on small screens
  • Agent error handling in AgentsTab — API failures no longer trigger success toasts or state refreshes
  • Resume agent modal now prevents double-submission with loading state and disabled button
  • Slash-do quick actions (/do:push, /do:review, etc.) no longer run in a worktree — they now execute on the app's active branch where they have the correct context
  • Feature-ideas prompt included "you are working in a git worktree on a feature branch" even when worktree was not configured — worktree context is now only injected by agentPromptBuilder when actually using a worktree
  • app-improve- task IDs were getting task- prefix added by taskParser.js, causing updateTask lookups to fail — tasks were never marked in_progress or completed after agent runs
  • Recovered app-improve- agents after server restart now correctly infer taskType: 'internal' instead of 'user'
  • Extracted hasKnownPrefix() and isInternalTaskId() helpers to eliminate prefix check drift across 8 locations
  • Screenshot and attachment uploads now clear after successful task form submission

Full Changelog

Full Diff: v1.41.2...v1.42.0

v1.41.2

04 Apr 15:32
0c5f937

Choose a tag to compare

Release v1.41.2

Released: 2026-04-04

Changed

  • Status badges in ProcessesTab and StatusBadge now use muted translucent backgrounds (bg-color/15) with matching text colors instead of solid full-opacity fills, improving dark mode readability
  • Extracted agentOptionButtonClass() helper to cos/constants.js for shared agent option toggle button styling; applied in ScheduleTab and AutomationTab
  • Wrapped AppOverrideRow in memo to avoid unnecessary re-renders
  • ScheduleTab agent option rows made fully tappable on mobile (44px touch targets, whole-row click area)
  • Scheduler now synthesizes cron expression from scheduledTime + interval instead of post-hoc tolerance hack, eliminating drift-based day-skip bug

Fixed

  • Scheduled jobs with scheduledTime could drift and skip a day after accumulating small timing errors — now cron is synthesized from scheduledTime at compute time for exact daily/weekday scheduling
  • Per-app cron scheduled tasks (e.g. feature-ideas at 1am) could be delayed up to eligibleIn ms when the next check interval was too long — improvement check now caps at 1 hour so per-app schedules are always checked on time
  • CoS agents that ran but made no code changes (worktree branch had no commits vs base) now silently clean up their worktree instead of leaving a stale branch and emitting a spurious warning
  • Worktree merge/PR failures now auto-spawn a recovery task so stale branches don't accumulate in managed app repos
  • Task edit form now closes after a successful save (shows error toast and stays open on API failure)

Full Changelog

Full Diff: v1.41.1...v1.41.2

v1.41.1

03 Apr 20:48
15b6722

Choose a tag to compare

Release v1.41.1

Released: 2026-04-03

Added

  • AI-powered narrative summaries for JIRA weekly status reports (tries each API provider until one succeeds)

Changed

  • JIRA reports now filter to current user's tickets only via currentUser() JQL
  • Status report UI simplified to personal weekly status format with copy-to-clipboard
  • Ticket keys rendered as clickable JIRA links anywhere in report text

Changed

  • Pin all npm dependencies to exact versions across all packages (no more ^ or ~ ranges) to prevent supply chain attacks
  • Heavy-mode dependency audit — 15 packages flagged for removal, full replacement plan saved to PLAN.md
  • Replace axios with owned server/lib/httpClient.js (fetch-based, AbortSignal.timeout, self-signed TLS via https.Agent)
  • Replace multer with owned server/lib/multipart.js (streaming multipart parser, no memory buffering, safe for 500MB+ files)
  • Replace unzipper with owned server/lib/zipStream.js (streaming ZIP parser via zlib.createInflateRaw, DEFLATE + stored entries)
  • Remove cors package from scaffold-generated project templates; generated code now uses inline CORS middleware

Changed

  • Replace node-telegram-bot-api with owned server/lib/telegramClient.js (fetch-based polling loop, all bot methods)
  • Replace supertest with owned server/lib/testHelper.js (HTTP server lifecycle + fetch-based request wrapper; 9 test files updated)
  • Replace react-hot-toast with owned client/src/components/ui/Toast.jsx (module-level store, Toaster component; 101 import sites updated)
  • Replace react-markdown with inline regex block/inline parser in MarkdownOutput.jsx (h1–h6, bold, italic, code, tables, lists, links)
  • Replace react-diff-viewer-continued with inline Myers LCS diff in CrossDomainTab.jsx; InlineDiff wrapped with React.memo
  • Replace fflate direct usage with native DecompressionStream + inline EOCD ZIP parser in GenomeTab.jsx

Changed

  • God file decomposition: split server/routes/cos.js (1,464 lines) into 9 focused sub-modules (cosStatusRoutes, cosTaskRoutes, cosAgentRoutes, cosReportRoutes, cosLearningRoutes, cosScheduleRoutes, cosJobRoutes, cosTemplateRoutes, cosInsightRoutes)
  • God file decomposition: split server/routes/scaffold.js (1,667 lines) into 4 template generators (scaffoldVite, scaffoldExpress, scaffoldIOS, scaffoldPortOS)
  • God file decomposition: split client/src/services/api.js (2,016 lines) into 27 domain sub-modules with barrel re-export; no consumer imports changed
  • Block npm postinstall scripts by default via .npmrc ignore-scripts=true; install:all explicitly rebuilds trusted packages (esbuild, node-pty)
  • Move Digital Twin work to backlog; promote god file decomposition to Next Up in PLAN.md
  • God file decomposition: split server/services/digital-twin.js (2,970 lines) into 10 focused modules (digital-twin-constants, digital-twin-helpers, digital-twin-meta, digital-twin-documents, digital-twin-testing, digital-twin-enrichment, digital-twin-export, digital-twin-context, digital-twin-analysis, digital-twin-import, digital-twin-status); digital-twin.js is now a thin barrel re-export

Fixed

  • Scheduled AI jobs (e.g. Daily Briefing) could get permanently stuck as "Due" if agent spawn failed — task:ready handler now catches errors and emits job:spawn-failed to re-register the timer; 5-minute spawning timeout also re-registers as safety net
  • Bug: providerOverride was incorrectly passed as model argument in processEnrichmentAnswer; corrected to modelOverride
  • Dynamic import() of safeJSONParse inside analyzeEnrichmentList replaced with static top-level import
  • loadMeta() was called inside per-document loop in analyzeAssessment; hoisted out to load once

Changed

  • getDocuments() now parallelizes all stat() calls with Promise.all
  • getAllTwinContent() now parallelizes all readFile() calls with Promise.all
  • Added extractJSON() and ensureDocumentInMeta() helpers to digital-twin-helpers.js; three duplicate document-push blocks in enrichment module replaced with helper calls

Changed

  • God file decomposition: split server/services/subAgentSpawner.js (3,820 lines) into 9 focused modules (agentState, agentModelSelection, agentRunTracking, agentErrorAnalysis, agentCompletion, agentPromptBuilder, agentCliSpawning, agentLifecycle, agentManagement); main file is now a 187-line orchestrator with re-exports for backward compatibility
  • isTruthyMeta/isFalsyMeta consolidated into agentState.js (single source of truth)
  • terminateAgent/killAgent runner path de-duplicated via shared terminateRunnerAgent helper
  • killAllAgents now terminates all agents in parallel with Promise.all
  • buildAgentPrompt context fetches (memory, CLAUDE.md, digital twin, tools) and .planning/ file reads now run in parallel
  • safeParse in agentCliSpawning.js replaced with safeJSONParse from fileUtils
  • Removed TOCTOU existsSync guards in agentPromptBuilder.js; rely on .catch(() => null) instead

Fixed

  • Auto-update from the UI was failing at git fetch step — switched from portos-update.sh (tag checkout) to update.sh (git pull --rebase) which adds STEP markers for UI progress, completion markers for boot-time result recording, and Windows support via update.ps1
  • Scheduled AI jobs (e.g. Daily Briefing) could get permanently stuck as "Due" if agent spawn failed — task:ready handler now catches errors and emits job:spawn-failed to re-register the timer
  • httpClient.js now rejects hanging promise when signal is pre-aborted; toast shown on task add failure
  • JIRA report provider discovery now tries all available API providers instead of failing on first unreachable one
  • agentCliSpawning.js imported completeExecution/errorExecution from executionLanes.js (wrong module); corrected to import from toolStateMachine.js, fixing server crash on startup
  • OpenClaw stream route now calls res.flushHeaders() before proxying SSE so headers reach the client immediately
  • OpenClaw stream reader loop wrapped in try/catch to handle AbortError on client disconnect without unhandled rejection
  • Orphaned htmlFor="compact-task-app" sr-only label in TaskAddForm compact mode removed (referenced select id that no longer exists after AppContextPicker refactor)
  • XSS: MarkdownOutput.jsx links now validate href protocol (allow http://, https://, / only); unsafe URIs render as plain text
  • Toast notifications missing background color — added bg-port-card with border
  • InlineDiff word diff used Set which collapsed duplicate common words; replaced with sequential LCS pointer matching
  • httpClient.js now auto-sets Content-Type: application/json when sending JSON body
  • zipStream.js sanitizes ZIP entry paths (normalizes separators, strips .. and . components)
  • multipart.js sanitizes file extension to alphanumeric characters only

Added

  • AppContextPicker component — reusable app selector with repo path display; replaces inline <select> in TaskAddForm (compact and full modes)
  • OpenClaw operator chat: SSE streaming with optimistic UI (user + streaming assistant placeholder appear immediately)
  • OpenClaw: file/image attachment support — drag & drop, paste screenshots, file picker
  • OpenClaw: app context, directory context, and extra instructions fields sent with messages
  • OpenClaw: Stop/Cancel button aborts in-flight stream via AbortController
  • OpenClaw: Cmd/Ctrl+Enter keyboard shortcut submits the composer
  • OpenClaw: auto-scroll to latest message during streaming
  • OpenClaw: collapsible "older chats" section for sessions beyond the top 6 non-empty ones
  • OpenClaw: synthetic default session injected when defaultSession config key has no matching session
  • formatDateTime added to client/src/utils/formatters.js (medium date + short time via Intl.DateTimeFormat)
  • readFileAsBase64 exported from client/src/utils/fileUpload.js for reuse across components

Changed

  • OpenClaw integration rewritten to use OpenResponses /v1/responses API and /tools/invoke for session discovery
  • normalizeAttachment builds OpenAI-compatible input_image/input_file blocks from base64 or URL sources
  • streamSessionMessage proxies upstream SSE with timeoutMs: 0 for long-running streaming responses
  • fetchWithTimeout accepts timeoutMs: 0 to opt out of the timeout (needed for streaming)
  • loadRuntime stabilized via selectedSessionIdRef — session switches no longer trigger a full runtime reload
  • After send, session lastMessageAt updated locally instead of triggering a full loadRuntime() reload
  • context state in OpenClaw simplified — removed derived appName/repoPath; computed at send time
  • Duplicate setMessages update pattern in handleSend extracted into updateAssistant(updater) helper

Full Changelog

Full Diff: v1.41.0...v1.41.1

v1.41.0

03 Apr 03:27
1839970

Choose a tag to compare

Release v1.41.0

Released: 2026-04-02

Full Changelog

Full Diff: v1.40.0...v1.41.0

Added

  • AI-powered narrative summaries for JIRA weekly status reports (tries each API provider until one succeeds)

Changed

  • JIRA reports now filter to current user's tickets only via currentUser() JQL
  • Status report UI simplified to personal weekly status format with copy-to-clipboard
  • Ticket keys rendered as clickable JIRA links anywhere in report text

Changed

  • Pin all npm dependencies to exact versions across all packages (no more ^ or ~ ranges) to prevent supply chain attacks
  • Heavy-mode dependency audit — 15 packages flagged for removal, full replacement plan saved to PLAN.md
  • Replace axios with owned server/lib/httpClient.js (fetch-based, AbortSignal.timeout, self-signed TLS via https.Agent)
  • Replace multer with owned server/lib/multipart.js (streaming multipart parser, no memory buffering, safe for 500MB+ files)
  • Replace unzipper with owned server/lib/zipStream.js (streaming ZIP parser via zlib.createInflateRaw, DEFLATE + stored entries)
  • Remove cors package from scaffold-generated project templates; generated code now uses inline CORS middleware

Changed

  • Replace node-telegram-bot-api with owned server/lib/telegramClient.js (fetch-based polling loop, all bot methods)
  • Replace supertest with owned server/lib/testHelper.js (HTTP server lifecycle + fetch-based request wrapper; 9 test files updated)
  • Replace react-hot-toast with owned client/src/components/ui/Toast.jsx (module-level store, Toaster component; 101 import sites updated)
  • Replace react-markdown with inline regex block/inline parser in MarkdownOutput.jsx (h1–h6, bold, italic, code, tables, lists, links)
  • Replace react-diff-viewer-continued with inline Myers LCS diff in CrossDomainTab.jsx; InlineDiff wrapped with React.memo
  • Replace fflate direct usage with native DecompressionStream + inline EOCD ZIP parser in GenomeTab.jsx

Changed

  • God file decomposition: split server/routes/cos.js (1,464 lines) into 9 focused sub-modules (cosStatusRoutes, cosTaskRoutes, cosAgentRoutes, cosReportRoutes, cosLearningRoutes, cosScheduleRoutes, cosJobRoutes, cosTemplateRoutes, cosInsightRoutes)
  • God file decomposition: split server/routes/scaffold.js (1,667 lines) into 4 template generators (scaffoldVite, scaffoldExpress, scaffoldIOS, scaffoldPortOS)
  • God file decomposition: split client/src/services/api.js (2,016 lines) into 27 domain sub-modules with barrel re-export; no consumer imports changed
  • Block npm postinstall scripts by default via .npmrc ignore-scripts=true; install:all explicitly rebuilds trusted packages (esbuild, node-pty)
  • Move Digital Twin work to backlog; promote god file decomposition to Next Up in PLAN.md
  • God file decomposition: split server/services/digital-twin.js (2,970 lines) into 10 focused modules (digital-twin-constants, digital-twin-helpers, digital-twin-meta, digital-twin-documents, digital-twin-testing, digital-twin-enrichment, digital-twin-export, digital-twin-context, digital-twin-analysis, digital-twin-import, digital-twin-status); digital-twin.js is now a thin barrel re-export

Fixed

  • Bug: providerOverride was incorrectly passed as model argument in processEnrichmentAnswer; corrected to modelOverride
  • Dynamic import() of safeJSONParse inside analyzeEnrichmentList replaced with static top-level import
  • loadMeta() was called inside per-document loop in analyzeAssessment; hoisted out to load once

Changed

  • getDocuments() now parallelizes all stat() calls with Promise.all
  • getAllTwinContent() now parallelizes all readFile() calls with Promise.all
  • Added extractJSON() and ensureDocumentInMeta() helpers to digital-twin-helpers.js; three duplicate document-push blocks in enrichment module replaced with helper calls

Changed

  • God file decomposition: split server/services/subAgentSpawner.js (3,820 lines) into 9 focused modules (agentState, agentModelSelection, agentRunTracking, agentErrorAnalysis, agentCompletion, agentPromptBuilder, agentCliSpawning, agentLifecycle, agentManagement); main file is now a 187-line orchestrator with re-exports for backward compatibility
  • isTruthyMeta/isFalsyMeta consolidated into agentState.js (single source of truth)
  • terminateAgent/killAgent runner path de-duplicated via shared terminateRunnerAgent helper
  • killAllAgents now terminates all agents in parallel with Promise.all
  • buildAgentPrompt context fetches (memory, CLAUDE.md, digital twin, tools) and .planning/ file reads now run in parallel
  • safeParse in agentCliSpawning.js replaced with safeJSONParse from fileUtils
  • Removed TOCTOU existsSync guards in agentPromptBuilder.js; rely on .catch(() => null) instead

Fixed

  • JIRA report provider discovery now tries all available API providers instead of failing on first unreachable one
  • agentCliSpawning.js imported completeExecution/errorExecution from executionLanes.js (wrong module); corrected to import from toolStateMachine.js, fixing server crash on startup
  • OpenClaw stream route now calls res.flushHeaders() before proxying SSE so headers reach the client immediately
  • OpenClaw stream reader loop wrapped in try/catch to handle AbortError on client disconnect without unhandled rejection
  • Orphaned htmlFor="compact-task-app" sr-only label in TaskAddForm compact mode removed (referenced select id that no longer exists after AppContextPicker refactor)
  • XSS: MarkdownOutput.jsx links now validate href protocol (allow http://, https://, / only); unsafe URIs render as plain text
  • Toast notifications missing background color — added bg-port-card with border
  • InlineDiff word diff used Set which collapsed duplicate common words; replaced with sequential LCS pointer matching
  • httpClient.js now auto-sets Content-Type: application/json when sending JSON body
  • zipStream.js sanitizes ZIP entry paths (normalizes separators, strips .. and . components)
  • multipart.js sanitizes file extension to alphanumeric characters only

Added

  • AppContextPicker component — reusable app selector with repo path display; replaces inline <select> in TaskAddForm (compact and full modes)
  • OpenClaw operator chat: SSE streaming with optimistic UI (user + streaming assistant placeholder appear immediately)
  • OpenClaw: file/image attachment support — drag & drop, paste screenshots, file picker
  • OpenClaw: app context, directory context, and extra instructions fields sent with messages
  • OpenClaw: Stop/Cancel button aborts in-flight stream via AbortController
  • OpenClaw: Cmd/Ctrl+Enter keyboard shortcut submits the composer
  • OpenClaw: auto-scroll to latest message during streaming
  • OpenClaw: collapsible "older chats" section for sessions beyond the top 6 non-empty ones
  • OpenClaw: synthetic default session injected when defaultSession config key has no matching session
  • formatDateTime added to client/src/utils/formatters.js (medium date + short time via Intl.DateTimeFormat)
  • readFileAsBase64 exported from client/src/utils/fileUpload.js for reuse across components

Changed

  • OpenClaw integration rewritten to use OpenResponses /v1/responses API and /tools/invoke for session discovery
  • normalizeAttachment builds OpenAI-compatible input_image/input_file blocks from base64 or URL sources
  • streamSessionMessage proxies upstream SSE with timeoutMs: 0 for long-running streaming responses
  • fetchWithTimeout accepts timeoutMs: 0 to opt out of the timeout (needed for streaming)
  • loadRuntime stabilized via selectedSessionIdRef — session switches no longer trigger a full runtime reload
  • After send, session lastMessageAt updated locally instead of triggering a full loadRuntime() reload
  • context state in OpenClaw simplified — removed derived appName/repoPath; computed at send time
  • Duplicate setMessages update pattern in handleSend extracted into updateAssistant(updater) helper

v1.40.0

30 Mar 08:08
5efc055

Choose a tag to compare

Release v1.40.0

Released: 2026-03-29

Fixed

  • Scheduled tasks defaulting to enabled for existing apps when new task types are added — isTaskTypeEnabledForApp now defaults to disabled (opt-in) instead of enabled (opt-out)
  • Autonomous job scheduler using UTC instead of local timezone for scheduled times — daily briefing at 4:30 AM local was firing at 4:30 AM UTC. Now uses nextLocalTime() to compute exact UTC target from local scheduled time
  • Codex agent output flooding UI with full prompt/config dump from stderr — filtered to only show tool execution lines and errors
  • On-demand tasks silently dropped when pipeline preconditions fail (e.g., REVIEW.md already exists) — on-demand tasks now skip precondition checks since the user explicitly requested them
  • Pipeline stage 2+ tasks stuck in queue forever — follow-up tasks were missing id and status: 'pending' fields when created with raw: true, making them invisible to the task evaluator
  • Pipeline tasks not marked completed after agent finishes — app-improve-* task IDs were misidentified as user tasks (expected sys- prefix), causing updateTask to look in the wrong file
  • Pipeline stage 2 tasks blocked by app cooldown — pipeline continuations now bypass the 30-minute app review cooldown
  • Pipeline artifacts (e.g., REVIEW.md) not cleaned up after final stage — automated cleanup now deletes fileNotExists precondition files when pipeline completes
  • Self-update failing with "exit code null" at npm-install step — PM2 watch restarted the server during git checkout (which changes server/ files), breaking the stdout pipe to the update script. SIGPIPE killed the script before || true could handle it, leaving the update incomplete. Added trap '' PIPE to ignore SIGPIPE so the script runs to completion.
  • Improved update error messages to show signal name (e.g., "killed by SIGPIPE") instead of opaque "exit code null"
  • Setup falsely reporting "Setup Complete!" when native PostgreSQL is selected but not installed — now auto-runs db.sh setup-native to install and configure PostgreSQL via Homebrew, and exits with error if setup fails instead of silently continuing

Added

  • Toggle to enable/disable all automations for an app on the Automation tab
  • "Process Now" button on pending task cards to force-spawn a specific task, bypassing cooldowns and evaluation intervals

Full Changelog

Full Diff: v1.39.0...v1.40.0

v1.39.0

28 Mar 19:26

Choose a tag to compare

Release v1.39.0

Released: 2026-03-28

Added

  • AI usage spike detection in proactive alerts — detects when daily token or session counts exceed 2.5x the 14-day rolling average
  • PR reviewer now scans for malicious content (prompt injection, data exfiltration, supply chain attacks) and verifies GOALS.md alignment before approving
  • PR reviewer verifies CI/CD passes and auto-merges clean PRs with squash + branch cleanup
  • Global Pause toggle with info tooltip on task schedule UI — replaces ambiguous "Enabled" toggle
  • Shared loadSlashdoFile utility in fileUtils.js for loading slashdo commands with !cat include resolution
  • Multi-stage task pipeline system — chain sequential agent stages where each stage gates the next
  • PR reviewer now runs as a 2-stage pipeline: security scan (read-only) → code review + merge
  • Pipeline stage badge on agent cards showing current stage progress
  • getStagePrompt() export in taskSchedule for resolving pipeline stage-specific prompts
  • Pipeline UI: collapsed row shows purple "2-stage" badge, expanded view shows stage flow visualization
  • Pipeline UI: tabbed prompt viewer shows each stage's full prompt with stage name tabs
  • Code reviewer pipeline tasks (code-reviewer-a, code-reviewer-b) — 2-stage pipeline where stage 1 reviews the codebase and writes REVIEW.md, stage 2 triages and implements recommendations
  • Per-stage provider/model support for multi-stage pipelines — each stage can use a different AI provider (e.g., Gemini reviews, Claude Opus implements)
  • REVIEW.md and REJECTED.md added to allowed app documents
  • MortalLoom export now includes goals, reads actual custom drink/nicotine presets, and parallelizes all I/O
  • MeatSpace Settings tab with import/export functionality
  • Browser download support via CDP Browser.setDownloadBehavior — downloads now land in data/browser-downloads/
  • Downloads section on Browser page showing file list with size and date
  • /api/browser/downloads endpoint for listing downloaded files
  • Genome markers: summary dashboard with tappable status filter pills, "Attention Needed" section surfacing concerns first, category quick-jump dropdown, categories collapsed by default for mobile
  • Genome markers: friendlier card UX with "What this means for you" framing, status-colored backgrounds, and renamed labels (Details, Your Notes, Learn More)
  • Voice capture for Brain — microphone button on inbox uses Web Speech API to transcribe speech into thoughts
  • Legacy Portrait export format — comprehensive human-readable Markdown document consolidating identity docs, traits, chronotype, taste profile, genome, longevity, goals, autobiography, and social presence
  • Autobiography prompt chains — LLM-generated follow-up questions after saving a story, enabling deeper exploration of life themes with linked story chains
  • RSS/Atom feed ingestion — subscribe to feeds, fetch/parse articles, read/mark-read from Brain > Feeds tab
  • AI-powered goal check-ins — "Run Check-In" button on goal detail panel generates LLM assessment of goal health (on-track/behind/at-risk), actionable recommendations, and motivational encouragement based on progress, velocity, milestones, and activity attendance
  • Chronotype-aware scheduling — Calendar Day and Week views now show genome-derived energy zone overlays (peak focus, exercise, wind-down) and cutoff markers (caffeine, last meal) based on the user's chronotype profile
  • Pipeline agent cards: stage-tabbed output view — Show button displays separate output panes for each pipeline stage with status indicators and on-demand loading
  • Agent cleanup warnings now surface in the UI — worktree merge failures, PR creation failures, and preserved worktrees show as yellow warnings in the agent card, completion toast, and notification bell

Changed

  • MeatSpace Import tab renamed to Settings — consolidates import and export in one place
  • Pipeline stages now display per-stage provider/model in Schedule tab UI
  • Fixed metadata.provider field mapping so scheduled task provider overrides are correctly passed to the agent spawner
  • PR reviewer prompt no longer requires global slash-do install — review checklist is inlined from bundled submodule
  • Removed duplicate pr-reviewer skill template from data.sample (single source of truth in taskSchedule.js)

Fixed

  • CoS orphan detection now checks if the agent completed successfully before treating a task as orphaned — prevents false orphan loops after server restarts
  • handleAgentCompletion now logs when updateTask returns an error, making silent task update failures visible in server logs
  • Digital twin sync now uses deep union merge for longevity/chronotype files, preserving genomic marker data across instances
  • Character avatar image now synced between instances alongside character metadata
  • Snapshot sync status no longer shows false "behind" when remote doesn't report checksums
  • Agent worktree branches now cleaned up even when worktree directory is already gone (fixes lingering branches after server restarts)
  • Instance names like "null", "void", "NaN", "undefined" are now accepted as valid hostnames
  • Peer renames no longer revert when remote peer re-announces (handleAnnounce now preserves user-set names)
  • Self instance card now shows sync status for all categories (Goals, Character, Digital Twin, Meatspace), not just Brain and Memory
  • CoS task evaluation now blocks tasks that exceeded max spawn limit before reaching spawn logic
  • Metadata count fields (totalSpawnCount, failureCount, orphanRetryCount) use Number() coercion to prevent string comparison bugs
  • jira-status-report task now runs in PortOS context (not the app's directory) and uses the correct PortOS API endpoint
  • jira-status-report agents no longer attempt to commit, push, or modify files (readOnly metadata flag)
  • readOnly tasks skip unnecessary git pull, JIRA branch creation, and worktree setup
  • Flaky test suite stabilized by increasing vitest timeout from 5s to 10s (parallel execution pressure caused intermittent timeouts)
  • Added PORTOS_API_URL constant to ports.js for dynamic API URL resolution in task prompts
  • Worktree merge failures now abort cleanly (merge --abort) instead of leaving the repo in MERGING state
  • Failed merges now preserve the branch for manual recovery instead of force-deleting it and orphaning commits
  • Orphaned worktree cleanup now attempts to merge committed work before removing (prevents losing PR/push failure preserved work)
  • External-repo worktrees (managed app agents) now cleaned up properly — previously invisible to git worktree list and accumulated on disk
  • Stash pop after rebase abort now handles conflicts consistently (checkout + drop) instead of leaving stale stashes

Removed

Full Changelog

Full Diff: v1.38.0...v1.39.0

v1.38.0

25 Mar 21:23
6a9ad67

Choose a tag to compare

Release v1.38.0

Released: 2026-03-25

Added

  • Time Capsule Snapshots for Digital Twin — create versioned archives of your complete digital twin (documents, traits, goals, genome, autobiography, test history) to track identity evolution over time. Includes create, view, compare, and delete functionality with a dedicated tab at /digital-twin/time-capsule
  • Granular per-peer data sync categories for PortOS Federation — enable/disable sync independently for Brain, Memory, Goals, Character, Digital Twin, and Meatspace data per peer instance. All categories disabled by default. Expandable sync categories panel on each peer card with enable/disable all controls. Snapshot-based sync with entity-level merge using last-writer-wins conflict resolution — never loses data from either side
  • Proactive alerts system with dashboard widget for system health monitoring
  • Bulk cleanup of merged git branches
  • Slashdo bundled as git submodule for reliable command access
  • CoS agents generate rich PR descriptions from branch commits and diff stats

Changed

  • Goals page: replace "Add Root Goal" button with inline quick-add input for faster goal creation
  • Goals page: remove manual refresh button, use Loader2 spinner for loading state
  • Goals page: mobile responsive redesign with drag-and-drop reparenting
  • Goals page: add provider/model selector to organize button, default to list view
  • CoS panel fully collapsible with 0px width when closed

Fixed

  • Toggle switches rendering oversized due to min-h/min-w 44px touch-target constraints inflating the visual element
  • Brain scheduler CLI error messages now include actual CLI output for diagnosability
  • Brain CLI provider stdin warning by closing stdin on spawn
  • Brain default model/provider in data.sample for new users
  • CoS spurious orphan retries from agent completion race
  • Goals nav link points to list view, expand all goals by default
  • Schedule badge styling with consistent pill design
  • Sidebar theme and ambient buttons hidden when collapsed

Full Changelog

Full Diff: v1.37.0...v1.38.0

v1.37.0

25 Mar 02:36
3a6f731

Choose a tag to compare

Release v1.37.0

Released: 2026-03-24

Added

  • Image Generation Settings — New Settings > Image Gen tab for configuring Stable Diffusion API (AUTOMATIC1111 / Forge WebUI). Auto-detects Flux models and adjusts parameters accordingly.
  • CoS Tools Registry — New onboard tools system (data/tools/) that lets CoS agents discover and use instance-specific capabilities like image generation. Tools are exposed in agent prompts via getToolsSummaryForPrompt().
  • Character Avatar Generation — D&D Character Sheet now supports AI-generated avatars via the configured SD API. Hover over the avatar area to generate a new portrait.
  • Image serving — Generated images stored in data/images/ and served via /data/images/ static route.
  • Diffusion progress streaming — Image generation now streams intermediate diffusion steps via Socket.IO. The character avatar shows a live preview of the image forming, a progress bar, and step counter during generation.

Fixed

  • Avatar images broken in dev mode — Added /data proxy to Vite dev config so generated images load correctly when running npm run dev.

Full Changelog

Full Diff: v1.36.0...v1.37.0