diff --git a/electron-builder.yml b/electron-builder.yml index e91c78f..829d41d 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -27,6 +27,9 @@ asarUnpack: # level deeper than the entry point: mcp-bots.js unpacked fine and still died on # `Cannot find module './bots.js'`. Pinned by test/asar-helpers.test.js. - "bots.js" + # One level deeper the same trap: mcp-task-manager.js requires the task-text limit, + # so that module has to sit outside the archive with it. + - "task-text-limit.js" files: - "**/*" diff --git a/mcp-task-manager.js b/mcp-task-manager.js index a486b8e..1adf933 100644 --- a/mcp-task-manager.js +++ b/mcp-task-manager.js @@ -13,6 +13,9 @@ const http = require('http'); const { StringDecoder } = require('string_decoder'); +// Same limit the HTTP API enforces; advertising a smaller one here makes the model +// shorten a task for no reason. +const { MAX_TASK_TEXT } = require('./task-text-limit.js'); const SERVER_URL = process.env.TASK_MANAGER_SERVER_URL || 'http://127.0.0.1:3000'; const TASK_ID = process.env.TASK_MANAGER_TASK_ID || ''; @@ -42,7 +45,7 @@ const TOOLS = [ type: 'object', properties: { title: { type: 'string', description: 'Short task title (max 200 chars)' }, - description: { type: 'string', description: 'Detailed task description (max 2000 chars)' }, + description: { type: 'string', description: `Detailed task description (max ${MAX_TASK_TEXT} chars)` }, status: { type: 'string', enum: ['backlog', 'todo', 'done'], description: 'todo = queue it for execution now (default). backlog = add to the board only, nothing runs. done = an already-finished item, e.g. a "- [x]" line from a plan you are importing.' }, context: { description: 'Curated context to pass to the child task. Include ONLY what the child needs — issue details, code snippets, error messages, etc. Can be a string or a JSON object. The child reads this via get_current_task.', diff --git a/package.json b/package.json index 1327428..68557e5 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "scripts": { "start": "node server.js", "dev": "node --watch server.js", - "test": "node --test test/render/*.test.mjs && node test/overload-detector.test.js && node test/usage-limit.test.js && node test/auth-errors.test.js && node test/env-load-order.test.js && node test/multi-agent-result.test.js && node test/terminal-session.test.js && node test/terminal-schema.test.js && node test/bots.test.js && node test/bot-inbox.test.js && node test/bots-api.test.js && node test/running-sessions.test.js && node test/session-liveness.test.js && node test/terminal-bridge.integration.test.js && node test/tmux-composite.test.js && node test/engine-spawn-cmd.test.js && node test/claude-firstrun.test.js && node test/telegram-format.test.js && node test/telegram-behaviour.test.js && node test/ask-user-question.test.js && node test/delegate-terminal.test.js && node test/agent-catalog.test.js && node test/update-flow.test.js && node test/kanban-schedule.test.js && node test/kanban-run-badges.test.js && node test/task-backlog.test.js && node test/i18n-completeness.test.js && node test/config-resolve.test.js && node test/chat-defaults.test.js && node test/chat-defaults-api.test.js && node test/run-continuation.test.js && node test/worktree-manager.test.js && node test/session-expiry.test.js && node test/setup-gate.test.js && node test/path-guard.test.js && node test/subscribe-nocatchup.test.js && node test/cli-import-remote.test.js && node test/remote-list-parse.test.js && node test/config-migrate.test.js && node test/engine-pane.test.js && node test/global-workspace.test.js && node test/ssh-secret.test.js && node test/agent-dag.test.js && node test/ssh-parser.test.js && node test/ssh-termination.test.js && node test/session-restart.test.js && node test/remote-env.test.js && node test/remote-files.test.js && node test/remote-files-api.test.js && node test/auth-token.test.js && node test/cmd-model.test.js && node test/origin-guard.test.js && node test/interrupted-recovery.test.js && node test/queue-persistence.test.js && node test/interrupt-idle-config.test.js && node test/agents-md.test.js && node test/editor-links.test.js && node test/editor-open-api.test.js && node test/interrupt-delivery.test.js && node test/terminal-pane-guard.integration.test.js && node test/composer-terminal.test.js && node test/claude-cli-status.test.js && node test/asar-helpers.test.js && node test/mac-signing.test.js && node test/release-mac.test.js && node test/task-workers.test.js && node test/git-clone.test.js && node test/responsive-ui.test.js && node test/kanban-delegation.test.js && node test/kanban-group-button.test.js && node test/terminal-keys.test.js && node test/electron-navigation.test.js && node test/cli-runtime.test.js && node test/worktree-safety.test.js && node test/auth-boundary.test.js && node test/cli-process-tree.test.js && node test/schedule-actions.test.js && node test/install-hooks.test.js && node test/frontend-recovery.test.js && node test/db-revisions.test.js && node test/frontend-refresh-races.test.js && node test/release-gate.test.js && node test/focused-workspace.test.js && node test/secondary-navigation.test.js && node test/section-controls-ux.test.js && node test/settings-ux.test.js && node test/team-forms-ux.test.js && node test/page-forms-ux.test.js && node test/sidebar-ux.test.js", + "test": "node --test test/render/*.test.mjs && node test/overload-detector.test.js && node test/usage-limit.test.js && node test/auth-errors.test.js && node test/env-load-order.test.js && node test/multi-agent-result.test.js && node test/terminal-session.test.js && node test/terminal-schema.test.js && node test/bots.test.js && node test/bot-inbox.test.js && node test/bots-api.test.js && node test/running-sessions.test.js && node test/session-liveness.test.js && node test/terminal-bridge.integration.test.js && node test/tmux-composite.test.js && node test/engine-spawn-cmd.test.js && node test/claude-firstrun.test.js && node test/telegram-format.test.js && node test/telegram-behaviour.test.js && node test/ask-user-question.test.js && node test/delegate-terminal.test.js && node test/agent-catalog.test.js && node test/update-flow.test.js && node test/kanban-schedule.test.js && node test/kanban-run-badges.test.js && node test/task-backlog.test.js && node test/i18n-completeness.test.js && node test/config-resolve.test.js && node test/chat-defaults.test.js && node test/chat-defaults-api.test.js && node test/run-continuation.test.js && node test/worktree-manager.test.js && node test/session-expiry.test.js && node test/setup-gate.test.js && node test/path-guard.test.js && node test/subscribe-nocatchup.test.js && node test/cli-import-remote.test.js && node test/remote-list-parse.test.js && node test/config-migrate.test.js && node test/engine-pane.test.js && node test/global-workspace.test.js && node test/ssh-secret.test.js && node test/agent-dag.test.js && node test/ssh-parser.test.js && node test/ssh-termination.test.js && node test/session-restart.test.js && node test/remote-env.test.js && node test/remote-files.test.js && node test/remote-files-api.test.js && node test/auth-token.test.js && node test/cmd-model.test.js && node test/origin-guard.test.js && node test/interrupted-recovery.test.js && node test/queue-persistence.test.js && node test/interrupt-idle-config.test.js && node test/agents-md.test.js && node test/editor-links.test.js && node test/editor-open-api.test.js && node test/interrupt-delivery.test.js && node test/terminal-pane-guard.integration.test.js && node test/composer-terminal.test.js && node test/claude-cli-status.test.js && node test/asar-helpers.test.js && node test/mac-signing.test.js && node test/release-mac.test.js && node test/task-workers.test.js && node test/git-clone.test.js && node test/responsive-ui.test.js && node test/kanban-delegation.test.js && node test/kanban-group-button.test.js && node test/terminal-keys.test.js && node test/electron-navigation.test.js && node test/cli-runtime.test.js && node test/worktree-safety.test.js && node test/auth-boundary.test.js && node test/cli-process-tree.test.js && node test/schedule-actions.test.js && node test/install-hooks.test.js && node test/frontend-recovery.test.js && node test/db-revisions.test.js && node test/frontend-refresh-races.test.js && node test/release-gate.test.js && node test/focused-workspace.test.js && node test/secondary-navigation.test.js && node test/section-controls-ux.test.js && node test/settings-ux.test.js && node test/team-forms-ux.test.js && node test/page-forms-ux.test.js && node test/sidebar-ux.test.js && node test/task-text-limit.test.js", "postinstall": "node scripts/install-hooks.js", "release": "node scripts/release.js", "release:mac": "node scripts/release-mac.js", diff --git a/public/kanban.html b/public/kanban.html index 9563df2..8dd2993 100644 --- a/public/kanban.html +++ b/public/kanban.html @@ -465,6 +465,8 @@ .modal-body .sc-sep { display:none; } .modal-body .sc-btn { min-height:32px; } .modal-body :is(input,select,textarea,button):focus-visible { outline:2px solid var(--accent); outline-offset:3px; } +.inp-hint{font-size:11px;color:var(--muted);margin-top:4px;line-height:1.4} +.inp-hint.over{color:var(--red)} .modal-body .inp-hint,.modal-body .sched-hint { line-height:1.6; margin-top:6px; } @media(max-width:600px){ .modal-body .grid2 { grid-template-columns:1fr; } @@ -1030,6 +1032,19 @@ document.documentElement.lang = lang; document.documentElement.dir = (lang === 'he') ? 'rtl' : 'ltr'; +// ─── Task text limit ─────────────────────────────────────────────────────── +// The number server.js stores and mcp-task-manager.js advertises (task-text-limit.js). +// A maxlength attribute cuts a paste without a word, so a field that holds prose +// also carries a counter: it reaches MAX_TASK_TEXT exactly where the text was cut. +const MAX_TASK_TEXT = 20000; +function updTextCount(id, outId) { + const el = $i(id), out = $i(outId); + if (!el || !out) return; + const n = el.value.length; + out.textContent = n + ' / ' + MAX_TASK_TEXT; + out.classList.toggle('over', n >= MAX_TASK_TEXT); +} + // Declarative i18n — same attribute contract as index.html: the markup carries the // key, this pass fills in text/attributes for the active language. Every user-facing // literal in the markup must be annotated; test/i18n-completeness.test.js enforces it. @@ -1952,7 +1967,7 @@