@trac3er/oh-my-god 2.0.1 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "OMG - Oh-My-God for Claude Code",
9
- "version": "2.0.1",
9
+ "version": "2.0.3",
10
10
  "homepage": "https://github.com/trac3er00/OMG",
11
11
  "repository": "https://github.com/trac3er00/OMG"
12
12
  },
@@ -14,7 +14,7 @@
14
14
  {
15
15
  "name": "omg",
16
16
  "description": "OMG plugin layer for Claude Code with native setup, orchestration, and interop.",
17
- "version": "2.0.1",
17
+ "version": "2.0.3",
18
18
  "source": "./",
19
19
  "author": {
20
20
  "name": "trac3er00"
@@ -32,5 +32,5 @@
32
32
  ]
33
33
  }
34
34
  ],
35
- "version": "2.0.1"
35
+ "version": "2.0.3"
36
36
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omg",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "description": "OMG plugin layer for Claude Code with native setup, orchestration, and interop.",
5
5
  "author": {
6
6
  "name": "trac3er00"
package/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ ## 2.0.3 - 2026-03-06
4
+
5
+ - removed OpenCode runtime, setup wiring, docs, and tests from the supported OMG host surface
6
+ - merged the remaining security and trust-review hardening work into `main` and cleaned up the finished `codex/*` branches
7
+ - published the post-merge patch release after the `v2.0.2` release target became immutable
8
+
9
+ ## 2.0.2 - 2026-03-06
10
+
11
+ - cleaned the repo for public launch by removing internal planning docs and stale private references
12
+ - added a public-readiness checker plus CI enforcement for docs, links, and community templates
13
+ - rewrote the public docs funnel around install, `/OMG:setup`, `/OMG:crazy`, proof, and contribution guidance
14
+
15
+ ## 2.0.1 - 2026-03-06
16
+
17
+ - standardized OMG public identity across docs, package metadata, plugin metadata, and CLI surfaces
18
+ - added native adoption flow through `OMG-setup.sh` and `/OMG:setup` with `OMG-only` and `coexist` modes
19
+ - added public-readiness hygiene checks and contributor-facing repo docs
20
+ - rewrote the public docs funnel around host install, `/OMG:setup`, `/OMG:crazy`, and proof-backed verification
@@ -0,0 +1,27 @@
1
+ # Code of Conduct
2
+
3
+ ## Our Standard
4
+
5
+ Treat contributors with respect. Discussions should stay technical, honest, and focused on moving the work forward.
6
+
7
+ Expected behavior:
8
+
9
+ - assume good intent
10
+ - critique ideas directly and respectfully
11
+ - provide evidence for technical claims
12
+ - avoid harassment, intimidation, or discriminatory language
13
+
14
+ Unacceptable behavior:
15
+
16
+ - personal attacks
17
+ - doxxing or privacy violations
18
+ - harassment or sustained disruption
19
+ - abusive, discriminatory, or sexualized language
20
+
21
+ ## Enforcement
22
+
23
+ Project maintainers may remove comments, reject contributions, or restrict participation when behavior makes the project unsafe or unproductive.
24
+
25
+ ## Scope
26
+
27
+ This applies to issues, pull requests, discussions, and other project communication spaces.
@@ -0,0 +1,62 @@
1
+ # Contributing to OMG
2
+
3
+ Thanks for contributing to OMG.
4
+
5
+ ## Local Setup
6
+
7
+ ```bash
8
+ python3 -m venv .venv
9
+ source .venv/bin/activate
10
+ pip install -r requirements.txt
11
+ python3 -m pytest tests -q
12
+ ```
13
+
14
+ If you are validating the public launch surface, also run:
15
+
16
+ ```bash
17
+ python3 scripts/check-omg-public-ready.py
18
+ python3 scripts/check-omg-standalone-clean.py
19
+ ./scripts/verify-standalone.sh
20
+ ```
21
+
22
+ ## Workflow
23
+
24
+ 1. Create a branch from `main`.
25
+ 2. Keep changes surgical and evidence-backed.
26
+ 3. Add or update tests before changing behavior.
27
+ 4. Run the relevant targeted tests while iterating.
28
+ 5. Run `python3 -m pytest tests -q` before opening a PR.
29
+
30
+ ## Pull Requests
31
+
32
+ PRs should explain:
33
+
34
+ - what changed
35
+ - why it changed
36
+ - how it was verified
37
+ - any follow-up risk or known limitation
38
+
39
+ Public-surface changes should also mention whether README, proof docs, install docs, and community docs stayed consistent.
40
+
41
+ ## Versioning and Releases
42
+
43
+ - OMG uses semantic version tags such as `v2.0.1`.
44
+ - `package.json`, plugin metadata, and release tags must agree before a release is cut.
45
+ - npm publishing is driven by the `publish-npm.yml` workflow on version tags.
46
+
47
+ Before cutting a release, run the checklist in [docs/release-checklist.md](docs/release-checklist.md).
48
+
49
+ ## CI Gates
50
+
51
+ The public release path is expected to pass:
52
+
53
+ - compat gate
54
+ - public-readiness hygiene check
55
+ - standalone verification
56
+ - full pytest suite
57
+
58
+ ## Scope Guidance
59
+
60
+ - Keep OMC, OMX, and Superpowers mentions limited to compatibility and adoption guidance.
61
+ - Avoid adding public commands that mirror another project's branding or command names.
62
+ - Prefer OMG-native setup and orchestration language in docs and UX.
package/OMG-setup.sh CHANGED
@@ -5,7 +5,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
5
  CLAUDE_DIR="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
6
6
  BACKUP_TS="$(date +%Y%m%d_%H%M%S)"
7
7
  BACKUP_DIR="$CLAUDE_DIR/.omg-backup-$BACKUP_TS"
8
- VERSION="2.0.1"
8
+ VERSION="2.0.2"
9
9
 
10
10
  PLUGIN_NAME="omg"
11
11
  PLUGIN_MARKETPLACE="omg"
package/README.md CHANGED
@@ -1,104 +1,89 @@
1
- # OMG 2.0.1
1
+ # OMG 2.0.3
2
2
 
3
- OMG upgrades your agent host instead of replacing it. It gives Claude Code, Codex, OpenCode, and other supported CLIs a tighter setup flow, stronger orchestration, adoption paths from older plugin stacks, and proof-backed verification.
3
+ [![Compat Gate](https://github.com/trac3er00/OMG/actions/workflows/omg-compat-gate.yml/badge.svg)](https://github.com/trac3er00/OMG/actions/workflows/omg-compat-gate.yml)
4
+ [![npm version](https://img.shields.io/npm/v/%40trac3er%2Foh-my-god)](https://www.npmjs.com/package/@trac3er/oh-my-god)
5
+ [![License](https://img.shields.io/github/license/trac3er00/OMG)](LICENSE)
6
+
7
+ OMG upgrades your agent host instead of replacing it. It gives Claude Code, Codex, and other supported CLIs a tighter setup flow, stronger orchestration, native adoption from older plugin stacks, and proof-backed verification.
4
8
 
5
9
  - Brand: `OMG`
6
10
  - Repo: `https://github.com/trac3er00/OMG`
7
11
  - npm: `@trac3er/oh-my-god`
8
12
  - Plugin id: `omg`
9
13
  - Marketplace id: `omg`
10
- - Version: `2.0.1`
11
-
12
- ## The Front Door
13
-
14
- OMG keeps the public journey small:
15
-
16
- 1. Install for your host.
17
- 2. Run `/OMG:setup`.
18
- 3. Run `/OMG:crazy <goal>`.
14
+ - Version: `2.0.3`
19
15
 
20
- Everything else is still available, but `setup` and `crazy` are the native OMG entrypoints.
16
+ ## Why OMG
21
17
 
22
- ## What OMG Does
18
+ - Small front door: install, run `/OMG:setup`, then `/OMG:crazy <goal>`.
19
+ - Multi-host support: Claude Code, Codex, Gemini CLI, and Kimi CLI.
20
+ - Native adoption: setup detects OMC, OMX, and Superpowers-style environments without exposing copycat public migration commands.
21
+ - Proof-first delivery: verification, provider coverage, HUD artifacts, and transcripts are published instead of implied.
23
22
 
24
- - Upgrades Claude Code, Codex, and OpenCode with a shared orchestration layer.
25
- - Detects overlapping ecosystems and offers native OMG adoption instead of public migration commands.
26
- - Supports two adoption modes:
27
- - `OMG-only`: recommended. OMG becomes the primary hooks, HUD, MCP, and orchestration layer.
28
- - `coexist`: advanced. OMG preserves other ecosystems where possible and avoids destructive overlap.
29
- - Presets reduce feature-flag sprawl:
30
- - `safe`
31
- - `balanced`
32
- - `interop`
33
- - `labs`
34
- - Keeps `compat` available for legacy skill routing without making it the main onboarding story.
23
+ ![OMG HUD](docs/assets/omg-hud.svg)
35
24
 
36
- ## Supported Hosts
25
+ ## Quickstart
37
26
 
38
- - Claude Code
39
- - Codex
40
- - OpenCode
41
- - Gemini CLI
42
- - Kimi CLI
43
-
44
- Claude Code, Codex, and OpenCode are the primary top-level install journeys in this release.
45
-
46
- ## Install
47
-
48
- ### npm
27
+ Install with npm:
49
28
 
50
29
  ```bash
51
30
  npm install @trac3er/oh-my-god
52
31
  ```
53
32
 
54
- ### git
33
+ Or clone and run the setup manager:
55
34
 
56
35
  ```bash
57
36
  git clone https://github.com/trac3er00/OMG
58
37
  cd OMG
59
38
  chmod +x OMG-setup.sh
60
- ./OMG-setup.sh install
39
+ ./OMG-setup.sh install --mode=omg-only --preset=balanced
40
+ ```
41
+
42
+ Then run:
43
+
44
+ ```text
45
+ /OMG:setup
46
+ /OMG:crazy stabilize auth and dashboard flows
61
47
  ```
62
48
 
63
- ### Host Guides
49
+ Success looks like:
64
50
 
65
- - Claude Code: [docs/install/claude-code.md](/Users/cminseo/Documents/scripts/Shell/OMG/docs/install/claude-code.md)
66
- - Codex: [docs/install/codex.md](/Users/cminseo/Documents/scripts/Shell/OMG/docs/install/codex.md)
67
- - OpenCode: [docs/install/opencode.md](/Users/cminseo/Documents/scripts/Shell/OMG/docs/install/opencode.md)
51
+ - supported hosts are detected
52
+ - `.mcp.json` is configured
53
+ - `.omg/state/adoption-report.json` is written when another ecosystem is present
54
+ - OMG reports the selected preset and next step
68
55
 
56
+ ## Install Guides
57
+
58
+ - Claude Code: [docs/install/claude-code.md](docs/install/claude-code.md)
59
+ - Codex: [docs/install/codex.md](docs/install/codex.md)
69
60
  ## Native Adoption
70
61
 
71
- OMG can adopt setups coming from OMC, OMX, and Superpowers-style environments through `/OMG:setup` and `OMG-setup.sh`.
62
+ OMG uses native setup language instead of public migration commands.
72
63
 
73
- - It detects overlapping ecosystems internally.
74
- - It writes an adoption report to `.omg/state/adoption-report.json`.
75
- - It recommends `OMG-only` and keeps `coexist` available when you want a non-destructive landing.
64
+ - `OMG-only`: recommended. OMG becomes the primary hooks, HUD, MCP, and orchestration layer.
65
+ - `coexist`: advanced. OMG preserves non-conflicting third-party surfaces and records overlap instead of overwriting it.
66
+ - Presets: `safe`, `balanced`, `interop`, `labs`.
76
67
 
77
- Details: [docs/migration/native-adoption.md](/Users/cminseo/Documents/scripts/Shell/OMG/docs/migration/native-adoption.md)
68
+ Compatibility references to OMC, OMX, and Superpowers are documented here: [docs/migration/native-adoption.md](docs/migration/native-adoption.md)
78
69
 
79
70
  ## Proof
80
71
 
81
- Trust is a product surface. OMG publishes proof for:
82
-
83
- - current verification results
84
- - verification status
85
- - provider coverage
86
- - adoption evidence
87
- - HUD artifact
88
- - sample transcripts
72
+ Current local verification for this release: `2425 passed, 2 skipped` on March 6, 2026.
89
73
 
90
- Current local verification for this release: `2444 passed, 2 skipped` on March 6, 2026.
74
+ - Verification and provider matrix: [docs/proof.md](docs/proof.md)
75
+ - Sample setup transcript: [docs/transcripts/setup.md](docs/transcripts/setup.md)
76
+ - Sample crazy transcript: [docs/transcripts/crazy.md](docs/transcripts/crazy.md)
77
+ - Release process: [docs/release-checklist.md](docs/release-checklist.md)
91
78
 
92
- See [docs/proof.md](/Users/cminseo/Documents/scripts/Shell/OMG/docs/proof.md).
79
+ ## Command Surface
93
80
 
94
- ## Commands
95
-
96
- Primary:
81
+ Primary entry points:
97
82
 
98
83
  - `/OMG:setup`
99
84
  - `/OMG:crazy`
100
85
 
101
- Advanced:
86
+ Advanced surfaces stay available for deeper workflows:
102
87
 
103
88
  - `/OMG:teams`
104
89
  - `/OMG:ccg`
@@ -106,6 +91,14 @@ Advanced:
106
91
  - `/OMG:ship`
107
92
  - `/OMG:security-review`
108
93
 
94
+ ## Contributing
95
+
96
+ Public contributions are welcome.
97
+
98
+ - Contribution guide: [CONTRIBUTING.md](CONTRIBUTING.md)
99
+ - Security reporting: [SECURITY.md](SECURITY.md)
100
+ - Changelog: [CHANGELOG.md](CHANGELOG.md)
101
+
109
102
  ## Positioning
110
103
 
111
104
  OMG is a plugin and orchestration layer for supported CLIs. It is not a base-model training project. The goal is to make frontier agent hosts tighter, safer, more interoperable, and more verifiable than the default experience.
package/SECURITY.md ADDED
@@ -0,0 +1,25 @@
1
+ # Security Policy
2
+
3
+ ## Reporting a Vulnerability
4
+
5
+ Please use GitHub's private vulnerability reporting for this repository if it is enabled.
6
+
7
+ If private reporting is not available, do not open a public issue with exploit details. Open a minimal issue asking for a private contact path through the maintainer's GitHub profile instead.
8
+
9
+ Include:
10
+
11
+ - affected version
12
+ - impact
13
+ - reproduction steps
14
+ - proof of concept if safe to share privately
15
+ - suggested mitigation if known
16
+
17
+ ## Response Expectations
18
+
19
+ - We will triage reports before public discussion.
20
+ - We may ask for additional reproduction details.
21
+ - Coordinated disclosure is preferred over immediate public disclosure.
22
+
23
+ ## Supported Versions
24
+
25
+ Security fixes are prioritized for the latest released version.
@@ -10,7 +10,7 @@ Feature-gated: requires `OMG_SETUP_ENABLED=1` or `settings.json._omg.features.SE
10
10
 
11
11
  ## Overview
12
12
 
13
- Native OMG setup for Claude Code, Codex, OpenCode, and other supported CLIs.
13
+ Native OMG setup for Claude Code, Codex, and other supported CLIs.
14
14
  The command keeps migration logic internal and focuses the user on a small adoption flow:
15
15
 
16
16
  1. Detect supported CLIs.
@@ -25,7 +25,6 @@ The command keeps migration logic internal and focuses the user on a small adopt
25
25
  Step 1: Detect CLIs
26
26
  - codex
27
27
  - gemini
28
- - opencode
29
28
  - kimi
30
29
 
31
30
  Step 2: Detect adoption context
@@ -69,3 +68,11 @@ The command emits a final summary that includes:
69
68
  - selected preset
70
69
  - selected adoption mode
71
70
  - adoption report path
71
+
72
+ ## Public Path
73
+
74
+ The public OMG journey is:
75
+
76
+ 1. install for your host
77
+ 2. run `/OMG:setup`
78
+ 3. run `/OMG:crazy <goal>`
@@ -8,7 +8,7 @@ at .omg/state/credentials.meta.
8
8
  CLI: python hooks/credential_store.py {add,list,remove,rotate} [options]
9
9
 
10
10
  Feature flag: OMG_MULTI_CREDENTIAL_ENABLED (default off)
11
- Design ref: .sisyphus/credential-store-design.md
11
+ Design note: encrypted credentials live in OMG-managed state under .omg/state
12
12
  """
13
13
  from __future__ import annotations
14
14
 
@@ -2,7 +2,7 @@
2
2
  """
3
3
  UserPromptSubmit Hook — OMG v1
4
4
 
5
- Inspired by oh-my-opencode's Sisyphus agent system. Key upgrades:
5
+ Inspired by earlier OMG routing experiments. Key upgrades:
6
6
  1. Intent classification BEFORE acting (IntentGate)
7
7
  2. Discipline enforcement — never stop halfway
8
8
  3. Agent-aware routing — Codex/Gemini/Claude orchestration
@@ -24,14 +24,12 @@ from runtime.mcp_config_writers import ( # noqa: E402
24
24
  write_claude_mcp_config,
25
25
  write_codex_mcp_config,
26
26
  write_gemini_mcp_config,
27
- write_opencode_mcp_config,
28
27
  write_kimi_mcp_config,
29
28
  )
30
29
 
31
30
  # Trigger provider auto-registration on import
32
31
  import runtime.providers.codex_provider # noqa: E402, F401
33
32
  import runtime.providers.gemini_provider # noqa: E402, F401
34
- import runtime.providers.opencode_provider # noqa: E402, F401
35
33
  import runtime.providers.kimi_provider # noqa: E402, F401
36
34
  from runtime.adoption import ( # noqa: E402
37
35
  CANONICAL_VERSION,
@@ -46,7 +44,6 @@ _logger = logging.getLogger(__name__)
46
44
  _INSTALL_HINTS: dict[str, str] = {
47
45
  "codex": "npm install -g @openai/codex",
48
46
  "gemini": "npm install -g @google/gemini-cli",
49
- "opencode": "npm install -g opencode-ai (or: curl -fsSL https://opencode.ai/install | bash)",
50
47
  "kimi": "uv tool install --python 3.13 kimi-cli",
51
48
  }
52
49
 
@@ -325,7 +322,7 @@ def get_cli_auth_instructions(provider: str) -> dict[str, str]:
325
322
  or store credentials.
326
323
 
327
324
  Args:
328
- provider: CLI provider name (e.g. "codex", "gemini", "kimi", "opencode").
325
+ provider: CLI provider name (e.g. "codex", "gemini", or "kimi").
329
326
 
330
327
  Returns:
331
328
  Dict with keys: install, auth, verify, subscription.
@@ -350,12 +347,6 @@ def get_cli_auth_instructions(provider: str) -> dict[str, str]:
350
347
  "verify": "kimi --version",
351
348
  "subscription": "Requires Kimi API key from platform.moonshot.cn",
352
349
  },
353
- "opencode": {
354
- "install": "npm install -g opencode-ai",
355
- "auth": "opencode auth login",
356
- "verify": "opencode --version",
357
- "subscription": "Requires Anthropic API key or Claude subscription",
358
- },
359
350
  }
360
351
 
361
352
  return instructions.get(provider, {
@@ -412,7 +403,6 @@ def configure_mcp(
412
403
  cli_writers = {
413
404
  "codex": write_codex_mcp_config,
414
405
  "gemini": write_gemini_mcp_config,
415
- "opencode": write_opencode_mcp_config,
416
406
  "kimi": write_kimi_mcp_config,
417
407
  }
418
408
 
@@ -460,7 +450,6 @@ def set_preferences(project_dir: str, preferences: dict[str, Any]) -> dict[str,
460
450
  default_cli_configs: dict[str, Any] = {
461
451
  "codex": {"subscription": "free", "max_parallel_agents": 1},
462
452
  "gemini": {"subscription": "free", "max_parallel_agents": 1},
463
- "opencode": {"subscription": "free", "max_parallel_agents": 1},
464
453
  "kimi": {"subscription": "free", "max_parallel_agents": 1},
465
454
  }
466
455
  preset = resolve_preset(cast(str | None, preferences.get("preset")))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trac3er/oh-my-god",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "description": "OMG (Oh My God) — Multi-agent orchestration, intelligent model routing, and durable session state for Claude Code",
5
5
  "main": "OMG-setup.sh",
6
6
  "scripts": {
package/plugins/README.md CHANGED
@@ -47,3 +47,8 @@ plugins/
47
47
  ## Adoption Notes
48
48
 
49
49
  Public migration commands are intentionally avoided. OMG uses `/OMG:setup` and `OMG-setup.sh` to detect and adopt older ecosystems internally, while `compat` remains focused on legacy skill routing.
50
+
51
+ ## Public Docs
52
+
53
+ - Install guides live in [docs/install/claude-code.md](../docs/install/claude-code.md) and [docs/install/codex.md](../docs/install/codex.md).
54
+ - Proof surface lives in [docs/proof.md](../docs/proof.md).
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omg-core",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "description": "Core OMG commands - native setup, routing, orchestration, and verification surfaces",
5
5
  "type": "omg-plugin",
6
6
  "commands": {
@@ -11,7 +11,7 @@ CANONICAL_REPO_URL = "https://github.com/trac3er00/OMG"
11
11
  CANONICAL_PACKAGE_NAME = "@trac3er/oh-my-god"
12
12
  CANONICAL_PLUGIN_ID = "omg"
13
13
  CANONICAL_MARKETPLACE_ID = "omg"
14
- CANONICAL_VERSION = "2.0.1"
14
+ CANONICAL_VERSION = "2.0.3"
15
15
 
16
16
  VALID_ADOPTION_MODES = ("omg-only", "coexist")
17
17
  VALID_PRESETS = ("safe", "balanced", "interop", "labs")
@@ -93,17 +93,6 @@ def write_gemini_mcp_config(server_url: str, server_name: str = "memory-server")
93
93
  _write_json(config_path, config)
94
94
 
95
95
 
96
- def write_opencode_mcp_config(server_url: str, server_name: str = "memory-server") -> None:
97
- config_path = Path.home() / ".config" / "opencode" / "opencode.json"
98
- config = _load_json(config_path)
99
- mcp = config.get("mcp")
100
- if not isinstance(mcp, dict):
101
- mcp = {}
102
- config["mcp"] = mcp
103
- mcp[server_name] = {"type": "remote", "url": server_url}
104
- _write_json(config_path, config)
105
-
106
-
107
96
  def write_kimi_mcp_config(server_url: str, server_name: str = "memory-server") -> None:
108
97
  config_path = Path.home() / ".kimi" / "mcp.json"
109
98
  config = _load_json(config_path)
@@ -26,7 +26,6 @@ _logger = logging.getLogger(__name__)
26
26
  try:
27
27
  import runtime.providers.codex_provider # noqa: F401 # pyright: ignore[reportUnusedImport]
28
28
  import runtime.providers.gemini_provider # noqa: F401 # pyright: ignore[reportUnusedImport]
29
- import runtime.providers.opencode_provider # noqa: F401 # pyright: ignore[reportUnusedImport]
30
29
  import runtime.providers.kimi_provider # noqa: F401 # pyright: ignore[reportUnusedImport]
31
30
  except ImportError:
32
31
  pass
@@ -550,7 +549,6 @@ def dispatch_to_model(agent_name: str, user_prompt: str, project_dir: str) -> di
550
549
  provider_name_map = {
551
550
  "codex-cli": "codex",
552
551
  "gemini-cli": "gemini",
553
- "opencode-cli": "opencode",
554
552
  "kimi-cli": "kimi",
555
553
  }
556
554
  provider_name = provider_name_map.get(preferred)
@@ -0,0 +1,193 @@
1
+ #!/usr/bin/env python3
2
+ """Check that the repo is safe and polished enough for a public launch."""
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import json
7
+ from pathlib import Path
8
+ import re
9
+
10
+ ROOT = Path(__file__).resolve().parents[1]
11
+
12
+ REQUIRED_PUBLIC_DOCS = [
13
+ "README.md",
14
+ "CONTRIBUTING.md",
15
+ "SECURITY.md",
16
+ "CODE_OF_CONDUCT.md",
17
+ "CHANGELOG.md",
18
+ ]
19
+
20
+ REQUIRED_COMMUNITY_TEMPLATES = [
21
+ ".github/ISSUE_TEMPLATE/bug_report.yml",
22
+ ".github/ISSUE_TEMPLATE/feature_request.yml",
23
+ ".github/pull_request_template.md",
24
+ ]
25
+
26
+ PUBLIC_DOC_GLOBS = [
27
+ "README.md",
28
+ "CONTRIBUTING.md",
29
+ "SECURITY.md",
30
+ "CODE_OF_CONDUCT.md",
31
+ "CHANGELOG.md",
32
+ "docs/**/*.md",
33
+ "plugins/README.md",
34
+ ".github/**/*.md",
35
+ ]
36
+
37
+ TEXT_GLOBS = [
38
+ "README.md",
39
+ "CONTRIBUTING.md",
40
+ "SECURITY.md",
41
+ "CODE_OF_CONDUCT.md",
42
+ "CHANGELOG.md",
43
+ "docs/**/*.md",
44
+ "commands/**/*.md",
45
+ "plugins/**/*.md",
46
+ "agents/**/*.md",
47
+ "rules/**/*.md",
48
+ "runtime/**/*.py",
49
+ "hooks/**/*.py",
50
+ "scripts/**/*.py",
51
+ ".github/workflows/**/*.yml",
52
+ ".github/workflows/**/*.yaml",
53
+ "OMG-setup.sh",
54
+ "install.sh",
55
+ "package.json",
56
+ "settings.json",
57
+ ".claude-plugin/**/*.json",
58
+ "plugins/**/*.json",
59
+ ]
60
+
61
+ MARKDOWN_LINK_RE = re.compile(r"!\[[^\]]*\]\(([^)]+)\)|\[[^\]]+\]\(([^)]+)\)")
62
+ ALLOW_PATTERN_REFERENCES = {
63
+ ROOT / "scripts" / "check-omg-public-ready.py",
64
+ }
65
+ ALLOW_DEPRECATED_MARKETPLACE = {
66
+ ROOT / "OMG-setup.sh",
67
+ ROOT / "scripts" / "check-omg-public-ready.py",
68
+ }
69
+
70
+
71
+ def _iter_files(root: Path, globs: list[str]) -> list[Path]:
72
+ files: list[Path] = []
73
+ for pattern in globs:
74
+ files.extend(path for path in root.glob(pattern) if path.is_file())
75
+ return sorted(set(files))
76
+
77
+
78
+ def _read(path: Path) -> str:
79
+ return path.read_text(encoding="utf-8")
80
+
81
+
82
+ def _find_text_violations(root: Path) -> list[str]:
83
+ violations: list[str] = []
84
+ for path in _iter_files(root, TEXT_GLOBS):
85
+ rel = path.relative_to(root)
86
+ content = _read(path)
87
+ if "/Users/" in content:
88
+ if path not in ALLOW_PATTERN_REFERENCES:
89
+ violations.append(f"{rel}: absolute local path found in public repo content")
90
+ if ".sisyphus/" in content:
91
+ if path not in ALLOW_PATTERN_REFERENCES:
92
+ violations.append(f"{rel}: stale internal path reference found (.sisyphus/)")
93
+ if "trac3er00/OAL" in content:
94
+ if path not in ALLOW_PATTERN_REFERENCES:
95
+ violations.append(f"{rel}: old repo identifier found (trac3er00/OAL)")
96
+ if "oh-advanced-layer" in content:
97
+ if path not in ALLOW_DEPRECATED_MARKETPLACE:
98
+ violations.append(f"{rel}: deprecated marketplace identifier found (oh-advanced-layer)")
99
+ return violations
100
+
101
+
102
+ def _find_missing_docs(root: Path) -> list[str]:
103
+ violations: list[str] = []
104
+ for rel in REQUIRED_PUBLIC_DOCS:
105
+ if not (root / rel).exists():
106
+ violations.append(f"{rel}: missing required public doc")
107
+ return violations
108
+
109
+
110
+ def _find_missing_templates(root: Path) -> list[str]:
111
+ violations: list[str] = []
112
+ for rel in REQUIRED_COMMUNITY_TEMPLATES:
113
+ if not (root / rel).exists():
114
+ violations.append(f"{rel}: missing required community template")
115
+ return violations
116
+
117
+
118
+ def _find_internal_docs(root: Path) -> list[str]:
119
+ plans_dir = root / "docs" / "plans"
120
+ if plans_dir.exists():
121
+ return [f"{plans_dir.relative_to(root)}: internal planning docs must not ship in public branch"]
122
+ return []
123
+
124
+
125
+ def _normalize_link_target(raw: str) -> str:
126
+ target = raw.strip()
127
+ if target.startswith("<") and target.endswith(">"):
128
+ target = target[1:-1].strip()
129
+ return target
130
+
131
+
132
+ def _is_relative_markdown_link(target: str) -> bool:
133
+ if not target:
134
+ return False
135
+ if target.startswith("#"):
136
+ return False
137
+ lowered = target.lower()
138
+ return not (
139
+ lowered.startswith("http://")
140
+ or lowered.startswith("https://")
141
+ or lowered.startswith("mailto:")
142
+ or lowered.startswith("data:")
143
+ or lowered.startswith("file:")
144
+ or target.startswith("/")
145
+ )
146
+
147
+
148
+ def _link_target_exists(doc_path: Path, target: str) -> bool:
149
+ file_part = target.split("#", 1)[0].split("?", 1)[0]
150
+ if not file_part:
151
+ return True
152
+ resolved = (doc_path.parent / file_part).resolve()
153
+ return resolved.exists()
154
+
155
+
156
+ def _find_broken_markdown_links(root: Path) -> list[str]:
157
+ violations: list[str] = []
158
+ for path in _iter_files(root, PUBLIC_DOC_GLOBS):
159
+ rel = path.relative_to(root)
160
+ content = _read(path)
161
+ for match in MARKDOWN_LINK_RE.finditer(content):
162
+ target = _normalize_link_target(match.group(1) or match.group(2) or "")
163
+ if not _is_relative_markdown_link(target):
164
+ continue
165
+ if not _link_target_exists(path, target):
166
+ violations.append(f"{rel}: broken markdown link -> {target}")
167
+ return violations
168
+
169
+
170
+ def main() -> int:
171
+ parser = argparse.ArgumentParser(description="Check OMG public-readiness hygiene")
172
+ parser.add_argument("--root", default=str(ROOT))
173
+ args = parser.parse_args()
174
+ root = Path(args.root).resolve()
175
+
176
+ violations = []
177
+ violations.extend(_find_missing_docs(root))
178
+ violations.extend(_find_missing_templates(root))
179
+ violations.extend(_find_internal_docs(root))
180
+ violations.extend(_find_text_violations(root))
181
+ violations.extend(_find_broken_markdown_links(root))
182
+ violations = sorted(set(violations))
183
+
184
+ if violations:
185
+ print(json.dumps({"status": "error", "violations": violations}, indent=2))
186
+ return 1
187
+
188
+ print(json.dumps({"status": "ok", "message": "public readiness check passed"}, indent=2))
189
+ return 0
190
+
191
+
192
+ if __name__ == "__main__":
193
+ raise SystemExit(main())
package/scripts/omg.py CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env python3
2
- """OMG 2.0.1 CLI entrypoint.
2
+ """OMG 2.0.3 CLI entrypoint.
3
3
 
4
4
  Implements practical command-line flows for:
5
5
  - omg ship
package/settings.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
3
- "_comment": "OMG 2.0.1 - project-level config with hook registrations, presets, and feature flags.",
3
+ "_comment": "OMG 2.0.3 - project-level config with hook registrations, presets, and feature flags.",
4
4
  "permissions": {
5
5
  "allow": [
6
6
  "Agent",
@@ -262,7 +262,7 @@
262
262
  ]
263
263
  },
264
264
  "_omg": {
265
- "_version": "2.0.1",
265
+ "_version": "2.0.3",
266
266
  "preset": "safe",
267
267
  "default_mode": "ulw+ralph",
268
268
  "vision_auto": true,
@@ -1,144 +0,0 @@
1
- """OpenCode CLI provider -- implements CLIProvider for the ``opencode`` binary."""
2
-
3
- from __future__ import annotations
4
-
5
- import json
6
- import logging
7
- import os
8
- import shlex
9
- import shutil
10
- import subprocess
11
- import uuid
12
- from typing import Any
13
-
14
- from runtime.cli_provider import CLIProvider, register_provider
15
- from runtime.tmux_session_manager import TmuxSessionManager
16
-
17
- _logger = logging.getLogger(__name__)
18
-
19
-
20
- class OpenCodeProvider(CLIProvider):
21
- """CLIProvider implementation for the OpenCode CLI (``opencode``)."""
22
-
23
- # -- identity -----------------------------------------------------------
24
-
25
- def get_name(self) -> str: # noqa: D401
26
- """Return the canonical provider name."""
27
- return "opencode"
28
-
29
- # -- detection ----------------------------------------------------------
30
-
31
- def detect(self) -> bool:
32
- """Return ``True`` when the ``opencode`` binary is available on PATH."""
33
- return shutil.which("opencode") is not None
34
-
35
- # -- authentication -----------------------------------------------------
36
-
37
- def check_auth(self) -> tuple[bool | None, str]:
38
- """Check OpenCode authentication status via ``opencode auth list``."""
39
- try:
40
- result = self.run_tool(["opencode", "auth", "list"], timeout=30)
41
- if result.returncode == 0:
42
- return True, result.stdout.strip()
43
- return False, result.stderr.strip() or result.stdout.strip()
44
- except Exception as exc:
45
- return None, f"opencode auth check failed: {exc}"
46
-
47
- # -- invocation ---------------------------------------------------------
48
-
49
- def invoke(self, prompt: str, project_dir: str, timeout: int = 120) -> dict[str, Any]: # pyright: ignore[reportExplicitAny]
50
- """Invoke ``opencode run`` via subprocess."""
51
- try:
52
- result = self.run_tool(
53
- ["opencode", "run", prompt],
54
- timeout=timeout,
55
- )
56
- return {
57
- "model": "opencode-cli",
58
- "output": result.stdout,
59
- "exit_code": result.returncode,
60
- }
61
- except subprocess.TimeoutExpired:
62
- return {"error": "opencode-cli timeout", "fallback": "claude"}
63
- except FileNotFoundError:
64
- return {"error": "opencode-cli not found", "fallback": "claude"}
65
- except Exception as exc:
66
- return {"error": str(exc), "fallback": "claude"}
67
-
68
- def invoke_json(self, prompt: str, project_dir: str, timeout: int = 120) -> dict[str, Any]: # pyright: ignore[reportExplicitAny]
69
- """Invoke ``opencode run --format json`` for raw JSON event stream output."""
70
- try:
71
- result = self.run_tool(
72
- ["opencode", "run", "--format", "json", prompt],
73
- timeout=timeout,
74
- )
75
- return {
76
- "model": "opencode-cli",
77
- "output": result.stdout,
78
- "exit_code": result.returncode,
79
- }
80
- except subprocess.TimeoutExpired:
81
- return {"error": "opencode-cli timeout", "fallback": "claude"}
82
- except FileNotFoundError:
83
- return {"error": "opencode-cli not found", "fallback": "claude"}
84
- except Exception as exc:
85
- return {"error": str(exc), "fallback": "claude"}
86
-
87
- def invoke_tmux(self, prompt: str, project_dir: str, timeout: int = 120) -> dict[str, Any]: # pyright: ignore[reportExplicitAny]
88
- """Invoke ``opencode run`` via a persistent tmux session.
89
-
90
- Falls back to :meth:`invoke` on failure.
91
- """
92
- try:
93
- mgr = TmuxSessionManager()
94
- session_name = mgr.make_session_name("opencode", unique_id=str(uuid.uuid4())[:8])
95
- session = mgr.get_or_create_session(session_name)
96
- output = mgr.send_command(session, f"opencode run {shlex.quote(prompt)}", timeout=timeout)
97
- mgr.kill_session(session)
98
- return {"model": "opencode-cli", "output": output, "exit_code": 0}
99
- except Exception as exc:
100
- _logger.warning("tmux opencode invocation failed, falling back to subprocess: %s", exc)
101
- return self.invoke(prompt, project_dir, timeout=timeout)
102
-
103
- # -- command helpers ----------------------------------------------------
104
-
105
- def get_non_interactive_cmd(self, prompt: str) -> list[str]:
106
- """Return the non-interactive command for opencode."""
107
- return ["opencode", "run", prompt]
108
-
109
- # -- configuration ------------------------------------------------------
110
-
111
- def get_config_path(self) -> str:
112
- """Return the OpenCode configuration file path."""
113
- return os.path.expanduser("~/.config/opencode/opencode.json")
114
-
115
- def write_mcp_config(self, server_url: str, server_name: str = "memory-server") -> None:
116
- """Write an MCP server entry to ``~/.config/opencode/opencode.json``.
117
-
118
- Uses JSON format with ``mcp`` key, ``type: "remote"``, and ``url`` field,
119
- merging into any existing configuration.
120
- """
121
- config_path = self.get_config_path()
122
- os.makedirs(os.path.dirname(config_path), exist_ok=True)
123
-
124
- # Load existing config or start fresh
125
- existing: dict[str, Any] = {} # pyright: ignore[reportExplicitAny]
126
- if os.path.exists(config_path):
127
- with open(config_path) as fh:
128
- try:
129
- existing = json.load(fh)
130
- except (json.JSONDecodeError, ValueError):
131
- existing = {}
132
-
133
- # Ensure mcp dict exists
134
- if "mcp" not in existing:
135
- existing["mcp"] = {}
136
-
137
- existing["mcp"][server_name] = {"type": "remote", "url": server_url}
138
-
139
- with open(config_path, "w") as fh:
140
- json.dump(existing, fh, indent=2)
141
-
142
-
143
- # -- auto-register on import -----------------------------------------------
144
- register_provider(OpenCodeProvider())