cueline 0.1.4 → 0.1.6
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 +2 -2
- package/.codex-plugin/plugin.json +2 -2
- package/CHANGELOG.md +37 -0
- package/README.ja.md +27 -13
- package/README.ko.md +27 -13
- package/README.md +43 -16
- package/README.zh-CN.md +29 -13
- package/README.zh-TW.md +41 -16
- package/config/routing.default.json +1 -0
- package/dist/src/api-caller-work.d.ts +18 -0
- package/dist/src/api-caller-work.js +397 -0
- package/dist/src/api-caller-work.js.map +1 -0
- package/dist/src/api-contracts.d.ts +37 -0
- package/dist/src/api-controller-handoff.d.ts +2 -2
- package/dist/src/api-controller-handoff.js +105 -11
- package/dist/src/api-controller-handoff.js.map +1 -1
- package/dist/src/api-runtime-lifecycle.js +8 -7
- package/dist/src/api-runtime-lifecycle.js.map +1 -1
- package/dist/src/api.d.ts +3 -1
- package/dist/src/api.js +32 -3
- package/dist/src/api.js.map +1 -1
- package/dist/src/browser/browser-adapter.d.ts +5 -0
- package/dist/src/browser/codex-iab/bootstrap.d.ts +1 -0
- package/dist/src/browser/codex-iab/bootstrap.js +43 -2
- package/dist/src/browser/codex-iab/bootstrap.js.map +1 -1
- package/dist/src/browser/codex-iab/chatgpt-client.js +7 -49
- package/dist/src/browser/codex-iab/chatgpt-client.js.map +1 -1
- package/dist/src/browser/codex-iab/submission-url.js +5 -1
- package/dist/src/browser/codex-iab/submission-url.js.map +1 -1
- package/dist/src/browser/codex-iab/tab-discovery.d.ts +3 -0
- package/dist/src/browser/codex-iab/tab-discovery.js +61 -0
- package/dist/src/browser/codex-iab/tab-discovery.js.map +1 -0
- package/dist/src/cli/main.js +27 -4
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/core/controller-command-execution.js +26 -2
- package/dist/src/core/controller-command-execution.js.map +1 -1
- package/dist/src/core/controller-loop.js +66 -23
- package/dist/src/core/controller-loop.js.map +1 -1
- package/dist/src/core/controller-turn.js +11 -0
- package/dist/src/core/controller-turn.js.map +1 -1
- package/dist/src/core/controller-types.d.ts +3 -1
- package/dist/src/core/ids.d.ts +1 -0
- package/dist/src/core/ids.js +3 -0
- package/dist/src/core/ids.js.map +1 -1
- package/dist/src/core/run-status.d.ts +31 -4
- package/dist/src/core/run-status.js +142 -4
- package/dist/src/core/run-status.js.map +1 -1
- package/dist/src/core/state-machine.d.ts +31 -1
- package/dist/src/core/state-machine.js +214 -2
- package/dist/src/core/state-machine.js.map +1 -1
- package/dist/src/jobs/status.d.ts +5 -0
- package/dist/src/jobs/status.js.map +1 -1
- package/dist/src/jobs/supervisor.js +32 -6
- package/dist/src/jobs/supervisor.js.map +1 -1
- package/dist/src/router/materialize.js +1 -0
- package/dist/src/router/materialize.js.map +1 -1
- package/dist/src/runners/process-runner.js +54 -0
- package/dist/src/runners/process-runner.js.map +1 -1
- package/dist/src/runners/runner-adapter.d.ts +9 -0
- package/dist/src/runners/runner-adapter.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/docs/architecture.md +8 -7
- package/docs/assets/cueline-loop-en.svg +1 -1
- package/docs/assets/cueline-loop-ja.svg +1 -1
- package/docs/assets/cueline-loop-ko.svg +1 -1
- package/docs/assets/cueline-loop-zh-CN.svg +1 -1
- package/docs/assets/cueline-loop-zh-TW.svg +1 -1
- package/docs/compatibility.md +8 -8
- package/docs/controller-protocol.md +4 -4
- package/docs/runner-contract.md +20 -7
- package/docs/state-and-recovery.md +19 -12
- package/package.json +2 -2
- package/skills/cueline/SKILL.md +51 -10
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cueline",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Use a ChatGPT web conversation as the text controller for durable local advice executed by the current Codex.",
|
|
3
|
+
"version": "0.1.6",
|
|
4
|
+
"description": "Use a ChatGPT web conversation as the text controller for durable local advice or explicitly claimed work executed by the current Codex.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "CueLine contributors"
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cueline",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Use a ChatGPT web conversation as the text controller for durable local advice executed by the current Codex.",
|
|
3
|
+
"version": "0.1.6",
|
|
4
|
+
"description": "Use a ChatGPT web conversation as the text controller for durable local advice or explicitly claimed work executed by the current Codex.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "CueLine contributors"
|
|
7
7
|
},
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.6 - 2026-07-15
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Add a durable caller-work claim protocol for local mutations. A `work` dispatch in caller mode now pauses as `caller_work_pending`; `claimCueLineCallerJob`, `startCueLineCallerJob`, heartbeat, release, and result submission bind the exact run, job, task hash, absolute workdir, caller identity, expiry, and monotonically increasing fencing token. An unstarted expired claim is safely reclaimable; started work that loses its claim becomes `ambiguous` and is never automatically retried.
|
|
8
|
+
- Expose separate controller, caller-work, and process-execution status surfaces. Process status includes the resolved runner, model, provider, PID, phase, and last-progress timestamp; model/provider discovery keeps the first valid Codex header instead of allowing later untrusted job output to spoof it. Caller work reports pending, claimed, and running phases without pretending that Pro used local tools.
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Ignore hidden, disabled, inert, ancestor-hidden, zero-geometry, or otherwise non-actionable residual `Stop answering` buttons. A completed Pro response can now reconcile even when ChatGPT retains a hidden stop control in the DOM.
|
|
13
|
+
- Preserve exact `inspect(job_ids)` targets and allocate the bounded controller-evidence budget to those jobs first, so Pro receives the requested stdout instead of repeatedly seeing only terminal status.
|
|
14
|
+
- Recover only one precisely fenced, normally submitted caller observation after an outer timeout, and release every observation lease in `finally`. Ambiguous/manual/multiple turns, URL mismatches, jobs, commands, and cancellations remain in explicit reconciliation paths.
|
|
15
|
+
- Make caller-work result submission crash-recoverable with a durable result-intent event; reject clock regression, invalid or reversed timestamps, forged or out-of-order claims, duplicate terminal results, and release-after-start. Any non-success result after work starts is normalized to `ambiguous`.
|
|
16
|
+
- Require both `executor: "process"` and `allowProcessExecution: true` at run creation and every nonterminal continuation. Process work never exposes a caller-claim surface, and a failing diagnostic progress hook cannot break process supervision.
|
|
17
|
+
- Launch the bundled `codex-default` process route with `--ignore-user-config`, preventing hidden inheritance of user-configured MCP commands and their process arguments. The runner still uses registered argv directly without a shell.
|
|
18
|
+
- Prefer the current injected built-in Browser binding before fallback discovery, while keeping all controller observation read-only and never invoking `Answer now`, `Respond now`, `Stop`, or equivalent interruption controls.
|
|
19
|
+
|
|
20
|
+
### Verification
|
|
21
|
+
|
|
22
|
+
- Added adversarial coverage for hidden stop controls and hidden ancestors, inspected-output prioritization, stale observer fencing, caller claim races/restarts/expiry/result crashes/clock attacks, process double authorization, caller-vs-process status separation, diagnostic-hook failure, and bundled route isolation.
|
|
23
|
+
- Verified the real ChatGPT Web Pro path with a new conversation and new caller run: each prompt was sent once, no process or work job was started, bounded local evidence was returned through caller advice, and Pro was allowed to finish every reasoning turn without interruption. The terminal Pro verdict was `complete`, with no additional evidence requested for the five scoped blockers.
|
|
24
|
+
|
|
25
|
+
## 0.1.5 - 2026-07-15
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- Add a durable built-in-browser `write_ahead_v1` submission contract. Only an exact request with that contract or request-correlated `definitely_not_sent` evidence may retry; the retry reuses the controller round. Status now reports `prompt_not_sent` / `retry` instead of incorrectly claiming that an unsent prompt is waiting for a response.
|
|
30
|
+
- Normalize contenteditable block newlines before prompt-readiness comparison, wait for the Pro composer label to hydrate before sending, extend new-conversation URL capture to 15 seconds for attachment conversion, prefer the active injected Browser binding, and recover from a stale selected webview by claiming the exact matching user conversation.
|
|
31
|
+
- Let manual submission confirmation atomically bind the first exact ChatGPT `/c/...` URL through the API and `cueline run reconcile ... --conversation-url URL`, without hand-editing the event log or resending.
|
|
32
|
+
- Make process recovery perform one-shot controller observation and always direct a stale process takeover through `reconcile_runtime`; the advertised reconcile-then-continue path is covered end to end.
|
|
33
|
+
- Fix nested `-h` / `--help` parsing and a date-dependent runtime-lease takeover test.
|
|
34
|
+
- Make the controller boundary explicit: Pro has no local tools or implicit path knowledge. Controller prompts and caller evidence require exact code/error identifiers, relevant code excerpts, absolute local paths, and an explicit request for any additional missing evidence. Pro observation must never invoke `Answer now`, `Respond now`, `Stop`, or an equivalent interruption control.
|
|
35
|
+
|
|
36
|
+
### Verification
|
|
37
|
+
|
|
38
|
+
- Real ChatGPT Web Pro attachment runs verified one-click submission, exact URL capture, fast `awaiting_controller` release, repeated one-shot observation while Pro reasoned, exact envelope reconciliation, zero duplicate jobs, and terminal `complete` without interruption.
|
|
39
|
+
|
|
3
40
|
## 0.1.4 - 2026-07-15
|
|
4
41
|
|
|
5
42
|
### Fixed
|
package/README.ja.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
**CueLine は、開いている ChatGPT のウェブ会話に判断を任せます。会話側はテキストコマンドを出し、CueLine が検証し、現在の Codex が許可されたローカル作業を実行します。**
|
|
15
15
|
|
|
16
|
-
ウェブページにローカルツールはありません。既定の `caller`
|
|
16
|
+
ウェブページにローカルツールはありません。既定の `caller` 実行では、`advise` は協調用の引き渡し、`work` は永続 claim と start が必要です。登録済みワーカーを起動する process executor には二重の明示的承認が必要です。
|
|
17
17
|
|
|
18
18
|
CueLine は独立した実装で、**ランタイムの npm 依存はゼロ**です。Omnilane や GPT Relay のラッパーではありません。
|
|
19
19
|
|
|
@@ -25,9 +25,9 @@ CueLine は独立した実装で、**ランタイムの npm 依存はゼロ**で
|
|
|
25
25
|
|
|
26
26
|
既定値以外の `maxRounds` は run 作成時に固定され、owner 不在の一時停止をまたいでコントローラーの総ラウンド数を数えます。後の続行では通常省略して永続値を再利用し、異なる値を渡すと予算を暗黙にリセットまたは拡張せず拒否します。
|
|
27
27
|
|
|
28
|
-
`startCueLineRun` と `runCueLine` の既定は `caller`
|
|
28
|
+
`startCueLineRun` と `runCueLine` の既定は `caller` です。送信後は `awaiting_controller` を返して lease を解放し、続行は 1 回の読み取り専用観測だけを行い、再送しません。`advise` は `awaiting_caller`、`work` は `awaiting_caller_work` を返します。work は現在の Codex が `claimCueLineCallerJob` と `startCueLineCallerJob` を成功させるまで開始されません。claim は run、job、task hash、絶対 workdir、caller identity、fencing token に結び付けられ、開始済み work は自動再試行されず、期限切れなら `ambiguous` になります。Pro はテキスト命令を提案・審査するだけで、ローカルツールは使いません。
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
Process モードは `executor: "process"` と `allowProcessExecution: true` の両方が必要で、非終端の続行でも第 2 の承認を再度渡します。組み込み route はさらに `--ignore-user-config` を使い、隠れた worker がユーザー設定の MCP server やそのコマンド引数を読み込まないようにします。レーンと候補は起動前に検証され、シェルも起動後の自動フォールバックも使いません。
|
|
31
31
|
|
|
32
32
|
コントローラープロトコルでは、ルーティングの階層を明確に区別します。`lane` に指定するのはレーン名の `default` であり、`codex-default` はそのレーン内の候補ランナーであって、レーンではありません。CueLine はジョブを一つでも登録する前に `dispatch` 全体を検証します。無効なレーンまたはランナーが一つでもあれば、途中まで実行せず、`dispatch` 全体を修正のために差し戻します。
|
|
33
33
|
|
|
@@ -48,15 +48,15 @@ ChatGPT Pro のサブスクリプションと、選択された Pro モデルは
|
|
|
48
48
|
npm レジストリからインストールします。
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
|
-
npm install -g cueline@0.1.
|
|
51
|
+
npm install -g cueline@0.1.6
|
|
52
52
|
cueline install
|
|
53
53
|
cueline doctor
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
フォールバックとして、[v0.1.
|
|
56
|
+
フォールバックとして、[v0.1.6 リリース](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.6) のパッケージ済み tarball をインストールすることもできます。同じリリースに `.sha256` チェックサムも置いてあります。
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.
|
|
59
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.6/cueline-0.1.6.tgz
|
|
60
60
|
cueline install
|
|
61
61
|
cueline doctor
|
|
62
62
|
```
|
|
@@ -89,23 +89,26 @@ cueline doctor
|
|
|
89
89
|
|
|
90
90
|
```js
|
|
91
91
|
import {
|
|
92
|
+
claimCueLineCallerJob,
|
|
92
93
|
continueCueLineRun,
|
|
93
94
|
createCodexIabAdapter,
|
|
95
|
+
heartbeatCueLineCallerJob,
|
|
94
96
|
runCueLine,
|
|
97
|
+
startCueLineCallerJob,
|
|
95
98
|
submitCueLineCallerJobResult,
|
|
96
99
|
} from "cueline";
|
|
97
100
|
|
|
98
101
|
let result = await runCueLine({
|
|
99
102
|
request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
|
|
100
|
-
browser: createCodexIabAdapter(),
|
|
103
|
+
browser: createCodexIabAdapter({ browser: globalThis.browser }),
|
|
101
104
|
// 任意:conversationUrl、routingConfig / routingConfigPath、home、cwd、
|
|
102
105
|
// runTimeoutMs、signal、ジョブごと/既定の期限。
|
|
103
106
|
}); // 既定は executor: "caller"
|
|
104
107
|
|
|
105
|
-
while (
|
|
108
|
+
while (["awaiting_controller", "awaiting_caller", "awaiting_caller_work"].includes(result.status)) {
|
|
106
109
|
if (result.status === "awaiting_controller") {
|
|
107
110
|
await waitBeforeNextObservation(); // 有界バックオフ。再送しない
|
|
108
|
-
} else {
|
|
111
|
+
} else if (result.status === "awaiting_caller") {
|
|
109
112
|
for (const job of result.pendingJobs ?? []) {
|
|
110
113
|
const stdout = await executeExactLocalAdvice(job.spec.task);
|
|
111
114
|
await submitCueLineCallerJobResult(result.runId, job.jobId, {
|
|
@@ -113,6 +116,17 @@ while (result.status === "awaiting_controller" || result.status === "awaiting_ca
|
|
|
113
116
|
stdout,
|
|
114
117
|
});
|
|
115
118
|
}
|
|
119
|
+
} else {
|
|
120
|
+
for (const job of result.pendingJobs ?? []) {
|
|
121
|
+
if (job.spec.mode !== "work") continue;
|
|
122
|
+
const claim = await claimCueLineCallerJob(result.runId, job.jobId, { callerId: "stable-codex-task-identity" });
|
|
123
|
+
const proof = { claimId: claim.claimId, callerId: claim.callerId, fencingToken: claim.fencingToken };
|
|
124
|
+
await startCueLineCallerJob(result.runId, job.jobId, proof);
|
|
125
|
+
const stdout = await executeExactLocalWork(job.spec.task, claim.workdir, {
|
|
126
|
+
heartbeat: () => heartbeatCueLineCallerJob(result.runId, job.jobId, proof),
|
|
127
|
+
});
|
|
128
|
+
await submitCueLineCallerJobResult(result.runId, job.jobId, { status: "succeeded", stdout }, { claim: proof });
|
|
129
|
+
}
|
|
116
130
|
}
|
|
117
131
|
result = await continueCueLineRun({ runId: result.runId });
|
|
118
132
|
}
|
|
@@ -122,7 +136,7 @@ if (result.status === "complete") {
|
|
|
122
136
|
}
|
|
123
137
|
```
|
|
124
138
|
|
|
125
|
-
`awaiting_controller`
|
|
139
|
+
`awaiting_controller` は再送なしの読み取り専用観測、`awaiting_caller` は advise の引き渡し、`awaiting_caller_work` は claim、start、実行、heartbeat、claim proof 付き提出の順です。Pro はローカルツールを直接使いません。
|
|
126
140
|
|
|
127
141
|
Codex のランタイムでは、`cueline api path` が出力する絶対パスのモジュールを import します。それがインストールしたパッケージのビルド済み API です。
|
|
128
142
|
|
|
@@ -137,7 +151,7 @@ $ cueline install
|
|
|
137
151
|
CueLine skill installed: /Users/you/.codex/skills/cueline
|
|
138
152
|
|
|
139
153
|
$ cueline doctor
|
|
140
|
-
CueLine 0.1.
|
|
154
|
+
CueLine 0.1.6
|
|
141
155
|
status ok
|
|
142
156
|
node 22.14.0 ok
|
|
143
157
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -179,7 +193,7 @@ Node が古すぎる場合、または有効な caller レーンが一つもな
|
|
|
179
193
|
|
|
180
194
|
`CUELINE_CONFIG` はルーティング設定ファイルを選び、`CUELINE_HOME` はローカル状態の置き場所を移します(既定は `~/.cueline`)。
|
|
181
195
|
|
|
182
|
-
Caller はプロセスを起動しません。`process`
|
|
196
|
+
Caller はプロセスを起動しません。`executor: "process"` と `allowProcessExecution: true` を同時に指定した場合だけ、`default` レーンの `codex-default` が隔離された `codex exec --ignore-user-config` を実行します。独立した `advise` の既定同時実行数は全体/レーンごとに 2、`work` を含むバッチは直列です。
|
|
183
197
|
|
|
184
198
|
状態は `CUELINE_HOME` の下に置かれます:
|
|
185
199
|
|
|
@@ -212,7 +226,7 @@ npm pack --dry-run
|
|
|
212
226
|
|
|
213
227
|
## 0.1 の制限
|
|
214
228
|
|
|
215
|
-
テキストコマンドのみ。長文の自動添付変換は対応しますが、意図的なファイルアップロード、画像、Deep Research、Projects、Apps は非対応です。Caller
|
|
229
|
+
テキストコマンドのみ。長文の自動添付変換は対応しますが、意図的なファイルアップロード、画像、Deep Research、Projects、Apps は非対応です。Caller work は明示的な claim/start、process 実行は二重承認が必要です。曖昧な送信や開始済みジョブを自動再試行しません。
|
|
216
230
|
|
|
217
231
|
完全な対応表は [compatibility](docs/compatibility.md) を参照してください。
|
|
218
232
|
|
package/README.ko.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
**CueLine은 열린 ChatGPT 웹 대화에 판단을 맡깁니다. 대화는 텍스트 명령을 내리고, CueLine이 검증하며, 현재 Codex가 허용된 로컬 작업을 수행합니다.**
|
|
15
15
|
|
|
16
|
-
웹 페이지에는 로컬 도구가 없습니다. 기본 `caller`
|
|
16
|
+
웹 페이지에는 로컬 도구가 없습니다. 기본 `caller` 실행에서 `advise`는 조정용 인계이며, `work`는 지속 claim과 start가 필요합니다. 등록된 워커를 띄우는 process executor는 이중 명시 승인이 필요합니다.
|
|
17
17
|
|
|
18
18
|
CueLine은 독립적인 구현이며 **런타임 npm 의존성이 전혀 없습니다**. Omnilane이나 GPT Relay를 감싼 래퍼가 아닙니다.
|
|
19
19
|
|
|
@@ -25,9 +25,9 @@ CueLine은 독립적인 구현이며 **런타임 npm 의존성이 전혀 없습
|
|
|
25
25
|
|
|
26
26
|
기본값이 아닌 `maxRounds`는 run 생성 시 고정되며 owner가 없는 일시 중지를 가로질러 컨트롤러 총 라운드 수를 셉니다. 이후 계속하기에서는 보통 생략해 지속 값을 재사용하고, 다른 값을 전달하면 예산을 몰래 재설정하거나 늘리지 않고 거부합니다.
|
|
27
27
|
|
|
28
|
-
`startCueLineRun`과 `runCueLine`의 기본값은 `caller`입니다.
|
|
28
|
+
`startCueLineRun`과 `runCueLine`의 기본값은 `caller`입니다. 전송 뒤 `awaiting_controller`를 반환하고 lease를 해제하며, 계속하기는 재전송 없이 읽기 전용 관측 한 번만 수행합니다. `advise`는 `awaiting_caller`, `work`는 `awaiting_caller_work`를 반환합니다. work는 현재 Codex가 `claimCueLineCallerJob`과 `startCueLineCallerJob`을 성공시키기 전에는 시작되지 않습니다. claim은 run, job, task hash, 절대 workdir, caller identity, fencing token에 묶이며 시작된 work는 자동 재시도되지 않고 만료 시 `ambiguous`가 됩니다. Pro는 텍스트 명령을 제안하고 검토할 뿐 로컬 도구를 쓰지 않습니다.
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
Process 모드는 `executor: "process"`와 `allowProcessExecution: true`가 모두 필요하며, 비종료 계속하기에서도 두 번째 승인을 다시 전달해야 합니다. 번들 route는 `--ignore-user-config`도 사용하므로 숨은 worker가 사용자 설정 MCP server나 그 명령 인자를 로드하지 않습니다. 레인과 후보는 시작 전에 검증되고 셸이나 시작 후 자동 폴백은 사용하지 않습니다.
|
|
31
31
|
|
|
32
32
|
컨트롤러 프로토콜은 라우팅 계층을 명확히 구분합니다. `lane`에는 레인 이름인 `default`를 써야 하며, `codex-default`는 그 레인 안의 후보 러너이지 레인이 아닙니다. CueLine은 작업을 하나라도 등록하기 전에 `dispatch` 전체를 검증합니다. 잘못된 레인이나 러너가 하나라도 있으면 일부를 먼저 실행하지 않고 `dispatch` 전체를 수정하도록 돌려보냅니다.
|
|
33
33
|
|
|
@@ -48,15 +48,15 @@ ChatGPT Pro 구독과 선택된 Pro 모델은 서로 다른 것입니다. 계정
|
|
|
48
48
|
npm 레지스트리에서 설치합니다:
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
|
-
npm install -g cueline@0.1.
|
|
51
|
+
npm install -g cueline@0.1.6
|
|
52
52
|
cueline install
|
|
53
53
|
cueline doctor
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
대안으로, [v0.1.
|
|
56
|
+
대안으로, [v0.1.6 릴리스](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.6)의 패키지 tarball을 설치할 수도 있습니다. 같은 릴리스에 `.sha256` 체크섬도 함께 있습니다.
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.
|
|
59
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.6/cueline-0.1.6.tgz
|
|
60
60
|
cueline install
|
|
61
61
|
cueline doctor
|
|
62
62
|
```
|
|
@@ -89,23 +89,26 @@ cueline doctor
|
|
|
89
89
|
|
|
90
90
|
```js
|
|
91
91
|
import {
|
|
92
|
+
claimCueLineCallerJob,
|
|
92
93
|
continueCueLineRun,
|
|
93
94
|
createCodexIabAdapter,
|
|
95
|
+
heartbeatCueLineCallerJob,
|
|
94
96
|
runCueLine,
|
|
97
|
+
startCueLineCallerJob,
|
|
95
98
|
submitCueLineCallerJobResult,
|
|
96
99
|
} from "cueline";
|
|
97
100
|
|
|
98
101
|
let result = await runCueLine({
|
|
99
102
|
request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
|
|
100
|
-
browser: createCodexIabAdapter(),
|
|
103
|
+
browser: createCodexIabAdapter({ browser: globalThis.browser }),
|
|
101
104
|
// 선택: conversationUrl, routingConfig / routingConfigPath, home, cwd,
|
|
102
105
|
// runTimeoutMs, signal, 작업별/기본 제한 시간.
|
|
103
106
|
}); // 기본 executor: "caller"
|
|
104
107
|
|
|
105
|
-
while (
|
|
108
|
+
while (["awaiting_controller", "awaiting_caller", "awaiting_caller_work"].includes(result.status)) {
|
|
106
109
|
if (result.status === "awaiting_controller") {
|
|
107
110
|
await waitBeforeNextObservation(); // 제한된 백오프. 재전송 금지
|
|
108
|
-
} else {
|
|
111
|
+
} else if (result.status === "awaiting_caller") {
|
|
109
112
|
for (const job of result.pendingJobs ?? []) {
|
|
110
113
|
const stdout = await executeExactLocalAdvice(job.spec.task);
|
|
111
114
|
await submitCueLineCallerJobResult(result.runId, job.jobId, {
|
|
@@ -113,6 +116,17 @@ while (result.status === "awaiting_controller" || result.status === "awaiting_ca
|
|
|
113
116
|
stdout,
|
|
114
117
|
});
|
|
115
118
|
}
|
|
119
|
+
} else {
|
|
120
|
+
for (const job of result.pendingJobs ?? []) {
|
|
121
|
+
if (job.spec.mode !== "work") continue;
|
|
122
|
+
const claim = await claimCueLineCallerJob(result.runId, job.jobId, { callerId: "stable-codex-task-identity" });
|
|
123
|
+
const proof = { claimId: claim.claimId, callerId: claim.callerId, fencingToken: claim.fencingToken };
|
|
124
|
+
await startCueLineCallerJob(result.runId, job.jobId, proof);
|
|
125
|
+
const stdout = await executeExactLocalWork(job.spec.task, claim.workdir, {
|
|
126
|
+
heartbeat: () => heartbeatCueLineCallerJob(result.runId, job.jobId, proof),
|
|
127
|
+
});
|
|
128
|
+
await submitCueLineCallerJobResult(result.runId, job.jobId, { status: "succeeded", stdout }, { claim: proof });
|
|
129
|
+
}
|
|
116
130
|
}
|
|
117
131
|
result = await continueCueLineRun({ runId: result.runId });
|
|
118
132
|
}
|
|
@@ -122,7 +136,7 @@ if (result.status === "complete") {
|
|
|
122
136
|
}
|
|
123
137
|
```
|
|
124
138
|
|
|
125
|
-
`awaiting_controller
|
|
139
|
+
`awaiting_controller`는 재전송 없는 읽기 전용 관측, `awaiting_caller`는 advise 인계, `awaiting_caller_work`는 claim, start, 실행, heartbeat, claim proof 제출 순서입니다. Pro는 로컬 도구를 직접 쓰지 않습니다.
|
|
126
140
|
|
|
127
141
|
Codex 런타임에서는 `cueline api path`가 출력하는 절대 경로 모듈을 import하세요. 그것이 설치한 패키지의 빌드된 API입니다.
|
|
128
142
|
|
|
@@ -137,7 +151,7 @@ $ cueline install
|
|
|
137
151
|
CueLine skill installed: /Users/you/.codex/skills/cueline
|
|
138
152
|
|
|
139
153
|
$ cueline doctor
|
|
140
|
-
CueLine 0.1.
|
|
154
|
+
CueLine 0.1.6
|
|
141
155
|
status ok
|
|
142
156
|
node 22.14.0 ok
|
|
143
157
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -179,7 +193,7 @@ Node 버전이 너무 낮거나 활성화된 caller 레인이 하나도 없으
|
|
|
179
193
|
|
|
180
194
|
`CUELINE_CONFIG`는 라우팅 설정 파일을 고르고, `CUELINE_HOME`은 로컬 상태의 위치를 옮깁니다(기본값 `~/.cueline`).
|
|
181
195
|
|
|
182
|
-
Caller는 프로세스를 띄우지 않습니다. `process`
|
|
196
|
+
Caller는 프로세스를 띄우지 않습니다. `executor: "process"`와 `allowProcessExecution: true`를 함께 지정한 경우에만 `default` 레인의 `codex-default`가 격리된 `codex exec --ignore-user-config`를 실행합니다. 독립 `advise`의 기본 동시 실행 상한은 전체/레인당 2이고, `work`가 포함된 배치는 직렬입니다.
|
|
183
197
|
|
|
184
198
|
상태는 `CUELINE_HOME` 아래에 놓입니다:
|
|
185
199
|
|
|
@@ -212,7 +226,7 @@ npm pack --dry-run
|
|
|
212
226
|
|
|
213
227
|
## 0.1의 한계
|
|
214
228
|
|
|
215
|
-
텍스트 명령 전용입니다. 긴 텍스트의 자동 첨부 변환은 지원하지만 의도적 파일 업로드, 이미지, Deep Research, Projects, Apps는 지원하지 않습니다. Caller
|
|
229
|
+
텍스트 명령 전용입니다. 긴 텍스트의 자동 첨부 변환은 지원하지만 의도적 파일 업로드, 이미지, Deep Research, Projects, Apps는 지원하지 않습니다. Caller work는 명시적 claim/start, process 실행은 이중 승인이 필요합니다. 모호한 전송이나 이미 시작된 작업은 자동 재시도하지 않습니다.
|
|
216
230
|
|
|
217
231
|
전체 표는 [compatibility](docs/compatibility.md)를 보세요.
|
|
218
232
|
|
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
**CueLine hands the wheel to an open ChatGPT web conversation: it plans the run and calls each next step, while CueLine checks every text command and the current Codex does the permitted local work.**
|
|
15
15
|
|
|
16
|
-
The web page never touches your machine and has no local tools. It only emits one text command per round. CueLine decides whether that command is well-formed and belongs to this run. By default, it persists
|
|
16
|
+
The web page never touches your machine and has no local tools. It only emits one text command per round. CueLine decides whether that command is well-formed and belongs to this run. By default, it persists caller jobs for the current Codex: `advise` is a coordination-only handoff, while `work` requires a durable claim and start before any mutation. An explicitly double-authorized process executor can instead run registered local workers. CueLine keeps bounded controller evidence and the full local record.
|
|
17
17
|
|
|
18
18
|
CueLine is a standalone implementation with **no runtime npm dependencies**. It is not a wrapper around Omnilane or GPT Relay.
|
|
19
19
|
|
|
@@ -25,9 +25,9 @@ Each round: CueLine writes down what it is about to ask, sends one observation i
|
|
|
25
25
|
|
|
26
26
|
A non-default `maxRounds` is fixed when the run is created and counts total controller rounds across every ownerless pause. Later continuations normally omit it and reuse the durable value; supplying a different value is rejected rather than silently resetting or widening the budget.
|
|
27
27
|
|
|
28
|
-
`caller` is the default executor for both `startCueLineRun` and `runCueLine`. With the built-in browser, CueLine submits once, captures the exact conversation URL, returns `awaiting_controller`, and releases the runtime lease instead of holding one tool call open while Pro thinks. A later `continueCueLineRun` performs one read-only observation: unfinished work returns `awaiting_controller` again without resending. A dispatch
|
|
28
|
+
`caller` is the default executor for both `startCueLineRun` and `runCueLine`. With the built-in browser, CueLine submits once, captures the exact conversation URL, returns `awaiting_controller`, and releases the runtime lease instead of holding one tool call open while Pro thinks. A later `continueCueLineRun` performs one read-only observation: unfinished work returns `awaiting_controller` again without resending. A dispatch produces durable pending jobs. `advise` returns `awaiting_caller`; it has no side-effect claim, so coordinate one session. `work` returns `awaiting_caller_work` and remains unstarted until the current Codex calls `claimCueLineCallerJob` and `startCueLineCallerJob`. The claim is bound to run, job, task hash, absolute workdir, caller identity, and a fencing token. Started work is never automatically retried; an expired started claim becomes `ambiguous`. ChatGPT proposed and reviewed the work—it did not use local tools or perform the work itself.
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
Process execution requires both `executor: "process"` and `allowProcessExecution: true`; a non-terminal continuation must pass the second authorization again. The bundled route also uses `--ignore-user-config`, preventing hidden workers from loading user-configured MCP servers or their command arguments. The controller chooses *what should happen* and 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. Independent advice defaults to two concurrent jobs globally and per lane; a batch containing `work` is serial. Once a worker starts, there is no silent fallback to a second candidate. Status exposes the resolved runner, PID, phase, last progress time, and safely observed model/provider metadata.
|
|
31
31
|
|
|
32
32
|
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.
|
|
33
33
|
|
|
@@ -48,15 +48,15 @@ You need Node.js 22+, Codex with its built-in Browser, and — for the bundled d
|
|
|
48
48
|
Install from the npm registry:
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
|
-
npm install -g cueline@0.1.
|
|
51
|
+
npm install -g cueline@0.1.6
|
|
52
52
|
cueline install
|
|
53
53
|
cueline doctor
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
As a fallback, install the packaged tarball from the [v0.1.
|
|
56
|
+
As a fallback, install the packaged tarball from the [v0.1.6 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.6), which also carries its `.sha256` checksum:
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.
|
|
59
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.6/cueline-0.1.6.tgz
|
|
60
60
|
cueline install
|
|
61
61
|
cueline doctor
|
|
62
62
|
```
|
|
@@ -89,23 +89,26 @@ The bundled `cueline` skill drives the package from Codex's own Node runtime, wh
|
|
|
89
89
|
|
|
90
90
|
```js
|
|
91
91
|
import {
|
|
92
|
+
claimCueLineCallerJob,
|
|
92
93
|
continueCueLineRun,
|
|
93
94
|
createCodexIabAdapter,
|
|
95
|
+
heartbeatCueLineCallerJob,
|
|
94
96
|
runCueLine,
|
|
97
|
+
startCueLineCallerJob,
|
|
95
98
|
submitCueLineCallerJobResult,
|
|
96
99
|
} from "cueline";
|
|
97
100
|
|
|
98
101
|
let result = await runCueLine({
|
|
99
102
|
request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
|
|
100
|
-
browser: createCodexIabAdapter(),
|
|
103
|
+
browser: createCodexIabAdapter({ browser: globalThis.browser }),
|
|
101
104
|
// Optional: conversationUrl, routingConfig / routingConfigPath, home, cwd,
|
|
102
105
|
// runTimeoutMs, signal, and per-job/default limits.
|
|
103
106
|
}); // defaults to executor: "caller"
|
|
104
107
|
|
|
105
|
-
while (
|
|
108
|
+
while (["awaiting_controller", "awaiting_caller", "awaiting_caller_work"].includes(result.status)) {
|
|
106
109
|
if (result.status === "awaiting_controller") {
|
|
107
110
|
await waitBeforeNextObservation(); // bounded backoff; never resend
|
|
108
|
-
} else {
|
|
111
|
+
} else if (result.status === "awaiting_caller") {
|
|
109
112
|
for (const job of result.pendingJobs ?? []) {
|
|
110
113
|
const stdout = await executeExactLocalAdvice(job.spec.task);
|
|
111
114
|
await submitCueLineCallerJobResult(result.runId, job.jobId, {
|
|
@@ -113,6 +116,28 @@ while (result.status === "awaiting_controller" || result.status === "awaiting_ca
|
|
|
113
116
|
stdout,
|
|
114
117
|
});
|
|
115
118
|
}
|
|
119
|
+
} else {
|
|
120
|
+
for (const job of result.pendingJobs ?? []) {
|
|
121
|
+
if (job.spec.mode !== "work") continue;
|
|
122
|
+
const claim = await claimCueLineCallerJob(result.runId, job.jobId, {
|
|
123
|
+
callerId: "stable-codex-task-identity",
|
|
124
|
+
});
|
|
125
|
+
const proof = {
|
|
126
|
+
claimId: claim.claimId,
|
|
127
|
+
callerId: claim.callerId,
|
|
128
|
+
fencingToken: claim.fencingToken,
|
|
129
|
+
};
|
|
130
|
+
await startCueLineCallerJob(result.runId, job.jobId, proof);
|
|
131
|
+
const stdout = await executeExactLocalWork(job.spec.task, claim.workdir, {
|
|
132
|
+
heartbeat: () => heartbeatCueLineCallerJob(result.runId, job.jobId, proof),
|
|
133
|
+
});
|
|
134
|
+
await submitCueLineCallerJobResult(
|
|
135
|
+
result.runId,
|
|
136
|
+
job.jobId,
|
|
137
|
+
{ status: "succeeded", stdout },
|
|
138
|
+
{ claim: proof },
|
|
139
|
+
);
|
|
140
|
+
}
|
|
116
141
|
}
|
|
117
142
|
result = await continueCueLineRun({ runId: result.runId });
|
|
118
143
|
}
|
|
@@ -122,7 +147,7 @@ if (result.status === "complete") {
|
|
|
122
147
|
}
|
|
123
148
|
```
|
|
124
149
|
|
|
125
|
-
`startCueLineRun` creates the durable run and returns `ready` without driving the browser. `runCueLine` creates and advances it to a durable controller-observation pause, caller handoff, or terminal state. `continueCueLineRun({ runId })` advances the same conversation and reuses its stored URL. `loadCueLineRunState(runId)` is read-only. A terminal run is returned as-is. Before continuation, run `cueline run status <run-id> --json`:
|
|
150
|
+
`startCueLineRun` creates the durable run and returns `ready` without driving the browser. `runCueLine` creates and advances it to a durable controller-observation pause, caller handoff, or terminal state. `continueCueLineRun({ runId })` advances the same conversation and reuses its stored URL. `loadCueLineRunState(runId)` is read-only. A terminal run is returned as-is. Before continuation, run `cueline run status <run-id> --json`: `controller_response_pending` with exactly one normally submitted turn and `safeNextAction: observe` means Pro's response has not yet been observed; wait briefly and continue it without resend. That exact read-only observer can be safely fenced even after its lease becomes stale, but ambiguous/manual submissions, jobs, pending commands, cancellation, or a missing/mismatched URL still require explicit recovery. `phase: prompt_not_sent` with `safeNextAction: retry` is used only with write-ahead or request-correlated `definitely_not_sent` evidence. Caller work phases report `claim_caller_work`, `start_caller_work`, or `continue_caller_work`; a dispatch alone is not local execution. An accepted response plus `jobs_running` means a double-authorized process executor is active.
|
|
126
151
|
|
|
127
152
|
Inside Codex's runtime, import the absolute module that `cueline api path` prints — that is the built API of the package you installed.
|
|
128
153
|
|
|
@@ -135,7 +160,7 @@ $ cueline install
|
|
|
135
160
|
CueLine skill installed: /Users/you/.codex/skills/cueline
|
|
136
161
|
|
|
137
162
|
$ cueline doctor
|
|
138
|
-
CueLine 0.1.
|
|
163
|
+
CueLine 0.1.6
|
|
139
164
|
status ok
|
|
140
165
|
node 22.14.0 ok
|
|
141
166
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -159,7 +184,7 @@ $ cueline run status run_... --json
|
|
|
159
184
|
$ cueline run takeover stale_run_... --json
|
|
160
185
|
{"runId":"stale_run_...","outcome":"taken_over","next":"continue",...}
|
|
161
186
|
|
|
162
|
-
$ cueline run reconcile run_... --request-id msg_... --manual-send-confirmed
|
|
187
|
+
$ cueline run reconcile run_... --request-id msg_... --manual-send-confirmed --conversation-url https://chatgpt.com/c/...
|
|
163
188
|
run_...\tmsg_...\tconfirmed
|
|
164
189
|
|
|
165
190
|
$ cueline run cancel run_...
|
|
@@ -180,7 +205,7 @@ Use `run takeover` only when `run status` reports an exact stale owner. It refus
|
|
|
180
205
|
|
|
181
206
|
`CUELINE_CONFIG` selects a routing file; `CUELINE_HOME` moves local state (default `~/.cueline`).
|
|
182
207
|
|
|
183
|
-
Caller execution needs no spawned route. When `executor: "process"`
|
|
208
|
+
Caller execution needs no spawned route. When `executor: "process"` and `allowProcessExecution: true` are both selected, the bundled `default` lane holds one candidate, `codex-default`: isolated `codex exec --ignore-user-config` with the task on stdin, `read-only` for `advise`, and `workspace-write` for `work`. To register a different process worker, copy [`config/routing.default.json`](config/routing.default.json), add your candidate, and point `CUELINE_CONFIG` at it.
|
|
184
209
|
|
|
185
210
|
State lives under `CUELINE_HOME`:
|
|
186
211
|
|
|
@@ -196,9 +221,11 @@ jobs/<job-id>.json per-job execution evidence
|
|
|
196
221
|
|
|
197
222
|
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.
|
|
198
223
|
|
|
199
|
-
Recovery reattaches only to the exact recorded conversation URL. CueLine recognizes long prompts that ChatGPT automatically converts into attachment chips and makes at most one send attempt. An ambiguous click is `possibly_sent` and is never clicked again. If an operator manually sends
|
|
224
|
+
Recovery reattaches only to the exact recorded conversation URL. CueLine recognizes long prompts that ChatGPT automatically converts into attachment chips and makes at most one send attempt. Contenteditable block newlines are normalized before readiness comparison. An ambiguous click is `possibly_sent` and is never clicked again. A response is considered in progress only while a visible, enabled, actionable Stop control exists; hidden residual buttons do not suppress a completed Pro response. If an operator manually sends an attachment after ChatGPT creates the first `/c/...` URL, `cueline run reconcile ... --manual-send-confirmed --conversation-url URL` atomically binds the exact URL and records an append-only confirmation; CueLine then requires exact conversation, Pro model, and protocol/run/round/request identity before importing the response without resend or duplicate dispatch.
|
|
225
|
+
|
|
226
|
+
Never interrupt Pro or use `Answer now`, `Respond now`, `Stop`, or an equivalent acceleration control while it is answering. Pro has no local tools and no default knowledge of repository layout or local paths. Caller evidence must include exact code/error identifiers, relevant code excerpts, and absolute local paths, then explicitly ask whether Pro needs more local evidence.
|
|
200
227
|
|
|
201
|
-
Controller observations prefer successful non-empty stdout, retain full stdout/stderr in local job status, and share one 12,000-character evidence budget with an explicit truncation marker.
|
|
228
|
+
Controller observations prefer successful non-empty stdout, retain full stdout/stderr in local job status, and share one 12,000-character evidence budget with an explicit truncation marker. An accepted `inspect(job_ids)` reserves that budget for the named jobs before unrelated evidence, so the next Pro turn receives the requested output instead of only its terminal status.
|
|
202
229
|
|
|
203
230
|
## Verify
|
|
204
231
|
|
|
@@ -215,7 +242,7 @@ npm pack --dry-run
|
|
|
215
242
|
|
|
216
243
|
## Limits in 0.1
|
|
217
244
|
|
|
218
|
-
Text commands only. One conversation per run. Selecting `Pro` is the only model switch CueLine makes. Automatic long-text-to-attachment conversion is supported, but deliberate file upload, images, Deep Research, Projects, and Apps are not. Caller
|
|
245
|
+
Text commands only. One conversation per run. Selecting `Pro` is the only model switch CueLine makes. Automatic long-text-to-attachment conversion is supported, but deliberate file upload, images, Deep Research, Projects, and Apps are not. Caller `work` requires an explicit durable claim/start and a heartbeat for long work; process execution requires two explicit authorization fields. No automatic retry or fallback starts work twice. macOS is the primary desktop target and Linux is the CI target; Windows is unverified. The adapter depends on the current ChatGPT web UI, so a UI change surfaces explicitly, never as a fabricated answer.
|
|
219
246
|
|
|
220
247
|
See [compatibility](docs/compatibility.md) for the full matrix.
|
|
221
248
|
|