From d7f8df407bb4fe1f8de79fb328052d55bf4b013c Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Sat, 30 May 2026 19:12:16 +0900 Subject: [PATCH] docs(omo-codex): batch 88 (12 files) --- .../plugin/components/rules/.gitattributes | 13 ++ .../plugin/components/rules/.gitignore | 6 + .../plugin/components/rules/AGENTS.md | 34 +++++ .../plugin/components/rules/CHANGELOG.md | 19 +++ .../omo-codex/plugin/components/rules/LICENSE | 21 +++ .../omo-codex/plugin/components/rules/NOTICE | 15 +++ .../plugin/components/rules/README.md | 124 ++++++++++++++++++ .../plugin/components/rules/biome.json | 48 +++++++ .../plugin/components/rules/package.json | 62 +++++++++ .../components/rules/tsconfig.build.json | 12 ++ .../plugin/components/rules/tsconfig.json | 27 ++++ .../plugin/components/rules/vitest.config.ts | 8 ++ 12 files changed, 389 insertions(+) create mode 100644 packages/omo-codex/plugin/components/rules/.gitattributes create mode 100644 packages/omo-codex/plugin/components/rules/.gitignore create mode 100644 packages/omo-codex/plugin/components/rules/AGENTS.md create mode 100644 packages/omo-codex/plugin/components/rules/CHANGELOG.md create mode 100644 packages/omo-codex/plugin/components/rules/LICENSE create mode 100644 packages/omo-codex/plugin/components/rules/NOTICE create mode 100644 packages/omo-codex/plugin/components/rules/README.md create mode 100644 packages/omo-codex/plugin/components/rules/biome.json create mode 100644 packages/omo-codex/plugin/components/rules/package.json create mode 100644 packages/omo-codex/plugin/components/rules/tsconfig.build.json create mode 100644 packages/omo-codex/plugin/components/rules/tsconfig.json create mode 100644 packages/omo-codex/plugin/components/rules/vitest.config.ts diff --git a/packages/omo-codex/plugin/components/rules/.gitattributes b/packages/omo-codex/plugin/components/rules/.gitattributes new file mode 100644 index 000000000..9363fdb74 --- /dev/null +++ b/packages/omo-codex/plugin/components/rules/.gitattributes @@ -0,0 +1,13 @@ +# Normalize line endings: store LF in git, check out LF on every platform. +# Required so biome's --check passes on Windows (default core.autocrlf=true). +* text=auto eol=lf + +# Explicit binary types +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.zip binary +*.tgz binary +*.gz binary diff --git a/packages/omo-codex/plugin/components/rules/.gitignore b/packages/omo-codex/plugin/components/rules/.gitignore new file mode 100644 index 000000000..bc848922c --- /dev/null +++ b/packages/omo-codex/plugin/components/rules/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +.DS_Store +*.log +coverage/ +.vitest/ +*.tgz diff --git a/packages/omo-codex/plugin/components/rules/AGENTS.md b/packages/omo-codex/plugin/components/rules/AGENTS.md new file mode 100644 index 000000000..83d16c844 --- /dev/null +++ b/packages/omo-codex/plugin/components/rules/AGENTS.md @@ -0,0 +1,34 @@ +# Repository Conventions + +Conventions for human contributors and AI agents working on this repository. + +## Style + +- Terse technical prose. No emojis in commits, issues, PR comments, or code. +- TypeScript strict mode. No `any`, no `@ts-ignore`, no `@ts-expect-error`, no enums. +- ESM modules with `.js` suffix in runtime import paths. +- Tabs for indentation. Double quotes for strings. +- Tests use vitest with `#given .. #when .. #then` descriptions or plain `// given / // when / // then` body comments. + +## Commands + +- `npm install` - install dependencies. +- `npm test` - run vitest once. +- `npm run typecheck` - strict TypeScript check. +- `npm run check` - type check, biome, and build. +- `npm pack --dry-run` - release package smoke test. +- `node dist/cli.js hook session-start < fixture.json` - smoke-test static rule injection. +- `node dist/cli.js hook post-tool-use < fixture.json` - smoke-test dynamic rule injection. + +## Constraints + +- No Bun APIs. Runtime is Node only because Codex launches plugin hooks with Node. +- Keep `SessionStart`, `UserPromptSubmit`, and `PostToolUse` hook behavior covered by tests. +- Keep Codex file path extraction for reads, edits, `apply_patch`, and shell-style tools covered by tests. +- Hook output must use the stable Codex hook JSON contract. +- Do not couple this package back to pi, omo, or senpi internal source paths. + +## Don'ts + +- No `git add -A` or `git add .`. Stage only the files you changed. +- No `git commit --no-verify`. No force pushes. No history rewriting on shared branches. diff --git a/packages/omo-codex/plugin/components/rules/CHANGELOG.md b/packages/omo-codex/plugin/components/rules/CHANGELOG.md new file mode 100644 index 000000000..ae8f598c3 --- /dev/null +++ b/packages/omo-codex/plugin/components/rules/CHANGELOG.md @@ -0,0 +1,19 @@ +# Changelog + +## Unreleased + +- Restrict the default `PostToolUse` hook matcher to Codex's canonical `apply_patch` tool name. +- Add opt-in `NODE_DEBUG=codex-rules` phase timing logs for `PostToolUse` debugging. +- Harden dynamic hook coverage for additional-context JSON output, disabled/static modes, failed tool responses, and duplicate suppression. +- Remove redundant apply_patch path scanning and stale tracked-tool constants. +- Use portable Codex hook interpolation and add package smoke coverage for hook entrypoints. +- Cap recursive rule directory scans and run CI on Windows in addition to Ubuntu and macOS. +- Replace the external glob matcher dependency with an internal matcher so clean Codex plugin installs run without `node_modules`. + +## 0.1.0 - 2026-05-15 + +- Port `pi-rules` rule loading, matching, formatting, truncation, and deduplication to a Codex plugin. +- Add `SessionStart`, `UserPromptSubmit`, and `PostToolUse` hooks for static and file-specific context injection. +- Add persistent per-session deduplication under Codex plugin data. +- Add Codex-aware path extraction for read, write, edit, multi-edit, `apply_patch`, and shell command payloads. +- Add tests, CI, release workflow, marketplace metadata, and local install support. diff --git a/packages/omo-codex/plugin/components/rules/LICENSE b/packages/omo-codex/plugin/components/rules/LICENSE new file mode 100644 index 000000000..09aac3c3b --- /dev/null +++ b/packages/omo-codex/plugin/components/rules/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Yeongyu Kim + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/omo-codex/plugin/components/rules/NOTICE b/packages/omo-codex/plugin/components/rules/NOTICE new file mode 100644 index 000000000..f86989913 --- /dev/null +++ b/packages/omo-codex/plugin/components/rules/NOTICE @@ -0,0 +1,15 @@ +codex-rules + +This package implements rule/context loading for Codex plugins. +Its behavior is ported from pi-rules in the pi coding-agent extension ecosystem +and inspired by oh-my-openagent (omo) at https://github.com/code-yeongyu/oh-my-openagent, +including omo's `.omo/rules/` workflow and rules-injector hook architecture. +omo is originally licensed under the Sustainable Use License 1.0. + +Yeongyu Kim (https://github.com/code-yeongyu), author of omo, pi-rules, and this +package, licenses the source distributed in this repository under the MIT License. +If any source was ported from omo or pi-rules, that ported source is re-licensed +here under MIT for distribution as a Codex plugin. See LICENSE for terms. + +picomatch is by Jon Schlinkert and contributors (https://github.com/micromatch/picomatch). +Distributed under the MIT License. diff --git a/packages/omo-codex/plugin/components/rules/README.md b/packages/omo-codex/plugin/components/rules/README.md new file mode 100644 index 000000000..c7a40dab5 --- /dev/null +++ b/packages/omo-codex/plugin/components/rules/README.md @@ -0,0 +1,124 @@ +# codex-rules + +Codex plugin that injects local project rule files into model context through lifecycle hooks. + +It ports the `pi-rules` rule injector to Codex: + +- `SessionStart` and `UserPromptSubmit` load static project instructions once per session. +- `PostToolUse` watches Codex `apply_patch` by default, then injects matching file-specific rules as additional context. +- `PostCompact` clears the per-session injection cache after manual or automatic compaction so relevant rules can be reintroduced into the compacted conversation. +- Session-level deduplication prevents the same rule from being repeated after it has been injected. + +`PostToolUse` output is context-only: it emits `hookSpecificOutput.additionalContext` and does not rewrite tool output. + +The runtime has no npm production dependencies, so a clean Codex marketplace copy can run without a follow-up `npm install`. + +## Rule Sources + +Project-level sources: + +- `AGENTS.md` +- `CLAUDE.md` +- `CONTEXT.md` +- `.omo/rules/**/*.md` +- `.claude/rules/**/*.md` +- `.cursor/rules/**/*.md` +- `.github/instructions/**/*.md` +- `.github/copilot-instructions.md` + +User-home sources are also supported by the ported engine when available. + +Markdown rule files may use frontmatter such as: + +```md +--- +description: TypeScript defaults +globs: ["**/*.ts", "**/*.tsx"] +alwaysApply: false +--- + +Prefer strict TypeScript and keep runtime imports ESM-compatible. +``` + +## Install Locally + +```bash +bunx lazycodex install +``` + +The local installer builds the plugin and copies a clean cache entry to: + +```text +~/.codex/plugins/cache/sisyphuslabs/omo/0.1.0 +``` + +It also enables: + +```toml +[features] +plugins = true +plugin_hooks = true + +[plugins."omo@sisyphuslabs"] +enabled = true +``` + +## Configuration + +Use `CODEX_RULES_*` environment variables: + +| Variable | Values | Default | +| --- | --- | --- | +| `CODEX_RULES_DISABLED` | `1`, `true`, `yes`, `on` | unset | +| `CODEX_RULES_MODE` | `both`, `static`, `dynamic`, `off` | `both` | +| `CODEX_RULES_MAX_RULE_CHARS` | positive integer | `12000` | +| `CODEX_RULES_MAX_RESULT_CHARS` | positive integer | `40000` | +| `CODEX_RULES_ENABLED_SOURCES` | comma-separated source names | `auto` | + +For migration from `pi-rules`, equivalent `PI_RULES_*` variables are accepted as fallbacks. + +## Debugging + +Enable hook phase timing with `NODE_DEBUG=codex-rules`: + +```bash +NODE_DEBUG=codex-rules node dist/cli.js hook post-tool-use < fixture.json +``` + +Debug lines go to stderr and hook JSON stays on stdout. The log includes `PostToolUse` phases such as `extract`, `fingerprint`, `load`, `persist`, elapsed `ms`, target counts, pending counts, rule counts, and output bytes. It does not log rule bodies or tool response contents. + +The default `PostToolUse` hook matcher is intentionally strict: it matches only Codex's canonical `apply_patch` hook tool name. Read tools, MCP filesystem tools, shell commands, and Claude-style `Write`/`Edit` aliases are not registered by default. + +## Development + +```bash +npm install +npm test +npm run check +npm run typecheck +npm pack --dry-run +``` + +Performance smoke test: + +```bash +npm run bench +``` + +Benchmark timings depend on the local machine. Use the relative counters and repeat-output checks when comparing runs. + +Hook smoke test: + +```bash +npm run build +printf '%s\n' '{"session_id":"s","transcript_path":null,"cwd":"/path/to/project","hook_event_name":"SessionStart","model":"gpt-5.5","permission_mode":"default","source":"startup"}' \ + | PLUGIN_DATA=/tmp/codex-rules-data node dist/cli.js hook session-start +``` + +## Privacy + +`codex-rules` runs locally. It reads local rule files and Codex hook payloads, writes per-session deduplication state under the Codex plugin data directory, and does not make network requests. + +## License + +MIT. See [LICENSE](LICENSE) and [NOTICE](NOTICE). diff --git a/packages/omo-codex/plugin/components/rules/biome.json b/packages/omo-codex/plugin/components/rules/biome.json new file mode 100644 index 000000000..5aa1a0dcc --- /dev/null +++ b/packages/omo-codex/plugin/components/rules/biome.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.4.15/schema.json", + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "style": { + "noDefaultExport": "error", + "noEnum": "error", + "noNonNullAssertion": "error", + "useImportType": "error", + "useConst": "error", + "useNodejsImportProtocol": "off" + }, + "complexity": { + "useLiteralKeys": "off" + }, + "suspicious": { + "noExplicitAny": "error", + "noTsIgnore": "error", + "noControlCharactersInRegex": "off", + "noEmptyInterface": "off" + } + } + }, + "formatter": { + "enabled": true, + "formatWithErrors": false, + "indentStyle": "tab", + "indentWidth": 3, + "lineWidth": 120 + }, + "files": { + "includes": ["src/**/*.ts", "test/**/*.ts", "vitest.config.ts", "!**/node_modules/**/*", "!**/dist/**/*"] + }, + "overrides": [ + { + "includes": ["vitest.config.ts"], + "linter": { + "rules": { + "style": { + "noDefaultExport": "off" + } + } + } + } + ] +} diff --git a/packages/omo-codex/plugin/components/rules/package.json b/packages/omo-codex/plugin/components/rules/package.json new file mode 100644 index 000000000..422bc80ff --- /dev/null +++ b/packages/omo-codex/plugin/components/rules/package.json @@ -0,0 +1,62 @@ +{ + "name": "@code-yeongyu/codex-rules", + "version": "0.1.0", + "description": "Codex plugin that injects project rule files into model context through lifecycle hooks.", + "type": "module", + "packageManager": "npm@11.12.1", + "license": "MIT", + "homepage": "https://github.com/code-yeongyu/codex-rules", + "repository": { + "type": "git", + "url": "git+https://github.com/code-yeongyu/codex-rules.git" + }, + "bugs": { + "url": "https://github.com/code-yeongyu/codex-rules/issues" + }, + "keywords": [ + "codex", + "codex-plugin", + "rules", + "hooks", + "agents-md", + "context-injection", + "typescript" + ], + "bin": { + "omo-rules": "./dist/cli.js" + }, + "files": [ + "bundled-rules", + "dist", + "hooks", + "skills", + ".codex-plugin", + "LICENSE", + "NOTICE", + "README.md", + "CHANGELOG.md" + ], + "scripts": { + "build": "tsc -p tsconfig.build.json", + "test": "vitest --run", + "test:watch": "vitest", + "bench": "npm run build --silent && node scripts/bench-codex-rules.mjs", + "typecheck": "tsc --noEmit", + "lint": "biome check .", + "lint:fix": "biome check --write .", + "check": "tsc --noEmit && biome check . && npm run build" + }, + "dependencies": { + "picomatch": "^4.0.3" + }, + "devDependencies": { + "@biomejs/biome": "2.4.15", + "@types/node": "^25.7.0", + "@types/picomatch": "^4.0.0", + "typescript": "^6.0.3", + "vitest": "^4.1.5" + }, + "engines": { + "node": ">=20.0.0" + } +} diff --git a/packages/omo-codex/plugin/components/rules/tsconfig.build.json b/packages/omo-codex/plugin/components/rules/tsconfig.build.json new file mode 100644 index 000000000..5b5bbcafd --- /dev/null +++ b/packages/omo-codex/plugin/components/rules/tsconfig.build.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "allowImportingTsExtensions": false, + "declaration": true, + "outDir": "dist", + "rootDir": "src", + "noEmit": false + }, + "include": ["src/**/*"], + "exclude": ["test/**/*"] +} diff --git a/packages/omo-codex/plugin/components/rules/tsconfig.json b/packages/omo-codex/plugin/components/rules/tsconfig.json new file mode 100644 index 000000000..342229c02 --- /dev/null +++ b/packages/omo-codex/plugin/components/rules/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "Node16", + "moduleResolution": "Node16", + "lib": ["ES2022"], + "strict": true, + "exactOptionalPropertyTypes": true, + "noUncheckedIndexedAccess": true, + "noPropertyAccessFromIndexSignature": true, + "verbatimModuleSyntax": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "esModuleInterop": true, + "allowImportingTsExtensions": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "useDefineForClassFields": false, + "types": ["node"], + "noEmit": true + }, + "include": ["src/**/*", "test/**/*"] +} diff --git a/packages/omo-codex/plugin/components/rules/vitest.config.ts b/packages/omo-codex/plugin/components/rules/vitest.config.ts new file mode 100644 index 000000000..c4fddb41c --- /dev/null +++ b/packages/omo-codex/plugin/components/rules/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + environment: "node", + pool: "threads", + }, +});