Commit Graph

276 Commits

Author SHA1 Message Date
ismeth 62cf707502 fix: resolve 11 council-audited violations across athena subsystem
- Add switch_agent to athena-junior deny list (P1 defense-in-depth)
- Add terminal status check to waitForSessionIds polling loop
- Add athena-junior to OverridableAgentNameSchema and AgentOverridesSchema
- Add explicit retry workflow instructions to non-interactive prompt Step 9
- Fix JSON schema generation to exclude defaulted fields from required arrays
- Fix docs example for non_interactive_member_list (remove Council: prefix)
- Use segment-aware regex in path-policy.ts to block fake.sisyphus/ paths
- Add defensive path resolution and contract validation for prompt_file
- Add explicit .optional() to AthenaOverrideConfigSchema fields for clarity
- Fix traversal check precision for .. prefixed directory names
2026-04-15 16:48:49 +09:00
ismeth 6db83b937f fix: resolve 7 council-validated PR violations
- Fix misleading background_wait instructions to show loop pattern with
  remaining_task_ids (race semantics, not block-all)
- Fix wrong Gemini model string: gemini-3-pro-preview → gemini-3-pro
- Add getMainSessionID() fallback when input.sessionID is undefined
- Narrow .gitignore packages/ to only ignore built binaries
- Fix contradictory config doc: non_interactive_members 'all' → 'custom'
- Add athena-junior to keyword-detector exclusion check
- Add .trim() before .toUpperCase() in resolveCouncilIntent
- Update snapshots for model string change
2026-04-15 16:48:48 +09:00
ismeth 7ffdd15b52 feat(athena-junior): add athena_council bulk launch tool
- Create src/tools/athena-council/ with council-launcher, tool factory, types
- Launch all council members in parallel via BackgroundManager with writeOutputToFile: true
- Wire tool into registry with backgroundManager + councilConfig dependencies
- Grant athena-junior athena_council permission, remove task permission
- Update non-interactive prompt to use athena_council instead of task tool
- Add explicit stop-after-result instruction to prevent post-output text
- 23 tests (14 tool + 9 launcher) using real temp files, no mock.module
2026-04-15 16:48:46 +09:00
ismeth 6e57d060e1 fix(council-finalize): append runtime guidance to tool response for same-turn delivery
Remove contextCollector dependency from council_finalize and append
Athena runtime guidance directly to the tool's JSON response string.
This fixes the timing bug where guidance registered via contextCollector
only arrived on the next message cycle, too late for Athena's same-turn
synthesis.

- Remove ContextCollector import, RegisterContext type, and collector.register() block
- Append buildAthenaRuntimeGuidance() output after JSON result with \n\n separator
- Simplify createCouncilFinalize() factory call in tool-registry (no options)
- Update unit tests: replace collector mock assertions with direct output string checks
- Update integration tests: wrap JSON.parse with extractJson() helper for hybrid output
2026-04-15 16:48:44 +09:00
ismeth a33a3d1095 refactor(athena): remove redundant council_read tool, use Read instead
council_read was a sandboxed readFile wrapper for .sisyphus/ archives.
Now that council_finalize extracts member responses into plain files,
the standard Read tool serves the same purpose. Removes the tool, its
tests, and updates Athena's prompt to reference Read directly.
2026-04-15 16:48:07 +09:00
ismeth 34faa7c67c refactor(switch-agent): replace deferred hook system with direct session.create + promptAsync
Adopt the opencode-handoff pattern: switch_agent now creates a new session
and sends the context via promptAsync immediately in the tool's execute
function, then navigates the TUI to the new session.

Removes ~1700 LOC of complexity: persistent state management, event-based
hook monitoring, retry logic, session idle waiting, apply verification,
and terminal detection — all replaced by 3 SDK calls.

Deleted: src/features/agent-switch/ (14 files), src/hooks/agent-switch/ (4 files)
Updated: Athena prompt to announce handoff before calling switch_agent
2026-04-15 16:48:01 +09:00
ismeth c265200f5f feat(athena): inject intent runtime guidance and action flows 2026-04-15 16:47:52 +09:00
ismeth f5829bf2fb fix(athena): resolve task output files to project directory instead of process.cwd()
task-output-writer wrote to process.cwd()/.sisyphus/task-outputs/ while
council_finalize read from ctx.directory/.sisyphus/task-outputs/. When
these differ, all output files appear missing.

Fix by passing directory to writeTaskOutput from BackgroundManager, and
adding basePath to council_read. Also removes process.chdir() from tests
that was masking the bug.
2026-04-15 16:47:20 +09:00
ismeth 2b70130c08 feat(athena): council member continuation enforcer, tool allowlist, and prompt fixes
- Add council-continuation-enforcer to nudge council members until they
  output COUNCIL_MEMBER_RESPONSE, replacing the hacky post-compaction hack
- Add background_wait + background_cancel to council member tool allowlist
  so members can properly manage their explore agents before responding
- Update COUNCIL_DELEGATION_ADDENDUM prompt to instruct members to cancel
  pending tasks and wait for explore results before final response
- Fix council_finalize path resolution to use project directory
- Remove post-compaction-continuation.ts and recentlyCompactedSessions hack
- Add council-response-checker for detecting response tag in session messages
2026-04-15 16:46:05 +09:00
ismeth 6b450b42db feat(athena): add intent parameter to prepare_council_prompt + wire hook into plugin system + update exports 2026-04-15 16:43:17 +09:00
ismeth b6b956c4c3 feat(council-archive): register council tools and add write_output_to_file to task tool
- Register council_finalize and council_read in tool registry
- Add write_output_to_file param to delegate-task, propagate to LaunchInput
- Create council-archive barrel exports
2026-04-15 16:43:17 +09:00
ismeth c75ae6bffd fix(athena): write council prompt to .sisyphus/tmp/, switch to allow-list permissions
Council members now use an allow-list (read, grep, glob, lsp_*, ast_grep_search)
instead of a deny-list. Prompt file moved from /tmp/ to .sisyphus/tmp/ so no
external_directory permission is needed. COUNCIL_MEMBER_PROMPT is included in
the temp file for self-contained council member instructions.
2026-04-15 16:39:28 +09:00
ismeth da0fba3166 feat(athena): add prepare_council_prompt tool for faster council launches
Athena saves the analysis prompt to a temp file once, then launches each
council member with a short "Read <path> for your instructions" prompt.
This eliminates repeated prompt text across N task calls while preserving
individual clickable task panes in the TUI.
2026-04-15 16:39:28 +09:00
ismeth 636c66ca62 fix: sync council-member tool restrictions across all layers, optimize athena guards
- Add switch_agent/background_wait to agent-tool-restrictions.ts (boolean format)
- Add dynamic council member name matching via COUNCIL_MEMBER_KEY_PREFIX
- Move athena question permission from hardcoded to tool-config-handler (CLI-mode aware)
- Rename appendMissingCouncilPrompt -> applyMissingCouncilGuard
- Optimize tool-execute-before: check hasPendingCouncilMembers before resolving session agent
- Add fallback_models to council-member/athena in schema.json
- Remove unused createAthenaAgent export from agents/index.ts
- Add cross-reference comments for restriction sync points
2026-04-15 16:39:04 +09:00
ismeth 9f541ed3ee fix(athena): address 9 council-audit findings — dead code, bugs, and hardening
Fixes from multi-model council audit (7 members, 19 findings, 9 selected):

- Use parseModelString() for cross-provider Anthropic thinking config (#3)
- Update stale AGENTS.md athena directory listing (#4)
- Replace prompt in appendMissingCouncilPrompt instead of appending (#5)
- Extract duplicated session cleanup logic in agent-switch hook (#6)
- Surface skipped council members when >=2 valid members exist (#9)
- Expand fallback handoff regex with negation guards (#11)
- Remove dead council-member agent from agentSources and tests (#12)
- Make runtime council member duplicate check case-insensitive (#14)
- Fix false-positive schema tests by adding required name field (#18)
2026-04-15 16:34:01 +09:00
ismeth 5769a48a94 fix(athena): update council member guards for new agent key format
The hasPendingCouncilMembers guard now matches the 'Council: ' prefix from COUNCIL_MEMBER_KEY_PREFIX instead of the old task.agent === 'council-member' check.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-15 16:31:01 +09:00
ismeth ac42ff6788 refactor(athena): remove athena_council from plugin wiring
Drop the barrel export, tool-registry registration, and agent-tool-restriction entry for the deleted athena_council tool.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-15 16:24:16 +09:00
ismeth 8de10c1f2b fix(agent-switch): make handoff durable and sync CLI TUI selection 2026-04-15 16:18:19 +09:00
ismeth 4764d65db1 fix(athena): parallelize council launches and gate handoff actions 2026-04-15 16:17:43 +09:00
ismeth ca199ee85b fix(athena): make council tool blocking — collect results directly instead of polling
The athena_council tool now waits for all council members to complete and
returns their collected results as markdown, eliminating the need for
Athena to repeatedly call background_output per member (which created
excessive UI noise).

- Add result-collector.ts that polls task status and fetches session content
- Update tool to accept BackgroundOutputClient and return formatted markdown
- Update Athena prompt to remove background_output polling steps
- Rewrite tests for new blocking behavior and markdown output format
2026-04-15 15:56:56 +09:00
ismeth 84185490f9 refactor(athena): rename session_handoff to switch_agent to avoid confusion with /handoff command
Rename across all layers to eliminate naming ambiguity:
- Tool: session_handoff → switch_agent
- Hook: agent-handoff → agent-switch
- Feature: agent-handoff/ → agent-switch/
- Types: SessionHandoffArgs → SwitchAgentArgs, PendingHandoff → PendingSwitch
- Functions: setPendingHandoff → setPendingSwitch, consumePendingHandoff → consumePendingSwitch

/handoff = inter-session context summary (existing command)
switch_agent = intra-session active agent change (our new tool)
2026-04-15 15:47:13 +09:00
ismeth 7db0f110ee feat(athena): add session handoff with Question tool for Atlas/Prometheus routing
After Athena synthesizes council findings, presents user with Question tool
TUI to choose: Atlas (fix now), Prometheus (create plan), or no action.
On selection, session_handoff tool stores intent + calls updateSessionAgent(),
then agent-handoff hook fires on session.idle to switch the main session's
active agent via promptAsync with synthesis context.
2026-04-15 15:45:46 +09:00
ismeth 74862cede9 feat(06-01): register athena council tool in runtime registry
- export createAthenaCouncilTool from tools index

- wire athena_council with agents.athena.council config in tool registry
2026-04-15 15:42:15 +09:00
YeonGyu-Kim 62c60ae9d8 fix: numeric skill names, ultrawork missing run_in_background, ZWSP agent lookups
- #3354: Coerce data.name to String in loadSkillFromPath/loadSkillFromPathAsync
  to prevent crash when YAML parses numeric skill names (e.g., name: 12306)

- #3416: Add required run_in_background parameter to all task() examples in
  ultrawork prompts (default, gpt, gemini, planner) to match tool schema

- #3379/#3417/#3418/#3337/#3335: Strip ZWSP (U+200B) before agent name
  comparisons in agent-tool-restrictions, sync-prompt-sender, tool-execute-after,
  tool-execute-before, oracle-verification-detector, call-omo-agent,
  recovery-prompt-config, and agent-variant to prevent ZWSP-prefixed display
  names from breaking exact-match lookups
2026-04-15 10:46:41 +09:00
YeonGyu-Kim 051ab840d6 Merge pull request #3348 from code-yeongyu/refactor/ulw-repo-cleanup-20260411
refactor: simplify nullish guards and remove dead no-op paths
2026-04-12 18:04:43 +09:00
YeonGyu-Kim eb495793db fix(event): prefer real session.idle over recent synthetic dedup (#2667)
The dedup logic dropped real session.idle events when a synthetic
idle had fired within the dedup window, losing data that downstream
hooks needed. Now real idle events always reach dispatchToHooks while
synthetic duplicates are still dropped when a real event came first.

🤖 Generated with OhMyOpenCode assistance
https://github.com/code-yeongyu/oh-my-opencode
2026-04-12 02:30:11 +09:00
YeonGyu-Kim a0d5131ee1 refactor(plugin): remove dead chat params code
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-12 00:07:10 +09:00
YeonGyu-Kim 0c5cd3a1c4 chore(agents): update all AGENTS.md generation dates to 2026-04-11
🤖 Generated with OhMyOpenCode assistance
2026-04-11 22:33:22 +09:00
YeonGyu-Kim f5dc1c0eba refactor(event): simplify tmux config check to direct property access 2026-04-11 22:14:48 +09:00
YeonGyu-Kim c9461a9085 fix(stop-continuation): scope start-work clearing to fallback template
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-11 21:36:40 +09:00
YeonGyu-Kim 9287abe157 fix(stop-continuation): clear chat.message fallback stop state before work resumes
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-11 21:24:03 +09:00
YeonGyu-Kim 6ec9a2bd79 fix(openclaw): skip session.created dispatch for subagent sessions 2026-04-10 18:47:18 +09:00
YeonGyu-Kim de156578ea fix(stop-continuation): clear stop state for native work-starting commands 2026-04-10 18:47:18 +09:00
YeonGyu-Kim c21c3630ca test(plugin): update plugin config and registry tests
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-10 15:53:25 +09:00
YeonGyu-Kim 1a090af2eb feat(tools): add tools for session manager and skill refresh
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-10 15:53:07 +09:00
YeonGyu-Kim b60b2bcc3f plugin: stop false provider cache warning 2026-04-10 13:43:58 +09:00
YeonGyu-Kim 30f4f06b9b test(chat-message): cover plain ulw without loop start
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-10 11:40:20 +09:00
YeonGyu-Kim 2083cb0710 feat(agents): add centralized GPT apply_patch permission guard
Extract hardcoded GPT apply_patch permission logic into a reusable module
to ensure consistent behavior across all agents. This prevents GPT models
from using the unreliable apply_patch tool while allowing other models.

- Add gpt-apply-patch-guard.ts with GPT_APPLY_PATCH_GUIDANCE and getGptApplyPatchPermission
- Update Hephaestus agent to use centralized permission logic
- Update Sisyphus-Junior agent to use centralized permission logic
- Update all GPT prompt builders to reference shared guidance constant

🤖 Generated with assistance of OhMyOpenCode
2026-04-10 10:47:27 +09:00
YeonGyu-Kim ab515b77d0 fix(stop-continuation): persist stop state across user messages (#3276)
The /stop-continuation command was ineffective because the stop-
continuation-guard cleared its stopped state on the very next
chat.message event. Since any user message (including normal chat
after stopping) triggers chat.message, the continuation would
resume immediately.

Root cause: the chat.message handler called clear(sessionID) on
every user message, treating it as a 'user resumed work' signal.
But the user expects /stop-continuation to persist until they
explicitly start work again.

Changes:
- stop-continuation-guard chat.message: no longer clears stop state
- tool-execute-before: /start-work, /ralph-loop, /ulw-loop now
  explicitly clear the stop state (so continuation resumes when
  user intentionally restarts work)
- Updated and added tests: 12 pass (3 new), 125 related tests pass

Closes #3276
2026-04-09 21:36:10 +09:00
YeonGyu-Kim 132a994cfc Merge pull request #3206 from Momentum96/fix/openclaw-reply-listener
fix(openclaw): stabilize reply listener wiring and runtime dispatch
2026-04-09 12:34:59 +09:00
GeonWoo Jeon (Jay) ade57474be fix(merge): resolve dev conflicts for openclaw branch 2026-04-09 12:23:38 +09:00
YeonGyu-Kim 0d5b087440 Revert "Merge pull request #3260 from code-yeongyu/fix/remove-zwsp-sort-prefixes"
This reverts commit c3be4c2793, reversing
changes made to d2bb5d57d1.
2026-04-09 12:21:02 +09:00
GeonWoo Jeon (Jay) 49d29c5565 fix(test): reset session manager storage in registry tests 2026-04-09 12:09:09 +09:00
YeonGyu-Kim 8b418ea38a fix(agents): remove ZWSP sort prefixes from display name helper (#3259)
AGENT_LIST_SORT_PREFIXES prepended U+200B Zero Width Space characters
to the four core agent display names so they would sort ahead of user
agents in the Tab cycle. Two problems with that approach surfaced:

  1. Some terminal emulators (Ghostty, certain Windows Terminal
     builds) render ZWSP as a visible box or extra space, producing a
     visible black gap in the status bar before "Sisyphus" and
     misaligning the layout (#3259).

  2. The prefixes leaked into the plugin API surface via config.agent
     keys, breaking prompt_async consumers that received
     ZWSP-contaminated agent names (#3238).

#3242 already removed every call site of getAgentListDisplayName() in
production code. That made the sort prefixes dead code: the constant
table was still defined but nothing read it. This PR finishes the
cleanup by:

  - Deleting the AGENT_LIST_SORT_PREFIXES constant entirely
  - Turning getAgentListDisplayName() into a thin alias over
    getAgentDisplayName() for BC with external importers
  - Keeping stripAgentListSortPrefix() as a legacy data migration for
    users upgrading from v3.14.0-v3.16.0 whose config.agent keys may
    still have ZWSP baked in from the old code path
  - Documenting the history on stripAgentListSortPrefix() so future
    maintainers understand why the stripper has to stay even after
    the injector is gone

Sort ordering is preserved via JS object insertion order in
reorderAgentsByPriority() plus the `order` field it injects on the
four core agents. Both mechanisms are already in place and both
pre-date this PR; the ZWSP prefix was an older third layer that was
only meant to work around alphabetical sorting in legacy OpenCode
before the `order` field landed upstream.

Tests: 4445 pass, 0 fail. Added 3 new assertions to
agent-display-names.test.ts verifying that getAgentListDisplayName
returns plain names containing no zero-width characters. Updated
chat-message.test.ts to use a literal ZWSP string instead of the
helper so the defensive-strip path still has coverage.

Closes #3259
2026-04-09 10:10:12 +09:00
YeonGyu-Kim cd95172e42 fix(start-work): keep native command agents on config keys 2026-04-08 15:58:02 +09:00
YeonGyu-Kim 78e6d780eb fix(plugin): verify event hook compatibility with v1.4.0
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-08 13:08:03 +09:00
YeonGyu-Kim e52dd340c6 fix(plugin): migrate chat.params to maxOutputTokens for v1.4.0
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-08 13:02:51 +09:00
GeonWoo Jeon (Jay) 21ab1a6475 fix(plugin): dispatch openclaw lifecycle events from handlers 2026-04-07 22:54:03 +09:00
YeonGyu-Kim 8f129eb4ad fix(test): update plugin tests to use getAgentListDisplayName for agent assertions
- Update plugin-interface.test.ts expectations to use getAgentListDisplayName
- Update chat-message.test.ts expectations for agent display names
- Add smoke test for quoted plan name resolution in chat-message.test.ts
- Aligns test expectations with proper agent name formatting

🤖 Generated with OhMyOpenCode assistance
2026-04-07 19:05:14 +09:00
YeonGyu-Kim 062b8cd718 Merge pull request #3169 from code-yeongyu/fix/sisyphus-junior-model
fix(model-fallback): respect user model override for sisyphus-junior category sessions (#2941)
2026-04-07 15:14:09 +09:00