cueline 0.1.1 → 0.1.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.
Files changed (61) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +31 -0
  4. package/README.ja.md +18 -7
  5. package/README.ko.md +18 -7
  6. package/README.md +18 -7
  7. package/README.zh-CN.md +18 -7
  8. package/README.zh-TW.md +18 -7
  9. package/dist/src/api.d.ts +23 -1
  10. package/dist/src/api.js +110 -6
  11. package/dist/src/api.js.map +1 -1
  12. package/dist/src/browser/browser-adapter.d.ts +1 -0
  13. package/dist/src/browser/codex-iab/bootstrap.d.ts +6 -0
  14. package/dist/src/browser/codex-iab/bootstrap.js.map +1 -1
  15. package/dist/src/browser/codex-iab/chatgpt-client.js +162 -41
  16. package/dist/src/browser/codex-iab/chatgpt-client.js.map +1 -1
  17. package/dist/src/cli/main.js +150 -8
  18. package/dist/src/cli/main.js.map +1 -1
  19. package/dist/src/core/controller-loop.d.ts +6 -0
  20. package/dist/src/core/controller-loop.js +240 -74
  21. package/dist/src/core/controller-loop.js.map +1 -1
  22. package/dist/src/core/run-status.d.ts +50 -0
  23. package/dist/src/core/run-status.js +169 -0
  24. package/dist/src/core/run-status.js.map +1 -0
  25. package/dist/src/core/state-machine.d.ts +2 -1
  26. package/dist/src/core/state-machine.js +22 -1
  27. package/dist/src/core/state-machine.js.map +1 -1
  28. package/dist/src/jobs/status.d.ts +6 -0
  29. package/dist/src/jobs/status.js.map +1 -1
  30. package/dist/src/jobs/supervisor.d.ts +2 -0
  31. package/dist/src/jobs/supervisor.js +44 -12
  32. package/dist/src/jobs/supervisor.js.map +1 -1
  33. package/dist/src/protocol/types.d.ts +1 -1
  34. package/dist/src/protocol/validate-command.js +18 -0
  35. package/dist/src/protocol/validate-command.js.map +1 -1
  36. package/dist/src/router/resolver.js +7 -1
  37. package/dist/src/router/resolver.js.map +1 -1
  38. package/dist/src/runners/process-runner.d.ts +2 -2
  39. package/dist/src/runners/process-runner.js +56 -5
  40. package/dist/src/runners/process-runner.js.map +1 -1
  41. package/dist/src/runners/runner-adapter.d.ts +9 -2
  42. package/dist/src/runners/runner-adapter.js.map +1 -1
  43. package/dist/src/state/cancellation.d.ts +42 -0
  44. package/dist/src/state/cancellation.js +160 -0
  45. package/dist/src/state/cancellation.js.map +1 -0
  46. package/dist/src/state/paths.d.ts +3 -0
  47. package/dist/src/state/paths.js +3 -0
  48. package/dist/src/state/paths.js.map +1 -1
  49. package/dist/src/state/runtime-lease.d.ts +28 -0
  50. package/dist/src/state/runtime-lease.js +179 -0
  51. package/dist/src/state/runtime-lease.js.map +1 -0
  52. package/dist/src/version.d.ts +1 -1
  53. package/dist/src/version.js +1 -1
  54. package/docs/compatibility.md +3 -1
  55. package/docs/controller-protocol.md +4 -2
  56. package/docs/runner-contract.md +7 -1
  57. package/docs/state-and-recovery.md +34 -9
  58. package/package.json +4 -2
  59. package/schemas/controller-observation.schema.json +1 -1
  60. package/scripts/validate-plugin.mjs +66 -0
  61. package/skills/cueline/SKILL.md +33 -5
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cueline",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Use a ChatGPT web conversation as the controller for durable local agent work.",
5
5
  "author": {
6
6
  "name": "CueLine contributors"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cueline",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Use a ChatGPT web conversation as the controller for durable local agent work.",
5
5
  "author": {
6
6
  "name": "CueLine contributors"
package/CHANGELOG.md ADDED
@@ -0,0 +1,31 @@
1
+ # Changelog
2
+
3
+ ## 0.1.3 - 2026-07-15
4
+
5
+ ### Fixed
6
+
7
+ - Add `cueline run status <run-id> --json` with accepted-controller-response evidence, the last accepted action and job keys, runtime ownership, safe next action, cancellation requests, and derived `orphaned` jobs. A new session no longer calls a persisted `running` value active when no live owner is proven.
8
+ - Add an owner heartbeat lease. A second session refuses to continue an active run, and a missing or stale owner requires inspection instead of another controller send.
9
+ - Run independent all-`advise` dispatches concurrently. Any dispatch containing `work` remains serial to avoid overlapping mutations.
10
+ - Add durable `run cancel` / `run stop` and `job cancel` requests, API `AbortSignal` support, and `runTimeoutMs`. Active `advise` cancellation becomes `cancelled`; interrupted `work` or ownerless legacy work becomes `ambiguous`.
11
+ - Persist job run ID, job key, lane, mode, and child PID for diagnosis. `cueline jobs --json` reports an observed status and never uses PID alone as kill authorization.
12
+ - Reject unsupported `runner_id` explicitly, require `runner`, and explain when a runner ID such as `codex-default` was placed in `lane`.
13
+ - Preserve built-in-browser attach failures instead of converting them to an empty tab list. Retry safe pre-submit attachment once, recheck an empty discovery result once, cache a new tab only after it loads, and use at most one CUA coordinate fallback after a transient send-locator failure.
14
+
15
+ ### Documentation
16
+
17
+ - Require `run status` before continuation and distinguish controller response acceptance, local job execution, runtime ownership, and outer waiter timeout.
18
+ - Document cancellation, run-level deadlines, `advise` concurrency, `work` serialization, and stale-job recovery semantics.
19
+
20
+ ## 0.1.2 - 2026-07-15
21
+
22
+ ### Fixed
23
+
24
+ - Wait up to five seconds for the ChatGPT composer model control to hydrate before reconciling an existing controller response. This prevents a visible `Pro` control from being rejected by an early DOM read.
25
+ - Preserve strict model verification during recovery: CueLine still requires both a `Pro` composer label and a Pro response model slug, and still refuses reconciliation when either proof is missing.
26
+ - Keep reconciliation read-only. Recovering an existing response does not resend the prompt, register a job, or execute Grove work.
27
+
28
+ ### Documentation
29
+
30
+ - Clarify that `default` is a lane while `codex-default` is a runner candidate inside that lane.
31
+ - Document safe `0.1.2` continuation behavior for pending controller turns, exact prompt matching, and ambiguous submissions.
package/README.ja.md CHANGED
@@ -25,6 +25,8 @@ CueLine は独立した実装で、**ランタイムの npm 依存はゼロ**で
25
25
 
26
26
  コントローラーは*何が起こるべきか*を選びます。ローカル側は*それを許すか、どう許すか*を選びます。レーンが有効であること、候補がプロセス起動の**前に**利用可能だと確認されていること、`argv[0]` があなたのルーティング設定によってすでに登録されていること。シェルを経由するものは何もありません。ワーカーがいったん起動したら、黙って 2 番目の候補にフォールバックすることはありません。失敗は再試行ではなく、証拠として返ります。
27
27
 
28
+ コントローラープロトコルでは、ルーティングの階層を明確に区別します。`lane` に指定するのはレーン名の `default` であり、`codex-default` はそのレーン内の候補ランナーであって、レーンではありません。CueLine はジョブを一つでも登録する前に `dispatch` 全体を検証します。無効なレーンまたはランナーが一つでもあれば、途中まで実行せず、`dispatch` 全体を修正のために差し戻します。
29
+
28
30
  これは許可リスト(allow-list)であって、サンドボックスではありません。登録されたワーカーは CueLine プロセス自身と同じ権限で動きます。`advise` は Codex の読み取り専用サンドボックスに、`work` は `workspace-write` に対応しますが、登録したものが、そのまま許可したものになります。
29
31
 
30
32
  ## コントローラーは Pro モデルでなければならない
@@ -42,15 +44,15 @@ ChatGPT Pro のサブスクリプションと、選択された Pro モデルは
42
44
  npm レジストリからインストールします。
43
45
 
44
46
  ```bash
45
- npm install -g cueline@0.1.1
47
+ npm install -g cueline@0.1.3
46
48
  cueline install
47
49
  cueline doctor
48
50
  ```
49
51
 
50
- フォールバックとして、[v0.1.1 リリース](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.1) のパッケージ済み tarball をインストールすることもできます。同じリリースに `.sha256` チェックサムも置いてあります。
52
+ フォールバックとして、[v0.1.3 リリース](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.3) のパッケージ済み tarball をインストールすることもできます。同じリリースに `.sha256` チェックサムも置いてあります。
51
53
 
52
54
  ```bash
53
- npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.1/cueline-0.1.1.tgz
55
+ npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.3/cueline-0.1.3.tgz
54
56
  cueline install
55
57
  cueline doctor
56
58
  ```
@@ -87,7 +89,8 @@ import { createCodexIabAdapter, runCueLine } from "cueline";
87
89
  const result = await runCueLine({
88
90
  request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
89
91
  browser: createCodexIabAdapter(),
90
- // 任意:conversationUrl、routingConfig / routingConfigPath、home、cwd、limits。
92
+ // 任意:conversationUrl、routingConfig / routingConfigPath、home、cwd、
93
+ // runTimeoutMs、signal、ジョブごと/既定の期限。
91
94
  });
92
95
 
93
96
  if (result.status === "complete") {
@@ -97,7 +100,7 @@ if (result.status === "complete") {
97
100
 
98
101
  Codex のランタイムでは、`cueline api path` が出力する絶対パスのモジュールを import します。それがインストールしたパッケージのビルド済み API です。
99
102
 
100
- `startCueLineRun` が明示的な開始点です(`runCueLine` はその別名)。`continueCueLineRun({ runId })` は中断した実行を同じ会話で再開し、新しいアダプターを渡さないかぎり保存済みの会話 URL を再利用します。`loadCueLineRunState(runId)` は永続化された状態を読むだけで、何も駆動しません。すでに `complete` または `blocked` に達した実行はそのまま返され、二度とディスパッチされません。
103
+ `startCueLineRun` が明示的な開始点です(`runCueLine` はその別名)。`continueCueLineRun({ runId })` は中断した実行を同じ会話で再開し、新しいアダプターを渡さないかぎり保存済みの会話 URL を再利用します。`loadCueLineRunState(runId)` は永続化された状態を読むだけで、何も駆動しません。すでに `complete`、`blocked`、または `cancelled` に達した実行はそのまま返され、二度とディスパッチされません。再開前に `cueline run status <run-id> --json` を実行してください。応答が受理済みで phase が `jobs_running` なら、ChatGPT の応答後にローカルジョブを実行中です。
101
104
 
102
105
  ## CLI
103
106
 
@@ -108,7 +111,7 @@ $ cueline install
108
111
  CueLine skill installed: /Users/you/.codex/skills/cueline
109
112
 
110
113
  $ cueline doctor
111
- CueLine 0.1.1
114
+ CueLine 0.1.3
112
115
  status ok
113
116
  node 22.14.0 ok
114
117
  config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
@@ -124,6 +127,12 @@ default codex-default available
124
127
  $ cueline jobs
125
128
  No jobs.
126
129
 
130
+ $ cueline run status run_... --json
131
+ {"status":"running","phase":"jobs_running","runtime":{"ownership":"active"},...}
132
+
133
+ $ cueline run cancel run_...
134
+ run_... requested affected_jobs=0
135
+
127
136
  $ cueline config path
128
137
  /usr/local/lib/node_modules/cueline/config/routing.default.json
129
138
 
@@ -143,13 +152,15 @@ Node が古すぎる場合、あるいは解決できるレーンが一つもな
143
152
 
144
153
  ```text
145
154
  runs/<run-id>/events.jsonl 追記のみ、正本
155
+ runs/<run-id>/runtime.json ライブ owner の heartbeat 証拠
156
+ runs/<run-id>/cancel.json 存在する場合は永続キャンセル要求
146
157
  runs/<run-id>/snapshot.json リプレイの最適化、破棄可能
147
158
  jobs/<job-id>.json ジョブごとの実行証拠
148
159
  ```
149
160
 
150
161
  記録そのものはイベントログです。コントローラーのターンは送信する前に書かれ、ジョブはプロセスが起動する前に登録されます。だからこそ、意図と副作用のあいだで中断が起きても痕跡が残ります。壊れたスナップショットは信用されず、無視されてイベント 1 番から再構築されます。
151
162
 
152
- 復帰は、その実行が記録したまさにその会話 URL にだけ再接続します。よく似たタブにつなぐことはありません。送信の状態が不確定なあいだにタブが消えた場合、CueLine `TAB_RECOVERY_UNSAFE` を投げて停止します。最初の送信がすでに届いたかどうかを証明できない以上、自動でプロンプトを送り直すことは決してありません。
163
+ 復帰は、その実行が記録したまさにその会話 URL にだけ再接続します。よく似たタブにつなぐことはありません。保留中のコントローラーターンについては、まず正確なリクエストに対応する完了済みの応答をその会話内で探し、見つかれば再送せず読み取り専用で照合します。古い状態に複数の保留ターンがある場合、呼び出し側が一つを明示的に選ぶ必要があります。唯一の保留中プロンプトが `definitely_not_sent` だと証明できた場合に限り、CueLine は自動で再試行します。送信状態が不明、またはタブが消えた場合は `TAB_RECOVERY_UNSAFE` を投げて停止します。
153
164
 
154
165
  ## 検証
155
166
 
package/README.ko.md CHANGED
@@ -25,6 +25,8 @@ CueLine은 독립적인 구현이며 **런타임 npm 의존성이 전혀 없습
25
25
 
26
26
  컨트롤러는 *무엇이 일어나야 하는지*를 고릅니다. 로컬 쪽은 *그것이 허용되는지, 어떻게 허용되는지*를 고릅니다. 레인이 활성화되어 있어야 하고, 후보는 어떤 프로세스가 뜨기 **전에** 사용 가능함이 확인되어야 하며, `argv[0]`은 당신의 라우팅 설정에 이미 등록되어 있어야 합니다. 셸을 거치는 것은 아무것도 없습니다. 워커가 일단 시작되면 두 번째 후보로 조용히 넘어가는 폴백은 없습니다. 실패는 재시도가 아니라 증거로 돌아옵니다.
27
27
 
28
+ 컨트롤러 프로토콜은 라우팅 계층을 명확히 구분합니다. `lane`에는 레인 이름인 `default`를 써야 하며, `codex-default`는 그 레인 안의 후보 러너이지 레인이 아닙니다. CueLine은 작업을 하나라도 등록하기 전에 `dispatch` 전체를 검증합니다. 잘못된 레인이나 러너가 하나라도 있으면 일부를 먼저 실행하지 않고 `dispatch` 전체를 수정하도록 돌려보냅니다.
29
+
28
30
  이것은 허용 목록(allow-list)이지 샌드박스가 아닙니다. 등록된 워커는 CueLine 프로세스 자신과 동일한 권한으로 실행됩니다. `advise`는 Codex의 읽기 전용 샌드박스에, `work`는 `workspace-write`에 대응하지만, 당신이 등록한 것이 곧 당신이 승인한 것입니다.
29
31
 
30
32
  ## 컨트롤러는 반드시 Pro 모델이어야 합니다
@@ -42,15 +44,15 @@ ChatGPT Pro 구독과 선택된 Pro 모델은 서로 다른 것입니다. 계정
42
44
  npm 레지스트리에서 설치합니다:
43
45
 
44
46
  ```bash
45
- npm install -g cueline@0.1.1
47
+ npm install -g cueline@0.1.3
46
48
  cueline install
47
49
  cueline doctor
48
50
  ```
49
51
 
50
- 대안으로, [v0.1.1 릴리스](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.1)의 패키지 tarball을 설치할 수도 있습니다. 같은 릴리스에 `.sha256` 체크섬도 함께 있습니다.
52
+ 대안으로, [v0.1.3 릴리스](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.3)의 패키지 tarball을 설치할 수도 있습니다. 같은 릴리스에 `.sha256` 체크섬도 함께 있습니다.
51
53
 
52
54
  ```bash
53
- npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.1/cueline-0.1.1.tgz
55
+ npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.3/cueline-0.1.3.tgz
54
56
  cueline install
55
57
  cueline doctor
56
58
  ```
@@ -87,7 +89,8 @@ import { createCodexIabAdapter, runCueLine } from "cueline";
87
89
  const result = await runCueLine({
88
90
  request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
89
91
  browser: createCodexIabAdapter(),
90
- // 선택: conversationUrl, routingConfig / routingConfigPath, home, cwd, limits.
92
+ // 선택: conversationUrl, routingConfig / routingConfigPath, home, cwd,
93
+ // runTimeoutMs, signal, 작업별/기본 제한 시간.
91
94
  });
92
95
 
93
96
  if (result.status === "complete") {
@@ -97,7 +100,7 @@ if (result.status === "complete") {
97
100
 
98
101
  Codex 런타임에서는 `cueline api path`가 출력하는 절대 경로 모듈을 import하세요. 그것이 설치한 패키지의 빌드된 API입니다.
99
102
 
100
- `startCueLineRun`이 명시적인 시작점입니다(`runCueLine`은 그 별칭). `continueCueLineRun({ runId })`은 중단된 실행을 같은 대화에서 재개하며, 새 어댑터를 넘기지 않는 한 저장된 대화 URL을 재사용합니다. `loadCueLineRunState(runId)`는 저장된 상태를 읽기만 하고 아무것도 구동하지 않습니다. 이미 `complete`나 `blocked`에 도달한 실행은 그대로 반환되며, 두 번 디스패치되지 않습니다.
103
+ `startCueLineRun`이 명시적인 시작점입니다(`runCueLine`은 그 별칭). `continueCueLineRun({ runId })`은 중단된 실행을 같은 대화에서 재개하며, 새 어댑터를 넘기지 않는 한 저장된 대화 URL을 재사용합니다. `loadCueLineRunState(runId)`는 저장된 상태를 읽기만 하고 아무것도 구동하지 않습니다. 이미 `complete`, `blocked`, `cancelled`에 도달한 실행은 그대로 반환되며, 두 번 디스패치되지 않습니다. 재개 전 `cueline run status <run-id> --json`을 실행하십시오. 응답이 수락되었고 phase가 `jobs_running`이면 ChatGPT 응답은 끝났고 로컬 작업이 실행 중입니다.
101
104
 
102
105
  ## CLI
103
106
 
@@ -108,7 +111,7 @@ $ cueline install
108
111
  CueLine skill installed: /Users/you/.codex/skills/cueline
109
112
 
110
113
  $ cueline doctor
111
- CueLine 0.1.1
114
+ CueLine 0.1.3
112
115
  status ok
113
116
  node 22.14.0 ok
114
117
  config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
@@ -124,6 +127,12 @@ default codex-default available
124
127
  $ cueline jobs
125
128
  No jobs.
126
129
 
130
+ $ cueline run status run_... --json
131
+ {"status":"running","phase":"jobs_running","runtime":{"ownership":"active"},...}
132
+
133
+ $ cueline run cancel run_...
134
+ run_... requested affected_jobs=0
135
+
127
136
  $ cueline config path
128
137
  /usr/local/lib/node_modules/cueline/config/routing.default.json
129
138
 
@@ -143,13 +152,15 @@ Node 버전이 너무 낮거나 해석 가능한 레인이 하나도 없으면 `
143
152
 
144
153
  ```text
145
154
  runs/<run-id>/events.jsonl 추가 전용, 정본
155
+ runs/<run-id>/runtime.json 활성 owner의 heartbeat 증거
156
+ runs/<run-id>/cancel.json 존재할 때 지속 취소 요청
146
157
  runs/<run-id>/snapshot.json 재생 최적화용, 버려도 무방
147
158
  jobs/<job-id>.json 작업별 실행 증거
148
159
  ```
149
160
 
150
161
  기록 그 자체는 이벤트 로그입니다. 컨트롤러의 턴은 보내기 전에 기록되고, 작업은 프로세스가 시작되기 전에 등록됩니다. 그래서 의도와 부작용 사이에서 중단이 일어나도 흔적이 남습니다. 손상된 스냅샷은 신뢰되지 않고, 무시된 뒤 이벤트 1번부터 다시 만들어집니다.
151
162
 
152
- 복구는 그 실행이 기록해 둔 바로 그 대화 URL에만 다시 연결하며, 비슷해 보이는 탭에는 결코 붙지 않습니다. 제출 상태가 불확실한 사이에 탭이 사라지면 CueLine은 `TAB_RECOVERY_UNSAFE`를 던지고 멈춥니다. 번째 전송이 이미 도착했는지 증명할 없기 때문에, 프롬프트를 스스로 다시 보내는 일은 결코 없습니다.
163
+ 복구는 그 실행이 기록해 둔 바로 그 대화 URL에만 다시 연결하며, 비슷해 보이는 탭에는 결코 붙지 않습니다. 보류 중인 컨트롤러 턴이 있으면 먼저 대화에서 정확한 요청과 연결된 완료 응답을 찾고, 찾으면 다시 보내지 않고 읽기 전용으로 대조해 복구합니다. 이전 상태에 보류 중인 턴이 여러 개 있으면 호출자가 하나를 명시적으로 선택해야 합니다. 유일한 보류 프롬프트가 `definitely_not_sent`임이 증명된 경우에만 CueLine이 자동으로 다시 시도합니다. 제출 상태가 불명확하거나 탭이 사라지면 `TAB_RECOVERY_UNSAFE`를 던지고 멈춥니다.
153
164
 
154
165
  ## 검증
155
166
 
package/README.md CHANGED
@@ -25,6 +25,8 @@ Each round: CueLine writes down what it is about to ask, sends one observation i
25
25
 
26
26
  The controller chooses *what should happen*. The local side chooses *whether and how it may happen*: the lane must be enabled, the candidate must be available **before** anything spawns, and `argv[0]` must already be registered by your routing config. Nothing is passed through a shell. Once a worker starts, there is no silent fallback to a second candidate — a failure comes back as evidence, not as a retry.
27
27
 
28
+ The controller protocol keeps routing levels explicit: `lane` names the lane (`default`), while `codex-default` is a candidate runner inside that lane, not a lane. CueLine validates the entire `dispatch` before registering any job; an invalid lane or runner rejects the whole dispatch for repair, so no valid-looking subset starts early.
29
+
28
30
  That is an allow-list, not a sandbox. A registered worker runs with the same permissions as the CueLine process itself; `advise` maps to a read-only Codex sandbox and `work` to `workspace-write`, but what you register is what you have authorized.
29
31
 
30
32
  ## The controller must be a Pro model
@@ -42,15 +44,15 @@ You need Node.js 22+, Codex with its built-in Browser, and — for the bundled d
42
44
  Install from the npm registry:
43
45
 
44
46
  ```bash
45
- npm install -g cueline@0.1.1
47
+ npm install -g cueline@0.1.3
46
48
  cueline install
47
49
  cueline doctor
48
50
  ```
49
51
 
50
- As a fallback, install the packaged tarball from the [v0.1.1 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.1), which also carries its `.sha256` checksum:
52
+ As a fallback, install the packaged tarball from the [v0.1.3 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.3), which also carries its `.sha256` checksum:
51
53
 
52
54
  ```bash
53
- npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.1/cueline-0.1.1.tgz
55
+ npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.3/cueline-0.1.3.tgz
54
56
  cueline install
55
57
  cueline doctor
56
58
  ```
@@ -87,7 +89,8 @@ import { createCodexIabAdapter, runCueLine } from "cueline";
87
89
  const result = await runCueLine({
88
90
  request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
89
91
  browser: createCodexIabAdapter(),
90
- // Optional: conversationUrl, routingConfig / routingConfigPath, home, cwd, limits.
92
+ // Optional: conversationUrl, routingConfig / routingConfigPath, home, cwd,
93
+ // runTimeoutMs, signal, and per-job/default limits.
91
94
  });
92
95
 
93
96
  if (result.status === "complete") {
@@ -95,7 +98,7 @@ if (result.status === "complete") {
95
98
  }
96
99
  ```
97
100
 
98
- `startCueLineRun` is the explicit start (`runCueLine` is its alias). `continueCueLineRun({ runId })` resumes an interrupted run in the same conversation, and reuses the stored conversation URL unless you hand it a new adapter. `loadCueLineRunState(runId)` reads persisted state without driving anything. A run that already reached `complete` or `blocked` is returned as-is, never dispatched twice.
101
+ `startCueLineRun` is the explicit start (`runCueLine` is its alias). `continueCueLineRun({ runId })` resumes an interrupted run in the same conversation, and reuses the stored conversation URL unless you hand it a new adapter. `loadCueLineRunState(runId)` reads persisted state without driving anything. A run that already reached `complete`, `blocked`, or `cancelled` is returned as-is, never dispatched twice. Before continuation, run `cueline run status <run-id> --json`: an accepted response plus `jobs_running` means ChatGPT already answered and local jobs are executing.
99
102
 
100
103
  Inside Codex's runtime, import the absolute module that `cueline api path` prints — that is the built API of the package you installed.
101
104
 
@@ -108,7 +111,7 @@ $ cueline install
108
111
  CueLine skill installed: /Users/you/.codex/skills/cueline
109
112
 
110
113
  $ cueline doctor
111
- CueLine 0.1.1
114
+ CueLine 0.1.3
112
115
  status ok
113
116
  node 22.14.0 ok
114
117
  config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
@@ -124,6 +127,12 @@ default codex-default available
124
127
  $ cueline jobs
125
128
  No jobs.
126
129
 
130
+ $ cueline run status run_... --json
131
+ {"status":"running","phase":"jobs_running","runtime":{"ownership":"active"},...}
132
+
133
+ $ cueline run cancel run_...
134
+ run_... requested affected_jobs=0
135
+
127
136
  $ cueline config path
128
137
  /usr/local/lib/node_modules/cueline/config/routing.default.json
129
138
 
@@ -143,13 +152,15 @@ State lives under `CUELINE_HOME`:
143
152
 
144
153
  ```text
145
154
  runs/<run-id>/events.jsonl append-only, authoritative
155
+ runs/<run-id>/runtime.json live-owner heartbeat evidence
156
+ runs/<run-id>/cancel.json durable cancellation request, when present
146
157
  runs/<run-id>/snapshot.json a replay optimization, disposable
147
158
  jobs/<job-id>.json per-job execution evidence
148
159
  ```
149
160
 
150
161
  The event log is the record: the controller turn is written before it is sent, and a job is registered before its process starts, so an interruption between intent and side effect leaves a trace. A corrupt snapshot is ignored and rebuilt from event 1 rather than trusted.
151
162
 
152
- Recovery reattaches only to the exact conversation URL the run recorded — never to a lookalike tab. If a tab disappears while a submission's status is ambiguous, CueLine throws `TAB_RECOVERY_UNSAFE` and stops. It never resends the prompt on its own, because it cannot prove whether the first one already landed.
163
+ Recovery reattaches only to the exact conversation URL the run recorded — never to a lookalike tab. For a pending controller turn, CueLine first looks in that conversation for a completed response correlated to the exact request; if found, it reconciles the response read-only instead of resending. If legacy state contains multiple pending turns, the caller must select one explicitly. CueLine retries automatically only when the sole pending prompt is proven `definitely_not_sent`; an ambiguous submission or a vanished tab throws `TAB_RECOVERY_UNSAFE` and stops.
153
164
 
154
165
  ## Verify
155
166
 
package/README.zh-CN.md CHANGED
@@ -25,6 +25,8 @@ CueLine 是独立实现,**没有任何运行时 npm 依赖**,也不是 Omnil
25
25
 
26
26
  控制器决定*应该发生什么*;本地这一侧决定*是否允许发生、以何种方式发生*:通道(lane)必须启用、候选必须在任何进程启动**之前**确认可用、`argv[0]` 必须早已由你的路由配置注册。没有任何内容会经过 shell。worker 一旦启动,就不会悄悄退回到第二个候选——失败以证据的形式返回,而不是自动重试。
27
27
 
28
+ 控制器协议有意区分路由层级:`lane` 填的是通道名称 `default`;`codex-default` 是该通道内的候选执行器,不是通道。CueLine 会在注册任何作业之前先验证整份 `dispatch`;只要包含无效通道或执行器,整份派工就会被退回修复,不会先执行其中一部分。
29
+
28
30
  这是白名单(allow-list),不是沙箱。已注册的 worker 拥有与 CueLine 进程本身相同的权限;`advise` 对应 Codex 的只读沙箱、`work` 对应 `workspace-write`,但你注册了什么,就等于你授权了什么。
29
31
 
30
32
  ## 控制器必须是 Pro 模型
@@ -42,15 +44,15 @@ ChatGPT Pro 订阅套餐与“选定的 Pro 模型”是两回事。账号或个
42
44
  从 npm registry 安装:
43
45
 
44
46
  ```bash
45
- npm install -g cueline@0.1.1
47
+ npm install -g cueline@0.1.3
46
48
  cueline install
47
49
  cueline doctor
48
50
  ```
49
51
 
50
- 作为后备,也可以安装 [v0.1.1 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.1) 上的打包 tarball,该 release 同时附带它的 `.sha256` 校验值:
52
+ 作为后备,也可以安装 [v0.1.3 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.3) 上的打包 tarball,该 release 同时附带它的 `.sha256` 校验值:
51
53
 
52
54
  ```bash
53
- npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.1/cueline-0.1.1.tgz
55
+ npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.3/cueline-0.1.3.tgz
54
56
  cueline install
55
57
  cueline doctor
56
58
  ```
@@ -87,7 +89,8 @@ import { createCodexIabAdapter, runCueLine } from "cueline";
87
89
  const result = await runCueLine({
88
90
  request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
89
91
  browser: createCodexIabAdapter(),
90
- // 可选:conversationUrl、routingConfig / routingConfigPath、home、cwd、limits。
92
+ // 可选:conversationUrl、routingConfig / routingConfigPath、home、cwd、
93
+ // runTimeoutMs、signal,以及作业/默认期限。
91
94
  });
92
95
 
93
96
  if (result.status === "complete") {
@@ -97,7 +100,7 @@ if (result.status === "complete") {
97
100
 
98
101
  在 Codex 的 runtime 里,import `cueline api path` 打印出的那个绝对路径模块——那就是你安装的那份包构建出来的 API。
99
102
 
100
- `startCueLineRun` 是显式的启动入口(`runCueLine` 是它的别名)。`continueCueLineRun({ runId })` 会在同一个会话中续跑被中断的运行,并复用已保存的会话链接,除非你传入新的 adapter。`loadCueLineRunState(runId)` 只读取已持久化的状态,不驱动任何东西。已经到达 `complete` 或 `blocked` 的运行会原样返回,绝不会被再次派发。
103
+ `startCueLineRun` 是显式的启动入口(`runCueLine` 是它的别名)。`continueCueLineRun({ runId })` 会在同一个会话中续跑被中断的运行,并复用已保存的会话链接,除非你传入新的 adapter。`loadCueLineRunState(runId)` 只读取已持久化的状态,不驱动任何东西。已经到达 `complete`、`blocked` 或 `cancelled` 的运行会原样返回,绝不会被再次派发。续跑前先执行 `cueline run status <run-id> --json`;已接受回复且 phase 为 `jobs_running` 表示 ChatGPT 已回复,本地作业正在执行。
101
104
 
102
105
  ## CLI
103
106
 
@@ -108,7 +111,7 @@ $ cueline install
108
111
  CueLine skill installed: /Users/you/.codex/skills/cueline
109
112
 
110
113
  $ cueline doctor
111
- CueLine 0.1.1
114
+ CueLine 0.1.3
112
115
  status ok
113
116
  node 22.14.0 ok
114
117
  config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
@@ -124,6 +127,12 @@ default codex-default available
124
127
  $ cueline jobs
125
128
  No jobs.
126
129
 
130
+ $ cueline run status run_... --json
131
+ {"status":"running","phase":"jobs_running","runtime":{"ownership":"active"},...}
132
+
133
+ $ cueline run cancel run_...
134
+ run_... requested affected_jobs=0
135
+
127
136
  $ cueline config path
128
137
  /usr/local/lib/node_modules/cueline/config/routing.default.json
129
138
 
@@ -143,13 +152,15 @@ CueLine skill removed: /Users/you/.codex/skills/cueline
143
152
 
144
153
  ```text
145
154
  runs/<run-id>/events.jsonl 仅追加、具权威性
155
+ runs/<run-id>/runtime.json 活跃 owner 的 heartbeat 证据
156
+ runs/<run-id>/cancel.json 存在时表示持久取消请求
146
157
  runs/<run-id>/snapshot.json 重放优化产物,可丢弃
147
158
  jobs/<job-id>.json 每个作业的执行证据
148
159
  ```
149
160
 
150
161
  事件日志才是记录本身:控制器这一轮在发送之前先写入、作业在进程启动之前先注册,因此“意图”与“副作用”之间若被中断,会留下痕迹。损坏的快照会被忽略并从第 1 号事件重建,而不是被信任。
151
162
 
152
- 续跑只会重新接回该次运行记录下来的那个会话 URL,绝不接到长得像的标签页。若某个标签页在“提交状态未明”的当下消失,CueLine 会抛出 `TAB_RECOVERY_UNSAFE` 并停下。它绝不自行重发提示,因为它无法证明第一次究竟发出去了没有。
163
+ 续跑只会重新接回该次运行记录下来的那个会话 URL,绝不接到长得像的标签页。对仍待处理的控制器回合,它会先在该会话中查找与确切请求对应的已完成回复;找到后以只读方式接回,而不是重发。若旧状态中同时有多个待处理回合,调用方必须明确选择一个。只有当唯一待处理提示能被证明为 `definitely_not_sent` 时,CueLine 才会自动重试;提交状态不明或标签页消失时,它会抛出 `TAB_RECOVERY_UNSAFE` 并停下。
153
164
 
154
165
  ## 验证
155
166
 
package/README.zh-TW.md CHANGED
@@ -25,6 +25,8 @@ CueLine 是獨立實作,**沒有任何 runtime npm 相依套件**,也不是
25
25
 
26
26
  主控端決定*該發生什麼*;本機這一側決定*能不能發生、怎麼發生*:通道(lane)必須啟用、候選項必須在任何程序啟動**之前**就確認可用、`argv[0]` 必須早已由你的路由設定註冊過。沒有任何東西會經過 shell。工作行程一旦啟動,就不會偷偷改用第二個候選項——失敗是以證據的形式回報,不是自動重試。
27
27
 
28
+ 主控協定刻意區分路由層級:`lane` 填的是通道名稱 `default`;`codex-default` 是該通道內的候選執行器,不是通道。CueLine 會在註冊任何工作前先驗證整份 `dispatch`;只要包含無效通道或執行器,整份派工就會被退回修正,不會先執行其中一部分。
29
+
28
30
  這是允許清單(allow-list),不是沙箱。已註冊的工作行程擁有跟 CueLine 行程本身相同的權限;`advise` 對應 Codex 的唯讀沙箱、`work` 對應 `workspace-write`,但你註冊了什麼,就等於你授權了什麼。
29
31
 
30
32
  ## 主控端必須是 Pro 模型
@@ -42,15 +44,15 @@ ChatGPT Pro 訂閱方案與「選定的 Pro 模型」是兩回事。帳號或個
42
44
  從 npm registry 安裝:
43
45
 
44
46
  ```bash
45
- npm install -g cueline@0.1.1
47
+ npm install -g cueline@0.1.3
46
48
  cueline install
47
49
  cueline doctor
48
50
  ```
49
51
 
50
- 作為備援,也可以安裝 [v0.1.1 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.1) 上的打包 tarball,該 release 同時附上它的 `.sha256` 校驗碼:
52
+ 作為備援,也可以安裝 [v0.1.3 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.3) 上的打包 tarball,該 release 同時附上它的 `.sha256` 校驗碼:
51
53
 
52
54
  ```bash
53
- npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.1/cueline-0.1.1.tgz
55
+ npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.3/cueline-0.1.3.tgz
54
56
  cueline install
55
57
  cueline doctor
56
58
  ```
@@ -87,7 +89,8 @@ import { createCodexIabAdapter, runCueLine } from "cueline";
87
89
  const result = await runCueLine({
88
90
  request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
89
91
  browser: createCodexIabAdapter(),
90
- // 選填:conversationUrl、routingConfig / routingConfigPath、home、cwd、limits。
92
+ // 選填:conversationUrl、routingConfig / routingConfigPath、home、cwd、
93
+ // runTimeoutMs、signal,以及各工作/預設期限。
91
94
  });
92
95
 
93
96
  if (result.status === "complete") {
@@ -97,7 +100,7 @@ if (result.status === "complete") {
97
100
 
98
101
  在 Codex 的 runtime 裡,import `cueline api path` 印出的那個絕對路徑模組——那就是你安裝的那份套件建置出來的 API。
99
102
 
100
- `startCueLineRun` 是明確的啟動入口(`runCueLine` 是它的別名)。`continueCueLineRun({ runId })` 會在同一個對話裡續跑被中斷的執行,並沿用已保存的對話網址,除非你另外傳入新的 adapter。`loadCueLineRunState(runId)` 只讀取已保存的狀態,不驅動任何東西。已經走到 `complete` 或 `blocked` 的執行會原樣回傳,絕不會被再派工一次。
103
+ `startCueLineRun` 是明確的啟動入口(`runCueLine` 是它的別名)。`continueCueLineRun({ runId })` 會在同一個對話裡續跑被中斷的執行,並沿用已保存的對話網址,除非你另外傳入新的 adapter。`loadCueLineRunState(runId)` 只讀取已保存的狀態,不驅動任何東西。已經走到 `complete`、`blocked` 或 `cancelled` 的執行會原樣回傳,絕不會被再派工一次。續跑前先執行 `cueline run status <run-id> --json`;若回覆已採用且 phase 是 `jobs_running`,代表 ChatGPT 已回覆,現在跑的是本機工作。
101
104
 
102
105
  ## CLI
103
106
 
@@ -108,7 +111,7 @@ $ cueline install
108
111
  CueLine skill installed: /Users/you/.codex/skills/cueline
109
112
 
110
113
  $ cueline doctor
111
- CueLine 0.1.1
114
+ CueLine 0.1.3
112
115
  status ok
113
116
  node 22.14.0 ok
114
117
  config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
@@ -124,6 +127,12 @@ default codex-default available
124
127
  $ cueline jobs
125
128
  No jobs.
126
129
 
130
+ $ cueline run status run_... --json
131
+ {"status":"running","phase":"jobs_running","runtime":{"ownership":"active"},...}
132
+
133
+ $ cueline run cancel run_...
134
+ run_... requested affected_jobs=0
135
+
127
136
  $ cueline config path
128
137
  /usr/local/lib/node_modules/cueline/config/routing.default.json
129
138
 
@@ -143,13 +152,15 @@ Node 版本太舊、或沒有任何通道解析得出來時,`cueline doctor`
143
152
 
144
153
  ```text
145
154
  runs/<run-id>/events.jsonl 只追加、具權威性
155
+ runs/<run-id>/runtime.json 活 owner 的 heartbeat 證據
156
+ runs/<run-id>/cancel.json 存在時代表持久取消要求
146
157
  runs/<run-id>/snapshot.json 重播的最佳化產物,可丟棄
147
158
  jobs/<job-id>.json 每個工作的執行證據
148
159
  ```
149
160
 
150
161
  事件日誌才是紀錄本身:主控端的這一輪在送出之前就先寫下、工作在行程啟動之前就先註冊,所以「意圖」與「副作用」之間若被中斷,會留下痕跡。壞掉的快照會被忽略、從第 1 號事件重建,而不是硬信它。
151
162
 
152
- 續跑只會重新接回該次執行記錄下來的那個對話網址,絕不接到長得像的分頁。若某個分頁在「送出狀態未明」的當下消失,CueLine 會丟出 `TAB_RECOVERY_UNSAFE` 並停下。它絕不自行重送提示,因為它無法證明第一次到底送出去了沒有。
163
+ 續跑只會重新接回該次執行記錄下來的那個對話網址,絕不接到長得像的分頁。對尚待處理的主控回合,它會先在該對話尋找與確切請求相符的已完成回覆;找到就以唯讀方式接回,不會重送。若舊狀態中同時有多個待處理回合,呼叫端必須明確指定一個。只有當唯一待處理提示能被證明為 `definitely_not_sent` 時,CueLine 才會自動重試;提交狀態不明或分頁消失時,會丟出 `TAB_RECOVERY_UNSAFE` 並停下。
153
164
 
154
165
  ## 驗證
155
166
 
package/dist/src/api.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { BrowserAdapter } from "./browser/browser-adapter.js";
2
2
  import { createCodexIabAdapter, type CodexIabAdapterOptions } from "./browser/codex-iab/chatgpt-client.js";
3
3
  import { type CueLineResult } from "./core/controller-loop.js";
4
+ import { type CueLineRunStatusSummary } from "./core/run-status.js";
4
5
  import { type CueLineRunState } from "./core/state-machine.js";
5
6
  import type { RoutingConfig } from "./router/types.js";
6
7
  export interface CueLineRuntimeOptions {
@@ -16,6 +17,9 @@ export interface CueLineRuntimeOptions {
16
17
  maxRounds?: number;
17
18
  maxRepairAttempts?: number;
18
19
  now?: () => Date;
20
+ signal?: AbortSignal;
21
+ cancellationPollIntervalMs?: number;
22
+ runTimeoutMs?: number;
19
23
  }
20
24
  export interface StartCueLineRunOptions extends CueLineRuntimeOptions {
21
25
  request: string;
@@ -26,11 +30,29 @@ export interface ContinueCueLineRunOptions extends CueLineRuntimeOptions {
26
30
  reconcileRequestId?: string;
27
31
  abandonOtherPendingTurns?: boolean;
28
32
  }
33
+ export interface CueLineRunCancellationResult {
34
+ runId: string;
35
+ outcome: "requested" | "cancelled" | "already_terminal";
36
+ affectedJobs: number;
37
+ }
38
+ export interface CueLineJobCancellationResult {
39
+ runId: string;
40
+ jobId: string;
41
+ outcome: "requested" | "ambiguous" | "already_terminal";
42
+ }
29
43
  export declare function defaultRoutingConfigPath(): string;
30
44
  export declare function routingConfigPath(environment?: NodeJS.ProcessEnv, explicitPath?: string): string;
31
45
  export declare function loadCueLineRunState(runId: string, options?: Pick<CueLineRuntimeOptions, "home" | "environment">): Promise<CueLineRunState>;
46
+ export declare function loadCueLineRunStatus(runId: string, options?: Pick<CueLineRuntimeOptions, "home" | "environment" | "now">): Promise<CueLineRunStatusSummary>;
47
+ export declare function cancelCueLineRun(runId: string, options?: Pick<CueLineRuntimeOptions, "home" | "environment" | "now"> & {
48
+ reason?: string;
49
+ }): Promise<CueLineRunCancellationResult>;
50
+ export declare function cancelCueLineJob(runId: string, jobId: string, options?: Pick<CueLineRuntimeOptions, "home" | "environment" | "now"> & {
51
+ reason?: string;
52
+ }): Promise<CueLineJobCancellationResult>;
32
53
  export declare function startCueLineRun(options: StartCueLineRunOptions): Promise<CueLineResult>;
33
54
  export declare function runCueLine(options: StartCueLineRunOptions): Promise<CueLineResult>;
34
55
  export declare function continueCueLineRun(options: ContinueCueLineRunOptions): Promise<CueLineResult>;
35
56
  export { createCodexIabAdapter };
36
- export type { BrowserAdapter, CueLineResult, CueLineRunState, RoutingConfig };
57
+ export { CUELINE_VERSION } from "./version.js";
58
+ export type { BrowserAdapter, CueLineResult, CueLineRunState, CueLineRunStatusSummary, RoutingConfig, };