Commit Graph

4818 Commits

Author SHA1 Message Date
YeonGyu-Kim d00a6bbf16 fix(keyword-detector): always trigger ultrawork keywords 2026-04-10 11:15:23 +09:00
YeonGyu-Kim f36231a8a6 fix(keyword-detector): trigger ulw shorthand anywhere 2026-04-10 11:12:56 +09:00
YeonGyu-Kim 5f90b238e0 fix(keyword-detector): restore ulw trigger after greeting prefixes 2026-04-10 11:09:01 +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
github-actions[bot] 498d021dc2 @zhoufanscut has signed the CLA in code-yeongyu/oh-my-openagent#3292 2026-04-09 15:17:28 +00:00
github-actions[bot] 5535750283 @revelri has signed the CLA in code-yeongyu/oh-my-openagent#3287 2026-04-09 14:30:17 +00:00
YeonGyu-Kim 6df597c60c Merge pull request #3279 from code-yeongyu/fix/stop-continuation-persistence
fix(stop-continuation): persist stop state across user messages (#3276)
2026-04-09 21:50:50 +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 69f47a9751 feat(keyword-detector): handle ultrawork keyword after greeting patterns
- Add TRAILING_GREETING_ULTRAWORK_PATTERN to detect 'hi ultrawork' style inputs
- Rename hasLeadingUltraworkKeyword to hasEdgeUltraworkKeyword for clarity
- Add extractUltraworkTask guard to return empty string for greeting-only inputs
- Add comprehensive test coverage for edge trigger scenarios

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-09 15:15:30 +09:00
YeonGyu-Kim 58be69114f docs: update AGENTS.md hierarchy with openclaw, runtime-fallback, skill-mcp-manager
- Add src/openclaw/AGENTS.md: bidirectional Discord/Telegram/webhook integration
- Add src/hooks/runtime-fallback/AGENTS.md: reactive provider error recovery
- Add src/features/skill-mcp-manager/AGENTS.md: tier-3 MCP lifecycle
- Update root AGENTS.md: refresh commit hash, add openclaw/IntentGate/Hashline refs
- Fix src/features/AGENTS.md: skill-mcp-manager file count 14→18, complexity MEDIUM→HIGH

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-09 15:14:40 +09:00
YeonGyu-Kim dc7a46809f Merge pull request #3268 from code-yeongyu/fix/ci-flake-model-resolution-pipeline
fix(ci): isolate model-resolution-pipeline test to prevent mock contamination
2026-04-09 14:24:13 +09:00
YeonGyu-Kim 7a1f121fdd fix(ci): isolate model-resolution-pipeline test to prevent mock contamination
The resolveModelPipeline test was consistently failing on CI
(resolveModelPipeline > does not return unused explicit user config
metadata in override result) while passing locally. Root cause is the
same mock.module contamination pattern as #3243: when bun runs all test
files in a single process, mock.module calls from other files (e.g.
model-resolver.test.ts) leak into this file's module scope.

Add mock.module('./logger', ...) so run-ci-tests.ts auto-detects the
file and runs it in its own isolated bun process.

This unblocks the v3.16.1 publish workflow which hit this flake twice.
2026-04-09 14:19:17 +09:00
github-actions[bot] d17b78afe6 @ayixiayi has signed the CLA in code-yeongyu/oh-my-openagent#3267 2026-04-09 04:19:35 +00:00
YeonGyu-Kim 4f88e0f4e1 fix(agents): restore canonical core agent ordering
Remap the core agent keys, default agent, and command routing back to\nlist display names so OpenCode's name-based sorting keeps the\ncanonical Sisyphus -> Hephaestus -> Prometheus -> Atlas order.\n\nAlso teach tool config lookups to resolve the prefixed list keys and\nadd regression tests that exercise the real ordering and routing path.
2026-04-09 12:50:05 +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
YeonGyu-Kim 55a57a8029 Merge pull request #3265 from code-yeongyu/revert/3260-restore-zwsp-sort-prefixes
Revert "fix(agents): remove ZWSP sort prefixes from display name helper (#3259)"
2026-04-09 12:27:09 +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) e5189f2164 fix(test): wait for async skill description refresh 2026-04-09 12:09:09 +09:00
GeonWoo Jeon (Jay) 49d29c5565 fix(test): reset session manager storage in registry tests 2026-04-09 12:09:09 +09:00
GeonWoo Jeon (Jay) 6aab2f7b34 fix(schema): use zod native json schema output 2026-04-09 12:09:09 +09:00
GeonWoo Jeon (Jay) 687e7bb243 fix(test): align zombie pane tmux mocks 2026-04-09 12:09:09 +09:00
GeonWoo Jeon (Jay) f82cc81c33 fix(ci): isolate discord reply listener test 2026-04-09 12:09:09 +09:00
github-actions[bot] ef95a99420 @gwegwe1234 has signed the CLA in code-yeongyu/oh-my-openagent#3264 2026-04-09 02:46:38 +00:00
YeonGyu-Kim 99a6d50db5 Merge pull request #3197 from code-yeongyu/fix/delegate-task-depth-guard
fix(delegate-task): tighten subagent depth guard + add regression smoke tests
2026-04-09 11:29:29 +09:00
YeonGyu-Kim 524e0f6cbd Merge pull request #3170 from code-yeongyu/fix/gpt-apply-patch
fix(agents): deny apply_patch for GPT models to prevent verification hangs (#2935)
2026-04-09 11:14:21 +09:00
YeonGyu-Kim e0ed5ddbe1 Merge pull request #3200 from code-yeongyu/fix/doctor-custom-providers
fix(doctor): false-positive 'Provider not found' for custom OpenAI-compatible providers
2026-04-09 11:13:40 +09:00
YeonGyu-Kim 21127b0308 Merge remote-tracking branch 'origin/dev' into fix/gpt-apply-patch-rebased 2026-04-09 11:06:36 +09:00
YeonGyu-Kim 545c444a85 Merge remote-tracking branch 'origin/dev' into fix/delegate-task-depth-guard-rebased 2026-04-09 11:06:31 +09:00
YeonGyu-Kim defe4e511c Merge remote-tracking branch 'origin/dev' into fix/doctor-custom-providers-rebased 2026-04-09 11:03:12 +09:00
YeonGyu-Kim 57ebb11e68 Merge pull request #3262 from code-yeongyu/fix/migration-sidecar
fix(migration): track applied migrations in sidecar so user reverts stick
2026-04-09 11:01:02 +09:00
YeonGyu-Kim 00a4f318ef fix(migration): track applied migrations in sidecar so user reverts stick
Users who auto-migrated from `openai/gpt-5.3-codex` to `openai/gpt-5.4`
and then reverted their config back to `gpt-5.3-codex` by hand had the
migration re-apply on every startup in an infinite loop. Discord bug
report pointed at the exact symptom: "i deleted the migrations and they
kept coming back".

The old migration tracking lived on the config body itself as a
`_migrations` string array. The skip-already-applied check relied on
the user not touching that field. But users hit by the unwanted
migration naturally reached for the JSON file to roll their model back,
and the natural human reaction to an incomprehensible internal field
next to their config is to delete it. That wiped the migration memory
and let the same migration re-apply at the next startup.

This PR introduces a sidecar state file that lives next to the config
as `<configPath>.migrations.json` and tracks applied migrations
outside the user's hand-editable config body. The migration pipeline:

  1. Reads applied migrations from BOTH the sidecar AND the legacy
     in-config `_migrations` field, unioning them. This keeps old
     configs that still carry `_migrations` working without forcing
     a reset.

  2. Writes the updated migration set to the sidecar, never to the
     config body.

  3. Strips the legacy `_migrations` field out of the config body on
     the first write after the sidecar takes over. Users stop seeing
     the mystery internal field in their own config from that point
     forward.

If the user also deletes the sidecar (explicit fresh-start gesture)
the migrations run again - that is intentional.

Tests (TDD, all new tests written before implementation):

  - src/shared/migration/migrations-sidecar.test.ts - 11 unit tests
    covering read/write/round-trip, malformed-payload resilience,
    parent-directory creation, sorted output for stable diffs, and
    non-string entry filtering.

  - src/shared/migration.test.ts - 6 new integration tests under the
    "migrateConfigFile with migration tracking via sidecar" block
    covering: no-op path, sidecar-only write, sidecar skip after user
    revert, legacy _migrations mirroring + strip, sidecar + legacy
    union with dedupe, and partial-history append. Existing
    "preserves existing _migrations and appends new ones" test was
    rewritten to assert the new sidecar-based contract.

  - Also fixes a latent test-hygiene bug: the shared
    /tmp/nonexistent-path-for-test.json config path used by many
    migrateConfigFile tests did not clean up its companion sidecar
    between tests, letting state from one test bleed into the next.
    Added afterEach that unlinks the sidecar.

Verified:

  - bun test src/shared/migration/ -> 11 new sidecar tests pass
  - bun test src/shared/migration.test.ts -> 82 pass, 0 fail
  - bun run typecheck -> clean
  - bun run script/run-ci-tests.ts -> 4458 pass, 0 fail (full suite)
2026-04-09 10:54:25 +09:00
github-actions[bot] 3eb36a1807 @NikkeTryHard has signed the CLA in code-yeongyu/oh-my-openagent#3261 2026-04-09 01:34:13 +00:00
YeonGyu-Kim c3be4c2793 Merge pull request #3260 from code-yeongyu/fix/remove-zwsp-sort-prefixes
fix(agents): remove ZWSP sort prefixes from display name helper (#3259)
2026-04-09 10:16:32 +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 d2bb5d57d1 Merge pull request #3258 from code-yeongyu/fix/auto-update-openagent-name-match
fix(auto-update): resolve cached version when installed as oh-my-openagent (#3257)
2026-04-09 07:34:01 +09:00
YeonGyu-Kim 4344a41eae fix(auto-update): resolve cached version when installed as oh-my-openagent (#3257)
The auto-update-checker's version resolver hardcoded the canonical
oh-my-opencode package name in three read paths:

  1. INSTALLED_PACKAGE_JSON pointed only at
     cache/node_modules/oh-my-opencode/package.json
  2. findPackageJsonUp() rejected any walked-up package.json whose name
     did not equal PACKAGE_NAME
  3. getLocalDevPath() only matched file:// plugin entries whose path
     contained the canonical name

The publish pipeline ships the same code under two npm package names
(oh-my-opencode canonical, oh-my-openagent alias). Users who add
"oh-my-openagent" to their opencode config end up with
node_modules/oh-my-openagent/package.json, so every read path above
silently missed the installed version and the startup toast fell back
to "unknown".

Introduce ACCEPTED_PACKAGE_NAMES + INSTALLED_PACKAGE_JSON_CANDIDATES in
constants.ts and teach the three readers to accept both names. Writes
are untouched (sync-package-json, pinned-version-updater, cache
invalidation) because the auto-update-checker still owns its own cache
workspace and writes to the canonical name there.

Tests: 54 auto-update-checker tests pass (4 new), full 4444-test suite
passes, tsc clean. New tests cover both install paths, the walk-up
resolver, and the priority order when both candidates exist.

Closes #3257
2026-04-09 07:29:07 +09:00
github-actions[bot] fcac67d1d2 @sen7971 has signed the CLA in code-yeongyu/oh-my-openagent#3248 2026-04-08 15:57:18 +00:00
YeonGyu-Kim af6df878bd Merge pull request #3243 from code-yeongyu/fix/ci-flaky-isolation
fix(ci): isolate model-resolver and prometheus-config tests from mock.module contamination
2026-04-08 23:44:52 +09:00
YeonGyu-Kim 6943b6d4d8 fix(ci): isolate model-resolver and prometheus-config tests from mock.module contamination
model-resolver.test.ts and prometheus-agent-config-builder.test.ts use
spyOn(shared, 'log') but do not own the logger module. When other test
files in the same bun test process call mock.module('../shared/logger'),
the import cache is poisoned and the spyOn targets a stale binding.

Add a lightweight mock.module call at the top of each file so the
auto-detection in run-ci-tests.ts picks them up as isolated targets.
This ensures each file gets its own module instance and the spy
captures all calls correctly.

Fixes the flaky CI failure pattern where resolveModelWithFallback and
buildPrometheusAgentConfig tests pass locally (separate bun process)
but fail in the shared CI batch.
2026-04-08 23:39:43 +09:00
YeonGyu-Kim dfcd8134ee Merge pull request #3242 from code-yeongyu/fix/zwsp-api-leak
fix(agents): remove ZWSP prefixes from config.agent keys (#3238)
2026-04-08 23:05:49 +09:00
YeonGyu-Kim 47283f9238 fix(agents): remove ZWSP prefixes from config.agent keys (#3238)
Agent names in the config.agent object (which becomes the /agent API
response) contained invisible Zero-Width Space (U+200B) characters
baked in by getAgentListDisplayName(). These ZWSP prefixes were used
for TUI sort ordering, but they leaked into the public API surface.

Impact: any prompt_async consumer that discovered agent names via the
/agent endpoint and passed them back to prompt_async without manual
ZWSP stripping got silent message drops — the agent name didn't match.
hy-pony's feishu-bridge integration went dark after upgrading to 3.16.0
with no error, no warning, and no indication that invisible Unicode
characters in agent names were the cause.

Fix: switch all four callsites from getAgentListDisplayName() (which
prepends \u200B×N) to getAgentDisplayName() (clean names):

- agent-key-remapper.ts: config keys → display names (was the primary
  injection point)
- agent-priority-order.ts: CORE_AGENT_ORDER lookup (must agree with
  the keys emitted by the remapper)
- command-config-handler.ts: command agent field normalization
- tool-config-handler.ts: agent config lookup (simplified fallback
  chain since the primary lookup is now clean)

Sort ordering is preserved by:
1. JS object insertion order from reorderAgentsByPriority()
2. The injected `order` field (1-4) added by injectOrderField()

getAgentListDisplayName() is marked @deprecated with a link to #3238.
AGENT_LIST_SORT_PREFIXES and stripAgentListSortPrefix() are kept for
any internal callers that strip prefixes from legacy data.

Closes #3238
2026-04-08 22:51:59 +09:00
YeonGyu-Kim ed62f827e3 Merge pull request #3236 from code-yeongyu/fix/compaction-failure-toast
fix(preemptive-compaction): notify user on failure and reduce timeout
2026-04-08 20:15:09 +09:00
YeonGyu-Kim 1ea0ee4319 fix(preemptive-compaction): notify user on failure and reduce timeout
Reports from david_66 on Discord: sessions get perceived as 'stuck' when
context usage crosses the 78% threshold. Investigation confirmed two
issues in the preemptive compaction hook:

1. PREEMPTIVE_COMPACTION_TIMEOUT_MS was 120s. While the summarize
   request is in flight, tool.execute.after short-circuits via the
   compactionInProgress guard. A hung summarize blocked the session
   for two full minutes before giving up, which users reasonably
   experience as a hang.

2. On failure (timeout or exception) only a log line was emitted. The
   user had no visibility into why their session was unresponsive or
   why auto-compaction never ran, so a transient upstream error could
   silently leave them well above the threshold with no signal.

Fix:

- Reduce timeout 120s -> 60s. Still gives the upstream a generous
  window, but caps the worst-case perceived hang at one minute.
- Show a warning toast via ctx.client.tui.showToast whenever the
  catch block fires, including the underlying error string so users
  can act (retry, manual /compact, or adjust provider).
- Include providerID/modelID in the Compaction failed log entry so
  wild failures are easier to correlate to a specific target model.

Two existing failure-path assertions were updated to match the new
log shape and a new test covers the toast notification contract.

Discord report: https://discord.com/channels/1452487457085063218/1490536332961906829/1491345441399505037
2026-04-08 20:10:25 +09:00
github-actions[bot] 686f903d1f @FrancoStino has signed the CLA in code-yeongyu/oh-my-openagent#3234 2026-04-08 10:52:51 +00:00
github-actions[bot] fbd3e7aabe release: v3.16.0 2026-04-08 10:04:19 +00:00
YeonGyu-Kim c5b6d59c94 Merge pull request #3227 from code-yeongyu/fix/installer-and-auto-update
fix(installer): enforce min version + upgrade pinned entries
2026-04-08 17:40:54 +09:00
YeonGyu-Kim d781b7537f Merge pull request #3226 from code-yeongyu/fix/plan-progress-and-trust
fix(plan): skill MCP trust + non-ASCII names + simple-mode progress + ralph-loop cap
2026-04-08 17:40:51 +09:00
YeonGyu-Kim bdf6e4195a Merge pull request #3225 from code-yeongyu/fix/agent-name-safety
fix(agent): narrow ULW auto-start + strip ZWSP on background path + fix auto-update identity
2026-04-08 17:40:48 +09:00
YeonGyu-Kim c37e440ba8 Merge pull request #3224 from code-yeongyu/fix/oauth-wiring
fix(oauth): wire refresh mutex + post-request auth handler
2026-04-08 17:40:46 +09:00