open-research-protocol 0.4.2 → 0.4.4
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.md +42 -9
- package/cli/orp.py +9770 -2497
- package/docs/AGENT_LOOP.md +4 -2
- package/docs/CANONICAL_CLI_BOUNDARY.md +337 -0
- package/docs/NPM_RELEASE_CHECKLIST.md +42 -10
- package/docs/ORP_LINK_RUNNER_PLAN.md +521 -0
- package/docs/ORP_PUBLIC_LAUNCH_CHECKLIST.md +24 -1
- package/docs/RUNNER_INTERNAL_OPERATIONS.md +107 -0
- package/package.json +3 -2
- package/scripts/npm-prepublish-guard.js +55 -0
- package/scripts/orp-release-smoke.sh +234 -0
- package/spec/v1/link-project.schema.json +57 -0
- package/spec/v1/link-session.schema.json +97 -0
- package/spec/v1/runner-machine.schema.json +48 -0
- package/spec/v1/runner-runtime.schema.json +130 -0
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
# ORP Link And Runner Plan
|
|
2
|
+
|
|
3
|
+
Use this document as the implementation plan for making project linking, session linking, and hosted runner delivery first-class ORP CLI features.
|
|
4
|
+
|
|
5
|
+
## Goal
|
|
6
|
+
|
|
7
|
+
Make the npm/CLI package the source of truth for:
|
|
8
|
+
|
|
9
|
+
- linking a local repo to a hosted ORP idea/world
|
|
10
|
+
- linking one or more local ORP sessions to live Codex sessions
|
|
11
|
+
- syncing machine/project/session availability to the hosted app
|
|
12
|
+
- receiving hosted jobs and routing them to the correct local Codex session
|
|
13
|
+
|
|
14
|
+
The Rust desktop app should remain the best UX for session discovery, terminal/window management, and local operator flow, but it should rely on the CLI-owned contract instead of maintaining a divergent one.
|
|
15
|
+
|
|
16
|
+
## Current State
|
|
17
|
+
|
|
18
|
+
What already exists:
|
|
19
|
+
|
|
20
|
+
- The CLI already supports project/world binding through `orp world bind`.
|
|
21
|
+
- The CLI already supports hosted auth, hosted ideas, hosted world inspection, hosted checkpoint queueing, and a checkpoint-oriented worker surface.
|
|
22
|
+
- The Rust app already shells out to `orp world bind` when linking a project.
|
|
23
|
+
- The Rust app already has a machine-runner sync and targeted prompt execution model based on linked projects and linked sessions.
|
|
24
|
+
|
|
25
|
+
What is misaligned:
|
|
26
|
+
|
|
27
|
+
- The Rust app stores local project/session state in `.orp/...`.
|
|
28
|
+
- The CLI stores repo governance state in `orp/` and `.git/orp/runtime.json`.
|
|
29
|
+
- Project binding exists as a low-level CLI command, but there is no CLI-owned project/session registry surface yet.
|
|
30
|
+
- There are effectively two worker lanes:
|
|
31
|
+
- checkpoint worker lane in the CLI
|
|
32
|
+
- machine-runner prompt lane in the Rust app
|
|
33
|
+
|
|
34
|
+
## Product Boundary
|
|
35
|
+
|
|
36
|
+
The CLI should own:
|
|
37
|
+
|
|
38
|
+
- the machine-readable project link format
|
|
39
|
+
- the machine-readable linked session format
|
|
40
|
+
- the machine runner sync format
|
|
41
|
+
- the hosted runner work loop contract
|
|
42
|
+
|
|
43
|
+
The Rust app should own:
|
|
44
|
+
|
|
45
|
+
- desktop UI
|
|
46
|
+
- session discovery
|
|
47
|
+
- session/window/tab management
|
|
48
|
+
- calling the CLI for canonical project/session link operations
|
|
49
|
+
|
|
50
|
+
## Canonical Concepts
|
|
51
|
+
|
|
52
|
+
### Linked Project
|
|
53
|
+
|
|
54
|
+
A linked project is a local repo that is associated with one hosted idea/world.
|
|
55
|
+
|
|
56
|
+
Required fields:
|
|
57
|
+
|
|
58
|
+
- `idea_id`
|
|
59
|
+
- `project_root`
|
|
60
|
+
|
|
61
|
+
Important optional fields:
|
|
62
|
+
|
|
63
|
+
- `idea_title`
|
|
64
|
+
- `world_id`
|
|
65
|
+
- `world_name`
|
|
66
|
+
- `github_url`
|
|
67
|
+
- `linked_at_utc`
|
|
68
|
+
- `linked_email`
|
|
69
|
+
|
|
70
|
+
### Linked Session
|
|
71
|
+
|
|
72
|
+
A linked session is a machine-local ORP session that can route work into a specific Codex session.
|
|
73
|
+
|
|
74
|
+
Required fields:
|
|
75
|
+
|
|
76
|
+
- `orp_session_id`
|
|
77
|
+
- `label`
|
|
78
|
+
- `state`
|
|
79
|
+
|
|
80
|
+
Important optional fields:
|
|
81
|
+
|
|
82
|
+
- `codex_session_id`
|
|
83
|
+
- `project_root`
|
|
84
|
+
- `role`
|
|
85
|
+
- `terminal_target`
|
|
86
|
+
- `last_active_at_utc`
|
|
87
|
+
- `archived`
|
|
88
|
+
- `primary`
|
|
89
|
+
|
|
90
|
+
### Machine Runner
|
|
91
|
+
|
|
92
|
+
A machine runner is the machine-local worker identity exposed to the hosted app.
|
|
93
|
+
|
|
94
|
+
Required fields:
|
|
95
|
+
|
|
96
|
+
- `machine_id`
|
|
97
|
+
- `machine_name`
|
|
98
|
+
- `platform`
|
|
99
|
+
- `runner_enabled`
|
|
100
|
+
|
|
101
|
+
Important optional fields:
|
|
102
|
+
|
|
103
|
+
- `last_heartbeat_at_utc`
|
|
104
|
+
- `last_sync_at_utc`
|
|
105
|
+
- `app_version`
|
|
106
|
+
- `linked_email`
|
|
107
|
+
|
|
108
|
+
### Hosted Job
|
|
109
|
+
|
|
110
|
+
A hosted job is a transport-agnostic unit of work that can target a project or an exact linked session.
|
|
111
|
+
|
|
112
|
+
Required fields:
|
|
113
|
+
|
|
114
|
+
- `job_id`
|
|
115
|
+
- `kind`
|
|
116
|
+
- `status`
|
|
117
|
+
|
|
118
|
+
Important optional fields:
|
|
119
|
+
|
|
120
|
+
- `idea_id`
|
|
121
|
+
- `world_id`
|
|
122
|
+
- `machine_id`
|
|
123
|
+
- `project_root`
|
|
124
|
+
- `orp_session_id`
|
|
125
|
+
- `codex_session_id`
|
|
126
|
+
- `prompt`
|
|
127
|
+
- `lease_id`
|
|
128
|
+
- `created_at_utc`
|
|
129
|
+
- `started_at_utc`
|
|
130
|
+
- `finished_at_utc`
|
|
131
|
+
|
|
132
|
+
## Storage Plan
|
|
133
|
+
|
|
134
|
+
### Repo-tracked state
|
|
135
|
+
|
|
136
|
+
Keep repo governance where the CLI already writes it:
|
|
137
|
+
|
|
138
|
+
- `orp/governance.json`
|
|
139
|
+
- `orp/agent-policy.json`
|
|
140
|
+
- `orp/HANDOFF.md`
|
|
141
|
+
- `orp/checkpoints/CHECKPOINT_LOG.md`
|
|
142
|
+
- `orp/state.json`
|
|
143
|
+
|
|
144
|
+
### Repo-local machine state
|
|
145
|
+
|
|
146
|
+
Store machine-local link/session data under `.git/orp/link/` so it does not dirty the worktree or leak machine-specific identifiers into git history.
|
|
147
|
+
|
|
148
|
+
Planned files:
|
|
149
|
+
|
|
150
|
+
- `.git/orp/link/project.json`
|
|
151
|
+
- `.git/orp/link/sessions/<orp_session_id>.json`
|
|
152
|
+
- `.git/orp/link/runner.json`
|
|
153
|
+
- `.git/orp/link/runtime.json`
|
|
154
|
+
|
|
155
|
+
### Global machine state
|
|
156
|
+
|
|
157
|
+
Store cross-repo machine identity in the user config directory:
|
|
158
|
+
|
|
159
|
+
- `~/.config/orp/machine.json`
|
|
160
|
+
|
|
161
|
+
### Migration source
|
|
162
|
+
|
|
163
|
+
Treat the Rust app's `.orp/project.json` and `.orp/sessions/*.json` as import sources during migration, not as long-term canonical storage.
|
|
164
|
+
|
|
165
|
+
## Planned CLI Surface
|
|
166
|
+
|
|
167
|
+
### Project link commands
|
|
168
|
+
|
|
169
|
+
```sh
|
|
170
|
+
orp link project bind --idea-id <idea-id> [--idea-title <title>] [--github-url <url>] [--codex-session-id <session-id>] --json
|
|
171
|
+
orp link project show --json
|
|
172
|
+
orp link project status --json
|
|
173
|
+
orp link project unbind --json
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Behavior:
|
|
177
|
+
|
|
178
|
+
- `bind` should call the hosted `world bind` flow and write `.git/orp/link/project.json`.
|
|
179
|
+
- `show` should print the stored local linked-project record.
|
|
180
|
+
- `status` should combine:
|
|
181
|
+
- local stored link
|
|
182
|
+
- hosted world state
|
|
183
|
+
- local repo governance status
|
|
184
|
+
- whether at least one linked session exists
|
|
185
|
+
- `unbind` should remove the local link record and optionally leave the hosted world intact unless an explicit hosted unlink is requested later.
|
|
186
|
+
|
|
187
|
+
### Session link commands
|
|
188
|
+
|
|
189
|
+
```sh
|
|
190
|
+
orp link session discover --json
|
|
191
|
+
orp link session register --orp-session-id <orp-session-id> --codex-session-id <codex-session-id> --label <label> [--primary] --json
|
|
192
|
+
orp link session list --json
|
|
193
|
+
orp link session show <orp-session-id> --json
|
|
194
|
+
orp link session set-primary <orp_session_id> --json
|
|
195
|
+
orp link session archive <orp_session_id> --json
|
|
196
|
+
orp link session unarchive <orp_session_id> --json
|
|
197
|
+
orp link session remove <orp_session_id> --json
|
|
198
|
+
orp link session import-rust --json
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Behavior:
|
|
202
|
+
|
|
203
|
+
- `discover` should find candidate Codex sessions relevant to the current project root.
|
|
204
|
+
- `register` should create or update a linked session record under `.git/orp/link/sessions/`.
|
|
205
|
+
- `list` should show active plus archived sessions.
|
|
206
|
+
- `set-primary` should guarantee only one primary session per linked project.
|
|
207
|
+
- `import-rust` should ingest Rust `.orp/sessions/*.json` state into CLI storage.
|
|
208
|
+
|
|
209
|
+
### Link summary commands
|
|
210
|
+
|
|
211
|
+
```sh
|
|
212
|
+
orp link status --json
|
|
213
|
+
orp link doctor --json
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Behavior:
|
|
217
|
+
|
|
218
|
+
- `status` should provide a single machine-readable view of linked project, linked sessions, and runner readiness.
|
|
219
|
+
- `doctor` should validate stale paths, missing Codex session ids, moved repos, duplicate primaries, and missing hosted auth.
|
|
220
|
+
|
|
221
|
+
### Runner commands
|
|
222
|
+
|
|
223
|
+
```sh
|
|
224
|
+
orp runner status --json
|
|
225
|
+
orp runner enable --json
|
|
226
|
+
orp runner disable --json
|
|
227
|
+
orp runner sync --json
|
|
228
|
+
orp runner work --once --json
|
|
229
|
+
orp runner work --continuous --poll-interval 30 --json
|
|
230
|
+
orp runner cancel [<job-id>] [--lease-id <lease-id>] --json
|
|
231
|
+
orp runner retry [<job-id>] [--lease-id <lease-id>] --json
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Behavior:
|
|
235
|
+
|
|
236
|
+
- `status` should report machine runner state plus linked project/session counts.
|
|
237
|
+
- `enable` / `disable` should toggle the local runner state.
|
|
238
|
+
- `sync` should publish linked projects and linked sessions to the hosted service.
|
|
239
|
+
- `work` should poll or subscribe, claim jobs, route work to a selected linked session, append logs/messages, and complete or fail the job.
|
|
240
|
+
- `cancel` / `retry` should operate on the local active or most recent lease-aware runner state when explicit ids are omitted.
|
|
241
|
+
|
|
242
|
+
## File Schemas
|
|
243
|
+
|
|
244
|
+
Formal schemas live in:
|
|
245
|
+
|
|
246
|
+
- [link-project.schema.json](/Users/codymitchell/Documents/code/orp/spec/v1/link-project.schema.json)
|
|
247
|
+
- [link-session.schema.json](/Users/codymitchell/Documents/code/orp/spec/v1/link-session.schema.json)
|
|
248
|
+
- [runner-machine.schema.json](/Users/codymitchell/Documents/code/orp/spec/v1/runner-machine.schema.json)
|
|
249
|
+
- [runner-runtime.schema.json](/Users/codymitchell/Documents/code/orp/spec/v1/runner-runtime.schema.json)
|
|
250
|
+
|
|
251
|
+
Planned file locations and schema usage:
|
|
252
|
+
|
|
253
|
+
- `.git/orp/link/project.json` -> `spec/v1/link-project.schema.json`
|
|
254
|
+
- `.git/orp/link/sessions/<orp_session_id>.json` -> `spec/v1/link-session.schema.json`
|
|
255
|
+
- `.git/orp/link/runner.json` -> `spec/v1/runner-machine.schema.json`
|
|
256
|
+
- `.git/orp/link/runtime.json` -> `spec/v1/runner-runtime.schema.json`
|
|
257
|
+
|
|
258
|
+
## Hosted Contract
|
|
259
|
+
|
|
260
|
+
The hosted runner contract should be transport-agnostic.
|
|
261
|
+
|
|
262
|
+
Do not couple business logic to polling.
|
|
263
|
+
|
|
264
|
+
Required lifecycle:
|
|
265
|
+
|
|
266
|
+
1. `sync`
|
|
267
|
+
- machine publishes linked projects and linked sessions
|
|
268
|
+
2. `claim`
|
|
269
|
+
- worker claims one job or receives one via push
|
|
270
|
+
3. `start`
|
|
271
|
+
- worker marks the job running
|
|
272
|
+
4. `heartbeat`
|
|
273
|
+
- worker renews lease while executing
|
|
274
|
+
5. `message` / `log`
|
|
275
|
+
- worker publishes progress
|
|
276
|
+
6. `cancel` / `retry`
|
|
277
|
+
- operator or automation can explicitly interrupt or requeue lease-aware work
|
|
278
|
+
7. `complete` or `fail`
|
|
279
|
+
- worker posts final result
|
|
280
|
+
|
|
281
|
+
All lifecycle operations after `claim` should carry the same `lease_id`.
|
|
282
|
+
|
|
283
|
+
Transport options that should all work with the same contract:
|
|
284
|
+
|
|
285
|
+
- polling
|
|
286
|
+
- SSE
|
|
287
|
+
- WebSocket
|
|
288
|
+
|
|
289
|
+
## First Implementation Slice
|
|
290
|
+
|
|
291
|
+
Scope:
|
|
292
|
+
|
|
293
|
+
- establish CLI-owned local linked-project and linked-session storage
|
|
294
|
+
- expose project/session status and manipulation commands
|
|
295
|
+
- do not replace the Rust machine-runner execution path yet
|
|
296
|
+
|
|
297
|
+
### Slice 1 Checklist
|
|
298
|
+
|
|
299
|
+
- [x] Add local link helpers in `cli/orp.py` for:
|
|
300
|
+
- link root resolution
|
|
301
|
+
- reading/writing `.git/orp/link/project.json`
|
|
302
|
+
- reading/writing `.git/orp/link/sessions/*.json`
|
|
303
|
+
- loading and validating schema-compatible records
|
|
304
|
+
- [x] Add `orp link project bind`
|
|
305
|
+
- [x] Add `orp link project show`
|
|
306
|
+
- [x] Add `orp link project status`
|
|
307
|
+
- [x] Add `orp link project unbind`
|
|
308
|
+
- [x] Add `orp link session register`
|
|
309
|
+
- [x] Add `orp link session list`
|
|
310
|
+
- [x] Add `orp link session set-primary`
|
|
311
|
+
- [x] Add `orp link session archive`
|
|
312
|
+
- [x] Add `orp link session remove`
|
|
313
|
+
- [x] Add `orp link status`
|
|
314
|
+
- [x] Add `orp link doctor`
|
|
315
|
+
- [x] Add `orp link session import-rust`
|
|
316
|
+
- [x] Add tests for:
|
|
317
|
+
- bind writes project file
|
|
318
|
+
- bind reuses hosted `world bind`
|
|
319
|
+
- session register writes session file
|
|
320
|
+
- exactly one primary session is enforced
|
|
321
|
+
- archive/remove behaviors
|
|
322
|
+
- Rust import reads `.orp/project.json` and `.orp/sessions/*.json`
|
|
323
|
+
- `link status` reports hosted auth / project / session readiness correctly
|
|
324
|
+
|
|
325
|
+
### Slice 1 Non-goals
|
|
326
|
+
|
|
327
|
+
- no hosted runner protocol rewrite yet
|
|
328
|
+
- no SSE/WebSocket delivery work yet
|
|
329
|
+
- no deprecation of Rust session storage yet
|
|
330
|
+
- no UI migration yet
|
|
331
|
+
|
|
332
|
+
### Slice 1 Acceptance Criteria
|
|
333
|
+
|
|
334
|
+
- A linked project can be created entirely from the CLI.
|
|
335
|
+
- One or more linked sessions can be registered entirely from the CLI.
|
|
336
|
+
- The Rust app can keep calling `orp world bind`, but also has a documented path to mirror its session state into the CLI registry.
|
|
337
|
+
- `orp link status --json` can answer:
|
|
338
|
+
- is this repo linked?
|
|
339
|
+
- what idea/world is it linked to?
|
|
340
|
+
- what sessions are available?
|
|
341
|
+
- which session is primary?
|
|
342
|
+
- is the repo runner-ready?
|
|
343
|
+
|
|
344
|
+
## Second Implementation Slice
|
|
345
|
+
|
|
346
|
+
Scope:
|
|
347
|
+
|
|
348
|
+
- add CLI-owned machine runner identity and sync
|
|
349
|
+
- keep transport as polling first
|
|
350
|
+
|
|
351
|
+
Checklist:
|
|
352
|
+
|
|
353
|
+
- [x] Add `~/.config/orp/machine.json`
|
|
354
|
+
- [x] Add `orp runner status`
|
|
355
|
+
- [x] Add `orp runner enable`
|
|
356
|
+
- [x] Add `orp runner disable`
|
|
357
|
+
- [x] Add `orp runner sync`
|
|
358
|
+
- [x] Reuse the Rust app's current sync payload shape for compatibility
|
|
359
|
+
- [x] Add tests for runner state persistence and sync payload generation
|
|
360
|
+
|
|
361
|
+
## Third Implementation Slice
|
|
362
|
+
|
|
363
|
+
Scope:
|
|
364
|
+
|
|
365
|
+
- add CLI-owned runner work loop for `session.prompt`
|
|
366
|
+
|
|
367
|
+
Checklist:
|
|
368
|
+
|
|
369
|
+
- [x] Add `orp runner work --once`
|
|
370
|
+
- [x] Add `orp runner work --continuous`
|
|
371
|
+
- [x] Implement claim/start/log/message/complete/fail flow
|
|
372
|
+
- [x] Route jobs by:
|
|
373
|
+
- explicit `orp_session_id` first
|
|
374
|
+
- primary linked session second
|
|
375
|
+
- first active linked session with a `codex_session_id` third
|
|
376
|
+
- [x] Add lease heartbeat support
|
|
377
|
+
- [x] Add tests for selection logic and job completion/failure handling
|
|
378
|
+
|
|
379
|
+
## Rust App Integration Checklist
|
|
380
|
+
|
|
381
|
+
- [x] Replace direct hosted link persistence with CLI-owned project link files
|
|
382
|
+
- [x] Replace direct session persistence with CLI-owned session link files or mirrored writes
|
|
383
|
+
- [x] Call `orp link session register` when adopting or labeling a session
|
|
384
|
+
- [x] Call `orp link session archive` when archiving a session
|
|
385
|
+
- [x] Call `orp runner sync` when the app's linked-project/session state changes
|
|
386
|
+
- [x] Either:
|
|
387
|
+
- keep the current Rust worker temporarily but make it conform to CLI schemas, or
|
|
388
|
+
- replace it with a wrapper around `orp runner work`
|
|
389
|
+
|
|
390
|
+
## Migration Checklist
|
|
391
|
+
|
|
392
|
+
- [x] Add `orp link session import-rust`
|
|
393
|
+
- [x] Add `orp link import-rust --all`
|
|
394
|
+
- [x] Detect `.orp/project.json` and `.orp/sessions/*.json`
|
|
395
|
+
- [x] Preserve `world_id`, `idea_id`, `idea_title`, and linked email where available
|
|
396
|
+
- [x] Preserve session labels and active/closed state
|
|
397
|
+
- [x] Preserve archived and ignored session tracking where possible
|
|
398
|
+
- [x] Do not delete Rust files during the initial migration phase
|
|
399
|
+
|
|
400
|
+
## Remaining Hosted Platform Checklist
|
|
401
|
+
|
|
402
|
+
The CLI and Rust app now share one client-side project/session/runner contract, but the hosted web app still needs to expose the matching server contract. The remaining work is now a hosted-platform implementation plan rather than more client-side alignment.
|
|
403
|
+
|
|
404
|
+
### Hosted Contract Alignment
|
|
405
|
+
|
|
406
|
+
- [x] Add the `/api/cli/runner/...` route family to the hosted app:
|
|
407
|
+
- `POST /api/cli/runner/sync`
|
|
408
|
+
- `POST /api/cli/runner/heartbeat`
|
|
409
|
+
- `GET /api/cli/runner/jobs/poll`
|
|
410
|
+
- `POST /api/cli/runner/jobs/:id/start`
|
|
411
|
+
- `POST /api/cli/runner/jobs/:id/messages`
|
|
412
|
+
- `POST /api/cli/runner/jobs/:id/logs`
|
|
413
|
+
- `POST /api/cli/runner/jobs/:id/complete`
|
|
414
|
+
- `POST /api/cli/runner/jobs/:id/cancel`
|
|
415
|
+
- `POST /api/cli/runner/jobs/:id/retry`
|
|
416
|
+
- [x] Extend hosted session state so synced sessions can persist `orp_session_id` in addition to `codex_session_id`.
|
|
417
|
+
- [x] Extend hosted job state so the server can persist `lease_id`, `lease_expires_at`, and `last_heartbeat_at`.
|
|
418
|
+
- [x] Keep the hosted runner API device-token authenticated, matching the existing CLI workspace routes.
|
|
419
|
+
|
|
420
|
+
### Hosted Queue Bridge
|
|
421
|
+
|
|
422
|
+
- [x] Bridge queued idea checkpoints onto the new runner API so existing checkpoint work can flow through `orp runner work`.
|
|
423
|
+
- [x] Return runner jobs as prompt-style work items with enough metadata to route by `ideaId`, `worldId`, `projectRoot`, and optional `orpSessionId`.
|
|
424
|
+
- [x] On completion, write successful and failed checkpoint responses back into `idea_checkpoint_responses` and checkpoint/job status fields.
|
|
425
|
+
- [x] Preserve existing `orp agent work` compatibility until the runner API is proven in production.
|
|
426
|
+
|
|
427
|
+
### Hosted Lease Hardening
|
|
428
|
+
|
|
429
|
+
- [x] Add local runner runtime state in `.git/orp/link/runtime.json` for active lease tracking, last job status, and operator events.
|
|
430
|
+
- [x] Add lease ids to runner claim/start/heartbeat/complete payloads and persist them across the full job lifecycle.
|
|
431
|
+
- [x] Add explicit cancel and retry/requeue endpoints plus CLI handling for those transitions.
|
|
432
|
+
- [x] Add stale local lease detection and operator-facing status warnings.
|
|
433
|
+
- [x] Add hosted stale-lease expiry and safe job reclamation rules.
|
|
434
|
+
- [x] Add server-side start/complete/cancel/retry validation against the active lease and machine id.
|
|
435
|
+
- [x] Bind synced hosted world sessions to the syncing runner machine so poll only claims jobs for repos/sessions that machine actually owns.
|
|
436
|
+
- [x] Layer SSE wake-up delivery on top of the same lease protocol while keeping polling as the stable fallback/default.
|
|
437
|
+
- Implemented on March 16, 2026.
|
|
438
|
+
- Added hosted `GET /api/cli/runner/events/stream`.
|
|
439
|
+
- Added CLI `--transport auto|poll|sse` for `orp runner work` and `orp agent work`.
|
|
440
|
+
- SSE is used only as a wake-up signal; job claiming still happens through the existing poll/lease flow.
|
|
441
|
+
- Deployed live on March 16, 2026 via Vercel deployment `dpl_EyxVoapbmsHXF795yKoHN9ua1qRm`.
|
|
442
|
+
- Verified direct production SSE stream response on `https://orp.earth/api/cli/runner/events/stream`.
|
|
443
|
+
- Verified a live `orp runner work --continuous --transport auto` smoke by queueing checkpoint `d6ddb357-ae66-46bb-98ef-4a19169fc59f`, claiming job `49ee5377-a7df-48af-8350-45524f7a6a77`, and finishing it successfully.
|
|
444
|
+
|
|
445
|
+
### Future Hosted Expansion
|
|
446
|
+
|
|
447
|
+
- [x] Add a first-class hosted enqueue path for generic `session.prompt` jobs beyond checkpoint reviews.
|
|
448
|
+
- [x] Keep checkpoint review jobs and prompt jobs on one hosted job system with distinct job kinds.
|
|
449
|
+
|
|
450
|
+
### Internal Rollout Operations
|
|
451
|
+
|
|
452
|
+
- [x] Add an internal admin runners console for machine heartbeat, active lease, and last completed/failed work visibility.
|
|
453
|
+
- [x] Add internal queue recovery controls for cancel/retry without the original machine lease.
|
|
454
|
+
- [x] Add route/helper logging for failed poll/start/complete flows, lease mismatches, missing-routeable-session failures, and repeated retry patterns.
|
|
455
|
+
- [x] Surface runner health in the Rust desktop app so operators can see online/syncing/working/error states locally.
|
|
456
|
+
- [x] Add an internal rollout and recovery runbook:
|
|
457
|
+
- [RUNNER_INTERNAL_OPERATIONS.md](/Users/codymitchell/Documents/code/orp/docs/RUNNER_INTERNAL_OPERATIONS.md)
|
|
458
|
+
- [x] Deploy the hosted runner backend changes to the real internal environment.
|
|
459
|
+
- [x] Run a live internal smoke on deployed infrastructure.
|
|
460
|
+
- Completed on March 16, 2026 against `https://orp.earth`.
|
|
461
|
+
- Verified `orp link project bind`, `orp link session register`, `orp runner enable`, `orp runner sync`, `orp checkpoint queue`, `orp runner work --once`, and `orp agent work --once`.
|
|
462
|
+
- Confirmed the production `orp` checkpoint job `78cd459a-fc0b-451b-af06-be2d27379169` completed successfully and produced checkpoint response `41087b8b-9556-4ec1-90c6-eefb69bac585`.
|
|
463
|
+
- [x] Add and verify a reusable Rust-side smoke harness for the desktop wrapper path.
|
|
464
|
+
- Implemented at [runner_smoke.rs](/Users/codymitchell/Documents/code/orp-rust/src/bin/runner_smoke.rs).
|
|
465
|
+
- Verified on March 16, 2026 against `https://orp.earth`.
|
|
466
|
+
- Confirmed Rust-side smoke job `853a55f9-b0e5-42f7-8f2f-cdc8db1a354c` completed successfully and produced checkpoint response `6b5aee77-f176-4249-a127-978b987da946`.
|
|
467
|
+
|
|
468
|
+
### Hosted Verification
|
|
469
|
+
|
|
470
|
+
- [x] Run route-level unit coverage for the hosted runner API surface.
|
|
471
|
+
- [x] Run TypeScript validation for the hosted app after runner changes.
|
|
472
|
+
- [x] Run a real disposable Postgres-backed smoke flow:
|
|
473
|
+
- `sync`
|
|
474
|
+
- `enqueue`
|
|
475
|
+
- `heartbeat`
|
|
476
|
+
- `poll`
|
|
477
|
+
- `start`
|
|
478
|
+
- `messages`
|
|
479
|
+
- `logs`
|
|
480
|
+
- `complete`
|
|
481
|
+
- final `poll -> job: null`
|
|
482
|
+
- [x] Fix backend issues surfaced by the real smoke flow:
|
|
483
|
+
- `dev_jobs.idea_id` text-to-uuid join mismatch in runner polling/loading
|
|
484
|
+
- `complete` returning terminal success while leaving `dev_jobs.state = running`
|
|
485
|
+
- [x] Fix backend issues surfaced by the live internal smoke:
|
|
486
|
+
- queued runner poll was not scoped to the syncing machine's linked world sessions
|
|
487
|
+
- `idea_world_sessions.runner_id` now binds each synced session to its owning runner machine
|
|
488
|
+
- [x] Fix CLI compatibility issues surfaced by the Rust-side smoke:
|
|
489
|
+
- `orp agent work` now preserves the caller's `repo_root` when constructing runner-primary compatibility args
|
|
490
|
+
|
|
491
|
+
## Edge Cases
|
|
492
|
+
|
|
493
|
+
- repo linked but no sessions registered
|
|
494
|
+
- multiple sessions, none primary
|
|
495
|
+
- multiple sessions, more than one marked primary
|
|
496
|
+
- project moved on disk
|
|
497
|
+
- linked world deleted remotely
|
|
498
|
+
- hosted account switched
|
|
499
|
+
- stale `codex_session_id`
|
|
500
|
+
- session archived locally but still referenced by hosted jobs
|
|
501
|
+
- no hosted auth while local link files exist
|
|
502
|
+
- runner enabled with zero linked projects
|
|
503
|
+
- runner enabled with linked projects but zero usable sessions
|
|
504
|
+
- Rust `.orp` state and CLI `.git/orp/link` state disagree
|
|
505
|
+
|
|
506
|
+
## Decision Log
|
|
507
|
+
|
|
508
|
+
Current decisions:
|
|
509
|
+
|
|
510
|
+
- Project and session link state should be machine-local and git-ignored by default.
|
|
511
|
+
- The CLI should own the canonical project/session/runner contract.
|
|
512
|
+
- The Rust app should remain the strongest desktop UX, not the source of truth.
|
|
513
|
+
- Transport choice should not change the hosted runner job lifecycle.
|
|
514
|
+
- Polling remains the stable v1 transport, and SSE is now available as an optional wake-up layer on the same lease protocol.
|
|
515
|
+
- Checkpoint review jobs and generic prompt jobs should share one hosted job system with distinct kinds.
|
|
516
|
+
- `orp runner work` is the primary worker surface, while `orp agent work` remains the compatibility path for now.
|
|
517
|
+
- Hosted routing should prefer an exact linked session first, then the primary linked session for that repo.
|
|
518
|
+
- Session discovery should stay Rust-led for now, with the CLI remaining the canonical registry and runner contract.
|
|
519
|
+
- Rollout should stay internal-first and staged.
|
|
520
|
+
- WebSocket is still optional future polish, not a prerequisite for the runner contract.
|
|
521
|
+
- Production has already proven the SSE wake-up layer with `--transport auto`; it is now polish, not speculation.
|
|
@@ -5,10 +5,25 @@ Use this checklist when releasing ORP as the unified public CLI and product surf
|
|
|
5
5
|
## 1. CLI readiness
|
|
6
6
|
|
|
7
7
|
- Run:
|
|
8
|
+
- `bash scripts/orp-release-smoke.sh`
|
|
8
9
|
- `python3 -m unittest discover -s tests -v`
|
|
10
|
+
- `git status --short`
|
|
11
|
+
- `git rev-list --left-right --count origin/main...HEAD`
|
|
12
|
+
- `npm view open-research-protocol version dist-tags --json`
|
|
9
13
|
- `npm pack --dry-run --cache /tmp/orp-npm-cache`
|
|
14
|
+
- `npm publish --dry-run`
|
|
10
15
|
- Smoke-test in a fresh directory:
|
|
16
|
+
- `bash scripts/orp-release-smoke.sh --hosted --codex-session-id <session-id>`
|
|
11
17
|
- `npm i -g open-research-protocol`
|
|
18
|
+
- `orp -h`
|
|
19
|
+
- `orp init`
|
|
20
|
+
- `orp status --json`
|
|
21
|
+
- `orp branch start work/bootstrap --allow-dirty --json`
|
|
22
|
+
- `orp checkpoint create -m "bootstrap governance" --json`
|
|
23
|
+
- `orp backup -m "backup bootstrap governance" --json`
|
|
24
|
+
- `orp gate run --profile default --json`
|
|
25
|
+
- `orp checkpoint create -m "capture passing validation" --json`
|
|
26
|
+
- `orp ready --json`
|
|
12
27
|
- `orp about --json`
|
|
13
28
|
- `orp auth login`
|
|
14
29
|
- `orp whoami --json`
|
|
@@ -26,15 +41,21 @@ Use this checklist when releasing ORP as the unified public CLI and product surf
|
|
|
26
41
|
|
|
27
42
|
## 3. Worker loop readiness
|
|
28
43
|
|
|
44
|
+
- Status:
|
|
45
|
+
Verified internally on March 16, 2026 against `https://orp.earth` with machine-scoped session routing and the polling-based runner lease flow, from both the direct CLI path and the Rust-side smoke harness.
|
|
29
46
|
- Confirm one bound world can complete:
|
|
30
47
|
- `orp checkpoint queue --idea-id <idea-id> --json`
|
|
31
|
-
- `orp
|
|
48
|
+
- `orp runner work --once --json`
|
|
49
|
+
- `orp agent work --once --json` remains available as the compatibility path
|
|
32
50
|
- Confirm the checkpoint response lands back in the hosted workspace.
|
|
51
|
+
- Confirm the hosted operator console reflects the same lifecycle at `/dashboard/admin/runners`.
|
|
52
|
+
- Use [RUNNER_INTERNAL_OPERATIONS.md](/Users/codymitchell/Documents/code/orp/docs/RUNNER_INTERNAL_OPERATIONS.md) for the internal rollout and recovery flow.
|
|
33
53
|
|
|
34
54
|
## 4. Package release
|
|
35
55
|
|
|
36
56
|
- Bump `package.json` version.
|
|
37
57
|
- Commit and push `main`.
|
|
58
|
+
- Expect `npm publish` to fail if the worktree is dirty or the release commit is not already on GitHub.
|
|
38
59
|
- Tag and push:
|
|
39
60
|
- `git tag vX.Y.Z`
|
|
40
61
|
- `git push origin vX.Y.Z`
|
|
@@ -54,6 +75,8 @@ Use this checklist when releasing ORP as the unified public CLI and product surf
|
|
|
54
75
|
- `npm view open-research-protocol version`
|
|
55
76
|
- `npm i -g open-research-protocol`
|
|
56
77
|
- `orp -h`
|
|
78
|
+
- `orp init`
|
|
79
|
+
- `orp status --json`
|
|
57
80
|
- `orp about --json`
|
|
58
81
|
|
|
59
82
|
## 7. Web app rollout coordination
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# ORP Runner Internal Operations
|
|
2
|
+
|
|
3
|
+
Use this guide for the internal-first rollout of the hosted ORP runner.
|
|
4
|
+
|
|
5
|
+
Current production note:
|
|
6
|
+
|
|
7
|
+
- The SSE wake-up route is live on `https://orp.earth` as of March 16, 2026 via Vercel deployment `dpl_EyxVoapbmsHXF795yKoHN9ua1qRm`.
|
|
8
|
+
- A live `orp runner work --continuous --transport auto` smoke has already succeeded against production with checkpoint `d6ddb357-ae66-46bb-98ef-4a19169fc59f` and job `49ee5377-a7df-48af-8350-45524f7a6a77`.
|
|
9
|
+
|
|
10
|
+
## Source of truth
|
|
11
|
+
|
|
12
|
+
- Session discovery stays Rust-led.
|
|
13
|
+
- The ORP CLI is the canonical link/session/runner contract.
|
|
14
|
+
- The hosted web app is the queue and lease authority.
|
|
15
|
+
- `orp runner work` is the primary worker surface.
|
|
16
|
+
- `orp agent work` remains available only as a compatibility path.
|
|
17
|
+
|
|
18
|
+
## Healthy runner definition
|
|
19
|
+
|
|
20
|
+
A healthy internal runner should satisfy all of the following:
|
|
21
|
+
|
|
22
|
+
- `orp auth login` succeeds for the operator account.
|
|
23
|
+
- `orp link project bind` has linked the repo to the intended hosted idea/world.
|
|
24
|
+
- At least one non-archived linked session exists for the repo.
|
|
25
|
+
- One linked session is primary, or the hosted job targets an exact session.
|
|
26
|
+
- `orp runner enable` has created a machine identity on the Mac.
|
|
27
|
+
- `orp runner sync` succeeds and the hosted admin runners console shows the machine.
|
|
28
|
+
- `orp runner work --once` can poll without lease errors.
|
|
29
|
+
- `orp runner work --continuous --transport auto` can idle without missing queued work.
|
|
30
|
+
- Heartbeats continue while work is running.
|
|
31
|
+
- Completed work clears the lease and updates the hosted world/checkpoint state.
|
|
32
|
+
|
|
33
|
+
## Deployment checklist
|
|
34
|
+
|
|
35
|
+
1. Apply the latest hosted database migrations.
|
|
36
|
+
2. Deploy the hosted web app with the `/api/cli/runner/...` routes enabled.
|
|
37
|
+
3. Confirm the admin runners console loads at `/dashboard/admin/runners`.
|
|
38
|
+
4. Confirm at least one internal machine can still sign in through the published `orp` CLI.
|
|
39
|
+
5. Confirm the Rust desktop app still discovers sessions and mirrors them into CLI link state.
|
|
40
|
+
6. After any machine-scoped session-schema change, run `orp runner sync` once on every active internal runner machine so hosted `idea_world_sessions.runner_id` is refreshed before expecting queued jobs to route correctly.
|
|
41
|
+
|
|
42
|
+
## Internal smoke flow
|
|
43
|
+
|
|
44
|
+
Run this on one internal machine after deploy:
|
|
45
|
+
|
|
46
|
+
1. `orp auth login`
|
|
47
|
+
2. `orp link project bind --idea-id <idea-id>`
|
|
48
|
+
3. `orp link session register --orp-session-id <orp-session-id> --codex-session-id <codex-session-id> --primary`
|
|
49
|
+
4. `orp runner enable`
|
|
50
|
+
5. `orp runner sync`
|
|
51
|
+
6. `orp checkpoint queue --idea-id <idea-id> --json`
|
|
52
|
+
7. `orp runner work --once --json`
|
|
53
|
+
8. Optionally leave a longer-lived worker running with `orp runner work --continuous --transport auto --json`
|
|
54
|
+
9. Confirm the checkpoint response lands in the hosted idea.
|
|
55
|
+
10. Confirm `/dashboard/admin/runners` shows:
|
|
56
|
+
- the machine heartbeat
|
|
57
|
+
- the claimed job
|
|
58
|
+
- lease cleared after completion
|
|
59
|
+
|
|
60
|
+
Latest known-good production smoke:
|
|
61
|
+
|
|
62
|
+
- Direct SSE probe returned `event: ready` followed by `event: timeout` against `https://orp.earth/api/cli/runner/events/stream`.
|
|
63
|
+
- Continuous runner mode with `--transport auto` claimed the queued checkpoint job immediately and completed it successfully.
|
|
64
|
+
|
|
65
|
+
## Rust desktop smoke harness
|
|
66
|
+
|
|
67
|
+
For a repeatable non-GUI Rust-side smoke, run the harness in `orp-rust` against the same live ORP CLI contract:
|
|
68
|
+
|
|
69
|
+
1. Point `ORP_CLI_BIN` at the CLI build you want the Rust app to exercise.
|
|
70
|
+
2. Run:
|
|
71
|
+
`cargo run --bin runner_smoke -- --project-root <repo-root> --idea-id <idea-id> --codex-session-id <codex-session-id> --queue-checkpoint-note "<note>" --work-once --agent-work-once`
|
|
72
|
+
3. Confirm:
|
|
73
|
+
- `runner_work.claimed = true`
|
|
74
|
+
- `runner_work.ok = true`
|
|
75
|
+
- `agent_work.compatibility.mode = runner-primary`
|
|
76
|
+
- `agent_work.claimed = false` once the queued job has already been consumed
|
|
77
|
+
|
|
78
|
+
## Admin console workflow
|
|
79
|
+
|
|
80
|
+
Use `/dashboard/admin/runners` to:
|
|
81
|
+
|
|
82
|
+
- inspect online and stale machines
|
|
83
|
+
- inspect queued, dispatched, and running jobs
|
|
84
|
+
- watch the top-level operational alerts for stale leases, missing sessions, stale heartbeats, and repeat retries
|
|
85
|
+
- spot missing-routeable-session issues
|
|
86
|
+
- spot stale leases
|
|
87
|
+
- spot repeated retry patterns
|
|
88
|
+
- cancel a stuck job
|
|
89
|
+
- requeue a failed or stale job
|
|
90
|
+
|
|
91
|
+
## Recovery playbook
|
|
92
|
+
|
|
93
|
+
Use these defaults unless there is a clearer incident-specific reason to do otherwise:
|
|
94
|
+
|
|
95
|
+
- If a job is `running` or `dispatched` with an expired lease, requeue it.
|
|
96
|
+
- If a job is clearly invalid or targeting the wrong repo/session, cancel it.
|
|
97
|
+
- If the same job has been retried 3+ times, pause and inspect the runner, session link, and prompt payload before requeueing again.
|
|
98
|
+
- If a machine is stale, verify the desktop app or CLI runner is still open before requeueing its work.
|
|
99
|
+
- If jobs queue up with no routeable session, repair the project/session link first instead of repeatedly retrying the job.
|
|
100
|
+
|
|
101
|
+
## Rollout policy
|
|
102
|
+
|
|
103
|
+
- Start with one internal operator machine.
|
|
104
|
+
- Expand to a small set of trusted internal machines after the first full smoke passes.
|
|
105
|
+
- Prefer one or a small handful of linked repos per machine during rollout.
|
|
106
|
+
- Treat the admin runners console as the operational dashboard for the staged rollout.
|
|
107
|
+
- Do not make WebSocket a prerequisite for rollout; polling remains the stable v1 transport and SSE is optional polish on top.
|