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
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"name": "superloopy",
"source": "./",
"description": "Strict evidence loop harness: repo-local loop state, success criteria, append-only ledgers, evidence-gated completion, plus skills (loop, research, frontend, clone) and a read-only/worker crew. Works on Claude Code and Codex from one repo.",
"version": "0.12.3",
"version": "0.12.4",
"license": "MIT",
"keywords": [
"claude-code",
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "superloopy",
"version": "0.12.3",
"version": "0.12.4",
"description": "Lightweight loop harness with strict evidence gates — Claude Code edition.",
"homepage": "https://github.com/beefiker/superloopy#readme",
"repository": "https://github.com/beefiker/superloopy",
Expand Down
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "superloopy",
"version": "0.12.3",
"version": "0.12.4",
"description": "Lightweight loop harness with strict evidence gates.",
"homepage": "https://github.com/beefiker/superloopy#readme",
"repository": "https://github.com/beefiker/superloopy",
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ Upgrades from pre-managed Superloopy releases are hash-bound: a complete exact l

Resolution finishes before launch, with no post-launch retry or model switch. The TOML pins configure routing, but a host that does not expose `agent_type` plus resolved-model attestation remains `model_unverified`; Superloopy never presents that as a proven GPT-5.6 runtime gate. The policy details are in `docs/superloopy-model-policy.md` (Codex) and `docs/superloopy-model-policy-claude.md` (Claude Code).

**Installed-plugin truth.** `installedPluginTruth` runs the read-only `codex plugin list --json` authority probe. A confirmed `superloopy@beefiker` version mismatch is informational in source scope, but fails installed scope. Missing Codex, no registered plugin, and invalid authority output stay informational and do not fail doctor. Never infer the installed version from cache directory names or repair without approval.

<table>
<tr>
<td align="center" width="33%"><img src=".github/assets/franky.png" width="190" alt="franky" /><br /><b>franky</b><br /><sub>builds it</sub></td>
Expand Down Expand Up @@ -169,12 +171,14 @@ Superloopy checks for updates on `SessionStart`. Marketplace installs are Codex-

Restart Codex after the upgrade. If hooks show up as Modified, approve them; the following approved `SessionStart` automatically reconciles the generated wrapper, all six agents, and model-routing state from the new plugin version. No Superloopy migration command is required. If definitions changed, follow only the Codex restart notice so the host reloads them.

If the plugin still looks stale or degraded after that, do a repair reinstall from the refreshed marketplace:
If a confirmed `installedPluginTruth` version mismatch still looks stale or degraded after that, approve a repair reinstall from the refreshed marketplace:

```
codex plugin add superloopy@beefiker
codex plugin add superloopy@beefiker --json
```

Then start a new Codex session.

If you installed from a checkout, update the checkout and rerun the installer:

```
Expand Down
2 changes: 2 additions & 0 deletions docs/superloopy-file-audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ Superloopy is its own lightweight loop harness: one small CLI, repo-local `.supe
| `src/help.js` | CLI help text with shortest evidence-backed flow and pass-artifact rule. | Superloopy-specific onboarding surface. |
| `src/hooks.js` | Codex hook runtime for bootstrap, receipts, guide-backed context, continuation, and steering. | SessionStart reuses fresh managed model state without a catalog query and surfaces compatibility or restart instructions when relevant. |
| `src/install-flow.js` | Distinguishes marketplace, checkout, future npx-local snapshot, and unknown install states. | Prevents unsafe npx self-update when Superloopy was installed from marketplace or checkout. |
| `src/installed-plugin-truth.js` | Bounded read-only Codex installed-plugin authority probe and strict Superloopy version classifier. | Uses only the exact `superloopy@beefiker` JSON entry; never scans or mutates caches, wrappers, or plugin state. |
| `src/installed-model-policy.js` | Read-only doctor check for cached routing, exact legacy/unmanaged fleets, all six managed agent files, and explicit live availability before or after install. | Reads only an explicitly supplied Codex home/state path; sanitizes failures and never writes or launches workers. |
| `src/legacy-agents.js` | Validates legacy manifest data, hashes personal agent files, classifies complete legacy fleets, and resolves the default Codex agent target. | Reads hashes and file kinds only; exact all-six matching is required before migration is authorized. |
| `src/interop.js` | Best-effort, advisory detection of a neighboring Superpowers install for coexistence routing. | Superloopy-native; read-only filesystem probe, env-overridable, never mutates state or fails a hook. |
Expand Down Expand Up @@ -504,6 +505,7 @@ Superloopy is its own lightweight loop harness: one small CLI, repo-local `.supe
| `test/host-adapter.test.js` | Unit tests for host-agnostic receipt recovery (direct + transcript fallback, evidence + audit). | Superloopy-native test only. |
| `test/humanize-korean.test.js` | Contract tests for the Korean humanizer audit script's accept and reject paths. | Superloopy-native test for dependency-free safeguards and protected-token gating. |
| `test/interop.test.js` | Tests Superpowers detection (override, filesystem, both hosts), the doctor interop check, and coexistence routing in loop guidance. | Tests Superloopy-native coexistence behavior only. |
| `test/installed-plugin-truth.test.js` | Unit coverage for authoritative version matching, malformed authority data, bounded subprocess failures, and output sanitization. | Uses injected process results only and never reads or changes the live Codex installation. |
| `test/installed-model-policy.test.js` | Read-only doctor coverage for absent, healthy, stale, mixed, tampered, and explicitly refreshed installed Codex routing. | Uses isolated temporary `CODEX_HOME` fixtures and injected catalog results; never reads or mutates personal installation state. |
| `test/loop-gates.test.js` | Gate, report, trace, check, review, finish, and checkpoint tests. | Covers completion evidence flows. |
| `test/loop.test.js` | Core lifecycle and command-capture unit tests. | Tests Superloopy state semantics. |
Expand Down
8 changes: 4 additions & 4 deletions docs/superloopy-loop-golden-set.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
# Superloopy Loop Golden Set
This is Superloopy's own long-running loop-engineering golden set. It scores Superloopy on explicit criteria, artifact-backed proof, strict continuation, local state, append-only history, repository clarity, and reviewable files. Inventory scope: Git-visible repository files from `git ls-files --cached --others --exclude-standard`.
## Strict Rules
- Each improvement turn must record a score before claiming completion.
- Each new score must be greater than the previous score.
- Each accepted score must be greater than the previous accepted score for this golden-set version.
- If a turn lowers the score, skip that turn's changes and continue from the last accepted state.
- Each improvement turn must record a score before claiming completion. Each new score must be greater than the previous score.
- Each accepted score must be greater than the previous accepted score for this golden-set version; if a turn lowers the score, skip that turn's changes and continue from the last accepted state.
- A score is invalid without command evidence, changed-file evidence, and a short next-turn improvement target.
- Pass evidence must be artifact-backed or test-backed. Narrative-only evidence is not enough.
## Threshold Model
Expand Down Expand Up @@ -466,6 +464,7 @@ Total: 100 points.
| `src/help.js` | CLI help tests. | Must show the shortest evidence-backed flow and pass-artifact rule. |
| `src/hooks.js` | Hook, model-install, and golden-hook tests. | Must run managed bootstrap at SessionStart, reuse fresh state without a catalog query, surface compatibility/restart status, and keep continuation, steering, and receipt validation fail-closed. |
| `src/install-flow.js` | `test/auto-update.test.js`. | Must distinguish marketplace, checkout, future npx-local snapshot, and unknown install states so unsafe npx updates stay off. |
| `src/installed-plugin-truth.js` | `test/installed-plugin-truth.test.js`. | Must use only the exact `superloopy@beefiker` JSON entry, bounded read-only Codex subprocess output, and strict version classification without scanning or mutating caches, wrappers, or plugin state. |
| `src/installed-model-policy.js` | `test/installed-model-policy.test.js`, doctor tests. | Must report absent/legacy/unmanaged/preferred/degraded/stale/mixed/tampered status and keep explicit availability refresh read-only before and after install. |
| `src/interop.js` | `test/interop.test.js`. | Must detect a neighboring Superpowers install best-effort across both hosts, honor the `SUPERLOOPY_SUPERPOWERS` override, and never mutate state or fail a hook. |
| `src/loop.js` | Core loop and CLI tests. | Must preserve lifecycle state, ledger appends, evidence recording, review, checkpoint, status, and steering. |
Expand Down Expand Up @@ -523,6 +522,7 @@ Total: 100 points.
| `test/host-adapter.test.js` | `npm test`. | Must verify direct and transcript-fallback receipt recovery for both evidence and audit receipts, including trailing-newline, oversized-final-message, tool-use-only, and stale-token cases. |
| `test/humanize-korean.test.js` | `node --test test/humanize-korean.test.js`. | Must prove the Korean humanizer audit script accepts preserved Korean output and rejects non-Korean or token-dropping output. |
| `test/installed-model-policy.test.js` | `npm test`. | Must cover absent, preferred, degraded, stale, mixed, unsupported, missing, and tampered installs plus read-only live refresh with isolated `CODEX_HOME` fixtures. |
| `test/installed-plugin-truth.test.js` | `npm test`. | Must cover authoritative version matching, malformed authority data, bounded subprocess failures, and output sanitization using injected process results only; never read or change the live Codex installation. |
| `test/interop.test.js` | `npm test`. | Must cover Superpowers detection, the informational doctor interop check, and coexistence routing in loop guidance. |
| `test/loop-gates.test.js` | `npm test`. | Must cover gate, report, trace, check, review, finish, and checkpoint behavior. |
| `test/loop.test.js` | `npm test`. | Must cover core lifecycle, evidence recording, steering, and command capture. |
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "superloopy",
"version": "0.12.3",
"version": "0.12.4",
"description": "A lightweight loop harness for Codex and Claude Code with strict evidence gates.",
"type": "module",
"bin": {
Expand Down
6 changes: 5 additions & 1 deletion skills/superloopy-doctor/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ This is a Superloopy health check, not a generic plugin drift audit.
- Do not clone external repos, search issue trackers, or compare unrelated harness layouts unless the user separately asks for research.
- `superloopy doctor` reports the plugin root it checked: by default it uses `source` scope in a recognized Superloopy checkout and `installed` scope elsewhere. Pin a checkout with `superloopy doctor --root <checkout> --scope source --json`; pin an installed cache with `superloopy doctor --root <cache> --scope installed --json`. Source verdicts still return machine-local diagnostics, but `installedModelPolicy` and `wrapper` do not gate source health.

## Installed-plugin Authority

`installedPluginTruth` runs the read-only `codex plugin list --json` authority probe for `superloopy@beefiker`; it never infers the installed version from cache directory names. A confirmed version mismatch is informational in source scope, but fails installed scope. Missing Codex, no registered plugin, and invalid authority output are informational and do not fail doctor. Report these four states as `current`, `version_mismatch`, `not_registered`, or `authority_unavailable`; never repair from this probe without explicit approval.

## Diagnostic Spine

1. Identify the target root: `pwd`, `git rev-parse --show-toplevel` when it is a checkout, and the installed plugin cache path when the wrapper points into one.
Expand All @@ -46,7 +50,7 @@ This is a Superloopy health check, not a generic plugin drift audit.
Recommend repair commands only after the read-only report explains the failure:

- Marketplace refresh: `codex plugin marketplace upgrade beefiker`.
- Repair reinstall: `codex plugin add superloopy@beefiker`.
- Confirmed `installedPluginTruth` mismatch after approval: `codex plugin add superloopy@beefiker --json`, then start a new Codex session.
- Checkout install: `node src/cli.js install --json`.
- Forced local wrapper/agent overwrite: `node src/cli.js install --force --json`.

Expand Down
2 changes: 2 additions & 0 deletions src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { beginLoop } from "./begin.js";
import { captureLoop } from "./capture.js";
import { checkLoop, formatCheckResult } from "./check.js";
import { formatDoctor, runDoctor } from "./doctor.js";
import { queryInstalledPluginTruth } from "./installed-plugin-truth.js";
import { finishLoop } from "./finish.js";
import { formatGuideResult } from "./guide.js";
import { fleetLoop, handoffLoop } from "./fleet.js";
Expand Down Expand Up @@ -137,6 +138,7 @@ async function runDoctorCommand(argv, stdout, cwd) {
const result = await runDoctor(selection.root, {
scope: selection.scope,
comparisonPath: parsed.comparisonPath,
queryInstalledPluginTruth,
installedModelPolicy: {
env: process.env,
homeDir: homedir(),
Expand Down
28 changes: 24 additions & 4 deletions src/doctor.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ const RUNTIME_IGNORE_SAMPLES = [
const GENERATED_INSTALL_FILES = new Set([
".codex-marketplace-install.json"
]);
const SOURCE_NON_GATING_CHECKS = new Set([
"installedModelPolicy",
"installedPluginTruth",
"wrapper"
]);

export async function runDoctor(cwd, options = {}) {
const scope = options.scope ?? "source";
Expand Down Expand Up @@ -58,7 +63,15 @@ export async function runDoctor(cwd, options = {}) {
const modelPolicy = await checkModelPolicy(cwd);
const claudeModelPolicy = await checkClaudeModelPolicy(cwd);
const installedModelPolicy = await checkInstalledModelPolicy(cwd, options.installedModelPolicy ?? {});
const checks = { pluginManifest, hooks, skills, cli, dependencies, runtimeBoundary, fileAudit, gateNotes, designAudit, comparisonSimilarity, reviewability, dispatchCoherence, claudeHostWiring, modelPolicy, claudeModelPolicy, installedModelPolicy, hostContract: checkHostContract(), interop: checkInterop(options), wrapper: checkWrapper({ ...options, diagnosedRoot: cwd }) };
const installedPluginTruth = options.queryInstalledPluginTruth === undefined
? {
ok: true,
informational: true,
state: "authority_unavailable",
message: "Codex installed-plugin authority is unavailable."
}
: options.queryInstalledPluginTruth(pluginManifest.ok ? pluginManifest.manifest.version : undefined);
const checks = { pluginManifest, hooks, skills, cli, dependencies, runtimeBoundary, fileAudit, gateNotes, designAudit, comparisonSimilarity, reviewability, dispatchCoherence, claudeHostWiring, modelPolicy, claudeModelPolicy, installedModelPolicy, installedPluginTruth, hostContract: checkHostContract(), interop: checkInterop(options), wrapper: checkWrapper({ ...options, diagnosedRoot: cwd }) };
return {
ok: doctorOverallOk(checks, scope),
scope,
Expand All @@ -68,20 +81,27 @@ export async function runDoctor(cwd, options = {}) {
}

export function doctorOverallOk(checks, scope) {
const excluded = scope === "source" ? new Set(["installedModelPolicy", "wrapper"]) : new Set();
return Object.entries(checks).every(([name, check]) => excluded.has(name) || check.ok);
return Object.entries(checks).every(([name, check]) =>
scope === "source" && SOURCE_NON_GATING_CHECKS.has(name) ? true : check.ok
);
}

export function formatDoctor(result) {
const lines = ["Superloopy doctor", `scope: ${result.scope ?? "source"}`];
for (const [name, check] of Object.entries(result.checks)) {
const verdict = check.ok ? check.warning === true ? "warn" : "ok" : "fail";
const verdict = doctorVerdict(name, check, result.scope ?? "source");
lines.push(`- ${name}: ${verdict}${doctorDetail(name, check)}`);
}
lines.push(`overall: ${result.ok ? "ok" : "fail"}`);
return `${lines.join("\n")}\n`;
}

function doctorVerdict(name, check, scope) {
if (scope === "source" && SOURCE_NON_GATING_CHECKS.has(name) && !check.ok) return "info";
if (!check.ok) return "fail";
return check.warning === true ? "warn" : "ok";
}

function doctorDetail(name, check) {
if (name === "comparisonSimilarity") return ` - ${comparisonSimilarityDetail(check)}`;
return check.message === undefined ? "" : ` - ${check.message}`;
Expand Down
Loading
Loading