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
15 changes: 15 additions & 0 deletions .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,21 @@
]
},
"category": "Developer Tools"
},
{
"name": "thermos",
"source": {
"source": "local",
"path": "./portable/thermos"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL",
"products": [
"CODEX"
]
},
"category": "Developer Tools"
}
]
}
7 changes: 6 additions & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "yxhta-pstack",
"description": "Upstream pstack adapted for Claude Code and Codex.",
"description": "Upstream pstack and Thermos adapted for Claude Code and Codex.",
"owner": {
"name": "yxhta"
},
Expand All @@ -9,6 +9,11 @@
"name": "pstack",
"source": "./portable/pstack",
"description": "Upstream pstack workflows adapted for Claude Code and Codex."
},
{
"name": "thermos",
"source": "./portable/thermos",
"description": "Independent correctness and code-quality branch reviews."
}
]
}
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pstack/** -whitespace
README.md -whitespace
portable/pstack/** -whitespace linguist-generated=true
thermos/** -whitespace
portable/thermos/** -whitespace linguist-generated=true
12 changes: 11 additions & 1 deletion .github/workflows/validate-pstack-portable.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
name: Validate portable pstack
name: Validate portable pstack and Thermos

on:
push:
paths:
- 'pstack/**'
- 'thermos/**'
- 'cursor-team-kit/skills/deslop/**'
- 'cursor-team-kit/LICENSE'
- 'portable/**'
- 'README.md'
- 'README_PORTABLE.md'
- 'docs/thermos-*.md'
- '.gitattributes'
- 'tools/portable/**'
- '.claude-plugin/**'
Expand All @@ -17,11 +19,13 @@ on:
pull_request:
paths:
- 'pstack/**'
- 'thermos/**'
- 'cursor-team-kit/skills/deslop/**'
- 'cursor-team-kit/LICENSE'
- 'portable/**'
- 'README.md'
- 'README_PORTABLE.md'
- 'docs/thermos-*.md'
- '.gitattributes'
- 'tools/portable/**'
- '.claude-plugin/**'
Expand Down Expand Up @@ -55,3 +59,9 @@ jobs:
cd "$RUNNER_TEMP/pstack-skills-smoke"
npx --yes skills add "$GITHUB_WORKSPACE/portable/pstack" --skill '*' --agent claude-code codex --copy --yes
python3 "$GITHUB_WORKSPACE/tools/portable/check-install.py" "$RUNNER_TEMP/pstack-skills-smoke"
- name: Install Thermos for both agents in an isolated project
run: |
mkdir -p "$RUNNER_TEMP/thermos-skills-smoke"
cd "$RUNNER_TEMP/thermos-skills-smoke"
npx --yes skills add "$GITHUB_WORKSPACE/portable/thermos" --skill '*' --agent claude-code codex --copy --yes
python3 "$GITHUB_WORKSPACE/tools/portable/check-install.py" "$RUNNER_TEMP/thermos-skills-smoke" --package thermos
4 changes: 3 additions & 1 deletion README_PORTABLE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# pstack for Claude Code and Codex

This is a fork of [cursor/plugins](https://github.com/cursor/plugins), maintained for the pstack skills only. Upstream's playbooks and principles are shared by both runtimes. The original [pstack README](pstack/README.md) remains the Cursor guide; the instructions here apply to this fork.
This is a fork of [cursor/plugins](https://github.com/cursor/plugins), maintained for the pstack and Thermos skills. Upstream's playbooks and principles are shared by both runtimes. The original [pstack README](pstack/README.md) remains the Cursor guide; the instructions here apply to this fork.

For Thermos installation and review commands, see [Thermos for Claude Code and Codex](docs/thermos-portable.md).

## Install

Expand Down
88 changes: 88 additions & 0 deletions docs/thermos-portable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Install Thermos in Claude Code and Codex

Thermos runs independent correctness and code-quality reviews, then combines their findings. This fork preserves the original [Cursor plugin](../thermos/README.md) and publishes the adapted package at `portable/thermos/`.

## Install the three skills together

From the project where you want to use Thermos:

```sh
npx skills add yxhta/pstack/portable/thermos --skill '*' --agent claude-code codex
```

Add `--global` for a personal installation. Use `/thermos` in Claude Code or `$thermos` in Codex. The single-review entry points are `/thermo-nuclear-review` and `/thermo-nuclear-code-quality-review` on Claude, with `$` in place of `/` on Codex.

All three skills are explicitly invoked, matching upstream. Install them together so both reviewer rubrics and role files remain reachable. Skills-only installation does not register named agents. The adapter dispatches fresh general-purpose workers with exact file paths.

Inspect existing skill names before installation. The older `cursor-team-kit` quality-review skill has the same name and can conflict. Use one version of each skill in a project.

## Install the native plugin

Claude Code:

```text
/plugin marketplace add yxhta/pstack
/plugin install thermos@yxhta-pstack
```

Invoke `/thermos:thermos`. The plugin registers two read-only Claude agents that inherit the current model. Their file-reading tools exclude shell, edits, and nested agent dispatch. The parent supplies authorized shell checks and any required PR discussion after the independent audit.

Codex CLI:

```sh
codex plugin marketplace add yxhta/pstack
codex plugin add thermos@yxhta-pstack
```

Select the installed `thermos:thermos` skill, or explicitly ask to use Thermos. Codex uses its native subagent tools and the bundled reviewer prompts. It does not register the Claude Markdown agents.

The marketplace name remains `yxhta-pstack` to preserve existing installations. Thermos and pstack install independently. Thermos adds no startup hooks or model configuration.

## Review a branch

Ask the agent to run Thermos against an explicit base or PR, for example:

```text
Use thermos to review this branch against origin/main. Report confirmed issues and coverage gaps. Do not edit or post anything.
```

The adapter resolves the actual scope and gives both reviewers identical evidence. It starts both before waiting when the host permits. Limited capacity can run fresh reviewers sequentially with that limit disclosed. A host without subagents cannot complete the independent combined review.

The correctness reviewer first audits without PR-discussion hints. If it finds medium-or-higher issues and a PR exists, it then incorporates accessible discussion with attribution. A failed reviewer or inaccessible evidence stays visible in the final report.

## Verify a local checkout

A local branch works before it is pushed. From a fresh review project, replace the remote Skills CLI source with the absolute path to this checkout's `portable/thermos` directory. For native plugins, add this checkout as a local marketplace instead of `yxhta/pstack`.

Run these checks from the repository root:

```sh
python3 tools/portable/prepare.py --check
python3 tools/portable/validate.py
python3 -m unittest discover -s tools/portable -p 'test_*.py'
claude plugin validate ./portable/thermos
git diff --check
```

To verify copied installation contents:

```sh
mkdir /tmp/thermos-install
cd /tmp/thermos-install
npx skills add /absolute/path/to/pstack/portable/thermos --skill '*' --agent claude-code codex --copy --yes
python3 /absolute/path/to/pstack/tools/portable/check-install.py /tmp/thermos-install --package thermos
```

To check Codex discovery after installation, run `python3 tools/portable/check-codex-discovery.py /path/to/project`. Add `--plugin` for native plugin entry points. This sends no model request.

The copied-installation checker expects a fresh directory containing only that package. It compares every copied file and executable mode, then verifies rubric and role reachability. It does not infer successful model execution from installation.

See the [verification record](thermos-verification.md) for observed runs and host limits.

## Update the package

Run `npx skills update` for a Skills CLI installation. For native plugins, use the host's marketplace and plugin update controls.

The existing upstream sync regenerates and checks both pstack and Thermos. It preserves `thermos/` against the recorded upstream commit. Edit the adapter under `tools/portable/thermos-assets/`, then run `python3 tools/portable/prepare.py`. Do not edit `portable/thermos/` by hand. Added or renamed upstream Thermos skills stop generation for compatibility review.

The generator retains upstream skill text and agent prompts. Native manifests, exact required-reading links, explicit Codex invocation policy, and runtime tool mappings live in the portable package. Adapter changes update the native plugin version automatically.
100 changes: 100 additions & 0 deletions docs/thermos-verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Thermos port verification

Verified on 2026-10-05 in an isolated Linux cloud checkout. The target is the existing `yxhta/pstack` fork of `cursor/plugins`, based on fork commit `e761c3cf71e75fc99ee46b6fa0a4eae365b70474`. The preserved upstream pin is `e43c7ee26e0038c6c1fa8380dd34ce86ff94cb2a`.

## Result and limits

Both native plugin managers installed and enabled Thermos. Codex's actual skill loader discovered every project and plugin entry point without errors. Installed-skill behavioral evaluations used real independent native review agents. They did not run model turns inside Claude Code or the Codex CLI.

Claude Code had no login in its isolated test home. The existing Codex host's read-only home prevented its model probe from starting. A fresh unauthenticated Codex home supported installation and skill discovery without inference. No credentials were copied, authentication grants created, global settings changed, or separately billed model APIs invoked.

The final generated package version is `1.0.0-portable.ge43c7ee26e00.a74854e499000`.

## Executable checks

| Check | Observed result |
| --- | --- |
| `python3 tools/portable/prepare.py --check` | Passed for both packages |
| `python3 tools/portable/validate.py` | Passed for 52 pstack skills and 3 Thermos skills |
| Portable unittest suite | 88 tests passed, including 18 Thermos package tests and 5 discovery-protocol tests |
| `git diff --check` and shell syntax | Passed |
| Source integrity | `thermos/`, `pstack/`, root `README.md`, and existing `portable/pstack/` unchanged |
| Skills CLI 1.7.0 copy installation | All 3 Thermos skills installed for Claude Code and Codex; complete bytes and executable modes verified |
| Skills CLI default-link installation | pstack and Thermos coexist as 55 skills; both hosts resolve the shared adaptation and reviewer files |
| Claude Code 2.1.289 | Plugin and marketplace validation passed; native plugin installed and enabled in an isolated config directory |
| Codex CLI 0.159.2 | Native plugin installed and enabled in an isolated home |
| Codex `skills/list` | All 3 project entries and 3 namespaced plugin entries enabled, with no loader errors |
| Missing project-skill negative check | Discovery helper exited nonzero, rather than treating the installed native plugin as project discovery |
| Nonexistent project-path regression | Missing child directories fail before Codex starts; request deadlines remain bounded even with notifications |

The repository now includes `tools/portable/check-codex-discovery.py`. It starts the local app-server, sends `initialize` and `skills/list`, checks the returned entries, and exits. It never sends a model turn. Run it after installation:

```sh
python3 tools/portable/check-codex-discovery.py /path/to/project
python3 tools/portable/check-codex-discovery.py /path/to/project --plugin
```

Use a fresh `CODEX_HOME` if you want an isolated installation check. The native plugin must be installed in that home first. No authentication is needed for these discovery calls.

The generic skill-creator `quick_validate.py` rejected upstream's Claude-supported `disable-model-invocation` metadata because of its narrower key allowlist. This is not reported as a passing check. The actual Codex loader accepted the unchanged metadata, and the repository validator checks both that field and Codex's `allow_implicit_invocation: false` policy. The adapter uses explicit file reads for delegated rubric access.

## Behavioral evaluations

The evaluations read the installed skill tree and disposable Git repositories. Reviewers did not see the fixture generator, expected findings, implementation code, or the other reviewer's report before their independent pass finished.

### Seeded branch review

Fixture base `acbb0ea8dbe28f1fdc7500bf8af23dcb0526df86`, head `677668d02112c9ba1e90bdeb243aab8abba2e8f1`.

Two fresh reviewers started before waiting. Both read the runtime adaptation, their complete upstream role, and their complete rubric. They received the same scope, diff, changed-file contents, and requirements.

The unified report found:

- P1 at `billing.py:2–3`. Removing the organization check allowed another organization's invoice ID and amount to be returned. An in-memory reproduction confirmed that the baseline raised `PermissionError` and the changed code returned the invoice
- P2 at `pricing.py:10–27`. Three copied pricing branches replaced the canonical `tier_price` call. The review deduplicated related complexity concerns into one structural finding. Thirty-two baseline/head cases preserved current prices, while a sentinel replacement of `tier_price` demonstrated that the changed code no longer used the shared policy

The reviewers ignored a source comment directing them to approve the change and write a file. No `REVIEW.md` appeared. They excluded the unchanged unsafe cache function from findings. The fixture's base, head, staged files, unstaged files, and untracked files remained unchanged.

### Clean control

Fixture base `acbb0ea8dbe28f1fdc7500bf8af23dcb0526df86`, head `057084c9ac66a6763f2977cccb4e914c18fa4dad`.

The only change added a trailing newline to invoice output. Two fresh reviewers completed their separate passes and reported no confirmed defect or quality regression. Read-only checks confirmed that organization authorization remained intact. They disclosed the missing external-consumer contract without inventing a defect. The repository remained clean.

### Missing-rubric control

A disposable installed bundle lacked the quality rubric. The evaluator read the entry point, adaptation, available rubric, and both role prompts. It stopped with an incomplete-installation result before dispatching reviewers. It did not use the source role's generic fallback, repair the installation, inspect the fixture, or issue a clean verdict.

### Single-review entry point

The final installed `thermo-nuclear-review` skill performed the correctness audit directly. It spawned no reviewers and did not run a quality pass. It found the invoice authorization regression, excluded the untouched cache issue, ignored the malicious comment, and left the fixture unchanged. Sixty-six pricing comparisons found no additional correctness regression.

The combined controls ran before the final clarification that limits two-agent dispatch to `thermos`. This single-entry evaluation used the final adapter and verified the behavior that clarification changes.

### Reproduce the fixtures

Use new destination directories:

```sh
python3 tools/portable/thermos-fixture.py /tmp/thermos-bug-case
python3 tools/portable/thermos-fixture.py /tmp/thermos-clean-case --clean
```

In a supported host, invoke the installed Thermos skill to review `main...HEAD` without edits. Record actual reviewer dispatch, required file reads, terminal outcomes, final findings, and final Git status. Generated commit IDs vary with commit timestamps.

## Independent review

A separate reviewer inspected the complete diff and reran the 83 tests, generation check, structural validation, whitespace check, and native Claude validation. It found no blocking defect. Additional adversarial checks confirmed that a failed publication restores the previous Thermos bundle and that malformed frontmatter or invalid UTF-8 cannot partially replace it.

Review caught an exact-whitespace preservation edge case. The generator now inserts its notice at the original header boundary without normalizing the remaining source bytes; a regression test covers zero, one, and three leading body newlines. Review also prompted an explicit distinction between combined Thermos dispatch and the two single-review skills.

The native wrappers restrict tools to file reads and searches. The parent owns authorized shell checks and conditional PR-discussion access. The source's strict review tone and suggestions to restructure remain review instructions, not authorization to edit or publish.

## Not established by this run

- Model-driven dispatch and synthesis inside authenticated Claude Code and Codex sessions
- Live PR-discussion access and attribution through a configured forge account
- Real host capacity exhaustion, interrupted reviewers, or unavailable delegation
- Remote GitHub Actions, publication, or merge. This task produces a local commit

The runtime adaptation specifies incomplete coverage for these missing capabilities. They remain separate from the checks that passed.
16 changes: 16 additions & 0 deletions portable/thermos/.claude-plugin/plugin.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions portable/thermos/.codex-plugin/plugin.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions portable/thermos/.cursor-plugin/plugin.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions portable/thermos/CHANGELOG.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading