cueline 0.1.6 → 0.1.7

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 (162) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +27 -0
  4. package/README.ja.md +29 -7
  5. package/README.ko.md +29 -7
  6. package/README.md +78 -11
  7. package/README.zh-CN.md +29 -7
  8. package/README.zh-TW.md +36 -8
  9. package/config/routing.schema.json +3 -0
  10. package/dist/src/api-caller-work.js +58 -14
  11. package/dist/src/api-caller-work.js.map +1 -1
  12. package/dist/src/api-contracts.d.ts +49 -0
  13. package/dist/src/api-controller-handoff.js +30 -38
  14. package/dist/src/api-controller-handoff.js.map +1 -1
  15. package/dist/src/api-run-verification.d.ts +3 -0
  16. package/dist/src/api-run-verification.js +174 -0
  17. package/dist/src/api-run-verification.js.map +1 -0
  18. package/dist/src/api-runtime-lifecycle.d.ts +6 -1
  19. package/dist/src/api-runtime-lifecycle.js +97 -8
  20. package/dist/src/api-runtime-lifecycle.js.map +1 -1
  21. package/dist/src/api.d.ts +17 -3
  22. package/dist/src/api.js +105 -38
  23. package/dist/src/api.js.map +1 -1
  24. package/dist/src/browser/browser-adapter.d.ts +15 -0
  25. package/dist/src/browser/codex-iab/bootstrap.d.ts +20 -0
  26. package/dist/src/browser/codex-iab/bootstrap.js +173 -9
  27. package/dist/src/browser/codex-iab/bootstrap.js.map +1 -1
  28. package/dist/src/browser/codex-iab/chatgpt-client.d.ts +3 -0
  29. package/dist/src/browser/codex-iab/chatgpt-client.js +115 -57
  30. package/dist/src/browser/codex-iab/chatgpt-client.js.map +1 -1
  31. package/dist/src/browser/codex-iab/probe.d.ts +36 -0
  32. package/dist/src/browser/codex-iab/probe.js +217 -0
  33. package/dist/src/browser/codex-iab/probe.js.map +1 -0
  34. package/dist/src/browser/codex-iab/recovery-evidence.d.ts +1 -1
  35. package/dist/src/browser/codex-iab/recovery-evidence.js +7 -10
  36. package/dist/src/browser/codex-iab/recovery-evidence.js.map +1 -1
  37. package/dist/src/browser/codex-iab/selectors.d.ts +1 -0
  38. package/dist/src/browser/codex-iab/selectors.js +1 -0
  39. package/dist/src/browser/codex-iab/selectors.js.map +1 -1
  40. package/dist/src/browser/codex-iab/send-button.d.ts +5 -0
  41. package/dist/src/browser/codex-iab/send-button.js +62 -0
  42. package/dist/src/browser/codex-iab/send-button.js.map +1 -0
  43. package/dist/src/browser/codex-iab/submission-url.js +6 -15
  44. package/dist/src/browser/codex-iab/submission-url.js.map +1 -1
  45. package/dist/src/browser/codex-iab/tab-discovery.js +45 -12
  46. package/dist/src/browser/codex-iab/tab-discovery.js.map +1 -1
  47. package/dist/src/browser/codex-iab/timing-options.d.ts +1 -0
  48. package/dist/src/browser/codex-iab/timing-options.js +5 -0
  49. package/dist/src/browser/codex-iab/timing-options.js.map +1 -0
  50. package/dist/src/cli/health-commands.d.ts +2 -0
  51. package/dist/src/cli/health-commands.js +191 -0
  52. package/dist/src/cli/health-commands.js.map +1 -0
  53. package/dist/src/cli/io.d.ts +4 -0
  54. package/dist/src/cli/io.js +2 -0
  55. package/dist/src/cli/io.js.map +1 -0
  56. package/dist/src/cli/main.d.ts +1 -5
  57. package/dist/src/cli/main.js +159 -77
  58. package/dist/src/cli/main.js.map +1 -1
  59. package/dist/src/cli/observation-commands.d.ts +2 -0
  60. package/dist/src/cli/observation-commands.js +239 -0
  61. package/dist/src/cli/observation-commands.js.map +1 -0
  62. package/dist/src/cli/run-status-view.d.ts +79 -0
  63. package/dist/src/cli/run-status-view.js +112 -0
  64. package/dist/src/cli/run-status-view.js.map +1 -0
  65. package/dist/src/core/controller-command-execution.d.ts +2 -2
  66. package/dist/src/core/controller-command-execution.js +82 -16
  67. package/dist/src/core/controller-command-execution.js.map +1 -1
  68. package/dist/src/core/controller-conversation-archive.d.ts +11 -0
  69. package/dist/src/core/controller-conversation-archive.js +109 -0
  70. package/dist/src/core/controller-conversation-archive.js.map +1 -0
  71. package/dist/src/core/controller-loop.d.ts +7 -1
  72. package/dist/src/core/controller-loop.js +114 -23
  73. package/dist/src/core/controller-loop.js.map +1 -1
  74. package/dist/src/core/controller-turn.d.ts +14 -2
  75. package/dist/src/core/controller-turn.js +109 -40
  76. package/dist/src/core/controller-turn.js.map +1 -1
  77. package/dist/src/core/controller-types.d.ts +2 -0
  78. package/dist/src/core/conversation-url.d.ts +3 -0
  79. package/dist/src/core/conversation-url.js +34 -0
  80. package/dist/src/core/conversation-url.js.map +1 -0
  81. package/dist/src/core/run-status.d.ts +9 -2
  82. package/dist/src/core/run-status.js +38 -25
  83. package/dist/src/core/run-status.js.map +1 -1
  84. package/dist/src/core/state-machine.d.ts +21 -1
  85. package/dist/src/core/state-machine.js +138 -13
  86. package/dist/src/core/state-machine.js.map +1 -1
  87. package/dist/src/core/timing.d.ts +9 -0
  88. package/dist/src/core/timing.js +22 -0
  89. package/dist/src/core/timing.js.map +1 -0
  90. package/dist/src/diagnostics/run-doctor.d.ts +22 -0
  91. package/dist/src/diagnostics/run-doctor.js +197 -0
  92. package/dist/src/diagnostics/run-doctor.js.map +1 -0
  93. package/dist/src/jobs/status.d.ts +5 -2
  94. package/dist/src/jobs/status.js +172 -12
  95. package/dist/src/jobs/status.js.map +1 -1
  96. package/dist/src/jobs/supervisor.js +57 -8
  97. package/dist/src/jobs/supervisor.js.map +1 -1
  98. package/dist/src/observation/run-handoff.d.ts +86 -0
  99. package/dist/src/observation/run-handoff.js +309 -0
  100. package/dist/src/observation/run-handoff.js.map +1 -0
  101. package/dist/src/observation/run-timeline.d.ts +32 -0
  102. package/dist/src/observation/run-timeline.js +278 -0
  103. package/dist/src/observation/run-timeline.js.map +1 -0
  104. package/dist/src/observation/run-watch.d.ts +15 -0
  105. package/dist/src/observation/run-watch.js +82 -0
  106. package/dist/src/observation/run-watch.js.map +1 -0
  107. package/dist/src/protocol/limits.d.ts +3 -0
  108. package/dist/src/protocol/limits.js +4 -0
  109. package/dist/src/protocol/limits.js.map +1 -0
  110. package/dist/src/protocol/lint-command.d.ts +24 -0
  111. package/dist/src/protocol/lint-command.js +210 -0
  112. package/dist/src/protocol/lint-command.js.map +1 -0
  113. package/dist/src/protocol/parse-command.js +4 -0
  114. package/dist/src/protocol/parse-command.js.map +1 -1
  115. package/dist/src/protocol/types.d.ts +12 -0
  116. package/dist/src/protocol/validate-command.js +76 -3
  117. package/dist/src/protocol/validate-command.js.map +1 -1
  118. package/dist/src/router/config-loader.js +23 -2
  119. package/dist/src/router/config-loader.js.map +1 -1
  120. package/dist/src/router/resolver.js +8 -3
  121. package/dist/src/router/resolver.js.map +1 -1
  122. package/dist/src/runners/process-runner.js +55 -12
  123. package/dist/src/runners/process-runner.js.map +1 -1
  124. package/dist/src/runners/runner-adapter.d.ts +2 -0
  125. package/dist/src/runners/runner-adapter.js.map +1 -1
  126. package/dist/src/state/atomic-write.d.ts +6 -0
  127. package/dist/src/state/atomic-write.js +43 -2
  128. package/dist/src/state/atomic-write.js.map +1 -1
  129. package/dist/src/state/cancellation.js +38 -4
  130. package/dist/src/state/cancellation.js.map +1 -1
  131. package/dist/src/state/event-log.js +5 -4
  132. package/dist/src/state/event-log.js.map +1 -1
  133. package/dist/src/state/private-directory.d.ts +5 -0
  134. package/dist/src/state/private-directory.js +37 -0
  135. package/dist/src/state/private-directory.js.map +1 -0
  136. package/dist/src/state/runtime-lease.js +19 -39
  137. package/dist/src/state/runtime-lease.js.map +1 -1
  138. package/dist/src/state/runtime-record-validation.d.ts +6 -0
  139. package/dist/src/state/runtime-record-validation.js +44 -0
  140. package/dist/src/state/runtime-record-validation.js.map +1 -0
  141. package/dist/src/state/runtime-retirement.js +58 -18
  142. package/dist/src/state/runtime-retirement.js.map +1 -1
  143. package/dist/src/state/runtime-takeover-intent.js +2 -2
  144. package/dist/src/state/runtime-takeover-intent.js.map +1 -1
  145. package/dist/src/state/store.d.ts +1 -0
  146. package/dist/src/state/store.js +12 -6
  147. package/dist/src/state/store.js.map +1 -1
  148. package/dist/src/version.d.ts +1 -1
  149. package/dist/src/version.js +1 -1
  150. package/docs/architecture.md +4 -4
  151. package/docs/compatibility.md +1 -1
  152. package/docs/controller-protocol.md +38 -7
  153. package/docs/experiments/protocol-lint.md +40 -0
  154. package/docs/experiments/run-doctor.md +39 -0
  155. package/docs/experiments/run-handoff.md +39 -0
  156. package/docs/experiments/run-timeline.md +35 -0
  157. package/docs/experiments/run-watch.md +31 -0
  158. package/docs/runner-contract.md +4 -3
  159. package/docs/state-and-recovery.md +15 -5
  160. package/package.json +1 -1
  161. package/schemas/controller-command.schema.json +89 -4
  162. package/skills/cueline/SKILL.md +13 -7
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cueline",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
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"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cueline",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
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"
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.7 - 2026-07-16
4
+
5
+ ### Added
6
+
7
+ - Add read-only operational surfaces for safe handoff and diagnosis: sanitized `runs`, causal `run doctor`, bounded `run watch`, metadata-only `run timeline`, explicit `run handoff`, durable-evidence `run verify`, controller-response `protocol lint`, machine-readable doctor/routing reports, and a non-mutating built-in-browser probe. These surfaces are strict allowlists and do not expose controller prompts, conversation URLs, job tasks/output, caller identities, task hashes, workdirs, runtime owner IDs, or untrusted exception text.
8
+ - Add deterministic pagination for `inspect(job_ids)` evidence. Pro can request the next exact slice using a content hash and character offset without rerunning a job or allowing one job to consume every later evidence window.
9
+ - Add opt-in `archiveControllerConversationOnComplete`. After a durable `complete`, CueLine may archive only the exact bound ChatGPT conversation while Pro is idle. The browser writes a durable checkpoint immediately before one Archive click; proven pre-click failures remain retryable, while a timeout, restart, missing checkpoint, navigation race, or missing proof becomes `ambiguous` and is never clicked again. `blocked` and `cancelled` runs are never archived.
10
+
11
+ ### Fixed
12
+
13
+ - Require visible, actionable send and stop controls. Hidden, disabled, inert, ancestor-hidden, zero-geometry, localized, or residual controls no longer prove that a prompt can be sent or that Pro is still answering.
14
+ - Refuse ambiguous ChatGPT tab discovery instead of selecting the first match. Exact conversation matching now canonicalizes only benign browser decoration and rejects lookalike hosts, credentials, nested paths, duplicate physical tabs, and navigation races.
15
+ - Accept a fast completed response as post-click proof after a send timeout, while preserving the one-click rule whenever completion cannot be proven. Browser timing options and all Node timer values are validated before they can schedule a spin, overflow, or unsafe delay.
16
+ - Preflight continuation, manual reconciliation, caller-result timestamps, runtime options, routing configuration, process workdirs, and controller commands before any durable mutation or browser/process action. Unknown fields, inherited object properties, invalid lanes/runners, unknown job targets, and action-incompatible fields now fail atomically.
17
+ - Bound controller envelopes, dispatch size, job references, process stdout/stderr, controller event evidence, and accumulated notices. Truncation is explicit and deterministic; full local job evidence remains in the private job status store.
18
+ - Make job status transitions durably atomic and terminally fenced. Concurrent, stale, status-first, event-first, and late-conflicting writers cannot regress or overwrite the first authoritative terminal result; process progress writes are coalesced without losing the final update.
19
+ - Strictly validate persisted job status, runtime lease, retirement, takeover, and cancellation records, including identity, chronology, filenames, unknown fields, canonical timestamps, and authoritative run-event agreement. Corrupt optional evidence degrades diagnosis instead of becoming trusted state.
20
+ - Keep CueLine state directories owner-only and refuse symlink/file substitutions. Caller work claims pin the canonical workdir identity; process jobs bind an absolute workdir before registration, so recovery cannot silently execute in another checkout.
21
+ - Normalize multiline recovery evidence without erasing meaningful indentation, and validate conversation identity consistently across submission, observation, manual reconciliation, and archive recovery.
22
+ - Fence runtime and lane-concurrency option records against caller mutation, and prevent unsafe process fallback or implicit route changes after a job has started.
23
+ - Correct terminal status reporting: a completed, blocked, or cancelled run now reports `continueAllowed: false`; a pending post-completion archive has its own explicit `controller_archive_pending` / `settle_controller_archive` state.
24
+
25
+ ### Verification
26
+
27
+ - Integrated 42 independently developed branches one at a time, running adversarial review and the full suite after every merge. Final integration passes 454/454 tests, TypeScript typecheck, plugin validation, fake smoke tests, and package-content checks.
28
+ - Verified a disposable real ChatGPT Web Pro run without interruption or `Answer now`: one prompt, exact `complete` delivery `LIVE_CONTROLLER_ARCHIVE_ACCEPTANCE_PASS`, one durable archive-start event, one archived event, zero ambiguous/failed archive events, and the pre-existing user conversation remained open.
29
+
3
30
  ## 0.1.6 - 2026-07-15
4
31
 
5
32
  ### Added
package/README.ja.md CHANGED
@@ -17,6 +17,15 @@
17
17
 
18
18
  CueLine は独立した実装で、**ランタイムの npm 依存はゼロ**です。Omnilane や GPT Relay のラッパーではありません。
19
19
 
20
+ ## 最新リリース:0.1.7
21
+
22
+ - 安全な run 一覧、doctor、watch、timeline、handoff、整合性検証、protocol lint、ブラウザー診断、inspect 証拠ページングを追加しました。
23
+ - タブ/ボタン証拠、コマンドとルーティング上限、原子的な job 状態、非公開の永続データ、workdir ID、runtime/cancel 記録、CLI の秘匿化を強化しました。
24
+ - 永続 `complete` 後に正確な会話だけをアーカイブする opt-in 機能を追加しました。クリック前 fence、Pro 再開/遷移チェック、曖昧後の再クリック禁止を備えます。
25
+ - 454/454 テストと使い捨ての実 ChatGPT Web Pro run を検証し、自然完了後に一度だけアーカイブし、既存のユーザー会話には触れませんでした。
26
+
27
+ 詳細は [changelog](CHANGELOG.md#017---2026-07-16) または不変の [v0.1.7 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.7) を参照してください。
28
+
20
29
  ## 1 回の実行は実際にどう進むか
21
30
 
22
31
  <img alt="Caller-first CueLine:ChatGPT がテキストコマンドを出し、現在の Codex がローカル助言を実行し、CueLine が完了まで有界な証拠を返す。" src="docs/assets/cueline-loop-ja.svg" width="100%">
@@ -48,15 +57,15 @@ ChatGPT Pro のサブスクリプションと、選択された Pro モデルは
48
57
  npm レジストリからインストールします。
49
58
 
50
59
  ```bash
51
- npm install -g cueline@0.1.6
60
+ npm install -g cueline@0.1.7
52
61
  cueline install
53
62
  cueline doctor
54
63
  ```
55
64
 
56
- フォールバックとして、[v0.1.6 リリース](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.6) のパッケージ済み tarball をインストールすることもできます。同じリリースに `.sha256` チェックサムも置いてあります。
65
+ フォールバックとして、[v0.1.7 リリース](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.7) のパッケージ済み tarball をインストールすることもできます。同じリリースに `.sha256` チェックサムも置いてあります。
57
66
 
58
67
  ```bash
59
- npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.6/cueline-0.1.6.tgz
68
+ npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.7/cueline-0.1.7.tgz
60
69
  cueline install
61
70
  cueline doctor
62
71
  ```
@@ -101,6 +110,7 @@ import {
101
110
  let result = await runCueLine({
102
111
  request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
103
112
  browser: createCodexIabAdapter({ browser: globalThis.browser }),
113
+ // opt-in:archiveControllerConversationOnComplete: true,
104
114
  // 任意:conversationUrl、routingConfig / routingConfigPath、home、cwd、
105
115
  // runTimeoutMs、signal、ジョブごと/既定の期限。
106
116
  }); // 既定は executor: "caller"
@@ -122,7 +132,7 @@ while (["awaiting_controller", "awaiting_caller", "awaiting_caller_work"].includ
122
132
  const claim = await claimCueLineCallerJob(result.runId, job.jobId, { callerId: "stable-codex-task-identity" });
123
133
  const proof = { claimId: claim.claimId, callerId: claim.callerId, fencingToken: claim.fencingToken };
124
134
  await startCueLineCallerJob(result.runId, job.jobId, proof);
125
- const stdout = await executeExactLocalWork(job.spec.task, claim.workdir, {
135
+ const stdout = await executeExactLocalWork(job.spec.task, claim.resolvedWorkdir, {
126
136
  heartbeat: () => heartbeatCueLineCallerJob(result.runId, job.jobId, proof),
127
137
  });
128
138
  await submitCueLineCallerJobResult(result.runId, job.jobId, { status: "succeeded", stdout }, { claim: proof });
@@ -140,18 +150,18 @@ if (result.status === "complete") {
140
150
 
141
151
  Codex のランタイムでは、`cueline api path` が出力する絶対パスのモジュールを import します。それがインストールしたパッケージのビルド済み API です。
142
152
 
143
- `startCueLineRun` は永続 run を作成して `ready` を返すだけです。`runCueLine` は作成後、永続 controller 観測待ち、caller 引き渡し、または終端まで進めます。owner 不在の `controller_response_pending` で通常送信済みターンが一つだけあり、`safeNextAction: observe` が示される場合、同じ Pro 応答を読み取り専用で観測する待機です。少し待って続行し、再送しません。`safeNextAction: reconcile` は曖昧、手動送信、または複数の保留ターンに使います。owner 不在の `caller_jobs_pending` は正常なローカル引き渡しであり、orphan や ChatGPT 待ちではありません。
153
+ `startCueLineRun` は永続 run を作成して `ready` を返すだけです。`runCueLine` は作成後、永続 controller 観測待ち、caller 引き渡し、または終端まで進めます。owner 不在の `controller_response_pending` で通常送信済みターンが一つだけあり、`safeNextAction: observe` が示される場合、同じ Pro 応答を読み取り専用で観測する待機です。少し待って続行し、再送しません。`safeNextAction: reconcile` は曖昧、手動送信、または複数の保留ターンに使います。owner 不在の `caller_jobs_pending` は正常なローカル引き渡しであり、orphan や ChatGPT 待ちではありません。CLI の `run status` は引き渡しに必要な metadata だけを出力し、task 本文、caller identity、task hash、workdir、runtime owner ID を含めません。正式な claim 後にだけ、API が正確な task と workdir を認可された caller に返します。
144
154
 
145
155
  ## CLI
146
156
 
147
- 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` で完全な引数を確認してください。
157
+ CLI はブラウザーを駆動しません。`doctor`、`routing`、`jobs`、`runs`、`run status`、`run verify`、`api path`、`config path` は読み取り専用です。`install`/`uninstall` はパッケージ所有のスキルリンクだけを変更します。`run reconcile`、`run takeover`、`run reconcile-runtime`、`run cancel`/`run stop`、`job cancel` は監査証拠を追記するか、永続 run/job 状態を変更します。状態を書き込むコマンドの前に `cueline help` で完全な引数を確認してください。
148
158
 
149
159
  ```console
150
160
  $ cueline install
151
161
  CueLine skill installed: /Users/you/.codex/skills/cueline
152
162
 
153
163
  $ cueline doctor
154
- CueLine 0.1.6
164
+ CueLine 0.1.7
155
165
  status ok
156
166
  node 22.14.0 ok
157
167
  config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
@@ -160,18 +170,30 @@ caller_ready yes
160
170
  caller_lanes 1
161
171
  process_available_lanes 1
162
172
 
173
+ $ cueline doctor --json
174
+ {"version":"0.1.7","status":"ok","node":{"version":"22.14.0","ok":true,"requirement":">=22"},...}
175
+
163
176
  $ cueline api path
164
177
  /usr/local/lib/node_modules/cueline/dist/src/api.js
165
178
 
166
179
  $ cueline routing
167
180
  default codex-default available
168
181
 
182
+ $ cueline routing --json
183
+ {"version":"0.1.7","availableLanes":1,"lanes":[{"name":"default","status":"available","selectedRunnerId":"codex-default"}],...}
184
+
169
185
  $ cueline jobs
170
186
  No jobs.
171
187
 
188
+ $ cueline runs
189
+ No runs.
190
+
172
191
  $ cueline run status run_... --json
173
192
  {"status":"running","executor":"caller","phase":"caller_jobs_pending","runtime":{"ownership":"missing"},...}
174
193
 
194
+ $ cueline run verify run_... --json
195
+ {"runId":"run_...","outcome":"verified","marker":"valid",...}
196
+
175
197
  $ cueline run takeover stale_run_... --json
176
198
  {"runId":"stale_run_...","outcome":"taken_over","next":"continue",...}
177
199
 
package/README.ko.md CHANGED
@@ -17,6 +17,15 @@
17
17
 
18
18
  CueLine은 독립적인 구현이며 **런타임 npm 의존성이 전혀 없습니다**. Omnilane이나 GPT Relay를 감싼 래퍼가 아닙니다.
19
19
 
20
+ ## 최신 릴리스: 0.1.7
21
+
22
+ - 안전한 run 목록, doctor, watch, timeline, handoff, 무결성 검증, protocol lint, 브라우저 진단, inspect 증거 페이지 기능을 추가했습니다.
23
+ - 탭/버튼 증거, 명령과 라우팅 한도, 원자적 job 상태, 비공개 영속 데이터, workdir ID, runtime/cancel 레코드, CLI 비식별화를 강화했습니다.
24
+ - 영속 `complete` 뒤 정확한 대화만 보관하는 opt-in 기능을 추가했습니다. 클릭 전 fence, Pro 재개/탐색 검사, 모호해진 뒤 재클릭 금지를 적용합니다.
25
+ - 454/454 테스트와 일회용 실제 ChatGPT Web Pro run을 검증했으며, 자연 완료 뒤 한 번만 보관하고 기존 사용자 대화는 건드리지 않았습니다.
26
+
27
+ 전체 내용은 [changelog](CHANGELOG.md#017---2026-07-16) 또는 변경 불가능한 [v0.1.7 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.7)에서 확인할 수 있습니다.
28
+
20
29
  ## 실행 한 번은 실제로 이렇게 흘러갑니다
21
30
 
22
31
  <img alt="Caller-first CueLine: ChatGPT가 텍스트 명령을 내리고 현재 Codex가 로컬 조언 작업을 수행하며 CueLine이 완료까지 제한된 증거를 반환합니다." src="docs/assets/cueline-loop-ko.svg" width="100%">
@@ -48,15 +57,15 @@ ChatGPT Pro 구독과 선택된 Pro 모델은 서로 다른 것입니다. 계정
48
57
  npm 레지스트리에서 설치합니다:
49
58
 
50
59
  ```bash
51
- npm install -g cueline@0.1.6
60
+ npm install -g cueline@0.1.7
52
61
  cueline install
53
62
  cueline doctor
54
63
  ```
55
64
 
56
- 대안으로, [v0.1.6 릴리스](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.6)의 패키지 tarball을 설치할 수도 있습니다. 같은 릴리스에 `.sha256` 체크섬도 함께 있습니다.
65
+ 대안으로, [v0.1.7 릴리스](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.7)의 패키지 tarball을 설치할 수도 있습니다. 같은 릴리스에 `.sha256` 체크섬도 함께 있습니다.
57
66
 
58
67
  ```bash
59
- npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.6/cueline-0.1.6.tgz
68
+ npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.7/cueline-0.1.7.tgz
60
69
  cueline install
61
70
  cueline doctor
62
71
  ```
@@ -101,6 +110,7 @@ import {
101
110
  let result = await runCueLine({
102
111
  request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
103
112
  browser: createCodexIabAdapter({ browser: globalThis.browser }),
113
+ // opt-in: archiveControllerConversationOnComplete: true,
104
114
  // 선택: conversationUrl, routingConfig / routingConfigPath, home, cwd,
105
115
  // runTimeoutMs, signal, 작업별/기본 제한 시간.
106
116
  }); // 기본 executor: "caller"
@@ -122,7 +132,7 @@ while (["awaiting_controller", "awaiting_caller", "awaiting_caller_work"].includ
122
132
  const claim = await claimCueLineCallerJob(result.runId, job.jobId, { callerId: "stable-codex-task-identity" });
123
133
  const proof = { claimId: claim.claimId, callerId: claim.callerId, fencingToken: claim.fencingToken };
124
134
  await startCueLineCallerJob(result.runId, job.jobId, proof);
125
- const stdout = await executeExactLocalWork(job.spec.task, claim.workdir, {
135
+ const stdout = await executeExactLocalWork(job.spec.task, claim.resolvedWorkdir, {
126
136
  heartbeat: () => heartbeatCueLineCallerJob(result.runId, job.jobId, proof),
127
137
  });
128
138
  await submitCueLineCallerJobResult(result.runId, job.jobId, { status: "succeeded", stdout }, { claim: proof });
@@ -140,18 +150,18 @@ if (result.status === "complete") {
140
150
 
141
151
  Codex 런타임에서는 `cueline api path`가 출력하는 절대 경로 모듈을 import하세요. 그것이 설치한 패키지의 빌드된 API입니다.
142
152
 
143
- `startCueLineRun`은 지속 run을 만들고 `ready`만 반환합니다. `runCueLine`은 생성 후 지속 controller 관측 대기, caller 인계 또는 종료 상태까지 진행합니다. owner가 없는 `controller_response_pending`에 정상 전송된 턴이 정확히 하나이고 `safeNextAction: observe`가 표시되면 같은 Pro 응답을 읽기 전용으로 관측하기 위한 대기입니다. 잠시 뒤 계속하고 재전송하지 마세요. `safeNextAction: reconcile`은 모호하거나 수동 전송되었거나 보류 턴이 여러 개인 경우에 사용합니다. owner가 없는 `caller_jobs_pending`은 정상적인 로컬 인계이며 orphan이나 ChatGPT 대기가 아닙니다.
153
+ `startCueLineRun`은 지속 run을 만들고 `ready`만 반환합니다. `runCueLine`은 생성 후 지속 controller 관측 대기, caller 인계 또는 종료 상태까지 진행합니다. owner가 없는 `controller_response_pending`에 정상 전송된 턴이 정확히 하나이고 `safeNextAction: observe`가 표시되면 같은 Pro 응답을 읽기 전용으로 관측하기 위한 대기입니다. 잠시 뒤 계속하고 재전송하지 마세요. `safeNextAction: reconcile`은 모호하거나 수동 전송되었거나 보류 턴이 여러 개인 경우에 사용합니다. owner가 없는 `caller_jobs_pending`은 정상적인 로컬 인계이며 orphan이나 ChatGPT 대기가 아닙니다. CLI의 `run status`는 인계에 필요한 metadata만 출력하며 task 본문, caller identity, task hash, workdir, runtime owner ID를 포함하지 않습니다. 정식 claim 뒤에만 API가 정확한 task와 workdir를 승인된 caller에게 반환합니다.
144
154
 
145
155
  ## CLI
146
156
 
147
- 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`로 전체 인수를 확인하세요.
157
+ CLI는 브라우저를 구동하지 않습니다. `doctor`, `routing`, `jobs`, `runs`, `run status`, `run verify`, `api path`, `config path`는 읽기 전용입니다. `install`/`uninstall`은 패키지가 소유한 스킬 링크만 변경합니다. `run reconcile`, `run takeover`, `run reconcile-runtime`, `run cancel`/`run stop`, `job cancel`은 감사 증거를 추가하거나 지속 run/job 상태를 변경합니다. 상태를 쓰는 명령 전에는 `cueline help`로 전체 인수를 확인하세요.
148
158
 
149
159
  ```console
150
160
  $ cueline install
151
161
  CueLine skill installed: /Users/you/.codex/skills/cueline
152
162
 
153
163
  $ cueline doctor
154
- CueLine 0.1.6
164
+ CueLine 0.1.7
155
165
  status ok
156
166
  node 22.14.0 ok
157
167
  config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
@@ -160,18 +170,30 @@ caller_ready yes
160
170
  caller_lanes 1
161
171
  process_available_lanes 1
162
172
 
173
+ $ cueline doctor --json
174
+ {"version":"0.1.7","status":"ok","node":{"version":"22.14.0","ok":true,"requirement":">=22"},...}
175
+
163
176
  $ cueline api path
164
177
  /usr/local/lib/node_modules/cueline/dist/src/api.js
165
178
 
166
179
  $ cueline routing
167
180
  default codex-default available
168
181
 
182
+ $ cueline routing --json
183
+ {"version":"0.1.7","availableLanes":1,"lanes":[{"name":"default","status":"available","selectedRunnerId":"codex-default"}],...}
184
+
169
185
  $ cueline jobs
170
186
  No jobs.
171
187
 
188
+ $ cueline runs
189
+ No runs.
190
+
172
191
  $ cueline run status run_... --json
173
192
  {"status":"running","executor":"caller","phase":"caller_jobs_pending","runtime":{"ownership":"missing"},...}
174
193
 
194
+ $ cueline run verify run_... --json
195
+ {"runId":"run_...","outcome":"verified","marker":"valid",...}
196
+
175
197
  $ cueline run takeover stale_run_... --json
176
198
  {"runId":"stale_run_...","outcome":"taken_over","next":"continue",...}
177
199
 
package/README.md CHANGED
@@ -17,17 +17,30 @@ The web page never touches your machine and has no local tools. It only emits on
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
 
20
+ ## Latest release: 0.1.7
21
+
22
+ - Added safe run inventory, doctor, watch, timeline, handoff, verification, protocol lint, browser diagnostics, and deterministic inspected-evidence pagination.
23
+ - Hardened browser tab/control evidence, command/routing bounds, atomic job status, private durable state, workdir identity, runtime/cancellation records, and redacted CLI output.
24
+ - Added opt-in exact-conversation archiving after durable `complete`, with a one-click write-ahead fence, Pro-active/navigation checks, and no retry after ambiguity.
25
+ - Verified 454/454 tests and a disposable real ChatGPT Web Pro run that completed and archived exactly once without interrupting Pro or touching the existing user conversation.
26
+
27
+ Read the complete [changelog](CHANGELOG.md#017---2026-07-16) or the immutable [v0.1.7 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.7).
28
+
20
29
  ## How a run actually goes
21
30
 
22
31
  <img alt="A caller-first CueLine run: ChatGPT emits text commands, the current Codex performs local advice, and CueLine returns bounded evidence until complete." src="docs/assets/cueline-loop-en.svg" width="100%">
23
32
 
24
33
  Each round: CueLine writes down what it is about to ask, sends one observation into the conversation, and later reads back exactly one `<CueLineControl>` envelope. The controller picks one of five actions — `dispatch`, `wait`, `inspect`, `complete`, `blocked` — and nothing outside that envelope is ever executed. A command that names the wrong run, the wrong round, or a malformed job is sent back for a bounded repair attempt rather than guessed at. The loop pauses at `awaiting_controller` after one durable send, at a caller handoff, or stops at `complete`, `blocked`, or the round limit (12 by default).
25
34
 
35
+ Controller commands also have fail-closed resource bounds: 131,072 characters
36
+ per envelope, 64 jobs per dispatch, and 256 explicit job IDs per wait or
37
+ inspect. These checks happen before job registration or process execution.
38
+
26
39
  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
40
 
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.
41
+ `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, canonical directory identity, caller identity, and a fencing token; callers execute only in its returned `resolvedWorkdir`. 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
42
 
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.
43
+ 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. A process `workdir` must be absolute; when omitted, CueLine binds the accepted job to the runtime's resolved absolute workspace so recovery cannot silently move it to another checkout. 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
44
 
32
45
  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
46
 
@@ -48,15 +61,15 @@ You need Node.js 22+, Codex with its built-in Browser, and — for the bundled d
48
61
  Install from the npm registry:
49
62
 
50
63
  ```bash
51
- npm install -g cueline@0.1.6
64
+ npm install -g cueline@0.1.7
52
65
  cueline install
53
66
  cueline doctor
54
67
  ```
55
68
 
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:
69
+ As a fallback, install the packaged tarball from the [v0.1.7 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.7), which also carries its `.sha256` checksum:
57
70
 
58
71
  ```bash
59
- npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.6/cueline-0.1.6.tgz
72
+ npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.7/cueline-0.1.7.tgz
60
73
  cueline install
61
74
  cueline doctor
62
75
  ```
@@ -79,7 +92,7 @@ cueline doctor
79
92
  Then, in Codex:
80
93
 
81
94
  1. Open `https://chatgpt.com` in Codex's built-in Browser and sign in.
82
- 2. Leave the conversation you want to be in charge selected — that page is the controller. Its composer must be on a `Pro` model; CueLine selects `Pro` for you if it is not, and refuses to send otherwise.
95
+ 2. Leave the conversation you want to be in charge selected — that page is the controller. If no selected tab is available and several matching ChatGPT tabs exist, CueLine returns `IAB_CHATGPT_TAB_AMBIGUOUS` instead of choosing the first one. Its composer must be on a `Pro` model; CueLine selects `Pro` for you if it is not, and refuses to send otherwise.
83
96
  3. Ask Codex to use CueLine for the task: *"Use CueLine and let the open ChatGPT Pro conversation direct this task."*
84
97
  4. Keep the returned `runId`. It is how an interrupted run is resumed.
85
98
 
@@ -101,6 +114,7 @@ import {
101
114
  let result = await runCueLine({
102
115
  request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
103
116
  browser: createCodexIabAdapter({ browser: globalThis.browser }),
117
+ // Optional opt-in: archiveControllerConversationOnComplete: true,
104
118
  // Optional: conversationUrl, routingConfig / routingConfigPath, home, cwd,
105
119
  // runTimeoutMs, signal, and per-job/default limits.
106
120
  }); // defaults to executor: "caller"
@@ -128,7 +142,7 @@ while (["awaiting_controller", "awaiting_caller", "awaiting_caller_work"].includ
128
142
  fencingToken: claim.fencingToken,
129
143
  };
130
144
  await startCueLineCallerJob(result.runId, job.jobId, proof);
131
- const stdout = await executeExactLocalWork(job.spec.task, claim.workdir, {
145
+ const stdout = await executeExactLocalWork(job.spec.task, claim.resolvedWorkdir, {
132
146
  heartbeat: () => heartbeatCueLineCallerJob(result.runId, job.jobId, proof),
133
147
  });
134
148
  await submitCueLineCallerJobResult(
@@ -147,20 +161,26 @@ if (result.status === "complete") {
147
161
  }
148
162
  ```
149
163
 
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.
164
+ `archiveControllerConversationOnComplete` defaults to `false` and is fixed when the run is created. When enabled, CueLine first persists `complete`, then archives only the exact bound conversation while Pro is idle. A proven failure before the durable click checkpoint can be retried; after that checkpoint, any timeout, restart, navigation race, or missing proof becomes `ambiguous` and CueLine never clicks Archive again. `blocked` and `cancelled` runs are left open.
165
+
166
+ `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. CLI status output is an explicit metadata allowlist: it omits task bodies, caller identities, task hashes, workdirs, and runtime owner IDs. The formal caller claim API returns the exact task and workdir to the authorized caller; the detailed read-only API remains available for trusted local diagnostics.
167
+
168
+ `listCueLineRuns()` is a read-only, sanitized inventory for discovering persisted run IDs. It omits controller text, conversation URLs, job tasks, and worker output.
169
+
170
+ `verifyCueLineRun(runId)` is a read-only integrity check for the creation marker, event replay and authority fences, optional snapshot, runtime lease, and job status evidence. It returns stable findings without returning durable run content.
151
171
 
152
172
  Inside Codex's runtime, import the absolute module that `cueline api path` prints — that is the built API of the package you installed.
153
173
 
154
174
  ## The CLI
155
175
 
156
- The CLI does not drive the browser. `doctor`, `routing`, `jobs`, `run status`, `api path`, and `config path` are read-only. `install`/`uninstall` change the package-owned skill link. `run reconcile`, `run takeover`, `run reconcile-runtime`, `run cancel`/`run stop`, and `job cancel` append evidence or change durable local run/job state. Run `cueline help` for every positional argument and option before using a state-changing command.
176
+ The CLI does not drive the browser. `doctor`, `routing`, `jobs`, `runs`, `run status`, `run verify`, `api path`, and `config path` are read-only. `install`/`uninstall` change the package-owned skill link. `run reconcile`, `run takeover`, `run reconcile-runtime`, `run cancel`/`run stop`, and `job cancel` append evidence or change durable local run/job state. Run `cueline help` for every positional argument and option before using a state-changing command.
157
177
 
158
178
  ```console
159
179
  $ cueline install
160
180
  CueLine skill installed: /Users/you/.codex/skills/cueline
161
181
 
162
182
  $ cueline doctor
163
- CueLine 0.1.6
183
+ CueLine 0.1.7
164
184
  status ok
165
185
  node 22.14.0 ok
166
186
  config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
@@ -169,18 +189,45 @@ caller_ready yes
169
189
  caller_lanes 1
170
190
  process_available_lanes 1
171
191
 
192
+ $ cueline doctor --json
193
+ {"version":"0.1.7","status":"ok","node":{"version":"22.14.0","ok":true,"requirement":">=22"},...}
194
+
172
195
  $ cueline api path
173
196
  /usr/local/lib/node_modules/cueline/dist/src/api.js
174
197
 
175
198
  $ cueline routing
176
199
  default codex-default available
177
200
 
201
+ $ cueline routing --json
202
+ {"version":"0.1.7","availableLanes":1,"lanes":[{"name":"default","status":"available","selectedRunnerId":"codex-default"}],...}
203
+
178
204
  $ cueline jobs
179
205
  No jobs.
180
206
 
207
+ $ cueline protocol lint response.txt --run-id run_... --round 3 --request-id msg_... --json
208
+ {"valid":false,"issues":[{"code":"LEGACY_RUNNER_ID_FIELD",...}]}
209
+
210
+ $ cueline runs
211
+ No runs.
212
+
181
213
  $ cueline run status run_... --json
182
214
  {"status":"running","executor":"caller","phase":"caller_jobs_pending","runtime":{"ownership":"missing"},...}
183
215
 
216
+ $ cueline run doctor run_... --json
217
+ {"outcome":"action_required","phase":"caller_jobs_pending","nextAction":"execute_caller_jobs",...}
218
+
219
+ $ cueline run watch run_... --after 42 --timeout-ms 5000 --json
220
+ {"outcome":"changed","previousSequence":42,"currentSequence":43,...}
221
+
222
+ $ cueline run handoff run_... --json
223
+ {"schema":"cueline-handoff/0.1","run":{"runId":"run_...","safeNextAction":"execute_caller_jobs"},...}
224
+
225
+ $ cueline run timeline run_... --after 40 --limit 20 --json
226
+ {"schema":"cueline-timeline/0.1","entries":[{"sequence":41,"type":"job_status",...}],...}
227
+
228
+ $ cueline run verify run_... --json
229
+ {"runId":"run_...","outcome":"verified","marker":"valid",...}
230
+
184
231
  $ cueline run takeover stale_run_... --json
185
232
  {"runId":"stale_run_...","outcome":"taken_over","next":"continue",...}
186
233
 
@@ -199,6 +246,26 @@ CueLine skill removed: /Users/you/.codex/skills/cueline
199
246
 
200
247
  `cueline doctor` exits non-zero when Node is too old or no enabled caller lane exists. `process_available_lanes` may be zero without degrading caller mode; use `cueline routing` to inspect process availability before explicitly selecting that executor. `cueline api path` is what the skill imports, so a packaged install needs no repository checkout. `cueline help` lists every command's exact syntax, including `--json` and the manual-reconcile confirmation flags.
201
248
 
249
+ The experimental `run doctor` command converts a run snapshot into stable
250
+ finding codes, bounded evidence, and a safe next action without writing state.
251
+ See [`docs/experiments/run-doctor.md`](docs/experiments/run-doctor.md).
252
+
253
+ The experimental `run watch` command performs a bounded, lease-free observation
254
+ using the durable event sequence as its cursor. See
255
+ [`docs/experiments/run-watch.md`](docs/experiments/run-watch.md).
256
+
257
+ The experimental `protocol lint` command validates a Pro envelope offline and
258
+ reports all known contract corrections in one pass. See
259
+ [`docs/experiments/protocol-lint.md`](docs/experiments/protocol-lint.md).
260
+
261
+ The experimental `run handoff` command produces a safe restart packet with
262
+ exact identities and absolute paths. See
263
+ [`docs/experiments/run-handoff.md`](docs/experiments/run-handoff.md).
264
+
265
+ The experimental `run timeline` command exposes a sanitized, cursor-paginated
266
+ audit view without raw event payloads. See
267
+ [`docs/experiments/run-timeline.md`](docs/experiments/run-timeline.md).
268
+
202
269
  Use `run takeover` only when `run status` reports an exact stale owner. It refuses a fresh active heartbeat and returns `next: continue` or `next: reconcile_runtime`; follow that value instead of guessing.
203
270
 
204
271
  ## Configuration
@@ -225,7 +292,7 @@ Recovery reattaches only to the exact recorded conversation URL. CueLine recogni
225
292
 
226
293
  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.
227
294
 
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.
295
+ 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. Every preferred output/error field includes a raw-character `evidence_window` and SHA-256 `content_hash`. When `next_offset` is non-null, Pro can inspect exactly one job by copying it as `evidence_offset` and the hash as `evidence_hash`; CueLine returns the next bounded window without rerunning the job. Changed evidence invalidates the cursor instead of mixing versions. 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. `wait` and `inspect` targets must be exact job IDs from the current observation; one unknown target rejects the entire command for repair before any partial wait or inspection. Controller commands are exact per action: unknown top-level fields, fields belonging to another action, empty/duplicate/malformed `job_ids`, `prompt` in place of `task`, and `runner_id` in place of `runner` are rejected with a repair error instead of silently ignored.
229
296
 
230
297
  ## Verify
231
298
 
package/README.zh-CN.md CHANGED
@@ -17,6 +17,15 @@
17
17
 
18
18
  CueLine 是独立实现,**没有任何运行时 npm 依赖**,也不是 Omnilane 或 GPT Relay 的包装层。
19
19
 
20
+ ## 最新版本:0.1.7
21
+
22
+ - 新增安全的 run 清单、doctor、watch、timeline、handoff、完整性验证、协议 lint、浏览器诊断与 inspect 证据分页。
23
+ - 强化标签页/按钮证据、命令与路由上限、原子 job 状态、私有持久数据、workdir 身份、runtime/取消记录和 CLI 脱敏。
24
+ - 新增可选的 `complete` 后精确会话归档:点击前有持久 fence,Pro 再次回答或页面切换时拒绝,进入模糊状态后绝不重复点击。
25
+ - 完成 454/454 测试和一次可丢弃的真实 ChatGPT Web Pro 验收;控制器自然完成、只归档一次,原有用户会话未被触碰。
26
+
27
+ 完整内容请查看 [changelog](CHANGELOG.md#017---2026-07-16) 或不可变的 [v0.1.7 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.7)。
28
+
20
29
  ## 一次运行实际是怎么走的
21
30
 
22
31
  <img alt="Caller-first CueLine 运行:ChatGPT 发出文本命令,当前 Codex 执行本地只读检查,CueLine 回传有界证据直至 complete。" src="docs/assets/cueline-loop-zh-CN.svg" width="100%">
@@ -48,15 +57,15 @@ ChatGPT Pro 订阅套餐与“选定的 Pro 模型”是两回事。账号或个
48
57
  从 npm registry 安装:
49
58
 
50
59
  ```bash
51
- npm install -g cueline@0.1.6
60
+ npm install -g cueline@0.1.7
52
61
  cueline install
53
62
  cueline doctor
54
63
  ```
55
64
 
56
- 作为后备,也可以安装 [v0.1.6 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.6) 上的打包 tarball,该 release 同时附带它的 `.sha256` 校验值:
65
+ 作为后备,也可以安装 [v0.1.7 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.7) 上的打包 tarball,该 release 同时附带它的 `.sha256` 校验值:
57
66
 
58
67
  ```bash
59
- npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.6/cueline-0.1.6.tgz
68
+ npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.7/cueline-0.1.7.tgz
60
69
  cueline install
61
70
  cueline doctor
62
71
  ```
@@ -101,6 +110,7 @@ import {
101
110
  let result = await runCueLine({
102
111
  request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
103
112
  browser: createCodexIabAdapter({ browser: globalThis.browser }),
113
+ // 可选并显式启用:archiveControllerConversationOnComplete: true,
104
114
  // 可选:conversationUrl、routingConfig / routingConfigPath、home、cwd、
105
115
  // runTimeoutMs、signal,以及作业/默认期限。
106
116
  }); // 默认 executor: "caller"
@@ -124,7 +134,7 @@ while (["awaiting_controller", "awaiting_caller", "awaiting_caller_work"].includ
124
134
  });
125
135
  const proof = { claimId: claim.claimId, callerId: claim.callerId, fencingToken: claim.fencingToken };
126
136
  await startCueLineCallerJob(result.runId, job.jobId, proof);
127
- const stdout = await executeExactLocalWork(job.spec.task, claim.workdir, {
137
+ const stdout = await executeExactLocalWork(job.spec.task, claim.resolvedWorkdir, {
128
138
  heartbeat: () => heartbeatCueLineCallerJob(result.runId, job.jobId, proof),
129
139
  });
130
140
  await submitCueLineCallerJobResult(result.runId, job.jobId, { status: "succeeded", stdout }, { claim: proof });
@@ -142,18 +152,18 @@ if (result.status === "complete") {
142
152
 
143
153
  在 Codex 的 runtime 里,import `cueline api path` 打印出的那个绝对路径模块——那就是你安装的那份包构建出来的 API。
144
154
 
145
- `startCueLineRun` 只创建持久 run 并返回 `ready`;`runCueLine` 创建并推进到持久 controller 观测暂停、caller 交接或终态。缺少 owner 的 `controller_response_pending` 若只有一个正常发送的回合且显示 `safeNextAction: observe`,表示同一个 Pro 回复仍待只读观测;稍后继续即可且不得重发。`safeNextAction: reconcile` 只用于模糊、人工发送或多个待对账回合。缺少 owner 的 `caller_jobs_pending` 是正常本地交接,并非 orphan,也不是仍在等 ChatGPT。
155
+ `startCueLineRun` 只创建持久 run 并返回 `ready`;`runCueLine` 创建并推进到持久 controller 观测暂停、caller 交接或终态。缺少 owner 的 `controller_response_pending` 若只有一个正常发送的回合且显示 `safeNextAction: observe`,表示同一个 Pro 回复仍待只读观测;稍后继续即可且不得重发。`safeNextAction: reconcile` 只用于模糊、人工发送或多个待对账回合。缺少 owner 的 `caller_jobs_pending` 是正常本地交接,并非 orphan,也不是仍在等 ChatGPT。CLI 的 `run status` 只输出交接所需元数据,不包含 task 正文、caller 身份、task hash、workdir 或 runtime owner ID;正式 claim 后,API 才把精确 task 与 workdir 交给获授权的 caller。
146
156
 
147
157
  ## CLI
148
158
 
149
- CLI 不驱动浏览器。`doctor`、`routing`、`jobs`、`run status`、`api path`、`config path` 都是只读;`install`/`uninstall` 只修改包所拥有的 skill 链接;`run reconcile`、`run takeover`、`run reconcile-runtime`、`run cancel`/`run stop`、`job cancel` 会追加审计证据或修改持久 run/job 状态。执行写入状态的命令前,先用 `cueline help` 核对完整参数。
159
+ CLI 不驱动浏览器。`doctor`、`routing`、`jobs`、`runs`、`run status`、`run verify`、`api path`、`config path` 都是只读;`install`/`uninstall` 只修改包所拥有的 skill 链接;`run reconcile`、`run takeover`、`run reconcile-runtime`、`run cancel`/`run stop`、`job cancel` 会追加审计证据或修改持久 run/job 状态。执行写入状态的命令前,先用 `cueline help` 核对完整参数。
150
160
 
151
161
  ```console
152
162
  $ cueline install
153
163
  CueLine skill installed: /Users/you/.codex/skills/cueline
154
164
 
155
165
  $ cueline doctor
156
- CueLine 0.1.6
166
+ CueLine 0.1.7
157
167
  status ok
158
168
  node 22.14.0 ok
159
169
  config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
@@ -162,18 +172,30 @@ caller_ready yes
162
172
  caller_lanes 1
163
173
  process_available_lanes 1
164
174
 
175
+ $ cueline doctor --json
176
+ {"version":"0.1.7","status":"ok","node":{"version":"22.14.0","ok":true,"requirement":">=22"},...}
177
+
165
178
  $ cueline api path
166
179
  /usr/local/lib/node_modules/cueline/dist/src/api.js
167
180
 
168
181
  $ cueline routing
169
182
  default codex-default available
170
183
 
184
+ $ cueline routing --json
185
+ {"version":"0.1.7","availableLanes":1,"lanes":[{"name":"default","status":"available","selectedRunnerId":"codex-default"}],...}
186
+
171
187
  $ cueline jobs
172
188
  No jobs.
173
189
 
190
+ $ cueline runs
191
+ No runs.
192
+
174
193
  $ cueline run status run_... --json
175
194
  {"status":"running","executor":"caller","phase":"caller_jobs_pending","runtime":{"ownership":"missing"},...}
176
195
 
196
+ $ cueline run verify run_... --json
197
+ {"runId":"run_...","outcome":"verified","marker":"valid",...}
198
+
177
199
  $ cueline run takeover stale_run_... --json
178
200
  {"runId":"stale_run_...","outcome":"taken_over","next":"continue",...}
179
201