- Add isGpt5_2Model type guard\n- ORACLE_GPT_5_2_PROMPT consolidating all knowledge from Claude default, GPT-5.4 generic, and GPT-5.5 variants (XML-tagged blocks, concrete verbosity clamps, long-context re-grounding, anti-narration tool rules, high-risk self-check)\n- MOMUS_GPT_5_2_PROMPT preserving blocker-finder philosophy with new tool_usage_rules block for parallel reference verification\n- Momus GPT-5.2 reasoningEffort set to xhigh per evaluation rigor needs
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
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\'
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.
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.
Stop the walk at the start directory when it sits outside $HOME so the
walker never falls through to filesystem root. Without this guard a
project at /tmp/x or /opt/projects/foo would surface unrelated configs
in /tmp, /opt, or / itself.
Also clean up reviewer-flagged friction:
- Rename ancestor path/override variables to *NearestFirst /
*FarthestFirst so the merge order is self-documenting and the
mid-flight `.slice().reverse()` is no longer surprising.
- Rename `migrateLegacyAndResolveCanonicalPath` to
`resolveConfigPathAfterLegacyMigration` to reflect that the helper
returns the path to load, which may still be the legacy path when
migration could not run.
- Replace `Object.assign({}, ...overrides)` with a named accumulator
loop so the closer-wins ordering is obvious from the code instead of
relying on a comment.
Tests added:
- start directory outside $HOME does not walk above itself
- multi-ancestor git_master merge order (closer wins, distant fields
still flow through)
- agent_definitions in an ancestor resolves against that ancestor's own
.opencode/ base path, not the start directory's
Closes#417.
The user config (`~/.config/opencode/oh-my-openagent.json[c]`) is no
longer the only level above the project. `loadPluginConfig` now walks
from the working directory up to `$HOME` (inclusive), collecting every
`.opencode/oh-my-openagent.json[c]` it finds along the way. Configs
closer to the working directory override configs farther up, allowing
per-tree setups like:
~/work/.opencode/oh-my-openagent.json # work credentials
~/dev/.opencode/oh-my-openagent.json # personal credentials
~/.config/opencode/oh-my-openagent.json # global fallback
This subsumes the previous single project-config load: the project's
own config is just the closest hit of the walk. `agent_definitions`
relative paths resolve against each ancestor's own `.opencode/` base,
`git_master` overrides accumulate across the walk (closer wins), and
legacy basenames are migrated wherever they appear.
`mcp_env_allowlist` is intentionally NOT extensible from walked
ancestors. It remains user-only as a security boundary so a malicious
or untrusted parent directory cannot extend the env var allowlist used
during ${VAR} expansion in `.mcp.json` files. The existing test that
pins this behaviour is extended to cover the multi-ancestor case.
`os.homedir()` caches in Bun, so the stop directory is resolved by
reading `process.env.HOME` directly. Production behaviour is unchanged
because the OS sets HOME at startup; tests can now redirect the walk
boundary by setting HOME to a temp directory before each call.
Walks up the directory tree from a start directory looking for
.opencode/oh-my-openagent.json[c] (or legacy basename) files. Returns
detected paths in nearest-first order, optionally stopping at a
caller-provided directory.
Reuses detectPluginConfigFile so canonical/legacy basename detection,
caching, and JSONC vs JSON precedence stay consistent with existing
config loading. Foundation for #417 hierarchical config discovery.
Replace in-window pane splitting with two purpose-built windows
(focus: main-vertical, grid: tiled) created off the target session,
so leader pane is never disturbed and layouts no longer collapse
under teammate count.
🤖 Generated with assistance of [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
Drop the per-pane select-pane title shuffle and the cyan border styling that leaked to window scope, then switch from main-vertical to tiled when there are 4 or more teammates so each pane keeps a usable height for the opencode TUI.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Bring the team member addendum and the team-mode skill in line with the
Claude Code experimental Agent Teams reference (../free-code) on the
behavioral framing the LLM needs, while keeping every omo-specific
constraint (TeamRunId param, lead-only tool blocklist, eligibility
registry, sisyphus-junior routing) intact.
Member addendum (src/features/team-mode/member-guidance.ts) — adopt
free-code teammatePromptAddendum.ts wisdom that was missing:
- "User interacts primarily with the team lead" — members no longer try
to address the user directly; they coordinate via task system + DMs.
- Stronger emphasis that plain assistant text is invisible to the team;
team_send_message is mandatory, not optional.
- Broadcast (`to: "*"`) called out explicitly with "sparingly" guidance
and the lead-only constraint.
- "Idle is normal" section: idle ≠ done, idle teammates can still
receive messages, the lead must not treat idle as an error.
- "Communication rules" section forbidding structured JSON status
messages and forbidding terminal tools as a peer-inspection backdoor;
always reference teammates by NAME, not session ID.
- Auto-delivery framing: messages arrive as new turns, no manual inbox
polling, no need to quote a teammate's message back to the lead.
Team-mode skill (src/features/builtin-skills/skills/team-mode.ts) —
adopt free-code TeamCreateTool/prompt.ts sections that were missing:
- Task ownership: any agent can set/change `owner` via team_task_update.
- Automatic message delivery: <peer_message ...> envelope flow.
- Teammate idle state: idle is the expected post-turn state; peer DM
summaries surface in the lead's idle notification.
- Discovering team members: team_status + ~/.omo/teams/ config; refer by
name, never raw session IDs.
- Task list coordination: claim by ID order (lowest first), check after
every completion, escalate blocking deadlocks to the lead.
- Communication rules: same anti-patterns as the member addendum, scoped
for the lead's awareness (no JSON status, no terminal peer-inspection,
no delegate-task from inside members).
Test (create.test.ts) updated to track the renamed section header
("Lead-only tools you must NOT call") and to lock the new free-code
parity assertions ("user interacts primarily with the team lead",
"Idle is normal", "structured JSON status messages").
All other contract tests (team-mode skill keyword/section tests,
member parser, runtime tests) untouched and still passing.
Generated with assistance of [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode).
When user types /hyperplan something, two pipelines race for the message:
1. keyword-detector hook (chat.message): the regex \b(hyperplan|hpp)\b
matches /hyperplan because \b is satisfied by the / boundary, so the
hook prepends <hyperplan-mode> to the text part.
2. auto-slash-command hook (chat.message, runs immediately after):
detectSlashCommand() checks `text.trimStart().startsWith("/")`. After
keyword-detector's prepend, the part now starts with <hyperplan-mode>
and the slash check fails, so the builtin command template
(with $ARGUMENTS substituted) is never injected.
The visible symptom: /hyperplan refactor X never runs the actual
HYPERPLAN_TEMPLATE - the user sees only the keyword-detector wrapper, which
is similar but not identical, and the slash command's $ARGUMENTS payload
is silently lost.
Fix: at the top of the keyword-detector hook, after isSystemDirective() but
before any keyword scan, bail out if the prompt text starts with a slash
command (^\s*\/[a-zA-Z][\w-]*\b). Slash commands are explicit invocations
and own their own mode-injection path; the keyword detector must not race
them. Free-form mentions like "hyperplan: refactor X" still trigger
keyword detection - only the leading-slash form is suppressed.
Lock the contract with three regression tests:
- /hyperplan refactor ... must NOT inject <hyperplan-mode>
- /hpp investigate ... must NOT inject (shorthand slash command)
- "hyperplan: refactor src/auth/handler.ts" still injects (free-form)
Generated with assistance of [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode).