Resumed Ralph sessions can leave the only active state under a foreign
session directory, so cancelling from the current session used to clear
nothing and let the owner path survive. The state_clear path now falls
back to the sole active owning session only when the current session has
no matching state, and it writes cancel signals for both sessions so stop
enforcement stays down during teardown.
Constraint: Cross-session resume can leave the only active Ralph state under a different session directory
Rejected: Broad-clear every session-scoped file for the mode | too destructive for parallel sessions
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep owner fallback constrained to the unambiguous single-owner case; do not widen it without a stronger ownership contract
Tested: npm test -- --run src/tools/__tests__/state-tools.test.ts src/hooks/persistent-mode/__tests__/cancel-race.test.ts
Tested: npm test -- --run src/tools/__tests__/cancel-integration.test.ts src/hooks/persistent-mode/session-isolation.test.ts src/lib/__tests__/mode-state-io.test.ts src/hooks/mode-registry/__tests__/session-isolation.test.ts
Tested: npx tsc --noEmit
Tested: npx eslint src/tools/state-tools.ts src/tools/__tests__/state-tools.test.ts src/hooks/persistent-mode/__tests__/cancel-race.test.ts
Related: #2743
Release includes:
- feat(team): cursor-agent as 4th tmux worker type (#2736)
- fix(keyword-detector): stop false-positive autopilot on "autonomous" (#2739)
- fix(self-improve): scope artifacts by topic for safer resumes (#2732)
Constraint: 4 version files must remain in sync (package.json, plugin.json, marketplace.json, package-lock.json)
Constraint: dist/ is gitignored but tracked; force-add required for new files
Confidence: high
Scope-risk: narrow
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The deployed scripts/keyword-detector.mjs still listed "autonomous" in the
autopilot trigger regex, even though src/hooks/keyword-detector/index.ts
and templates/hooks/keyword-detector.mjs both removed it some time ago.
Because "autonomous" is extremely common in technical/research prose
("autonomous driving", "autonomous agent", "autonomous system"), the
UserPromptSubmit hook was silently creating autopilot-state.json on
completely unrelated prompts. The Stop hook (persistent-mode.mjs) then
treated autopilot as active and forced the assistant into a
"[AUTOPILOT - Phase: unspecified] Autopilot not complete. Continue working."
block loop that the user could not easily escape — state_clear from the
cancel skill did not target the per-project state path and the Stop hook
kept refreshing it.
Reproduction (before this patch):
echo '{"hook_event_name":"UserPromptSubmit","cwd":"'"$(pwd)"'",
"session_id":"x","prompt":"DriveVLA-W0: World Models Amplify Data
Scaling Law in Autonomous Driving"}' | node scripts/keyword-detector.mjs
-> emits [MAGIC KEYWORD: AUTOPILOT] and writes
.omc/state/sessions/x/autopilot-state.json
After the patch the same prompt returns
{"continue":true,"suppressOutput":true} and no state file is created,
while an explicit "autopilot build a todo CLI" prompt still triggers
autopilot as expected.
Changes:
- scripts/keyword-detector.mjs: drop "autonomous" from the autopilot
regex; add a comment explaining why, pointing at the already-aligned
TS source and templates mjs.
- src/__tests__/keyword-detector-script.test.ts: add two regression
tests — one negative ("Autonomous Driving" paper title must not
activate autopilot state) and one positive control (explicit
"autopilot ..." still writes state and emits the magic keyword).
The runtime guidance test mocked CLI availability with a narrower union than the
production signature now accepts. Widening the test helper to CliAgentType keeps
the assertion behavior unchanged while matching the cursor-aware contract.
Constraint: Fix only the CI TypeScript failure on PR #2736
Rejected: Change production signatures back to the older union | would broaden scope beyond the test-only fix
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep test doubles typed against shared agent contracts when provider unions expand
Tested: npx tsc --noEmit
Not-tested: Vitest runtime execution
Adds cursor-agent (Cursor's Composer 2 REPL) as a first-class
\`omc team\` worker provider alongside claude/codex/gemini. Spawned
via the existing tmux-pane path (no bridge changes); cursor workers
appear as cmux/tmux split panes that the user can both observe and
type into directly.
## Changes
- \`src/team/model-contract.ts\`
- Extend \`CliAgentType\` union with \`'cursor'\`.
- Add \`cursor\` entry to \`CONTRACTS\` with binary \`cursor-agent\`,
minimal launch args (no model flag — cursor-agent owns its own
model selection inside the REPL), and \`supportsPromptMode: false\`.
- \`src/team/types.ts\`
- Extend \`WorkerBackend\` with \`'tmux-cursor'\`.
- Widen \`WorkerInfo.worker_cli\` to include \`'cursor'\`.
- \`src/team/capabilities.ts\`
- Map \`tmux-cursor\` to \`['code-edit', 'refactoring', 'general']\`
so the fitness scorer routes appropriate executor work to cursor.
- \`src/team/cli-detection.ts\`
- Detect \`cursor-agent\` in \`detectAllClis()\`.
- \`src/team/worker-bootstrap.ts\`
- Add \`case 'cursor':\` to \`agentTypeGuidance\` with REPL-aware
instructions: stay in session, claim/transition tasks via
team-api, do not auto-exit, take only executor-style work.
- \`src/team/cli-worker-contract.ts\`
- Skip verdict-file injection for cursor in \`shouldInjectContract\`,
matching the existing claude carve-out. Cursor REPL cannot perform
write-verdict-and-exit.
- \`src/cli/team.ts\`
- Add \`'cursor'\` to \`VALID_CLI_AGENT_TYPES\` and update help text.
## Why executor-only
Codex and Gemini set \`supportsPromptMode: true\` because they are
one-shot CLIs that run a single prompt and exit. The CLI-worker output
contract (CONTRACT_ROLES = critic, code-reviewer, security-reviewer,
test-engineer) depends on this exit-on-complete behavior to surface
structured verdict JSON back to the leader.
cursor-agent is an interactive REPL: it does not exit after answering a
prompt. Routing a reviewer role to a cursor worker would hang the team
because the verdict file is never written and the worker never exits.
This patch:
1. Marks \`supportsPromptMode: false\` on the cursor contract.
2. Updates \`shouldInjectContract\` to skip cursor (alongside claude).
3. Documents the constraint inline in the agentTypeGuidance.
Mailbox/inbox/sentinel/heartbeat behavior is unchanged — cursor workers
participate in the standard \`.omc/state/team/<team>/\` filesystem A2A
the same way claude workers do.
## Verification
- \`npx tsc --noEmit\` passes for all production sources.
- One residual error in \`src/__tests__/runtime-guidance-plan-ralph.test.ts\`
(line 87) requires widening a hard-coded test helper signature
\`(agentType: "claude" | "codex" | "gemini") => agentType is "claude"\`
to \`(agentType: CliAgentType) => agentType is "claude"\` — a one-line
type-only update. My local agent harness currently guards \`*.test.ts\`
edits, so I'm flagging this as a follow-up for a maintainer or
in-PR amendment rather than ship a stale-typed test.
## Usage
Once cmux PR #3031 (tmux-compat short-form expansion) lands, this
enables:
\`\`\`
omc team 1:cursor:executor "implement the X feature"
omc team 1:cursor,1:codex:critic "implement and review the Y change"
\`\`\`
Add a dedicated resolver for self-improve artifact roots, teach validation to resolve scoped settings, and document the topic-scoped layout while preserving legacy flat-root fallback. The focused regression test covers default, explicit-topic, and legacy compatibility behavior without widening into unrelated self-improve changes.
Constraint: Keep scope narrow to self-improve topic-scoped path resolution and compatibility
Rejected: Reworking broader self-improve runtime behavior | unnecessary for issue #2731
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Route future self-improve path reads through the resolver instead of hardcoding .omc/self-improve/
Tested: npm run test:run -- src/cli/__tests__/self-improve-paths.test.ts
Tested: npm run build
Tested: npm run lint -- src/cli/__tests__/self-improve-paths.test.ts
Not-tested: Full self-improve runtime end-to-end loop execution
Includes the autoresearch-as-a-skill migration (#2727) and the
company-context MCP contract scaffolding. Both ship as opt-in
experimental surfaces; minor bump reflects the new functionality
even though the features are not yet GA.
Constraint: autoresearch migration touches shared skill-state and persistent-mode plumbing — minor bump signals upgrade caution despite the experimental label
Confidence: high
Scope-risk: moderate
Copy templates/hooks/lib into ~/.claude/hooks/lib for standalone installs and update reconciliation so .mjs hooks keep resolving stdin and atomic-write helpers after omc update.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Regenerate CLI and runtime bundles plus compiled TypeScript artifacts so
dist/ matches the skill-first autoresearch sources introduced in the two
preceding commits. Also captures incidental rebuilds for plugin-patterns
and other modules whose dist/ on dev was stale relative to its src/.
Constraint: dist/ is tracked-but-gitignored and must stay in sync with src/
Confidence: high
Scope-risk: narrow
Directive: Do not hand-edit dist/ or bridge/*.cjs; always run npm run build
Autoresearch still writes active mode state through the legacy shared path while stop hooks and exclusivity checks have moved toward session-aware enforcement. This commit adds a narrow compatibility bridge for autoresearch stop-hook checks and routes startup exclusivity through the registry's cross-session active-mode detection.
Constraint: Existing autoresearch lifecycle APIs do not yet thread session identifiers end-to-end.
Rejected: Full session-scoped autoresearch normalization now | broader runtime migration than the reviewed defects require.
Rejected: Generic readModeState session fallback | would weaken the session isolation contract for unrelated modes.
Confidence: high
Scope-risk: narrow
Directive: Keep the legacy bridge autoresearch-specific until a dedicated session-normalization migration retires shared autoresearch state.
Tested: npm test -- --run src/hooks/persistent-mode/stop-hook-blocking.test.ts src/autoresearch/__tests__/runtime.test.ts
Tested: npm run build
Tested: lsp_diagnostics_directory totalErrors=0
Not-tested: Full repository test suite
The team runtime requires a clean leader workspace before it can launch
review workers in dedicated worktrees. This checkpoint captures the
stateful autoresearch migration exactly as verified so the requested
team review can run against a stable branch tip.
Constraint: omx team refuses to launch from a dirty leader workspace
Rejected: Stash local changes temporarily | workers would review an outdated tree
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep omc autoresearch as a hard-deprecated shim; do not restore CLI runtime ownership without revisiting the skill-first contract
Tested: npm run build; targeted vitest suites; project diagnostics via lsp_diagnostics_directory
Not-tested: Full repository test suite; live cron/native scheduling integration
CI exercises both the rendered skill template and the raw shipped SKILL.md.
The previous PR update changed the contract from an injected
ambiguityThreshold sentence to a placeholder/resolved-threshold step, so the
tests need to assert that contract directly. The static skill prose also needs
the portable config-dir notation required by the skill config-dir guard.
Constraint: Keep the static native-loader threshold fix intact
Rejected: Restore the old ambiguityThreshold = ... renderer sentence | would re-couple tests to renderer-only wording
Confidence: high
Scope-risk: narrow
Reversibility: clean
Tested: npx vitest run src/__tests__/skills.test.ts -t "loads deep-interview ambiguityThreshold from settings before state init and updates the announcement copy|refreshes cached deep-interview output when the configured threshold changes without requiring manual cache clearing|replaces all hardcoded 20%/0.2 threshold references in deep-interview template \(issue #2545\)|ships a config-aware deep-interview SKILL.md for native skill-loader paths \(issue #2723\)"
Tested: npx vitest run src/__tests__/auto-slash-aliases.test.ts src/__tests__/skills.test.ts src/skills/__tests__/skill-config-dir.test.ts -t "applies deep-interview threshold runtime injection in slash/materialized output|loads deep-interview ambiguityThreshold from settings before state init and updates the announcement copy|refreshes cached deep-interview output when the configured threshold changes without requiring manual cache clearing|replaces all hardcoded 20%/0.2 threshold references in deep-interview template \(issue #2545\)|ships a config-aware deep-interview SKILL.md for native skill-loader paths \(issue #2723\)|CLAUDE_CONFIG_DIR|total baseline should not increase"
Not-tested: Full test suite
Related: #2723
Claude Code native plugin skill loading can consume the bundled SKILL.md without passing through OMC renderBundledSkillBody. That left the shipped deep-interview skill with hardcoded 20%/0.2 guidance on qualified slash and Skill() paths even though OMC-rendered paths were fixed.
This change makes the bundled deep-interview SKILL.md self-describing for threshold resolution, replacing static 20%/0.2 guidance with runtime placeholders the model must resolve from settings before state init. The existing renderer still resolves those placeholders for OMC-owned paths, so current slash and materialized behavior stays intact.
Constraint: Native Claude plugin skill loading may bypass OMC render hooks
Rejected: Fix this only in renderBundledSkillBody | does not reach raw SKILL.md consumers
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep deep-interview threshold guidance config-aware in raw SKILL.md, not only in JS render transforms
Tested: npx vitest run src/__tests__/auto-slash-aliases.test.ts src/__tests__/skills.test.ts -t "applies deep-interview threshold runtime injection in slash/materialized output|replaces all hardcoded 20%/0.2 threshold references in deep-interview template \(issue #2545\)|ships a config-aware deep-interview SKILL.md for native skill-loader paths \(issue #2723\)"
Not-tested: End-to-end Claude Code native marketplace loader invocation outside repo tests
Related: #2723
Codex review on #2722 correctly flagged that [\s\S]*? could cross call
boundaries — dropping the shell flag from runTypeCheck could still pass
if runTests or runLint kept theirs, because the lazy match would just
continue past the end of the target call until it found the flag in a
sibling options object.
Replaced [\s\S]*? with [^}]*? and anchored the match to this call's own
options-object boundaries (\{ … \}\s*\);), so each assertion fails
independently when its target call loses the flag. Keep the option
objects flat — nested braces would terminate [^}]*? prematurely.
Confidence: high
Scope-risk: narrow
Directive: If future option objects nest braces (e.g. { env: { … } }),
switch these to balanced-scan or per-call substring extraction —
[^}]*? stops at the first inner }.
Not-tested: Mutation-test that synthetically removes each shell flag
and asserts each test fails independently.
Three sibling instances of the CVE-2024-27980 EINVAL class fixed in
v4.12.1 for the HUD wrapper, all in src/hooks/plugin-patterns/index.ts:
- runTypeCheck spawnSync('npx', ['tsc', '--noEmit'], …) L280
- runTests execFileSync('npm',['test'], …) L301
- runLint execFileSync('npm',['run','lint'], …) L337
On Windows + Node 20.12+ / 18.20+ / 21.7+, spawning npm/npx (which
resolve to npm.cmd / npx.cmd) via spawnSync/execFileSync without
shell:true throws EINVAL. All three callers are exported, re-exported
through src/hooks/index.ts, and invoked unconditionally by
runPreCommitChecks() in the same file, so every Windows user hitting
the plugin pre-commit flow trips these.
Each call now opts in to shell:true only on win32 so POSIX spawn
behavior is byte-for-byte identical to before.
Added three static-content assertions to plugin-patterns.test.ts under
a new `win32 spawn hardening (#2721)` describe. Static assertions are
the only regression guard available: CI runs Ubuntu-only (see
.github/workflows/ci.yml — every runs-on is ubuntu-latest), so the
existing behavioral tests (runLint "exit 0" etc.) never exercise the
broken Windows spawn path.
Follow-up to #2715 / PR #2719 (v4.12.1). Fixes#2721.
Constraint: CI is Ubuntu-only; behavioral tests cannot detect win32
spawn regressions. Static content assertions are required as the
regression guard.
Constraint: The three regex assertions must remain tolerant of inline
option-object reformatting ([\s\S]*? + anchored to the literal args
and the shell flag) so future lint-driven reflows don't false-fail.
Rejected: Centralize via a spawnWithShellOnWindows() helper | out of
scope for a point fix; maintainer can land that separately.
Rejected: Replace execFileSync/spawnSync with exec() on Windows |
reintroduces shell-injection risk and changes error semantics.
Rejected: Gate on a Node-version check instead of platform | the
project's engines.node is >=20.0.0 and pre-20.12 is out of support
scope, so platform gating is simpler and covers every supported Node.
Confidence: high
Scope-risk: narrow
Directive: Do not remove `shell: process.platform === 'win32'` from
these call sites without either dropping Windows support or replacing
with a helper that encapsulates the same mitigation.
Not-tested: A behavioral Windows-runner test that asserts EINVAL pre-fix
and absence-of-EINVAL post-fix. Requires adding a windows-latest
matrix to .github/workflows/ci.yml, out of scope for this patch.
Add devswha to the top README as a Document Specialist directly below the ambassadors section so the contributor roster reflects current documentation ownership and links to the correct GitHub profile.\n\nConstraint: Keep this as a docs-only change limited to README.md\nRejected: Adding the entry under Ambassadors | requested role is Document Specialist\nConfidence: high\nScope-risk: narrow\nReversibility: clean\nDirective: Keep contributor role links pointed at canonical GitHub profile URLs\nTested: README.md diff inspection on dev\nNot-tested: Render preview on GitHub
Add devswha to the top README as a Document Specialist directly below the ambassadors section so the contributor roster reflects current documentation ownership and links to the correct GitHub profile.\n\nConstraint: Keep this as a docs-only change limited to README.md\nRejected: Adding the entry under Ambassadors | requested role is Document Specialist\nConfidence: high\nScope-risk: narrow\nReversibility: clean\nDirective: Keep contributor role links pointed at canonical GitHub profile URLs\nTested: README.md diff inspection on dev\nNot-tested: Render preview on GitHub
The HUD wrapper needs npm root discovery to keep global installs reachable when cache and marketplace paths are absent. Node 20.12+ rejects direct npm.cmd execFileSync calls on Windows unless shell execution is enabled, so limit shell:true to the Windows npm.cmd probe while preserving the existing non-Windows npm exec behavior.
Constraint: Node 20.12+ requires shell execution for Windows .cmd/.bat child_process calls.
Rejected: Use execSync('npm root -g') everywhere | broader behavior change for non-Windows wrapper runtime.
Confidence: high
Scope-risk: narrow
Tested: npm test -- --run src/installer/__tests__/hud-wrapper-env.test.ts src/__tests__/hud-windows.test.ts src/__tests__/hud-wrapper-template-sync.test.ts src/__tests__/hud-marketplace-resolution.test.ts
Tested: npx tsc
OMX deep-interview and ralplan flows can write approved artifacts and state
under .omx, but the post-ralplan shortcut path only recognized .omc plan
artifacts, only parsed omc launch hints, and returned early before short
follow-up prompts like "team" could reach the approved execution gate.
This narrows the fix to the state-transition detection path: planning artifact
resolution now reads both .omc and .omx plan roots, launch hints accept OMX
commands, and keyword-detector checks approved follow-ups before the no-match
fast path while recognizing OMX ralplan state files.
Constraint: Team keyword auto-detection remains disabled to avoid worker respawn loops
Rejected: Re-enable generic team keyword detection | would broaden behavior beyond the broken post-ralplan transition
Rejected: Rewrite ralplan state storage globally to .omx only | wider migration than needed for issue #2714
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep approved follow-up detection aligned with both OMC and OMX artifact/state namespaces unless runtime ownership is fully unified
Tested: npx vitest run src/planning/__tests__/artifacts.test.ts src/team/__tests__/followup-planner.test.ts src/__tests__/keyword-detector-script.test.ts
Not-tested: Full repository test suite
Related: #2714
The first #2711 fix correctly stopped native Windows shells from receiving
Unix-only exec wrapping, but the preflight path in runClaudeOutsideTmux
still keyed off process.platform alone. That caused MSYS2/Git Bash sessions
on Windows to skip the existing POSIX sleep/tcflush preflight even though
they still use login-shell wrapping.
Constraint: Keep native Windows COMSPEC handling intact
Constraint: Preserve existing POSIX/MSYS2 login-shell behavior without broad launch refactors
Rejected: Revert the Windows-specific path entirely | would reintroduce the original PowerShell failure
Rejected: Add separate MSYS2-specific launch branches everywhere | broader drift than needed
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When branching shell launch behavior, key off native-Windows-vs-POSIX shell semantics, not process.platform by itself
Tested: npm test -- --run src/cli/__tests__/tmux-utils.test.ts src/cli/__tests__/launch.test.ts src/cli/__tests__/autoresearch-guided.test.ts
Tested: npm run build:cli
Not-tested: Live tmux launch on a real MSYS2/Git Bash Windows host
Related: #2711
Related: #2713
Native Windows shells were receiving Unix login-shell syntax from
wrapWithLoginShell and related tmux launch paths, causing PowerShell/cmd
sessions to fail before Claude or autoresearch setup could start. This
change keeps the existing POSIX/MSYS2 login-shell behavior, but routes
native Windows paths through COMSPEC-compatible command building and
Windows-safe env injection.
Constraint: Preserve existing POSIX login-shell + rc-sourcing behavior
Constraint: Keep the fix narrow to wrapWithLoginShell and directly related launch/setup paths
Rejected: Disable login-shell wrapping everywhere on win32 | would regress MSYS2/Git Bash support
Rejected: Broad tmux contract rewrite | unnecessary drift beyond issue #2711
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If future tmux launch paths add inline env prefixes, use the platform-aware tmux command builders instead of raw Unix shell syntax
Tested: npm test -- --run src/cli/__tests__/tmux-utils.test.ts src/cli/__tests__/launch.test.ts src/cli/__tests__/autoresearch-guided.test.ts
Tested: npm run build:cli
Not-tested: Live tmux launch on a real Windows host
Related: #2711
The earlier root canonicalization reused validateWorkingDirectory, which is
correct for MCP tool entrypoints but too strict for direct mode-state I/O
callers used by tests and temp workspaces. Narrow the fix so mode-state-io
collapses only directories that are inside a git worktree back to that
worktree root, while leaving non-git temp directories untouched.
Constraint: Direct mode-state-io callers must continue to work in standalone temp directories outside the repo root
Rejected: Keep validateWorkingDirectory in mode-state-io | rejects legitimate temp workspaces and breaks session-state cleanup tests
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Use git-root canonicalization here only for nested worktree paths; keep stricter trusted-root enforcement at MCP/tool boundaries
Tested: npx vitest run src/lib/__tests__/mode-state-io.test.ts src/hooks/session-end/__tests__/mode-state-cleanup.test.ts src/hooks/session-end/__tests__/subdirectory-cwd.test.ts src/hooks/session-end/__tests__/team-cleanup.test.ts
Tested: npx vitest run src/hooks/persistent-mode/__tests__/ralph-verification-flow.test.ts src/hooks/persistent-mode/__tests__/rate-limit-stop.test.ts src/hooks/persistent-mode/__tests__/skill-state-stop.test.ts src/hooks/persistent-mode/__tests__/team-ralplan-stop.test.ts
Not-tested: Full repo test suite
Mode-state I/O was still resolving .omc state paths from the caller's raw
working directory, which let nested cwds create state under subdirectories
instead of the owning git worktree root. Canonicalize the root through
validateWorkingDirectory before resolving, scanning, reading, writing, or
clearing state paths, and add regression coverage for nested cwd calls.
Constraint: OMC MCP tools must keep honoring the trusted worktree-root policy used elsewhere
Rejected: Fix only state_write tool paths | would leave read/clear and direct mode-state-io callers inconsistent
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep mode-state-io path resolution aligned with validateWorkingDirectory so nested cwds cannot recreate local .omc state
Tested: npx vitest run src/lib/__tests__/mode-state-io.test.ts
Tested: npx tsc --noEmit
Not-tested: Full repo test suite
`/omc-teams` already delegates to `omc team`, whose workers share one cwd. The compatibility skill only showed the current-repo launch form, so plans stored in one repo could spawn Codex workers in that repo while target repos lived in siblings. The skill now makes the workspace-root/absolute-plan-path contract explicit and uses the existing `--cwd` support instead of adding runtime heuristics.\n\nConstraint: `omc team` runtime remains single-working-directory\nRejected: Auto-infer workspace roots in runtime | brittle path heuristics and broad behavior drift\nConfidence: high\nScope-risk: narrow\nDirective: Keep multi-repo `/omc-teams` launches anchored to a shared workspace root unless the runtime grows explicit multi-workspace support\nTested: npm run test:run -- src/__tests__/skills.test.ts\nTested: npm run build:cli\nNot-tested: live tmux Codex launch across sibling repositories
The original branch update bundled unrelated generated dist churn alongside the
intended workflow-slot/state-init source changes. This follow-up commit reverts
only the generated artifacts that do not correspond to the touched source areas,
so the PR diff stays aligned with the bridge, keyword-detector, persistent-mode,
mode-registry, skill-state, mode-names, and state-tools changes.
Constraint: GitHub PR #2701 must update via the real head branch instead of a local-only approval path
Constraint: Keep the follow-up diff limited to generated artifacts that shrink the existing PR scope
Rejected: Force-push a rewritten replacement commit | unnecessary history rewrite for a narrow cleanup-only fix
Rejected: Keep all dist outputs from 56718e05 | preserves unrelated churn that blocks review
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Regenerate and commit dist only for source areas that remain in the final PR diff
Tested: Branch diff review vs dev after cleanup; targeted verification pending on final commit SHA
Not-tested: Full project-wide build/lint suite for this cleanup-only dist follow-up
The cache-repair path trusted raw installPath strings from installed_plugins.json, so an OMC entry containing ../ segments could still pass the existing prefix check and receive a full payload sync outside plugins/cache. This narrows the fix to canonical containment in the repair predicate and adds an issue-scoped regression test for the escape path.
Constraint: Keep the repair flow behavior unchanged for valid cache-installed OMC roots
Rejected: Broaden path hardening across unrelated installer flows in the same patch | would enlarge review scope beyond the verified repair bug
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Any future cache-root checks should compare canonical paths, not normalized raw strings
Tested: npm run build; ./node_modules/.bin/vitest run src/installer/__tests__/plugin-cache-sync.test.ts src/__tests__/auto-update.test.ts src/__tests__/installer-omc-reference.test.ts; ./node_modules/.bin/tsc --noEmit --pretty false; ./node_modules/.bin/eslint src/installer/index.ts src/installer/__tests__/plugin-cache-sync.test.ts; direct local reproduction of syncInstalledPluginPayload escape path before and after fix
Not-tested: Full repository vitest suite; src/__tests__/installer-plugin-agents.test.ts timed out in this environment during unrelated runs
The original company-context interface change landed with the right code and
skill-surface updates, but review correctly held the PR until the missing
acceptance-doc pieces were explicit. This follow-up adds the settings-schema
page entry for companyContext and records the issue's requested ~5% prompt-
directive miss-rate / residual-risk language without widening runtime scope.
Constraint: Keep the follow-up documentation-only and avoid runtime behavior changes
Constraint: Satisfy issue #2692 acceptance criteria exactly enough for merge review
Rejected: Expand the fix into broader doc cross-linking or runtime wording cleanup | unnecessary scope growth for a blocked PR follow-up
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep future company-context changes aligned with the current .claude/omc.jsonc / ~/.config/claude-omc/config.jsonc config surface unless the runtime contract changes first
Tested: npx vitest run src/config/__tests__/loader.test.ts -t "company context configuration"
Tested: git diff --check -- docs/company-context-interface.md docs/settings-schema.md
Tested: local link existence check for docs/settings-schema.md -> ./company-context-interface.md
Tested: lsp_diagnostics on both changed docs files reported 0 errors
Tested: architect verification APPROVED
Not-tested: Full repo build/test suite (intentionally skipped for docs-only narrow follow-up)