Commit Graph

696 Commits

Author SHA1 Message Date
YeonGyu-Kim 30adce9cad fix(prompt-gate): share message reservations 2026-05-15 12:55:56 +09:00
YeonGyu-Kim 1e7a7600a2 docs(agents-md): regenerate hierarchical AGENTS.md knowledge base for v4.1.1
Refresh all AGENTS.md files to reflect codebase state at 5ffbe0e24 (was cd31d2a1a, 197 commits behind).

Key drift corrections across 45 modified + 1 new file:

Root AGENTS.md:
- TS file counts: 1967 -> 2034 in src/ (1337 source + 697 test)
- LOC: 278k -> 292k
- Barrel index.ts: 120 -> 122
- Hook tier composition: 52/59 -> 54/61 (base/with team-mode)
- Tool Guard hooks: 14 -> 16 (add fsync-skip-warning, bash-file-read-guard)
- Add boulder feature, agent-ordering schema, .agents/ directory, v4.1.1 release tag
- Add generated/ directory entry

src/AGENTS.md:
- Subsystem inventory: agents 96->102, hooks 570->581, tools 306->314,
  features 389->400, shared 258->278, cli 150->158, plugin 55->56
- LOC totals refreshed for every subsystem
- Schema files: 32 -> 30

src/hooks/AGENTS.md:
- Tier 2 (Tool Guard): 14 -> 16 hooks, add fsyncSkipWarning row
- Total: 52 base / 59 team-mode -> 54 base / 61 team-mode
- zauc-mocks count: 7 -> 5

src/features/AGENTS.md:
- background-agent: 47 -> 57 files, mention archive fallback
- opencode-skill-loader: 33 -> 30
- tmux-subagent: 34 -> 32

src/plugin/AGENTS.md:
- Tool Guard composer count: 14 -> 16
- Aggregator total: 43 -> 45

src/cli/AGENTS.md:
- Add new boulder subcommand (BoulderState inspector)
- Command count: 6 -> 7

NEW: src/features/boulder-state/AGENTS.md
- Document the new Boulder work tracking feature
- Schema v2 with BoulderState/BoulderWorkState/TaskSessionState
- Lifecycle, storage, integration points with atlas/ralph-loop hooks

All other AGENTS.md files: Generated date 2026-05-08 -> 2026-05-14.
2026-05-14 12:57:46 +09:00
YeonGyu-Kim 38b1433ff5 fix(continuation): mark resumes synthetic 2026-05-13 13:09:26 +09:00
YeonGyu-Kim 6035a551ad fix(background-agent): route session prompts by directory 2026-05-12 18:13:39 +09:00
YeonGyu-Kim d5fbada13d test: make unsafe test coercion explicit
Move test coercion out of a hidden global and require each test to import the helper so review tools and runtime scripts can see the unsafe boundary.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-12 15:51:31 +09:00
YeonGyu-Kim 8b093a1115 test(shared): remove unsafe test assertions
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-12 15:41:17 +09:00
YeonGyu-Kim 2d656bd6bf Merge pull request #3964 from code-yeongyu/fix/electron-bun-runtime-shims
fix(electron): eliminate raw Bun.* runtime calls so plugin loads on OpenCode Desktop
2026-05-12 13:00:49 +09:00
YeonGyu-Kim db3256baf6 test: harden dist-bundle regression guard + Node smoke test
Existing test only checked `globalThis.Bun` top-level destructures
and `__require` calls. Add two new test cases:

1. Raw Bun runtime API scanner: scans dist/index.js for any
   `Bun.<anyMethod>(` or `Bun.<anyMethod>.` call outside shim-safe
   patterns (runtime.Bun, globalThis.Bun, typeof Bun, and the
   "Bun is not defined" error-message string). Uses a negative
   lookbehind so shim indirection (`runtime.Bun.foo`) passes.

2. Node smoke test: imports dist/index.js under
   `node --input-type=module` and asserts stderr contains no
   `ReferenceError` and no `Bun is not defined`. The existing
   case 3 only checked exit code, which masked lazy-evaluation
   crashes that fire after import. Reading exports forces lazy
   module-level evaluation paths to run.
2026-05-12 12:46:50 +09:00
YeonGyu-Kim 2386cbd9b9 refactor(port-utils): drop Bun.serve in favor of node:net probe
isPortAvailable() previously bound a one-shot Bun.serve and stopped it.
That call was reachable from the plugin bundle through
src/shared/index.ts barrel re-export and crashed on Electron.

Switch to node:net.createServer().listen(port, host), which Bun fully
implements as well. Adds a 2s safety timeout and removes both
"error" and "listening" handlers on resolution to prevent listener
leaks. Behavior is bit-equivalent: returns true iff a server can bind
to (host, port) right now.

Test file is fully rewritten away from stale Bun.serve mocking. New
tests exercise: free-port detection via port 0, EADDRINUSE handling
via a real net.createServer blocker, findAvailablePort range
exhaustion, getAvailableServerPort auto-selection, 127.0.0.1 default
hostname binding, and probe-server resource cleanup.
2026-05-12 12:46:50 +09:00
YeonGyu-Kim 0aafe20a85 refactor: route raw Bun.file/write/hash/which/spawn through runtime shims
Eliminates 19 unguarded `Bun.*` runtime call sites in the plugin bundle
that crashed with `ReferenceError: Bun is not defined` under Electron.

Per-tool-call hot paths (executed on every Read/Edit):
- src/tools/hashline-edit/hash-computation.ts: Bun.hash.xxHash32 → bunHashXxh32
- src/tools/hashline-edit/hashline-edit-executor.ts: 8 sites via bunFile/bunWrite
- src/hooks/hashline-read-enhancer/hook.ts: Bun.file → bunFile
- src/hooks/hashline-edit-diff-enhancer/hook.ts: 2 sites via bunFile

Plugin-load paths:
- src/hooks/claude-code-hooks/config.ts and config-loader.ts: Bun.file → bunFile
- src/features/claude-code-mcp-loader/loader.ts: Bun.file → bunFile
- src/features/claude-code-plugin-loader/mcp-server-loader.ts: Bun.file → bunFile
- src/features/team-mode/deps.ts: Bun.spawn → spawn shim
- src/hooks/session-notification-utils.ts: Bun.which → bunWhich, also drops
  the bare `declare const Bun` ambient declaration
- src/shared/binary-downloader.ts: Bun.write → bunWrite

Pure mechanical API swaps. No control-flow or signature changes.
2026-05-12 12:46:50 +09:00
YeonGyu-Kim 4394f34225 feat(shim): add bun-file/hash/which shims with Node fallbacks
The plugin builds with `bun build --target bun` and runs under OpenCode
CLI (Bun SEA) but also under OpenCode Desktop (Electron / Node V8) where
`globalThis.Bun` does not exist. Mirror the existing `bun-spawn-shim.ts`
pattern for three more Bun runtime APIs:

- bun-file-shim: bunFile()/bunWrite() backed by node:fs/promises with
  ArrayBuffer slicing to avoid Node Buffer pool exposure
- bun-hash-shim: pure-JS XXH32, bit-exact with Bun.hash.xxHash32 verified
  by 1200-pair fuzz comparison so existing hashline LINE#ID tags remain
  stable across runtimes
- bun-which-shim: synchronous PATH walker with Windows .exe/.cmd/.bat/.com
  extensions plus isUnsafeCommandName guard that rejects path separators,
  parent traversal, drive letters and null bytes before any probe

Each shim uses the canonical `runtime.Bun !== undefined` detection and
delegates to native Bun under IS_BUN, otherwise uses Node primitives.
Each ships with a co-located test that exercises both branches via the
`node:vm.runInNewContext` pattern from bun-hash-shim.test.ts.
2026-05-12 12:46:50 +09:00
YeonGyu-Kim 4da48555ee fix(plugin): normalize event session ids
Handle OpenCode session events that carry the session ID under properties.info.id or properties.info.sessionID so background tasks and continuation hooks do not miss idle/error/delete events.

Add regression coverage for nested session.idle events completing background tasks and waking continuation hooks.
2026-05-12 12:32:26 +09:00
YeonGyu-Kim 0de6bd7253 fix(ralph-loop): reject promptAsync error responses 2026-05-12 12:06:49 +09:00
acamq 38c50d6a39 Merge pull request #3827 from ShishaBoyTJ/fix/tmux-subagent-single-dispatch
fix: support cmux tmux compatibility
2026-05-10 19:41:10 -06:00
acamq 0d19c31274 fix: add cmux __tmux-compat prefix to interactive_bash tool
Extract isCmuxCompatEnvironment to shared module and fix
interactive_bash to resolve cmux executables with the __tmux-compat
prefix, matching all other tmux command paths in the codebase.
2026-05-10 19:29:42 -06:00
YeonGyu-Kim 4b281f949e Merge pull request #3914 from code-yeongyu/fix/max-output-tokens
fix: prevent non-positive maxOutputTokens from leaking to SDK
2026-05-11 09:22:39 +09:00
YeonGyu-Kim f6a6bb32a1 Merge pull request #3910 from code-yeongyu/fix/config-migration-repeated-bak
fix(config): use r+ mode for fsync on Windows to prevent migration retry loop
2026-05-11 09:05:12 +09:00
YeonGyu-Kim 64f9a70712 fix(config): use r+ when fsyncing migrated temp file
Apply the Windows-safe open mode in migrateLegacyPluginEntry and add a regression test to assert the temp fd is opened with r+ before fsync.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-11 08:54:46 +09:00
acamq cb3aba96d0 Merge pull request #3927 from acamq/feat/support-dsv4-thinking
fix(model-settings): support DeepSeek reasoning effort
2026-05-10 10:25:55 -06:00
acamq 5259bdfd20 fix(model-settings): apply reasoning aliases with capabilities 2026-05-10 10:19:34 -06:00
acamq fd670a8169 fix(model-settings): enable DeepSeek reasoning effort 2026-05-10 10:12:22 -06:00
acamq cfab5caea3 fix(installer): add opencode-go fallback entries for deep and artistry categories
The deep and artistry category fallback chains had no opencode-go provider
entries, causing them to fall through to the ultimate fallback
(opencode/gpt-5-nano) which is not available to opencode-go users.

Add opencode-go entries:
- deep: deepseek-v4-pro -> kimi-k2.6 -> glm-5.1
- artistry: kimi-k2.6 -> glm-5.1

Fixes #3924
2026-05-10 10:11:59 -06:00
acamq c5e89f1eea fix(model-settings): support family reasoning aliases 2026-05-10 10:11:55 -06:00
YeonGyu-Kim 98da8b675b fix(installer): apply extractSemverFromOutput to opencode-binary version probe
The same output.trim() bug fixed in PR #3909 for doctor exists in the
installer's opencode-binary.ts. Without this fix, `bunx oh-my-opencode
install` would store polluted Electron stdout (e.g., `00:24:25.202 >
app starting { version: '1.14.33', packaged: true }`) as the OpenCode
version in config, breaking downstream version-dependent logic.

- Extract extractSemverFromOutput to src/shared/extract-semver.ts
  (precedent: spawn-with-windows-hide is in shared because used by
  both doctor and installer)
- src/cli/doctor/checks/system-binary.ts now imports from shared and
  re-exports for backward compat
- src/cli/config-manager/opencode-binary.ts uses the shared helper
  with `?? output.trim()` fallback to preserve legacy behavior on
  non-semver-shaped successful outputs (e.g., custom builds)
- Add 4 installer regression tests covering: clean semver, polluted
  Electron stdout (regression for #3765 installer caller), fallback
  for non-semver, null when no binary on PATH

Refs #3765
2026-05-10 15:32:36 +09:00
YeonGyu-Kim 279f0d150f fix(chat-params): guard non-positive max output tokens 2026-05-10 15:03:01 +09:00
YeonGyu-Kim f45452ae6c fix(config): use r+ mode for fsync on Windows to prevent migration retry loop
openSync with read-only mode fails fsync on Windows because FlushFileBuffers requires write-permission FD. This caused atomic writes to fail silently, leaving migrated config unwritten and triggering repeated migration + .bak.<timestamp> generation on every startup.

Same root cause as PR #3644 (#3643). Hyperplan disappear is a secondary symptom of plugin load instability.

Fixes #3877
2026-05-10 14:53:28 +09:00
YeonGyu-Kim b36389ef2c fix(team-mode): keep member communication tools visible 2026-05-10 12:54:16 +09:00
YeonGyu-Kim be2acd49b5 fix(delegate-task): hide team tools from subagents 2026-05-09 16:30:40 +09:00
YeonGyu-Kim 8eadf2056f perf(shared): avoid spawning opencode for version checks 2026-05-08 16:58:50 +09:00
YeonGyu-Kim 3a738e7047 Merge remote-tracking branch 'origin/dev' into feature/configurable-agent-ordering 2026-05-08 16:08:26 +09:00
YeonGyu-Kim 9522dd4ca4 feat(config): add configurable agent ordering 2026-05-08 16:08:18 +09:00
YeonGyu-Kim 43b0529557 feat(hooks): surface fsync-skip warnings to AI agent via tool output
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-08 15:08:34 +09:00
YeonGyu-Kim 6b69505940 feat(shared): wire tolerantFsync to record skips with path classification
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-08 15:08:19 +09:00
YeonGyu-Kim 20ae3f8ba5 feat(shared): add fsync-skip tracker and path-environment classifier
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-08 15:08:05 +09:00
YeonGyu-Kim 7735b2abd5 fix(shared): tolerate EPERM during fsync in writeFileAtomically
Replaces fsyncSync(tempFileDescriptor) with tolerantFsyncSync, allowing
EPERM/EACCES/ENOTSUP/EINVAL during fsync while still propagating real
errors. Adds an optional deps.fsyncSync injection point used solely by
the new EPERM tolerance regression tests.

Without this fix, plugin startup itself can fail on synced folders
because writeFileAtomically is used by config migrations and posthog
activity state — the same EPERM-on-fsync failure pattern reported for
team_create.
2026-05-08 14:09:17 +09:00
YeonGyu-Kim 9d83255426 feat(shared): add tolerant-fsync utility for synced-folder filesystems
Adds isToleratedFsyncError, tolerantFsync (async, FileHandle), and
tolerantFsyncSync (sync, fd) helpers that swallow filesystem-limitation
errors during fsync (EPERM, EACCES, ENOTSUP, EINVAL) while still
propagating real errors (EIO, ENOSPC, EBADF, etc.). Synced folders
like iCloud Drive, OneDrive, and antivirus-locked files reject fsync
with EPERM even though the underlying write+rename succeeded; for the
runtime data this codebase persists, losing the durability hint is
acceptable in exchange for not blocking the operation entirely.

The helper is intentionally not barrel-exported (consumers import the
file directly), matching the existing convention for write-file-atomically.
2026-05-08 14:09:16 +09:00
YeonGyu-Kim 2dfa6336f5 fix(metis): switch primary model to claude-sonnet-4-6 + correct AGENTS.md inaccuracies
Source code change:
- src/shared/model-requirements.ts: prepend claude-sonnet-4-6 to metis fallback
  chain so Sonnet becomes the default. Opus 4.7 max remains as the immediate
  fallback for callers who want extra reasoning.
- src/shared/model-requirements.test.ts: update assertion to expect Sonnet
  primary + Opus secondary.

AGENTS.md accuracy fixes (verified against source):
- Agent modes: Sisyphus/Hephaestus are 'primary' (not 'all'); Sisyphus-Junior
  is 'subagent' (not 'all'). Confirmed via 'const MODE: AgentMode = ...' in
  each agent file. Also clarified Prometheus has no agentSources factory and
  is built via buildPrometheusAgentConfig.
- Sisyphus fallback chain: corrected order to kimi-k2.6 → k2p5 → kimi-k2.5
  → gpt-5.5 medium → glm-5 → big-pickle (was missing kimi-k2.5).
- Librarian/Explore: added missing minimax-m2.7 step between -highspeed and
  claude-haiku-4-5.
- Metis chain: removed fictitious gemini-3.1-pro entry.
- Sisyphus-Junior chain: spelled out the actual fallback (was 'user-configurable').
- Temperatures: Sisyphus/Hephaestus do not set explicit temperature (model
  default); Sisyphus-Junior is 0.1 via SISYPHUS_JUNIOR_DEFAULTS.
- Quick category default: gpt-5.4-mini (not gpt-5.4-mini-fast).

Team-mode corrections:
- Eligibility registry has 3 verdicts: eligible (sisyphus, atlas, sisyphus-junior),
  conditional (hephaestus — needs D-36 teammate permission), hard-reject
  (oracle, librarian, explore, multimodal-looker, metis, momus, prometheus).
- Schema has 11 fields, not 4: added max_messages_per_run, max_wall_clock_minutes,
  max_member_turns, base_dir, message_payload_max_bytes, recipient_unread_max_bytes,
  mailbox_poll_interval_ms.
- Hooks: 'team-session-events' is 4 sub-handlers in src/plugin/event.ts
  (team-idle-wake-hint, team-lead-orphan-handler, team-member-error-handler,
  team-member-status-handler), not a single Continuation-tier hook.
- Tier counts now show base + team-mode: ToolGuard 14/15, Transform 5/7.
- Total: 52 base hooks, 59 with team-mode.

Doc cascade for the Metis change:
- docs/guide/orchestration.md, agent-model-matching.md, installation.md
- docs/reference/configuration.md, features.md
2026-05-08 13:06:34 +09:00
YeonGyu-Kim 838b5ae216 docs(agents): refresh hierarchical AGENTS.md with team-mode coverage
Update root + 43 directory-level AGENTS.md files to reflect current state:
- Root AGENTS.md rewritten with accurate counts (1967 TS files, 1304 source +
  663 test, 278k LOC, 120 barrel index.ts), 7-step init flow, 5-tier hook
  composition, and full Team Mode section (12 team_* tools, eligibility,
  storage layout, config gate)
- src/AGENTS.md adds team-mode init step, current per-subdir file/LOC table
- src/tools/AGENTS.md documents conditional gates (team-mode +12, task
  system +4, hashline +1, interactive_bash +1, look_at +1) with always-on
  baseline of 20
- src/hooks/AGENTS.md splits into 5 tiers + 4 conditional team-mode hooks
- src/features/team-mode/AGENTS.md surfaces 12 tools, eligible agents,
  spawn-race-safe invariants, and integration points
- src/features/builtin-skills/AGENTS.md tracks 10 skills incl. team-mode
- src/agents/AGENTS.md, src/plugin/AGENTS.md, src/config/AGENTS.md updated
  for team-mode awareness, accurate counts, and current schema field list
- All other AGENTS.md files refreshed to 2026-05-08 generation date
2026-05-08 12:08:42 +09:00
ShishaBoyTJ 8236d7d6b8 fix: support cmux tmux compatibility 2026-05-07 19:25:50 +09:00
YeonGyu-Kim 6b49e3bddc test agent runtime sort behavior 2026-05-07 18:52:44 +09:00
YeonGyu-Kim ee938aa097 fix full-suite isolation regressions 2026-05-07 18:36:03 +09:00
YeonGyu-Kim 8586cb8965 fix(posthog): disable feature flags, remove plugin_loaded event for billing optimization
- Remove plugin_loaded telemetry from index.ts (was 46.5% of all events, ~2.83M/month)
- Add enableLocalEvaluation: false to prevent feature flag polling/decide calls
- Add strictLocalEvaluation: true to prevent server fallback requests
- Add disableRemoteConfig: true to prevent remote config network requests
- Remove 'plugin_loaded' from PostHogActivityReason type
- Update tests: remove stale mocks, add SDK options verification test
- enableExceptionAutocapture: false already present (kept)

Estimated billing reduction: ~$960+/month from feature flag requests,
plus ~2.83M fewer events/month from plugin_loaded removal.
2026-05-07 16:44:05 +09:00
YeonGyu-Kim 7bd863b214 Merge pull request #3813 from code-yeongyu/fix/agent-name-backslash-sanitize
fix(agent): sanitize backslash/quote from agent name
2026-05-06 18:14:39 +09:00
YeonGyu-Kim 25d183fbe8 fix(agent): sanitize backslash/quote from agent name in launch() and background-executor
Agent names like \hephaestus\ cause 'Agent not found' errors because
sanitizeSubagentType() was only called in subagent-resolver.ts but not
in the direct manager.launch() path or background-executor.ts.

- manager.ts: strip leading/trailing backslash/quote chars from input.agent
  before validation so \hephaestus\ → hephaestus
- background-executor.ts: call sanitizeSubagentType(args.subagent_type)
  instead of passing raw value to manager.launch()
- agent-display-names.ts: reuse sanitizeSubagentType in stripAgentListSortPrefix
- Add unit tests for all three fix points

Fixes: sessions dying with 'Agent not found: \hephaestus\'
2026-05-06 17:41:41 +09:00
YeonGyu-Kim 37d981ef1f Merge pull request #3634 from auyua9/fix/ast-grep-pattern-hints
fix(ast-grep): restore pattern hints in tools
2026-05-06 17:15:17 +09:00
YeonGyu-Kim 0a7306c6c1 Merge pull request #3637 from ihoooohi/fix/claude-thinking-legacy-alias-collision
fix(aliases): stop rewriting canonical claude-opus-4-6-thinking
2026-05-06 17:15:09 +09:00
YeonGyu-Kim 9b87fd5019 Merge pull request #3744 from Arcadi4/dev
Allow "max" option for "reasoningEffort" field in config schema
2026-05-06 17:14:57 +09:00
Samuele Domenico Ruffino 467a4a5eed fix(test): use toContain instead of providers[0].toBe for multi-provider entries
Restore consistent assertion style in librarian and explore tests.
Multi-provider entries like ["opencode-go", "vercel"] should use
toContain() not providers[0].toBe() to match the established pattern.
2026-05-06 16:51:59 +09:00
Samuele Domenico Ruffino b7d77da88f fix(capabilities): add kimi-k2.6 to supplemental model entries
kimi-k2.6 is referenced in fallback chains but missing from the bundled snapshot (which only has kimi-k2.5). Added supplemental entry with specs matching models.dev data.
2026-05-06 16:51:59 +09:00
Samuele Domenico Ruffino 6cd40df4cb feat(opencode-go): upgrade glm-5 → glm-5.1 and kimi-k2.5 → kimi-k2.6 in fallback chains 2026-05-06 16:45:30 +09:00