Commit Graph

5 Commits

Author SHA1 Message Date
Maximilian Roos cfd6f099bc fix(codex): clear activity marker on session end (#3660)
Codex now exposes `SessionEnd`, but Worktrunk’s Codex plugin only
returned the activity marker to idle at turn end. This adds a
main-session exit hook that clears the marker, using Codex’s
three-second maximum hook timeout so cleanup has the best chance to
complete without delaying shutdown.

The CLI help, plugin-layout guidance, user documentation, generated
mirrors, metadata test, and help snapshot now describe and verify the
complete Codex lifecycle.

Tested with `cargo run -- hook pre-merge --yes` (4,564 tests passed; 1
skipped).

> _This was written by Claude Code on behalf of max_.
2026-07-29 20:57:26 -07:00
Maximilian Roos 36ba57bdca fix(plugin): ship skills to Codex installs via a generated real-file mirror (#3440)
Codex installs of the worktrunk plugin carried no skills. `codex plugin
add` copies the plugin into `$CODEX_HOME/plugins/cache/` via
`copy_dir_recursive` (codex-rs core-plugins), which handles only regular
files and directories — so the `skills -> ../../skills` symlink (and the
nested `reference/README.md` link inside the tree) were silently
dropped, and sessions load from that cache copy. Verified against
codex-cli 0.144.1 both by reading the tagged sources and by installing
this repo's plugin into a scratch `CODEX_HOME`: the installed root had
no `skills/` at all and `codex debug prompt-input` showed an empty
plugin skill inventory.

This PR cuts the plugin's `skills` symlink over to a **generated
real-file mirror** of the authored repo-root `skills/`, kept current by
a new `sync_plugin_skills_mirror` stage in `test_docs_are_in_sync`
(dereferences symlinks, deletes stale files, self-heals and fails on
drift — same pattern as the other generated mirrors). Repo-root
`skills/` stays the authored home: Gemini hard-probes it at the
extension root, the docs sync writes into it, and Windows checkouts read
it. Reversing the symlink direction instead would put a symlink at the
repo root, breaking Gemini's install copy and every Windows checkout —
which also surfaces a latent bug this fixes: symlinks materialize as
plain text files on Windows clones, so installs from a Windows checkout
shipped no skills to Claude or Codex either.

It also drops the Codex manifest's `skills: "./skills/"` key: with no
key, Codex scans `<plugin-root>/skills/` by convention
(`default_skill_roots` in `codex-rs/core-plugins/src/loader.rs`), and
the explicit path resolves to the same directory, so the key was
redundant — symmetric with the Claude manifest cutover in #3431.

**For the reviewer:**

- The 20 files under `plugins/worktrunk/skills/` are the generated
mirror (byte-identical to repo-root `skills/`; git stores shared blobs
once). `plugins/worktrunk/CLAUDE.md` → "Plugin skills are a generated
mirror" documents the rationale with codex-rs citations.
- `sync_plugin_skills_mirror` in
`tests/integration_tests/readme_sync.rs` is the sync stage (Step 3b of
the pipeline); it already proved itself once in this branch — merging
main regenerated `reference/{config,list}.md` in the mirror.
- `test_plugin_layout_is_consolidated` now pins the mirror shape
cross-platform (real directory, no symlinks anywhere under it),
replacing the unix-only symlink assertion.

**Verification:** fresh scratch-`CODEX_HOME` install now carries both
skills into the cache and `codex debug prompt-input` lists `worktrunk`
and `wt-switch-create`; `claude plugin validate` passes and `claude
--plugin-dir … plugin details` discovers Skills (2) plus all 8 hooks;
Gemini's repo-root path is untouched. A 2×2 probe matrix (manifest key
present/absent × real dir/symlink) confirmed key-absence changes nothing
and symlinks ship nothing.

> _This was written by Claude Code on behalf of max_

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 17:48:30 -07:00
Worktrunk Bot 512a94de2f feat(plugin): ship Codex-native activity hooks (#3364) 2026-07-06 23:05:15 -07:00
Maximilian Roos 233cd493d0 fix(codex): drop activity-marker hooks Codex can't drive (#2786)
The Codex plugin shipped `hooks.json` with `SessionStart`→💬,
`UserPromptSubmit`→🤖, and `Stop`→💬. But codex-cli 0.130.0's
`HookEventNameWire` schema (extracted from the binary) has **no
`Stop`/turn-end event**: `PreToolUse`, `PermissionRequest`,
`PostToolUse`, `PreCompact`, `PostCompact`, `SessionStart`,
`UserPromptSubmit`. So on Codex the 🤖 marker set at `UserPromptSubmit`
could never return to 💬 — a Codex worktree stuck at "working" for the
entire session. That's worse than the docs claimed ("rests at 💬").

This removes the marker hooks entirely until Codex exposes a turn-end
hook event. The Codex plugin now ships only the configuration skill;
activity tracking joins worktree-isolation and `/wt-switch-create` as
Claude-Code-only. A re-enablement comment (exact conditions + the files
to restore) lives in `src/commands/config/codex.rs` and a new
`CLAUDE.md` → "Codex Plugin" section, which also documents the accepted
tradeoff that the `skills/` symlink exposes the Claude-only
`wt-switch-create` skill to Codex (harmless — Codex can't act on it).

Bundled adjacent fixes: `plugin.json` metadata drift
(`description`/`longDescription` no longer claim activity hooks;
`homepage`/`websiteURL` `https://worktrunk.dev/claude-code/` →
`https://worktrunk.dev`), and the install/uninstall/`--help`/docs text
made honest about Codex having only the configuration skill.

**Reviewer navigation:** `src/commands/config/codex.rs` +
`src/cli/config.rs` (runtime + `--help` text),
`docs/content/claude-code.md` (skill ref + `llms.txt` auto-synced),
`CLAUDE.md` (new section), `tests/integration_tests/config_show.rs`
(`test_codex_plugin_metadata_is_valid_json` now asserts `hooks` absent +
guards metadata regression). Snapshot env-block churn is stale-fixture
convergence to the repo's current `/nonexistent/wt/` convention, not a
leak.

**Testing:** Full pre-merge gate green locally (3704 tests, 0 skipped;
lints clean). The metadata test was strengthened; the marker behavior
itself is removed, so there's nothing runtime-testable to add.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 15:29:54 -07:00
Maximilian Roos f00b787e1b fix(codex): relocate plugin into subdir so the marketplace resolves it (#2782)
## Problem

#2780 put `.agents/plugins/marketplace.json` at the path codex-cli
reads, but the plugin was still **uninstallable**. Driving the Codex
`/plugins` TUI surfaced the real, complete set of constraints in
codex-cli 0.130.0:

1. A plugin `source` must be the **object** form
`{"source":"local","path":"./plugins/<name>"}` — a bare string `"./"`
fails with `local plugin source path must not be empty`.
2. The path must be a **non-empty subdirectory**. Codex resolves it
relative to the marketplace root (repo root), so a repo-root plugin
(`./.codex-plugin/` at the top) can't be referenced at all — every Codex
marketplace plugin lives in
`./plugins/<name>/.codex-plugin/plugin.json`, exactly like the
OpenAI-curated marketplace.

So the plugin had to move into a subdirectory.

## Changes

- Move `.codex-plugin/` → `plugins/worktrunk/.codex-plugin/` and
`hooks/` → `plugins/worktrunk/hooks/` (a plugin-root sibling, matching
the curated layout where `skills/` and `assets/` sit beside
`.codex-plugin/`).
- `plugins/worktrunk/skills` → symlink to `../../skills` so the shared
`worktrunk` + `wt-switch-create` skills stay single-source (no
duplication; the repo still auto-syncs `skills/worktrunk/reference/`).
- Rewrite `.agents/plugins/marketplace.json` with the object `source`,
`policy.installation: "AVAILABLE"`, and `category` that Codex actually
parses.
- `plugin.json` `hooks` → `./hooks/hooks.json` (plugin-root relative).
- Update the install hint (`src/commands/config/codex.rs`), docs,
auto-synced skill reference, the validity test, and the install
snapshot.

## Verification

Verified end-to-end against codex-cli 0.130.0: repointed a local
marketplace at the worktree and drove `/plugins`. The `Worktrunk`
marketplace now appears (plugin count 123 → 124), the plugin shows as
**Available** with **both skills resolved** (`worktrunk:worktrunk`,
`worktrunk:wt-switch-create` — the symlink works), and it installs.

`test_codex_plugin_metadata_is_valid_json` now asserts the object
`source`, `policy.installation`, `interface.displayName`, and the new
paths. `test_docs_are_in_sync` and the install snapshot are updated;
full `config_show` module (119 tests) + pre-commit pass.

**Caveat (documented, not a regression):** plugin-bundled *command*
hooks remain gated by Codex's `plugin_hooks` feature flag — already
covered in the troubleshooting docs (`codex features enable
plugin_hooks`). The pre-install plugin detail view shows "No plugin
hooks", consistent with every one of the 123 curated plugins (none
bundle command hooks, so this path has no working precedent to verify
against in-TUI). Marker behavior with `plugin_hooks` enabled is the
remaining thing to confirm in a real installed session.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 14:29:03 -07:00