diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 1541386..cca6445 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -11,7 +11,7 @@ { "name": "co-dialectic", "source": "./plugins/co-dialectic", - "description": "Co-Dialectic v4.2.0 \u2014 LLM prompt optimizer + auto-verify by stakes (Safe/Private/Shared/Significant/Live) + auto-handoff on closure + honesty selector + agent-swarm + hygiene cycle + cross-family cascade-then-jury review + hallucination detector + research-first mode + fish-swarm orchestration.", + "description": "Co-Dialectic v4.9.0 \u2014 LLM prompt optimizer + auto-verify by stakes (Safe/Private/Shared/Significant/Live) + auto-handoff on closure + honesty selector + agent-swarm + hygiene cycle + cross-family cascade-then-jury review + hallucination detector + research-first mode + fish-swarm orchestration.", "version": "4.9.0", "category": "productivity" }, diff --git a/.gitignore b/.gitignore index f45652f..9d76a7f 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,8 @@ handoff.md __pycache__/ *.pyc docs/*.pdf +logs/ +.claude/worktrees/ # AI tool configs — generated by IDE/AI tools, workspace-private .aider.instructions.md @@ -25,6 +27,7 @@ docs/*.pdf .windsurfrules .cursorrules .cursorignore +/AGENTS.md # Demo production artifacts — private dev assets, live in career workspace plugins/co-dialectic/demo/frames/ diff --git a/CLAUDE-ISSUES.md b/CLAUDE-ISSUES.md new file mode 100644 index 0000000..a67a45e --- /dev/null +++ b/CLAUDE-ISSUES.md @@ -0,0 +1,37 @@ +# Issues Log — 2026-05-11 + +**Branch:** `add-cursor-codex-support` +**Canonical version:** `4.9.0` +**Test suite:** 57/57 PASS, 0 FAIL, 1 WARN (missing agent-marketplace dir — cosmetic) + +--- + +## Version Inconsistencies (6) — ALL FIXED + +| # | File | Was | Now | Status | +|---|------|-----|-----|--------| +| 1 | `SKILL-lite.md` line 4 | `3.0.0-lite` | `4.9.0-lite` | FIXED | +| 2 | `SKILL-lite.md` line 23 | `v3.0.0-lite active` | `v4.9.0-lite active` | FIXED | +| 3 | `SKILL.md` line 30 | `v4.7.0 active` | `v4.9.0 active` | FIXED | +| 4 | `plugin.json` desc | `v4.8.0` | `v4.9.0` | FIXED | +| 5 | `marketplace.json` desc | `v4.2.0` | `v4.9.0` | FIXED | +| 6 | `install.ps1` line 15 | `$Version = "3.0.0"` | `$Version = "4.9.0"` | FIXED | + +--- + +## Codex Compatibility (`logs/codex-compat-test.log`) + +- Install, byte-identical template match, idempotency, CLI visibility: **ALL PASSED** +- Codex CLI (`codex-cli 0.130.0-alpha.5`) read `AGENTS.md` and listed all `codi` commands +- No issues found + +## Cursor Compatibility (`logs/cursor-compat-test.log`) + +- Local install (`--target cursor`): **PASSED** — `.cursor/rules/co-dialectic.mdc` byte-identical to adapter +- `CO_DIALECTIC_REPO` file:// and plain path variants: **PASSED** +- Raw `main` URL for `.mdc`: **404** — expected pre-merge; resolves when branch merges to `main` +- No code fix needed + +## Cleanup — DONE + +- Removed stale temp artifacts: `logs/cursor_chk.YUub8O`, `logs/.plugin-test-tmp/`, `.cursor_test_nested/` diff --git a/README.md b/README.md index b47f863..3eeca08 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,18 @@ After installing, open a new session and say: **help me set up co-dialectic** - **macOS/Linux:** `curl -fsSL https://thewhyman.gateway.scarf.sh/install.sh | bash` - **Windows:** `Invoke-RestMethod -Uri https://thewhyman.gateway.scarf.sh/install.ps1 | Invoke-Expression` +Target a specific local AI runtime: +```bash +# Cursor: writes .cursor/rules/co-dialectic.mdc +curl -fsSL https://thewhyman.gateway.scarf.sh/install.sh | bash -s -- --target cursor + +# Codex: appends an idempotent Co-Dialectic block to AGENTS.md +curl -fsSL https://thewhyman.gateway.scarf.sh/install.sh | bash -s -- --target codex + +# Both Cursor and Codex +curl -fsSL https://thewhyman.gateway.scarf.sh/install.sh | bash -s -- --target all +``` + **Claude.ai / ChatGPT web / Gemini web — paste into your AI chat:** > I want to install Co-Dialectic to improve my AI conversations. Please read the install instructions at https://github.com/Exponential-OS/prompt-engineering-in-action and help me set it up. If you cannot access URLs, let me know and I'll paste the SKILL.md file contents directly. @@ -407,4 +419,3 @@ Day 10: Both anticipate each other → Communication sharpens **Generative principles accelerate the flywheel.** Every lesson codified as a broad principle (not a narrow keyword fix) covers infinite future situations. The broader the lesson, the faster the flywheel spins. - diff --git a/install.ps1 b/install.ps1 index adc91e1..3b0d11e 100644 --- a/install.ps1 +++ b/install.ps1 @@ -3,12 +3,16 @@ Co-Dialectic Manager for Windows. #> param( - [switch]$BgCheck + [switch]$BgCheck, + [ValidateSet("auto", "cursor", "codex", "all")] + [string]$Target = "auto", + [switch]$Lite, + [switch]$Full ) $ErrorActionPreference = "Stop" -$RepoUrl = "https://raw.githubusercontent.com/Exponential-OS/prompt-engineering-in-action/main" -$Version = "3.0.0" +$RepoUrl = if ($env:CO_DIALECTIC_REPO) { $env:CO_DIALECTIC_REPO } else { "https://raw.githubusercontent.com/Exponential-OS/prompt-engineering-in-action/main" } +$Version = "4.9.0" $ConfigDir = Join-Path $env:USERPROFILE ".co-dialectic" # ----------------------------------------- @@ -58,6 +62,116 @@ function Ask-Choice { return $Choice } +function Get-RepoFileContent { + param([string]$SourceUrl) + + if (Test-Path $SourceUrl) { + return Get-Content $SourceUrl -Raw + } + + if ($SourceUrl.StartsWith("$RepoUrl/")) { + $LocalPath = $SourceUrl.Substring($RepoUrl.Length + 1) -replace '/', [IO.Path]::DirectorySeparatorChar + if (Test-Path $LocalPath) { + return Get-Content $LocalPath -Raw + } + if ($PSScriptRoot) { + $ScriptRelativePath = Join-Path $PSScriptRoot $LocalPath + if (Test-Path $ScriptRelativePath) { + return Get-Content $ScriptRelativePath -Raw + } + } + + if ($LocalPath -eq ("plugins/co-dialectic/adapters/cursor/co-dialectic.mdc" -replace '/', [IO.Path]::DirectorySeparatorChar)) { + return Get-CursorAdapterContent + } + if ($LocalPath -eq ("plugins/co-dialectic/adapters/codex/AGENTS.md" -replace '/', [IO.Path]::DirectorySeparatorChar)) { + return Get-CodexAdapterContent + } + } + + return Invoke-RestMethod -Uri $SourceUrl +} + +function Get-CursorAdapterContent { + return @' +--- +description: Co-Dialectic prompt sharpening and verification rules for Cursor +alwaysApply: true +--- + +### BEGIN CO-DIALECTIC ### +# Co-Dialectic for Cursor + +Co-Dialectic is always active in this workspace. Keep the behavior compact and code-focused. + +## Runtime Defaults +- Default to Cruise mode: answer directly unless the user's prompt is ambiguous enough that a wrong implementation is likely. +- Keep status metadata quiet by default. Do not prepend persona/score lines unless the user asks for `codi status`. +- Prefer short, actionable prompt sharpening over teaching. If the user's ask is unclear, rewrite the ask in one sentence, state the assumption, and proceed when the assumption is low-risk. +- Use Drive mode only when the next step would change architecture, delete data, publish externally, or spend money. + +## Cursor Coding Behavior +- Read the relevant files before editing. +- Preserve user changes. Do not revert unrelated edits. +- Keep patches scoped to the requested behavior. +- Prefer existing project patterns and libraries over new abstractions. +- Run focused validation when available, and report what did or did not run. +- For reviews, lead with defects and file/line references before summaries. + +## Verification By Stakes +- Routine local edits: run syntax/type/unit checks that are already present. +- Shared or user-facing changes: also inspect edge cases, error states, and docs/install paths. +- Significant claims, security, legal, financial, medical, or release guidance: verify against primary/current sources before presenting as fact. + +## Commands +- `codi status`: summarize active mode, assumptions, and any verification gaps. +- `codi drive`: ask before applying sharpened prompts or taking broad actions. +- `codi cruise`: proceed with reasonable assumptions and concise notes. +- `codi quiet`: suppress status surfaces unless something needs attention. +- `codi review`: switch to code-review posture, prioritizing bugs and regressions. +- `codi handoff`: produce a concise continuation note with files touched, decisions, tests, and next steps. + +### END CO-DIALECTIC ### +'@ +} + +function Get-CodexAdapterContent { + return @' +### BEGIN CO-DIALECTIC ### +# Co-Dialectic for Codex + +Use Co-Dialectic as a lightweight engineering discipline layer, not as a chat persona system. + +## Defaults +- Stay concise and implementation-oriented. +- Read code before changing it. +- Make scoped edits that follow the repository's existing patterns. +- Preserve user changes and ignore unrelated dirty worktree files. +- Prefer `rg`/`rg --files` for search. +- Use patch-style edits for manual file changes. +- Run focused tests or checks when available, and say exactly what ran. + +## Prompt Sharpening +- If the user's request is clear, do the work. +- If the request is ambiguous but low-risk, state the assumption and proceed. +- If the ambiguity could cause destructive, externally visible, or expensive work, ask one direct question. +- When helpful, internally rewrite vague requests into concrete acceptance criteria before implementation. + +## Verification By Stakes +- Routine code edits: local tests, type checks, or lint checks where practical. +- Installer, release, security, or public-facing changes: validate idempotency, failure paths, and documentation. +- Current facts or high-stakes guidance: verify with primary/current sources before treating them as true. + +## Commands +- `codi status`: report assumptions, touched files, validation, and remaining risk. +- `codi review`: use code-review posture; findings first, then brief summary. +- `codi handoff`: write a continuation summary with branch, files changed, tests, and next steps. +- `codi quiet`: minimize Co-Dialectic surface text. + +### END CO-DIALECTIC ### +'@ +} + # ----------------------------------------- # MAIN MENU # ----------------------------------------- @@ -65,7 +179,11 @@ Write-Host "What would you like to do?" Write-Host " [1] Install or Update" Write-Host " [2] Uninstall completely" Write-Host " [3] Exit" -$MenuChoice = Ask-Choice "Select [1, 2, or 3]" "1" +if ($Target -eq "auto") { + $MenuChoice = Ask-Choice "Select [1, 2, or 3]" "1" +} else { + $MenuChoice = "1" +} if ($MenuChoice -eq "3") { exit 0 } @@ -95,6 +213,20 @@ if ($MenuChoice -eq "2") { } } } + $CursorRule = ".cursor\rules\co-dialectic.mdc" + if (Test-Path $CursorRule) { + Remove-Item -Force $CursorRule + Write-Host " Removed $CursorRule" + } + if (Test-Path "AGENTS.md") { + $HasBlock = Select-String -Path "AGENTS.md" -Pattern "### BEGIN CO-DIALECTIC ###" -Quiet + if ($HasBlock) { + $Content = Get-Content "AGENTS.md" -Raw + $Content = $Content -replace '(?s)### BEGIN CO-DIALECTIC ###.*?### END CO-DIALECTIC ###\s*', '' + Set-Content -Path "AGENTS.md" -Value $Content -Encoding UTF8 + Write-Host " Removed from AGENTS.md" + } + } # Remove Folders $Dirs = @( @@ -119,7 +251,13 @@ if ($MenuChoice -eq "2") { Write-Host "Which version do you want to install?" Write-Host " [1] Standard (Best for Pro/Paid AI users)" Write-Host " [2] Lite (Best for Free/Fast AI limits)" -$VersionChoice = Ask-Choice "Select [1/2]" "1" +if ($Lite -or (($Target -ne "auto") -and (-not $Full))) { + $VersionChoice = "2" +} elseif ($Full) { + $VersionChoice = "1" +} else { + $VersionChoice = Ask-Choice "Select [1/2]" "1" +} $SelectedVerStr = "full" if ($VersionChoice -eq "2") { @@ -131,15 +269,21 @@ if ($VersionChoice -eq "2") { Write-Host "⬇️ Downloading Standard version..." -ForegroundColor Yellow } -try { - $SkillContent = Invoke-RestMethod -Uri $SkillUrl -} catch { - Write-Host "Failed to download SKILL.md" -ForegroundColor Red - exit 1 -} +if ($Target -eq "auto") { + try { + $SkillContent = Get-RepoFileContent $SkillUrl + } catch { + Write-Host "Failed to download SKILL.md" -ForegroundColor Red + exit 1 + } -$TrackOptIn = Ask-User "📊 Share anonymous install metrics to help the project (OS/Tool choices)? [Y/n]" "y" -$BgUpdates = Ask-User "🔄 Enable weekly background checks for updates via Scheduled Tasks? [Y/n]" "y" + $TrackOptIn = Ask-User "📊 Share anonymous install metrics to help the project (OS/Tool choices)? [Y/n]" "y" + $BgUpdates = Ask-User "🔄 Enable weekly background checks for updates via Scheduled Tasks? [Y/n]" "y" +} else { + $SkillContent = "" + $TrackOptIn = $false + $BgUpdates = $false +} $Installed = $false $InstalledTools = @() @@ -208,10 +352,104 @@ function Append-Or-Replace { } } +function Install-OwnedFile { + param( + [string]$SourceUrl, + [string]$TargetFile, + [string]$PromptMsg, + [string]$DefaultAns, + [string]$ToolName, + [bool]$Force = $false + ) + + if ((-not $Force) -and (-not (Ask-User $PromptMsg $DefaultAns))) { return } + + try { + $Content = Get-RepoFileContent $SourceUrl + } catch { + Write-Host " ❌ Failed to download $SourceUrl" -ForegroundColor Red + return + } + + $Parent = Split-Path $TargetFile + if (($Parent -ne "") -and (-not (Test-Path $Parent))) { + New-Item -ItemType Directory -Force -Path $Parent | Out-Null + } + $Content | Set-Content -Path $TargetFile -Encoding UTF8 -NoNewline + Write-Host " ✅ Installed $TargetFile" -ForegroundColor Green + $script:Installed = $true + $script:InstalledTools += $ToolName +} + +function Append-Or-ReplaceRemote { + param( + [string]$SourceUrl, + [string]$TargetFile, + [string]$PromptMsg, + [string]$DefaultAns, + [string]$ToolName, + [bool]$Force = $false + ) + + if ((-not $Force) -and (-not (Ask-User $PromptMsg $DefaultAns))) { return } + + try { + $RemoteContent = Get-RepoFileContent $SourceUrl + } catch { + Write-Host " ❌ Failed to download $SourceUrl" -ForegroundColor Red + return + } + + if (-not (Test-Path $TargetFile)) { + $RemoteContent | Set-Content -Path $TargetFile -Encoding UTF8 -NoNewline + Write-Host " ✅ Added to $TargetFile" -ForegroundColor Green + } else { + $Content = Get-Content $TargetFile -Raw + if ($Content -match "### BEGIN CO-DIALECTIC ###") { + $Content = $Content -replace '(?s)### BEGIN CO-DIALECTIC ###.*?### END CO-DIALECTIC ###\s*', '' + Set-Content -Path $TargetFile -Value ($Content.TrimEnd() + "`n`n" + $RemoteContent) -Encoding UTF8 + Write-Host " ✅ Updated $TargetFile" -ForegroundColor Green + } else { + Add-Content -Path $TargetFile -Value "`n$RemoteContent" -Encoding UTF8 + Write-Host " ✅ Added to $TargetFile" -ForegroundColor Green + } + } + + $script:Installed = $true + $script:InstalledTools += $ToolName +} + +function Target-Selected { + param([string]$Name) + if ($Target -eq "all") { return $true } + return $Target -eq $Name +} + Write-Host "" Write-Host "Scanning for AI environments..." Write-Host "" +if ($Target -ne "auto") { + if (Target-Selected "cursor") { + Install-OwnedFile ` + "$RepoUrl/plugins/co-dialectic/adapters/cursor/co-dialectic.mdc" ` + ".cursor\rules\co-dialectic.mdc" ` + "✅ Install Cursor project rules to .cursor/rules/co-dialectic.mdc? [Y/n]" ` + "y" ` + "cursor_mdc" ` + $true + } + if (Target-Selected "codex") { + Append-Or-ReplaceRemote ` + "$RepoUrl/plugins/co-dialectic/adapters/codex/AGENTS.md" ` + "AGENTS.md" ` + "✅ Add Codex instructions to AGENTS.md? [Y/n]" ` + "y" ` + "codex_agents" ` + $true + } +} else { + # 1. Antigravity Support (dedicated skill file, full overwrite) $AntigravityPath = Join-Path $env:USERPROFILE ".gemini\antigravity\skills" if (Test-Path $AntigravityPath) { @@ -232,7 +470,22 @@ if (Test-Path $ClaudePath) { # 3. Cursor Support if ((Test-Path ".cursor") -or (Test-Path ".cursorrules")) { - Append-Or-Replace ".cursorrules" "✅ Detected Cursor project. Add to .cursorrules? [Y/n]" "y" "cursor" + Install-OwnedFile ` + "$RepoUrl/plugins/co-dialectic/adapters/cursor/co-dialectic.mdc" ` + ".cursor\rules\co-dialectic.mdc" ` + "✅ Detected Cursor project. Install modern Cursor rule to .cursor/rules/co-dialectic.mdc? [Y/n]" ` + "y" ` + "cursor_mdc" + Write-Host "" +} + +if ((Test-Path "AGENTS.md") -or (Get-Command codex -ErrorAction SilentlyContinue)) { + Append-Or-ReplaceRemote ` + "$RepoUrl/plugins/co-dialectic/adapters/codex/AGENTS.md" ` + "AGENTS.md" ` + "✅ Detected Codex. Add workspace instructions to AGENTS.md? [Y/n]" ` + "y" ` + "codex_agents" Write-Host "" } @@ -250,6 +503,8 @@ if (Ask-User "📋 Copy instructions to clipboard for web/desktop apps? [y/N]" " Write-Host "" } +} + if (-not $Installed) { Write-Host "ℹ️ No installation selected. Downloading SKILL.md to current directory..." if (-not (Test-Path "plugins\co-dialectic\skills\co-dialectic")) { New-Item -ItemType Directory -Force -Path "plugins\co-dialectic\skills\co-dialectic" | Out-Null } diff --git a/install.sh b/install.sh index 3df7c3d..b98729f 100755 --- a/install.sh +++ b/install.sh @@ -4,9 +4,12 @@ set -e -REPO="https://raw.githubusercontent.com/Exponential-OS/prompt-engineering-in-action/main" +REPO="${CO_DIALECTIC_REPO:-https://raw.githubusercontent.com/Exponential-OS/prompt-engineering-in-action/main}" VERSION="4.9.0" CONFIG_DIR="$HOME/.co-dialectic" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" 2>/dev/null && pwd || pwd)" +TARGET_ARG="auto" +VERSION_ARG="" # Co-Dialectic plugin skill inventory (v4.3.0). Shared by install + uninstall. # Append a new skill name here when a new skill is added to the plugin. @@ -22,13 +25,48 @@ PLUGIN_SKILLS=( "waky-waky" ) +fetch_repo_file() { + local source_url="$1" + local target_file="$2" + local local_path="${source_url#"$REPO/"}" + + if [ -f "$source_url" ]; then + cp "$source_url" "$target_file" + elif [ "$local_path" != "$source_url" ] && [ -f "$local_path" ]; then + cp "$local_path" "$target_file" + elif [ "$local_path" != "$source_url" ] && [ -f "$SCRIPT_DIR/$local_path" ]; then + cp "$SCRIPT_DIR/$local_path" "$target_file" + else + if curl -fsSL "$source_url" -o "$target_file" 2>/dev/null; then + return 0 + fi + case "$local_path" in + plugins/co-dialectic/adapters/cursor/co-dialectic.mdc) + write_cursor_adapter "$target_file" + ;; + plugins/co-dialectic/adapters/codex/AGENTS.md) + write_codex_adapter "$target_file" + ;; + *) + return 1 + ;; + esac + fi +} + # ----------------------------------------- # BACKGROUND CHECKER # ----------------------------------------- if [ "$1" = "--bg-check" ]; then mkdir -p "$CONFIG_DIR" # Read YAML-frontmatter `version: "X.Y.Z"` first (v3+), fall back to legacy `**Version:**`. - SKILL_REMOTE=$(curl -fsSL "$REPO/plugins/co-dialectic/skills/co-dialectic/SKILL.md") + TMP_BG_SKILL=$(mktemp) + if fetch_repo_file "$REPO/plugins/co-dialectic/skills/co-dialectic/SKILL.md" "$TMP_BG_SKILL"; then + SKILL_REMOTE=$(cat "$TMP_BG_SKILL") + else + SKILL_REMOTE="" + fi + rm -f "$TMP_BG_SKILL" REMOTE_VERSION=$(echo "$SKILL_REMOTE" | awk -F'"' '/^[[:space:]]*version:[[:space:]]*"/{print $2; exit}') if [ -z "$REMOTE_VERSION" ]; then REMOTE_VERSION=$(echo "$SKILL_REMOTE" | grep "\*\*Version:\*\*" | head -n 1 | awk '{print $2}') @@ -46,6 +84,119 @@ if [ "$1" = "--bg-check" ]; then exit 0 fi +while [ "$#" -gt 0 ]; do + case "$1" in + --target) + shift + TARGET_ARG="${1:-auto}" + ;; + --target=*) + TARGET_ARG="${1#--target=}" + ;; + --lite) + VERSION_ARG="lite" + ;; + --full) + VERSION_ARG="full" + ;; + --help|-h) + echo "Usage: install.sh [--target auto|cursor|codex|all] [--lite|--full]" + exit 0 + ;; + esac + shift +done + +case "$TARGET_ARG" in + auto|cursor|codex|all) ;; + *) + echo "❌ Unknown --target '$TARGET_ARG'. Use cursor, codex, all, or auto." + exit 1 + ;; +esac + +write_cursor_adapter() { + local target_file="$1" + cat > "$target_file" <<'EOF' +--- +description: Co-Dialectic prompt sharpening and verification rules for Cursor +alwaysApply: true +--- + +### BEGIN CO-DIALECTIC ### +# Co-Dialectic for Cursor + +Co-Dialectic is always active in this workspace. Keep the behavior compact and code-focused. + +## Runtime Defaults +- Default to Cruise mode: answer directly unless the user's prompt is ambiguous enough that a wrong implementation is likely. +- Keep status metadata quiet by default. Do not prepend persona/score lines unless the user asks for `codi status`. +- Prefer short, actionable prompt sharpening over teaching. If the user's ask is unclear, rewrite the ask in one sentence, state the assumption, and proceed when the assumption is low-risk. +- Use Drive mode only when the next step would change architecture, delete data, publish externally, or spend money. + +## Cursor Coding Behavior +- Read the relevant files before editing. +- Preserve user changes. Do not revert unrelated edits. +- Keep patches scoped to the requested behavior. +- Prefer existing project patterns and libraries over new abstractions. +- Run focused validation when available, and report what did or did not run. +- For reviews, lead with defects and file/line references before summaries. + +## Verification By Stakes +- Routine local edits: run syntax/type/unit checks that are already present. +- Shared or user-facing changes: also inspect edge cases, error states, and docs/install paths. +- Significant claims, security, legal, financial, medical, or release guidance: verify against primary/current sources before presenting as fact. + +## Commands +- `codi status`: summarize active mode, assumptions, and any verification gaps. +- `codi drive`: ask before applying sharpened prompts or taking broad actions. +- `codi cruise`: proceed with reasonable assumptions and concise notes. +- `codi quiet`: suppress status surfaces unless something needs attention. +- `codi review`: switch to code-review posture, prioritizing bugs and regressions. +- `codi handoff`: produce a concise continuation note with files touched, decisions, tests, and next steps. + +### END CO-DIALECTIC ### +EOF +} + +write_codex_adapter() { + local target_file="$1" + cat > "$target_file" <<'EOF' +### BEGIN CO-DIALECTIC ### +# Co-Dialectic for Codex + +Use Co-Dialectic as a lightweight engineering discipline layer, not as a chat persona system. + +## Defaults +- Stay concise and implementation-oriented. +- Read code before changing it. +- Make scoped edits that follow the repository's existing patterns. +- Preserve user changes and ignore unrelated dirty worktree files. +- Prefer `rg`/`rg --files` for search. +- Use patch-style edits for manual file changes. +- Run focused tests or checks when available, and say exactly what ran. + +## Prompt Sharpening +- If the user's request is clear, do the work. +- If the request is ambiguous but low-risk, state the assumption and proceed. +- If the ambiguity could cause destructive, externally visible, or expensive work, ask one direct question. +- When helpful, internally rewrite vague requests into concrete acceptance criteria before implementation. + +## Verification By Stakes +- Routine code edits: local tests, type checks, or lint checks where practical. +- Installer, release, security, or public-facing changes: validate idempotency, failure paths, and documentation. +- Current facts or high-stakes guidance: verify with primary/current sources before treating them as true. + +## Commands +- `codi status`: report assumptions, touched files, validation, and remaining risk. +- `codi review`: use code-review posture; findings first, then brief summary. +- `codi handoff`: write a continuation summary with branch, files changed, tests, and next steps. +- `codi quiet`: minimize Co-Dialectic surface text. + +### END CO-DIALECTIC ### +EOF +} + # ----------------------------------------- # UI HELPERS # ----------------------------------------- @@ -56,7 +207,15 @@ ask_user() { local prompt="$1" local default="$2" local reply - if [ -t 0 ]; then read -r -p "$prompt " reply; elif [ -c /dev/tty ]; then read -r -p "$prompt " reply /dev/null; then + : + else + echo -n "$prompt " + reply="$default" + echo "$reply (auto-selected)" + fi if [[ -z "$reply" ]]; then reply="$default"; fi case "$reply" in [Yy]* ) return 0 ;; * ) return 1 ;; esac } @@ -65,7 +224,15 @@ ask_choice() { local prompt="$1" local default="$2" local reply - if [ -t 0 ]; then read -r -p "$prompt " reply; elif [ -c /dev/tty ]; then read -r -p "$prompt " reply /dev/null; then + : + else + echo -n "$prompt " + reply="$default" + echo "$reply (auto-selected)" + fi if [[ -z "$reply" ]]; then reply="$default"; fi echo "$reply" } @@ -77,7 +244,11 @@ echo "What would you like to do?" echo " [1] Install or Update" echo " [2] Uninstall completely" echo " [3] Exit" -MENU_CHOICE=$(ask_choice "Select [1, 2, or 3]:" "1") +if [ "$TARGET_ARG" = "auto" ]; then + MENU_CHOICE=$(ask_choice "Select [1, 2, or 3]:" "1") +else + MENU_CHOICE="1" +fi if [ "$MENU_CHOICE" = "3" ]; then echo "Exiting." @@ -106,6 +277,16 @@ if [ "$MENU_CHOICE" = "2" ]; then echo " Removed from $TARGET" fi done + if [ -f ".cursor/rules/co-dialectic.mdc" ]; then + rm -f ".cursor/rules/co-dialectic.mdc" + echo " Removed .cursor/rules/co-dialectic.mdc" + fi + if [ -f "AGENTS.md" ] && grep -q "### BEGIN CO-DIALECTIC ###" "AGENTS.md"; then + awk '/### BEGIN CO-DIALECTIC ###/{flag=1} !flag {print} /### END CO-DIALECTIC ###/{flag=0}' "AGENTS.md" > "AGENTS.md.tmp" + cat "AGENTS.md.tmp" > "AGENTS.md" + rm "AGENTS.md.tmp" + echo " Removed from AGENTS.md" + fi # 2b. Remove fish gate hook from ~/.claude/settings.json unwire_agent_hook @@ -137,7 +318,15 @@ echo "" echo "Which version do you want to install?" echo " [1] Standard (Best for Pro/Paid AI users)" echo " [2] Lite (Best for Free/Fast AI limits)" -VERSION_CHOICE=$(ask_choice "Select [1/2]:" "1") +if [ "$VERSION_ARG" = "lite" ]; then + VERSION_CHOICE="2" +elif [ "$VERSION_ARG" = "full" ]; then + VERSION_CHOICE="1" +elif [ "$TARGET_ARG" != "auto" ]; then + VERSION_CHOICE="2" +else + VERSION_CHOICE=$(ask_choice "Select [1/2]:" "1") +fi if [ "$VERSION_CHOICE" = "2" ]; then SKILL_URL="$REPO/plugins/co-dialectic/skills/co-dialectic/SKILL-lite.md" @@ -150,7 +339,21 @@ else fi TMP_SKILL=$(mktemp) -curl -fsSL "$SKILL_URL" -o "$TMP_SKILL" +fetch_repo_file "$SKILL_URL" "$TMP_SKILL" + +INSTALLED=false +INSTALLED_TOOLS="" +TRACK_OPT_IN=false +BG_UPDATES=false + +if [ "$TARGET_ARG" = "auto" ]; then + if ask_user "📊 Share anonymous install metrics to help the project (OS/Tool choices)? [Y/n]" "y"; then + TRACK_OPT_IN=true + fi + if ask_user "🔄 Enable weekly background checks for updates? [Y/n]" "y"; then + BG_UPDATES=true + fi +fi # ----------------------------------------- # Plugin skill install helpers @@ -168,7 +371,7 @@ fetch_skill_extras() { case "$skill_name" in judge-panel) mkdir -p "$skill_dir/scripts" - if curl -fsSL "$REPO/plugins/co-dialectic/skills/judge-panel/scripts/judge_panel.py" -o "$skill_dir/scripts/judge_panel.py"; then + if fetch_repo_file "$REPO/plugins/co-dialectic/skills/judge-panel/scripts/judge_panel.py" "$skill_dir/scripts/judge_panel.py"; then chmod +x "$skill_dir/scripts/judge_panel.py" 2>/dev/null || true echo " └─ scripts/judge_panel.py (cascade harness)" else @@ -190,8 +393,8 @@ install_fish_gate() { local failed=0 mkdir -p "$FISH_INSTALL_DIR/hooks" - if curl -fsSL "$REPO/plugins/co-dialectic/fish/HOW.py" \ - -o "$FISH_INSTALL_DIR/HOW.py" 2>/dev/null; then + if fetch_repo_file "$REPO/plugins/co-dialectic/fish/HOW.py" \ + "$FISH_INSTALL_DIR/HOW.py"; then chmod +x "$FISH_INSTALL_DIR/HOW.py" echo " ✅ fish/HOW.py (pre-task gate engine)" else @@ -199,8 +402,8 @@ install_fish_gate() { failed=$((failed + 1)) fi - if curl -fsSL "$REPO/plugins/co-dialectic/fish/hooks/claude-code.py" \ - -o "$FISH_INSTALL_DIR/hooks/claude-code.py" 2>/dev/null; then + if fetch_repo_file "$REPO/plugins/co-dialectic/fish/hooks/claude-code.py" \ + "$FISH_INSTALL_DIR/hooks/claude-code.py"; then chmod +x "$FISH_INSTALL_DIR/hooks/claude-code.py" echo " ✅ fish/hooks/claude-code.py (Claude Code PreToolUse adapter)" else @@ -315,7 +518,7 @@ download_skills_direct() { else skill_src="$REPO/plugins/co-dialectic/skills/$skill/SKILL.md" fi - if curl -fsSL "$skill_src" -o "$skill_dir/SKILL.md"; then + if fetch_repo_file "$skill_src" "$skill_dir/SKILL.md"; then echo " ✅ $skill_dir/SKILL.md" fetch_skill_extras "$skill" "$skill_dir" else @@ -364,7 +567,7 @@ install_plugin() { else skill_src="$REPO/plugins/co-dialectic/skills/$skill/SKILL.md" fi - if curl -fsSL "$skill_src" -o "$skill_dir/SKILL.md"; then + if fetch_repo_file "$skill_src" "$skill_dir/SKILL.md"; then echo " ✅ $skill_dir/SKILL.md" fetch_skill_extras "$skill" "$skill_dir" else @@ -421,10 +624,110 @@ append_or_replace() { fi } +install_owned_file() { + local source_url="$1" + local target_file="$2" + local prompt_msg="$3" + local default_ans="$4" + local tool_name="$5" + local force="${6:-false}" + local tmp_file + + if [ "$force" != "true" ] && ! ask_user "$prompt_msg" "$default_ans"; then + return + fi + + mkdir -p "$(dirname "$target_file")" + tmp_file=$(mktemp) + if fetch_repo_file "$source_url" "$tmp_file"; then + cat "$tmp_file" > "$target_file" + rm -f "$tmp_file" + echo " ✅ Installed $target_file" + INSTALLED=true + INSTALLED_TOOLS="$INSTALLED_TOOLS,$tool_name" + else + rm -f "$tmp_file" + echo " ❌ failed to fetch $source_url" + fi +} + +append_or_replace_remote() { + local source_url="$1" + local target_file="$2" + local prompt_msg="$3" + local default_ans="$4" + local tool_name="$5" + local force="${6:-false}" + local tmp_file + + if [ "$force" != "true" ] && ! ask_user "$prompt_msg" "$default_ans"; then + return + fi + + tmp_file=$(mktemp) + if ! fetch_repo_file "$source_url" "$tmp_file"; then + rm -f "$tmp_file" + echo " ❌ failed to fetch $source_url" + return + fi + + if [ ! -f "$target_file" ]; then + cat "$tmp_file" > "$target_file" + echo " ✅ Added to $target_file" + elif grep -q "### BEGIN CO-DIALECTIC ###" "$target_file" 2>/dev/null; then + awk '/### BEGIN CO-DIALECTIC ###/{flag=1} !flag {print} /### END CO-DIALECTIC ###/{flag=0}' "$target_file" > "${target_file}.tmp" + cat "$tmp_file" >> "${target_file}.tmp" + cat "${target_file}.tmp" > "$target_file" + rm "${target_file}.tmp" + echo " ✅ Updated $target_file" + else + echo "" >> "$target_file" + cat "$tmp_file" >> "$target_file" + echo " ✅ Added to $target_file" + fi + rm -f "$tmp_file" + INSTALLED=true + INSTALLED_TOOLS="$INSTALLED_TOOLS,$tool_name" +} + +target_selected() { + local target="$1" + [ "$TARGET_ARG" = "all" ] && return 0 + case ",$TARGET_ARG," in + *",$target,"*) return 0 ;; + *) return 1 ;; + esac +} + echo "" echo "Scanning for AI environments..." echo "" +if [ "$TARGET_ARG" != "auto" ]; then + if target_selected "cursor"; then + install_owned_file \ + "$REPO/plugins/co-dialectic/adapters/cursor/co-dialectic.mdc" \ + ".cursor/rules/co-dialectic.mdc" \ + "✅ Install Cursor project rules to .cursor/rules/co-dialectic.mdc? [Y/n]" \ + "y" \ + "cursor_mdc" \ + "true" + fi + if target_selected "codex"; then + append_or_replace_remote \ + "$REPO/plugins/co-dialectic/adapters/codex/AGENTS.md" \ + "AGENTS.md" \ + "✅ Add Codex instructions to AGENTS.md? [Y/n]" \ + "y" \ + "codex_agents" \ + "true" + fi + if [ "$INSTALLED" = false ]; then + echo "❌ No installation completed for --target '$TARGET_ARG'. See fetch errors above." + exit 1 + fi +else + # Directory-based plugin installs (Antigravity, Claude Code) — all 6 skills. # For Claude Code users the recommended path is `/plugin install co-dialectic@xos` # via the marketplace; this installer path is the fallback for users not going @@ -446,8 +749,8 @@ if [ -d "$HOME/.claude" ]; then # the plugin itself (naming collision). Install the main skill # directly so `codi on` resolves correctly. mkdir -p "$HOME/.claude/skills/co-dialectic" - if curl -fsSL "$REPO/plugins/co-dialectic/skills/co-dialectic/SKILL.md" \ - -o "$HOME/.claude/skills/co-dialectic/SKILL.md" 2>/dev/null; then + if fetch_repo_file "$REPO/plugins/co-dialectic/skills/co-dialectic/SKILL.md" \ + "$HOME/.claude/skills/co-dialectic/SKILL.md"; then echo " ✅ co-dialectic skill registered at ~/.claude/skills/" else echo " ⚠️ Could not fetch main skill file — run installer again to retry" @@ -486,7 +789,22 @@ if [ -d "$HOME/.claude" ]; then fi if [ -d ".cursor" ] || [ -f ".cursorrules" ]; then - append_or_replace ".cursorrules" "✅ Detected Cursor project. Add to .cursorrules? [Y/n]" "y" "cursor" + install_owned_file \ + "$REPO/plugins/co-dialectic/adapters/cursor/co-dialectic.mdc" \ + ".cursor/rules/co-dialectic.mdc" \ + "✅ Detected Cursor project. Install modern Cursor rule to .cursor/rules/co-dialectic.mdc? [Y/n]" \ + "y" \ + "cursor_mdc" + echo "" +fi + +if [ -f "AGENTS.md" ] || command -v codex > /dev/null 2>&1; then + append_or_replace_remote \ + "$REPO/plugins/co-dialectic/adapters/codex/AGENTS.md" \ + "AGENTS.md" \ + "✅ Detected Codex. Add workspace instructions to AGENTS.md? [Y/n]" \ + "y" \ + "codex_agents" echo "" fi @@ -505,6 +823,8 @@ if ask_user "📋 Copy to clipboard for web apps (claude.ai, ChatGPT)? [y/N]" "n INSTALLED_TOOLS="$INSTALLED_TOOLS,clipboard" fi +fi + if [ "$INSTALLED" = false ]; then echo "ℹ️ No installation selected. Downloading to ./plugins/co-dialectic/skills/co-dialectic/SKILL.md" mkdir -p plugins/co-dialectic/skills/co-dialectic @@ -515,6 +835,7 @@ fi # Apply Background Checks if [ "$BG_UPDATES" = true ] && [[ "$OSTYPE" == "darwin"* ]]; then PLIST_FILE="$HOME/Library/LaunchAgents/com.codialectic.updater.plist" + mkdir -p "$(dirname "$PLIST_FILE")" cat << 'EOF' > "$PLIST_FILE" @@ -536,8 +857,11 @@ if [ "$BG_UPDATES" = true ] && [[ "$OSTYPE" == "darwin"* ]]; then EOF launchctl unload "$PLIST_FILE" 2>/dev/null || true - launchctl load "$PLIST_FILE" - echo "⏰ Native background updater installed (checks weekly via launchd)." + if launchctl load "$PLIST_FILE" 2>/dev/null; then + echo "⏰ Native background updater installed (checks weekly via launchd)." + else + echo "⚠️ Could not load macOS background updater. Run the installer from a normal user terminal to enable weekly checks." + fi fi # Save Config diff --git a/plugins/co-dialectic/.claude-plugin/plugin.json b/plugins/co-dialectic/.claude-plugin/plugin.json index b37cb65..9ae7ee8 100644 --- a/plugins/co-dialectic/.claude-plugin/plugin.json +++ b/plugins/co-dialectic/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "co-dialectic", - "description": "Co-Dialectic v4.8.0 — LLM prompt optimizer + auto-verify by stakes + semantic T3 classification + background agent lifecycle manager (dedup/timeout/capacity/registration/session-sweep) + worktree-isolation foreground gate + runtime-agnostic executor types + fish-swarm MUST-spawn dispatch mandate + Protocol 0 post-compaction re-init + plugin user-content gate. Cross-family cascade-then-jury review, judge-panel, hallucination detector, fish-swarm orchestration, session handoff. Works with any LLM runtime.", + "description": "Co-Dialectic v4.9.0 — LLM prompt optimizer + auto-verify by stakes + semantic T3 classification + background agent lifecycle manager (dedup/timeout/capacity/registration/session-sweep) + worktree-isolation foreground gate + runtime-agnostic executor types + fish-swarm MUST-spawn dispatch mandate + Protocol 0 post-compaction re-init + plugin user-content gate. Cross-family cascade-then-jury review, judge-panel, hallucination detector, fish-swarm orchestration, session handoff. Works with any LLM runtime.", "version": "4.9.0", "author": { "name": "Anand Vallamsetla" diff --git a/plugins/co-dialectic/README.md b/plugins/co-dialectic/README.md index bde02bf..d6cfc81 100644 --- a/plugins/co-dialectic/README.md +++ b/plugins/co-dialectic/README.md @@ -91,6 +91,24 @@ If you're on a **company-managed machine** where your employer controls Claude C This works for: Claude.ai, the API, IDE extensions, enterprise Claude Code where `/plugin` is blocked, or anyone who prefers it. +### Cursor and Codex adapters + +For modern Cursor projects, install the compact rule adapter: + +```bash +curl -fsSL https://thewhyman.gateway.scarf.sh/install.sh | bash -s -- --target cursor +``` + +This writes `.cursor/rules/co-dialectic.mdc`. + +For Codex workspaces, install the lightweight engineering adapter: + +```bash +curl -fsSL https://thewhyman.gateway.scarf.sh/install.sh | bash -s -- --target codex +``` + +This appends an idempotent Co-Dialectic block to `AGENTS.md`. + **Grab the skill file:** The core skill is a single Markdown file: diff --git a/plugins/co-dialectic/adapters/codex/AGENTS.md b/plugins/co-dialectic/adapters/codex/AGENTS.md new file mode 100644 index 0000000..7c726fe --- /dev/null +++ b/plugins/co-dialectic/adapters/codex/AGENTS.md @@ -0,0 +1,32 @@ +### BEGIN CO-DIALECTIC ### +# Co-Dialectic for Codex + +Use Co-Dialectic as a lightweight engineering discipline layer, not as a chat persona system. + +## Defaults +- Stay concise and implementation-oriented. +- Read code before changing it. +- Make scoped edits that follow the repository's existing patterns. +- Preserve user changes and ignore unrelated dirty worktree files. +- Prefer `rg`/`rg --files` for search. +- Use patch-style edits for manual file changes. +- Run focused tests or checks when available, and say exactly what ran. + +## Prompt Sharpening +- If the user's request is clear, do the work. +- If the request is ambiguous but low-risk, state the assumption and proceed. +- If the ambiguity could cause destructive, externally visible, or expensive work, ask one direct question. +- When helpful, internally rewrite vague requests into concrete acceptance criteria before implementation. + +## Verification By Stakes +- Routine code edits: local tests, type checks, or lint checks where practical. +- Installer, release, security, or public-facing changes: validate idempotency, failure paths, and documentation. +- Current facts or high-stakes guidance: verify with primary/current sources before treating them as true. + +## Commands +- `codi status`: report assumptions, touched files, validation, and remaining risk. +- `codi review`: use code-review posture; findings first, then brief summary. +- `codi handoff`: write a continuation summary with branch, files changed, tests, and next steps. +- `codi quiet`: minimize Co-Dialectic surface text. + +### END CO-DIALECTIC ### diff --git a/plugins/co-dialectic/adapters/cursor/co-dialectic.mdc b/plugins/co-dialectic/adapters/cursor/co-dialectic.mdc new file mode 100644 index 0000000..04ccb72 --- /dev/null +++ b/plugins/co-dialectic/adapters/cursor/co-dialectic.mdc @@ -0,0 +1,38 @@ +--- +description: Co-Dialectic prompt sharpening and verification rules for Cursor +alwaysApply: true +--- + +### BEGIN CO-DIALECTIC ### +# Co-Dialectic for Cursor + +Co-Dialectic is always active in this workspace. Keep the behavior compact and code-focused. + +## Runtime Defaults +- Default to Cruise mode: answer directly unless the user's prompt is ambiguous enough that a wrong implementation is likely. +- Keep status metadata quiet by default. Do not prepend persona/score lines unless the user asks for `codi status`. +- Prefer short, actionable prompt sharpening over teaching. If the user's ask is unclear, rewrite the ask in one sentence, state the assumption, and proceed when the assumption is low-risk. +- Use Drive mode only when the next step would change architecture, delete data, publish externally, or spend money. + +## Cursor Coding Behavior +- Read the relevant files before editing. +- Preserve user changes. Do not revert unrelated edits. +- Keep patches scoped to the requested behavior. +- Prefer existing project patterns and libraries over new abstractions. +- Run focused validation when available, and report what did or did not run. +- For reviews, lead with defects and file/line references before summaries. + +## Verification By Stakes +- Routine local edits: run syntax/type/unit checks that are already present. +- Shared or user-facing changes: also inspect edge cases, error states, and docs/install paths. +- Significant claims, security, legal, financial, medical, or release guidance: verify against primary/current sources before presenting as fact. + +## Commands +- `codi status`: summarize active mode, assumptions, and any verification gaps. +- `codi drive`: ask before applying sharpened prompts or taking broad actions. +- `codi cruise`: proceed with reasonable assumptions and concise notes. +- `codi quiet`: suppress status surfaces unless something needs attention. +- `codi review`: switch to code-review posture, prioritizing bugs and regressions. +- `codi handoff`: produce a concise continuation note with files touched, decisions, tests, and next steps. + +### END CO-DIALECTIC ### diff --git a/plugins/co-dialectic/skills/co-dialectic/SKILL-lite.md b/plugins/co-dialectic/skills/co-dialectic/SKILL-lite.md index 43f4473..452f20e 100644 --- a/plugins/co-dialectic/skills/co-dialectic/SKILL-lite.md +++ b/plugins/co-dialectic/skills/co-dialectic/SKILL-lite.md @@ -1,7 +1,7 @@ ### BEGIN CO-DIALECTIC ### # Co-Dialectic (Lite Version) -**Version:** 3.0.0-lite +**Version:** 4.9.0-lite **Repository:** https://github.com/Exponential-OS/prompt-engineering-in-action **Install (Claude Code/Cowork):** `/plugin marketplace add Exponential-OS/prompt-engineering-in-action` then `/plugin install co-dialectic@xos` **Author:** Anand Vallamsetla ([@thewhyman](https://github.com/thewhyman)) @@ -20,7 +20,7 @@ When first activated in a new chat, orient the user with a clean, scannable welc - **First reply only:** -> **Co-Dialectic v3.0.0-lite active.** +> **Co-Dialectic v4.9.0-lite active.** > You sharpen the AI. The AI sharpens you. Both get better every day. > > Every response starts with a status line like this: diff --git a/plugins/co-dialectic/skills/co-dialectic/SKILL.md b/plugins/co-dialectic/skills/co-dialectic/SKILL.md index 7d7a56c..d8c8b02 100644 --- a/plugins/co-dialectic/skills/co-dialectic/SKILL.md +++ b/plugins/co-dialectic/skills/co-dialectic/SKILL.md @@ -27,7 +27,7 @@ When first activated in a new chat, orient the user with a clean, scannable welc - **First reply only (also fires on post-compaction re-init):** -> **Co-Dialectic v4.7.0 active.** +> **Co-Dialectic v4.9.0 active.** > Sharper prompts. Grounded answers. Smarter cost routing — all automatic. > > **What's running on every message:** diff --git a/test-plugin.sh b/test-plugin.sh index da7b752..76c0992 100755 --- a/test-plugin.sh +++ b/test-plugin.sh @@ -122,6 +122,32 @@ for path in $(grep -o '\$REPO/[^ "]*' install.sh | sed 's/\$REPO\///' | grep -v [ -f "$path" ] && pass "$path" || fail "$path missing locally" done +# Regression: Cursor target must still install when the adapter asset is absent +# from the configured REPO, matching the "raw main .mdc returns 404" failure mode. +TMP_CURSOR_FALLBACK=$(mktemp -d) +REPO_ROOT_FOR_FALLBACK=$(pwd) +mkdir -p \ + "$TMP_CURSOR_FALLBACK/fake-repo/plugins/co-dialectic/skills/co-dialectic" \ + "$TMP_CURSOR_FALLBACK/project/.cursor" \ + "$TMP_CURSOR_FALLBACK/home" +cp plugins/co-dialectic/skills/co-dialectic/SKILL-lite.md \ + "$TMP_CURSOR_FALLBACK/fake-repo/plugins/co-dialectic/skills/co-dialectic/SKILL-lite.md" +if (cd "$TMP_CURSOR_FALLBACK/project" && \ + HOME="$TMP_CURSOR_FALLBACK/home" \ + CO_DIALECTIC_REPO="$TMP_CURSOR_FALLBACK/fake-repo" \ + bash "$REPO_ROOT_FOR_FALLBACK/install.sh" --target cursor) \ + > "$TMP_CURSOR_FALLBACK/install.log" 2>&1; then + if cmp -s "$TMP_CURSOR_FALLBACK/project/.cursor/rules/co-dialectic.mdc" \ + plugins/co-dialectic/adapters/cursor/co-dialectic.mdc; then + pass "Cursor fallback installs .mdc when adapter asset is missing from REPO" + else + fail "Cursor fallback .mdc differs from adapter template" + fi +else + fail "Cursor fallback install failed (see $TMP_CURSOR_FALLBACK/install.log)" +fi +rm -rf "$TMP_CURSOR_FALLBACK" + # ----------------------------------------------- # 9. README relative links # -----------------------------------------------