patchwork-os 0.2.0-beta.2 → 0.2.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.bridge.md +5 -5
- package/README.md +156 -12
- package/dist/activityLog.d.ts +6 -0
- package/dist/activityLog.js +8 -0
- package/dist/activityLog.js.map +1 -1
- package/dist/analyticsPrefs.d.ts +35 -2
- package/dist/analyticsPrefs.js +120 -21
- package/dist/analyticsPrefs.js.map +1 -1
- package/dist/analyticsSend.js +5 -1
- package/dist/analyticsSend.js.map +1 -1
- package/dist/bridge.d.ts +2 -0
- package/dist/bridge.js +111 -7
- package/dist/bridge.js.map +1 -1
- package/dist/bridgeLockDiscovery.d.ts +27 -1
- package/dist/bridgeLockDiscovery.js +37 -11
- package/dist/bridgeLockDiscovery.js.map +1 -1
- package/dist/commands/patchworkInit.d.ts +5 -0
- package/dist/commands/patchworkInit.js +86 -7
- package/dist/commands/patchworkInit.js.map +1 -1
- package/dist/commands/recipe.d.ts +51 -0
- package/dist/commands/recipe.js +353 -2
- package/dist/commands/recipe.js.map +1 -1
- package/dist/commands/recipeInstall.js +6 -3
- package/dist/commands/recipeInstall.js.map +1 -1
- package/dist/commands/task.js +2 -2
- package/dist/commands/task.js.map +1 -1
- package/dist/config.d.ts +9 -2
- package/dist/config.js +35 -17
- package/dist/config.js.map +1 -1
- package/dist/connectors/tokenStorage.js +46 -10
- package/dist/connectors/tokenStorage.js.map +1 -1
- package/dist/featureFlags.d.ts +76 -0
- package/dist/featureFlags.js +166 -2
- package/dist/featureFlags.js.map +1 -1
- package/dist/index.js +765 -69
- package/dist/index.js.map +1 -1
- package/dist/lockfile.js +4 -1
- package/dist/lockfile.js.map +1 -1
- package/dist/patchworkConfig.js +5 -0
- package/dist/patchworkConfig.js.map +1 -1
- package/dist/recipeOrchestration.js +35 -1
- package/dist/recipeOrchestration.js.map +1 -1
- package/dist/recipeRoutes.d.ts +36 -0
- package/dist/recipeRoutes.js +231 -32
- package/dist/recipeRoutes.js.map +1 -1
- package/dist/recipes/agentExecutor.d.ts +25 -5
- package/dist/recipes/agentExecutor.js.map +1 -1
- package/dist/recipes/chainedRunner.js +16 -2
- package/dist/recipes/chainedRunner.js.map +1 -1
- package/dist/recipes/connectorPreflight.d.ts +53 -0
- package/dist/recipes/connectorPreflight.js +79 -0
- package/dist/recipes/connectorPreflight.js.map +1 -0
- package/dist/recipes/githubInstallSource.d.ts +62 -0
- package/dist/recipes/githubInstallSource.js +125 -0
- package/dist/recipes/githubInstallSource.js.map +1 -0
- package/dist/recipes/haltCategory.d.ts +80 -0
- package/dist/recipes/haltCategory.js +125 -0
- package/dist/recipes/haltCategory.js.map +1 -0
- package/dist/recipes/idempotencyKey.d.ts +126 -0
- package/dist/recipes/idempotencyKey.js +298 -0
- package/dist/recipes/idempotencyKey.js.map +1 -0
- package/dist/recipes/judgeSummary.d.ts +50 -0
- package/dist/recipes/judgeSummary.js +47 -0
- package/dist/recipes/judgeSummary.js.map +1 -0
- package/dist/recipes/judgeVerdict.d.ts +48 -0
- package/dist/recipes/judgeVerdict.js +174 -0
- package/dist/recipes/judgeVerdict.js.map +1 -0
- package/dist/recipes/migrations/index.d.ts +9 -0
- package/dist/recipes/migrations/index.js +133 -0
- package/dist/recipes/migrations/index.js.map +1 -1
- package/dist/recipes/runBudget.d.ts +70 -0
- package/dist/recipes/runBudget.js +109 -0
- package/dist/recipes/runBudget.js.map +1 -0
- package/dist/recipes/scheduler.js +1 -1
- package/dist/recipes/scheduler.js.map +1 -1
- package/dist/recipes/schema.d.ts +30 -0
- package/dist/recipes/toolRegistry.js +19 -0
- package/dist/recipes/toolRegistry.js.map +1 -1
- package/dist/recipes/tools/http.d.ts +10 -0
- package/dist/recipes/tools/http.js +176 -0
- package/dist/recipes/tools/http.js.map +1 -0
- package/dist/recipes/tools/index.d.ts +1 -0
- package/dist/recipes/tools/index.js +1 -0
- package/dist/recipes/tools/index.js.map +1 -1
- package/dist/recipes/validation.js +1 -1
- package/dist/recipes/validation.js.map +1 -1
- package/dist/recipes/yamlRunner.d.ts +71 -7
- package/dist/recipes/yamlRunner.js +156 -22
- package/dist/recipes/yamlRunner.js.map +1 -1
- package/dist/runLog.d.ts +28 -0
- package/dist/runLog.js +5 -0
- package/dist/runLog.js.map +1 -1
- package/dist/server.d.ts +65 -0
- package/dist/server.js +302 -3
- package/dist/server.js.map +1 -1
- package/dist/streamableHttp.js +17 -6
- package/dist/streamableHttp.js.map +1 -1
- package/dist/tools/bridgeDoctor.js +6 -2
- package/dist/tools/bridgeDoctor.js.map +1 -1
- package/dist/tools/ccRoutines.d.ts +221 -0
- package/dist/tools/ccRoutines.js +264 -0
- package/dist/tools/ccRoutines.js.map +1 -0
- package/dist/tools/getCodeCoverage.js +7 -3
- package/dist/tools/getCodeCoverage.js.map +1 -1
- package/dist/tools/index.js +6 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/recentTracesDigest.js +56 -11
- package/dist/tools/recentTracesDigest.js.map +1 -1
- package/dist/tools/testRunners/vitestJest.js +3 -1
- package/dist/tools/testRunners/vitestJest.js.map +1 -1
- package/dist/tools/utils.js +6 -3
- package/dist/tools/utils.js.map +1 -1
- package/package.json +17 -6
- package/scripts/postinstall.mjs +27 -0
- package/scripts/smoke/run-all.mjs +162 -0
- package/scripts/start-all.mjs +513 -0
- package/scripts/start-all.ps1 +209 -0
- package/scripts/start-all.sh +73 -17
- package/scripts/start-orchestrator.ps1 +158 -0
- package/scripts/start-remote.mjs +122 -0
- package/templates/automation-policies/recipe-authoring.json +1 -1
- package/templates/automation-policies/security-first.json +1 -1
- package/templates/automation-policies/strict-lint.json +1 -1
- package/templates/automation-policies/test-driven.json +1 -1
- package/templates/automation-policy.example.json +1 -1
- package/templates/co.patchwork-os.bridge.plist +1 -1
- package/templates/recipes/approval-queue-ui-test.yaml +1 -1
- package/templates/recipes/ctx-loop-test.yaml +1 -1
- package/templates/recipes/webhook/apple-watch-health-log.yaml +145 -0
- package/dist/commands/marketplace.d.ts +0 -16
- package/dist/commands/marketplace.js +0 -32
- package/dist/commands/marketplace.js.map +0 -1
- package/dist/recipes/legacyRecipeCompat.d.ts +0 -10
- package/dist/recipes/legacyRecipeCompat.js +0 -131
- package/dist/recipes/legacyRecipeCompat.js.map +0 -1
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
#Requires -Version 5.1
|
|
2
|
+
<#
|
|
3
|
+
.SYNOPSIS
|
|
4
|
+
Windows orchestrator for bridge + Claude + Patchwork dashboard.
|
|
5
|
+
|
|
6
|
+
.DESCRIPTION
|
|
7
|
+
Cross-platform alternative to start-all.sh for native Windows (PowerShell/cmd).
|
|
8
|
+
Starts the bridge, waits for the lock file, launches Claude --ide, and
|
|
9
|
+
optionally starts the Patchwork dashboard dev server and opens it in the browser.
|
|
10
|
+
|
|
11
|
+
Run via npm:
|
|
12
|
+
npm run start:bridge # bridge only (simplest)
|
|
13
|
+
npm run start-all:win # full orchestrator (bridge + claude + dashboard)
|
|
14
|
+
|
|
15
|
+
Or directly:
|
|
16
|
+
pwsh -File scripts\start-all.ps1
|
|
17
|
+
pwsh -File scripts\start-all.ps1 --no-dashboard
|
|
18
|
+
pwsh -File scripts\start-all.ps1 --workspace C:\my\project --dashboard-port 3200
|
|
19
|
+
|
|
20
|
+
.PARAMETER Workspace
|
|
21
|
+
Directory to open in Claude (default: current directory).
|
|
22
|
+
|
|
23
|
+
.PARAMETER Full
|
|
24
|
+
Pass --full to the bridge, registering all ~95 tools including git/terminal/file ops.
|
|
25
|
+
Default is slim mode (27 IDE-exclusive tools).
|
|
26
|
+
|
|
27
|
+
.PARAMETER NoDashboard
|
|
28
|
+
Skip starting the Patchwork dashboard.
|
|
29
|
+
|
|
30
|
+
.PARAMETER DashboardPort
|
|
31
|
+
Port for the Next.js dashboard dev server (default: 3200).
|
|
32
|
+
|
|
33
|
+
.PARAMETER BridgePort
|
|
34
|
+
Port for the bridge (default: auto-assigned via lock file).
|
|
35
|
+
|
|
36
|
+
.PARAMETER Notify
|
|
37
|
+
ntfy.sh topic for push notifications (optional).
|
|
38
|
+
#>
|
|
39
|
+
[CmdletBinding()]
|
|
40
|
+
param(
|
|
41
|
+
[string]$Workspace = ".",
|
|
42
|
+
[switch]$Full,
|
|
43
|
+
[switch]$NoDashboard,
|
|
44
|
+
[int] $DashboardPort = 3200,
|
|
45
|
+
[int] $BridgePort = 0,
|
|
46
|
+
[string]$Notify = ""
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
Set-StrictMode -Version Latest
|
|
50
|
+
$ErrorActionPreference = "Stop"
|
|
51
|
+
|
|
52
|
+
# ── Resolve paths ─────────────────────────────────────────────────────────────
|
|
53
|
+
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
54
|
+
$BridgeDir = Split-Path -Parent $ScriptDir
|
|
55
|
+
$DashboardDir = Join-Path $BridgeDir "dashboard"
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
$Workspace = (Resolve-Path $Workspace).Path
|
|
59
|
+
} catch {
|
|
60
|
+
Write-Error "Workspace directory not found: $Workspace"
|
|
61
|
+
exit 1
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# ── Helpers ───────────────────────────────────────────────────────────────────
|
|
65
|
+
function Write-Status($msg) { Write-Host "[orchestrator] $msg" -ForegroundColor Cyan }
|
|
66
|
+
function Write-Ok($msg) { Write-Host "[ok] $msg" -ForegroundColor Green }
|
|
67
|
+
function Write-Warn($msg) { Write-Host "[warn] $msg" -ForegroundColor Yellow }
|
|
68
|
+
|
|
69
|
+
function Send-Notify($msg) {
|
|
70
|
+
if (-not $Notify) { return }
|
|
71
|
+
try {
|
|
72
|
+
Invoke-RestMethod -Uri "https://ntfy.sh/$Notify" -Method Post -Body $msg -TimeoutSec 5 | Out-Null
|
|
73
|
+
} catch { Write-Warn "ntfy notification failed: $_" }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
# ── Track child processes for cleanup ─────────────────────────────────────────
|
|
77
|
+
$Jobs = [System.Collections.Generic.List[System.Diagnostics.Process]]::new()
|
|
78
|
+
|
|
79
|
+
function Stop-AllJobs {
|
|
80
|
+
foreach ($p in $Jobs) {
|
|
81
|
+
if (-not $p.HasExited) {
|
|
82
|
+
try { $p.Kill($true) } catch { }
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
# Clean up on Ctrl+C or exit
|
|
88
|
+
$null = Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action { Stop-AllJobs }
|
|
89
|
+
try { [Console]::TreatControlCAsInput = $false } catch { }
|
|
90
|
+
|
|
91
|
+
# ── Build bridge args ─────────────────────────────────────────────────────────
|
|
92
|
+
$BridgeArgs = @("--workspace", $Workspace)
|
|
93
|
+
if ($BridgePort -gt 0) { $BridgeArgs += @("--port", $BridgePort) }
|
|
94
|
+
if ($Full) { $BridgeArgs += "--full" }
|
|
95
|
+
|
|
96
|
+
# ── Start bridge ──────────────────────────────────────────────────────────────
|
|
97
|
+
Write-Status "Starting bridge (workspace: $Workspace)..."
|
|
98
|
+
|
|
99
|
+
$BridgeInfo = New-Object System.Diagnostics.ProcessStartInfo
|
|
100
|
+
$BridgeInfo.UseShellExecute = $false
|
|
101
|
+
# On Windows, npm global bins are .cmd wrappers — must invoke via cmd.exe.
|
|
102
|
+
# Quote each argument so workspace paths with spaces (e.g. "C:\Users\Jane Doe\...") survive.
|
|
103
|
+
$BridgeInfo.FileName = "cmd.exe"
|
|
104
|
+
$quotedArgs = $BridgeArgs | ForEach-Object { if ($_ -match '\s') { "`"$_`"" } else { $_ } }
|
|
105
|
+
$BridgeInfo.Arguments = "/c claude-ide-bridge " + ($quotedArgs -join " ")
|
|
106
|
+
|
|
107
|
+
$BridgeProc = [System.Diagnostics.Process]::Start($BridgeInfo)
|
|
108
|
+
$Jobs.Add($BridgeProc)
|
|
109
|
+
|
|
110
|
+
# ── Wait for lock file ────────────────────────────────────────────────────────
|
|
111
|
+
Write-Status "Waiting for bridge lock file..."
|
|
112
|
+
$ClaudeBase = if ($env:CLAUDE_CONFIG_DIR) { $env:CLAUDE_CONFIG_DIR } else { Join-Path $env:USERPROFILE ".claude" }
|
|
113
|
+
$IdeDir = Join-Path $ClaudeBase "ide"
|
|
114
|
+
$Deadline = (Get-Date).AddSeconds(30)
|
|
115
|
+
$LockFile = $null
|
|
116
|
+
|
|
117
|
+
while ((Get-Date) -lt $Deadline) {
|
|
118
|
+
$locks = Get-ChildItem -Path $IdeDir -Filter "*.lock" -ErrorAction SilentlyContinue |
|
|
119
|
+
Where-Object { $_.LastWriteTime -gt (Get-Date).AddSeconds(-60) }
|
|
120
|
+
if ($locks) {
|
|
121
|
+
# Find the lock that matches our workspace
|
|
122
|
+
foreach ($lf in $locks) {
|
|
123
|
+
try {
|
|
124
|
+
$content = Get-Content $lf.FullName -Raw | ConvertFrom-Json
|
|
125
|
+
if ($content.isBridge -and
|
|
126
|
+
($content.workspace -replace '\\','/' ) -eq ($Workspace -replace '\\','/')) {
|
|
127
|
+
$LockFile = $lf
|
|
128
|
+
$DetectedPort = [int][System.IO.Path]::GetFileNameWithoutExtension($lf.Name)
|
|
129
|
+
break
|
|
130
|
+
}
|
|
131
|
+
} catch { }
|
|
132
|
+
}
|
|
133
|
+
if ($LockFile) { break }
|
|
134
|
+
}
|
|
135
|
+
Start-Sleep -Milliseconds 200
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (-not $LockFile) {
|
|
139
|
+
Write-Error "Bridge lock file not written after 30s. Bridge may have failed to start."
|
|
140
|
+
Stop-AllJobs
|
|
141
|
+
exit 1
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
Write-Ok "Bridge ready on port $DetectedPort"
|
|
145
|
+
Send-Notify "Bridge started on port $DetectedPort"
|
|
146
|
+
|
|
147
|
+
# ── Start Claude --ide ────────────────────────────────────────────────────────
|
|
148
|
+
Write-Status "Starting claude --ide..."
|
|
149
|
+
$ClaudeInfo = New-Object System.Diagnostics.ProcessStartInfo
|
|
150
|
+
$ClaudeInfo.FileName = "cmd.exe"
|
|
151
|
+
$ClaudeInfo.Arguments = "/c claude --ide"
|
|
152
|
+
$ClaudeInfo.UseShellExecute = $false
|
|
153
|
+
$ClaudeProc = [System.Diagnostics.Process]::Start($ClaudeInfo)
|
|
154
|
+
$Jobs.Add($ClaudeProc)
|
|
155
|
+
|
|
156
|
+
# ── Start dashboard ───────────────────────────────────────────────────────────
|
|
157
|
+
$DashProc = $null
|
|
158
|
+
if (-not $NoDashboard) {
|
|
159
|
+
if (-not (Test-Path (Join-Path $DashboardDir "node_modules"))) {
|
|
160
|
+
Write-Warn "dashboard/node_modules not found. Run 'npm ci' in the dashboard directory first, or pass -NoDashboard."
|
|
161
|
+
} else {
|
|
162
|
+
Write-Status "Starting dashboard on http://localhost:$DashboardPort ..."
|
|
163
|
+
|
|
164
|
+
$env:PATCHWORK_BRIDGE_PORT = $DetectedPort
|
|
165
|
+
$DashInfo = New-Object System.Diagnostics.ProcessStartInfo
|
|
166
|
+
$DashInfo.FileName = "cmd.exe"
|
|
167
|
+
$DashInfo.Arguments = "/c npx next dev -p $DashboardPort"
|
|
168
|
+
$DashInfo.WorkingDirectory = $DashboardDir
|
|
169
|
+
$DashInfo.UseShellExecute = $false
|
|
170
|
+
$DashProc = [System.Diagnostics.Process]::Start($DashInfo)
|
|
171
|
+
$Jobs.Add($DashProc)
|
|
172
|
+
|
|
173
|
+
# Poll until Next.js answers, then open the browser
|
|
174
|
+
$DashUrl = "http://localhost:$DashboardPort"
|
|
175
|
+
$DashDeadline = (Get-Date).AddSeconds(60)
|
|
176
|
+
$Opened = $false
|
|
177
|
+
while ((Get-Date) -lt $DashDeadline) {
|
|
178
|
+
try {
|
|
179
|
+
$r = Invoke-WebRequest -Uri $DashUrl -UseBasicParsing -TimeoutSec 1 -ErrorAction Stop
|
|
180
|
+
if ($r.StatusCode -lt 500) {
|
|
181
|
+
Write-Ok "Dashboard ready — opening $DashUrl"
|
|
182
|
+
Start-Process $DashUrl # opens default browser on Windows
|
|
183
|
+
$Opened = $true
|
|
184
|
+
break
|
|
185
|
+
}
|
|
186
|
+
} catch { }
|
|
187
|
+
Start-Sleep -Milliseconds 1000
|
|
188
|
+
}
|
|
189
|
+
if (-not $Opened) {
|
|
190
|
+
Write-Warn "Dashboard did not respond within 60s — open $DashUrl manually."
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
# ── Wait ──────────────────────────────────────────────────────────────────────
|
|
196
|
+
Write-Host ""
|
|
197
|
+
Write-Ok "All processes started. Press Ctrl+C to stop."
|
|
198
|
+
Write-Host " Bridge PID : $($BridgeProc.Id)"
|
|
199
|
+
Write-Host " Claude PID : $($ClaudeProc.Id)"
|
|
200
|
+
if ($DashProc) { Write-Host " Dashboard : http://localhost:$DashboardPort (PID $($DashProc.Id))" }
|
|
201
|
+
Write-Host ""
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
# Block until the bridge exits (primary process)
|
|
205
|
+
$BridgeProc.WaitForExit()
|
|
206
|
+
} finally {
|
|
207
|
+
Write-Status "Bridge exited — stopping all processes..."
|
|
208
|
+
Stop-AllJobs
|
|
209
|
+
}
|
package/scripts/start-all.sh
CHANGED
|
@@ -52,10 +52,11 @@ IDE_NAME=""
|
|
|
52
52
|
VPS=""
|
|
53
53
|
FULL_MODE=""
|
|
54
54
|
NO_DASHBOARD=""
|
|
55
|
+
NO_TMUX=""
|
|
55
56
|
DASHBOARD_PORT="3200"
|
|
56
57
|
BRIDGE_PORT_FLAG=""
|
|
57
58
|
AUTOMATION_POLICY=""
|
|
58
|
-
|
|
59
|
+
DRIVER="subprocess"
|
|
59
60
|
BRIDGE_READY_TIMEOUT="${BRIDGE_READY_TIMEOUT:-30}"
|
|
60
61
|
LAST_CLAUDE_RESTART=0
|
|
61
62
|
RESTART_COUNT=0
|
|
@@ -71,10 +72,11 @@ while [[ $# -gt 0 ]]; do
|
|
|
71
72
|
--vps) VPS="$2"; shift 2 ;;
|
|
72
73
|
--full) FULL_MODE="--full"; shift ;;
|
|
73
74
|
--no-dashboard) NO_DASHBOARD=1; shift ;;
|
|
75
|
+
--no-tmux) NO_TMUX=1; shift ;;
|
|
74
76
|
--dashboard-port) DASHBOARD_PORT="$2"; shift 2 ;;
|
|
75
77
|
--bridge-port) BRIDGE_PORT_FLAG="--port $2"; shift 2 ;;
|
|
76
78
|
--automation-policy) AUTOMATION_POLICY="$2"; shift 2 ;;
|
|
77
|
-
--
|
|
79
|
+
--driver) DRIVER="$2"; shift 2 ;;
|
|
78
80
|
*) echo "Unknown option: $1" >&2; exit 1 ;;
|
|
79
81
|
esac
|
|
80
82
|
done
|
|
@@ -128,10 +130,12 @@ except Exception:
|
|
|
128
130
|
done < <(ls ~/.claude/ide/*.lock 2>/dev/null)
|
|
129
131
|
|
|
130
132
|
# --- Dependency checks ---
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
if [[ -z "$NO_TMUX" ]]; then
|
|
134
|
+
command -v tmux >/dev/null 2>&1 || {
|
|
135
|
+
echo "Error: tmux is required. Install with: brew install tmux (or pass --no-tmux for background mode)" >&2
|
|
136
|
+
exit 1
|
|
137
|
+
}
|
|
138
|
+
fi
|
|
135
139
|
command -v claude >/dev/null 2>&1 || {
|
|
136
140
|
echo "Error: claude CLI not found on PATH." >&2
|
|
137
141
|
exit 1
|
|
@@ -141,6 +145,56 @@ command -v node >/dev/null 2>&1 || {
|
|
|
141
145
|
exit 1
|
|
142
146
|
}
|
|
143
147
|
|
|
148
|
+
# --- No-tmux background mode ---
|
|
149
|
+
if [[ -n "$NO_TMUX" ]]; then
|
|
150
|
+
PIDS_DIR="$HOME/.patchwork/pids"
|
|
151
|
+
mkdir -p "$PIDS_DIR"
|
|
152
|
+
|
|
153
|
+
# Load credentials from ~/.patchwork/.env
|
|
154
|
+
if [[ -f "$HOME/.patchwork/.env" ]]; then
|
|
155
|
+
set -a; source "$HOME/.patchwork/.env"; set +a
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
BRIDGE_DIR_ABS="$(cd "$BRIDGE_DIR" && pwd)"
|
|
159
|
+
BRIDGE_BIN="$BRIDGE_DIR_ABS/node_modules/.bin/claude-ide-bridge"
|
|
160
|
+
[[ -f "$BRIDGE_BIN" ]] || BRIDGE_BIN="claude-ide-bridge"
|
|
161
|
+
|
|
162
|
+
echo "=== Patchwork OS — background mode (--no-tmux) ==="
|
|
163
|
+
|
|
164
|
+
# Start bridge
|
|
165
|
+
echo " Starting bridge..."
|
|
166
|
+
"$BRIDGE_BIN" ${FULL_MODE} ${BRIDGE_PORT_FLAG} \
|
|
167
|
+
${AUTOMATION_POLICY:+--automation --automation-policy "$AUTOMATION_POLICY" --driver "$DRIVER"} \
|
|
168
|
+
>> "$HOME/.patchwork/bridge.log" 2>&1 &
|
|
169
|
+
echo $! > "$PIDS_DIR/bridge.pid"
|
|
170
|
+
echo " Bridge PID: $! (log: ~/.patchwork/bridge.log)"
|
|
171
|
+
|
|
172
|
+
# Start dashboard if available
|
|
173
|
+
DASHBOARD_DIR="$BRIDGE_DIR_ABS/dashboard"
|
|
174
|
+
if [[ -z "$NO_DASHBOARD" ]] && [[ -d "$DASHBOARD_DIR" ]]; then
|
|
175
|
+
if [[ ! -d "$DASHBOARD_DIR/node_modules" ]]; then
|
|
176
|
+
echo " Installing dashboard dependencies..."
|
|
177
|
+
npm install --prefer-offline --prefix "$DASHBOARD_DIR" || {
|
|
178
|
+
echo "Warning: dashboard npm install failed — skipping dashboard." >&2
|
|
179
|
+
}
|
|
180
|
+
fi
|
|
181
|
+
if [[ -d "$DASHBOARD_DIR/node_modules" ]]; then
|
|
182
|
+
(cd "$DASHBOARD_DIR" && \
|
|
183
|
+
DASHBOARD_PASSWORD="${DASHBOARD_PASSWORD:-}" \
|
|
184
|
+
DASHBOARD_SESSION_SECRET="${DASHBOARD_SESSION_SECRET:-}" \
|
|
185
|
+
npx next dev -p "$DASHBOARD_PORT" \
|
|
186
|
+
>> "$HOME/.patchwork/dashboard.log" 2>&1) &
|
|
187
|
+
echo $! > "$PIDS_DIR/dashboard.pid"
|
|
188
|
+
echo " Dashboard PID: $! (log: ~/.patchwork/dashboard.log)"
|
|
189
|
+
echo " Dashboard: http://localhost:${DASHBOARD_PORT}"
|
|
190
|
+
fi
|
|
191
|
+
fi
|
|
192
|
+
|
|
193
|
+
echo ""
|
|
194
|
+
echo "To stop: kill \$(cat ~/.patchwork/pids/bridge.pid) \$(cat ~/.patchwork/pids/dashboard.pid) 2>/dev/null"
|
|
195
|
+
exit 0
|
|
196
|
+
fi
|
|
197
|
+
|
|
144
198
|
# --- tmux session management ---
|
|
145
199
|
if [[ -z "${TMUX:-}" ]]; then
|
|
146
200
|
if tmux has-session -t "$SESSION" 2>/dev/null; then
|
|
@@ -168,7 +222,7 @@ if [[ -z "$FULL_MODE" ]]; then
|
|
|
168
222
|
fi
|
|
169
223
|
if [[ -n "$AUTOMATION_POLICY" ]]; then
|
|
170
224
|
echo ""
|
|
171
|
-
echo " ⚡ Automation: enabled (driver: $
|
|
225
|
+
echo " ⚡ Automation: enabled (driver: $DRIVER)"
|
|
172
226
|
echo " Policy: $AUTOMATION_POLICY"
|
|
173
227
|
fi
|
|
174
228
|
echo ""
|
|
@@ -207,7 +261,7 @@ if [[ -n "$IDE_NAME" ]]; then
|
|
|
207
261
|
fi
|
|
208
262
|
BRIDGE_AUTOMATION_FLAGS=""
|
|
209
263
|
if [[ -n "$AUTOMATION_POLICY" ]]; then
|
|
210
|
-
BRIDGE_AUTOMATION_FLAGS="--automation --automation-policy $(printf '%q' "$AUTOMATION_POLICY") --
|
|
264
|
+
BRIDGE_AUTOMATION_FLAGS="--automation --automation-policy $(printf '%q' "$AUTOMATION_POLICY") --driver $(printf '%q' "$DRIVER")"
|
|
211
265
|
fi
|
|
212
266
|
# Use compiled dist when src/ is absent (npm install), tsx during local development
|
|
213
267
|
if [[ -f "$BRIDGE_DIR/src/index.ts" ]]; then
|
|
@@ -381,22 +435,24 @@ tmux send-keys -t "${SESSION}:0.3" "$REMOTE_CMD" Enter
|
|
|
381
435
|
# Pane 4: Dashboard (only if not --no-dashboard and dashboard dir exists)
|
|
382
436
|
DASHBOARD_DIR="$BRIDGE_DIR/dashboard"
|
|
383
437
|
if [[ -z "$NO_DASHBOARD" ]] && [[ -d "$DASHBOARD_DIR" ]]; then
|
|
384
|
-
#
|
|
385
|
-
# an unhelpful error in pane 4. Surface a concrete remediation step in the
|
|
386
|
-
# orchestrator pane so the user knows what to do.
|
|
438
|
+
# Self-healing: install dashboard deps if node_modules is missing.
|
|
387
439
|
if [[ ! -d "$DASHBOARD_DIR/node_modules" ]]; then
|
|
388
|
-
echo ""
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
440
|
+
echo "[orchestrator] Installing dashboard dependencies (first-time setup)..."
|
|
441
|
+
npm install --prefer-offline --prefix "$DASHBOARD_DIR" || {
|
|
442
|
+
echo "Error: dashboard npm install failed. Run manually: cd $(printf '%q' "$DASHBOARD_DIR") && npm install" >&2
|
|
443
|
+
exit 1
|
|
444
|
+
}
|
|
445
|
+
fi
|
|
446
|
+
# Load dashboard credentials from ~/.patchwork/.env so Next.js picks them up.
|
|
447
|
+
if [[ -f "$HOME/.patchwork/.env" ]]; then
|
|
448
|
+
set -a; source "$HOME/.patchwork/.env"; set +a
|
|
393
449
|
fi
|
|
394
450
|
BRIDGE_PORT=$(basename "$LOCK_FILE" .lock)
|
|
395
451
|
# Call `next dev -p` directly. `npm run dev` hardcodes `-p 3200`, so
|
|
396
452
|
# `--dashboard-port` previously only changed the printed URL while
|
|
397
453
|
# Next.js stayed on 3200. Bypassing the npm script makes the flag
|
|
398
454
|
# actually configure the dev server end-to-end.
|
|
399
|
-
DASHBOARD_CMD="cd $(printf '%q' "$DASHBOARD_DIR") && PATCHWORK_BRIDGE_PORT=${BRIDGE_PORT} npx next dev -p ${DASHBOARD_PORT}"
|
|
455
|
+
DASHBOARD_CMD="cd $(printf '%q' "$DASHBOARD_DIR") && PATCHWORK_BRIDGE_PORT=${BRIDGE_PORT} DASHBOARD_PASSWORD=$(printf '%q' "${DASHBOARD_PASSWORD:-}") DASHBOARD_SESSION_SECRET=$(printf '%q' "${DASHBOARD_SESSION_SECRET:-}") npx next dev -p ${DASHBOARD_PORT}"
|
|
400
456
|
notify "Starting dashboard on http://localhost:${DASHBOARD_PORT}"
|
|
401
457
|
tmux send-keys -t "${SESSION}:0.4" "$DASHBOARD_CMD" Enter
|
|
402
458
|
# Poll the dashboard port until Next.js answers, then open the browser.
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#Requires -Version 5.1
|
|
2
|
+
<#
|
|
3
|
+
.SYNOPSIS
|
|
4
|
+
Windows orchestrator launcher — bridges multiple IDE windows simultaneously.
|
|
5
|
+
|
|
6
|
+
.DESCRIPTION
|
|
7
|
+
Starts the meta-bridge that coordinates multiple IDE windows. Each IDE window
|
|
8
|
+
must already have the claude-ide-bridge extension running — this script
|
|
9
|
+
connects to them all via the orchestrator mode.
|
|
10
|
+
|
|
11
|
+
Run via npm:
|
|
12
|
+
npm run start-orchestrator:win
|
|
13
|
+
|
|
14
|
+
Or directly:
|
|
15
|
+
pwsh -File scripts\start-orchestrator.ps1
|
|
16
|
+
pwsh -File scripts\start-orchestrator.ps1 -Port 4746 -Verbose
|
|
17
|
+
|
|
18
|
+
.PARAMETER Port
|
|
19
|
+
Orchestrator port (default: 4746).
|
|
20
|
+
|
|
21
|
+
.PARAMETER Notify
|
|
22
|
+
ntfy.sh topic for push notifications (optional).
|
|
23
|
+
|
|
24
|
+
.PARAMETER Verbose
|
|
25
|
+
Enable verbose orchestrator logging.
|
|
26
|
+
#>
|
|
27
|
+
[CmdletBinding()]
|
|
28
|
+
param(
|
|
29
|
+
[int] $Port = 4746,
|
|
30
|
+
[string]$Notify = "",
|
|
31
|
+
[switch]$VerboseLogging
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
Set-StrictMode -Version Latest
|
|
35
|
+
$ErrorActionPreference = "Stop"
|
|
36
|
+
|
|
37
|
+
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
38
|
+
$BridgeDir = Split-Path -Parent $ScriptDir
|
|
39
|
+
|
|
40
|
+
function Write-Status($msg) { Write-Host "[orchestrator] $msg" -ForegroundColor Cyan }
|
|
41
|
+
function Write-Ok($msg) { Write-Host "[ok] $msg" -ForegroundColor Green }
|
|
42
|
+
function Write-Warn($msg) { Write-Host "[warn] $msg" -ForegroundColor Yellow }
|
|
43
|
+
|
|
44
|
+
function Send-Notify($msg) {
|
|
45
|
+
if (-not $Notify) { return }
|
|
46
|
+
try {
|
|
47
|
+
Invoke-RestMethod -Uri "https://ntfy.sh/$Notify" -Method Post -Body $msg -TimeoutSec 5 | Out-Null
|
|
48
|
+
} catch { Write-Warn "ntfy notification failed: $_" }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
$Jobs = [System.Collections.Generic.List[System.Diagnostics.Process]]::new()
|
|
52
|
+
|
|
53
|
+
function Stop-AllJobs {
|
|
54
|
+
foreach ($p in $Jobs) {
|
|
55
|
+
if (-not $p.HasExited) { try { $p.Kill($true) } catch { } }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
$null = Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action { Stop-AllJobs }
|
|
60
|
+
|
|
61
|
+
# ── Dependency check ──────────────────────────────────────────────────────────
|
|
62
|
+
$claudeFound = $false
|
|
63
|
+
try {
|
|
64
|
+
$null = & where.exe claude 2>$null
|
|
65
|
+
$claudeFound = $true
|
|
66
|
+
} catch { }
|
|
67
|
+
|
|
68
|
+
if (-not $claudeFound) {
|
|
69
|
+
Write-Error "claude CLI not found on PATH. Install from https://docs.anthropic.com/en/docs/claude-code"
|
|
70
|
+
exit 1
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# ── Build orchestrator args ───────────────────────────────────────────────────
|
|
74
|
+
$orchArgs = @("orchestrator", "--port", $Port)
|
|
75
|
+
if ($VerboseLogging) { $orchArgs += "--verbose" }
|
|
76
|
+
|
|
77
|
+
# Use dist/ (npm install) or fallback message
|
|
78
|
+
$distIndex = Join-Path $BridgeDir "dist\index.js"
|
|
79
|
+
if (-not (Test-Path $distIndex)) {
|
|
80
|
+
Write-Error "dist/index.js not found. Run 'npm run build' first."
|
|
81
|
+
exit 1
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# ── Start orchestrator bridge ─────────────────────────────────────────────────
|
|
85
|
+
Write-Status "Starting orchestrator bridge on port $Port..."
|
|
86
|
+
|
|
87
|
+
$orchInfo = New-Object System.Diagnostics.ProcessStartInfo
|
|
88
|
+
$orchInfo.FileName = "cmd.exe"
|
|
89
|
+
$orchInfo.Arguments = "/c node `"$distIndex`" " + ($orchArgs -join " ")
|
|
90
|
+
$orchInfo.UseShellExecute = $false
|
|
91
|
+
$orchInfo.WorkingDirectory = $BridgeDir
|
|
92
|
+
$orchProc = [System.Diagnostics.Process]::Start($orchInfo)
|
|
93
|
+
$Jobs.Add($orchProc)
|
|
94
|
+
|
|
95
|
+
# ── Wait for lock file ────────────────────────────────────────────────────────
|
|
96
|
+
$ClaudeBase = if ($env:CLAUDE_CONFIG_DIR) { $env:CLAUDE_CONFIG_DIR } else { Join-Path $env:USERPROFILE ".claude" }
|
|
97
|
+
$IdeDir = Join-Path $ClaudeBase "ide"
|
|
98
|
+
$LockFile = Join-Path $IdeDir "$Port.lock"
|
|
99
|
+
$Deadline = (Get-Date).AddSeconds(20)
|
|
100
|
+
|
|
101
|
+
Write-Status "Waiting for orchestrator lock file..."
|
|
102
|
+
while ((Get-Date) -lt $Deadline -and -not (Test-Path $LockFile)) {
|
|
103
|
+
Start-Sleep -Milliseconds 200
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (-not (Test-Path $LockFile)) {
|
|
107
|
+
Write-Error "Orchestrator lock file not written after 20s. Bridge may have failed to start."
|
|
108
|
+
Stop-AllJobs
|
|
109
|
+
exit 1
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
$lockContent = Get-Content $LockFile -Raw | ConvertFrom-Json
|
|
114
|
+
$token = $lockContent.authToken
|
|
115
|
+
} catch {
|
|
116
|
+
$token = "(unknown)"
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
Write-Ok "Orchestrator ready on port $Port"
|
|
120
|
+
Send-Notify "Orchestrator started on port $Port"
|
|
121
|
+
|
|
122
|
+
# ── Start Claude --ide ────────────────────────────────────────────────────────
|
|
123
|
+
Write-Status "Starting claude --ide (connects to orchestrator)..."
|
|
124
|
+
|
|
125
|
+
$claudeEnv = [System.Collections.Generic.Dictionary[string,string]]::new()
|
|
126
|
+
foreach ($entry in [System.Environment]::GetEnvironmentVariables().GetEnumerator()) {
|
|
127
|
+
$claudeEnv[$entry.Key] = $entry.Value
|
|
128
|
+
}
|
|
129
|
+
$claudeEnv["CLAUDE_CODE_IDE_SKIP_VALID_CHECK"] = "true"
|
|
130
|
+
|
|
131
|
+
$claudeInfo = New-Object System.Diagnostics.ProcessStartInfo
|
|
132
|
+
$claudeInfo.FileName = "cmd.exe"
|
|
133
|
+
$claudeInfo.Arguments = "/c claude --ide"
|
|
134
|
+
$claudeInfo.UseShellExecute = $false
|
|
135
|
+
foreach ($kv in $claudeEnv.GetEnumerator()) {
|
|
136
|
+
$claudeInfo.EnvironmentVariables[$kv.Key] = $kv.Value
|
|
137
|
+
}
|
|
138
|
+
$claudeProc = [System.Diagnostics.Process]::Start($claudeInfo)
|
|
139
|
+
$Jobs.Add($claudeProc)
|
|
140
|
+
|
|
141
|
+
# ── Summary ───────────────────────────────────────────────────────────────────
|
|
142
|
+
Write-Host ""
|
|
143
|
+
Write-Ok "Orchestrator running. Press Ctrl+C to stop all processes."
|
|
144
|
+
Write-Host " Orchestrator PID : $($orchProc.Id)"
|
|
145
|
+
Write-Host " Claude PID : $($claudeProc.Id)"
|
|
146
|
+
Write-Host " Port : $Port"
|
|
147
|
+
Write-Host " Token : $($token.Substring(0, [Math]::Min(8, $token.Length)))..."
|
|
148
|
+
Write-Host ""
|
|
149
|
+
Write-Host "Each IDE window with the bridge extension running will be discovered"
|
|
150
|
+
Write-Host "automatically. Type /ide in Claude Code to verify the connection."
|
|
151
|
+
Write-Host ""
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
$orchProc.WaitForExit()
|
|
155
|
+
} finally {
|
|
156
|
+
Write-Status "Orchestrator exited — stopping all processes..."
|
|
157
|
+
Stop-AllJobs
|
|
158
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Cross-platform auto-restart wrapper for claude remote-control.
|
|
4
|
+
* Replaces start-remote.sh — works on Windows, macOS, and Linux without tmux.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* node scripts/start-remote.mjs [--notify <ntfy-topic>]
|
|
8
|
+
* npm run remote:node
|
|
9
|
+
*
|
|
10
|
+
* Controls:
|
|
11
|
+
* Ctrl+C — exit cleanly (no restart)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { spawn } from "node:child_process";
|
|
15
|
+
|
|
16
|
+
const args = process.argv.slice(2);
|
|
17
|
+
function flag(name) {
|
|
18
|
+
const i = args.indexOf(name);
|
|
19
|
+
return i !== -1 ? (args[i + 1] ?? null) : null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const NTFY_TOPIC = flag("--notify") ?? "";
|
|
23
|
+
const RESTART_BASE_MS = 5_000;
|
|
24
|
+
const RESTART_MAX_MS = 300_000;
|
|
25
|
+
const HEALTHY_MS = 60_000;
|
|
26
|
+
const MAX_FAILURES = 50;
|
|
27
|
+
const IS_WIN = process.platform === "win32";
|
|
28
|
+
|
|
29
|
+
function ts() {
|
|
30
|
+
return new Date().toLocaleTimeString();
|
|
31
|
+
}
|
|
32
|
+
function log(msg) {
|
|
33
|
+
process.stdout.write(`[${ts()}] ${msg}\n`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function notify(msg, priority = "default") {
|
|
37
|
+
if (!NTFY_TOPIC) return;
|
|
38
|
+
fetch(`https://ntfy.sh/${NTFY_TOPIC}`, {
|
|
39
|
+
method: "POST",
|
|
40
|
+
body: msg,
|
|
41
|
+
headers: { Title: "Claude Remote", Priority: priority },
|
|
42
|
+
signal: AbortSignal.timeout(10_000),
|
|
43
|
+
}).catch(() => {});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
console.log("=== Remote Control auto-restart wrapper ===");
|
|
47
|
+
console.log(" Ctrl+C to exit cleanly");
|
|
48
|
+
if (NTFY_TOPIC) console.log(` Push notifications: ntfy.sh/${NTFY_TOPIC}`);
|
|
49
|
+
console.log("");
|
|
50
|
+
|
|
51
|
+
let stopping = false;
|
|
52
|
+
let delayMs = RESTART_BASE_MS;
|
|
53
|
+
let failures = 0;
|
|
54
|
+
let currentProc = null;
|
|
55
|
+
|
|
56
|
+
process.on("SIGINT", () => {
|
|
57
|
+
stopping = true;
|
|
58
|
+
currentProc?.kill();
|
|
59
|
+
});
|
|
60
|
+
process.on("SIGTERM", () => {
|
|
61
|
+
stopping = true;
|
|
62
|
+
currentProc?.kill();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
async function sleep(ms) {
|
|
66
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
while (!stopping) {
|
|
70
|
+
const startMs = Date.now();
|
|
71
|
+
|
|
72
|
+
const exitCode = await new Promise((resolve) => {
|
|
73
|
+
currentProc = spawn(
|
|
74
|
+
IS_WIN ? "cmd.exe" : "claude",
|
|
75
|
+
IS_WIN
|
|
76
|
+
? ["/c", "claude", "remote-control", "--spawn=session"]
|
|
77
|
+
: ["remote-control", "--spawn=session"],
|
|
78
|
+
{ stdio: "inherit", shell: false },
|
|
79
|
+
);
|
|
80
|
+
currentProc.on("exit", (code) => resolve(code ?? 0));
|
|
81
|
+
currentProc.on("error", (err) => {
|
|
82
|
+
log(`Spawn error: ${err.message}`);
|
|
83
|
+
resolve(1);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
currentProc = null;
|
|
88
|
+
if (stopping) break;
|
|
89
|
+
|
|
90
|
+
// Ctrl+C propagated from child exits with 130
|
|
91
|
+
if (exitCode === 130) {
|
|
92
|
+
log("Exited by user.");
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const elapsed = Date.now() - startMs;
|
|
97
|
+
if (elapsed >= HEALTHY_MS) {
|
|
98
|
+
failures = 0;
|
|
99
|
+
delayMs = RESTART_BASE_MS;
|
|
100
|
+
} else {
|
|
101
|
+
failures++;
|
|
102
|
+
delayMs = Math.min(
|
|
103
|
+
RESTART_BASE_MS * 2 ** Math.min(failures - 1, 6),
|
|
104
|
+
RESTART_MAX_MS,
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (failures >= MAX_FAILURES) {
|
|
109
|
+
log(`Too many consecutive failures (${MAX_FAILURES}). Giving up.`);
|
|
110
|
+
notify(`Circuit breaker: ${MAX_FAILURES} failures. Giving up.`, "high");
|
|
111
|
+
process.exit(1);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
log(
|
|
115
|
+
`Remote control disconnected (exit ${exitCode}). Restarting in ${delayMs / 1000}s...`,
|
|
116
|
+
);
|
|
117
|
+
notify(
|
|
118
|
+
`Disconnected (exit ${exitCode}). Restarting in ${delayMs / 1000}s...`,
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
await sleep(delayMs);
|
|
122
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": "recipe-authoring — runs preflight automatically when a .yaml recipe file is saved. Closes the authoring inner loop: edit → save → instant validation feedback via Claude task.",
|
|
3
|
-
"_usage": "Copy to automation-policy.json. Requires --automation --automation-policy <path> --
|
|
3
|
+
"_usage": "Copy to automation-policy.json. Requires --automation --automation-policy <path> --driver subprocess",
|
|
4
4
|
|
|
5
5
|
"automationSystemPrompt": "Recipe lint bot. ≤10 lines. No preamble. List issues with file:line if available. End with 'Recipe OK' when clean.",
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": "security-first — monitors auth, payment, and API surface for vulnerabilities on every relevant change.",
|
|
3
|
-
"_usage": "Copy to automation-policy.json. Requires --automation --automation-policy <path> --
|
|
3
|
+
"_usage": "Copy to automation-policy.json. Requires --automation --automation-policy <path> --driver subprocess",
|
|
4
4
|
|
|
5
5
|
"automationSystemPrompt": "Automation bot. Drop articles/filler. Fragments OK. Abbreviate: DB/auth/config/req/res/fn. X→Y arrows. ≤5 lines. No preamble. Call tools → report results only.",
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": "strict-lint — triggers on every save and error, enforces zero-warning policy.",
|
|
3
|
-
"_usage": "Copy to automation-policy.json. Requires --automation --automation-policy <path> --
|
|
3
|
+
"_usage": "Copy to automation-policy.json. Requires --automation --automation-policy <path> --driver subprocess",
|
|
4
4
|
|
|
5
5
|
"automationSystemPrompt": "Automation bot. Drop articles/filler. Fragments OK. Abbreviate: DB/auth/config/req/res/fn. X→Y arrows. ≤5 lines. No preamble. Call tools → report results only.",
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": "test-driven — enforces test coverage and runs tests automatically on every relevant change.",
|
|
3
|
-
"_usage": "Copy to automation-policy.json. Requires --automation --automation-policy <path> --
|
|
3
|
+
"_usage": "Copy to automation-policy.json. Requires --automation --automation-policy <path> --driver subprocess",
|
|
4
4
|
|
|
5
5
|
"automationSystemPrompt": "Automation bot. Drop articles/filler. Fragments OK. Abbreviate: DB/auth/config/req/res/fn. X→Y arrows. ≤5 lines. No preamble. Call tools → report results only.",
|
|
6
6
|
|