Releases: atomantic/PortOS
v1.44.1
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:303chained.catch()ontoagentActionExecutor.init(), but thatinit()is synchronous and returnsundefined. The.catchcall threw at module load, crashingportos-serverimmediately after PM2 started it. Introduced during the v1.44.0 cycle and shipped because the release pipeline had no step that actually bootedserver/index.js— unit tests (vitest) import service modules in isolation and never execute the top-level initialization inindex.js, andnpm run buildonly builds the client. Dropped the.catchsinceinit()is sync; added a newnpm run smokestep (scripts/smoke-boot.js) that spawnsserver/index.jsin 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.shtemplate — auto-detects schemes, defaults to every available platform — the deploy script generator PortOS installs into Xcode projects (generateDeployScriptinserver/services/xcodeScripts.js) now produces a single universal template that auto-detects available schemes (trying bothTargetName/TargetName macOS/TargetName_WatchandTargetName_iOS/TargetName_macOS/TargetName_watchOScandidates) so one template works across all naming conventions. The default (./deploy.shwith 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--allto 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 restoresproject.ymlandproject.pbxprojto their byte-exact pre-bump state, so a failed upload doesn't permanently consume a build number committed to main.--transport DAVon iOS/watchOS uploads for more reliable multipart handling. SharedexportOptions.plistacross platforms (was duplicated three times). Explicit--ios/--macos/--watchflags hard-error on missing schemes;--alland the default silently skip missing ones. Existing per-project deploy.sh files are NEVER overwritten byinstallScripts— this new template only lands when installing into projects that don't already have one.scaffoldXcode.jsREADME 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 atlib/tailscale-https.jsexportingcreateTailscaleServers,watchCertReload, andhasTailscaleCert. PortOS itself now uses the helper (dogfood). App schema gains an optionaltlsPortfield — when set, the Launch button on the app grid and detail view openshttps://<host>:<tlsPort>/as the primary action (with plain HTTP demoted to a muted secondary button, and Dev UI still reachable whendevUiPortis set). The PortOS baseline app auto-reflectstlsPort: PORTS.APIwhenever 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 touiPort + 1000), PortOS copieslib/tailscale-https.jsinto the target app's repo at<repoPath>/lib/tailscale-https.jsand records thetlsPortinapps.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 pointsCERT_DIRat (or symlinks)data/certsin the PortOS install. New backend routePOST /api/apps/:id/upgrade-tls { tlsPort, force }(409ALREADY_EXISTSwhen a helper already lives in the target). Client launch URLs consolidated intoclient/src/services/appUrls.js(getLaunchUrls,getPrimaryLaunchUrl) so tile and detail views build URLs through one function.apiCore.request()now enriches thrown errors witherr.code+err.statusso callers can branch on server error codes. -
Cyber Muse CoS avatar — GLB-backed holographic head — new
museoption 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-supplieddata/avatar/model.glbthrough a new/api/avatar/model.glbroute (server/routes/avatar.js, HEAD + GET, 404 when missing,model/gltf-binarywhen 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 onuseGLTF(drei) and reuses the existing Sparkles/halo/ground-glow chrome. Zod enum foravatarStylegained'muse'inserver/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, sohttps://localhost:5555always tripped a cert warning. When HTTPS is active the server now also spins up a plain HTTP listener bound to127.0.0.1:5553that attaches to the same Express app and Socket.IO instance —http://localhost:5553works without cert warnings and Chrome still treats it as a secure context (so getUserMedia / mic access continues to work). Override the port viaPORTOS_HTTP_PORT. Documented indocs/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_navigatetool 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 stabledata-voice-refrefs, and caps at 200 elements.useVoiceUiSynchook (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 soonChangefires),ui_select(dropdowns with fuzzy option matching),ui_check(checkboxes + radios),ui_list_interactables(deep-dive fallback). Misses return a helpfulavailablelist 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 throughhttps://<host>instead ofhttp://<ip>— so app links inPeerAppsListalso upgrade to HTTPS automatically. NewGET /api/instances/tailnet-suffixendpoint shells out to the localtailscale status --jsonand 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.updatePeernow accepts an optionalhostfield (validated as a DNS name; empty string clears); invalid hosts return 400 instead of silent no-ops.addPeeralso acceptshostfor direct-DNS registration. Vite dev proxy auto-detectsdata/certs/cert.pemand flips its target tohttps://localhost:5555withsecure: falsewhen 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 a100.x.x.xTailscale IP because the origin isn't a secure context. Newscripts/setup-cert.jsprefers a real Let's Encrypt cert viatailscale cert <machine>.<tailnet>.ts.net(Tailscale...
v1.43.0
Release v1.43.0
Released: 2026-04-14
Added
- Test coverage for 7 previously untested modules:
commandSecurity,httpClient,platform,memoryBM25,notifications,search, andtaskSchedule— 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.shwith--ios,--macos,--watch,--allflags for TestFlight deployment - Generic
take_screenshots.shandtake_screenshots_macos.shfor App Store screenshot automation - UI test target with
ScreenshotTests.swiftstubs for XCUITest-based screenshot capture - Shared module for cross-platform code, macOS entitlements, watchOS companion app
- Generic
- 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
/simplifynow 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.shtemplate — altool upload check false-positive — generated deploy scripts grepped altool output for plainERROR:to detect upload failures, but altool's multipart uploader logs every transient retry asERROR: [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 inxcodeScripts.js. -
Submodule status API (
/api/git/submodules/status) always returned empty array —stdout.trim()was stripping the leading space status character fromgit submodule statusoutput, 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-toplevelmatches the expected worktree path before trustinggit status; prevents broken worktrees (missing.gitfile) 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 viaGET /api/v0/models, auto-loads the configured model (or first available LLM) viaPOST /api/v1/models/load, and retries with the actually-loaded model id — mirroring the existing embedding auto-load path inmemoryEmbeddings.js -
Browser CDP downloads reverting to
~/Downloads—Browser.setDownloadBehavioris DevTools-session-scoped in Chrome: the instant the WebSocket that issued the command closes, Chrome tears down the session'sBrowserHandlerand 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.jsnow 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
questionIndexwith each response; server scorers (both local and LLM-based) user.questionIndex ?? iso the correct challenge is paired with each answer
Full Changelog
Full Diff: v1.42.0...v1.43.0
v1.42.0
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-swiftthat queue CoS agent tasks with the full command instructions - Multi-line task context now renders as a dedicated
### Task Contextsection 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
agentPromptBuilderwhen actually using a worktree app-improve-task IDs were gettingtask-prefix added bytaskParser.js, causingupdateTasklookups to fail — tasks were never marked in_progress or completed after agent runs- Recovered
app-improve-agents after server restart now correctly infertaskType: 'internal'instead of'user' - Extracted
hasKnownPrefix()andisInternalTaskId()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
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 tocos/constants.jsfor shared agent option toggle button styling; applied in ScheduleTab and AutomationTab - Wrapped
AppOverrideRowinmemoto 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+intervalinstead of post-hoc tolerance hack, eliminating drift-based day-skip bug
Fixed
- Scheduled jobs with
scheduledTimecould drift and skip a day after accumulating small timing errors — now cron is synthesized fromscheduledTimeat compute time for exact daily/weekday scheduling - Per-app cron scheduled tasks (e.g.
feature-ideasat 1am) could be delayed up toeligibleInms 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
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
axioswith ownedserver/lib/httpClient.js(fetch-based, AbortSignal.timeout, self-signed TLS via https.Agent) - Replace
multerwith ownedserver/lib/multipart.js(streaming multipart parser, no memory buffering, safe for 500MB+ files) - Replace
unzipperwith ownedserver/lib/zipStream.js(streaming ZIP parser via zlib.createInflateRaw, DEFLATE + stored entries) - Remove
corspackage from scaffold-generated project templates; generated code now uses inline CORS middleware
Changed
- Replace
node-telegram-bot-apiwith ownedserver/lib/telegramClient.js(fetch-based polling loop, all bot methods) - Replace
supertestwith ownedserver/lib/testHelper.js(HTTP server lifecycle + fetch-based request wrapper; 9 test files updated) - Replace
react-hot-toastwith ownedclient/src/components/ui/Toast.jsx(module-level store, Toaster component; 101 import sites updated) - Replace
react-markdownwith inline regex block/inline parser inMarkdownOutput.jsx(h1–h6, bold, italic, code, tables, lists, links) - Replace
react-diff-viewer-continuedwith inline Myers LCS diff inCrossDomainTab.jsx;InlineDiffwrapped withReact.memo - Replace
fflatedirect usage with nativeDecompressionStream+ inline EOCD ZIP parser inGenomeTab.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
.npmrcignore-scripts=true;install:allexplicitly 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.jsis 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:readyhandler now catches errors and emitsjob:spawn-failedto re-register the timer; 5-minute spawning timeout also re-registers as safety net - Bug:
providerOverridewas incorrectly passed as model argument inprocessEnrichmentAnswer; corrected tomodelOverride - Dynamic
import()ofsafeJSONParseinsideanalyzeEnrichmentListreplaced with static top-level import loadMeta()was called inside per-document loop inanalyzeAssessment; hoisted out to load once
Changed
getDocuments()now parallelizes allstat()calls withPromise.allgetAllTwinContent()now parallelizes allreadFile()calls withPromise.all- Added
extractJSON()andensureDocumentInMeta()helpers todigital-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/isFalsyMetaconsolidated intoagentState.js(single source of truth)terminateAgent/killAgentrunner path de-duplicated via sharedterminateRunnerAgenthelperkillAllAgentsnow terminates all agents in parallel withPromise.allbuildAgentPromptcontext fetches (memory, CLAUDE.md, digital twin, tools) and.planning/file reads now run in parallelsafeParseinagentCliSpawning.jsreplaced withsafeJSONParsefrom fileUtils- Removed TOCTOU
existsSyncguards inagentPromptBuilder.js; rely on.catch(() => null)instead
Fixed
- Auto-update from the UI was failing at
git fetchstep — switched fromportos-update.sh(tag checkout) toupdate.sh(git pull --rebase) which adds STEP markers for UI progress, completion markers for boot-time result recording, and Windows support viaupdate.ps1 - Scheduled AI jobs (e.g. Daily Briefing) could get permanently stuck as "Due" if agent spawn failed —
task:readyhandler now catches errors and emitsjob:spawn-failedto re-register the timer httpClient.jsnow 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.jsimportedcompleteExecution/errorExecutionfromexecutionLanes.js(wrong module); corrected to import fromtoolStateMachine.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 inTaskAddFormcompact mode removed (referenced select id that no longer exists after AppContextPicker refactor) - XSS:
MarkdownOutput.jsxlinks now validatehrefprotocol (allowhttp://,https://,/only); unsafe URIs render as plain text - Toast notifications missing background color — added
bg-port-cardwith border InlineDiffword diff usedSetwhich collapsed duplicate common words; replaced with sequential LCS pointer matchinghttpClient.jsnow auto-setsContent-Type: application/jsonwhen sending JSON bodyzipStream.jssanitizes ZIP entry paths (normalizes separators, strips..and.components)multipart.jssanitizes file extension to alphanumeric characters only
Added
AppContextPickercomponent — reusable app selector with repo path display; replaces inline<select>inTaskAddForm(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
defaultSessionconfig key has no matching session formatDateTimeadded toclient/src/utils/formatters.js(medium date + short time viaIntl.DateTimeFormat)readFileAsBase64exported fromclient/src/utils/fileUpload.jsfor reuse across components
Changed
- OpenClaw integration rewritten to use OpenResponses
/v1/responsesAPI and/tools/invokefor session discovery normalizeAttachmentbuilds OpenAI-compatibleinput_image/input_fileblocks from base64 or URL sourcesstreamSessionMessageproxies upstream SSE withtimeoutMs: 0for long-running streaming responsesfetchWithTimeoutacceptstimeoutMs: 0to opt out of the timeout (needed for streaming)loadRuntimestabilized viaselectedSessionIdRef— session switches no longer trigger a full runtime reload- After send, session
lastMessageAtupdated locally instead of triggering a fullloadRuntime()reload contextstate in OpenClaw simplified — removed derivedappName/repoPath; computed at send time- Duplicate
setMessagesupdate pattern inhandleSendextracted intoupdateAssistant(updater)helper
Full Changelog
Full Diff: v1.41.0...v1.41.1
v1.41.0
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
axioswith ownedserver/lib/httpClient.js(fetch-based, AbortSignal.timeout, self-signed TLS via https.Agent) - Replace
multerwith ownedserver/lib/multipart.js(streaming multipart parser, no memory buffering, safe for 500MB+ files) - Replace
unzipperwith ownedserver/lib/zipStream.js(streaming ZIP parser via zlib.createInflateRaw, DEFLATE + stored entries) - Remove
corspackage from scaffold-generated project templates; generated code now uses inline CORS middleware
Changed
- Replace
node-telegram-bot-apiwith ownedserver/lib/telegramClient.js(fetch-based polling loop, all bot methods) - Replace
supertestwith ownedserver/lib/testHelper.js(HTTP server lifecycle + fetch-based request wrapper; 9 test files updated) - Replace
react-hot-toastwith ownedclient/src/components/ui/Toast.jsx(module-level store, Toaster component; 101 import sites updated) - Replace
react-markdownwith inline regex block/inline parser inMarkdownOutput.jsx(h1–h6, bold, italic, code, tables, lists, links) - Replace
react-diff-viewer-continuedwith inline Myers LCS diff inCrossDomainTab.jsx;InlineDiffwrapped withReact.memo - Replace
fflatedirect usage with nativeDecompressionStream+ inline EOCD ZIP parser inGenomeTab.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
.npmrcignore-scripts=true;install:allexplicitly 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.jsis now a thin barrel re-export
Fixed
- Bug:
providerOverridewas incorrectly passed as model argument inprocessEnrichmentAnswer; corrected tomodelOverride - Dynamic
import()ofsafeJSONParseinsideanalyzeEnrichmentListreplaced with static top-level import loadMeta()was called inside per-document loop inanalyzeAssessment; hoisted out to load once
Changed
getDocuments()now parallelizes allstat()calls withPromise.allgetAllTwinContent()now parallelizes allreadFile()calls withPromise.all- Added
extractJSON()andensureDocumentInMeta()helpers todigital-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/isFalsyMetaconsolidated intoagentState.js(single source of truth)terminateAgent/killAgentrunner path de-duplicated via sharedterminateRunnerAgenthelperkillAllAgentsnow terminates all agents in parallel withPromise.allbuildAgentPromptcontext fetches (memory, CLAUDE.md, digital twin, tools) and.planning/file reads now run in parallelsafeParseinagentCliSpawning.jsreplaced withsafeJSONParsefrom fileUtils- Removed TOCTOU
existsSyncguards inagentPromptBuilder.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.jsimportedcompleteExecution/errorExecutionfromexecutionLanes.js(wrong module); corrected to import fromtoolStateMachine.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 inTaskAddFormcompact mode removed (referenced select id that no longer exists after AppContextPicker refactor) - XSS:
MarkdownOutput.jsxlinks now validatehrefprotocol (allowhttp://,https://,/only); unsafe URIs render as plain text - Toast notifications missing background color — added
bg-port-cardwith border InlineDiffword diff usedSetwhich collapsed duplicate common words; replaced with sequential LCS pointer matchinghttpClient.jsnow auto-setsContent-Type: application/jsonwhen sending JSON bodyzipStream.jssanitizes ZIP entry paths (normalizes separators, strips..and.components)multipart.jssanitizes file extension to alphanumeric characters only
Added
AppContextPickercomponent — reusable app selector with repo path display; replaces inline<select>inTaskAddForm(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
defaultSessionconfig key has no matching session formatDateTimeadded toclient/src/utils/formatters.js(medium date + short time viaIntl.DateTimeFormat)readFileAsBase64exported fromclient/src/utils/fileUpload.jsfor reuse across components
Changed
- OpenClaw integration rewritten to use OpenResponses
/v1/responsesAPI and/tools/invokefor session discovery normalizeAttachmentbuilds OpenAI-compatibleinput_image/input_fileblocks from base64 or URL sourcesstreamSessionMessageproxies upstream SSE withtimeoutMs: 0for long-running streaming responsesfetchWithTimeoutacceptstimeoutMs: 0to opt out of the timeout (needed for streaming)loadRuntimestabilized viaselectedSessionIdRef— session switches no longer trigger a full runtime reload- After send, session
lastMessageAtupdated locally instead of triggering a fullloadRuntime()reload contextstate in OpenClaw simplified — removed derivedappName/repoPath; computed at send time- Duplicate
setMessagesupdate pattern inhandleSendextracted intoupdateAssistant(updater)helper
v1.40.0
Release v1.40.0
Released: 2026-03-29
Fixed
- Scheduled tasks defaulting to enabled for existing apps when new task types are added —
isTaskTypeEnabledForAppnow 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
idandstatus: 'pending'fields when created withraw: 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 (expectedsys-prefix), causingupdateTaskto 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
fileNotExistsprecondition files when pipeline completes - Self-update failing with "exit code null" at npm-install step — PM2 watch restarted the server during
git checkout(which changesserver/files), breaking the stdout pipe to the update script. SIGPIPE killed the script before|| truecould handle it, leaving the update incomplete. Addedtrap '' PIPEto 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-nativeto 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
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
loadSlashdoFileutility in fileUtils.js for loading slashdo commands with!catinclude 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 indata/browser-downloads/ - Downloads section on Browser page showing file list with size and date
/api/browser/downloadsendpoint 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.providerfield mapping so scheduled task provider overrides are correctly passed to the agent spawner - PR reviewer prompt no longer requires global
slash-doinstall — 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_URLconstant toports.jsfor 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 listand 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
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
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 viagetToolsSummaryForPrompt(). - 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
/dataproxy to Vite dev config so generated images load correctly when runningnpm run dev.
Full Changelog
Full Diff: v1.36.0...v1.37.0