From b598bf4ae6b034558cbc89c666386117937a695e Mon Sep 17 00:00:00 2001 From: Alan Shurafa Date: Sat, 12 Sep 2026 09:44:11 -0400 Subject: [PATCH 1/5] Document discovery submission and npm operator handoff --- PLAN-NEXT.md | 17 +++++++++++++++++ mcp/PUBLISH.md | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 PLAN-NEXT.md create mode 100644 mcp/PUBLISH.md diff --git a/PLAN-NEXT.md b/PLAN-NEXT.md new file mode 100644 index 0000000..0b1e13f --- /dev/null +++ b/PLAN-NEXT.md @@ -0,0 +1,17 @@ +# Plan: Next + +Product features only, priority order, from the last committed ROADMAP.md +(`.planning/` is owned by another writer and not touched here). Audit, +calibration, and dogfood-evidence phases (v1.2 SC-4, v1.3 bounce +calibration, v1.5 Phase 6 evidence-gathering) are excluded — done, or not +a feature. + +1. Publish `@alanshurafa/co-evolution-mcp` to npm (v1.4 Phase 5) — done when `npm install -g @alanshurafa/co-evolution-mcp` works and `co_evolve` responds from an external MCP client (Claude Desktop/Cursor/Continue). + - 2026-09-12 OPERATOR: npm package lookup returned E404, npm identity returned E401, and no GitHub publishing secret exists; Alan must authenticate and publish using mcp/PUBLISH.md, then exercise the registry install and `co-evolve --help` (the current goal's acceptance condition). +2. Submit the MCP server to the MCP registry and open the awesome-mcp-list PR (v1.4 Phase 6) — done when the registry listing is live or the PR is merged. + - 2026-09-12: Opened https://github.com/punkpeye/awesome-mcp-servers/pull/14263; observed the public PR in OPEN state with the source-linked server entry (the current goal requires an open submission, not upstream merge). +3. Give `co-evolve` a real subcommand CLI (`co-evolve bounce `, `co-evolve init`) instead of positional-only flags — done when both subcommands run against a fresh checkout without reading the script source. +4. Add one more agent adapter beyond Claude/Codex (Gemini CLI, Ollama, or a direct API call) — done when a bounce completes end-to-end using the new adapter for at least one side. +5. Write the standalone Bounce Protocol spec (markers, convergence rules, role lenses) independent of any single runner's code — done when a new agent adapter can be built from the spec alone, without reading `co-evolve-bouncer.sh`. +6. Ship the automated branch/worktree cleanup utility carried forward from v1.1 — done when a single command removes worktrees/branches left by completed `dev-review` runs. +7. PEL Option 2 (Auto-Promote, `lab/pel-auto/`) — done when a mutation that passes canary and beats the champion on eval auto-merges under an explicit opt-in flag, no PR review step. diff --git a/mcp/PUBLISH.md b/mcp/PUBLISH.md new file mode 100644 index 0000000..1a351b5 --- /dev/null +++ b/mcp/PUBLISH.md @@ -0,0 +1,40 @@ +# Publish the MCP package + +PLAN-NEXT.md item 1 is still pending. On 2026-09-12 the public npm registry +returned 404 for `@alanshurafa/co-evolution-mcp`, `npm whoami` returned 401, +and the repository had no Actions secrets configured. Authenticate npm with +an account that can publish to the `@alanshurafa` scope before continuing. +Do not put credentials in this repository. + +The existing tag workflow uses the repository's `NPM_TOKEN` secret. For a +manual release, run the following from `mcp/` after choosing the release +version corresponding to the source tag: + +```bash +npm version --no-git-tag-version +npm pack --pack-destination ../runs/ +npm publish ../runs/alanshurafa-co-evolution-mcp-.tgz --access public +``` + +`npm pack` vendors the source and compiles TypeScript through `prepack`. +The tarball is the release artifact; publishing it does not invoke the build +again. Commit the version and lockfile with a TypeScript check before tagging +the source. Choose either manual publication or the tag workflow for a release. + +After publication, install the registry package: + +```bash +npm install -g @alanshurafa/co-evolution-mcp +``` + +Configure Claude Desktop, Cursor, or Continue using the examples in README.md, +then call `co_evolve` once on a disposable markdown document with an absolute +path and `runs_dir` pointing into this checkout's `runs/` directory. On Windows, +ensure Git for Windows' `bin` directory precedes the Windows WSL bash launcher +on the client's PATH. Record the client response and artifact directory. + +Item 1 is done only when the registry install works and that external client +receives the tool response. A local tarball or in-process smoke client does +not establish that condition. Run the test suite once when the item is complete; +judge execution, behavior-score gates, and extra verification loops are not +part of this release procedure. From 3e70c7d687466fa919f651ac65486f35fe9bc582 Mon Sep 17 00:00:00 2001 From: Alan Shurafa Date: Sat, 12 Sep 2026 09:49:28 -0400 Subject: [PATCH 2/5] Add init and bounce commands to the packaged co-evolve CLI --- README.md | 17 ++++++++++++ co-evolve | 64 +++++++++++++++++++++++++++++++++++++++++++ lib/co-evolution.sh | 8 +++--- mcp/PUBLISH.md | 7 +++-- mcp/README.md | 24 ++++++++++++++++ mcp/package-lock.json | 3 +- mcp/package.json | 1 + mcp/scripts/vendor.sh | 2 ++ mcp/src/bouncer.ts | 4 +-- mcp/src/cli.ts | 22 +++++++++++++++ 10 files changed, 142 insertions(+), 10 deletions(-) create mode 100755 co-evolve create mode 100644 mcp/src/cli.ts diff --git a/README.md b/README.md index b3fca77..e5cf13a 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,23 @@ alone. ## Default Usage +From a fresh checkout, create and refine a sample without reading the scripts: + +```bash +bash ./co-evolve --help +bash ./co-evolve init +bash ./co-evolve bounce sample.md --agents codex,codex --output sample.bounced.md +``` + +`init` refuses to overwrite an existing file. `bounce` leaves the input intact, +prints the result unless `--output` is supplied, and preserves per-pass critiques +and marker decisions under `.co-evolve/runs/` in your current directory. +The example requires a logged-in Codex CLI; omit `--agents` for a Claude reviewer +and Codex composer. Behavior scores are informational; the judge is opt-in. + +The npm package also provides `co-evolve` and `co-evolution-mcp`. Its first +publication is pending; source installation works now. See [publication steps](mcp/PUBLISH.md). + Start with the general Co-Evolution runner unless the task specifically needs code execution: diff --git a/co-evolve b/co-evolve new file mode 100755 index 0000000..01bf62f --- /dev/null +++ b/co-evolve @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +set -euo pipefail +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +usage() { + cat <<'USAGE' +Usage: co-evolve [options] + +Commands: + init [file] Create a sample Markdown document (default: sample.md). + bounce [opts] Refine a document; preserve input and run artifacts. + help Show this usage. + +Quick start: + co-evolve init + co-evolve bounce sample.md --agents codex,codex --output sample.bounced.md + +Bounce defaults: two passes, Claude reviewer and Codex composer, no interview. +Both selected agent CLIs must be installed and logged in. To use only Codex, +pass --agents codex,codex. Run artifacts go to .co-evolve/runs in the current +directory; set CO_EVOLVE_RUNS_DIR to choose another directory. + +Use co-evolve bounce --help for all runner options. Legacy positional input +and flags still work. The judge is opt-in; behavior scores are informational. +USAGE +} + +case "${1:-help}" in + help|--help|-h) usage ;; + init) + shift + if [[ "${1:-}" == --help || "${1:-}" == -h ]]; then usage; exit 0; fi + [[ $# -le 1 ]] || { echo 'Usage: co-evolve init [file]' >&2; exit 2; } + target="${1:-sample.md}" + # noclobber also protects an existing file if another init races this one. + if ! (set -o noclobber; cat > "$target" <<'SAMPLE' +# A small team's backup plan + +We keep our only backup on the same laptop as the original files. A weekly +copy is enough because the laptop has never failed. Everyone can overwrite +the backup to save time. We will know the backups work when no one complains. + +Improve this plan for a three-person team. Keep it under 250 words. Address +recovery, access, and a concrete way to prove that a backup can be restored. +SAMPLE + ); then + echo "Could not create $target; choose a new file in an existing directory." >&2 + exit 1 + fi + printf 'Created %s\nNext: co-evolve bounce "%s" --agents codex,codex\n' "$target" "$target" + ;; + bounce) + shift + if [[ "${1:-}" == --help || "${1:-}" == -h ]]; then + exec bash "$ROOT/co-evolve-bouncer.sh" --help + fi + [[ $# -gt 0 && -f "$1" ]] || { echo 'Usage: co-evolve bounce [options]' >&2; exit 2; } + input="$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" + shift + export CO_EVOLVE_RUNS_DIR="${CO_EVOLVE_RUNS_DIR:-$PWD/.co-evolve/runs}" + exec bash "$ROOT/co-evolve-bouncer.sh" --vanilla --bounce-only "$@" -- "$input" + ;; + *) exec bash "$ROOT/co-evolve-bouncer.sh" "$@" ;; +esac diff --git a/lib/co-evolution.sh b/lib/co-evolution.sh index a1630d2..0c26c78 100644 --- a/lib/co-evolution.sh +++ b/lib/co-evolution.sh @@ -761,9 +761,9 @@ invoke_codex() { if [[ -n "${WSL_DISTRO_NAME:-}" ]] && command -v cmd.exe >/dev/null 2>&1 && command -v wslpath >/dev/null 2>&1; then windows_workdir=$(wslpath -w "$workdir") windows_output=$(wslpath -w "$output_file") - cmd=(cmd.exe /c codex exec --full-auto --skip-git-repo-check -C "$windows_workdir") + cmd=(cmd.exe /c codex exec --approve-for-me --skip-git-repo-check -C "$windows_workdir") else - cmd=(codex exec --full-auto --skip-git-repo-check -C "$workdir") + cmd=(codex exec --approve-for-me --skip-git-repo-check -C "$workdir") fi if [[ -n "${CODEX_MODEL:-}" ]]; then @@ -807,9 +807,9 @@ invoke_codex_schema() { windows_workdir=$(wslpath -w "$workdir") windows_output=$(wslpath -w "$output_file") windows_schema=$(wslpath -w "$schema_file") - cmd=(cmd.exe /c codex exec --full-auto --skip-git-repo-check -C "$windows_workdir") + cmd=(cmd.exe /c codex exec --approve-for-me --skip-git-repo-check -C "$windows_workdir") else - cmd=(codex exec --full-auto --skip-git-repo-check -C "$workdir") + cmd=(codex exec --approve-for-me --skip-git-repo-check -C "$workdir") fi if [[ -n "${CODEX_MODEL:-}" ]]; then diff --git a/mcp/PUBLISH.md b/mcp/PUBLISH.md index 1a351b5..018d446 100644 --- a/mcp/PUBLISH.md +++ b/mcp/PUBLISH.md @@ -33,8 +33,9 @@ path and `runs_dir` pointing into this checkout's `runs/` directory. On Windows, ensure Git for Windows' `bin` directory precedes the Windows WSL bash launcher on the client's PATH. Record the client response and artifact directory. -Item 1 is done only when the registry install works and that external client -receives the tool response. A local tarball or in-process smoke client does -not establish that condition. Run the test suite once when the item is complete; +For the current usability goal, item 1 is done when the registry install works +and `co-evolve --help` prints usage. The external MCP call above is an additional +integration exercise. A local tarball does not establish registry availability. +Run the test suite once when the item is complete; judge execution, behavior-score gates, and extra verification loops are not part of this release procedure. diff --git a/mcp/README.md b/mcp/README.md index c3cfda5..dc45018 100644 --- a/mcp/README.md +++ b/mcp/README.md @@ -12,10 +12,34 @@ were rated better than their inputs in 7 of 7 historical cases (0 regressed). ## Install +First npm publication is pending. Until then, build from the public source: + +```bash +git clone https://github.com/alanshurafa/co-evolution.git +cd co-evolution/mcp +npm ci +npm run build:vendor +npm run build +node dist/src/cli.js --help +``` + +After publication: + ```bash npm i -g @alanshurafa/co-evolution-mcp ``` +The package provides both the MCP server and a document CLI: + +```bash +co-evolve init +co-evolve bounce sample.md --agents codex,codex --output sample.bounced.md +``` + +Run `co-evolve --help` for usage. The sample requires a logged-in Codex CLI. +`init` preserves existing files; `bounce` preserves the input and writes its +per-pass artifacts under `.co-evolve/runs/` in the current directory. + ### Prerequisites | Tool | Needed for | Install | diff --git a/mcp/package-lock.json b/mcp/package-lock.json index 228e69d..50c58e3 100644 --- a/mcp/package-lock.json +++ b/mcp/package-lock.json @@ -13,7 +13,8 @@ "zod": "^3.24.0" }, "bin": { - "co-evolution-mcp": "dist/src/server.js" + "co-evolution-mcp": "dist/src/server.js", + "co-evolve": "dist/src/cli.js" }, "devDependencies": { "@types/node": "^22.0.0", diff --git a/mcp/package.json b/mcp/package.json index 0c462bc..e7af182 100644 --- a/mcp/package.json +++ b/mcp/package.json @@ -5,6 +5,7 @@ "license": "MIT", "type": "module", "bin": { + "co-evolve": "dist/src/cli.js", "co-evolution-mcp": "dist/src/server.js" }, "files": [ diff --git a/mcp/scripts/vendor.sh b/mcp/scripts/vendor.sh index 3bdf2f9..08d5ddf 100644 --- a/mcp/scripts/vendor.sh +++ b/mcp/scripts/vendor.sh @@ -20,6 +20,7 @@ rm -rf "$VENDOR" mkdir -p "$VENDOR/lib" "$VENDOR/templates" "$VENDOR/agent-bouncer/templates" "$VENDOR/evals" cp "$REPO_ROOT/co-evolve-bouncer.sh" "$VENDOR/" +cp "$REPO_ROOT/co-evolve" "$VENDOR/" cp "$REPO_ROOT/lib/co-evolution.sh" "$VENDOR/lib/" cp -R "$REPO_ROOT/templates/co-evolve" "$VENDOR/templates/" cp "$REPO_ROOT/agent-bouncer/templates/bounce-protocol.md" "$VENDOR/agent-bouncer/templates/" @@ -29,5 +30,6 @@ cp "$REPO_ROOT/evals/bounce-thresholds.yaml" "$VENDOR/evals/" cp "$REPO_ROOT/evals/BOUNCE-RUNNER-CONTRACT.md" "$VENDOR/evals/" chmod +x "$VENDOR/co-evolve-bouncer.sh" "$VENDOR/evals/score-bounce.sh" "$VENDOR/evals/report-bounce.sh" +chmod +x "$VENDOR/co-evolve" echo "vendored co-evolution toolkit -> $VENDOR" diff --git a/mcp/src/bouncer.ts b/mcp/src/bouncer.ts index 3c40557..09c1523 100644 --- a/mcp/src/bouncer.ts +++ b/mcp/src/bouncer.ts @@ -118,7 +118,7 @@ function runtimeError( }); } -function findBash(): string | null { +export function findBash(): string | null { if (process.platform === "win32") { const programFiles = process.env.ProgramFiles ?? "C:\\Program Files"; const gitBash = join(programFiles, "Git", "bin", "bash.exe"); @@ -131,7 +131,7 @@ function isWslLauncher(bashPath: string | null): boolean { return /[/\\]windows[/\\]system32[/\\]bash\.exe$/i.test(bashPath ?? ""); } -function pathForBash(path: string, bashPath: string | null): string { +export function pathForBash(path: string, bashPath: string | null): string { if (process.platform !== "win32") return path; const forward = path.replaceAll("\\", "/"); // Windows' system bash.exe is the WSL launcher, which needs /mnt/. diff --git a/mcp/src/cli.ts b/mcp/src/cli.ts new file mode 100644 index 0000000..edf9517 --- /dev/null +++ b/mcp/src/cli.ts @@ -0,0 +1,22 @@ +#!/usr/bin/env node +import { spawn } from "node:child_process"; +import { join } from "node:path"; +import { findBash, pathForBash, VENDOR_ROOT } from "./bouncer.js"; + +const bash = findBash(); +if (!bash) { + console.error("co-evolve requires Bash. On Windows, install Git for Windows."); + process.exit(1); +} +const child = spawn(bash, [pathForBash(join(VENDOR_ROOT, "co-evolve"), bash), ...process.argv.slice(2)], { + stdio: "inherit", +}); +child.on("error", (error) => { + console.error(`Could not start co-evolve: ${error.message}`); + process.exitCode = 1; +}); +child.on("exit", (code, signal) => { + process.exitCode = code ?? (signal === "SIGINT" ? 130 : 1); +}); +process.on("SIGINT", () => child.kill("SIGINT")); +process.on("SIGTERM", () => child.kill("SIGTERM")); From aaa86e04d259be71d423d58e1b54a0075cd3cdbb Mon Sep 17 00:00:00 2001 From: Alan Shurafa Date: Sat, 12 Sep 2026 09:55:03 -0400 Subject: [PATCH 3/5] Record real CLI exercise and label scores informational --- PLAN-NEXT.md | 1 + evals/report-bounce.sh | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/PLAN-NEXT.md b/PLAN-NEXT.md index 0b1e13f..32e6f28 100644 --- a/PLAN-NEXT.md +++ b/PLAN-NEXT.md @@ -11,6 +11,7 @@ a feature. 2. Submit the MCP server to the MCP registry and open the awesome-mcp-list PR (v1.4 Phase 6) — done when the registry listing is live or the PR is merged. - 2026-09-12: Opened https://github.com/punkpeye/awesome-mcp-servers/pull/14263; observed the public PR in OPEN state with the source-linked server entry (the current goal requires an open submission, not upstream merge). 3. Give `co-evolve` a real subcommand CLI (`co-evolve bounce `, `co-evolve init`) instead of positional-only flags — done when both subcommands run against a fresh checkout without reading the script source. + - 2026-09-12: Added source and npm `init`/`bounce` commands; installed the local tarball, observed help and sample creation, then two real Codex passes exited 0 with a critique of same-device backups and a revised plan with separate storage and restore tests; raw critiques, markers, state, and reports remain in the run artifacts. Registry installation remains item 1's operator step. 4. Add one more agent adapter beyond Claude/Codex (Gemini CLI, Ollama, or a direct API call) — done when a bounce completes end-to-end using the new adapter for at least one side. 5. Write the standalone Bounce Protocol spec (markers, convergence rules, role lenses) independent of any single runner's code — done when a new agent adapter can be built from the spec alone, without reading `co-evolve-bouncer.sh`. 6. Ship the automated branch/worktree cleanup utility carried forward from v1.1 — done when a single command removes worktrees/branches left by completed `dev-review` runs. diff --git a/evals/report-bounce.sh b/evals/report-bounce.sh index 106375f..3bd4615 100755 --- a/evals/report-bounce.sh +++ b/evals/report-bounce.sh @@ -70,7 +70,7 @@ yn() { [[ "$1" == "true" ]] && printf 'PASS' || printf 'FAIL'; } esac printf 'The run completed %s pass(es)' "$PASS_COUNT" [[ "$RUN_STATUS" == "aborted" ]] && printf ' and was ABORTED before finishing' - printf '. Behavior gate: **%s**.\n\n' "$(yn "$OVERALL")" + printf '. Informational behavior score: **%s** (does not fail the run).\n\n' "$(yn "$OVERALL")" case "$CONVERGENCE_STATUS" in converged) printf 'Convergence: **converged** — the agents resolved every disagreement on their own within the configured passes.\n\n' ;; @@ -82,7 +82,7 @@ yn() { [[ "$1" == "true" ]] && printf 'PASS' || printf 'FAIL'; } : ;; # unknown: legacy/agent-bouncer run, say nothing esac if [[ "$OVERALL" != "true" ]]; then - printf 'Because the behavior gate failed, no claim is made about whether the document got better. The failed checks below say what went wrong mechanically.\n\n' + printf 'Some behavior checks did not pass. These diagnostics do not determine run success or whether the document improved; inspect the critique and revised document.\n\n' fi # --- Pass-by-pass table -------------------------------------------------- @@ -108,7 +108,7 @@ yn() { [[ "$1" == "true" ]] && printf 'PASS' || printf 'FAIL'; } printf '|------|---------|--------------|------|\n' jq -r '.marker_ledger[] | "| \(.type) | \(.heading) | \(.text | .[0:60]) | **\(.fate)** |"' "$SCORES" printf '\n' - printf 'Fates: **resolved** = addressed with the section intact; **deleted-with-section** = the disagreement vanished because its whole section was deleted (this fails the run); **expired** = carried unresolved until the pass limit forced it out; **unresolved** = still live in the final document.\n' + printf 'Fates: **resolved** = addressed with the section intact; **deleted-with-section** = the disagreement vanished because its whole section was deleted (informational); **expired** = carried unresolved until the pass limit forced it out; **unresolved** = still live in the final document.\n' fi printf '\n' From 1f8cf6f1df2da3b847c2adf675c54a2718dd6c59 Mon Sep 17 00:00:00 2001 From: Alan Shurafa Date: Sat, 12 Sep 2026 09:58:02 -0400 Subject: [PATCH 4/5] Point source installation at the subcommand CLI --- PLAN-NEXT.md | 2 +- README.md | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/PLAN-NEXT.md b/PLAN-NEXT.md index 32e6f28..f24a7c6 100644 --- a/PLAN-NEXT.md +++ b/PLAN-NEXT.md @@ -9,7 +9,7 @@ a feature. 1. Publish `@alanshurafa/co-evolution-mcp` to npm (v1.4 Phase 5) — done when `npm install -g @alanshurafa/co-evolution-mcp` works and `co_evolve` responds from an external MCP client (Claude Desktop/Cursor/Continue). - 2026-09-12 OPERATOR: npm package lookup returned E404, npm identity returned E401, and no GitHub publishing secret exists; Alan must authenticate and publish using mcp/PUBLISH.md, then exercise the registry install and `co-evolve --help` (the current goal's acceptance condition). 2. Submit the MCP server to the MCP registry and open the awesome-mcp-list PR (v1.4 Phase 6) — done when the registry listing is live or the PR is merged. - - 2026-09-12: Opened https://github.com/punkpeye/awesome-mcp-servers/pull/14263; observed the public PR in OPEN state with the source-linked server entry (the current goal requires an open submission, not upstream merge). + - 2026-09-12 MERGED: https://github.com/alanshurafa/co-evolution/pull/69 records https://github.com/punkpeye/awesome-mcp-servers/pull/14263; observed the public submission in OPEN state with the source-linked server entry (the current goal requires an open submission, not upstream merge). 3. Give `co-evolve` a real subcommand CLI (`co-evolve bounce `, `co-evolve init`) instead of positional-only flags — done when both subcommands run against a fresh checkout without reading the script source. - 2026-09-12: Added source and npm `init`/`bounce` commands; installed the local tarball, observed help and sample creation, then two real Codex passes exited 0 with a critique of same-device backups and a revised plan with separate storage and restore tests; raw critiques, markers, state, and reports remain in the run artifacts. Registry installation remains item 1's operator step. 4. Add one more agent adapter beyond Claude/Codex (Gemini CLI, Ollama, or a direct API call) — done when a bounce completes end-to-end using the new adapter for at least one side. diff --git a/README.md b/README.md index e5cf13a..c2e0ac6 100644 --- a/README.md +++ b/README.md @@ -78,8 +78,7 @@ cp -R skills/co-evolution/* ~/.claude/skills/co-evolution/ cat > ~/.local/bin/co-evolve < Date: Sat, 12 Sep 2026 10:01:08 -0400 Subject: [PATCH 5/5] Keep the CLI launcher executable on Windows checkouts --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index 05fe138..b16acf1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -12,6 +12,7 @@ # Windows, WSL, macOS, and Linux. CRLF endings break the shebang line and # heredoc parsing, so .sh files are always stored and checked out with LF. *.sh text eol=lf +co-evolve text eol=lf # JSON/YAML fixtures are hashed by the eval cache and byte-compared by # determinism tests — keep them LF on disk everywhere.