patchcord 0.6.41 → 0.6.42
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/.claude-plugin/plugin.json +1 -1
- package/harnesses.json +228 -0
- package/package.json +3 -2
package/harnesses.json
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": [
|
|
3
|
+
"Machine-readable harness capability registry. Consumed by mux (lead@mux-v2) to decide",
|
|
4
|
+
"whether a seat can hold a Patchcord listener and whether two seats may share a host.",
|
|
5
|
+
"",
|
|
6
|
+
"TWO SCOPE FIELDS ON PURPOSE. `installer_scope` is where OUR installer writes.",
|
|
7
|
+
"`harness_scope` is what the HARNESS itself supports. They are not the same question and",
|
|
8
|
+
"conflating them is what this file exists to prevent: in one thread I answered three",
|
|
9
|
+
"harness-capability questions with installer behaviour and was wrong all three times.",
|
|
10
|
+
"hermes is the worked example — our installer writes one global file, and hermes supports",
|
|
11
|
+
"many isolated profiles. 'Our installer writes X' never implies 'the harness only does X'.",
|
|
12
|
+
"",
|
|
13
|
+
"EVIDENCE IS EARNED, NOT TYPED. This file may only ever say \"declared\" or \"absent\".",
|
|
14
|
+
"\"tested\" is not a legal value here — it lives in tests/test-harness-registry.mjs, in a",
|
|
15
|
+
"list that names what was observed and by whom. A writer can type a confident guess into",
|
|
16
|
+
"a data file; a writer cannot type an observation into a test they did not run. If you",
|
|
17
|
+
"believe a row deserves \"tested\", add it there with the observation, not here.",
|
|
18
|
+
"",
|
|
19
|
+
"Any row whose listener.wake is not \"none\" MUST have a real subscribe path on disk, or",
|
|
20
|
+
"carry blocked_reason saying why not. hermes is why: it HAS a subscribe skill directory",
|
|
21
|
+
"and, until 0.6.41, could not actually be armed. Directory presence is necessary, never",
|
|
22
|
+
"sufficient."
|
|
23
|
+
],
|
|
24
|
+
"version": 1,
|
|
25
|
+
"harnesses": [
|
|
26
|
+
{
|
|
27
|
+
"id": "claude_code",
|
|
28
|
+
"aliases": ["claude"],
|
|
29
|
+
"cli": "claude",
|
|
30
|
+
"kind": "terminal",
|
|
31
|
+
"installer_scope": "project",
|
|
32
|
+
"installer_config": ".mcp.json",
|
|
33
|
+
"harness_scope": "project",
|
|
34
|
+
"listener": {
|
|
35
|
+
"wake": "realtime",
|
|
36
|
+
"mechanism": "subscribe-skill-under-monitor",
|
|
37
|
+
"self_arm": true,
|
|
38
|
+
"survives_wake": true,
|
|
39
|
+
"evidence": "declared"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"id": "codex",
|
|
44
|
+
"aliases": [],
|
|
45
|
+
"cli": "codex",
|
|
46
|
+
"kind": "terminal",
|
|
47
|
+
"installer_scope": "project",
|
|
48
|
+
"installer_config": ".codex/config.toml",
|
|
49
|
+
"harness_scope": "project",
|
|
50
|
+
"listener": {
|
|
51
|
+
"wake": "none",
|
|
52
|
+
"mechanism": "stop-hook-nudge-only",
|
|
53
|
+
"self_arm": false,
|
|
54
|
+
"survives_wake": null,
|
|
55
|
+
"evidence": "declared",
|
|
56
|
+
"note": "A stop hook fires at the END of a turn. An idle codex seat hears nothing. No subscribe skill exists for codex in this package."
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"id": "cursor",
|
|
61
|
+
"aliases": [],
|
|
62
|
+
"cli": "cursor-agent",
|
|
63
|
+
"kind": "terminal",
|
|
64
|
+
"installer_scope": "project",
|
|
65
|
+
"installer_config": ".cursor/mcp.json",
|
|
66
|
+
"harness_scope": "unknown",
|
|
67
|
+
"listener": {
|
|
68
|
+
"wake": "realtime",
|
|
69
|
+
"mechanism": "subscribe-skill-background-shell",
|
|
70
|
+
"self_arm": true,
|
|
71
|
+
"survives_wake": null,
|
|
72
|
+
"evidence": "declared",
|
|
73
|
+
"note": "The skill claims it wakes the agent. Nobody in this repo has watched it happen."
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"id": "grok",
|
|
78
|
+
"aliases": ["grok_cli", "grok_build"],
|
|
79
|
+
"cli": "grok",
|
|
80
|
+
"kind": "terminal",
|
|
81
|
+
"installer_scope": "project",
|
|
82
|
+
"installer_config": ".grok/config.toml",
|
|
83
|
+
"harness_scope": "project",
|
|
84
|
+
"listener": {
|
|
85
|
+
"wake": "realtime",
|
|
86
|
+
"mechanism": "subscribe-skill",
|
|
87
|
+
"self_arm": true,
|
|
88
|
+
"survives_wake": null,
|
|
89
|
+
"evidence": "declared",
|
|
90
|
+
"note": "Grok resolves configs from cwd up to the git root, so per-seat identity works. Wake is claimed by the skill, not observed."
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"id": "opencode",
|
|
95
|
+
"aliases": [],
|
|
96
|
+
"cli": "opencode",
|
|
97
|
+
"kind": "terminal",
|
|
98
|
+
"installer_scope": "project",
|
|
99
|
+
"installer_config": "opencode.json",
|
|
100
|
+
"harness_scope": "unknown",
|
|
101
|
+
"listener": {
|
|
102
|
+
"wake": "realtime",
|
|
103
|
+
"mechanism": "installed-plugin",
|
|
104
|
+
"self_arm": true,
|
|
105
|
+
"survives_wake": true,
|
|
106
|
+
"evidence": "declared",
|
|
107
|
+
"note": "The installer writes .opencode/plugins/patchcord.js, which spawns `patchcord subscribe` and calls client.session.prompt() on each message. It prompts on the realtime event rather than session.idle deliberately: session.idle re-prompting has a teardown race in headless `opencode run`."
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"id": "kimi",
|
|
112
|
+
"aliases": [],
|
|
113
|
+
"cli": "kimi",
|
|
114
|
+
"kind": "terminal",
|
|
115
|
+
"installer_scope": "project",
|
|
116
|
+
"installer_config": ".kimi-code/mcp.json",
|
|
117
|
+
"harness_scope": "unknown",
|
|
118
|
+
"listener": {
|
|
119
|
+
"wake": "poll",
|
|
120
|
+
"mechanism": "poll-script",
|
|
121
|
+
"self_arm": true,
|
|
122
|
+
"survives_wake": false,
|
|
123
|
+
"evidence": "declared",
|
|
124
|
+
"note": "NOT realtime. patchcord-subscribe.sh polls /api/inbox and EXITS 0 on a pending count; Kimi starts a turn when a background task reaches a terminal state. So the listener dies on every delivery and the agent must re-arm it. Re-arm is the failure point: an agent that skips it is silently deaf from then on."
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"id": "hermes",
|
|
129
|
+
"aliases": [],
|
|
130
|
+
"cli": "hermes",
|
|
131
|
+
"kind": "terminal",
|
|
132
|
+
"installer_scope": "global",
|
|
133
|
+
"installer_config": "~/.hermes/config.yaml",
|
|
134
|
+
"harness_scope": "per-profile",
|
|
135
|
+
"installer_defect": "The path is hardcoded to ~/.hermes/config.yaml. The installer never calls `hermes config path` and does not know profiles exist, so installing while a non-default profile is active writes the DEFAULT profile's config — the wrong file, silently. Not fixed as of 0.6.41.",
|
|
136
|
+
"listener": {
|
|
137
|
+
"wake": "realtime",
|
|
138
|
+
"mechanism": "webhook-bridge",
|
|
139
|
+
"self_arm": false,
|
|
140
|
+
"survives_wake": true,
|
|
141
|
+
"evidence": "declared",
|
|
142
|
+
"note": "`patchcord subscribe --hermes` POSTs to a Hermes gateway webhook per message; the gateway injects a prompt. No re-arm needed. self_arm is false: a human creates the route and starts the bridge once. A deploy that waits N seconds for a SEAT-started listener will fail hermes forever while hermes is fully push-capable.",
|
|
143
|
+
"blocked_until": "0.6.41",
|
|
144
|
+
"blocked_reason": "Before 0.6.41 the `patchcord subscribe` wrapper spawned subscribe.mjs with no arguments, so --hermes never reached the child that gates on it. The env var arrived, the flag did not, the flag is the gate. The bridge was unreachable by its own documented command and failed silently. Fixed; not yet observed end to end."
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"id": "antigravity",
|
|
149
|
+
"aliases": ["agy"],
|
|
150
|
+
"cli": "antigravity",
|
|
151
|
+
"kind": "terminal",
|
|
152
|
+
"installer_scope": "project",
|
|
153
|
+
"installer_config": ".agents/mcp_config.json",
|
|
154
|
+
"harness_scope": "unknown",
|
|
155
|
+
"listener": {
|
|
156
|
+
"wake": "none",
|
|
157
|
+
"mechanism": null,
|
|
158
|
+
"self_arm": false,
|
|
159
|
+
"survives_wake": null,
|
|
160
|
+
"evidence": "declared",
|
|
161
|
+
"note": "No subscribe skill of any kind in this package."
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"id": "openclaw",
|
|
166
|
+
"aliases": [],
|
|
167
|
+
"cli": "openclaw",
|
|
168
|
+
"kind": "terminal",
|
|
169
|
+
"installer_scope": "unknown",
|
|
170
|
+
"installer_config": "~/.openclaw/openclaw.json",
|
|
171
|
+
"harness_scope": "unknown",
|
|
172
|
+
"listener": {
|
|
173
|
+
"wake": "none",
|
|
174
|
+
"mechanism": null,
|
|
175
|
+
"self_arm": false,
|
|
176
|
+
"survives_wake": null,
|
|
177
|
+
"evidence": "absent",
|
|
178
|
+
"note": "installer_scope is unknown, not global. We PREFER `openclaw mcp set patchcord`, so openclaw decides where the entry lands; the ~/.openclaw path is only our fallback when that CLI is missing. Nobody here has openclaw installed. Do not refuse a second openclaw seat on the strength of this row — refuse on a test or not at all."
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"id": "windsurf",
|
|
183
|
+
"aliases": [],
|
|
184
|
+
"cli": null,
|
|
185
|
+
"kind": "editor",
|
|
186
|
+
"installer_scope": "global",
|
|
187
|
+
"installer_config": "~/.codeium/windsurf/mcp_config.json",
|
|
188
|
+
"harness_scope": "unknown",
|
|
189
|
+
"listener": { "wake": "none", "mechanism": null, "self_arm": false, "survives_wake": null, "evidence": "declared" }
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"id": "vscode",
|
|
193
|
+
"aliases": [],
|
|
194
|
+
"cli": null,
|
|
195
|
+
"kind": "editor",
|
|
196
|
+
"installer_scope": "project",
|
|
197
|
+
"installer_config": ".vscode/mcp.json",
|
|
198
|
+
"harness_scope": "unknown",
|
|
199
|
+
"listener": { "wake": "none", "mechanism": null, "self_arm": false, "survives_wake": null, "evidence": "declared" }
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"id": "zed",
|
|
203
|
+
"aliases": [],
|
|
204
|
+
"cli": null,
|
|
205
|
+
"kind": "editor",
|
|
206
|
+
"installer_scope": "global",
|
|
207
|
+
"installer_config": "~/.config/zed/settings.json",
|
|
208
|
+
"harness_scope": "unknown",
|
|
209
|
+
"listener": { "wake": "none", "mechanism": null, "self_arm": false, "survives_wake": null, "evidence": "declared" }
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"id": "cline",
|
|
213
|
+
"aliases": [],
|
|
214
|
+
"cli": null,
|
|
215
|
+
"kind": "editor",
|
|
216
|
+
"installer_scope": "global",
|
|
217
|
+
"installer_config": "cline_mcp_settings.json (VS Code globalStorage)",
|
|
218
|
+
"harness_scope": "unknown",
|
|
219
|
+
"listener": { "wake": "none", "mechanism": null, "self_arm": false, "survives_wake": null, "evidence": "declared" }
|
|
220
|
+
}
|
|
221
|
+
],
|
|
222
|
+
"retired": [
|
|
223
|
+
{
|
|
224
|
+
"id": "gemini",
|
|
225
|
+
"reason": "Retired as an install target; Antigravity covers Google's agent. CLIENT_TYPE_MAP slot \"5\" is left UNASSIGNED rather than reused, so a stale connect page sending client_type=gemini falls through to no choice instead of silently configuring a different harness and writing someone's token to the wrong file. Do not mirror the gap as a bug and do not fill it."
|
|
226
|
+
}
|
|
227
|
+
]
|
|
228
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "patchcord",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.42",
|
|
4
4
|
"description": "Cross-machine agent messaging for Claude Code and Codex",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"version": "node scripts/sync-plugin-version.mjs && git add .claude-plugin/plugin.json"
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"per-project-skills/",
|
|
33
33
|
"commands/",
|
|
34
34
|
"README.md",
|
|
35
|
-
"plugins/"
|
|
35
|
+
"plugins/",
|
|
36
|
+
"harnesses.json"
|
|
36
37
|
]
|
|
37
38
|
}
|