cueline 0.1.2 → 0.1.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.
Files changed (116) hide show
  1. package/.claude-plugin/plugin.json +2 -2
  2. package/.codex-plugin/plugin.json +3 -3
  3. package/CHANGELOG.md +38 -0
  4. package/README.ja.md +65 -21
  5. package/README.ko.md +65 -21
  6. package/README.md +70 -23
  7. package/README.zh-CN.md +65 -21
  8. package/README.zh-TW.md +68 -22
  9. package/dist/src/api-contracts.d.ts +77 -0
  10. package/dist/src/api-contracts.js +2 -0
  11. package/dist/src/api-contracts.js.map +1 -0
  12. package/dist/src/api-controller-handoff.d.ts +6 -0
  13. package/dist/src/api-controller-handoff.js +253 -0
  14. package/dist/src/api-controller-handoff.js.map +1 -0
  15. package/dist/src/api-runtime-lifecycle.d.ts +22 -0
  16. package/dist/src/api-runtime-lifecycle.js +568 -0
  17. package/dist/src/api-runtime-lifecycle.js.map +1 -0
  18. package/dist/src/api.d.ts +9 -27
  19. package/dist/src/api.js +138 -42
  20. package/dist/src/api.js.map +1 -1
  21. package/dist/src/browser/browser-adapter.d.ts +11 -1
  22. package/dist/src/browser/codex-iab/bootstrap.d.ts +16 -0
  23. package/dist/src/browser/codex-iab/bootstrap.js +49 -0
  24. package/dist/src/browser/codex-iab/bootstrap.js.map +1 -1
  25. package/dist/src/browser/codex-iab/chatgpt-client.js +346 -120
  26. package/dist/src/browser/codex-iab/chatgpt-client.js.map +1 -1
  27. package/dist/src/browser/codex-iab/recovery-evidence.d.ts +6 -0
  28. package/dist/src/browser/codex-iab/recovery-evidence.js +37 -0
  29. package/dist/src/browser/codex-iab/recovery-evidence.js.map +1 -0
  30. package/dist/src/browser/codex-iab/submission-url.d.ts +2 -0
  31. package/dist/src/browser/codex-iab/submission-url.js +53 -0
  32. package/dist/src/browser/codex-iab/submission-url.js.map +1 -0
  33. package/dist/src/cli/main.js +305 -20
  34. package/dist/src/cli/main.js.map +1 -1
  35. package/dist/src/core/controller-abort.d.ts +1 -0
  36. package/dist/src/core/controller-abort.js +11 -0
  37. package/dist/src/core/controller-abort.js.map +1 -0
  38. package/dist/src/core/controller-command-execution.d.ts +9 -0
  39. package/dist/src/core/controller-command-execution.js +299 -0
  40. package/dist/src/core/controller-command-execution.js.map +1 -0
  41. package/dist/src/core/controller-loop.d.ts +3 -37
  42. package/dist/src/core/controller-loop.js +386 -291
  43. package/dist/src/core/controller-loop.js.map +1 -1
  44. package/dist/src/core/controller-turn.d.ts +16 -0
  45. package/dist/src/core/controller-turn.js +309 -0
  46. package/dist/src/core/controller-turn.js.map +1 -0
  47. package/dist/src/core/controller-types.d.ts +58 -0
  48. package/dist/src/core/controller-types.js +2 -0
  49. package/dist/src/core/controller-types.js.map +1 -0
  50. package/dist/src/core/persisted-run.d.ts +4 -0
  51. package/dist/src/core/persisted-run.js +19 -0
  52. package/dist/src/core/persisted-run.js.map +1 -0
  53. package/dist/src/core/process-liveness.d.ts +2 -0
  54. package/dist/src/core/process-liveness.js +44 -0
  55. package/dist/src/core/process-liveness.js.map +1 -0
  56. package/dist/src/core/run-status.d.ts +53 -0
  57. package/dist/src/core/run-status.js +224 -0
  58. package/dist/src/core/run-status.js.map +1 -0
  59. package/dist/src/core/state-machine.d.ts +17 -4
  60. package/dist/src/core/state-machine.js +170 -16
  61. package/dist/src/core/state-machine.js.map +1 -1
  62. package/dist/src/jobs/status.d.ts +7 -1
  63. package/dist/src/jobs/status.js.map +1 -1
  64. package/dist/src/jobs/supervisor.d.ts +2 -0
  65. package/dist/src/jobs/supervisor.js +47 -13
  66. package/dist/src/jobs/supervisor.js.map +1 -1
  67. package/dist/src/protocol/types.d.ts +1 -1
  68. package/dist/src/protocol/validate-command.js +18 -0
  69. package/dist/src/protocol/validate-command.js.map +1 -1
  70. package/dist/src/router/resolver.d.ts +2 -1
  71. package/dist/src/router/resolver.js +31 -13
  72. package/dist/src/router/resolver.js.map +1 -1
  73. package/dist/src/runners/process-runner.d.ts +2 -2
  74. package/dist/src/runners/process-runner.js +113 -9
  75. package/dist/src/runners/process-runner.js.map +1 -1
  76. package/dist/src/runners/runner-adapter.d.ts +9 -2
  77. package/dist/src/runners/runner-adapter.js.map +1 -1
  78. package/dist/src/state/atomic-write.js +17 -2
  79. package/dist/src/state/atomic-write.js.map +1 -1
  80. package/dist/src/state/cancellation.d.ts +42 -0
  81. package/dist/src/state/cancellation.js +168 -0
  82. package/dist/src/state/cancellation.js.map +1 -0
  83. package/dist/src/state/event-log.d.ts +17 -1
  84. package/dist/src/state/event-log.js +328 -18
  85. package/dist/src/state/event-log.js.map +1 -1
  86. package/dist/src/state/paths.d.ts +4 -0
  87. package/dist/src/state/paths.js +4 -0
  88. package/dist/src/state/paths.js.map +1 -1
  89. package/dist/src/state/runtime-lease.d.ts +53 -0
  90. package/dist/src/state/runtime-lease.js +727 -0
  91. package/dist/src/state/runtime-lease.js.map +1 -0
  92. package/dist/src/state/runtime-retirement.d.ts +16 -0
  93. package/dist/src/state/runtime-retirement.js +95 -0
  94. package/dist/src/state/runtime-retirement.js.map +1 -0
  95. package/dist/src/state/runtime-takeover-intent.d.ts +1 -0
  96. package/dist/src/state/runtime-takeover-intent.js +18 -0
  97. package/dist/src/state/runtime-takeover-intent.js.map +1 -0
  98. package/dist/src/state/store.d.ts +12 -1
  99. package/dist/src/state/store.js +246 -40
  100. package/dist/src/state/store.js.map +1 -1
  101. package/dist/src/version.d.ts +1 -1
  102. package/dist/src/version.js +1 -1
  103. package/docs/architecture.md +16 -11
  104. package/docs/assets/cueline-loop-en.svg +11 -10
  105. package/docs/assets/cueline-loop-ja.svg +11 -10
  106. package/docs/assets/cueline-loop-ko.svg +11 -10
  107. package/docs/assets/cueline-loop-zh-CN.svg +11 -10
  108. package/docs/assets/cueline-loop-zh-TW.svg +11 -10
  109. package/docs/compatibility.md +16 -8
  110. package/docs/controller-protocol.md +8 -4
  111. package/docs/runner-contract.md +26 -6
  112. package/docs/state-and-recovery.md +69 -16
  113. package/package.json +4 -3
  114. package/schemas/controller-observation.schema.json +1 -1
  115. package/scripts/validate-plugin.mjs +66 -0
  116. package/skills/cueline/SKILL.md +89 -13
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cueline",
3
- "version": "0.1.2",
4
- "description": "Use a ChatGPT web conversation as the controller for durable local agent work.",
3
+ "version": "0.1.4",
4
+ "description": "Use a ChatGPT web conversation as the text controller for durable local advice 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.2",
4
- "description": "Use a ChatGPT web conversation as the controller for durable local agent work.",
3
+ "version": "0.1.4",
4
+ "description": "Use a ChatGPT web conversation as the text controller for durable local advice executed by the current Codex.",
5
5
  "author": {
6
6
  "name": "CueLine contributors"
7
7
  },
@@ -9,7 +9,7 @@
9
9
  "interface": {
10
10
  "displayName": "CueLine",
11
11
  "shortDescription": "Let ChatGPT Pro direct durable local agent runs.",
12
- "longDescription": "CueLine lets a ChatGPT web conversation plan, dispatch, inspect, and complete local agent work while Codex validates commands, executes registered workers, and persists the run.",
12
+ "longDescription": "CueLine lets a ChatGPT web conversation issue validated text commands while the current Codex executes caller-mode advice or an explicitly selected process executor runs registered workers, with durable recovery evidence.",
13
13
  "developerName": "CueLine contributors",
14
14
  "category": "Productivity",
15
15
  "capabilities": [],
package/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.4 - 2026-07-15
4
+
5
+ ### Fixed
6
+
7
+ - Make `caller` the default executor for both `startCueLineRun` and `runCueLine`. A validated `dispatch` now returns durable pending jobs to the current Codex instead of silently spawning `codex exec`; the caller submits each terminal result before continuing the same run. Caller execution accepts `advise` only and rejects `work` until an execution claim can prevent duplicate side effects. The process executor remains available only when selected explicitly.
8
+ - Split built-in-IAB caller turns into durable submit and one-shot observe calls. After exactly one send, CueLine waits briefly for the exact `/c/...` URL, persists `submitted`, returns `awaiting_controller`, and releases the lease instead of tying Pro thinking to one outer 300-second waiter. Each continuation reads the same request/URL once and returns immediately if unfinished; it never resends. A delayed URL is captured safely, while a missing URL becomes `possibly_sent` rather than an unrecoverable fake pause. Post-creation failures expose `details.run_id` for reconciliation.
9
+ - Detach durable controller and caller pauses from a single tool wait: ownerless `controller_response_pending` and `caller_jobs_pending` phases are healthy, jobs stay visible with run ID/job key/lane/mode/task, concurrent continuation/result submission is lease-serialized, and `cueline run takeover` can retire one exact stale heartbeat without stealing an active owner. `controller.responseAccepted` is false while a newer turn is pending even when historical accepted-action evidence exists. Caller advice itself has no execution claim, so the first terminal evidence wins and `work` remains forbidden.
10
+ - Bound explicit process execution to two concurrent jobs globally and per lane by default, including advice still running from an earlier controller round, while preserving serial execution for any batch containing `work`. Process cancellation, timeout, and normal leader exit now settle the owned process group, including surviving descendants.
11
+ - Recognize ChatGPT's automatic long-prompt attachment conversion as `attachment_ready`. Submission waits for a stable inline prompt or a newly created attachment and performs at most one send attempt; an ambiguous locator/coordinate click becomes `possibly_sent` and is never retried.
12
+ - Add append-only manual submission recovery with `cueline run reconcile <run-id> --request-id <request-id> --manual-send-confirmed`. Recovery requires the exact conversation, exact Pro model evidence, and exact protocol/run/round/request envelope; it can restore a specified abandoned turn without resending or duplicate dispatch. Legacy manually sent attachment turns may lack a pre-submit assistant-count baseline; that path ignores an older assistant response until the exact pending envelope appears, while automatic attachment recovery still requires the baseline.
13
+ - Prefer successful non-empty worker stdout in controller observations, retain full stdout/stderr in job status, and enforce one global 12,000-character controller-evidence budget with an explicit truncation notice.
14
+ - Reject both `complete` and `blocked` while any required or optional job remains pending/running, preventing a terminal command from orphaning background work. Any non-normal process-loop exit (including round exhaustion or invalid controller output) now cancels and settles all owned active jobs before releasing its lease. When a retired runtime writes a conflicting job status file late, `cueline jobs` keeps the authoritative run-event status, marks `observedStatus: conflict`, exposes the file value as `persistedStatus`, and omits the untrusted late result.
15
+ - Make runtime creation, lease takeover, cancellation observation, caller result submission, and run creation race-safe. A crash-stale mutation lock rotates a persistent fence before reuse, and each lease generation writes a separate epoch record, so a paused old writer cannot overwrite or release the new owner. Event appends use complete fsynced, create-if-absent sequence segments instead of a persistent global event lock; a durable legacy-prefix fence prevents a still-loaded 0.1.3 writer from colliding with segmented sequence numbers. Runtime-authored events carry an owner ID. Exact takeover first preserves the operator's expected owner/heartbeat as immutable intent, then atomically replaces that exact stale lease while embedding its authoritative event cutoff; failed replacement leaves the old owner valid, while committed late events stay auditable but cannot mutate replayed state. The cutoff is mirrored to immutable retirement evidence before the replacement lease is removed. Ownerless process runs reconcile only after verifying that neither the recorded process nor its process group survives; otherwise they remain inspectable instead of being falsely settled.
16
+ - Bind recovery response text and its conversation URL in the same DOM evaluation, closing a navigation race where a later `tab.url()` read could otherwise validate evidence captured from another conversation.
17
+ - Report `safeNextAction: observe` only for one normally submitted controller turn that is waiting for Pro, while reserving `reconcile` for ambiguous, manually submitted, or multiple pending turns. CLI help now prints every positional argument and option, distinguishes read-only commands from append-only or state-changing recovery/cancellation commands, and returns the documented usage exit code 2 for invalid reconcile arguments.
18
+ - Enforce `maxRounds` as one durable total-run limit across caller pauses. A split caller run no longer resets its round budget on every `continueCueLineRun`; omitted continuation options reuse the persisted limit, and attempts to widen or shrink it are rejected before another controller turn is sent.
19
+
20
+ ### Documentation
21
+
22
+ - Document the caller-first lifecycle, `awaiting_controller` submit/observe boundary, the web controller's text-only/no-local-tools boundary, explicit process execution and concurrency, attachment/manual reconciliation, ownerless controller/caller pauses, bounded evidence, exact CLI state effects, and the timeout semantics: `runTimeoutMs` limits each owned advancement in caller mode rather than ownerless Pro thinking between calls.
23
+
24
+ ## 0.1.3 - 2026-07-15
25
+
26
+ ### Fixed
27
+
28
+ - 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.
29
+ - 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.
30
+ - Run independent all-`advise` dispatches concurrently. Any dispatch containing `work` remains serial to avoid overlapping mutations.
31
+ - 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`.
32
+ - 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.
33
+ - Reject unsupported `runner_id` explicitly, require `runner`, and explain when a runner ID such as `codex-default` was placed in `lane`.
34
+ - 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.
35
+
36
+ ### Documentation
37
+
38
+ - Require `run status` before continuation and distinguish controller response acceptance, local job execution, runtime ownership, and outer waiter timeout.
39
+ - Document cancellation, run-level deadlines, `advise` concurrency, `work` serialization, and stale-job recovery semantics.
40
+
3
41
  ## 0.1.2 - 2026-07-15
4
42
 
5
43
  ### Fixed
package/README.ja.md CHANGED
@@ -11,17 +11,21 @@
11
11
  <a href="README.md">English</a> · <a href="README.zh-TW.md">繁體中文</a> · <a href="README.zh-CN.md">简体中文</a> · <b>日本語</b> · <a href="README.ko.md">한국어</a>
12
12
  </p>
13
13
 
14
- **CueLine は、開いている ChatGPT のウェブ会話にハンドルを渡します。会話側が実行全体を計画し、次の一手を出す。CueLine はそのコマンドを一つずつ検証し、実際の作業をここ、あなたのマシンで行います。**
14
+ **CueLine は、開いている ChatGPT のウェブ会話に判断を任せます。会話側はテキストコマンドを出し、CueLine が検証し、現在の Codex が許可されたローカル作業を実行します。**
15
15
 
16
- ウェブページがあなたのマシンに触れることはありません。ページが出せるのは、1 ラウンドにつき小さなテキストコマンドが一つだけです。CueLine はそのコマンドが正しい形式か、この実行(run)に属するものか、どのローカルワーカーに対応するかを判断し、そのうえで実行し、証拠を保存し、証拠を返します。
16
+ ウェブページにローカルツールはありません。既定の `caller` 実行では、CueLine が `advise` ジョブを永続化し、現在の Codex が実行して結果を提出します。登録済みワーカーを起動するには `process` executor を明示します。
17
17
 
18
18
  CueLine は独立した実装で、**ランタイムの npm 依存はゼロ**です。Omnilane や GPT Relay のラッパーではありません。
19
19
 
20
20
  ## 1 回の実行は実際にどう進むか
21
21
 
22
- <img alt="CueLine 1 回の実行をプロンプトブックとして読む:マシンが観測を送り、コントローラーがコマンドを 1 つ出し、登録済みの runner が実行し、complete が出るまで続く。" src="docs/assets/cueline-loop-ja.svg" width="100%">
22
+ <img alt="Caller-first CueLine:ChatGPT がテキストコマンドを出し、現在の Codex がローカル助言を実行し、CueLine が完了まで有界な証拠を返す。" src="docs/assets/cueline-loop-ja.svg" width="100%">
23
23
 
24
- 各ラウンドで CueLine は、これから何を尋ねるのかをまず記録し、観測(observation)を 1 件だけ会話に送り、`<CueLineControl>` エンベロープを**ちょうど 1 つだけ**読み戻します。コントローラーは 5 つのアクション——`dispatch`、`wait`、`inspect`、`complete`、`blocked`——から 1 つを選び、エンベロープの外にあるテキストが実行されることは一切ありません。誤った run、誤ったラウンド、あるいは不正なジョブ定義を指すコマンドは、推測で補われることなく、回数制限つきの修復のために差し戻されます。ループは `complete` または `blocked` で停止し、ラウンド上限(既定 12 回)に達した場合も停止します。
24
+ 各ラウンドで CueLine は観測を送り、後で `<CueLineControl>` エンベロープを**ちょうど 1 つだけ**読み戻します。コントローラーは `dispatch`、`wait`、`inspect`、`complete`、`blocked` のいずれかを選びます。ループは 1 回の永続的な送信後に `awaiting_controller` で一時停止し、caller への引き渡し、`complete`、`blocked`、またはラウンド上限(既定 12 回)でも停止します。
25
+
26
+ 既定値以外の `maxRounds` は run 作成時に固定され、owner 不在の一時停止をまたいでコントローラーの総ラウンド数を数えます。後の続行では通常省略して永続値を再利用し、異なる値を渡すと予算を暗黙にリセットまたは拡張せず拒否します。
27
+
28
+ `startCueLineRun` と `runCueLine` の既定は `caller` です。組み込みブラウザーでは、CueLine は 1 回だけ送信して正確な会話 URL を保存し、Pro の思考中に 1 回のツール呼び出しを保持せず、runtime lease を解放して `awaiting_controller` を返します。後の `continueCueLineRun` は読み取り専用の観測を 1 回だけ行い、未完了なら再送せず再び `awaiting_controller` を返します。`dispatch` の後に `awaiting_caller` を返し、現在の Codex が各 `advise` を実行して `submitCueLineCallerJobResult` で提出し、同じ run を続行します。Pro コントローラー自身がローカルツールを使ったわけではありません。Caller advice には execution claim がないため、1 つの session が実行するよう調整してください。2 つの session が同じ確認を行う可能性はありますが、最初に提出された終端証拠だけが採用されます。Caller の `work` は拒否されます。
25
29
 
26
30
  コントローラーは*何が起こるべきか*を選びます。ローカル側は*それを許すか、どう許すか*を選びます。レーンが有効であること、候補がプロセス起動の**前に**利用可能だと確認されていること、`argv[0]` があなたのルーティング設定によってすでに登録されていること。シェルを経由するものは何もありません。ワーカーがいったん起動したら、黙って 2 番目の候補にフォールバックすることはありません。失敗は再試行ではなく、証拠として返ります。
27
31
 
@@ -44,15 +48,15 @@ ChatGPT Pro のサブスクリプションと、選択された Pro モデルは
44
48
  npm レジストリからインストールします。
45
49
 
46
50
  ```bash
47
- npm install -g cueline@0.1.2
51
+ npm install -g cueline@0.1.4
48
52
  cueline install
49
53
  cueline doctor
50
54
  ```
51
55
 
52
- フォールバックとして、[v0.1.2 リリース](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.2) のパッケージ済み tarball をインストールすることもできます。同じリリースに `.sha256` チェックサムも置いてあります。
56
+ フォールバックとして、[v0.1.4 リリース](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.4) のパッケージ済み tarball をインストールすることもできます。同じリリースに `.sha256` チェックサムも置いてあります。
53
57
 
54
58
  ```bash
55
- npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.2/cueline-0.1.2.tgz
59
+ npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.4/cueline-0.1.4.tgz
56
60
  cueline install
57
61
  cueline doctor
58
62
  ```
@@ -84,38 +88,63 @@ cueline doctor
84
88
  ## コードから駆動する
85
89
 
86
90
  ```js
87
- import { createCodexIabAdapter, runCueLine } from "cueline";
88
-
89
- const result = await runCueLine({
91
+ import {
92
+ continueCueLineRun,
93
+ createCodexIabAdapter,
94
+ runCueLine,
95
+ submitCueLineCallerJobResult,
96
+ } from "cueline";
97
+
98
+ let result = await runCueLine({
90
99
  request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
91
100
  browser: createCodexIabAdapter(),
92
- // 任意:conversationUrl、routingConfig / routingConfigPath、home、cwd、limits。
93
- });
101
+ // 任意:conversationUrl、routingConfig / routingConfigPath、home、cwd、
102
+ // runTimeoutMs、signal、ジョブごと/既定の期限。
103
+ }); // 既定は executor: "caller"
104
+
105
+ while (result.status === "awaiting_controller" || result.status === "awaiting_caller") {
106
+ if (result.status === "awaiting_controller") {
107
+ await waitBeforeNextObservation(); // 有界バックオフ。再送しない
108
+ } else {
109
+ for (const job of result.pendingJobs ?? []) {
110
+ const stdout = await executeExactLocalAdvice(job.spec.task);
111
+ await submitCueLineCallerJobResult(result.runId, job.jobId, {
112
+ status: "succeeded",
113
+ stdout,
114
+ });
115
+ }
116
+ }
117
+ result = await continueCueLineRun({ runId: result.runId });
118
+ }
94
119
 
95
120
  if (result.status === "complete") {
96
121
  console.log(result.finalDeliveryText);
97
122
  }
98
123
  ```
99
124
 
125
+ `awaiting_controller` が返った場合、同じ正確な request は送信済みですが、Pro の応答はまだ観測されていません。後の続行は読み取り専用で観測し、再送しません。`awaiting_caller` が返ったら、現在の Codex が `result.pendingJobs` の各 `advise` を実行し、実際の結果を `submitCueLineCallerJobResult` で提出してから `continueCueLineRun` を呼びます。Pro のウェブページがローカルツールを直接使うわけではありません。
126
+
100
127
  Codex のランタイムでは、`cueline api path` が出力する絶対パスのモジュールを import します。それがインストールしたパッケージのビルド済み API です。
101
128
 
102
- `startCueLineRun` が明示的な開始点です(`runCueLine` はその別名)。`continueCueLineRun({ runId })` は中断した実行を同じ会話で再開し、新しいアダプターを渡さないかぎり保存済みの会話 URL を再利用します。`loadCueLineRunState(runId)` は永続化された状態を読むだけで、何も駆動しません。すでに `complete` または `blocked` に達した実行はそのまま返され、二度とディスパッチされません。
129
+ `startCueLineRun` は永続 run を作成して `ready` を返すだけです。`runCueLine` は作成後、永続 controller 観測待ち、caller 引き渡し、または終端まで進めます。owner 不在の `controller_response_pending` で通常送信済みターンが一つだけあり、`safeNextAction: observe` が示される場合、同じ Pro 応答を読み取り専用で観測する待機です。少し待って続行し、再送しません。`safeNextAction: reconcile` は曖昧、手動送信、または複数の保留ターンに使います。owner 不在の `caller_jobs_pending` は正常なローカル引き渡しであり、orphan や ChatGPT 待ちではありません。
103
130
 
104
131
  ## CLI
105
132
 
106
- CLI はブラウザーを駆動しません。スキルのリンクを管理し、ローカル側が健全かどうかを教えます。
133
+ CLI はブラウザーを駆動しません。`doctor`、`routing`、`jobs`、`run status`、`api path`、`config path` は読み取り専用です。`install`/`uninstall` はパッケージ所有のスキルリンクだけを変更します。`run reconcile`、`run takeover`、`run reconcile-runtime`、`run cancel`/`run stop`、`job cancel` は監査証拠を追記するか、永続 run/job 状態を変更します。状態を書き込むコマンドの前に `cueline help` で完全な引数を確認してください。
107
134
 
108
135
  ```console
109
136
  $ cueline install
110
137
  CueLine skill installed: /Users/you/.codex/skills/cueline
111
138
 
112
139
  $ cueline doctor
113
- CueLine 0.1.2
140
+ CueLine 0.1.4
114
141
  status ok
115
142
  node 22.14.0 ok
116
143
  config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
117
144
  home /Users/you/.cueline
118
- available_lanes 1
145
+ caller_ready yes
146
+ caller_lanes 1
147
+ process_available_lanes 1
119
148
 
120
149
  $ cueline api path
121
150
  /usr/local/lib/node_modules/cueline/dist/src/api.js
@@ -126,6 +155,15 @@ default codex-default available
126
155
  $ cueline jobs
127
156
  No jobs.
128
157
 
158
+ $ cueline run status run_... --json
159
+ {"status":"running","executor":"caller","phase":"caller_jobs_pending","runtime":{"ownership":"missing"},...}
160
+
161
+ $ cueline run takeover stale_run_... --json
162
+ {"runId":"stale_run_...","outcome":"taken_over","next":"continue",...}
163
+
164
+ $ cueline run cancel run_...
165
+ run_... requested affected_jobs=0
166
+
129
167
  $ cueline config path
130
168
  /usr/local/lib/node_modules/cueline/config/routing.default.json
131
169
 
@@ -133,25 +171,31 @@ $ cueline uninstall
133
171
  CueLine skill removed: /Users/you/.codex/skills/cueline
134
172
  ```
135
173
 
136
- Node が古すぎる場合、あるいは解決できるレーンが一つもない場合、`cueline doctor` は非ゼロで終了します。そのため事前チェックとしてそのまま使えます。`cueline routing` は、黙って別のものを選ぶのではなく、そのレーンがなぜ使えないのかを示します。`cueline api path` が出すのはスキルが import するモジュールなので、パッケージ導入ならリポジトリの取得は不要です。`cueline help` ですべて一覧できます。
174
+ Node が古すぎる場合、または有効な caller レーンが一つもない場合、`cueline doctor` は非ゼロで終了します。`process_available_lanes` が 0 でも caller モードは劣化しません。process executor を明示的に選ぶ前だけ `cueline routing` で process の可用性を確認してください。`cueline api path` が出すのはスキルが import するモジュールなので、パッケージ導入ならリポジトリの取得は不要です。`cueline help` は `--json` と手動 reconcile の必須確認フラグを含む各コマンドの正確な構文を一覧します。
175
+
176
+ `run takeover` は `run status` が exact stale owner を示す場合だけ使います。新しい active heartbeat は拒否されます。返された `next: continue` または `next: reconcile_runtime` に従い、推測で進めないでください。
137
177
 
138
178
  ## 設定
139
179
 
140
180
  `CUELINE_CONFIG` はルーティング設定ファイルを選び、`CUELINE_HOME` はローカル状態の置き場所を移します(既定は `~/.cueline`)。
141
181
 
142
- 同梱の `default` レーンには候補が 1 つ、`codex-default` があります。タスクを stdin で渡して `codex exec` を実行し、`advise` `read-only`、`work` は `workspace-write` を使います。別のワーカーを登録するには、[`config/routing.default.json`](config/routing.default.json) をコピーして候補を追加し、`CUELINE_CONFIG` をそこに向けます。`argv[0]` の実行ファイルはその行為によって登録され、レーンが解決するにはそれが `PATH` 上にある必要もあります。
182
+ Caller はプロセスを起動しません。`process` executor を明示した場合だけ、`default` レーンの `codex-default` `codex exec` を実行します。独立した `advise` の既定同時実行数は全体/レーンごとに 2、`work` を含むバッチは直列です。
143
183
 
144
184
  状態は `CUELINE_HOME` の下に置かれます:
145
185
 
146
186
  ```text
147
- runs/<run-id>/events.jsonl 追記のみ、正本
187
+ runs/<run-id>/events.jsonl + events.jsonl.segments/ 追記のみ、正本
188
+ runs/<run-id>/runtime.json.fence + runtime.json.epochs/ 世代分離されたライブ owner heartbeat 証拠
189
+ runs/<run-id>/runtime.json.retired-owners/ 不変の旧 owner イベント cutoff
190
+ runs/<run-id>/runtime.json.takeover-intents/ 不変の exact takeover 試行記録
191
+ runs/<run-id>/cancel.json 存在する場合は永続キャンセル要求
148
192
  runs/<run-id>/snapshot.json リプレイの最適化、破棄可能
149
193
  jobs/<job-id>.json ジョブごとの実行証拠
150
194
  ```
151
195
 
152
196
  記録そのものはイベントログです。コントローラーのターンは送信する前に書かれ、ジョブはプロセスが起動する前に登録されます。だからこそ、意図と副作用のあいだで中断が起きても痕跡が残ります。壊れたスナップショットは信用されず、無視されてイベント 1 番から再構築されます。
153
197
 
154
- 復帰は、その実行が記録したまさにその会話 URL にだけ再接続します。よく似たタブにつなぐことはありません。保留中のコントローラーターンについては、まず正確なリクエストに対応する完了済みの応答をその会話内で探し、見つかれば再送せず読み取り専用で照合します。古い状態に複数の保留ターンがある場合、呼び出し側が一つを明示的に選ぶ必要があります。唯一の保留中プロンプトが `definitely_not_sent` だと証明できた場合に限り、CueLine は自動で再試行します。送信状態が不明、またはタブが消えた場合は `TAB_RECOVERY_UNSAFE` を投げて停止します。
198
+ 復帰は完全に同じ会話 URL にだけ接続します。ChatGPT が長文を添付に自動変換した場合は `attachment_ready` として認識し、送信クリックは最大 1 回です。曖昧なクリックは `possibly_sent` となり再送しません。手動送信後は `cueline run reconcile RUN_ID --request-id REQUEST_ID --manual-send-confirmed` で正式に確認し、同一 conversation、Pro 証拠、protocol/run/round/request identity をすべて検証します。コントローラー証拠は成功時の非空 stdout を優先し、全体 12,000 文字に制限します。完全な stdout/stderr はローカルに保持します。
155
199
 
156
200
  ## 検証
157
201
 
@@ -168,7 +212,7 @@ npm pack --dry-run
168
212
 
169
213
  ## 0.1 の制限
170
214
 
171
- テキストのみ。1 回の実行につき会話は 1 つ。CueLine が行うモデル切り替えは `Pro` の選択だけです。画像、ファイルアップロード、Deep Research、Projects、Apps には対応しません。ワーカーが起動したあとの自動リトライやフォールバックはありません。失敗した `work` ジョブは、どこまで進んだか CueLine には証明できないため、副作用が不確定であるという印つきで報告されます。主なデスクトップ対象は macOS、CI 対象は Linux です。Windows は未検証で、`install.sh` Windows 用インストーラーではありません。アダプターは現行の ChatGPT ウェブ UI に依存するため、UI が変わった場合は `COMPOSER_MISSING`、`SEND_BUTTON_MISSING`、あるいは応答タイムアウトとして明示的に表面化します——でっち上げの回答になることは決してありません。
215
+ テキストコマンドのみ。長文の自動添付変換は対応しますが、意図的なファイルアップロード、画像、Deep Research、Projects、Apps は非対応です。Caller `advise` のみで、`work` には明示的な process executor が必要です。曖昧な送信や開始済みジョブを自動再試行しません。
172
216
 
173
217
  完全な対応表は [compatibility](docs/compatibility.md) を参照してください。
174
218
 
package/README.ko.md CHANGED
@@ -11,17 +11,21 @@
11
11
  <a href="README.md">English</a> · <a href="README.zh-TW.md">繁體中文</a> · <a href="README.zh-CN.md">简体中文</a> · <a href="README.ja.md">日本語</a> · <b>한국어</b>
12
12
  </p>
13
13
 
14
- **CueLine은 이미 열려 있는 ChatGPT 웹 대화에 운전대를 넘깁니다. 대화가 실행 전체를 계획하고 다음 단계를 지시하면, CueLine 모든 명령을 검증하고 실제 작업은 바로 이곳, 당신의 머신에서 수행합니다.**
14
+ **CueLine은 열린 ChatGPT 웹 대화에 판단을 맡깁니다. 대화는 텍스트 명령을 내리고, CueLine 검증하며, 현재 Codex가 허용된 로컬 작업을 수행합니다.**
15
15
 
16
- 페이지는 당신의 머신을 건드리지 않습니다. 페이지가 내보내는 것은 라운드당 작은 텍스트 명령 하나뿐입니다. CueLine 명령의 형식이 올바른지, 이번 실행(run)에 속하는지, 어떤 로컬 워커에 대응하는지를 판단한 뒤에야 실행하고, 증거를 보관하고, 그 증거를 돌려줍니다.
16
+ 페이지에는 로컬 도구가 없습니다. 기본 `caller` 실행에서는 CueLine `advise` 작업을 지속 상태로 넘기고 현재 Codex가 실행해 결과를 제출합니다. 등록된 워커를 띄우려면 `process` executor를 명시해야 합니다.
17
17
 
18
18
  CueLine은 독립적인 구현이며 **런타임 npm 의존성이 전혀 없습니다**. Omnilane이나 GPT Relay를 감싼 래퍼가 아닙니다.
19
19
 
20
20
  ## 실행 한 번은 실제로 이렇게 흘러갑니다
21
21
 
22
- <img alt="CueLine 실행 번을 프롬프트북처럼 읽기: 머신이 관측을 보내고, 컨트롤러가 명령 하나를 내리고, 등록된 runner가 실행하며, complete가 나올 때까지 이어집니다." src="docs/assets/cueline-loop-ko.svg" width="100%">
22
+ <img alt="Caller-first CueLine: ChatGPT가 텍스트 명령을 내리고 현재 Codex가 로컬 조언 작업을 수행하며 CueLine이 완료까지 제한된 증거를 반환합니다." src="docs/assets/cueline-loop-ko.svg" width="100%">
23
23
 
24
- 매 라운드마다 CueLine은 무엇을 물으려 하는지 먼저 기록하고, 관측(observation) 하나를 대화에 보낸 뒤, `<CueLineControl>` 엔벨로프를 **정확히 하나만** 읽어 옵니다. 컨트롤러는 다섯 가지 동작 — `dispatch`, `wait`, `inspect`, `complete`, `blocked` 중 하나를 고르며, 엔벨로프 바깥의 텍스트는 절대 실행되지 않습니다. 잘못된 run이나 잘못된 라운드를 가리키거나 작업 정의가 잘못된 명령은 추측으로 메워지지 않고, 횟수가 제한된 복구 시도를 위해 되돌려 보내집니다. 루프는 `complete` 또는 `blocked`에서 멈추며, 라운드 한도(기본 12회) 소진해도 멈춥니다.
24
+ 매 라운드마다 CueLine은 관측 하나를 보내고 나중에 `<CueLineControl>` 엔벨로프를 **정확히 하나만** 읽습니다. 컨트롤러는 `dispatch`, `wait`, `inspect`, `complete`, `blocked` 중 하나를 고릅니다. 루프는 번의 영속적인 전송 `awaiting_controller`에서 일시 중지하며 caller 인계, `complete`, `blocked`, 또는 라운드 상한(기본 12회)에서도 멈춥니다.
25
+
26
+ 기본값이 아닌 `maxRounds`는 run 생성 시 고정되며 owner가 없는 일시 중지를 가로질러 컨트롤러 총 라운드 수를 셉니다. 이후 계속하기에서는 보통 생략해 지속 값을 재사용하고, 다른 값을 전달하면 예산을 몰래 재설정하거나 늘리지 않고 거부합니다.
27
+
28
+ `startCueLineRun`과 `runCueLine`의 기본값은 `caller`입니다. 내장 브라우저에서는 CueLine이 한 번만 전송하고 정확한 대화 URL을 저장한 뒤, Pro가 생각하는 동안 한 도구 호출을 붙잡지 않고 runtime lease를 해제하여 `awaiting_controller`를 반환합니다. 이후 `continueCueLineRun`은 읽기 전용 관측을 한 번만 수행하며, 미완료이면 재전송 없이 다시 `awaiting_controller`를 반환합니다. `dispatch` 뒤에는 `awaiting_caller`를 반환하고, 현재 Codex가 각 `advise`를 실행해 `submitCueLineCallerJobResult`로 제출한 뒤 같은 run을 계속합니다. Pro 컨트롤러 자체가 로컬 도구를 사용한 것은 아닙니다. Caller advice에는 execution claim이 없으므로 한 session만 실행하도록 조정해야 합니다. 두 session이 같은 점검을 수행할 수 있지만, 먼저 제출된 종료 증거만 채택됩니다. Caller의 `work`는 거부됩니다.
25
29
 
26
30
  컨트롤러는 *무엇이 일어나야 하는지*를 고릅니다. 로컬 쪽은 *그것이 허용되는지, 어떻게 허용되는지*를 고릅니다. 레인이 활성화되어 있어야 하고, 후보는 어떤 프로세스가 뜨기 **전에** 사용 가능함이 확인되어야 하며, `argv[0]`은 당신의 라우팅 설정에 이미 등록되어 있어야 합니다. 셸을 거치는 것은 아무것도 없습니다. 워커가 일단 시작되면 두 번째 후보로 조용히 넘어가는 폴백은 없습니다. 실패는 재시도가 아니라 증거로 돌아옵니다.
27
31
 
@@ -44,15 +48,15 @@ ChatGPT Pro 구독과 선택된 Pro 모델은 서로 다른 것입니다. 계정
44
48
  npm 레지스트리에서 설치합니다:
45
49
 
46
50
  ```bash
47
- npm install -g cueline@0.1.2
51
+ npm install -g cueline@0.1.4
48
52
  cueline install
49
53
  cueline doctor
50
54
  ```
51
55
 
52
- 대안으로, [v0.1.2 릴리스](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.2)의 패키지 tarball을 설치할 수도 있습니다. 같은 릴리스에 `.sha256` 체크섬도 함께 있습니다.
56
+ 대안으로, [v0.1.4 릴리스](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.4)의 패키지 tarball을 설치할 수도 있습니다. 같은 릴리스에 `.sha256` 체크섬도 함께 있습니다.
53
57
 
54
58
  ```bash
55
- npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.2/cueline-0.1.2.tgz
59
+ npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.4/cueline-0.1.4.tgz
56
60
  cueline install
57
61
  cueline doctor
58
62
  ```
@@ -84,38 +88,63 @@ cueline doctor
84
88
  ## 코드에서 구동하기
85
89
 
86
90
  ```js
87
- import { createCodexIabAdapter, runCueLine } from "cueline";
88
-
89
- const result = await runCueLine({
91
+ import {
92
+ continueCueLineRun,
93
+ createCodexIabAdapter,
94
+ runCueLine,
95
+ submitCueLineCallerJobResult,
96
+ } from "cueline";
97
+
98
+ let result = await runCueLine({
90
99
  request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
91
100
  browser: createCodexIabAdapter(),
92
- // 선택: conversationUrl, routingConfig / routingConfigPath, home, cwd, limits.
93
- });
101
+ // 선택: conversationUrl, routingConfig / routingConfigPath, home, cwd,
102
+ // runTimeoutMs, signal, 작업별/기본 제한 시간.
103
+ }); // 기본 executor: "caller"
104
+
105
+ while (result.status === "awaiting_controller" || result.status === "awaiting_caller") {
106
+ if (result.status === "awaiting_controller") {
107
+ await waitBeforeNextObservation(); // 제한된 백오프. 재전송 금지
108
+ } else {
109
+ for (const job of result.pendingJobs ?? []) {
110
+ const stdout = await executeExactLocalAdvice(job.spec.task);
111
+ await submitCueLineCallerJobResult(result.runId, job.jobId, {
112
+ status: "succeeded",
113
+ stdout,
114
+ });
115
+ }
116
+ }
117
+ result = await continueCueLineRun({ runId: result.runId });
118
+ }
94
119
 
95
120
  if (result.status === "complete") {
96
121
  console.log(result.finalDeliveryText);
97
122
  }
98
123
  ```
99
124
 
125
+ `awaiting_controller`가 반환되면 같은 정확한 request는 이미 전송되었지만 Pro 응답은 아직 관측되지 않은 것입니다. 이후 계속하기는 읽기 전용으로 관측하며 재전송하지 않습니다. `awaiting_caller`가 반환되면 현재 Codex가 `result.pendingJobs`의 각 `advise`를 실행하고 실제 결과를 `submitCueLineCallerJobResult`로 제출한 뒤 `continueCueLineRun`을 호출합니다. Pro 웹 페이지가 로컬 도구를 직접 쓰는 것은 아닙니다.
126
+
100
127
  Codex 런타임에서는 `cueline api path`가 출력하는 절대 경로 모듈을 import하세요. 그것이 설치한 패키지의 빌드된 API입니다.
101
128
 
102
- `startCueLineRun`이 명시적인 시작점입니다(`runCueLine`은 별칭). `continueCueLineRun({ runId })`은 중단된 실행을 같은 대화에서 재개하며, 어댑터를 넘기지 않는 저장된 대화 URL을 재사용합니다. `loadCueLineRunState(runId)`는 저장된 상태를 읽기만 하고 아무것도 구동하지 않습니다. 이미 `complete`나 `blocked`에 도달한 실행은 그대로 반환되며, 디스패치되지 않습니다.
129
+ `startCueLineRun`은 지속 run을 만들고 `ready`만 반환합니다. `runCueLine`은 생성 지속 controller 관측 대기, caller 인계 또는 종료 상태까지 진행합니다. owner가 없는 `controller_response_pending`에 정상 전송된 턴이 정확히 하나이고 `safeNextAction: observe`가 표시되면 같은 Pro 응답을 읽기 전용으로 관측하기 위한 대기입니다. 잠시 계속하고 재전송하지 마세요. `safeNextAction: reconcile`은 모호하거나 수동 전송되었거나 보류 턴이 여러 개인 경우에 사용합니다. owner가 없는 `caller_jobs_pending`은 정상적인 로컬 인계이며 orphan이나 ChatGPT 대기가 아닙니다.
103
130
 
104
131
  ## CLI
105
132
 
106
- CLI는 브라우저를 구동하지 않습니다. 스킬 링크를 관리하고, 로컬 쪽이 멀쩡한지 알려줍니다.
133
+ CLI는 브라우저를 구동하지 않습니다. `doctor`, `routing`, `jobs`, `run status`, `api path`, `config path`는 읽기 전용입니다. `install`/`uninstall`은 패키지가 소유한 스킬 링크만 변경합니다. `run reconcile`, `run takeover`, `run reconcile-runtime`, `run cancel`/`run stop`, `job cancel`은 감사 증거를 추가하거나 지속 run/job 상태를 변경합니다. 상태를 쓰는 명령 전에는 `cueline help`로 전체 인수를 확인하세요.
107
134
 
108
135
  ```console
109
136
  $ cueline install
110
137
  CueLine skill installed: /Users/you/.codex/skills/cueline
111
138
 
112
139
  $ cueline doctor
113
- CueLine 0.1.2
140
+ CueLine 0.1.4
114
141
  status ok
115
142
  node 22.14.0 ok
116
143
  config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
117
144
  home /Users/you/.cueline
118
- available_lanes 1
145
+ caller_ready yes
146
+ caller_lanes 1
147
+ process_available_lanes 1
119
148
 
120
149
  $ cueline api path
121
150
  /usr/local/lib/node_modules/cueline/dist/src/api.js
@@ -126,6 +155,15 @@ default codex-default available
126
155
  $ cueline jobs
127
156
  No jobs.
128
157
 
158
+ $ cueline run status run_... --json
159
+ {"status":"running","executor":"caller","phase":"caller_jobs_pending","runtime":{"ownership":"missing"},...}
160
+
161
+ $ cueline run takeover stale_run_... --json
162
+ {"runId":"stale_run_...","outcome":"taken_over","next":"continue",...}
163
+
164
+ $ cueline run cancel run_...
165
+ run_... requested affected_jobs=0
166
+
129
167
  $ cueline config path
130
168
  /usr/local/lib/node_modules/cueline/config/routing.default.json
131
169
 
@@ -133,25 +171,31 @@ $ cueline uninstall
133
171
  CueLine skill removed: /Users/you/.codex/skills/cueline
134
172
  ```
135
173
 
136
- Node 버전이 너무 낮거나 해석 가능한 레인이 하나도 없으면 `cueline doctor`는 0이 아닌 코드로 종료합니다. 그래서 사전 점검용으로 그대로 있습니다. `cueline routing`은 조용히 다른 것을 고르는 대신, 레인이 왜 사용 불가인지 보여줍니다. `cueline api path`가 출력하는 것이 곧 스킬이 import하는 모듈이므로, 패키지로 설치했다면 저장소를 받을 필요가 없습니다. `cueline help`가 전부를 나열합니다.
174
+ Node 버전이 너무 낮거나 활성화된 caller 레인이 하나도 없으면 `cueline doctor`는 0이 아닌 코드로 종료합니다. `process_available_lanes`가 0이어도 caller 모드는 저하되지 않습니다. process executor를 명시적으로 선택하기 전에만 `cueline routing`으로 process 가용성을 확인하세요. `cueline api path`가 출력하는 것이 곧 스킬이 import하는 모듈이므로, 패키지로 설치했다면 저장소를 받을 필요가 없습니다. `cueline help`는 `--json`과 수동 reconcile 필수 확인 플래그를 포함한 각 명령의 정확한 구문을 나열합니다.
175
+
176
+ `run takeover`는 `run status`가 exact stale owner를 표시할 때만 사용합니다. 새로운 active heartbeat는 거부됩니다. 반환된 `next: continue` 또는 `next: reconcile_runtime`을 따르고 추측해서 진행하지 마세요.
137
177
 
138
178
  ## 설정
139
179
 
140
180
  `CUELINE_CONFIG`는 라우팅 설정 파일을 고르고, `CUELINE_HOME`은 로컬 상태의 위치를 옮깁니다(기본값 `~/.cueline`).
141
181
 
142
- 기본 제공 `default` 레인에는 후보가 하나, `codex-default`가 있습니다. 작업을 stdin으로 넘겨 `codex exec`를 실행하며, `advise`에는 `read-only`, `work`에는 `workspace-write`를 씁니다. 다른 워커를 등록하려면 [`config/routing.default.json`](config/routing.default.json)을 복사해 후보를 추가하고 `CUELINE_CONFIG`를 그쪽으로 가리키면 됩니다. `argv[0]`의 실행 파일은 바로 행위로 등록되며, 레인이 해석되려면 그것이 `PATH` 위에도 있어야 합니다.
182
+ Caller는 프로세스를 띄우지 않습니다. `process` executor를 명시한 경우에만 `default` 레인의 `codex-default`가 `codex exec`를 실행합니다. 독립 `advise`의 기본 동시 실행 상한은 전체/레인당 2이고, `work`가 포함된 배치는 직렬입니다.
143
183
 
144
184
  상태는 `CUELINE_HOME` 아래에 놓입니다:
145
185
 
146
186
  ```text
147
- runs/<run-id>/events.jsonl 추가 전용, 정본
187
+ runs/<run-id>/events.jsonl + events.jsonl.segments/ 추가 전용, 정본
188
+ runs/<run-id>/runtime.json.fence + runtime.json.epochs/ 세대가 격리된 활성 owner heartbeat 증거
189
+ runs/<run-id>/runtime.json.retired-owners/ 변경 불가능한 이전 owner 이벤트 cutoff
190
+ runs/<run-id>/runtime.json.takeover-intents/ 변경 불가능한 exact takeover 시도 기록
191
+ runs/<run-id>/cancel.json 존재할 때 지속 취소 요청
148
192
  runs/<run-id>/snapshot.json 재생 최적화용, 버려도 무방
149
193
  jobs/<job-id>.json 작업별 실행 증거
150
194
  ```
151
195
 
152
196
  기록 그 자체는 이벤트 로그입니다. 컨트롤러의 턴은 보내기 전에 기록되고, 작업은 프로세스가 시작되기 전에 등록됩니다. 그래서 의도와 부작용 사이에서 중단이 일어나도 흔적이 남습니다. 손상된 스냅샷은 신뢰되지 않고, 무시된 뒤 이벤트 1번부터 다시 만들어집니다.
153
197
 
154
- 복구는 실행이 기록해 둔 바로 그 대화 URL에만 다시 연결하며, 비슷해 보이는 탭에는 결코 붙지 않습니다. 보류 중인 컨트롤러 턴이 있으면 먼저 대화에서 정확한 요청과 연결된 완료 응답을 찾고, 찾으면 다시 보내지 않고 읽기 전용으로 대조해 복구합니다. 이전 상태에 보류 중인 턴이 여러 있으면 호출자가 하나를 명시적으로 선택해야 합니다. 유일한 보류 프롬프트가 `definitely_not_sent`임이 증명된 경우에만 CueLine이 자동으로 다시 시도합니다. 제출 상태가 불명확하거나 탭이 사라지면 `TAB_RECOVERY_UNSAFE`를 던지고 멈춥니다.
198
+ 복구는 완전히 같은 대화 URL에만 연결합니다. ChatGPT가 텍스트를 첨부로 자동 변환하면 `attachment_ready`로 인식하며 전송 클릭은 최대 번입니다. 모호한 클릭은 `possibly_sent`가 되고 재전송하지 않습니다. 수동 전송 뒤에는 `cueline run reconcile RUN_ID --request-id REQUEST_ID --manual-send-confirmed`로 정식 확인하고 동일 conversation, Pro 증거, protocol/run/round/request identity를 모두 검증합니다. 컨트롤러 증거는 성공한 비어 있지 않은 stdout을 우선하며 전체 12,000자로 제한하고, 전체 stdout/stderr는 로컬에 보존합니다.
155
199
 
156
200
  ## 검증
157
201
 
@@ -168,7 +212,7 @@ npm pack --dry-run
168
212
 
169
213
  ## 0.1의 한계
170
214
 
171
- 텍스트 전용. 실행 하나당 대화 하나. CueLine이 수행하는 모델 전환은 `Pro` 선택뿐입니다. 이미지, 파일 업로드, Deep Research, Projects, Apps는 지원하지 않습니다. 워커가 시작된 뒤의 자동 재시도나 폴백도 없습니다. 실패한 `work` 작업은 어디까지 진행됐는지 CueLine이 증명할 수 없으므로, 부작용이 불확실하다는 표시와 함께 보고됩니다. 주력 데스크톱 대상은 macOS이고 CI 대상은 Linux입니다. Windows는 검증되지 않았으며 `install.sh`는 Windows용 설치 프로그램이 아닙니다. 어댑터는 현재의 ChatGPT 웹 UI에 의존하므로, UI바뀌면 `COMPOSER_MISSING`, `SEND_BUTTON_MISSING`, 또는 응답 타임아웃으로 명시적으로 드러납니다 — 지어낸 답으로 둔갑하는 일은 결코 없습니다.
215
+ 텍스트 명령 전용입니다. 텍스트의 자동 첨부 변환은 지원하지만 의도적 파일 업로드, 이미지, Deep Research, Projects, Apps는 지원하지 않습니다. Caller는 `advise`만 허용하며 `work`에는 명시적 process executor필요합니다. 모호한 전송이나 이미 시작된 작업은 자동 재시도하지 않습니다.
172
216
 
173
217
  전체 표는 [compatibility](docs/compatibility.md)를 보세요.
174
218