diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..ed1d783 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,40 @@ +# Changelog + +This changelog records user-visible RTK Codex Plugin releases. + +## [Unreleased] + +## [0.1.0] - 2026-07-25 + +### Included + +- PreToolUse classification for supported shell command payloads; +- optional `rtk rewrite ` integration with bounded validation and + fail-open behavior; +- pre-execution guarding for recognized long-line inspection shapes; +- PostToolUse byte, line, and best-effort aggregate-turn budgets; +- local artifact preservation for qualifying guarded or compacted output; +- stream, parallel-tool, wrapper, bypass, and Pitlane pass-through handling; +- standard-library test coverage for the public behavior surface. + +### Documentation + +- added architecture, decision-flow, sequence, and state-lifecycle diagrams; +- documented Python 3.11+ and POSIX requirements; +- documented native Windows exclusion and WSL2 operation; +- added pinned release installation, update, rollback, and uninstall guidance; +- documented every output-budget override and state path; +- documented artifact sensitivity, permissions, retention, and trust + boundaries; +- added compatibility, troubleshooting, contribution, and security guides. + +### Release scope + +- POSIX plugin/source tarball; +- SHA-256 integrity manifest; +- no bundled RTK executable; +- no native Windows, PyPI, or npm package; +- no signed provenance or reproducible-build claim. + +[Unreleased]: https://github.com/mmmihaeel/rtk-codex-plugin/compare/v0.1.0...HEAD +[0.1.0]: https://github.com/mmmihaeel/rtk-codex-plugin/releases/tag/v0.1.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..908f422 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,80 @@ +# Contributing + +RTK Codex Plugin is intentionally small, but classifier and output-budget +changes can alter shell behavior. Contributions should be narrow, explicit +about command semantics, and backed by focused tests. + +## Environment + +Use Python 3.11+ on Linux, WSL2, or another POSIX environment: + +```bash +python3 --version +git clone https://github.com/mmmihaeel/rtk-codex-plugin.git +cd rtk-codex-plugin +``` + +The project uses only the Python standard library. + +## Run verification + +```bash +python3 -m json.tool .codex-plugin/plugin.json >/dev/null +python3 -m json.tool hooks/hooks.json >/dev/null +test -x hooks/rtk-codex-hook +test -x hooks/rtk-output-guard +test -x hooks/rtk-output-post-hook +make test +``` + +The public suite discovers 50 tests: 49 pass and one public-projection exporter +check is intentionally skipped because that exporter is not included here. + +## Change expectations + +For classifier changes, add cases covering: + +- the intended rewrite or guard path; +- neighboring pass-through and exact-output shapes; +- wrappers, environment prefixes, quoting, and shell-control boundaries; +- missing, invalid, or failing external RTK behavior; +- Pitlane-owned shapes when integration ordering could change. + +For PostToolUse changes, cover: + +- byte and line thresholds; +- summary-smaller checks and artifact removal; +- aggregate turn state; +- `write_stdin` and parallel payloads; +- bypass markers; +- sensitive path and filename handling. + +Do not add benchmark, token-saving, security, or cross-runtime claims without +reproducible evidence. + +## Documentation + +Update public documentation when a change affects: + +- supported Python or platforms; +- plugin/hook payload contracts; +- environment variables or default limits; +- artifact locations, permissions, or retention; +- bypass behavior; +- optional RTK interface; +- ecosystem ordering or compatibility. + +All public prose must remain English. Verify Markdown formatting, local links, +and examples before opening a pull request. + +## Pull requests + +Describe: + +- the user-visible behavior; +- why the selected classifier boundary is safe enough for its intended role; +- exact tests run; +- platform/runtime combinations not tested; +- security, artifact, or release impact. + +Contributions are accepted under the [MIT License](./LICENSE). diff --git a/README.md b/README.md index 1df6f2c..bd2013a 100644 --- a/README.md +++ b/README.md @@ -1,112 +1,129 @@ -

rtk-codex-plugin

+

RTK Codex Plugin

- Keep Codex shell output useful before it burns the context window. + Context-budget hygiene for shell-heavy agent sessions.

- A small Codex-compatible shell plugin for command rewrite, bounded long-line output, and artifact-backed output compaction. + A small, auditable plugin that classifies shell requests before execution, + optionally asks rtk for a rewrite, and compacts oversized + model-visible output into local artifacts after execution.

+ + Latest RTK Codex Plugin release + CI status MIT License - Python 3 - Codex plugin hooks + Python 3.11 or later + POSIX runtime

Install - · + · + Architecture + · + Configuration + · Compatibility - · - Stack Fit + · + Security

-`rtk-codex-plugin` adds a shell-focused `PreToolUse` hook for Codex-compatible -runtimes. It has three jobs: - -- route eligible Bash/`exec_command` calls through `rtk rewrite` for more - compact output; -- wrap risky long-line inspections with a bounded output guard; -- compact medium/large model-visible tool output after execution while - preserving the full raw output, including `write_stdin` streams, in local - artifacts. - -The guard is useful even when `rtk` is not installed. Rewrite mode is optional -and activates only when the `rtk` binary is available in `PATH`. - -## Part of the Codez stack - -The Codez stack is modular. Each layer can be used on its own unless a higher -layer explicitly opts into it. - -| Layer | Public surface | Responsibility | Dependency | -| --- | --- | --- | --- | -| [Codez](https://github.com/mmmihaeel/codez) | Codex-compatible runtime | App Server v2, goal RPC, long-session hardening, prompt pruning, and plugin hooks | Does not require Teledex | -| [RTK Codex Plugin](https://github.com/mmmihaeel/rtk-codex-plugin) | Optional Codex plugin | Shell/token safety through `rtk rewrite` and bounded output guarding | Requires a Codex-compatible plugin-hook runtime; does not require Teledex | -| [Pitlane Codex Plugin](https://github.com/mmmihaeel/pitlane-codex-plugin) | Optional Codex plugin | Code-navigation/token-saving rewrites through a host-local `pitlane` CLI | Requires a Codex-compatible plugin-hook runtime and local `pitlane`; does not require Teledex | -| [Teledex](https://github.com/mmmihaeel/teledex) | Telegram gateway/session layer | Topics, queues, live steer, `/goal` UX, and delivery/recovery around durable agent sessions | Full mode is optimized for Codez App Server v2; upstream `codex exec --json` is legacy compatibility only | - -## Why People Use It - -- avoid huge JSONL, log, and prompt-capture lines flooding the model context -- keep simple shell exploration compact without changing test or machine - command semantics -- preserve no-rewrite command semantics for `rg --files`, `git status --short`, - `jq`/JSON modes, counts, lists, direct `rg`/`grep` searches, build/test - commands, Docker commands, and interactive commands while still compacting - oversized model-visible output -- install as a small plugin instead of changing every shell command by hand - -## Mental Model - -| Piece | Role | -| --- | --- | -| Codex-compatible runtime | executes `PreToolUse` hooks before shell calls | -| `rtk-codex-hook` | decides whether a command should be guarded, rewritten, or left alone | -| `rtk-output-guard` | caps per-line and total stdout for risky inspections | -| `rtk-output-post-hook` | compacts large model-visible shell output with artifact refs | -| optional `rtk` binary | rewrites eligible commands into a compact shell form | +`rtk-codex-plugin` is designed for +[Codez](https://github.com/mmmihaeel/codez) and runtimes implementing the same +plugin manifest, hook payload, matcher, updated-input, and PostToolUse feedback +contracts. It works without an `rtk` executable for recognized output-guard +paths; command rewriting activates only when a compatible `rtk` is on `PATH`. + +## At a glance + +| Area | Current contract | +| --------------------- | ---------------------------------------------- | +| Release | `v0.1.0` | +| Runtime | Python 3.11+ on a POSIX host | +| Verified environments | GitHub Actions Ubuntu; local Ubuntu on WSL2 | +| Native Windows | Not supported in `v0.1.0` | +| Python dependencies | Standard library only | +| Optional dependency | `rtk` CLI implementing `rtk rewrite ` | +| State | Local artifacts and per-turn budget records | +| License | MIT | + +## What it does + +| Stage | Component | Responsibility | +| ------------------------ | ---------------------- | -------------------------------------------------------------------------------------------------------------------------- | +| Before execution | `rtk-codex-hook` | Classify shell input, preserve deliberate pass-through cases, select the bounded guard, or request an optional RTK rewrite | +| During guarded execution | `rtk-output-guard` | Limit recognized long-line inspection output while retaining the merged stream in a local artifact when truncation occurs | +| After execution | `rtk-output-post-hook` | Apply byte, line, and aggregate-turn budgets; emit compact model feedback with a local artifact reference when beneficial | + +Pass-through means the **command** is not rewritten before execution. Its +result can still be compacted by PostToolUse when it exceeds configured +budgets. Use the explicit bypass only when raw model-visible output is required. + +## Architecture + +```mermaid +flowchart LR + accTitle: RTK Codex Plugin request and output flow + accDescr: A shell request passes through a PreToolUse classifier. It is left unchanged, rewritten by an optional RTK command, or wrapped by a bounded output guard. After execution, a PostToolUse budget check either keeps the response or stores the received text locally and returns a compact summary. + + Request["Shell tool request"] --> Pre["PreToolUse classifier"] + + Pre -->|"Explicit bypass or pass-through"| Original["Original command"] + Pre -->|"Eligible and rtk available"| RTK["rtk rewrite"] + Pre -->|"Recognized risky inspection"| Guard["rtk-output-guard"] + + RTK --> Updated["Validated replacement"] + Original --> Execute["Runtime executes command"] + Updated --> Execute + Guard --> Execute + + Execute --> Post["PostToolUse budget check"] + Post -->|"Within budgets"| Response["Original tool response"] + Post -->|"Budget exceeded and summary is smaller"| Artifact["Local artifact with best-effort restrictive permissions"] + Artifact --> Summary["Compact summary, path, and SHA-256"] +``` -Architecture at a glance: +The detailed sequence, failure behavior, state model, and trust boundaries are +in [Architecture](./docs/architecture.md). -```text -Codex shell tool call - -> PreToolUse hook - -> risky JSONL/log/prompt inspection? run through rtk-output-guard - -> otherwise eligible simple command? ask rtk rewrite - -> no-rewrite/build/test/Docker/interactive command? pass through unchanged - -> PostToolUse hook - -> medium/large model-visible output? summary + full local artifact -``` +## Decision policy -## Highlights +| Input shape | PreToolUse behavior | PostToolUse behavior | +| --------------------------------------------------------------------------------------------------- | ----------------------------------------------- | ----------------------------------------------------------------- | +| Explicit `RTK_CODEX_BYPASS=1` | No guard or rewrite | No compaction when the relevant command/stream bypass rules match | +| Tests, builds, Git, direct search, JSON/machine modes, Docker, interactive or live-control commands | Preserve the original command | Oversized output can still be compacted | +| Recognized line-limited inspection pipeline, risky-file limiter, or `codex debug prompt-input` | Replace with the bounded guard | Guarded result remains eligible for normal budgeting | +| Eligible simple command with compatible `rtk` | Accept only a bounded, control-free replacement | Result remains eligible for budgeting | +| Missing, timed-out, invalid, or unsafe RTK rewrite | Preserve the original command | Normal budgeting still applies | -- bounds known long-line inspection shapes before execution -- bounds medium/large model-visible output after execution, including large - pass-through command output unless explicitly bypassed -- works without `rtk` for output guarding -- skips rewrite when exact stdout matters -- uses plain Python scripts and a small plugin manifest -- designed to work standalone and to fit the modular Codez stack +This classifier is a context guardrail, not a command-security system. It does +not sandbox commands, authorize actions, redact secrets, or replace runtime +approvals. -## Quick Start +## Five-minute install -Clone the plugin into the plugin cache used by your Codex-compatible runtime. -One common cache layout looks like this: +Run the installation inside Linux, macOS, or WSL2: ```bash codex_home="${CODEX_HOME:-$HOME/.codex}" -git clone https://github.com/mmmihaeel/rtk-codex-plugin \ + +git clone --branch v0.1.0 --depth 1 \ + https://github.com/mmmihaeel/rtk-codex-plugin.git \ "$codex_home/plugins/cache/github/rtk-codex-plugin/local" + +test -x \ + "$codex_home/plugins/cache/github/rtk-codex-plugin/local/hooks/rtk-codex-hook" ``` -Enable plugin hooks and the plugin key that matches your install location: +Enable plugin discovery and hook execution: ```toml [features] @@ -117,21 +134,98 @@ plugin_hooks = true enabled = true ``` -Run the focused test suite: +The exact plugin key depends on the runtime's installation source and cache +layout. See [Install](./docs/install.md) for release archives, verification, +updates, rollback, and uninstall. + +## Default budgets + +| Control | Default | +| -------------------------------------- | -------------: | +| Human-facing output | 5 KiB | +| General visible output | 12 KiB | +| Aggregate visible output per turn | 32 KiB | +| Visible lines | 300 | +| Summary head / tail | 4 KiB / 2 KiB | +| Pre-execution line body / visible body | 4 KiB / 64 KiB | +| Maximum accepted RTK rewrite | 16 KiB | +| RTK rewrite timeout | 4 seconds | + +Limits are measured in UTF-8 bytes and lines, not model tokens. Configuration +ranges and state paths are documented in +[Configuration](./docs/configuration.md). + +## Model-visible compaction + +When compaction is beneficial, the PostToolUse hook emits a summary shaped like: + +```text +[rtk-output-guard: output compacted] +class: build-or-test-output +reason: medium-large human-facing output exceeded 5120 bytes +original_bytes: ... +artifact: ~/.local/state/rtk-codex-plugin/artifacts/... +sha256: ... +``` + +The artifact contains the complete text **received by PostToolUse**. The plugin +cannot recover content that a host runtime truncated earlier. SHA-256 identifies +the artifact contents; it does not encrypt or authenticate them. + +## Verification + +The repository contains a standard-library `unittest` suite covering rewrite +acceptance, pass-through classification, risky inspection guards, compaction, +aggregate budgets, stream handling, parallel-tool handling, and bypass rules. ```bash -make test +python3 tests/test_rtk_codex_hook.py ``` -Read next: +Current evidence: + +- 49 of 50 tests pass on Ubuntu/WSL2; +- one public-projection exporter check is intentionally skipped; +- GitHub Actions runs the suite on Ubuntu; +- no cross-repository, live Codez installation test is claimed. + +## Boundaries + +- Python 3.11+ and a POSIX environment are required for the complete plugin. +- Native Windows is unsupported; use WSL2 and clone inside the Linux + environment. +- The optional RTK executable is trusted local code resolved from `PATH`. +- Guarded execution merges stderr into stdout before applying visible limits. +- PostToolUse budgeting is best-effort and depends on the host's hook contract. +- Artifacts may contain credentials, private source, or sensitive logs. +- Artifact and budget files persist until the operator removes them; no + automatic retention or quota is included. + +Read [Security](./SECURITY.md) before using the plugin with sensitive output. + +## Ecosystem + +RTK Codex Plugin is an optional edge component. Codez does not require it, and +the plugin does not require Teledex or Pitlane. See +[Stack fit](./docs/stack.md) for dependency direction and the conservative +multi-plugin ordering recommendation. + +## Documentation + +| Document | Purpose | +| -------------------------------------------- | ------------------------------------------------------------------- | +| [Install](./docs/install.md) | Pinned installation, activation, verification, updates, and removal | +| [Architecture](./docs/architecture.md) | Hook sequence, decision flow, state, and trust boundaries | +| [Configuration](./docs/configuration.md) | Environment variables, defaults, clamps, and storage paths | +| [Compatibility](./docs/compatibility.md) | Platform and runtime contract | +| [Troubleshooting](./docs/troubleshooting.md) | Discovery, rewrite, artifact, and platform diagnostics | +| [Stack fit](./docs/stack.md) | Optional ecosystem relationships | +| [Security](./SECURITY.md) | Trusted-code model, sensitive artifacts, and reporting | +| [Contributing](./CONTRIBUTING.md) | Development and verification expectations | +| [Changelog](./CHANGELOG.md) | Release history | -- [Install](./docs/install.md) -- [Compatibility](./docs/compatibility.md) -- [Stack Fit](./docs/stack.md) +## License -## Notes +Released under the [MIT License](./LICENSE). -- `rtk` rewrite is optional; install `rtk` separately when you want rewrite mode. -- output guarding stays active without `rtk` -- the plugin is intentionally shell-hook-only; gateway/session behavior belongs - in higher-level tools +Copyright (c) 2026 Mykhailo Yarytskyi and contributors. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..b00d008 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,109 @@ +# Security Policy + +RTK Codex Plugin is trusted local hook code. It can inspect and replace shell +tool input, observe tool output supplied by the runtime, call a local +executable, and persist raw text to disk. It is a context-budget guardrail, not +a sandbox, approval system, command sanitizer, secret scanner, or +data-loss-prevention boundary. + +## Supported versions + +Security fixes target the latest tagged release and the current default branch. + +| Version | Supported | +| -------------- | ---------------------------------------- | +| Latest release | Yes | +| Default branch | Yes | +| Older releases | No separate long-term support commitment | + +## Reporting a vulnerability + +Use a +[private GitHub security advisory](https://github.com/mmmihaeel/rtk-codex-plugin/security/advisories/new) +for sensitive issues. Include: + +- affected release or commit; +- runtime and Python versions; +- operating environment; +- minimal reproduction; +- whether the issue affects PreToolUse, guarded execution, PostToolUse, or + artifact state; +- expected and observed impact. + +Do not attach real credentials, private source, raw production artifacts, or +active exploit data to a public issue. + +## Trusted-code model + +Enabling the plugin expands the runtime's trusted computing base: + +- the hook scripts execute with the runtime user's permissions; +- the optional `rtk` executable is resolved from `PATH` and trusted; +- an accepted RTK replacement can change command semantics; +- a guard wrapper can change process shape and merge stderr into stdout; +- local plugin updates change executable behavior. + +Pin reviewed release tags, protect the installation directory, and control +`PATH`. Runtime approvals and sandbox policy must remain enabled independently. + +## Command boundaries + +The pre-hook rejects obviously unsuitable RTK output such as control characters, +shell-control markers, and oversized replacements. Those are syntactic checks, +not a proof of safety or semantic equivalence. + +When the pre-execution guard is selected, the wrapped command runs through the +POSIX shell. Depending on the host runtime, approval or logging surfaces may see +the Python/Base64 wrapper rather than the original command. Operators should +not treat the wrapper as authorization. + +## Sensitive artifacts + +Artifacts may contain: + +- credentials or tokens printed by commands; +- private source code; +- logs and personal data; +- prompts, tool responses, or infrastructure details. + +The plugin requests `0700` directories and `0600` files on POSIX, but +permissions are best-effort and filesystem-dependent. Artifacts: + +- are not encrypted; +- have no automatic expiry; +- have no size quota; +- persist after plugin uninstall; +- must not be uploaded without review. + +Use `RTK_CODEX_ARTIFACT_DIR` and `RTK_CODEX_BUDGET_DIR` to place state on an +appropriate protected filesystem. Review the resolved paths before manual +cleanup. + +SHA-256 in a compact summary identifies the stored bytes. It does not prove +authenticity, encrypt the content, or prevent later modification. + +## Host truncation + +PostToolUse preserves the complete string supplied in `tool_response` when +compaction succeeds. If the runtime, shell adapter, transport, or another hook +truncated content earlier, the plugin cannot recover it. + +## Bypass + +`RTK_CODEX_BYPASS=1` intentionally disables both rewrite/guard selection and +PostToolUse compaction for recognized command/stream forms. Use it narrowly: +raw output may be large or sensitive and becomes model-visible under the host +runtime's normal handling. + +## Platform boundary + +The complete `v0.1.0` plugin requires Python 3.11+ on POSIX. Native Windows is +unsupported. Run under WSL2 instead of attempting to weaken or replace POSIX +locking and executable-script assumptions without a reviewed code change. + +## Release verification + +Download releases only from the +[GitHub releases page](https://github.com/mmmihaeel/rtk-codex-plugin/releases) +and verify `SHA256SUMS`. Checksums provide transport integrity, not a signature +or reproducible-build attestation. diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..d49d307 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,208 @@ +# Architecture + +RTK Codex Plugin is a two-stage hook pipeline around a runtime-owned shell +execution. PreToolUse can replace the command input; PostToolUse can emit +compact model feedback with an artifact reference for oversized output. The +plugin does not execute the normal command itself unless it deliberately +selects the bounded pre-execution guard. + +## System context + +```mermaid +flowchart LR + accTitle: RTK Codex Plugin system context + accDescr: A compatible agent runtime sends shell requests through PreToolUse, executes the selected command under its own approval and sandbox policy, then sends the response through PostToolUse. The plugin may call a local RTK executable and write local state with best-effort restrictive permissions. + + Agent["Agent"] --> Runtime["Compatible agent runtime"] + + subgraph Plugin["RTK Codex Plugin"] + Pre["PreToolUse classifier"] + Guard["Bounded output guard"] + Post["PostToolUse budgeter"] + end + + Runtime --> Pre + Pre -. "optional rewrite request" .-> RTK["Local rtk CLI"] + Pre --> Runtime + Runtime --> Guard + Guard --> Shell["POSIX shell"] + Shell --> Guard + Guard --> Runtime + Runtime --> Tools["Other shell and local tool paths"] + Tools --> Runtime + Runtime --> Post + Post --> Runtime + Guard --> State["Local artifact state"] + Post --> State +``` + +Approvals and sandboxing remain owned by the host runtime. The plugin is not a +policy engine. + +## Request sequence + +```mermaid +sequenceDiagram + accTitle: RTK Codex Plugin request sequence + accDescr: A compatible runtime asks the pre-hook to classify a command, executes the original, rewritten, or guarded form, then lets the post-hook preserve or compact the response. + + participant Agent + participant Runtime + participant Pre as PreToolUse hook + participant RTK as Optional rtk CLI + participant Shell + participant Post as PostToolUse hook + participant State as Local state + + Agent->>Runtime: Shell command + Runtime->>Pre: PreToolUse payload + + alt Recognized risky inspection + Pre-->>Runtime: Guard-wrapper command + else Eligible simple command and rtk available + Pre->>RTK: rtk rewrite command + RTK-->>Pre: Replacement or no rewrite + Pre-->>Runtime: Updated input or no change + else Pass-through or bypass + Pre-->>Runtime: No change + end + + Runtime->>Shell: Execute selected command + Shell-->>Runtime: Tool response + Runtime->>Post: PostToolUse payload + + alt Response exceeds budget and summary is smaller + Post->>State: Store response received by hook + State-->>Post: Path and SHA-256 + Post-->>Runtime: Compact summary + else Response stays within budget + Post-->>Runtime: No change + end + + Runtime-->>Agent: Model-visible result +``` + +## Components + +| Component | Input | Output | Responsibility | +| --------------------------- | ---------------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------- | +| `.codex-plugin/plugin.json` | Plugin discovery | Manifest metadata and paths | Points the runtime at hooks and the bundled skill | +| `hooks/hooks.json` | Runtime hook registry | Matchers and commands | Binds supported tool names to PreToolUse and PostToolUse | +| `rtk-codex-hook` | PreToolUse JSON | No change or `updatedInput` JSON | Classifies commands, selects guard paths, and validates optional RTK rewrites | +| `rtk-output-guard` | Base64-encoded command | Bounded merged output plus optional artifact metadata | Runs recognized risky inspection shapes and preserves the merged stream when truncation occurs | +| `rtk-output-post-hook` | PostToolUse JSON | No change or compact feedback | Applies byte/line/turn budgets and stores the response received by the hook | +| Artifact state | Raw output text | Local file and SHA-256 | Preserves content omitted from the model-facing summary | +| Budget state | Session/turn counters | JSON and lock files | Tracks best-effort aggregate visible output | + +## PreToolUse decision flow + +The pre-hook accepts `tool_input.command` or `tool_input.cmd` for the manifest's +supported shell tool names. + +```mermaid +flowchart TD + accTitle: PreToolUse classification + accDescr: The classifier first honors explicit bypass, then selects a bounded guard for recognized risky inspections, preserves deliberate pass-through commands, or asks an optional RTK executable for a rewrite. Invalid rewrites are ignored. + + Start["Receive command"] --> Bypass{"Explicit bypass?"} + Bypass -->|"Yes"| Keep["Keep original command"] + Bypass -->|"No"| Risky{"Recognized risky line-limited inspection?"} + Risky -->|"Yes"| Wrap["Return guard wrapper"] + Risky -->|"No"| Pass{"Pass-through family or shell control?"} + Pass -->|"Yes"| Keep + Pass -->|"No"| Available{"rtk available on PATH?"} + Available -->|"No"| Keep + Available -->|"Yes"| Rewrite["rtk rewrite command"] + Rewrite --> Valid{"Non-empty, changed, at most 16 KiB, no control bytes or shell-control markers?"} + Valid -->|"No"| Keep + Valid -->|"Yes"| Replace["Return updated command"] +``` + +The RTK subprocess receives the command as one argument, has a four-second +timeout, and may signal a usable result with exit code `0` or `3`. Missing, +timed-out, undecodable, oversized, or syntactically rejected results leave the +original command unchanged. + +This is a syntactic guard, not proof that a returned command is semantically +safe. + +## Bounded pre-execution guard + +Recognized line-limited inspection pipelines, direct `head`/`tail`/`sed` +limiters over JSON, JSONL, NDJSON, or log files, and +`codex debug prompt-input` can be wrapped with a Python helper. The wrapper: + +- decodes the selected command from Base64; +- executes it through the POSIX shell; +- merges stderr into stdout; +- shows at most 4 KiB of each line body by default; +- shows at most 64 KiB of response body by default; +- propagates the child process exit code; +- stores the complete merged stream only when truncation occurs. + +Status notices and artifact metadata are emitted in addition to the nominal +64 KiB visible body, so that value is not a strict upper bound on every byte +written by the wrapper. + +## PostToolUse budgeting + +The post-hook evaluates the first matching condition: + +1. known human-facing/stream/parallel output exceeds 5 KiB; +2. any string output exceeds 12 KiB; +3. output exceeds 300 lines; +4. adding the output would exceed the best-effort 32 KiB turn budget. + +It then writes the received response to a local artifact and tries progressively +smaller head/tail summaries. Compact feedback is emitted only when the summary +saves at least 512 bytes or is no more than 90% of the received response. +Otherwise the new artifact is removed and the hook emits no change. + +On successful compaction, the hook writes the summary to stderr and exits with +the hook feedback code `2`. A compatible runtime must interpret that contract +as compact model feedback and expose it appropriately to the model. + +## State lifecycle + +```mermaid +stateDiagram-v2 + [*] --> Received + Received --> Unchanged: Within budgets + Received --> ArtifactWritten: Budget exceeded + ArtifactWritten --> Compacted: Summary is materially smaller + ArtifactWritten --> ArtifactRemoved: Summary is not smaller + Compacted --> Persisted + ArtifactRemoved --> Unchanged + Persisted --> [*]: Manual retention only + Unchanged --> [*] +``` + +Artifacts, budget counters, lock files, and stream-bypass markers have no +automatic expiry. The aggregate turn budget is best-effort: its pre-check is +not locked, state failures leave output unchanged, and concurrent hooks can +race. + +## Trust boundaries + +| Boundary | Consequence | Operator responsibility | +| ---------------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------- | +| Runtime to plugin | Hook code can observe and alter commands and output | Install only reviewed versions | +| Plugin to `rtk` | The first matching executable on `PATH` is trusted | Pin and verify the RTK distribution and `PATH` | +| Guard to shell | Guarded commands run through `shell=True` with merged stderr/stdout | Do not treat the wrapper as a sandbox | +| Runtime to PostToolUse | The plugin sees only the response supplied by the host | Do not claim recovery of earlier host truncation | +| Plugin to local state | Raw artifacts may contain sensitive content | Restrict paths, review permissions, and clean up manually | +| Summary to model | Artifact paths and hashes become model-visible | Do not expose paths that reveal sensitive host structure unnecessarily | + +## Compatibility boundary + +Full behavior requires a runtime that implements: + +- `.codex-plugin/plugin.json` discovery; +- `${PLUGIN_ROOT}` expansion; +- hook matchers from `hooks/hooks.json`; +- PreToolUse `updatedInput` replacement; +- PostToolUse string feedback and exit-code-`2` handling; +- the listed shell, stream, and parallel tool identifiers. + +Support in one Codex-derived runtime does not automatically prove compatibility +with every other runtime. See [Compatibility](./compatibility.md). diff --git a/docs/compatibility.md b/docs/compatibility.md index 5b5a458..a4c7867 100644 --- a/docs/compatibility.md +++ b/docs/compatibility.md @@ -1,52 +1,124 @@ # Compatibility -The plugin is intended for Codex-compatible runtimes that support: - -- plugin manifests via `.codex-plugin/plugin.json`; -- hook declarations via `hooks/hooks.json`; -- `PreToolUse` and `PostToolUse` hooks for shell/Bash or compatible - `exec_command` tool calls; -- `${PLUGIN_ROOT}` expansion in hook commands. - -Known integration layers: - -- [Codez](https://github.com/mmmihaeel/codez) is the recommended public runtime - layer when you want plugin hooks plus token-aware context behavior. -- Other Codez/Codex-compatible runtimes can execute the hook directly if they - support plugin-loaded `PreToolUse` shell hooks. -- Telegram or remote-worker gateways can sync the plugin to worker machines, - but no gateway is required for local usage. [Teledex](https://github.com/mmmihaeel/teledex) - is the Codez-first Telegram gateway layer; its full mode is optimized for - Codez App Server v2, while upstream `codex exec --json` is legacy - compatibility only. - -`rtk` command rewrite requires the `rtk` binary in `PATH`. Output guarding does -not require `rtk`. - -## Pass-Through Policy - -The hook avoids rewriting commands where exact output is expected: - -- tests and package-manager check commands -- build commands -- direct `rg`/`grep` searches, including regex-like patterns -- Docker commands -- machine-readable modes such as JSON, porcelain, counts, and file lists -- interactive commands -- binary-ish output commands -- shell-control forms that are not recognized risky inspection pipelines - -Recognized JSONL, log, and prompt-input inspection shapes are guarded before -execution so a single long line cannot dominate the context window. Larger -model-visible output is compacted after execution with a local artifact path -and hash, including pass-through command families such as standalone -`jq`/JSON-style commands, Docker/SSH output, build/test output, Git path -streams, `write_stdin` stream output, and parallel-wrapper output when the -runtime exposes them through `PostToolUse`. Set `RTK_CODEX_BYPASS=1` when raw -model-visible output must be preserved above the caps. - -## Dependency Boundary - -RTK does not require Teledex. It only requires a Codex-compatible runtime that -supports plugin-loaded `PreToolUse` shell hooks. Teledex can install or sync -RTK for workers, but gateway/session behavior stays outside this plugin. +RTK Codex Plugin is designed for Codez and runtimes that implement the same +plugin and hook contracts. A Codex-derived name alone is not a compatibility +guarantee. + +## Platform matrix + +| Environment | `v0.1.0` status | Notes | +| -------------------- | ------------------------- | ----------------------------------------------------------------------------------------- | +| Ubuntu / Linux POSIX | Verified | GitHub Actions and the complete test suite | +| Ubuntu on WSL2 | Verified | Complete test suite run locally | +| macOS | Expected, not CI-verified | Required POSIX APIs are available, but this release has no macOS CI evidence | +| Native Windows | Unsupported | `fcntl`, POSIX shell syntax, executable shebangs, and file-mode expectations are required | +| Containers | Environment-dependent | Works when Python 3.11+, POSIX tools, writable state, and runtime hooks are present | + +Python 3.11+ is required because the hooks use `datetime.UTC`; the PostToolUse +budget lock also depends on `fcntl`. + +## Runtime contract + +Full functionality requires: + +- `.codex-plugin/plugin.json` discovery; +- `hooks/hooks.json` loading; +- `${PLUGIN_ROOT}` expansion; +- executable command hooks; +- PreToolUse `updatedInput` replacement; +- PostToolUse response feedback from stderr with exit code `2`; +- string `tool_response` payloads for output compaction. + +Manifest matchers cover: + +| Stage | Tool identifiers | +| ----------- | --------------------------------------------------------------------------------------------- | +| PreToolUse | `Bash`, `exec_command`, `functions.exec_command` | +| PostToolUse | PreToolUse identifiers plus `write_stdin`, `functions.write_stdin`, `multi_tool_use.parallel` | + +The scripts can recognize selected namespaced `exec_command` forms internally, +but the runtime invokes only identifiers matched by the manifest. + +## Codez relationship + +[Codez](https://github.com/mmmihaeel/codez) is the primary documented runtime +because it exposes compatible plugin discovery, PreToolUse input replacement, +PostToolUse handling, and `hooks/list`. + +The RTK repository verifies the hook scripts in isolation. It does not currently +contain a cross-repository live installation test against a tagged Codez +release, so compatibility is an interface-level claim rather than an +end-to-end certification. + +## Optional RTK interface + +Rewrite mode expects: + +```text +rtk rewrite +``` + +Contract: + +- executable name: `rtk` on `PATH`; +- accepted exit codes: `0` and `3`; +- output: UTF-8 replacement command on stdout; +- timeout: four seconds; +- maximum accepted replacement: 16 KiB; +- control characters and shell-control markers: rejected. + +No provider, distribution, or minimum RTK version is bundled or attested by +this repository. Missing or rejected RTK output preserves the original command. + +## PreToolUse policy + +The classifier broadly preserves the original command for: + +- shell-control or multi-command forms, except recognized bounded inspection + pipelines; +- tests and builds; +- direct Git, JQ, `rg`, `grep`, and `find`; +- JSON, porcelain, count, list, and other machine-readable modes; +- Docker, interactive, live-control, and binary-output commands; +- recognized Pitlane navigation shapes. + +Recognized line-limited inspection pipelines, direct risky-file limiters, and +`codex debug prompt-input` can be wrapped by the bounded guard before those +general pass-through rules. + +Pass-through applies only to the command. Large output from these families can +still be compacted after execution. + +## PostToolUse contract + +The hook operates only on a non-empty string `tool_response`. It can preserve +the complete text received from the runtime in a local artifact, but cannot +recover content truncated before PostToolUse. + +Successful compaction requires: + +- a configured threshold to be exceeded; +- a summary materially smaller than the received response; +- a runtime that interprets exit code `2` and stderr as compact model feedback. + +Aggregate accounting is best-effort rather than a strict concurrency-safe +quota. + +## External integrations + +- No Teledex or gateway is required. +- Pitlane is optional and independently released. +- Loading RTK before Pitlane is the recommended order for their documented + classifier responsibilities, but no cross-plugin end-to-end test is claimed. + +See [Stack fit](./stack.md). + +## Release scope + +`v0.1.0` publishes a POSIX source/plugin archive. It does not publish: + +- a native Windows package; +- a PyPI or npm package; +- an RTK executable; +- a Codez runtime; +- a signed or reproducible-build attestation. diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..e363bb0 --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,164 @@ +# Configuration + +RTK Codex Plugin has two configuration layers: + +1. runtime feature/plugin activation in the Codex configuration; +2. process environment variables controlling bypass, output budgets, and state + locations. + +## Runtime activation + +```toml +[features] +plugins = true +plugin_hooks = true + +[plugins."rtk-codex-plugin@github"] +enabled = true +``` + +The plugin key is installation-source-specific. Confirm the effective key and +hook definitions through the runtime's plugin or `hooks/list` inspection +surface. + +## Canonical bypass + +Use `RTK_CODEX_BYPASS=1` when exact model-visible output is required: + +```bash +RTK_CODEX_BYPASS=1 command-that-must-remain-raw +``` + +The assignment must be part of the command environment in a position recognized +by the classifier, or set in the hook process environment. Unset the variable +to resume normal behavior; do not rely on `=0` because pre- and post-hook +parsing intentionally differs. + +Accepted process-level disable aliases: + +| Variable | Intended use | +| ------------------------ | ------------------------------------ | +| `RTK_CODEX_BYPASS` | Canonical per-command/session bypass | +| `RTK_CODEX_HOOK_DISABLE` | Disable this plugin's hook behavior | +| `RTK_DISABLE` | Compatibility disable alias | +| `RTK_DISABLED` | Compatibility disable alias | + +Pass-through is not a bypass. It preserves the original command before +execution, while PostToolUse may still compact oversized output. + +## PostToolUse budgets + +All byte values count UTF-8 bytes. + +| Variable | Default | Accepted range | Meaning | +| ------------------------------------------ | ------: | --------------: | -------------------------------------------------------------------------------------------------------------- | +| `RTK_CODEX_HUMAN_OUTPUT_BYTES` | 5,120 | 1,024–1,048,576 | Threshold for known human-facing, stream, parallel, build/test, shell-control/pipeline, and live-output shapes | +| `RTK_CODEX_VISIBLE_OUTPUT_BYTES` | 12,288 | 1,024–1,048,576 | General single-response threshold | +| `RTK_CODEX_VISIBLE_OUTPUT_LINES` | 300 | 20–10,000 | General line-count threshold | +| `RTK_CODEX_AGGREGATE_VISIBLE_OUTPUT_BYTES` | 32,768 | 0–4,194,304 | Best-effort per-turn visible budget; `0` disables aggregate accounting | +| `RTK_CODEX_SUMMARY_HEAD_BYTES` | 4,096 | 512–32,768 | Preferred head excerpt size | +| `RTK_CODEX_SUMMARY_TAIL_BYTES` | 2,048 | 256–32,768 | Preferred tail excerpt size | + +Values outside the accepted range are clamped. Invalid integers fall back to +their defaults. + +Example: + +```bash +export RTK_CODEX_HUMAN_OUTPUT_BYTES=8192 +export RTK_CODEX_VISIBLE_OUTPUT_BYTES=24576 +export RTK_CODEX_AGGREGATE_VISIBLE_OUTPUT_BYTES=65536 +``` + +The summary builder may reduce the configured head/tail excerpt further when +needed to ensure the compact feedback is materially smaller than the received +response. + +## Fixed PreToolUse guard limits + +The current plugin release does not expose environment overrides for the guard +selected by `rtk-codex-hook`. + +| Control | Value | +| --------------------------- | -----: | +| Visible bytes per line body | 4,096 | +| Visible output body | 65,536 | + +The guard emits status and artifact-reference text beyond the visible body +budget. + +## Optional RTK contract + +Command rewrite activates only when an executable named `rtk` is found on +`PATH`. The required interface is: + +```text +rtk rewrite +``` + +The plugin: + +- waits at most four seconds; +- accepts exit code `0` or `3`; +- reads a UTF-8 replacement from stdout; +- rejects empty, unchanged, control-containing, shell-control, or over-16-KiB + replacements; +- leaves the original command unchanged on missing, timed-out, invalid, or + rejected output. + +The plugin does not pin or install an RTK distribution. The operator owns that +executable's provenance and version. + +## State locations + +### Artifacts + +Resolution order: + +1. `RTK_CODEX_ARTIFACT_DIR`; +2. `$XDG_STATE_HOME/rtk-codex-plugin/artifacts`; +3. `~/.local/state/rtk-codex-plugin/artifacts`. + +Pre-execution guard artifacts use an additional `pretool/` directory unless an +explicit override is set. PostToolUse artifacts use: + +```text +///--.txt +``` + +### Budget and bypass state + +Resolution order: + +1. `RTK_CODEX_BUDGET_DIR`; +2. `$XDG_STATE_HOME/rtk-codex-plugin/budgets`; +3. `~/.local/state/rtk-codex-plugin/budgets`. + +This directory can contain: + +- `-.json` counters; +- matching `.lock` files; +- `stream-bypass/` marker files. + +Example isolated configuration: + +```bash +export RTK_CODEX_ARTIFACT_DIR="$PWD/.rtk-state/artifacts" +export RTK_CODEX_BUDGET_DIR="$PWD/.rtk-state/budgets" +``` + +Do not place those directories in a tracked repository. + +## Permissions and retention + +The plugin requests `0700` for state directories and `0600` for files on POSIX, +but enforcement is best-effort and depends on the filesystem. Files are not +encrypted. + +There is no automatic retention, quota, or cleanup. Artifacts can contain +credentials, private source, logs, prompts, or other sensitive data. Inspect +the exact configured root before deleting anything, and never upload the state +directory blindly. + +See [Security](../SECURITY.md) and +[Troubleshooting](./troubleshooting.md). diff --git a/docs/install.md b/docs/install.md index 8fb7ac3..5d3c640 100644 --- a/docs/install.md +++ b/docs/install.md @@ -1,18 +1,70 @@ # Install -This plugin expects a Codex-compatible runtime that supports plugin manifests -and `PreToolUse` hooks. +Install RTK Codex Plugin inside the same POSIX environment that runs the agent +runtime. -Clone the plugin into the plugin cache used by your runtime. One common cache -layout is: +## Prerequisites + +- Python 3.11 or later; +- Linux, WSL2, or another compatible POSIX environment; +- Git for the pinned-clone path, or `tar` for the release archive; +- a runtime implementing the required plugin and hook contracts; +- optional: a compatible `rtk` executable on `PATH` for command rewriting. + +Native Windows is not supported in `v0.1.0`. On Windows, open WSL2 and perform +the clone, extraction, configuration, and runtime launch inside Linux. + +## Option 1: pinned Git installation + +```bash +python3 --version + +codex_home="${CODEX_HOME:-$HOME/.codex}" +plugin_dir="$codex_home/plugins/cache/github/rtk-codex-plugin/local" + +git clone --branch v0.1.0 --depth 1 \ + https://github.com/mmmihaeel/rtk-codex-plugin.git \ + "$plugin_dir" + +test -x "$plugin_dir/hooks/rtk-codex-hook" +test -x "$plugin_dir/hooks/rtk-output-guard" +test -x "$plugin_dir/hooks/rtk-output-post-hook" +``` + +Cloning a release tag avoids silently moving with `main`. + +## Option 2: release archive + +Download `rtk-codex-plugin-v0.1.0.tar.gz` and `SHA256SUMS` from the +[v0.1.0 release](https://github.com/mmmihaeel/rtk-codex-plugin/releases/tag/v0.1.0). ```bash +sha256sum -c SHA256SUMS + codex_home="${CODEX_HOME:-$HOME/.codex}" -git clone https://github.com/mmmihaeel/rtk-codex-plugin \ - "$codex_home/plugins/cache/github/rtk-codex-plugin/local" +plugin_dir="$codex_home/plugins/cache/github/rtk-codex-plugin/local" + +mkdir -p "$plugin_dir" +tar -xzf rtk-codex-plugin-v0.1.0.tar.gz \ + --strip-components=1 \ + -C "$plugin_dir" + +test -x "$plugin_dir/hooks/rtk-codex-hook" ``` -Enable plugin support in your Codex config: +The release uses a POSIX tar archive so LF endings and executable modes are +preserved. If the executable checks fail: + +```bash +chmod 0755 \ + "$plugin_dir/hooks/rtk-codex-hook" \ + "$plugin_dir/hooks/rtk-output-guard" \ + "$plugin_dir/hooks/rtk-output-post-hook" +``` + +## Activate the plugin + +Add the matching plugin key to the runtime configuration: ```toml [features] @@ -23,10 +75,95 @@ plugin_hooks = true enabled = true ``` -If your runtime assigns a different marketplace or local plugin key, enable the -key that matches its cache layout. +The exact key depends on the runtime and installation source. Restart or reload +the runtime after changing plugin configuration. + +If the runtime exposes App Server hook inspection, call `hooks/list` for the +current working directory and confirm both stages are discovered: + +- PreToolUse: `rtk-codex-hook`; +- PostToolUse: `rtk-output-post-hook`. + +## Verify the checkout + +From the plugin directory: + +```bash +python3 -m json.tool .codex-plugin/plugin.json >/dev/null +python3 -m json.tool hooks/hooks.json >/dev/null +python3 tests/test_rtk_codex_hook.py +``` + +Expected public-suite result: + +```text +Ran 50 tests +OK (skipped=1) +``` + +The intentional skip covers a private projection exporter that is not included +in the public repository. + +## Guard-only operation + +No separate RTK install is required for the recognized pre-execution output +guard or PostToolUse compaction. Without `rtk` on `PATH`, eligible rewrite +requests simply keep their original command. + +For rewrite mode, verify only the interface this plugin consumes: + +```bash +command -v rtk +rtk rewrite 'example command' +``` + +The plugin does not install, pin, or attest the external executable. + +## Update + +For a tag-based clone: + +```bash +cd "$plugin_dir" +git fetch --tags origin +git checkout v0.1.0 +``` + +Replace `v0.1.0` with a reviewed newer release tag. Read the changelog and rerun +the test suite before enabling the new version. + +## Roll back or uninstall + +Disable the plugin in runtime configuration first: + +```toml +[plugins."rtk-codex-plugin@github"] +enabled = false +``` + +Restart the runtime, then move the checkout to a reversible backup: + +```bash +mv "$plugin_dir" "${plugin_dir}.disabled-v0.1.0" +``` + +Artifact and budget state is stored separately and is intentionally not removed +by uninstalling the plugin. Review +[Configuration](./configuration.md#state-locations) and +[Security](../SECURITY.md) before cleaning that data. + +## Development checkout + +Contributors can track `main` in a separate development path: + +```bash +git clone https://github.com/mmmihaeel/rtk-codex-plugin.git +cd rtk-codex-plugin +python3 tests/test_rtk_codex_hook.py +``` -`rtk` is optional. If it is missing, rewrite mode is skipped and bounded-output -guarding still works for recognized risky command shapes. +Do not point production plugin configuration at a moving development checkout +without an intentional update policy. -No Teledex or gateway install is required for local plugin usage. +See [Troubleshooting](./troubleshooting.md) for hook discovery, line endings, +and platform diagnostics. diff --git a/docs/stack.md b/docs/stack.md index fef2a47..88ce736 100644 --- a/docs/stack.md +++ b/docs/stack.md @@ -1,39 +1,55 @@ # Stack Fit -`rtk-codex-plugin` is useful as a standalone Codex-compatible plugin, but it is -also designed to sit in a larger local-agent stack. - -## Part of the Codez stack - -The Codez stack is modular. Each layer can be used on its own unless a higher -layer explicitly opts into it. - -| Layer | Public surface | Responsibility | Dependency | -| --- | --- | --- | --- | -| [Codez](https://github.com/mmmihaeel/codez) | Codex-compatible runtime | App Server v2, goal RPC, long-session hardening, prompt pruning, and plugin hooks | Does not require Teledex | -| [RTK Codex Plugin](https://github.com/mmmihaeel/rtk-codex-plugin) | Optional Codex plugin | Shell/token safety through `rtk rewrite` and bounded output guarding | Requires a Codex-compatible plugin-hook runtime; does not require Teledex | -| [Pitlane Codex Plugin](https://github.com/mmmihaeel/pitlane-codex-plugin) | Optional Codex plugin | Code-navigation/token-saving rewrites through a host-local `pitlane` CLI | Requires a Codex-compatible plugin-hook runtime and local `pitlane`; does not require Teledex | -| [Teledex](https://github.com/mmmihaeel/teledex) | Telegram gateway/session layer | Topics, queues, live steer, `/goal` UX, and delivery/recovery around durable agent sessions | Full mode is optimized for Codez App Server v2; upstream `codex exec --json` is legacy compatibility only | - -The plugin does not own sessions, chat delivery, host registries, or project -metadata. It only handles shell command rewrite and bounded output at the hook -layer. - -## Plain Version - -Codez runs the agent. RTK makes risky shell output safer and smaller. Pitlane -makes routine code browsing smaller by replacing safe source reads with indexed -CLI calls. Teledex is the Telegram/session gateway that can drive a runtime, -but it is not part of the Codez runtime itself. - -RTK does not require Codez, Pitlane, or Teledex. Codez is linked because it has -a clean public repository and is the recommended runtime when you want plugin -hooks plus token-aware context behavior. Teledex is linked as the Codez-first -Telegram gateway layer; it can install or sync RTK for workers, but RTK remains -usable without any gateway. - -## Plugin Order - -When RTK and Pitlane are both enabled, load RTK before Pitlane. RTK handles -general shell-output safety; Pitlane then wins only for the narrow -code-navigation commands it accepts. +RTK Codex Plugin is an optional edge component in the Codez ecosystem. It owns +shell request classification and model-visible output budgeting; it does not +own the runtime, gateway, or indexed navigation service. + +```mermaid +flowchart TB + accTitle: RTK Codex Plugin ecosystem position + accDescr: Codez can load RTK and Pitlane as optional local plugins. Teledex may drive Codez as an external gateway. RTK has no dependency on the gateway or the Pitlane plugin. + + Teledex["Teledex
optional gateway"] -. "JSON-RPC client" .-> Codez["Codez
agent runtime"] + RTK["RTK Codex Plugin
rewrite and output budgets"] -. "optional hooks" .-> Codez + Pitlane["Pitlane Codex Plugin
indexed navigation rewrites"] -. "optional hooks" .-> Codez + RTK -. "optional local executable contract" .-> RTKCLI["rtk CLI"] +``` + +## Responsibilities + +| Project | Owns | Does not own | +| ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | +| [Codez](https://github.com/mmmihaeel/codez) | Agent runtime, tool policy, App Server, plugin execution | RTK-specific classification or gateway delivery | +| [RTK Codex Plugin](https://github.com/mmmihaeel/rtk-codex-plugin) | Optional command rewrite adapter, bounded inspection wrapper, PostToolUse output budgets | Sandboxing, approvals, sessions, Telegram delivery, or RTK distribution | +| [Pitlane Codex Plugin](https://github.com/mmmihaeel/pitlane-codex-plugin) | Optional indexed source-navigation rewrites | General output budgeting or runtime policy | +| [Teledex](https://github.com/mmmihaeel/teledex) | Telegram transport, session routing, queueing, and recovery | Runtime command policy or plugin implementation | + +## Dependency direction + +- RTK Codex Plugin requires only a compatible hook runtime and Python 3.11+ on + POSIX. +- Codez does not require RTK. +- RTK does not require Pitlane or Teledex. +- Teledex may provision plugins for workers, but gateway operation remains + outside this repository. +- The optional `rtk` executable is a separate local dependency resolved from + `PATH`. + +## Multi-plugin order + +When both RTK and Pitlane are enabled, loading RTK before Pitlane is the +recommended integration order: + +1. RTK handles its general command and output-budget responsibilities. +2. Pitlane may claim the narrow indexed-navigation forms it recognizes. + +RTK classifier tests preserve documented Pitlane-owned navigation shapes, but +this repository does not contain a cross-plugin end-to-end test. Treat the +ordering as an integration recommendation, then verify it against the exact +plugin releases installed. + +## Security boundary + +Every enabled hook is trusted local code. Plugins can inspect or alter tool +input and output, but they do not replace Codez approvals, sandboxing, or host +access control. See [Security](../SECURITY.md). diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md new file mode 100644 index 0000000..8a976ff --- /dev/null +++ b/docs/troubleshooting.md @@ -0,0 +1,167 @@ +# Troubleshooting + +Start with the runtime's plugin and hook inventory, then test the hook scripts +inside the same POSIX environment as the runtime. + +## The plugin is not discovered + +Check the expected layout: + +```text +/ +├── .codex-plugin/plugin.json +├── hooks/hooks.json +├── hooks/rtk-codex-hook +├── hooks/rtk-output-guard +└── hooks/rtk-output-post-hook +``` + +Validate the manifests: + +```bash +python3 -m json.tool .codex-plugin/plugin.json >/dev/null +python3 -m json.tool hooks/hooks.json >/dev/null +``` + +Confirm both runtime features and the correct installation-specific plugin key +are enabled. If available, use App Server `hooks/list` for the target working +directory and inspect load warnings. + +## A hook is not executable + +```bash +test -x hooks/rtk-codex-hook +test -x hooks/rtk-output-guard +test -x hooks/rtk-output-post-hook +``` + +Restore POSIX modes: + +```bash +chmod 0755 hooks/rtk-codex-hook hooks/rtk-output-guard hooks/rtk-output-post-hook +``` + +If the checkout was created by native Windows Git, inspect line endings. CRLF +in a shebang script can produce a `bad interpreter` error. Clone or extract the +release inside WSL2, or convert the hook files back to LF. + +## Native Windows fails + +Native Windows is unsupported in `v0.1.0`. The complete hook pipeline requires +POSIX executable scripts, shell syntax, and `fcntl`. + +Use WSL2 and run all of the following inside Linux: + +- plugin installation; +- runtime launch; +- Python tests; +- artifact inspection. + +## A command is not rewritten + +This can be expected. PreToolUse preserves: + +- explicit bypass; +- shell-control and multi-command forms; +- tests, builds, direct search, Git, JQ, Docker, interactive, live-control, and + machine-readable commands; +- Pitlane-owned navigation shapes; +- commands when `rtk` is missing or returns an invalid replacement. + +Check the optional executable: + +```bash +command -v rtk +rtk rewrite 'the original command' +``` + +The plugin accepts only exit code `0` or `3`, waits four seconds, and rejects +empty, unchanged, oversized, control-containing, or shell-control output. + +## A pass-through command still has compacted output + +Pass-through preserves the **pre-execution command**. PostToolUse is a separate +stage and can compact large test, build, Git, JSON, Docker, SSH, stream, or +parallel output. + +For one command that genuinely needs raw model-visible output: + +```bash +RTK_CODEX_BYPASS=1 command +``` + +Unset the variable afterward. + +## Output is compacted unexpectedly + +Review the active values: + +```bash +env | grep '^RTK_CODEX_' +``` + +Defaults: + +- human-facing output: 5 KiB; +- general output: 12 KiB; +- aggregate turn output: 32 KiB; +- visible lines: 300. + +See [Configuration](./configuration.md#posttooluse-budgets) for clamps and +overrides. + +## No artifact was retained + +An artifact is intentionally removed when the generated summary is not +materially smaller than the response. For compacted output, the summary includes +the artifact path and SHA-256. + +The plugin stores only the response delivered to PostToolUse. If the host +runtime truncated content earlier, the artifact cannot restore it. + +## Find local state + +Unless overridden: + +```bash +state_home="${XDG_STATE_HOME:-$HOME/.local/state}" +find "$state_home/rtk-codex-plugin" -maxdepth 4 -type f -print +``` + +Artifacts can contain sensitive raw output and have no automatic retention. +Inspect paths and contents before any cleanup or upload. + +## PostToolUse exits with code 2 + +For this plugin, exit code `2` with a summary on stderr is the successful +compaction feedback contract. A compatible runtime should recognize that +feedback and expose the compact summary appropriately to the model. + +If the runtime treats it as a generic hook failure, that runtime does not +implement the required PostToolUse contract. + +## Tests fail on Windows + +Run the suite under Linux/WSL2: + +```bash +python3 tests/test_rtk_codex_hook.py +``` + +Direct native-Windows subprocess execution cannot launch the extensionless +POSIX hook files and does not provide `fcntl`. + +## CI passes but local execution fails + +Compare: + +- Python version (`3.11+`); +- POSIX environment; +- executable bits; +- LF line endings; +- plugin path and `${PLUGIN_ROOT}` expansion; +- filesystem permissions for artifact and budget roots; +- hook timeout behavior in the host runtime. + +For sensitive or potentially exploitable failures, follow +[Security](../SECURITY.md) instead of posting raw artifacts publicly.