Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "session-optimizer-codex",
"interface": {
"displayName": "Session Optimizer"
},
"plugins": [
{
"name": "refine-gate",
"source": {
"source": "local",
"path": "./plugins/refine-gate"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Productivity"
}
]
}
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
shellcheck --version

- name: Refine gate contract tests
run: pytest tests/test_refine_gate.py -v
run: pytest tests/test_refine_gate.py tests/test_portable_packaging.py -v

- name: Subagent tracker tests
run: pytest tests/test_subagent_usage.py -v
Expand All @@ -57,11 +57,13 @@ jobs:
run: |
python -m json.tool .claude-plugin/marketplace.json > /dev/null
python -m json.tool .claude-plugin/plugin.json > /dev/null
python -m json.tool .agents/plugins/marketplace.json > /dev/null
python -m json.tool hooks/hooks.json > /dev/null
for plugin in context-guard refine-gate statusline; do
python -m json.tool "plugins/$plugin/.claude-plugin/plugin.json" > /dev/null
python -m json.tool "plugins/$plugin/hooks/hooks.json" > /dev/null
done
python -m json.tool plugins/refine-gate/.codex-plugin/plugin.json > /dev/null
python -m json.tool plugins/statusline/assets/statusline-budget.json > /dev/null
python -m json.tool plugins/statusline/assets/ctxguard-thresholds.json > /dev/null
python -m json.tool plugins/statusline/assets/pricing.json > /dev/null
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ All notable changes to this project are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- A skills-only Codex package for `refine-gate`, exposed through a repository
marketplace at `.agents/plugins/marketplace.json`.
- Gemini CLI installation through the existing portable Agent Skill.

### Changed

- The `refine` skill now uses the portable Agent Skills frontmatter and
host-neutral wording. Claude's `UserPromptSubmit` hook and plugin manifests
are unchanged.

## [2.1.1] - 2026-07-26

Statusline only. No change to context-guard or refine-gate.
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ keeping long [Claude Code](https://code.claude.com) sessions **readable,
cheap, and un-poisoned** — shipped from one marketplace. Install exactly the
ones you want; none requires the others.

`refine-gate` is also packaged as a portable Agent Skill for Codex and Gemini
CLI. `context-guard` and `statusline` remain Claude-specific because their
behavior depends on Claude lifecycle hooks, session files, and statusline
metrics.

```
/plugin marketplace add cdeust/session-optimizer
```
Expand All @@ -17,6 +22,9 @@ ones you want; none requires the others.
| [**refine-gate**](plugins/refine-gate) | `/plugin install refine-gate@session-optimizer-marketplace` | A `UserPromptSubmit` hook + `/refine` skill that bind vague prompt references ("the SSE solution", "like before", "still broken") to concrete artifacts with evidence, then select an execution strategy from a research-backed table — before any code is touched. |
| [**statusline**](plugins/statusline) | `/plugin install statusline@session-optimizer-marketplace` | A multi-line status bar: discrete heat-track context bar tied to per-model checkpoint thresholds, one deduplicated cost ledger covering subagent spend, telemetry (tok/s, compactions, cache countdown), rate-limit gauges with burn-rate pacing, and terminal-width fitting. Ships an install skill — after installing, ask Claude to "install the statusline" and it wires everything. |

For Codex and Gemini installation commands, see the
[refine-gate README](plugins/refine-gate/README.md).

## Why

A long Claude Code session degrades in four ways as the context window fills:
Expand Down Expand Up @@ -53,6 +61,7 @@ These plugins make that discipline *visible* (statusline), *automatic*

```
.claude-plugin/marketplace.json # the marketplace (three plugins + deprecated meta shim)
.agents/plugins/marketplace.json # Codex marketplace (portable refine-gate only)
plugins/
context-guard/ # Stop guard + memory-writer agent + SubagentStop tracker
refine-gate/ # UserPromptSubmit gate + /refine skill
Expand Down
36 changes: 36 additions & 0 deletions plugins/refine-gate/.codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "refine-gate",
"version": "2.0.0",
"description": "Bind ambiguous requests to concrete evidence before an agent changes code.",
"author": {
"name": "Clement Deust",
"email": "admin@ai-architect.tools",
"url": "https://github.com/cdeust"
},
"homepage": "https://github.com/cdeust/session-optimizer/tree/main/plugins/refine-gate",
"repository": "https://github.com/cdeust/session-optimizer",
"license": "MIT",
"keywords": [
"prompt-engineering",
"intent-binding",
"evidence",
"verification"
],
"skills": "./skills/",
"interface": {
"displayName": "Refine Gate",
"shortDescription": "Ground ambiguous requests before execution",
"longDescription": "Resolve vague references to concrete artifacts, separate symptoms from goals, and define externally verifiable acceptance criteria before implementation begins.",
"developerName": "Clement Deust",
"category": "Productivity",
"capabilities": [
"Read"
],
"websiteURL": "https://github.com/cdeust/session-optimizer",
"privacyPolicyURL": "https://github.com/cdeust/session-optimizer/blob/main/PRIVACY.md",
"defaultPrompt": [
"Refine this request before changing code.",
"Bind every vague reference in this bug report."
]
}
}
35 changes: 31 additions & 4 deletions plugins/refine-gate/README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# refine-gate

A prompt-binding gate for [Claude Code](https://code.claude.com):
a `UserPromptSubmit` hook (`hooks/refine_gate.py`) plus the `/refine` skill
(`skills/refine/`).
A portable prompt-binding skill for Claude Code, Codex, and Gemini CLI. The
Claude package also includes a `UserPromptSubmit` hook
(`hooks/refine_gate.py`) that applies the `/refine` skill automatically.

Communication failures cost more than code failures: "make it work
exactly like the SSE solution" carries precise intent that the model
can bind to the wrong artifact and then build the wrong thing —
correctly. The refine gate makes that binding explicit and cheap to
correct BEFORE work starts.

## Install
## Install on Claude Code

```
/plugin marketplace add cdeust/session-optimizer
Expand All @@ -20,6 +20,28 @@ correct BEFORE work starts.
The plugin wires the `UserPromptSubmit` hook and registers the `/refine`
skill automatically. Requires Python 3.

## Install on Codex

```bash
codex plugin marketplace add cdeust/session-optimizer
codex plugin add refine-gate@session-optimizer-codex
```

Start a new Codex session, then invoke `$refine` explicitly or describe an
ambiguous implementation request that matches the skill description. The
Codex package is intentionally skills-only: it does not register the
Claude-specific hook.

## Install on Gemini CLI

```bash
gemini skills install https://github.com/cdeust/session-optimizer.git \
--path plugins/refine-gate/skills/refine
```

Confirm activation when Gemini asks for skill consent. Gemini receives the
same `SKILL.md`; automatic per-prompt gating remains specific to Claude Code.

## How it works

The hook inspects every prompt on two tiers:
Expand Down Expand Up @@ -90,6 +112,11 @@ has no hook mechanism — there, upload `skills/refine/` as an Agent
Skill (same SKILL.md format): the `/refine` procedure travels; the
automatic per-prompt gate does not.

Codex and Gemini use the portable Agent Skill. They receive the complete
binding and verification procedure, but not the Claude hook. This separation
keeps the Claude automation unchanged while avoiding unsupported hook claims
on other hosts.

## License

[MIT](../../LICENSE) © Clement Deust
38 changes: 15 additions & 23 deletions plugins/refine-gate/skills/refine/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,18 @@ description: >
prompt (terse, frustrated, ambiguous, or shorthand), resolves every vague
reference to a concrete artifact, recalls past decisions and lessons, and
compiles a verifiable execution contract BEFORE any code is touched.
Invoke as /refine <raw prompt>, or on any prompt where intent might be
misread. Prevents: solving the wrong problem, dead/unwired code,
Invoke explicitly as $refine in Codex, /refine in Claude Code, or by skill
activation in Gemini CLI whenever intent might be misread. Prevents:
solving the wrong problem, dead/unwired code,
band-aid fixes, non-scalable hot paths, unreadable output.
category: engineering
trigger: >
The user describes a task or bug in shorthand ("make it work like before",
"the X solution", "it's still broken"), references prior work without
naming files/commits, or a previous attempt missed their intent.
input: >
The raw prompt verbatim (skill args; if empty, the user's last message).
output: >
A compiled execution contract (goal, resolved references, constraints,
acceptance criteria, non-goals) — then execution under that contract.
---

## Automation

A `UserPromptSubmit` hook (`hooks/refine_gate.py`, wired by this
plugin's `hooks/hooks.json`) applies this skill automatically on two
tiers:
On Claude Code, a `UserPromptSubmit` hook (`hooks/refine_gate.py`, wired by
this plugin's `hooks/hooks.json`) applies this skill automatically on two
tiers. Codex and Gemini load the same skill explicitly or by description;
their packages do not claim to install the Claude-specific hook.

* **Tier 1 — reference markers**: prior-artifact shorthand, "exactly
as/like", repeat-failure phrasing → inject the full binding-table
Expand Down Expand Up @@ -89,7 +81,7 @@ Binding table (mandatory in the contract):
| "the sse solution" | `/api/graph/events` + `graph_event_stream.{py,js}` | recall #4197485, grep |

A load-bearing reference that cannot be bound with evidence is a STOP:
ask ONE batch of clarifying questions (AskUserQuestion, ≤3 questions,
ask ONE batch of clarifying questions (≤3 questions,
each offering the concrete candidates found). Never guess silently on
a load-bearing binding; never ask about bindings the evidence already
settles.
Expand All @@ -108,11 +100,11 @@ request, the contract's goal is a DIAGNOSIS, not a fix — say so.

### 4. Compile the constraints

Always binding (do not restate, reference): the active coding
standards — the project's CLAUDE.md / lint config, plus the user's
global rules when present (e.g. `~/.claude/rules/coding-standards.md`:
SOLID, Clean Architecture layers, size limits, no dead/unwired code,
root-cause-only fixes, local reasoning, zetetic source discipline).
Always binding (do not restate, reference): the active coding standards —
the project's `AGENTS.md`, `GEMINI.md`, `CLAUDE.md`, or lint configuration as
applicable, plus the host's active user rules. Preserve size limits, no
dead/unwired code, root-cause-only fixes, local reasoning, and any zetetic
source discipline those rules require.

Add prompt-specific constraints extracted from the user's words and
from recalled lessons (e.g. "no in-between interface" → polling/
Expand Down Expand Up @@ -200,8 +192,8 @@ After execution (or after the user corrects a binding), store the raw
phrase → correct binding pair via your memory layer's remember tool
when one is installed (e.g. `cortex:remember`, tags: ["archival",
"lesson", "prompt-binding"], agent_topic scoped), so the next session
binds it instantly; without a memory layer, note it in the project's
own records (CLAUDE.md or a docs note). Mis-bindings the user had to
binds it instantly; without a memory layer, note it in the project's own
durable instructions or documentation. Mis-bindings the user had to
correct are the highest-value memories this skill produces.

## Failure modes this skill exists to prevent
Expand Down
51 changes: 51 additions & 0 deletions tests/test_portable_packaging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""Cross-host packaging contracts for the portable refine-gate skill."""

from __future__ import annotations

import json
import re
from pathlib import Path


ROOT = Path(__file__).resolve().parent.parent
PLUGIN = ROOT / "plugins" / "refine-gate"


def _json(path: Path) -> dict:
return json.loads(path.read_text(encoding="utf-8"))


def test_codex_plugin_is_skills_only_and_points_to_real_content():
manifest = _json(PLUGIN / ".codex-plugin" / "plugin.json")

assert manifest["name"] == PLUGIN.name
assert manifest["skills"] == "./skills/"
assert (PLUGIN / manifest["skills"]).is_dir()
assert "hooks" not in manifest
assert "mcpServers" not in manifest


def test_codex_marketplace_resolves_refine_gate_from_repo_root():
marketplace = _json(ROOT / ".agents" / "plugins" / "marketplace.json")
entry = next(p for p in marketplace["plugins"] if p["name"] == "refine-gate")

assert entry["source"] == {
"source": "local",
"path": "./plugins/refine-gate",
}
assert (ROOT / entry["source"]["path"]).resolve() == PLUGIN.resolve()
assert entry["policy"] == {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL",
}
assert entry["category"] == "Productivity"


def test_refine_skill_uses_portable_agent_skills_frontmatter():
text = (PLUGIN / "skills" / "refine" / "SKILL.md").read_text(encoding="utf-8")
assert text.startswith("---\n")
frontmatter = text.split("---", 2)[1]
keys = set(re.findall(r"^([A-Za-z][A-Za-z0-9_-]*):", frontmatter, re.MULTILINE))

assert keys == {"name", "description"}
assert "name: refine" in frontmatter
Loading