Commit Graph

268 Commits

Author SHA1 Message Date
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
YeonGyu-Kim 6ebe1bf1ab Merge pull request #3176 from code-yeongyu/fix/issue-3113
fix(keyword-detector): start ralph-loop when ulw keyword detected (#3113)
2026-04-07 15:14:07 +09:00
YeonGyu-Kim 717c976c66 fix(keyword-detector): start ralph-loop when ulw keyword detected (#3113)
Plain 'ulw' keyword now starts the continuation loop via
ralphLoop.startLoop(), matching README promise. Wired through
create-core-hooks.ts and create-transform-hooks.ts.

TDD: 40 keyword-detector tests pass, 1239 hook tests pass, tsc clean.

Closes #3113
2026-04-07 15:11:29 +09:00
YeonGyu-Kim 889294a5fd fix(model-fallback): respect user model override for sisyphus-junior category sessions (#2941)
When users configure agents.sisyphus-junior.model, category sessions
should use that model without falling back to hardcoded
AGENT_MODEL_REQUIREMENTS. Two leaks existed:

1. Launch-time: category-resolver.ts did not check overrideModel when
   deciding whether to use the hardcoded fallbackChain. Fixed by adding
   overrideModel to the suppression condition.

2. Runtime retry: model-fallback hook.ts treated undefined fallbackChain
   (from setSessionFallbackChain(id, undefined)) as 'no override' and
   fell through to AGENT_MODEL_REQUIREMENTS on session.error/status
   retry. Fixed by storing explicit empty array and checking .has()
   instead of truthiness.

Tests added:
- hook.test.ts: explicit empty session fallback suppresses agent chain
- event.model-fallback-2941.test.ts: session.error does not arm retry
- category-resolver.test.ts: overrideModel suppresses fallbackChain
- tools.test.ts: sisyphusJuniorModel override assertion
2026-04-07 11:20:42 +09:00
YeonGyu-Kim f8c626086e fix(agent-names): use HTTP-header-safe display names and config keys for API calls (#3138)
Display names with parentheses like 'Atlas (Plan Executor)' cause HTTP
header validation errors in x-opencode-agent-name. This was blocking
Atlas/Prometheus from working via /start-work and auto-retry.

Changes:
- Display names: parens -> dashes ('Atlas - Plan Executor')
- Hooks (start-work, no-hephaestus-non-gpt, no-sisyphus-gpt): use
  config keys ('atlas', 'sisyphus', 'hephaestus') for agent API fields
- auto-retry: use config key instead of display name for promptAsync
- agent-override-protection: handle dash-suffix normalization
- Updated all test expectations to match new format

Closes #3138
2026-04-07 10:08:04 +09:00
YeonGyu-Kim e62d5d7a22 fix(agents): strip ZWSP ordering prefixes in session state, config lookups, and override protection
Prevent ZWSP sort prefixes from leaking into stored agent names, config
key lookups, and override-protection normalization. Ensures prefixed
list-display names resolve correctly throughout the pipeline.

🤖 Generated with [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode) assistance
2026-04-06 18:07:26 +09:00
YeonGyu-Kim 6d66659025 docs(src): update hook composition counts in src and plugin AGENTS.md
- Core hooks: 39 -> 43 (Session 24, ToolGuard 14, Transform 5)
- Total hooks: 48 -> 52
- Add transform hooks tier to plugin composition table
- Update session/tool-guard hook name lists
2026-04-05 14:12:30 +09:00
YeonGyu-Kim 7243bfa483 fix(tool-registry): use interactive bash availability for tool registration
🤖 Generated with assistance of [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
2026-04-05 13:27:55 +09:00
YeonGyu-Kim 07ccbd2047 fix(event): respect tmux integration disabled state in event forwarding
🤖 Generated with assistance of [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
2026-04-05 13:27:50 +09:00