charness 3.6.0 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +274 -0
- package/DEVELOPMENT.md +31 -5
- package/MIGRATION_RENAME_TO_CHARNESS.md +3 -2
- package/README.md +84 -782
- package/SETUP.md +37 -10
- package/agent-plugin/.claude-plugin/plugin.json +7 -0
- package/agent-plugin/README.md +35 -0
- package/agent-plugin/skills/charness-delegate-claude/SKILL.md +85 -0
- package/agent-plugin/skills/charness-delegate-claude/summarize-events.py +90 -0
- package/agent-plugin/skills/charness-delegate-opencode/SKILL.md +68 -0
- package/agent-plugin/skills/charness-manager/SKILL.md +152 -0
- package/dist/adapters/adapterNames.d.ts +6 -0
- package/dist/adapters/adapterNames.d.ts.map +1 -1
- package/dist/adapters/adapterNames.js +8 -2
- package/dist/adapters/adapterNames.js.map +1 -1
- package/dist/adapters/claudeCliAdapter.d.ts +8 -0
- package/dist/adapters/claudeCliAdapter.d.ts.map +1 -1
- package/dist/adapters/claudeCliAdapter.js +42 -5
- package/dist/adapters/claudeCliAdapter.js.map +1 -1
- package/dist/adapters/claudeJsonStreamAdapter.d.ts +10 -9
- package/dist/adapters/claudeJsonStreamAdapter.d.ts.map +1 -1
- package/dist/adapters/claudeJsonStreamAdapter.js +53 -55
- package/dist/adapters/claudeJsonStreamAdapter.js.map +1 -1
- package/dist/adapters/createAdapter.d.ts +8 -0
- package/dist/adapters/createAdapter.d.ts.map +1 -1
- package/dist/adapters/createAdapter.js +14 -2
- package/dist/adapters/createAdapter.js.map +1 -1
- package/dist/adapters/openCodeAdapter.d.ts +43 -6
- package/dist/adapters/openCodeAdapter.d.ts.map +1 -1
- package/dist/adapters/openCodeAdapter.js +95 -6
- package/dist/adapters/openCodeAdapter.js.map +1 -1
- package/dist/agentLogin/agentLogin.d.ts +1 -1
- package/dist/agentLogin/agentLogin.d.ts.map +1 -1
- package/dist/apiRetryKick.d.ts +4 -3
- package/dist/apiRetryKick.d.ts.map +1 -1
- package/dist/apiRetryKick.js +16 -9
- package/dist/apiRetryKick.js.map +1 -1
- package/dist/bot.d.ts.map +1 -1
- package/dist/bot.js +1313 -381
- package/dist/bot.js.map +1 -1
- package/dist/cli/claudeProfiles.d.ts +11 -6
- package/dist/cli/claudeProfiles.d.ts.map +1 -1
- package/dist/cli/claudeProfiles.js +50 -22
- package/dist/cli/claudeProfiles.js.map +1 -1
- package/dist/cli/hot.d.ts +5 -0
- package/dist/cli/hot.d.ts.map +1 -1
- package/dist/cli/hot.js +71 -25
- package/dist/cli/hot.js.map +1 -1
- package/dist/cli/tscWatchGuard.d.ts +95 -0
- package/dist/cli/tscWatchGuard.d.ts.map +1 -0
- package/dist/cli/tscWatchGuard.js +295 -0
- package/dist/cli/tscWatchGuard.js.map +1 -0
- package/dist/cli.js +12 -1
- package/dist/cli.js.map +1 -1
- package/dist/connectors/jira/answerSink.d.ts +10 -0
- package/dist/connectors/jira/answerSink.d.ts.map +1 -1
- package/dist/connectors/jira/answerSink.js +13 -0
- package/dist/connectors/jira/answerSink.js.map +1 -1
- package/dist/connectors/jira/config.d.ts +2 -0
- package/dist/connectors/jira/config.d.ts.map +1 -1
- package/dist/connectors/jira/config.js +9 -1
- package/dist/connectors/jira/config.js.map +1 -1
- package/dist/connectors/jira/connector.d.ts +11 -1
- package/dist/connectors/jira/connector.d.ts.map +1 -1
- package/dist/connectors/jira/connector.js +13 -1
- package/dist/connectors/jira/connector.js.map +1 -1
- package/dist/connectors/jira/inbound.d.ts +29 -4
- package/dist/connectors/jira/inbound.d.ts.map +1 -1
- package/dist/connectors/jira/inbound.js +71 -8
- package/dist/connectors/jira/inbound.js.map +1 -1
- package/dist/connectors/jira/issueBlocks.d.ts +5 -0
- package/dist/connectors/jira/issueBlocks.d.ts.map +1 -1
- package/dist/connectors/jira/issueBlocks.js +11 -0
- package/dist/connectors/jira/issueBlocks.js.map +1 -1
- package/dist/connectors/jira/prompt.d.ts +4 -0
- package/dist/connectors/jira/prompt.d.ts.map +1 -1
- package/dist/connectors/jira/prompt.js +11 -2
- package/dist/connectors/jira/prompt.js.map +1 -1
- package/dist/connectors/telegram/bindPicker.d.ts +5 -0
- package/dist/connectors/telegram/bindPicker.d.ts.map +1 -1
- package/dist/connectors/telegram/bindPicker.js +18 -1
- package/dist/connectors/telegram/bindPicker.js.map +1 -1
- package/dist/connectors/telegram/bindPickerClaims.d.ts +46 -0
- package/dist/connectors/telegram/bindPickerClaims.d.ts.map +1 -0
- package/dist/connectors/telegram/bindPickerClaims.js +83 -0
- package/dist/connectors/telegram/bindPickerClaims.js.map +1 -0
- package/dist/connectors/telegram/bindSweep.d.ts +32 -0
- package/dist/connectors/telegram/bindSweep.d.ts.map +1 -0
- package/dist/connectors/telegram/bindSweep.js +47 -0
- package/dist/connectors/telegram/bindSweep.js.map +1 -0
- package/dist/connectors/telegram/bindingWelcome.d.ts +23 -0
- package/dist/connectors/telegram/bindingWelcome.d.ts.map +1 -0
- package/dist/connectors/telegram/bindingWelcome.js +26 -0
- package/dist/connectors/telegram/bindingWelcome.js.map +1 -0
- package/dist/connectors/telegram/botApiConnection.d.ts +74 -0
- package/dist/connectors/telegram/botApiConnection.d.ts.map +1 -0
- package/dist/connectors/telegram/botApiConnection.js +201 -0
- package/dist/connectors/telegram/botApiConnection.js.map +1 -0
- package/dist/connectors/telegram/commands/botCore.d.ts +8 -2
- package/dist/connectors/telegram/commands/botCore.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/botSkills.d.ts +21 -0
- package/dist/connectors/telegram/commands/botSkills.d.ts.map +1 -0
- package/dist/connectors/telegram/commands/botSkills.js +133 -0
- package/dist/connectors/telegram/commands/botSkills.js.map +1 -0
- package/dist/connectors/telegram/commands/callbackMessage.d.ts +5 -0
- package/dist/connectors/telegram/commands/callbackMessage.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/callbackMessage.js +9 -0
- package/dist/connectors/telegram/commands/callbackMessage.js.map +1 -1
- package/dist/connectors/telegram/commands/compaction.d.ts +65 -3
- package/dist/connectors/telegram/commands/compaction.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/compaction.js +512 -94
- package/dist/connectors/telegram/commands/compaction.js.map +1 -1
- package/dist/connectors/telegram/commands/displayModes.d.ts +1 -1
- package/dist/connectors/telegram/commands/displayModes.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/displayModes.js +6 -18
- package/dist/connectors/telegram/commands/displayModes.js.map +1 -1
- package/dist/connectors/telegram/commands/fallbackChain.js +5 -5
- package/dist/connectors/telegram/commands/fallbackChain.js.map +1 -1
- package/dist/connectors/telegram/commands/reminders.d.ts +1 -1
- package/dist/connectors/telegram/commands/reminders.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/reminders.js +4 -15
- package/dist/connectors/telegram/commands/reminders.js.map +1 -1
- package/dist/connectors/telegram/commands/selfUpdate.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/selfUpdate.js +1 -11
- package/dist/connectors/telegram/commands/selfUpdate.js.map +1 -1
- package/dist/connectors/telegram/commands/taskAgents.d.ts +22 -0
- package/dist/connectors/telegram/commands/taskAgents.d.ts.map +1 -0
- package/dist/connectors/telegram/commands/taskAgents.js +104 -0
- package/dist/connectors/telegram/commands/taskAgents.js.map +1 -0
- package/dist/connectors/telegram/commands/todo.d.ts +82 -0
- package/dist/connectors/telegram/commands/todo.d.ts.map +1 -0
- package/dist/connectors/telegram/commands/todo.js +384 -0
- package/dist/connectors/telegram/commands/todo.js.map +1 -0
- package/dist/connectors/telegram/commands/topicCommand.d.ts +6 -2
- package/dist/connectors/telegram/commands/topicCommand.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/topicCommand.js +6 -9
- package/dist/connectors/telegram/commands/topicCommand.js.map +1 -1
- package/dist/connectors/telegram/openBindMessages.d.ts +45 -0
- package/dist/connectors/telegram/openBindMessages.d.ts.map +1 -0
- package/dist/connectors/telegram/openBindMessages.js +67 -0
- package/dist/connectors/telegram/openBindMessages.js.map +1 -0
- package/dist/connectors/telegram/outputFlushPlan.d.ts +49 -0
- package/dist/connectors/telegram/outputFlushPlan.d.ts.map +1 -1
- package/dist/connectors/telegram/outputFlushPlan.js +46 -0
- package/dist/connectors/telegram/outputFlushPlan.js.map +1 -1
- package/dist/connectors/telegram/pendingTopicName.d.ts +26 -0
- package/dist/connectors/telegram/pendingTopicName.d.ts.map +1 -0
- package/dist/connectors/telegram/pendingTopicName.js +27 -0
- package/dist/connectors/telegram/pendingTopicName.js.map +1 -0
- package/dist/connectors/test/connector.d.ts.map +1 -1
- package/dist/connectors/test/connector.js +6 -1
- package/dist/connectors/test/connector.js.map +1 -1
- package/dist/i18n/de.d.ts.map +1 -1
- package/dist/i18n/de.js +90 -7
- package/dist/i18n/de.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +90 -7
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/es.d.ts.map +1 -1
- package/dist/i18n/es.js +90 -7
- package/dist/i18n/es.js.map +1 -1
- package/dist/i18n/fr.d.ts.map +1 -1
- package/dist/i18n/fr.js +90 -7
- package/dist/i18n/fr.js.map +1 -1
- package/dist/i18n/hi.d.ts.map +1 -1
- package/dist/i18n/hi.js +90 -7
- package/dist/i18n/hi.js.map +1 -1
- package/dist/i18n/ja.d.ts.map +1 -1
- package/dist/i18n/ja.js +90 -7
- package/dist/i18n/ja.js.map +1 -1
- package/dist/i18n/ka.d.ts.map +1 -1
- package/dist/i18n/ka.js +90 -7
- package/dist/i18n/ka.js.map +1 -1
- package/dist/i18n/pt.d.ts.map +1 -1
- package/dist/i18n/pt.js +90 -7
- package/dist/i18n/pt.js.map +1 -1
- package/dist/i18n/ru.d.ts.map +1 -1
- package/dist/i18n/ru.js +90 -7
- package/dist/i18n/ru.js.map +1 -1
- package/dist/i18n/uk.d.ts.map +1 -1
- package/dist/i18n/uk.js +90 -7
- package/dist/i18n/uk.js.map +1 -1
- package/dist/i18n/uz.d.ts.map +1 -1
- package/dist/i18n/uz.js +90 -7
- package/dist/i18n/uz.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +90 -7
- package/dist/i18n/zh.js.map +1 -1
- package/dist/i18n.d.ts +1 -1
- package/dist/i18n.js +1 -1
- package/dist/installManager.d.ts +13 -0
- package/dist/installManager.d.ts.map +1 -1
- package/dist/installManager.js +38 -4
- package/dist/installManager.js.map +1 -1
- package/dist/instanceSettings.d.ts +40 -1
- package/dist/instanceSettings.d.ts.map +1 -1
- package/dist/instanceSettings.js +105 -26
- package/dist/instanceSettings.js.map +1 -1
- package/dist/openCodeQuestionFlow.d.ts +30 -0
- package/dist/openCodeQuestionFlow.d.ts.map +1 -1
- package/dist/openCodeQuestionFlow.js +43 -0
- package/dist/openCodeQuestionFlow.js.map +1 -1
- package/dist/postToSession.d.ts +20 -5
- package/dist/postToSession.d.ts.map +1 -1
- package/dist/postToSession.js +38 -7
- package/dist/postToSession.js.map +1 -1
- package/dist/remoteRun/cliArgs.d.ts +73 -0
- package/dist/remoteRun/cliArgs.d.ts.map +1 -0
- package/dist/remoteRun/cliArgs.js +197 -0
- package/dist/remoteRun/cliArgs.js.map +1 -0
- package/dist/remoteRun/commands.d.ts +56 -0
- package/dist/remoteRun/commands.d.ts.map +1 -0
- package/dist/remoteRun/commands.js +306 -0
- package/dist/remoteRun/commands.js.map +1 -0
- package/dist/remoteRun/depsPlan.d.ts +16 -0
- package/dist/remoteRun/depsPlan.d.ts.map +1 -0
- package/dist/remoteRun/depsPlan.js +82 -0
- package/dist/remoteRun/depsPlan.js.map +1 -0
- package/dist/remoteRun/exitCodes.d.ts +34 -0
- package/dist/remoteRun/exitCodes.d.ts.map +1 -0
- package/dist/remoteRun/exitCodes.js +38 -0
- package/dist/remoteRun/exitCodes.js.map +1 -0
- package/dist/remoteRun/foreground.d.ts +29 -0
- package/dist/remoteRun/foreground.d.ts.map +1 -0
- package/dist/remoteRun/foreground.js +159 -0
- package/dist/remoteRun/foreground.js.map +1 -0
- package/dist/remoteRun/interrupts.d.ts +17 -0
- package/dist/remoteRun/interrupts.d.ts.map +1 -0
- package/dist/remoteRun/interrupts.js +41 -0
- package/dist/remoteRun/interrupts.js.map +1 -0
- package/dist/remoteRun/jobFiles.d.ts +31 -0
- package/dist/remoteRun/jobFiles.d.ts.map +1 -0
- package/dist/remoteRun/jobFiles.js +84 -0
- package/dist/remoteRun/jobFiles.js.map +1 -0
- package/dist/remoteRun/jobFormat.d.ts +16 -0
- package/dist/remoteRun/jobFormat.d.ts.map +1 -0
- package/dist/remoteRun/jobFormat.js +130 -0
- package/dist/remoteRun/jobFormat.js.map +1 -0
- package/dist/remoteRun/jobId.d.ts +15 -0
- package/dist/remoteRun/jobId.d.ts.map +1 -0
- package/dist/remoteRun/jobId.js +85 -0
- package/dist/remoteRun/jobId.js.map +1 -0
- package/dist/remoteRun/jobMeta.d.ts +18 -0
- package/dist/remoteRun/jobMeta.d.ts.map +1 -0
- package/dist/remoteRun/jobMeta.js +33 -0
- package/dist/remoteRun/jobMeta.js.map +1 -0
- package/dist/remoteRun/jobQuery.d.ts +12 -0
- package/dist/remoteRun/jobQuery.d.ts.map +1 -0
- package/dist/remoteRun/jobQuery.js +22 -0
- package/dist/remoteRun/jobQuery.js.map +1 -0
- package/dist/remoteRun/jobRecords.d.ts +22 -0
- package/dist/remoteRun/jobRecords.d.ts.map +1 -0
- package/dist/remoteRun/jobRecords.js +145 -0
- package/dist/remoteRun/jobRecords.js.map +1 -0
- package/dist/remoteRun/jobState.d.ts +62 -0
- package/dist/remoteRun/jobState.d.ts.map +1 -0
- package/dist/remoteRun/jobState.js +132 -0
- package/dist/remoteRun/jobState.js.map +1 -0
- package/dist/remoteRun/leaseTiming.d.ts +18 -0
- package/dist/remoteRun/leaseTiming.d.ts.map +1 -0
- package/dist/remoteRun/leaseTiming.js +43 -0
- package/dist/remoteRun/leaseTiming.js.map +1 -0
- package/dist/remoteRun/output.d.ts +35 -0
- package/dist/remoteRun/output.d.ts.map +1 -0
- package/dist/remoteRun/output.js +82 -0
- package/dist/remoteRun/output.js.map +1 -0
- package/dist/remoteRun/pathPatterns.d.ts +33 -0
- package/dist/remoteRun/pathPatterns.d.ts.map +1 -0
- package/dist/remoteRun/pathPatterns.js +115 -0
- package/dist/remoteRun/pathPatterns.js.map +1 -0
- package/dist/remoteRun/probe.d.ts +56 -0
- package/dist/remoteRun/probe.d.ts.map +1 -0
- package/dist/remoteRun/probe.js +123 -0
- package/dist/remoteRun/probe.js.map +1 -0
- package/dist/remoteRun/project.d.ts +26 -0
- package/dist/remoteRun/project.d.ts.map +1 -0
- package/dist/remoteRun/project.js +159 -0
- package/dist/remoteRun/project.js.map +1 -0
- package/dist/remoteRun/projectConfig.d.ts +38 -0
- package/dist/remoteRun/projectConfig.d.ts.map +1 -0
- package/dist/remoteRun/projectConfig.js +87 -0
- package/dist/remoteRun/projectConfig.js.map +1 -0
- package/dist/remoteRun/remoteRunCli.d.ts +15 -0
- package/dist/remoteRun/remoteRunCli.d.ts.map +1 -0
- package/dist/remoteRun/remoteRunCli.js +144 -0
- package/dist/remoteRun/remoteRunCli.js.map +1 -0
- package/dist/remoteRun/remoteRunError.d.ts +14 -0
- package/dist/remoteRun/remoteRunError.d.ts.map +1 -0
- package/dist/remoteRun/remoteRunError.js +28 -0
- package/dist/remoteRun/remoteRunError.js.map +1 -0
- package/dist/remoteRun/rsync.d.ts +17 -0
- package/dist/remoteRun/rsync.d.ts.map +1 -0
- package/dist/remoteRun/rsync.js +39 -0
- package/dist/remoteRun/rsync.js.map +1 -0
- package/dist/remoteRun/runnerClient.d.ts +50 -0
- package/dist/remoteRun/runnerClient.d.ts.map +1 -0
- package/dist/remoteRun/runnerClient.js +139 -0
- package/dist/remoteRun/runnerClient.js.map +1 -0
- package/dist/remoteRun/runners.d.ts +57 -0
- package/dist/remoteRun/runners.d.ts.map +1 -0
- package/dist/remoteRun/runners.js +181 -0
- package/dist/remoteRun/runners.js.map +1 -0
- package/dist/remoteRun/runnersConfig.d.ts +44 -0
- package/dist/remoteRun/runnersConfig.d.ts.map +1 -0
- package/dist/remoteRun/runnersConfig.js +107 -0
- package/dist/remoteRun/runnersConfig.js.map +1 -0
- package/dist/remoteRun/safeCopy.d.ts +31 -0
- package/dist/remoteRun/safeCopy.d.ts.map +1 -0
- package/dist/remoteRun/safeCopy.js +137 -0
- package/dist/remoteRun/safeCopy.js.map +1 -0
- package/dist/remoteRun/sendPlan.d.ts +67 -0
- package/dist/remoteRun/sendPlan.d.ts.map +1 -0
- package/dist/remoteRun/sendPlan.js +139 -0
- package/dist/remoteRun/sendPlan.js.map +1 -0
- package/dist/remoteRun/ssh.d.ts +62 -0
- package/dist/remoteRun/ssh.d.ts.map +1 -0
- package/dist/remoteRun/ssh.js +202 -0
- package/dist/remoteRun/ssh.js.map +1 -0
- package/dist/remoteRun/submit.d.ts +29 -0
- package/dist/remoteRun/submit.d.ts.map +1 -0
- package/dist/remoteRun/submit.js +142 -0
- package/dist/remoteRun/submit.js.map +1 -0
- package/dist/requests/answerRequest.d.ts +5 -0
- package/dist/requests/answerRequest.d.ts.map +1 -1
- package/dist/requests/answerRequest.js +16 -1
- package/dist/requests/answerRequest.js.map +1 -1
- package/dist/requests/requestLedger.d.ts +13 -0
- package/dist/requests/requestLedger.d.ts.map +1 -1
- package/dist/requests/requestLedger.js +9 -0
- package/dist/requests/requestLedger.js.map +1 -1
- package/dist/requests/topicRequestSettle.d.ts +30 -0
- package/dist/requests/topicRequestSettle.d.ts.map +1 -0
- package/dist/requests/topicRequestSettle.js +23 -0
- package/dist/requests/topicRequestSettle.js.map +1 -0
- package/dist/requests/wakeUpEngine.d.ts +4 -0
- package/dist/requests/wakeUpEngine.d.ts.map +1 -1
- package/dist/requests/wakeUpEngine.js +5 -1
- package/dist/requests/wakeUpEngine.js.map +1 -1
- package/dist/scheduler/delivery.d.ts +2 -0
- package/dist/scheduler/delivery.d.ts.map +1 -1
- package/dist/scheduler/delivery.js +8 -4
- package/dist/scheduler/delivery.js.map +1 -1
- package/dist/scheduler/mcpSurface.d.ts +59 -10
- package/dist/scheduler/mcpSurface.d.ts.map +1 -1
- package/dist/scheduler/mcpSurface.js +276 -79
- package/dist/scheduler/mcpSurface.js.map +1 -1
- package/dist/scheduler/recurrence.d.ts +5 -0
- package/dist/scheduler/recurrence.d.ts.map +1 -1
- package/dist/scheduler/recurrence.js +12 -2
- package/dist/scheduler/recurrence.js.map +1 -1
- package/dist/scheduler/strictToolInput.d.ts +45 -0
- package/dist/scheduler/strictToolInput.d.ts.map +1 -0
- package/dist/scheduler/strictToolInput.js +155 -0
- package/dist/scheduler/strictToolInput.js.map +1 -0
- package/dist/scheduler/types.d.ts +5 -0
- package/dist/scheduler/types.d.ts.map +1 -1
- package/dist/scheduler/workerWatch.d.ts +23 -0
- package/dist/scheduler/workerWatch.d.ts.map +1 -0
- package/dist/scheduler/workerWatch.js +26 -0
- package/dist/scheduler/workerWatch.js.map +1 -0
- package/dist/selfUpdate/emittedSource.d.ts +11 -0
- package/dist/selfUpdate/emittedSource.d.ts.map +1 -0
- package/dist/selfUpdate/emittedSource.js +24 -0
- package/dist/selfUpdate/emittedSource.js.map +1 -0
- package/dist/selfUpdate/gitSource.d.ts +0 -6
- package/dist/selfUpdate/gitSource.d.ts.map +1 -1
- package/dist/selfUpdate/gitSource.js +2 -18
- package/dist/selfUpdate/gitSource.js.map +1 -1
- package/dist/selfUpdate/updatePending.d.ts +1 -1
- package/dist/sendErrorClassifier.d.ts +10 -0
- package/dist/sendErrorClassifier.d.ts.map +1 -1
- package/dist/sendErrorClassifier.js +22 -0
- package/dist/sendErrorClassifier.js.map +1 -1
- package/dist/state.d.ts +78 -7
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +125 -8
- package/dist/state.js.map +1 -1
- package/dist/stateFile.d.ts +9 -0
- package/dist/stateFile.d.ts.map +1 -0
- package/dist/stateFile.js +57 -0
- package/dist/stateFile.js.map +1 -0
- package/dist/stt/sttInstall.d.ts +7 -3
- package/dist/stt/sttInstall.d.ts.map +1 -1
- package/dist/stt/sttInstall.js +8 -4
- package/dist/stt/sttInstall.js.map +1 -1
- package/dist/stt/sttSettings.d.ts +2 -1
- package/dist/stt/sttSettings.d.ts.map +1 -1
- package/dist/stt/sttSettings.js +3 -2
- package/dist/stt/sttSettings.js.map +1 -1
- package/dist/stt/transcribeChain.js +2 -0
- package/dist/stt/transcribeChain.js.map +1 -1
- package/dist/testTimings.d.ts +13 -3
- package/dist/testTimings.d.ts.map +1 -1
- package/dist/testTimings.js +26 -2
- package/dist/testTimings.js.map +1 -1
- package/dist/todos/board.d.ts +83 -0
- package/dist/todos/board.d.ts.map +1 -0
- package/dist/todos/board.js +227 -0
- package/dist/todos/board.js.map +1 -0
- package/dist/todos/format.d.ts +33 -0
- package/dist/todos/format.d.ts.map +1 -0
- package/dist/todos/format.js +90 -0
- package/dist/todos/format.js.map +1 -0
- package/dist/todos/merge.d.ts +46 -0
- package/dist/todos/merge.d.ts.map +1 -0
- package/dist/todos/merge.js +137 -0
- package/dist/todos/merge.js.map +1 -0
- package/dist/todos/midTurn.d.ts +75 -0
- package/dist/todos/midTurn.d.ts.map +1 -0
- package/dist/todos/midTurn.js +214 -0
- package/dist/todos/midTurn.js.map +1 -0
- package/dist/todos/nag.d.ts +85 -0
- package/dist/todos/nag.d.ts.map +1 -0
- package/dist/todos/nag.js +103 -0
- package/dist/todos/nag.js.map +1 -0
- package/dist/todos/order.d.ts +25 -0
- package/dist/todos/order.d.ts.map +1 -0
- package/dist/todos/order.js +61 -0
- package/dist/todos/order.js.map +1 -0
- package/dist/todos/projects.d.ts +102 -0
- package/dist/todos/projects.d.ts.map +1 -0
- package/dist/todos/projects.js +342 -0
- package/dist/todos/projects.js.map +1 -0
- package/dist/todos/registry.d.ts +64 -0
- package/dist/todos/registry.d.ts.map +1 -0
- package/dist/todos/registry.js +116 -0
- package/dist/todos/registry.js.map +1 -0
- package/dist/todos/reminderEngine.d.ts +78 -0
- package/dist/todos/reminderEngine.d.ts.map +1 -0
- package/dist/todos/reminderEngine.js +162 -0
- package/dist/todos/reminderEngine.js.map +1 -0
- package/dist/todos/store.d.ts +34 -0
- package/dist/todos/store.d.ts.map +1 -0
- package/dist/todos/store.js +208 -0
- package/dist/todos/store.js.map +1 -0
- package/dist/todos/tools.d.ts +26 -0
- package/dist/todos/tools.d.ts.map +1 -0
- package/dist/todos/tools.js +25 -0
- package/dist/todos/tools.js.map +1 -0
- package/dist/todos/types.d.ts +85 -0
- package/dist/todos/types.d.ts.map +1 -0
- package/dist/todos/types.js +30 -0
- package/dist/todos/types.js.map +1 -0
- package/dist/trackers/taskAgentLimit.d.ts +58 -0
- package/dist/trackers/taskAgentLimit.d.ts.map +1 -0
- package/dist/trackers/taskAgentLimit.js +62 -0
- package/dist/trackers/taskAgentLimit.js.map +1 -0
- package/dist/trackers/taskAgentSlots.d.ts +109 -0
- package/dist/trackers/taskAgentSlots.d.ts.map +1 -0
- package/dist/trackers/taskAgentSlots.js +227 -0
- package/dist/trackers/taskAgentSlots.js.map +1 -0
- package/dist/trackers/types.d.ts +14 -0
- package/dist/trackers/types.d.ts.map +1 -0
- package/dist/trackers/types.js +3 -0
- package/dist/trackers/types.js.map +1 -0
- package/dist/types.d.ts +80 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/adoptReplayGate.d.ts +16 -0
- package/dist/utils/adoptReplayGate.d.ts.map +1 -0
- package/dist/utils/adoptReplayGate.js +35 -0
- package/dist/utils/adoptReplayGate.js.map +1 -0
- package/dist/utils/agentPlugin.d.ts +113 -0
- package/dist/utils/agentPlugin.d.ts.map +1 -0
- package/dist/utils/agentPlugin.js +192 -0
- package/dist/utils/agentPlugin.js.map +1 -0
- package/dist/utils/autoContinueOnLimit.d.ts +7 -4
- package/dist/utils/autoContinueOnLimit.d.ts.map +1 -1
- package/dist/utils/autoContinueOnLimit.js +8 -5
- package/dist/utils/autoContinueOnLimit.js.map +1 -1
- package/dist/utils/botSkills.d.ts +62 -0
- package/dist/utils/botSkills.d.ts.map +1 -0
- package/dist/utils/botSkills.js +53 -0
- package/dist/utils/botSkills.js.map +1 -0
- package/dist/utils/botSkillsSetting.d.ts +7 -0
- package/dist/utils/botSkillsSetting.d.ts.map +1 -0
- package/dist/utils/botSkillsSetting.js +9 -0
- package/dist/utils/botSkillsSetting.js.map +1 -0
- package/dist/utils/claudeCodeVersion.d.ts +7 -0
- package/dist/utils/claudeCodeVersion.d.ts.map +1 -1
- package/dist/utils/claudeCodeVersion.js +14 -1
- package/dist/utils/claudeCodeVersion.js.map +1 -1
- package/dist/utils/claudeCompactHook.d.ts +33 -15
- package/dist/utils/claudeCompactHook.d.ts.map +1 -1
- package/dist/utils/claudeCompactHook.js +36 -17
- package/dist/utils/claudeCompactHook.js.map +1 -1
- package/dist/utils/claudeCompactSummary.d.ts +15 -0
- package/dist/utils/claudeCompactSummary.d.ts.map +1 -0
- package/dist/utils/claudeCompactSummary.js +96 -0
- package/dist/utils/claudeCompactSummary.js.map +1 -0
- package/dist/utils/claudeLimitSwitch.d.ts +11 -9
- package/dist/utils/claudeLimitSwitch.d.ts.map +1 -1
- package/dist/utils/claudeLimitSwitch.js +18 -16
- package/dist/utils/claudeLimitSwitch.js.map +1 -1
- package/dist/utils/claudeProfiles.d.ts +5 -0
- package/dist/utils/claudeProfiles.d.ts.map +1 -1
- package/dist/utils/claudeProfiles.js +14 -0
- package/dist/utils/claudeProfiles.js.map +1 -1
- package/dist/utils/claudeSessionTitle.d.ts +2 -1
- package/dist/utils/claudeSessionTitle.d.ts.map +1 -1
- package/dist/utils/claudeSessionTitle.js +14 -14
- package/dist/utils/claudeSessionTitle.js.map +1 -1
- package/dist/utils/claudeUsage.d.ts +95 -15
- package/dist/utils/claudeUsage.d.ts.map +1 -1
- package/dist/utils/claudeUsage.js +241 -41
- package/dist/utils/claudeUsage.js.map +1 -1
- package/dist/utils/claudeUsageRefresher.d.ts +10 -0
- package/dist/utils/claudeUsageRefresher.d.ts.map +1 -1
- package/dist/utils/claudeUsageRefresher.js +11 -0
- package/dist/utils/claudeUsageRefresher.js.map +1 -1
- package/dist/utils/claudeUserEntry.d.ts +50 -0
- package/dist/utils/claudeUserEntry.d.ts.map +1 -0
- package/dist/utils/claudeUserEntry.js +120 -0
- package/dist/utils/claudeUserEntry.js.map +1 -0
- package/dist/utils/clearThreadOutputQueues.d.ts +4 -3
- package/dist/utils/clearThreadOutputQueues.d.ts.map +1 -1
- package/dist/utils/clearThreadOutputQueues.js +1 -1
- package/dist/utils/clearThreadOutputQueues.js.map +1 -1
- package/dist/utils/compactOnIdle.d.ts +33 -13
- package/dist/utils/compactOnIdle.d.ts.map +1 -1
- package/dist/utils/compactOnIdle.js +35 -15
- package/dist/utils/compactOnIdle.js.map +1 -1
- package/dist/utils/fallbackBridge.d.ts +5 -0
- package/dist/utils/fallbackBridge.d.ts.map +1 -1
- package/dist/utils/fallbackBridge.js +19 -3
- package/dist/utils/fallbackBridge.js.map +1 -1
- package/dist/utils/fallbackChain.d.ts +9 -3
- package/dist/utils/fallbackChain.d.ts.map +1 -1
- package/dist/utils/fallbackChain.js +21 -3
- package/dist/utils/fallbackChain.js.map +1 -1
- package/dist/utils/fileSendPlan.d.ts +6 -0
- package/dist/utils/fileSendPlan.d.ts.map +1 -1
- package/dist/utils/fileSendPlan.js +11 -0
- package/dist/utils/fileSendPlan.js.map +1 -1
- package/dist/utils/fileSendService.d.ts +7 -1
- package/dist/utils/fileSendService.d.ts.map +1 -1
- package/dist/utils/fileSendService.js +6 -2
- package/dist/utils/fileSendService.js.map +1 -1
- package/dist/utils/groupFinalizePlan.d.ts +8 -10
- package/dist/utils/groupFinalizePlan.d.ts.map +1 -1
- package/dist/utils/groupFinalizePlan.js +8 -12
- package/dist/utils/groupFinalizePlan.js.map +1 -1
- package/dist/utils/jsonStreamHost.d.ts +13 -0
- package/dist/utils/jsonStreamHost.d.ts.map +1 -1
- package/dist/utils/jsonStreamHost.js +13 -0
- package/dist/utils/jsonStreamHost.js.map +1 -1
- package/dist/utils/messageSendService.d.ts +5 -3
- package/dist/utils/messageSendService.d.ts.map +1 -1
- package/dist/utils/messageSendService.js +12 -5
- package/dist/utils/messageSendService.js.map +1 -1
- package/dist/utils/openCodeCompactPlugin.d.ts +39 -14
- package/dist/utils/openCodeCompactPlugin.d.ts.map +1 -1
- package/dist/utils/openCodeCompactPlugin.js +106 -38
- package/dist/utils/openCodeCompactPlugin.js.map +1 -1
- package/dist/utils/promptDelivery.d.ts +29 -12
- package/dist/utils/promptDelivery.d.ts.map +1 -1
- package/dist/utils/promptDelivery.js +13 -5
- package/dist/utils/promptDelivery.js.map +1 -1
- package/dist/utils/sentKindsSummary.d.ts +10 -0
- package/dist/utils/sentKindsSummary.d.ts.map +1 -0
- package/dist/utils/sentKindsSummary.js +18 -0
- package/dist/utils/sentKindsSummary.js.map +1 -0
- package/dist/utils/telegramError.d.ts +6 -0
- package/dist/utils/telegramError.d.ts.map +1 -1
- package/dist/utils/telegramError.js +12 -0
- package/dist/utils/telegramError.js.map +1 -1
- package/dist/utils/topicView.d.ts +1 -1
- package/dist/utils/topicView.js +1 -1
- package/dist/utils/transcribeAudio.d.ts +10 -0
- package/dist/utils/transcribeAudio.d.ts.map +1 -1
- package/dist/utils/transcribeAudio.js +22 -3
- package/dist/utils/transcribeAudio.js.map +1 -1
- package/dist/utils/transcriptErrorTime.d.ts +8 -0
- package/dist/utils/transcriptErrorTime.d.ts.map +1 -0
- package/dist/utils/transcriptErrorTime.js +56 -0
- package/dist/utils/transcriptErrorTime.js.map +1 -0
- package/dist/utils/wedgeRecovery.d.ts +2 -0
- package/dist/utils/wedgeRecovery.d.ts.map +1 -1
- package/dist/utils/wedgeRecovery.js +1 -1
- package/dist/utils/wedgeRecovery.js.map +1 -1
- package/package.json +11 -3
- package/remoteRun/runner.sh +1242 -0
- package/stt/gigaam_sidecar.py +555 -50
package/SETUP.md
CHANGED
|
@@ -143,7 +143,7 @@ WantedBy=default.target
|
|
|
143
143
|
```
|
|
144
144
|
|
|
145
145
|
`nvm.sh` puts the nvm Node — and so `charness`, `claude` and `opencode` — on the service's `PATH`, which a service does not
|
|
146
|
-
inherit from your shell. `KillMode=process` is the one [Restart behaviour](
|
|
146
|
+
inherit from your shell. `KillMode=process` is the one [Restart behaviour](docs/backends.md#restart-behaviour) asks for: systemd's
|
|
147
147
|
default would kill the agents' tmux and `opencode serve` with the bot, and while systemd marks `process` «not recommended»
|
|
148
148
|
([systemd.kill](https://www.freedesktop.org/software/systemd/man/latest/systemd.kill.html)), leaving them running is exactly
|
|
149
149
|
what lets a bot restart keep its agents. Enable it and let the user manager start without a login:
|
|
@@ -229,7 +229,7 @@ stopped; this is not confirmed on current WSL. If the bot stops after you log in
|
|
|
229
229
|
**Known risks.**
|
|
230
230
|
|
|
231
231
|
- A Windows restart, a Windows Update reboot or `wsl --shutdown` ends the agents' processes, like a container restart:
|
|
232
|
-
each conversation resumes with its next message ([Restart behaviour](
|
|
232
|
+
each conversation resumes with its next message ([Restart behaviour](docs/backends.md#restart-behaviour)).
|
|
233
233
|
- **If a Windows program that the bot calls fails, run `wsl --update` in PowerShell first** and try again: the known
|
|
234
234
|
failures below were fixed in newer WSL. The details, for whoever helps you: Windows `.exe` interop from a systemd service
|
|
235
235
|
has failed in some WSL versions. WSL 2.0.5–2.0.13 could not run a Windows program stored in the Linux filesystem from a
|
|
@@ -273,7 +273,7 @@ your chosen providers need them.
|
|
|
273
273
|
| `CLAUDE_BIN` | (auto) | The `claude` binary is not on PATH due to nvm/asdf/systemd PATH differences |
|
|
274
274
|
| `ANTHROPIC_API_KEY` | — | A custom MCP/OpenCode plugin/auth resolver explicitly reads it; not needed for normal Claude CLI auth. The json-stream Claude backend strips it from the agent's env (subscription billing) |
|
|
275
275
|
| `SCHEDULER_MCP_PORT` | an OS-chosen free loopback port | You need a stable, explicitly chosen port; it must differ from this instance's `OPENCODE_URL` port |
|
|
276
|
-
| `CLAUDE_SCRAPE_DEBUG` | off | You are debugging Claude tmux scraping and need full RAW/FILTERED chunks |
|
|
276
|
+
| `CLAUDE_SCRAPE_DEBUG` | off | You are debugging Claude tmux scraping (the deprecated tmux backend) and need full RAW/FILTERED chunks |
|
|
277
277
|
| `AGENT_IDLE_MINUTES` | `55` | A json-stream Claude topic idle for this long is compacted (when `/compact_on_idle` allows) and its process stopped; the session sleeps and the next message resumes it — shorten it only for a test; a non-positive or non-numeric value keeps the default |
|
|
278
278
|
| `REQUEST_BACKSTOP_MINUTES` | `90` | A request (a Jira hand-over, a message in an answers-only topic) with nothing seen working on it for this long is re-posted to its session — shorten it only for a test; a non-positive or non-numeric value keeps the default |
|
|
279
279
|
| `TMUX_SOCKET_NAME` | — (the default tmux server) | The instance must run its agents on its OWN tmux server (`tmux -L <name>`; any plain name except `default`). Recommended for a second instance on one host: at boot an instance kills every agent session on its server that its own state does not know |
|
|
@@ -304,7 +304,7 @@ hostnames: their ports and tmux servers are their own.
|
|
|
304
304
|
**The bot updates itself.** With `autoUpdate` on (the default) an instance checks for a new version every hour (the first
|
|
305
305
|
check 10 minutes after it starts), installs it when nobody is using the bot, restarts **in place** — the same process id, so
|
|
306
306
|
systemd, pm2, `nohup` or a terminal see nothing, and every agent keeps running (what survives:
|
|
307
|
-
[Restart behaviour](
|
|
307
|
+
[Restart behaviour](docs/backends.md#restart-behaviour)) — and says in General what changed:
|
|
308
308
|
|
|
309
309
|
```
|
|
310
310
|
🔄 Charness updated: 3.4.0 → 3.5.0
|
|
@@ -364,7 +364,9 @@ safe to run blindly:
|
|
|
364
364
|
changed;
|
|
365
365
|
- a hot-mode instance (`charness hot`) rebuilds and restarts the worker
|
|
366
366
|
by itself (after a dependency install the script touches `tsconfig.json`
|
|
367
|
-
so `tsc -w` recompiles with the new modules
|
|
367
|
+
so `tsc -w` recompiles with the new modules; should the watcher miss the pulled files anyway — its file-system events can
|
|
368
|
+
be dropped under the load of a big pull — the supervisor notices a source newer than its build and restarts the watcher by
|
|
369
|
+
itself); a non-hot instance gets
|
|
368
370
|
`yarn build` — the script never kills processes (the bot's updater restarts it);
|
|
369
371
|
- changes to the hot supervisor itself (`src/cli.ts`, `src/cli/hot.ts`,
|
|
370
372
|
`nodemon.json`) are flagged with a warning: with the bot's updater the supervisor
|
|
@@ -380,6 +382,17 @@ entry:
|
|
|
380
382
|
|
|
381
383
|
(create the log directory once: `mkdir -p ~/.local/state/charness`).
|
|
382
384
|
|
|
385
|
+
### Runners for heavy commands (`remote-run`)
|
|
386
|
+
|
|
387
|
+
A test suite, a build or an emulator run can take most of the machine the bot lives on. List other machines you reach by ssh in
|
|
388
|
+
`~/.config/charness/runners.json` (one file per OS user, shared by every instance of that user) and agents can send such commands
|
|
389
|
+
there with `charness remote-run`: output, exit code and declared result files come back as if the command had run locally. Without a
|
|
390
|
+
runner listed nothing changes for anyone, and agents are not told of the command. Setting a runner up by hand (an account of its own,
|
|
391
|
+
`rsync`, Pueue), the file's fields, `.remote-run`, every command and the exit codes: [docs/remote-run.md](docs/remote-run.md).
|
|
392
|
+
|
|
393
|
+
A **Jira** agent reaches `charness` through the bot's `PATH`; when that `PATH` lacks it, map it in `jira.json` `agentBinaries`
|
|
394
|
+
([Jira setup](#jira-setup)).
|
|
395
|
+
|
|
383
396
|
## Telegram setup
|
|
384
397
|
|
|
385
398
|
Four steps: create a bot, (optionally) set up a group, launch from your projects folder, bind a topic to an agent.
|
|
@@ -448,7 +461,7 @@ visible topic list, per-topic names/icons, quick agent switching — but it is
|
|
|
448
461
|
4. **Remove the bot from the group and add it again.** Telegram caches the
|
|
449
462
|
privacy-mode flag on join; without re-adding, the bot keeps private-mode and
|
|
450
463
|
ignores free-form messages (see
|
|
451
|
-
[Troubleshooting → Bot doesn't see text](
|
|
464
|
+
[Troubleshooting → Bot doesn't see text](docs/troubleshooting.md#bot-doesnt-see-text-telegram)).
|
|
452
465
|
|
|
453
466
|
<p>
|
|
454
467
|
<img src="docs/images/02-enable-topics.png" width="360" alt="Group settings → Topics toggle enabled (Forum mode)" />
|
|
@@ -576,7 +589,7 @@ next start and shows the progress in General (or in its log).
|
|
|
576
589
|
|
|
577
590
|
- **Needs** `uv` (on `PATH` or in `~/.local/bin`), or `python3` ≥ 3.10 with the venv module (`apt install python3-venv`
|
|
578
591
|
on Debian/Ubuntu). The install builds a private venv — your Python is left alone.
|
|
579
|
-
- **Disk:** about
|
|
592
|
+
- **Disk:** about 500 MB under `<DATA_DIR>/stt` (the model is 216 MB; the rest is the Python packages and their cache — about 100 MB of it is the ffmpeg libraries that read MP3, M4A and joined OGG files).
|
|
580
593
|
- **RAM:** nothing while it is not running. The recogniser process starts with the first voice note that needs it (about
|
|
581
594
|
+2–3 s once), uses about 0.5 GB for short voices and up to about 0.9 GB while a 5-minute voice is recognised with the
|
|
582
595
|
default 4 workers, and exits by itself after 15 idle minutes (`gigaam.idleMinutes`, `0` = never). Idle time, workers,
|
|
@@ -585,6 +598,7 @@ next start and shows the progress in General (or in its log).
|
|
|
585
598
|
recognised in parallel. A hot reload of the bot keeps a running recogniser; stopping or killing the bot takes it down.
|
|
586
599
|
- **Russian only.** English words come out in Cyrillic or garbled; with a `language` other than `ru` set, the engine is
|
|
587
600
|
skipped and the next one in the chain answers.
|
|
601
|
+
- **Voice message formats:** a voice message is normally OGG/Opus, but Telegram also lets one be an MP3 or an M4A (AAC), and some apps join several OGG files into one — the local engine recognises each of these to its last second. Only *voice messages* are transcribed: an audio file sent as a file or as an audio message goes to the agent, not to speech recognition.
|
|
588
602
|
- It listens on `127.0.0.1` only, on a port the OS picks, and answers only a per-start secret token.
|
|
589
603
|
- **Docker is not supported yet** (the image has no `python3-venv`).
|
|
590
604
|
|
|
@@ -598,7 +612,7 @@ be written, the tap that needed it says so and names the path. The file is optio
|
|
|
598
612
|
a hand edit applies to the next session start, no restart.
|
|
599
613
|
|
|
600
614
|
```json
|
|
601
|
-
{ "defaultEffort": "medium", "autoUpdate": "on", "whatsNew": true }
|
|
615
|
+
{ "defaultEffort": "medium", "autoUpdate": "on", "whatsNew": true, "botSkills": "on" }
|
|
602
616
|
```
|
|
603
617
|
|
|
604
618
|
| Field | Meaning |
|
|
@@ -606,6 +620,9 @@ a hand edit applies to the next session start, no restart.
|
|
|
606
620
|
| `defaultEffort` | The reasoning effort of every topic that has no `/effort` pick of its own: `low`, `medium`, `high`, `xhigh`, `max`, `auto` or `ultracode`. Set it from **`/effort` in the General topic** (a tap writes the file), or by hand. Leave it out and the built-in default, `medium`, applies |
|
|
607
621
|
| `autoUpdate` | What the instance does about a new charness version: `on` installs it by itself when the bot is idle, `notify` says it is out and offers a button, `off` never looks. Set it from **`/update` in General**, or by hand. Leave it out and `on` applies ([Updating](#updating)) |
|
|
608
622
|
| `whatsNew` | `true` (default): after an update General lists the CHANGELOG entries it brought; `false`: only the «Updated a → b» line. Set from `/update` in General, or by hand |
|
|
623
|
+
| `botSkills` | Whether the skills Charness ships with its agents (`charness-manager`, the two delegate skills) and the hint to load the manager reach them ([Commands](docs/commands.md#skills-the-bot-gives-its-agents)): `"on"` or `"off"`. The default of an instance whose **General** never chose — a Jira-only instance, which has no General, sets it here; `/bot_skills` in General overrides it for the instance once used; leave it out and `on` applies. A running agent keeps its skills until its next start |
|
|
624
|
+
| `taskAgents` | The cap on tracker task agents ([Jira setup](#jira-setup)): `{ "maxConcurrent": 5 }` — how many conversations of a connected tracker (Jira issues) may work on a hand-over at once, for the whole bot; an issue over it waits in a queue and starts by itself. `0` = no limit, 100 the most. The default of an instance whose **General** never chose — a Jira-only instance, which has no General, sets it here; **`/task_agents` in General** overrides it for the instance once used (a picker, or any number typed after the command). Leave it out and `5` applies |
|
|
625
|
+
| `todo` | The shared todo lists ([Commands](docs/commands.md#shared-todo-lists)): `{ "isEnabled": true, "reminderMinutes": 60 }`. `isEnabled: false` turns the feature off (agents are not offered the tools); `reminderMinutes` is how long an agent may work without updating its list before it is reminded, `0` = never. Set both from **`/todo` in General → Settings**, or by hand — the way for an instance without a General topic (a Jira-only one). Leave it out and on / 60 apply |
|
|
609
626
|
|
|
610
627
|
What a new Claude session starts with, first that exists: the topic's own `/effort` pick, the platform's default
|
|
611
628
|
(a Jira conversation: `effort` in `jira.json`, `high` when absent — Jira never reads `defaultEffort`), `defaultEffort`,
|
|
@@ -681,7 +698,7 @@ talk to the bot there.
|
|
|
681
698
|
| Variable | Default | Description |
|
|
682
699
|
|---|---|---|
|
|
683
700
|
| `ALLOWED_GROUP_ID` | (auto-pair) | Numeric forum supergroup id (`-100…`). Leave empty to auto-pair with the first forum group a group **admin/creator** contacts the bot from (id is saved to `state.json`; re-point with `/pair`). A **name** is not accepted. A numeric value disables auto-pairing |
|
|
684
|
-
| `CHAT_MODE` | `both` | Which surface(s) this instance serves: `group`, `dm`, or `both` — see [Two surfaces](
|
|
701
|
+
| `CHAT_MODE` | `both` | Which surface(s) this instance serves: `group`, `dm`, or `both` — see [Two surfaces](docs/backends.md#two-surfaces-group-topics-bot-dm-or-both) |
|
|
685
702
|
| `OWNER_USER_ID` | — | **Optional.** Numeric Telegram user id of the owner — leave it unset to run group-only (the DM surface stays inert; a group works fully without it). Set it only to enable the owner-DM surface; **required** solely for `CHAT_MODE=dm` |
|
|
686
703
|
|
|
687
704
|
**Localized in 12 languages** — the bot UI (commands, buttons, notices) speaks
|
|
@@ -771,11 +788,21 @@ connector behaves is described in [`src/connectors/jira/README.md`](src/connecto
|
|
|
771
788
|
`runBudgetPer24h` defaults to 5; `model` and `effort` set the sessions' Claude model and reasoning effort
|
|
772
789
|
(optional; absent → `opus` and `high`, either key overrides only its own default). `extraFields` (optional,
|
|
773
790
|
none by default) names fields by id (`customfield_…`, or a system one like `duedate`) the agent should see next to the standard
|
|
774
|
-
ones, shown under their site name; an id the site does not list is logged at start and left out. `
|
|
791
|
+
ones, shown under their site name; an id the site does not list is logged at start and left out. `repos`
|
|
792
|
+
(optional) lists the repositories the project's issues work on, by folder name (`["example-repo"]`): the
|
|
793
|
+
[shared todo lists](docs/commands.md#shared-todo-lists) put the conversations of projects that share a name on one
|
|
794
|
+
board, together with the Telegram topics on a repository folder of that name; projects without `repos` share one
|
|
795
|
+
board for the whole instance. `agentBinaries` (optional, host runtime) maps a tool name to the absolute path of an executable — for
|
|
775
796
|
example `{ "ffmpeg": "/opt/tools/ffmpeg" }` — which is checked at start and put on the agents' PATH. `adapter` is `claude-json-stream` (the default — the agent process is stopped when an issue
|
|
776
797
|
idles) or `claude-per-turn` (stopped after every answer); either way the issue's conversation sleeps between
|
|
777
798
|
requests and the next request resumes it.
|
|
778
799
|
|
|
800
|
+
**How many agents run at once.** The AI works on at most 5 issues at the same time, all projects together — set
|
|
801
|
+
`taskAgents.maxConcurrent` in [`settings.json`](#instance-settings-settingsjson) (`0` = no limit; read without a
|
|
802
|
+
restart). An issue handed over beyond that gets one comment saying it is queued, stays assigned to the AI and starts by
|
|
803
|
+
itself when an agent hands its issue back, the one that waited longest first — also across a restart. An @-mention
|
|
804
|
+
(answer only) is never held back, and a lower number never stops an agent that is already working.
|
|
805
|
+
|
|
779
806
|
5. Start it with a clean environment, so nothing of the calling shell reaches it:
|
|
780
807
|
|
|
781
808
|
```bash
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# agent-plugin — the skills Charness gives its agents
|
|
2
|
+
|
|
3
|
+
A Claude Code plugin (`charness`) whose skills every bot-started agent session gets: Telegram topics and Jira
|
|
4
|
+
conversations, Claude Code and OpenCode. The operator's own sessions outside the bot do not get them.
|
|
5
|
+
|
|
6
|
+
| Skill | What it is for |
|
|
7
|
+
|-------|----------------|
|
|
8
|
+
| `charness-manager` | Orchestrating detached workers in a bot session: the delivery loop, the one-worker queue, the watch check that fires when a worker exits OR stalls (`schedule_create` + `checkCommand`), accounts through `claude_profiles`, talking to the user through the bot's tools |
|
|
9
|
+
| `charness-delegate-claude` | Launching, watching and resuming a detached `claude -p` worker (`summarize-events.py` reads its event log) |
|
|
10
|
+
| `charness-delegate-opencode` | The same for `opencode run` |
|
|
11
|
+
|
|
12
|
+
## How a session gets them
|
|
13
|
+
|
|
14
|
+
- **Claude Code:** every bot launch of an agent session (json-stream and tmux, start and resume) carries
|
|
15
|
+
`--plugin-dir <package>/agent-plugin`. Claude Code namespaces plugin skills by the plugin name and the skill's
|
|
16
|
+
FOLDER: `charness:charness-manager`. `--setting-sources project,local` (a Jira session) does not drop them.
|
|
17
|
+
- **OpenCode:** the `opencode serve` the bot starts gets `OPENCODE_CONFIG_DIR=<DATA_DIR>/opencode-config`, a
|
|
18
|
+
bot-owned folder whose `skills` is a symlink to this folder's `skills/`. OpenCode adds those skills to the
|
|
19
|
+
project's and the user's own; it writes files (`.gitignore`) into that folder, which is why it is not this
|
|
20
|
+
folder. An operator who set `OPENCODE_CONFIG_DIR` keeps it, and OpenCode topics then go without these skills.
|
|
21
|
+
- **Switched off:** the «Bot skills» switch (`/bot_skills`, `botSkills` in `settings.json`; `src/utils/botSkills.ts`) drops
|
|
22
|
+
the `--plugin-dir` of a Claude conversation at its next start or resume, and the hint to load `charness-manager` from the
|
|
23
|
+
bot MCP's instructions; the OpenCode server follows the instance value only (replaced at the bot's next start).
|
|
24
|
+
|
|
25
|
+
## Rules for a skill here
|
|
26
|
+
|
|
27
|
+
- Folder name = frontmatter `name` = `charness-<role>`. OpenCode has no namespaces: a skill named like a
|
|
28
|
+
project's or user's own one (`manager`) would replace it there.
|
|
29
|
+
- The watch recipe in `charness-manager` is the `workerWatchCheckCommand` constant of
|
|
30
|
+
`src/scheduler/workerWatch.ts` verbatim (a unit test holds them equal), and every bot tool a skill names must
|
|
31
|
+
exist on the bot's MCP surface.
|
|
32
|
+
- Written for this public repository: no real ids, paths or names. The shared rules repository keeps its own
|
|
33
|
+
`manager`; a change wanted in both is ported by hand.
|
|
34
|
+
- Shipped in the npm package (`files`); a commit that touches only this folder still counts as a release change.
|
|
35
|
+
A Claude session reads a new version at its next start, OpenCode when it next creates the folder's instance.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: charness-delegate-claude
|
|
3
|
+
description: "In a Charness-run session, use to launch, watch, finish and resume a builder, reviewer, investigator or planner as a detached `claude -p` process instead of an in-process sub-agent: the account from claude_profiles, the role's model and effort, a full-privilege worker with deny rules, its event log, the bot watch check, resuming the same session. Load charness-manager first."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Detached Claude Code worker (Charness session)
|
|
7
|
+
|
|
8
|
+
A worker is `claude -p`: one turn per process, the conversation kept between runs by its session id. Load
|
|
9
|
+
`charness-manager` first — it holds the delivery loop and the watch check this skill arms.
|
|
10
|
+
|
|
11
|
+
## Account, model, effort
|
|
12
|
+
|
|
13
|
+
- New worker: call `claude_profiles` with the worker's model and no `currentProfile`. Start the worker with
|
|
14
|
+
`CLAUDE_CONFIG_DIR=<configDir>` of the `recommended` profile (nothing when its `configDir` is null); without it
|
|
15
|
+
the worker drains YOUR account. The bot picks the account whose weekly limit resets soonest.
|
|
16
|
+
- `recommended: null`: no account is usable now. Do not launch; `schedule_create` with `onceAt` = `nextAvailable.at`
|
|
17
|
+
and a prompt that stands on its own (plan path, scope, what to launch), then end the turn. If `nextAvailable` is
|
|
18
|
+
null too, no account names a time it frees up: ask the user a native question (nothing can run, no time known) and
|
|
19
|
+
`schedule_create` a one-off retry about 30 minutes ahead, with such a prompt.
|
|
20
|
+
- Confirm the login under that directory: `env -u ANTHROPIC_API_KEY claude auth status --text`.
|
|
21
|
+
- Role defaults, unless the user names others:
|
|
22
|
+
- builder (code, tests, debugging, live runs): `--model sonnet --effort xhigh`;
|
|
23
|
+
- investigator (a cause still unclear after a builder failed on it twice): `--model opus --effort high`;
|
|
24
|
+
- reviewer: `--model opus --effort high`; a small or mechanical diff (docs, tests only): `--effort medium`;
|
|
25
|
+
- planner and the research feeding a plan: `--model opus --effort high`, `xhigh` for a large feature.
|
|
26
|
+
- Never Sonnet for work on data persistence (storage, DB schema and migrations, sync, merge and conflict
|
|
27
|
+
resolution, backups — anything that can lose or corrupt user data): every role runs on Opus, a builder at
|
|
28
|
+
`--model opus --effort xhigh` (`max` for a deep investigation). This beats the role defaults above.
|
|
29
|
+
- Never Fable for a worker: it drains the shared session and weekly limits fastest.
|
|
30
|
+
- The first `system`/`init` event must name the requested model; on a mismatch stop the worker and tell the user.
|
|
31
|
+
|
|
32
|
+
## Launch
|
|
33
|
+
|
|
34
|
+
1. Make a private run directory, generate a UUID for the session, write the brief into `<run-dir>/brief.md`:
|
|
35
|
+
the task and its context (the worker does not see this conversation), the skills it must load by name, every
|
|
36
|
+
resource another live process holds, and "report every changed file and how you verified".
|
|
37
|
+
2. Run it in the target checkout:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
setsid nohup env -u ANTHROPIC_API_KEY CLAUDE_CONFIG_DIR="<configDir>" \
|
|
41
|
+
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 BASH_MAX_TIMEOUT_MS=7200000 \
|
|
42
|
+
claude -p --session-id "<uuid>" --model "<model>" --effort "<effort>" \
|
|
43
|
+
--dangerously-skip-permissions \
|
|
44
|
+
--disallowedTools Agent "Bash(git push *)" "Bash(git reset --hard *)" "Bash(git clean *)" "Bash(git branch -D *)" \
|
|
45
|
+
--output-format stream-json --verbose --include-partial-messages \
|
|
46
|
+
< "<run-dir>/brief.md" > "<run-dir>/events.jsonl" 2> "<run-dir>/stderr.log" &
|
|
47
|
+
echo $! > "<run-dir>/pid"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
- Leave out `CLAUDE_CONFIG_DIR=…` for the default profile.
|
|
51
|
+
- `setsid nohup` detaches the worker from your process, so the bot stopping your idle process never ends it.
|
|
52
|
+
- `--disallowedTools` takes several values, so an option must follow it, never the prompt.
|
|
53
|
+
- `CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1` stops the worker from backgrounding a run that would die when its turn
|
|
54
|
+
ends; `BASH_MAX_TIMEOUT_MS` lets one foreground command run up to 2 hours. Longer work → split it.
|
|
55
|
+
- Full privileges with deny rules, never a restricted allowlist: a refused ordinary command ends the worker's
|
|
56
|
+
turn early.
|
|
57
|
+
- A checkout below the folder that holds `.claude/skills` does not see those skills: add
|
|
58
|
+
`--add-dir "<that folder>"` and check that the `init` event's `skills` lists every skill the brief names.
|
|
59
|
+
3. Check the PID: `ps -o args= -p "$(cat "<run-dir>/pid")"` must show `claude -p … <uuid>`. If it does not (the CLI
|
|
60
|
+
handed over to a new process), take it from `pgrep -f "^claude -p .*<uuid>"` and write that into the pid file.
|
|
61
|
+
4. Record the UUID, the profile name you launched on, the checkout and the run directory in the plan, then arm the
|
|
62
|
+
watch check from `charness-manager` with this PID and run directory.
|
|
63
|
+
|
|
64
|
+
## Watch and finish
|
|
65
|
+
|
|
66
|
+
- Progress: `python3 <this skill's base directory>/summarize-events.py <run-dir>/events.jsonl` — the tools it ran
|
|
67
|
+
last, its last words, the final result, the account's usage windows.
|
|
68
|
+
- A quiet log alone does not prove a hang: look at the last tool call and API retries before stopping a worker.
|
|
69
|
+
- Done means ALL of: a final event `"type": "result"` with `"is_error": false`, the task's actual output in it,
|
|
70
|
+
and the process gone. `"subtype": "success"` alone is not enough — it also appeared on an auth failure.
|
|
71
|
+
|
|
72
|
+
## Resume
|
|
73
|
+
|
|
74
|
+
- Confirm the old PID is gone, then repeat the launch with `--resume "<uuid>"` instead of `--session-id`, a new
|
|
75
|
+
brief and new log files (`events-2.jsonl`, …), and arm a new check. Never `--continue` or `--fork-session`.
|
|
76
|
+
- Keep the model, effort and flags of the first run.
|
|
77
|
+
- The account: call `claude_profiles` with `currentProfile` = the profile name recorded at launch; the worker stays on
|
|
78
|
+
it unless it can no longer run. Launch under the `recommended` profile's `configDir`, record that name.
|
|
79
|
+
- A run rejected on a usage limit ("You've hit your session limit"): call `claude_profiles` with `currentProfile` and
|
|
80
|
+
`isStoppedByLimit: true`, and resume the SAME session at once under the `recommended` profile — never wait while an
|
|
81
|
+
account is usable. `recommended: null` → `schedule_create` with `onceAt` = `nextAvailable.at` and a prompt that
|
|
82
|
+
stands on its own (resume this session, call `claude_profiles` again); `nextAvailable` null too → ask the user a
|
|
83
|
+
native question and `schedule_create` the same one-off retry about 30 minutes ahead.
|
|
84
|
+
- To stop a worker: confirm the PID is that worker (`ps -o args= -p <pid>`), `kill -TERM <pid>`, confirm it is
|
|
85
|
+
gone. Never kill by name, never a process you did not start.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Summarize a detached `claude -p --output-format stream-json` worker log.
|
|
3
|
+
|
|
4
|
+
Usage: summarize-events.py <events.jsonl> [<tool calls to show>]
|
|
5
|
+
|
|
6
|
+
Prints the model, the last tool calls, the last text, the final result and the account's usage windows,
|
|
7
|
+
so a manager can judge a worker's progress without reading the raw stream.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import sys
|
|
12
|
+
|
|
13
|
+
defaultToolCallCount = 8
|
|
14
|
+
textPreviewLength = 300
|
|
15
|
+
inputPreviewLength = 120
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def readEvents(path):
|
|
19
|
+
events = []
|
|
20
|
+
with open(path, encoding="utf-8", errors="replace") as file:
|
|
21
|
+
for line in file:
|
|
22
|
+
line = line.strip()
|
|
23
|
+
if not line:
|
|
24
|
+
continue
|
|
25
|
+
try:
|
|
26
|
+
events.append(json.loads(line))
|
|
27
|
+
except json.JSONDecodeError:
|
|
28
|
+
continue # a line still being written
|
|
29
|
+
return events
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def describeToolInput(toolInput):
|
|
33
|
+
if not isinstance(toolInput, dict):
|
|
34
|
+
return ""
|
|
35
|
+
for key in ("command", "file_path", "pattern", "description", "prompt"):
|
|
36
|
+
value = toolInput.get(key)
|
|
37
|
+
if isinstance(value, str) and value:
|
|
38
|
+
return " ".join(value.split())[:inputPreviewLength]
|
|
39
|
+
return ""
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def main():
|
|
43
|
+
if len(sys.argv) < 2:
|
|
44
|
+
print(__doc__.strip())
|
|
45
|
+
return 2
|
|
46
|
+
toolCallCount = int(sys.argv[2]) if len(sys.argv) > 2 else defaultToolCallCount
|
|
47
|
+
events = readEvents(sys.argv[1])
|
|
48
|
+
|
|
49
|
+
model = None
|
|
50
|
+
toolCalls = []
|
|
51
|
+
lastText = ""
|
|
52
|
+
result = None
|
|
53
|
+
usageWindows = {}
|
|
54
|
+
for event in events:
|
|
55
|
+
eventType = event.get("type")
|
|
56
|
+
if eventType == "system" and event.get("subtype") == "init":
|
|
57
|
+
model = event.get("model")
|
|
58
|
+
elif eventType == "assistant":
|
|
59
|
+
for block in (event.get("message") or {}).get("content") or []:
|
|
60
|
+
if block.get("type") == "tool_use":
|
|
61
|
+
toolCalls.append(f"{block.get('name')}: {describeToolInput(block.get('input'))}")
|
|
62
|
+
elif block.get("type") == "text" and block.get("text", "").strip():
|
|
63
|
+
lastText = block["text"]
|
|
64
|
+
elif eventType == "result":
|
|
65
|
+
result = event
|
|
66
|
+
elif eventType == "rate_limit_event":
|
|
67
|
+
windows = (event.get("rate_limit_info") or {}).get("unifiedWindows") or {}
|
|
68
|
+
for name, window in windows.items():
|
|
69
|
+
usageWindows[name] = window
|
|
70
|
+
|
|
71
|
+
print(f"events: {len(events)} model: {model} tool calls: {len(toolCalls)}")
|
|
72
|
+
if toolCalls:
|
|
73
|
+
print("last tool calls:")
|
|
74
|
+
for call in toolCalls[-toolCallCount:]:
|
|
75
|
+
print(f" - {call}")
|
|
76
|
+
if lastText:
|
|
77
|
+
print("last text: " + " ".join(lastText.split())[:textPreviewLength])
|
|
78
|
+
if result is None:
|
|
79
|
+
print("result: none yet (still running, or it died before finishing)")
|
|
80
|
+
else:
|
|
81
|
+
summary = {key: result.get(key) for key in ("subtype", "is_error", "num_turns", "total_cost_usd")}
|
|
82
|
+
print(f"result: {json.dumps(summary)}")
|
|
83
|
+
print("result text: " + " ".join(str(result.get("result", "")).split())[:textPreviewLength])
|
|
84
|
+
for name, window in sorted(usageWindows.items()):
|
|
85
|
+
print(f"usage {name}: {window.get('utilization')} (resets at {window.get('resetsAt')}, {window.get('status')})")
|
|
86
|
+
return 0
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
if __name__ == "__main__":
|
|
90
|
+
sys.exit(main())
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: charness-delegate-opencode
|
|
3
|
+
description: "In a Charness-run session, use to launch, watch, finish and resume a builder, reviewer or researcher as a detached `opencode run` process instead of an in-process sub-agent: model and variant, deny rules, its JSON event log, the bot watch check, resuming the same session. Load charness-manager first."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Detached OpenCode worker (Charness session)
|
|
7
|
+
|
|
8
|
+
A worker is `opencode run`: it exits when its turn goes idle and keeps the session for a later run. Load
|
|
9
|
+
`charness-manager` first — it holds the delivery loop and the watch check this skill arms.
|
|
10
|
+
|
|
11
|
+
## Model and variant
|
|
12
|
+
|
|
13
|
+
- The model and variant the user named; otherwise the ones this conversation runs on. `opencode models` lists
|
|
14
|
+
what the configured providers offer — pick a listed model and a variant it supports.
|
|
15
|
+
|
|
16
|
+
## Launch
|
|
17
|
+
|
|
18
|
+
1. Make a private run directory and write the brief into `<run-dir>/brief.md`: the task and its context (the
|
|
19
|
+
worker does not see this conversation), the skills it must load by name, every resource another live process
|
|
20
|
+
holds, "spawn no sub-agents", "wait for your own tests before ending your turn", and "report every changed
|
|
21
|
+
file and how you verified".
|
|
22
|
+
2. Run it:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
setsid nohup env OPENCODE_CONFIG_CONTENT='{"permission":{"bash":{"git push*":"deny","git reset --hard*":"deny","git clean*":"deny","git branch -D*":"deny"}}}' \
|
|
26
|
+
opencode run --auto --dir "<checkout>" --model "<provider>/<model>" --variant "<variant>" \
|
|
27
|
+
--format json --title "<scope>" \
|
|
28
|
+
< "<run-dir>/brief.md" > "<run-dir>/events.jsonl" 2> "<run-dir>/stderr.log" &
|
|
29
|
+
echo $! > "<run-dir>/pid"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- `setsid nohup` detaches the worker from your process, so the bot stopping your idle process never ends it.
|
|
33
|
+
- `--auto` approves every request that is not denied — the deny rules are the only guard, the brief is not one.
|
|
34
|
+
Never edit the global OpenCode permissions for this.
|
|
35
|
+
- Without `--auto` the CLI refuses ordinary requests and the worker stalls.
|
|
36
|
+
3. Check the PID: `ps -o args= -p "$(cat "<run-dir>/pid")"` must show `opencode run … --title <scope>`. If it
|
|
37
|
+
does not (the launcher handed over to a new process), take the newest match,
|
|
38
|
+
`pgrep -n -f "opencode.* run .*--title <scope>"` (a launcher may run the binary as a child: two matches), and
|
|
39
|
+
write that one PID into the pid file — the watch fires "worker exited" at once on a PID that is not the worker.
|
|
40
|
+
4. Record the session id — the top-level `sessionID` of the first JSON event in `events.jsonl` — with the
|
|
41
|
+
checkout and run directory in the plan, then arm the watch check from `charness-manager` with this PID and
|
|
42
|
+
run directory.
|
|
43
|
+
|
|
44
|
+
## Watch and finish
|
|
45
|
+
|
|
46
|
+
- The log gets an event per finished step or tool call, not per token: one long command can leave it quiet. Add
|
|
47
|
+
the folder that command writes to into the watch check.
|
|
48
|
+
- Read progress from the tool calls, not only the text events:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
jq -r 'select(.type=="tool_use" or .type=="text") |
|
|
52
|
+
(.part.tool // "SAY") + (.part.state.metadata.exit // "" | if .=="" then "" else " exit=\(.)" end)
|
|
53
|
+
+ " :: " + ((.part.state.title // .part.text // "") | gsub("\\s+";" ") | .[0:120])' \
|
|
54
|
+
"<run-dir>/events.jsonl" | tail -30
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- Trust the `exit=` of a command over what the worker says about it.
|
|
58
|
+
- Done means the process is gone AND its last turn holds the task's result without an `error` event or a failed
|
|
59
|
+
tool. A `step_finish` may still be followed by another step. When unsure: `opencode export <session-id>`.
|
|
60
|
+
|
|
61
|
+
## Resume
|
|
62
|
+
|
|
63
|
+
- Confirm the old PID is gone, then repeat the launch with `--session "<session-id>"`, a new brief and new log
|
|
64
|
+
files, and arm a new check. Keep the checkout, model and variant. Never `--continue` or `--fork`.
|
|
65
|
+
- A turn stopped by a provider's usage limit: resume the same session with another provider's model whose
|
|
66
|
+
context window holds the session.
|
|
67
|
+
- To stop a worker: confirm the PID is that worker (`ps -o args= -p <pid>`), `kill -TERM <pid>`, confirm it is
|
|
68
|
+
gone. Never kill the OpenCode server or a process you did not start.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: charness-manager
|
|
3
|
+
description: "In a Charness-run session (the bot's MCP tools such as schedule_create, answer_request, claude_profiles are present) use this INSTEAD of any other manager skill before you dispatch, watch or resume a worker — a detached `claude -p` or `opencode run` builder, reviewer, researcher or planner — and whenever the user calls you the manager. Drives a plan to done without writing code yourself, and watches every worker with a bot check that fires when the worker exits OR stalls."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Manager in a Charness session
|
|
7
|
+
|
|
8
|
+
You orchestrate: workers build, test, review and commit; you decide, keep the plan honest and keep the user
|
|
9
|
+
informed. You never write product code and never review a diff yourself.
|
|
10
|
+
|
|
11
|
+
## Modes
|
|
12
|
+
|
|
13
|
+
- **autonomous** — the default for a scheduled or unattended run, or when the user says so. Drive a READY plan
|
|
14
|
+
(no draft marker, no open questions); ask nothing; decide from the plan and the project rules; stop and report
|
|
15
|
+
what you cannot resolve. Without a named plan pick one ready plan that a worker can finish alone (the oldest by
|
|
16
|
+
its file date); none → say "nothing to do" and stop.
|
|
17
|
+
- **interactive** — the user is talking to you. Answer their question first, decide every point yourself and list
|
|
18
|
+
the decisions for them to correct, ask only about a fork you could not resolve.
|
|
19
|
+
|
|
20
|
+
## Rules that never bend
|
|
21
|
+
|
|
22
|
+
- Never force-push, tag, bump a version or merge a merge request.
|
|
23
|
+
- You check a worker's result only through another agent's report, `git log`, `git show --stat` and the plan's
|
|
24
|
+
checkboxes — never by reading its code, running its tests or re-running its e2e yourself.
|
|
25
|
+
- Parallel by default, on the same checkout — no worktree needed: reviewers and researchers run without limit
|
|
26
|
+
alongside everything else; several builders run at once when they edit independent parts of the code (name
|
|
27
|
+
each one's area in its brief; two tasks touching the same file queue).
|
|
28
|
+
- Serialize only what shares state: builds, test runs (devices, ports, e2e lanes — through their locks) and
|
|
29
|
+
commits (one at a time, path-limited). Two workers never share a file, a port, a browser profile or a device at
|
|
30
|
+
once. Every new ask joins the queue the moment it is said; start it at once when nothing it needs is taken,
|
|
31
|
+
else tell the user its place.
|
|
32
|
+
- A change the user can see is done only with a real end-to-end test that ran and passed. Never accept a stub, a
|
|
33
|
+
lower-level substitute or "test debt".
|
|
34
|
+
- Interactive: a commit YOU make yourself (a plan edit, bookkeeping) needs the user's yes first; workers commit
|
|
35
|
+
their own work without asking.
|
|
36
|
+
|
|
37
|
+
## Launching workers
|
|
38
|
+
|
|
39
|
+
- Load `charness-delegate-claude` or `charness-delegate-opencode` before the first launch and follow it: the CLI the
|
|
40
|
+
user named, otherwise the CLI you run in.
|
|
41
|
+
- Brief for a ready plan: its path, "implement it yourself, spawn no sub-agents", and — when several scopes go to
|
|
42
|
+
one builder — "your scopes are one batch: test each pointwise (unit tests and only its own new or changed e2e
|
|
43
|
+
flows), the full suites run once at the finish".
|
|
44
|
+
- Brief without a plan: like a colleague who just walked in — the goal, file paths, what to change and why. Never
|
|
45
|
+
"based on your findings, implement it".
|
|
46
|
+
- Name the skills the worker must load, never their content, and never restate project rules. Name every resource
|
|
47
|
+
another live process holds (a checkout, a port, a device).
|
|
48
|
+
- Role skills such as `developer`, `task-review`, `review`, `commit`: name them when the project offers them.
|
|
49
|
+
Otherwise state the role in words — builder: implement, test, self-review, commit each scope, no push;
|
|
50
|
+
reviewer: read the commit range against the plan or the user's asks and report findings, change nothing.
|
|
51
|
+
- Reuse the warm session: rework, the next small scope, or the next role on the same task resumes the SAME worker
|
|
52
|
+
session instead of starting a fresh one.
|
|
53
|
+
|
|
54
|
+
## Watch every worker with a bot check
|
|
55
|
+
|
|
56
|
+
Right after each launch, create ONE check for that worker run with `schedule_create`: cron `*/10 * * * *`,
|
|
57
|
+
`isPinSilent: true`, a name like `watch <role> <scope>`, and this `checkCommand` with the real PID and run directory:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
kill -0 <pid> 2>/dev/null || { echo "worker <pid> exited"; exit 1; }; [ -n "$(find "<run-dir>" -mmin -45 -print -quit)" ] || { echo "<run-dir>: no change for 45 min"; exit 2; }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- It fails on EITHER signal: the worker's process is gone, or nothing in its run directory changed for 45
|
|
64
|
+
minutes. A check that only runs `kill -0 <pid>` never fires on a hung worker — never arm one.
|
|
65
|
+
- `isPinSilent: true`: the check's alert is pinned, and a worker that simply finished fires it too — a loud pin
|
|
66
|
+
per finished worker would notify the user for nothing. What the user must notice you ask as a question.
|
|
67
|
+
- The run directory is where the worker writes all the time (its event log). A worker that runs one long command
|
|
68
|
+
may write nothing for a while: add the folder that command writes to (`find "<run-dir>" "<test-output-dir>" …`).
|
|
69
|
+
- The check's `prompt` must stand on its own — the wake may reach a resumed or compacted you: the role, the scope
|
|
70
|
+
or plan path, PID, session id, run directory, and "read the result, decide, then cancel this check".
|
|
71
|
+
- The first failure is ALSO the "worker finished" signal. On the wake read the worker's result first (its final
|
|
72
|
+
event, its exit, the end of its log), then decide: finished → the next step of the loop; stalled → look at its
|
|
73
|
+
last tool call, stop it, resume the same session; stopped by a usage limit → resume it at once on another account
|
|
74
|
+
(Accounts and usage limits).
|
|
75
|
+
- Then cancel the check (`schedule_list` → `schedule_cancel`) — that also unpins its alert, so a finished worker
|
|
76
|
+
leaves nothing pinned. A new run gets a new check.
|
|
77
|
+
- Never build your own watcher: no sleep loop, `CronCreate`, `ScheduleWakeup`, background job or tmux pane. They
|
|
78
|
+
live in your process, which the bot stops after an idle stretch.
|
|
79
|
+
|
|
80
|
+
## Between wakes
|
|
81
|
+
|
|
82
|
+
- After launching a worker and arming its check, write the worker state into the plan or draft (PID, session id,
|
|
83
|
+
account profile name, run directory, scope, check name), then END your turn. The bot stops an idle agent process and resumes the
|
|
84
|
+
conversation when the check wakes it; you lose nothing that is written down.
|
|
85
|
+
- Start workers with `setsid nohup` (the delegate skills show the command), so stopping your own process never
|
|
86
|
+
takes a worker down.
|
|
87
|
+
- A worker must never hand back a run it has not read: one that ended its turn with a build or test still in
|
|
88
|
+
flight is resumed to wait for it, read it and finish.
|
|
89
|
+
|
|
90
|
+
## Delivery loop — a ready plan
|
|
91
|
+
|
|
92
|
+
1. **Build.** One builder for the whole plan (or a group of small scopes); it commits each scope as it is green.
|
|
93
|
+
A large or risky scope, or an independent part running in parallel, may get a builder of its own.
|
|
94
|
+
2. **Bookkeeping.** A finished scope flips its `[x]`; the commit that flips the plan's last box also moves the
|
|
95
|
+
plan file to `completed/`.
|
|
96
|
+
3. **Finish — only when the whole task is done, never per scope:**
|
|
97
|
+
1. A fresh reviewer reviews ALL the task's commits once. Its brief: the plan path or the user's asks nearly
|
|
98
|
+
verbatim, and the commit range — nothing else. Findings go back to a builder as rework, then a new review.
|
|
99
|
+
2. Clean → a builder runs ALL test suites in full and fixes every failure.
|
|
100
|
+
3. Any fixes in 2 → a separate reviewer reviews just those fixes; a change it makes sends you back to 2.
|
|
101
|
+
Each loop runs up to 10 cycles while the findings are concrete local fixes, telling the user about each cycle
|
|
102
|
+
past the third — even when new findings keep landing in the same area. A major finding, or the 10 cycles used
|
|
103
|
+
up: stop, leave the work for inspection, report.
|
|
104
|
+
4. **Push** only when the user allowed it (in chat or in their own instructions); otherwise report it ready to
|
|
105
|
+
push — as a question the user will notice (below).
|
|
106
|
+
|
|
107
|
+
## No plan yet — interactive
|
|
108
|
+
|
|
109
|
+
- **Bugs and small reworks:** capture each into a living plan the moment it is said (stable ids, never renumber,
|
|
110
|
+
never drop a deferral). An unambiguous one goes to a builder at once; only a fork you cannot resolve goes to
|
|
111
|
+
the user first.
|
|
112
|
+
- **A feature or idea:** capture a draft; a researcher worker investigates the code and the web, decides every
|
|
113
|
+
point itself and returns a summary, its decisions and only the forks it could not resolve. Show them, record
|
|
114
|
+
the locked decisions, and ask before switching to building.
|
|
115
|
+
|
|
116
|
+
## Accounts and usage limits
|
|
117
|
+
|
|
118
|
+
- Before every Claude worker launch call `claude_profiles` with the worker's model and start the worker with
|
|
119
|
+
`CLAUDE_CONFIG_DIR=<configDir>` of `recommended` (nothing when it is null). A new worker goes to the account whose
|
|
120
|
+
weekly limit resets soonest. Never launch on an account billed to API credits unless the user asked.
|
|
121
|
+
- Record the profile name beside the worker's session id. Every resume calls `claude_profiles` with
|
|
122
|
+
`currentProfile` = that name, so a warm worker stays on its account.
|
|
123
|
+
- A worker stopped by a usage limit resumes its SAME session at once, never a fresh worker (which would redo the
|
|
124
|
+
work): call `claude_profiles` with `currentProfile` and `isStoppedByLimit: true` and resume under the account it
|
|
125
|
+
recommends. `recommended: null` → nothing is usable: `schedule_create` a one-off resume (`onceAt` =
|
|
126
|
+
`nextAvailable.at`) whose prompt stands on its own. `nextAvailable` null too → no account names a time it frees
|
|
127
|
+
up: ask the user a native question (nothing can run) and `schedule_create` the same one-off retry about 30
|
|
128
|
+
minutes ahead.
|
|
129
|
+
- Your own usage limit is the bot's business: it waits or switches and then wakes you.
|
|
130
|
+
|
|
131
|
+
## Talking to the user
|
|
132
|
+
|
|
133
|
+
- The user keeps the bot's topics muted: your plain text reaches the topic silently. Anything they must notice —
|
|
134
|
+
a blocker, a fork, "ready to push" — ask as a native question (Claude Code: `AskUserQuestion`; OpenCode: its
|
|
135
|
+
question tool); the bot pins it, and the pin notifies. In autonomous mode stop and report instead.
|
|
136
|
+
- A message headed `[Request <id> · from: …]` is answered through `answer_request` (`progress`, `question`,
|
|
137
|
+
`final`); do not repeat its text as plain text afterwards.
|
|
138
|
+
- The passing-run video of a new e2e test → `send_file_to_user` (H.264 `.mp4`, sent as a video). Several
|
|
139
|
+
separate items, e.g. one per finished scope → `send_messages_to_user`.
|
|
140
|
+
- Work the user wants later → `schedule_create` with `onceAt` and a prompt that stands on its own.
|
|
141
|
+
- Write for a non-technical reader: the status, then the next steps as a short numbered list of who does what.
|
|
142
|
+
|
|
143
|
+
## A tracker conversation (Jira)
|
|
144
|
+
|
|
145
|
+
There are no `schedule_*` tools and nothing will wake you. Do not end your turn while a worker runs: wait in the
|
|
146
|
+
turn with foreground polls of at most 10 minutes each, checking the same two signals (the PID, the run directory
|
|
147
|
+
changing), report interim progress with `answer_request` kind `progress`, and end with kind `final`.
|
|
148
|
+
|
|
149
|
+
## Finally
|
|
150
|
+
|
|
151
|
+
Confirm from the reports that every changed file is listed, verification passed, the reviews are clean and the
|
|
152
|
+
plan is archived. Blocked or incomplete → leave the plan as it is for inspection. Report one line of outcome.
|
|
@@ -14,6 +14,12 @@ export declare const openCodeAdapterName = "opencode";
|
|
|
14
14
|
* lifecycle, the same tmux session name and host dir per conversation.
|
|
15
15
|
*/
|
|
16
16
|
export declare const claudePerTurnAdapterName = "claude-per-turn";
|
|
17
|
+
/**
|
|
18
|
+
* The tmux-scrape Claude Code backend (the interactive TUI driven by keystrokes, output scraped from the pane).
|
|
19
|
+
* DEPRECATED and frozen: no new work and no new-feature tests on it. It stays selectable (`/claude_mode`) and
|
|
20
|
+
* existing topics on it keep working, but {@link claudeJsonStreamAdapterName} is the recommended backend.
|
|
21
|
+
*/
|
|
22
|
+
export declare const claudeTmuxAdapterName = "claude";
|
|
17
23
|
/** Both backends that run the json-stream host (one process per conversation at a time). */
|
|
18
24
|
export declare function checkIsJsonStreamBackend(name: string): boolean;
|
|
19
25
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapterNames.d.ts","sourceRoot":"","sources":["../../src/adapters/adapterNames.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,wFAAwF;AACxF,eAAO,MAAM,2BAA2B,uBAAuB,CAAC;AAEhE,kDAAkD;AAClD,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAE9C;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,oBAAoB,CAAC;AAE1D,4FAA4F;AAC5F,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE1D"}
|
|
1
|
+
{"version":3,"file":"adapterNames.d.ts","sourceRoot":"","sources":["../../src/adapters/adapterNames.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,wFAAwF;AACxF,eAAO,MAAM,2BAA2B,uBAAuB,CAAC;AAEhE,kDAAkD;AAClD,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAE9C;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,oBAAoB,CAAC;AAE1D;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,WAAW,CAAC;AAE9C,4FAA4F;AAC5F,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE1D"}
|