cueline 0.2.2 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/CHANGELOG.md +53 -0
- package/README.ja.md +9 -12
- package/README.ko.md +9 -12
- package/README.md +9 -12
- package/README.zh-CN.md +9 -12
- package/README.zh-TW.md +9 -12
- package/dist/src/api-run-prune.d.ts +41 -0
- package/dist/src/api-run-prune.js +218 -0
- package/dist/src/api-run-prune.js.map +1 -0
- package/dist/src/api.d.ts +3 -0
- package/dist/src/api.js +3 -0
- package/dist/src/api.js.map +1 -1
- package/dist/src/cli/health-commands.js +35 -0
- package/dist/src/cli/health-commands.js.map +1 -1
- package/dist/src/cli/main.js +95 -3
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/cli/observation-commands.js +94 -1
- package/dist/src/cli/observation-commands.js.map +1 -1
- package/dist/src/diagnostics/offline-self-test.d.ts +23 -0
- package/dist/src/diagnostics/offline-self-test.js +163 -0
- package/dist/src/diagnostics/offline-self-test.js.map +1 -0
- package/dist/src/diagnostics/secret-audit.d.ts +25 -0
- package/dist/src/diagnostics/secret-audit.js +114 -0
- package/dist/src/diagnostics/secret-audit.js.map +1 -0
- package/dist/src/diagnostics/upgrade-preflight.d.ts +41 -0
- package/dist/src/diagnostics/upgrade-preflight.js +182 -0
- package/dist/src/diagnostics/upgrade-preflight.js.map +1 -0
- package/dist/src/jobs/status.js +11 -1
- package/dist/src/jobs/status.js.map +1 -1
- package/dist/src/observation/run-bundle.d.ts +27 -0
- package/dist/src/observation/run-bundle.js +55 -0
- package/dist/src/observation/run-bundle.js.map +1 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/docs/1.0/ideas/machine-output-contracts.md +47 -0
- package/docs/1.0/ideas/node26-contract.md +50 -0
- package/docs/1.0/ideas/offline-self-test.md +52 -0
- package/docs/1.0/ideas/upgrade-preflight.md +46 -0
- package/docs/compatibility.md +5 -5
- package/package.json +12 -2
- package/schemas/cli-doctor.schema.json +77 -0
- package/schemas/cli-routing-explain.schema.json +88 -0
- package/schemas/cli-routing.schema.json +65 -0
- package/schemas/cli-run-audit-secrets.schema.json +72 -0
- package/schemas/cli-run-export.schema.json +410 -0
- package/schemas/cli-runs-prune.schema.json +93 -0
- package/scripts/artifact-integrity.mjs +114 -0
- package/scripts/release-check.mjs +118 -0
- package/scripts/validate-cli-contracts.mjs +59 -0
- package/scripts/validate-doc-versions.mjs +79 -0
- package/scripts/validate-node-support.mjs +118 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cueline",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
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.
|
|
3
|
+
"version": "0.3.1",
|
|
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,58 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.1 - 2026-07-18
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Accept cancelled `ambiguous` job-result evidence produced when a running
|
|
8
|
+
`work` job is interrupted, keeping persisted run and job listings readable
|
|
9
|
+
without weakening cancellation checks for other terminal statuses.
|
|
10
|
+
- Backfill `cancelled: false` when reading pre-0.1.7 job-result evidence that
|
|
11
|
+
predates the field, so legacy runs stay readable; writes still require the
|
|
12
|
+
full strict shape.
|
|
13
|
+
|
|
14
|
+
### Verification
|
|
15
|
+
|
|
16
|
+
- Verified with a red/green regression oracle (new tests fail on the 0.3.0
|
|
17
|
+
validator), TypeScript typecheck, build, 535/535 tests, all release gates,
|
|
18
|
+
and live recovery of three previously unreadable on-disk runs, cross-checked
|
|
19
|
+
by an independent adversarial review line.
|
|
20
|
+
|
|
21
|
+
## 0.3.0 - 2026-07-17
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- Operator tooling: `runs prune` retention sweep over terminal runs (dry-run
|
|
26
|
+
by default, deletion serialized with the runtime lease lock), `run
|
|
27
|
+
audit-secrets` masked scan of durable events for secret-shaped strings, and
|
|
28
|
+
`run export` one-file sanitized support bundles.
|
|
29
|
+
- Release engineering: `self-test` offline controller-loop check, `upgrade
|
|
30
|
+
preflight` read-only migration report, `npm run release:check` release
|
|
31
|
+
gate, reproducible pack artifacts with SHA-256 verification, a
|
|
32
|
+
documentation version guard, and a Node 22/24/26 support contract in CI.
|
|
33
|
+
- Machine-output contracts: versioned strict JSON Schemas for `doctor`,
|
|
34
|
+
`routing`, `routing explain`, `runs prune`, `run audit-secrets`, and
|
|
35
|
+
`run export`; contract tests reject added fields, nested injection, empty
|
|
36
|
+
sections, and contradictory shapes.
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
- Run-scoped commands fail closed for an absent run instead of fabricating a
|
|
41
|
+
healthy view; a sweep pins this for every read and mutating surface.
|
|
42
|
+
- Secret audit reports a secret-shaped object key as a finding and masks it
|
|
43
|
+
in the finding path instead of echoing it verbatim.
|
|
44
|
+
- Prune re-reads runtime ownership inside the lease mutation lock before
|
|
45
|
+
deletion, and only a definite ENOENT counts as a completed removal; any
|
|
46
|
+
other filesystem error keeps the run and records the error.
|
|
47
|
+
|
|
48
|
+
### Verification
|
|
49
|
+
|
|
50
|
+
- Verified TypeScript typecheck, build, 532/532 unit/integration/smoke tests,
|
|
51
|
+
plugin validation, pack dry-run, release:check, offline self-test, and
|
|
52
|
+
upgrade preflight on the unified candidate, cross-reviewed adversarially by
|
|
53
|
+
two independent lines (AJV negative oracle: seven malicious mutations all
|
|
54
|
+
rejected).
|
|
55
|
+
|
|
3
56
|
## 0.2.2 - 2026-07-17
|
|
4
57
|
|
|
5
58
|
### Fixed
|
package/README.ja.md
CHANGED
|
@@ -22,15 +22,12 @@
|
|
|
22
22
|
|
|
23
23
|
CueLine は独立した実装で、**ランタイムの npm 依存はゼロ**です。Omnilane のラッパーではありません。
|
|
24
24
|
|
|
25
|
-
## 最新リリース:0.
|
|
25
|
+
## 最新リリース:0.3.1
|
|
26
26
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
- 容量警告はコントローラーが実際にページングできる証拠だけを数えます。永続上限を超える真の総量は独立した決定的な通知で開示され、証拠が十分ならコントローラーは早期に判断できます。
|
|
30
|
-
- リプレイされた証拠はバイト単位で安定します。検証済みの正規上限マーカーはそのまま保持され、旧形式の切り詰めマーカーは整合性エラーなしに決定的へ再適用されます。
|
|
31
|
-
- 490/490 テストに加え、実 process runner で検証しました。真の総量を持つ上限イベントマーカーを 1 つ書き込み、コントローラー 2 ターンで完了しました。
|
|
27
|
+
- 永続 job ステータスのバリデータが、runner が実際に書き出す 2 つの形状を誤って拒否する問題を修正しました:キャンセルされた `work` job が `ambiguous` と `cancelled: true` で記録される形状、および `cancelled` フィールド導入前(0.1.7 未満)の旧証跡です。いずれか一方だけでも該当 run が恒久的に読み取り不能になり、jobs 一覧全体が失敗していました。読み取り側は両形状を受け入れ、書き込み側は完全な厳格契約を維持します。
|
|
28
|
+
- 赤/緑の回帰オラクル、535/535 テスト、全リリースゲート、さらに読み取り不能だった 3 つの実 run の復旧で検証し、独立した敵対的レビューで相互確認しました。
|
|
32
29
|
|
|
33
|
-
詳細は [changelog](CHANGELOG.md#
|
|
30
|
+
詳細は [changelog](CHANGELOG.md#031---2026-07-18) またはバージョン指定の [v0.3.1 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.1) を参照してください。
|
|
34
31
|
|
|
35
32
|
## 1 回の実行は実際にどう進むか
|
|
36
33
|
|
|
@@ -71,15 +68,15 @@ ChatGPT Pro のサブスクリプションと、選択された Pro モデルは
|
|
|
71
68
|
npm レジストリからインストールします。
|
|
72
69
|
|
|
73
70
|
```bash
|
|
74
|
-
npm install -g cueline@0.
|
|
71
|
+
npm install -g cueline@0.3.1
|
|
75
72
|
cueline install
|
|
76
73
|
cueline doctor
|
|
77
74
|
```
|
|
78
75
|
|
|
79
|
-
フォールバックとして、[v0.
|
|
76
|
+
フォールバックとして、[v0.3.1 リリース](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.1) のパッケージ済み tarball をインストールすることもできます。同じリリースに `.sha256` チェックサムも置いてあります。
|
|
80
77
|
|
|
81
78
|
```bash
|
|
82
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.
|
|
79
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.3.1/cueline-0.3.1.tgz
|
|
83
80
|
cueline install
|
|
84
81
|
cueline doctor
|
|
85
82
|
```
|
|
@@ -186,7 +183,7 @@ CLI はブラウザーを駆動しません。状態を書き込むコマンド
|
|
|
186
183
|
|
|
187
184
|
```console
|
|
188
185
|
$ cueline doctor
|
|
189
|
-
CueLine 0.
|
|
186
|
+
CueLine 0.3.1
|
|
190
187
|
status ok
|
|
191
188
|
node 22.14.0 ok
|
|
192
189
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -292,7 +289,7 @@ npm pack --dry-run
|
|
|
292
289
|
|
|
293
290
|
## 開発
|
|
294
291
|
|
|
295
|
-
TypeScript、ESM、Node の組み込みモジュールのみ。`npm run build` は `dist/` へコンパイルし、テストは `node --test` でコンパイル済みの成果物に対して実行します。CI は Ubuntu と macOS 上の Node 22 / 24 を対象とします。
|
|
292
|
+
TypeScript、ESM、Node の組み込みモジュールのみ。`npm run build` は `dist/` へコンパイルし、テストは `node --test` でコンパイル済みの成果物に対して実行します。CI は Ubuntu と macOS 上の Node 22 / 24 / 26 を対象とします。
|
|
296
293
|
|
|
297
294
|
CueLine は独立したプロジェクトであり、OpenAI やその他いかなる企業とも提携しておらず、推奨・後援も受けていません。[provenance](docs/provenance.md) と [third-party notices](THIRD_PARTY_NOTICES.md) を参照してください。
|
|
298
295
|
|
package/README.ko.md
CHANGED
|
@@ -22,15 +22,12 @@
|
|
|
22
22
|
|
|
23
23
|
CueLine은 독립적인 구현이며 **런타임 npm 의존성이 전혀 없습니다**. Omnilane을 감싼 래퍼가 아닙니다.
|
|
24
24
|
|
|
25
|
-
## 최신 릴리스: 0.
|
|
25
|
+
## 최신 릴리스: 0.3.1
|
|
26
26
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
- 용량 경고는 컨트롤러가 실제로 페이징할 수 있는 증거만 계산합니다. 영속 상한을 넘는 실제 총량은 별도의 결정적 알림으로 공개되며, 증거가 충분하면 컨트롤러는 조기에 결정할 수 있습니다.
|
|
30
|
-
- 재생된 증거는 바이트 단위로 안정적입니다. 검증된 정규 상한 마커는 그대로 유지되고, 구형 절단 마커는 무결성 오류 없이 결정적으로 다시 상한이 적용됩니다.
|
|
31
|
-
- 490/490 테스트와 함께 실제 process runner로 검증했습니다. 실제 총량을 담은 상한 이벤트 마커 하나를 기록하고 컨트롤러 2턴 안에 완료했습니다.
|
|
27
|
+
- 영속 job 상태 검증기가 runner가 실제로 기록하는 두 가지 형태를 잘못 거부하던 문제를 수정했습니다: 취소된 `work` job이 `ambiguous`와 `cancelled: true`로 기록되는 형태, 그리고 `cancelled` 필드 도입 이전(0.1.7 미만)의 레거시 증거입니다. 둘 중 하나만 있어도 해당 run이 영구적으로 읽을 수 없게 되고 전체 jobs 목록이 실패했습니다. 읽기 경로는 두 형태를 모두 수용하며, 쓰기 경로는 완전한 엄격 계약을 유지합니다.
|
|
28
|
+
- 레드/그린 회귀 오라클, 535/535 테스트, 모든 릴리스 게이트, 그리고 읽을 수 없던 실제 run 3개의 복구로 검증했으며 독립적인 적대적 리뷰로 교차 확인했습니다.
|
|
32
29
|
|
|
33
|
-
전체 내용은 [changelog](CHANGELOG.md#
|
|
30
|
+
전체 내용은 [changelog](CHANGELOG.md#031---2026-07-18) 또는 버전이 지정된 [v0.3.1 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.1)에서 확인할 수 있습니다.
|
|
34
31
|
|
|
35
32
|
## 실행 한 번은 실제로 이렇게 흘러갑니다
|
|
36
33
|
|
|
@@ -71,15 +68,15 @@ ChatGPT Pro 구독과 선택된 Pro 모델은 서로 다른 것입니다. 계정
|
|
|
71
68
|
npm 레지스트리에서 설치합니다:
|
|
72
69
|
|
|
73
70
|
```bash
|
|
74
|
-
npm install -g cueline@0.
|
|
71
|
+
npm install -g cueline@0.3.1
|
|
75
72
|
cueline install
|
|
76
73
|
cueline doctor
|
|
77
74
|
```
|
|
78
75
|
|
|
79
|
-
대안으로, [v0.
|
|
76
|
+
대안으로, [v0.3.1 릴리스](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.1)의 패키지 tarball을 설치할 수도 있습니다. 같은 릴리스에 `.sha256` 체크섬도 함께 있습니다.
|
|
80
77
|
|
|
81
78
|
```bash
|
|
82
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.
|
|
79
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.3.1/cueline-0.3.1.tgz
|
|
83
80
|
cueline install
|
|
84
81
|
cueline doctor
|
|
85
82
|
```
|
|
@@ -186,7 +183,7 @@ CLI는 브라우저를 구동하지 않습니다. 상태를 쓰는 명령 전에
|
|
|
186
183
|
|
|
187
184
|
```console
|
|
188
185
|
$ cueline doctor
|
|
189
|
-
CueLine 0.
|
|
186
|
+
CueLine 0.3.1
|
|
190
187
|
status ok
|
|
191
188
|
node 22.14.0 ok
|
|
192
189
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -292,7 +289,7 @@ npm pack --dry-run
|
|
|
292
289
|
|
|
293
290
|
## 개발
|
|
294
291
|
|
|
295
|
-
TypeScript, ESM, Node 내장 모듈만 사용합니다. `npm run build`는 `dist/`로 컴파일하고, 테스트는 `node --test`로 컴파일된 결과물을 대상으로 실행합니다. CI는 Ubuntu와 macOS의 Node 22
|
|
292
|
+
TypeScript, ESM, Node 내장 모듈만 사용합니다. `npm run build`는 `dist/`로 컴파일하고, 테스트는 `node --test`로 컴파일된 결과물을 대상으로 실행합니다. CI는 Ubuntu와 macOS의 Node 22, 24, 26을 다룹니다.
|
|
296
293
|
|
|
297
294
|
CueLine은 독립 프로젝트이며 OpenAI를 비롯한 어떤 회사와도 제휴하거나 보증·후원을 받지 않았습니다. [provenance](docs/provenance.md)와 [third-party notices](THIRD_PARTY_NOTICES.md)를 참고하세요.
|
|
298
295
|
|
package/README.md
CHANGED
|
@@ -22,15 +22,12 @@ The web page never touches your machine and has no local tools. It only emits on
|
|
|
22
22
|
|
|
23
23
|
CueLine is a standalone implementation with **no runtime npm dependencies**. It is not a wrapper around Omnilane.
|
|
24
24
|
|
|
25
|
-
## Latest release: 0.
|
|
25
|
+
## Latest release: 0.3.1
|
|
26
26
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
- Capacity warnings count only evidence the controller can actually page through; true totals beyond the durable cap are reported in a separate deterministic notice, and the controller may decide as soon as evidence is sufficient.
|
|
30
|
-
- Replayed evidence stays byte-stable: a validated canonical cap marker is preserved as-is, and legacy truncation markers re-cap deterministically without integrity errors.
|
|
31
|
-
- Verified 490/490 tests, plus a real process-runner run that wrote one capped event marker carrying the true total and completed in two controller turns.
|
|
27
|
+
- Fixed the durable job-status validator rejecting two shapes real runners persist: a cancelled `work` job recorded as `ambiguous` with `cancelled: true`, and pre-0.1.7 evidence that predates the `cancelled` field. Either one permanently marked the owning run unreadable and made the whole jobs listing throw. Reads accept both shapes now; writes keep the full strict contract.
|
|
28
|
+
- Verified with a red/green regression oracle, 535/535 tests, all release gates, and live recovery of three previously unreadable on-disk runs, cross-checked by an independent adversarial review.
|
|
32
29
|
|
|
33
|
-
Read the complete [changelog](CHANGELOG.md#
|
|
30
|
+
Read the complete [changelog](CHANGELOG.md#031---2026-07-18) or the versioned [v0.3.1 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.1).
|
|
34
31
|
|
|
35
32
|
## How a run actually goes
|
|
36
33
|
|
|
@@ -73,15 +70,15 @@ You need Node.js 22+, Codex with its built-in Browser, and — for the bundled d
|
|
|
73
70
|
Install from the npm registry:
|
|
74
71
|
|
|
75
72
|
```bash
|
|
76
|
-
npm install -g cueline@0.
|
|
73
|
+
npm install -g cueline@0.3.1
|
|
77
74
|
cueline install
|
|
78
75
|
cueline doctor
|
|
79
76
|
```
|
|
80
77
|
|
|
81
|
-
As a fallback, install the packaged tarball from the [v0.
|
|
78
|
+
As a fallback, install the packaged tarball from the [v0.3.1 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.1), which also carries its `.sha256` checksum:
|
|
82
79
|
|
|
83
80
|
```bash
|
|
84
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.
|
|
81
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.3.1/cueline-0.3.1.tgz
|
|
85
82
|
cueline install
|
|
86
83
|
cueline doctor
|
|
87
84
|
```
|
|
@@ -197,7 +194,7 @@ The CLI does not drive the browser. Run `cueline help` for every positional argu
|
|
|
197
194
|
|
|
198
195
|
```console
|
|
199
196
|
$ cueline doctor
|
|
200
|
-
CueLine 0.
|
|
197
|
+
CueLine 0.3.1
|
|
201
198
|
status ok
|
|
202
199
|
node 22.14.0 ok
|
|
203
200
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -301,7 +298,7 @@ See [compatibility](docs/compatibility.md) for the full matrix.
|
|
|
301
298
|
|
|
302
299
|
## Development
|
|
303
300
|
|
|
304
|
-
TypeScript, ESM, Node built-ins only. `npm run build` compiles to `dist/`; tests run on the compiled output with `node --test`. CI covers Node 22 and
|
|
301
|
+
TypeScript, ESM, Node built-ins only. `npm run build` compiles to `dist/`; tests run on the compiled output with `node --test`. CI covers Node 22, 24, and 26 on Ubuntu and macOS.
|
|
305
302
|
|
|
306
303
|
CueLine is an independent project and is not affiliated with, endorsed by, or sponsored by OpenAI or any other company. See [provenance](docs/provenance.md) and [third-party notices](THIRD_PARTY_NOTICES.md).
|
|
307
304
|
|
package/README.zh-CN.md
CHANGED
|
@@ -22,15 +22,12 @@
|
|
|
22
22
|
|
|
23
23
|
CueLine 是独立实现,**没有任何运行时 npm 依赖**,也不是 Omnilane 的包装层。
|
|
24
24
|
|
|
25
|
-
## 最新版本:0.
|
|
25
|
+
## 最新版本:0.3.1
|
|
26
26
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
- 容量警告只统计控制器实际能翻到的证据;超过持久上限的真实总量改由独立的确定性通知披露,控制器在证据充分时即可提前决策。
|
|
30
|
-
- 重放证据字节稳定:通过校验的规范上限标记原样保留,旧版截断标记则确定性地重新套用上限,不产生完整性错误。
|
|
31
|
-
- 完成 490/490 测试,并用真实 process runner 验证:单个上限事件标记携带真实总量写入,两个控制器轮次内完成。
|
|
27
|
+
- 修复持久 job 状态验证器误拒两种 runner 实际会写出的形状:被取消的 `work` job 以 `ambiguous` 搭配 `cancelled: true` 记录,以及 0.1.7 之前、尚无 `cancelled` 字段的旧证据。两者任一都会让所属 run 永久无法读取,并使整个 jobs 列表直接失败。现在读取端接受这两种形状;写入端仍维持完整严格契约。
|
|
28
|
+
- 以红绿回归测试、535/535 测试、全部发布闸门,加上三个原本无法读取的实际 run 成功恢复验证,并经独立对抗式审查交叉确认。
|
|
32
29
|
|
|
33
|
-
完整内容请查看 [changelog](CHANGELOG.md#
|
|
30
|
+
完整内容请查看 [changelog](CHANGELOG.md#031---2026-07-18) 或版本化的 [v0.3.1 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.1)。
|
|
34
31
|
|
|
35
32
|
## 一次运行实际是怎么走的
|
|
36
33
|
|
|
@@ -71,15 +68,15 @@ ChatGPT Pro 订阅套餐与“选定的 Pro 模型”是两回事。账号或个
|
|
|
71
68
|
从 npm registry 安装:
|
|
72
69
|
|
|
73
70
|
```bash
|
|
74
|
-
npm install -g cueline@0.
|
|
71
|
+
npm install -g cueline@0.3.1
|
|
75
72
|
cueline install
|
|
76
73
|
cueline doctor
|
|
77
74
|
```
|
|
78
75
|
|
|
79
|
-
作为后备,也可以安装 [v0.
|
|
76
|
+
作为后备,也可以安装 [v0.3.1 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.1) 上的打包 tarball,该 release 同时附带它的 `.sha256` 校验值:
|
|
80
77
|
|
|
81
78
|
```bash
|
|
82
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.
|
|
79
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.3.1/cueline-0.3.1.tgz
|
|
83
80
|
cueline install
|
|
84
81
|
cueline doctor
|
|
85
82
|
```
|
|
@@ -188,7 +185,7 @@ CLI 不驱动浏览器。执行写入状态的命令前,先用 `cueline help`
|
|
|
188
185
|
|
|
189
186
|
```console
|
|
190
187
|
$ cueline doctor
|
|
191
|
-
CueLine 0.
|
|
188
|
+
CueLine 0.3.1
|
|
192
189
|
status ok
|
|
193
190
|
node 22.14.0 ok
|
|
194
191
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -294,7 +291,7 @@ npm pack --dry-run
|
|
|
294
291
|
|
|
295
292
|
## 开发
|
|
296
293
|
|
|
297
|
-
TypeScript、ESM,仅使用 Node 内置模块。`npm run build` 编译到 `dist/`;测试以 `node --test` 运行编译产物。CI 覆盖 Ubuntu 与 macOS 上的 Node 22
|
|
294
|
+
TypeScript、ESM,仅使用 Node 内置模块。`npm run build` 编译到 `dist/`;测试以 `node --test` 运行编译产物。CI 覆盖 Ubuntu 与 macOS 上的 Node 22、24、26。
|
|
298
295
|
|
|
299
296
|
CueLine 是独立项目,与 OpenAI 或任何其他公司均无隶属关系,也未获其背书或赞助。见 [provenance](docs/provenance.md) 与 [third-party notices](THIRD_PARTY_NOTICES.md)。
|
|
300
297
|
|
package/README.zh-TW.md
CHANGED
|
@@ -22,15 +22,12 @@
|
|
|
22
22
|
|
|
23
23
|
CueLine 是獨立實作,**沒有任何 runtime npm 相依套件**,也不是 Omnilane 的包裝層。
|
|
24
24
|
|
|
25
|
-
## 最新版本:0.
|
|
25
|
+
## 最新版本:0.3.1
|
|
26
26
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
- 容量警告只計算主控實際翻得到的證據;超過持久上限的真實總量改以獨立的決定性通知揭露,主控在證據足夠時即可提前決策。
|
|
30
|
-
- 重播證據位元組穩定:通過驗證的正規上限標記原樣保留,舊版截斷標記則決定性地重新套用上限,不產生完整性錯誤。
|
|
31
|
-
- 完成 490/490 測試,並以真實 process runner 驗證:單一上限事件標記帶真實總量寫入,兩個主控回合內完成。
|
|
27
|
+
- 修正持久 job 狀態驗證器誤拒兩種 runner 實際會寫出的形狀:被取消的 `work` job 以 `ambiguous` 搭配 `cancelled: true` 記錄,以及 0.1.7 之前、尚無 `cancelled` 欄位的舊證據。兩者任一都會讓所屬 run 永久無法讀取,並使整個 jobs 清單直接失敗。現在讀取端接受這兩種形狀;寫入端仍維持完整嚴格契約。
|
|
28
|
+
- 以紅綠迴歸測試、535/535 測試、全部發佈閘門,加上三個原本無法讀取的實際 run 成功復原驗證,並經獨立對抗式審查交叉確認。
|
|
32
29
|
|
|
33
|
-
完整內容請看 [changelog](CHANGELOG.md#
|
|
30
|
+
完整內容請看 [changelog](CHANGELOG.md#031---2026-07-18) 或版本化的 [v0.3.1 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.1)。
|
|
34
31
|
|
|
35
32
|
## 一次執行實際上怎麼跑
|
|
36
33
|
|
|
@@ -71,15 +68,15 @@ ChatGPT Pro 訂閱方案與「選定的 Pro 模型」是兩回事。帳號或個
|
|
|
71
68
|
從 npm registry 安裝:
|
|
72
69
|
|
|
73
70
|
```bash
|
|
74
|
-
npm install -g cueline@0.
|
|
71
|
+
npm install -g cueline@0.3.1
|
|
75
72
|
cueline install
|
|
76
73
|
cueline doctor
|
|
77
74
|
```
|
|
78
75
|
|
|
79
|
-
作為備援,也可以安裝 [v0.
|
|
76
|
+
作為備援,也可以安裝 [v0.3.1 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.1) 上的打包 tarball,該 release 同時附上它的 `.sha256` 校驗碼:
|
|
80
77
|
|
|
81
78
|
```bash
|
|
82
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.
|
|
79
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.3.1/cueline-0.3.1.tgz
|
|
83
80
|
cueline install
|
|
84
81
|
cueline doctor
|
|
85
82
|
```
|
|
@@ -197,7 +194,7 @@ CLI 不驅動瀏覽器。執行寫入狀態的命令前,先用 `cueline help`
|
|
|
197
194
|
|
|
198
195
|
```console
|
|
199
196
|
$ cueline doctor
|
|
200
|
-
CueLine 0.
|
|
197
|
+
CueLine 0.3.1
|
|
201
198
|
status ok
|
|
202
199
|
node 22.14.0 ok
|
|
203
200
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -303,7 +300,7 @@ npm pack --dry-run
|
|
|
303
300
|
|
|
304
301
|
## 開發
|
|
305
302
|
|
|
306
|
-
TypeScript、ESM,只用 Node 內建模組。`npm run build` 會編譯到 `dist/`;測試以 `node --test` 跑編譯後的產物。CI 涵蓋 Ubuntu 與 macOS 上的 Node 22
|
|
303
|
+
TypeScript、ESM,只用 Node 內建模組。`npm run build` 會編譯到 `dist/`;測試以 `node --test` 跑編譯後的產物。CI 涵蓋 Ubuntu 與 macOS 上的 Node 22、24、26。
|
|
307
304
|
|
|
308
305
|
CueLine 是獨立專案,與 OpenAI 或任何其他公司皆無隸屬關係,亦未獲其背書或贊助。見 [provenance](docs/provenance.md) 與 [third-party notices](THIRD_PARTY_NOTICES.md)。
|
|
309
306
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { CueLineRuntimeOptions } from "./api-contracts.js";
|
|
2
|
+
export declare const PRUNABLE_RUN_STATES: readonly ["complete", "blocked", "cancelled"];
|
|
3
|
+
export type PrunableRunState = (typeof PRUNABLE_RUN_STATES)[number];
|
|
4
|
+
export type CueLineRunPruneKeptReason = "unreadable" | "non_terminal" | "state_excluded" | "runtime_active" | "active_jobs" | "too_recent" | "delete_failed";
|
|
5
|
+
export interface CueLineRunPruneDecision {
|
|
6
|
+
runId: string;
|
|
7
|
+
decision: "pruned" | "eligible" | "kept";
|
|
8
|
+
reason?: CueLineRunPruneKeptReason;
|
|
9
|
+
status?: string;
|
|
10
|
+
lastEventAt?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface CueLineRunPruneError {
|
|
13
|
+
runId: string;
|
|
14
|
+
message: string;
|
|
15
|
+
}
|
|
16
|
+
export interface CueLineRunPruneResult {
|
|
17
|
+
home: string;
|
|
18
|
+
apply: boolean;
|
|
19
|
+
olderThanMs: number;
|
|
20
|
+
cutoff: string;
|
|
21
|
+
states: PrunableRunState[];
|
|
22
|
+
decisions: CueLineRunPruneDecision[];
|
|
23
|
+
prunedRuns: number;
|
|
24
|
+
eligibleRuns: number;
|
|
25
|
+
keptRuns: number;
|
|
26
|
+
removedJobRecords: number;
|
|
27
|
+
errors: CueLineRunPruneError[];
|
|
28
|
+
}
|
|
29
|
+
export interface CueLineRunPruneOptions extends Pick<CueLineRuntimeOptions, "home" | "environment" | "now"> {
|
|
30
|
+
olderThanMs: number;
|
|
31
|
+
states?: readonly PrunableRunState[];
|
|
32
|
+
apply?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Retention sweep over persisted runs. Only terminal runs (complete, blocked,
|
|
36
|
+
* cancelled) whose runtime lease is not active, with zero pending or running
|
|
37
|
+
* jobs, and whose last durable event is older than the cutoff are eligible.
|
|
38
|
+
* Dry-run by default: nothing is deleted unless `apply` is true. Unreadable
|
|
39
|
+
* runs are always kept; deciding about corrupt evidence requires a human.
|
|
40
|
+
*/
|
|
41
|
+
export declare function pruneCueLineRuns(options: CueLineRunPruneOptions): Promise<CueLineRunPruneResult>;
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { access, readdir, rm } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { listCueLineRuns } from "./api-runtime-lifecycle.js";
|
|
4
|
+
import { CueLineError } from "./core/errors.js";
|
|
5
|
+
import { runtimeEnvironment } from "./core/runtime.js";
|
|
6
|
+
import { JobStatusStore } from "./jobs/status.js";
|
|
7
|
+
import { defaultCueLineHome, runPaths } from "./state/paths.js";
|
|
8
|
+
import { readRuntimeLease, withRuntimeLeaseMutation, } from "./state/runtime-lease.js";
|
|
9
|
+
export const PRUNABLE_RUN_STATES = ["complete", "blocked", "cancelled"];
|
|
10
|
+
function normalizedStates(states) {
|
|
11
|
+
const requested = states === undefined ? PRUNABLE_RUN_STATES : states;
|
|
12
|
+
const unique = [];
|
|
13
|
+
for (const state of requested) {
|
|
14
|
+
if (!PRUNABLE_RUN_STATES.includes(state)) {
|
|
15
|
+
throw new CueLineError("RUN_PRUNE_STATE_INVALID", `Only terminal run states may be pruned; '${state}' is not one of: ${PRUNABLE_RUN_STATES.join(", ")}.`);
|
|
16
|
+
}
|
|
17
|
+
if (!unique.includes(state))
|
|
18
|
+
unique.push(state);
|
|
19
|
+
}
|
|
20
|
+
if (unique.length === 0) {
|
|
21
|
+
throw new CueLineError("RUN_PRUNE_STATE_INVALID", "At least one terminal run state is required.");
|
|
22
|
+
}
|
|
23
|
+
return unique;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Only a definite ENOENT counts as "gone". Any other filesystem error
|
|
27
|
+
* (EACCES, EIO, …) must propagate, otherwise the RUNTIME_MUTATION_FENCED
|
|
28
|
+
* recovery path would misclassify an unverifiable directory as pruned.
|
|
29
|
+
*/
|
|
30
|
+
async function definitelyMissing(target) {
|
|
31
|
+
try {
|
|
32
|
+
await access(target);
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (error.code === "ENOENT")
|
|
37
|
+
return true;
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function removeJobRecordsForRuns(home, runIds, errors) {
|
|
42
|
+
if (runIds.size === 0)
|
|
43
|
+
return 0;
|
|
44
|
+
const directory = path.join(home, "jobs");
|
|
45
|
+
let names;
|
|
46
|
+
try {
|
|
47
|
+
names = await readdir(directory);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (error.code === "ENOENT")
|
|
51
|
+
return 0;
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
const jobIds = new Set();
|
|
55
|
+
for (const name of names) {
|
|
56
|
+
if (name.endsWith(".json"))
|
|
57
|
+
jobIds.add(name.slice(0, -".json".length));
|
|
58
|
+
else if (name.endsWith(".terminal"))
|
|
59
|
+
jobIds.add(name.slice(0, -".terminal".length));
|
|
60
|
+
}
|
|
61
|
+
const statusStore = new JobStatusStore(home);
|
|
62
|
+
let removed = 0;
|
|
63
|
+
for (const jobId of [...jobIds].sort()) {
|
|
64
|
+
let runId;
|
|
65
|
+
try {
|
|
66
|
+
runId = (await statusStore.read(jobId))?.runId;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// An unparsable job record never names a run; leave it for `jobs` to surface.
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (runId === undefined || !runIds.has(runId))
|
|
73
|
+
continue;
|
|
74
|
+
try {
|
|
75
|
+
await rm(path.join(directory, `${jobId}.json`), { force: true });
|
|
76
|
+
await rm(path.join(directory, `${jobId}.terminal`), { force: true });
|
|
77
|
+
removed += 1;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
errors.push({
|
|
81
|
+
runId,
|
|
82
|
+
message: `job record '${jobId}': ${error instanceof Error ? error.message : String(error)}`,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return removed;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Retention sweep over persisted runs. Only terminal runs (complete, blocked,
|
|
90
|
+
* cancelled) whose runtime lease is not active, with zero pending or running
|
|
91
|
+
* jobs, and whose last durable event is older than the cutoff are eligible.
|
|
92
|
+
* Dry-run by default: nothing is deleted unless `apply` is true. Unreadable
|
|
93
|
+
* runs are always kept; deciding about corrupt evidence requires a human.
|
|
94
|
+
*/
|
|
95
|
+
export async function pruneCueLineRuns(options) {
|
|
96
|
+
if (!Number.isFinite(options.olderThanMs) ||
|
|
97
|
+
options.olderThanMs < 0) {
|
|
98
|
+
throw new CueLineError("RUN_PRUNE_AGE_INVALID", "olderThanMs must be a non-negative finite number of milliseconds.");
|
|
99
|
+
}
|
|
100
|
+
const environment = options.environment ?? runtimeEnvironment();
|
|
101
|
+
const home = options.home ?? defaultCueLineHome(environment);
|
|
102
|
+
const states = normalizedStates(options.states);
|
|
103
|
+
const apply = options.apply === true;
|
|
104
|
+
const now = options.now === undefined ? new Date() : options.now();
|
|
105
|
+
const cutoffMs = now.getTime() - options.olderThanMs;
|
|
106
|
+
const cutoff = new Date(cutoffMs).toISOString();
|
|
107
|
+
const runs = await listCueLineRuns({
|
|
108
|
+
home,
|
|
109
|
+
...(options.environment === undefined ? {} : { environment: options.environment }),
|
|
110
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
111
|
+
});
|
|
112
|
+
const decisions = [];
|
|
113
|
+
const errors = [];
|
|
114
|
+
const prunedRunIds = new Set();
|
|
115
|
+
let eligibleRuns = 0;
|
|
116
|
+
let keptRuns = 0;
|
|
117
|
+
for (const run of runs) {
|
|
118
|
+
if (!run.readable) {
|
|
119
|
+
decisions.push({ runId: run.runId, decision: "kept", reason: "unreadable" });
|
|
120
|
+
keptRuns += 1;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const base = {
|
|
124
|
+
runId: run.runId,
|
|
125
|
+
status: run.status,
|
|
126
|
+
lastEventAt: run.lastEventAt,
|
|
127
|
+
};
|
|
128
|
+
if (!PRUNABLE_RUN_STATES.includes(run.status)) {
|
|
129
|
+
decisions.push({ ...base, decision: "kept", reason: "non_terminal" });
|
|
130
|
+
keptRuns += 1;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (!states.includes(run.status)) {
|
|
134
|
+
decisions.push({ ...base, decision: "kept", reason: "state_excluded" });
|
|
135
|
+
keptRuns += 1;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (run.runtimeOwnership === "active") {
|
|
139
|
+
decisions.push({ ...base, decision: "kept", reason: "runtime_active" });
|
|
140
|
+
keptRuns += 1;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (run.activeJobs > 0) {
|
|
144
|
+
decisions.push({ ...base, decision: "kept", reason: "active_jobs" });
|
|
145
|
+
keptRuns += 1;
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
const lastEventMs = Date.parse(run.lastEventAt);
|
|
149
|
+
if (!Number.isFinite(lastEventMs) || lastEventMs >= cutoffMs) {
|
|
150
|
+
decisions.push({ ...base, decision: "kept", reason: "too_recent" });
|
|
151
|
+
keptRuns += 1;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
if (!apply) {
|
|
155
|
+
decisions.push({ ...base, decision: "eligible" });
|
|
156
|
+
eligibleRuns += 1;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
// The inventory above is a snapshot; a runtime could claim the lease
|
|
161
|
+
// between listing and deletion. Re-read and delete inside the lease
|
|
162
|
+
// mutation lock so this serializes with RuntimeLease.claim — a plain
|
|
163
|
+
// re-read before rm still leaves a window for a claim to land between
|
|
164
|
+
// the two awaits.
|
|
165
|
+
const deleted = await withRuntimeLeaseMutation(home, run.runId, async () => {
|
|
166
|
+
const recheck = await readRuntimeLease(home, run.runId, {
|
|
167
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
168
|
+
});
|
|
169
|
+
if (recheck.ownership === "active")
|
|
170
|
+
return false;
|
|
171
|
+
await rm(runPaths(home, run.runId).runDir, { recursive: true, force: true });
|
|
172
|
+
return true;
|
|
173
|
+
});
|
|
174
|
+
if (!deleted) {
|
|
175
|
+
decisions.push({ ...base, decision: "kept", reason: "runtime_active" });
|
|
176
|
+
keptRuns += 1;
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
prunedRunIds.add(run.runId);
|
|
180
|
+
decisions.push({ ...base, decision: "pruned" });
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
// Deleting the run directory removes its own fence record, so the
|
|
184
|
+
// lock's post-operation fence check reports RUNTIME_MUTATION_FENCED
|
|
185
|
+
// for runs that ever had a runtime generation. Under the mutation lock
|
|
186
|
+
// nobody else can rotate the fence, so if the directory is gone the
|
|
187
|
+
// mismatch is self-inflicted and the deletion succeeded.
|
|
188
|
+
if (error instanceof CueLineError &&
|
|
189
|
+
error.code === "RUNTIME_MUTATION_FENCED" &&
|
|
190
|
+
(await definitelyMissing(runPaths(home, run.runId).runDir).catch(() => false))) {
|
|
191
|
+
prunedRunIds.add(run.runId);
|
|
192
|
+
decisions.push({ ...base, decision: "pruned" });
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
errors.push({
|
|
196
|
+
runId: run.runId,
|
|
197
|
+
message: error instanceof Error ? error.message : String(error),
|
|
198
|
+
});
|
|
199
|
+
decisions.push({ ...base, decision: "kept", reason: "delete_failed" });
|
|
200
|
+
keptRuns += 1;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const removedJobRecords = await removeJobRecordsForRuns(home, prunedRunIds, errors);
|
|
204
|
+
return {
|
|
205
|
+
home,
|
|
206
|
+
apply,
|
|
207
|
+
olderThanMs: options.olderThanMs,
|
|
208
|
+
cutoff,
|
|
209
|
+
states,
|
|
210
|
+
decisions,
|
|
211
|
+
prunedRuns: prunedRunIds.size,
|
|
212
|
+
eligibleRuns,
|
|
213
|
+
keptRuns,
|
|
214
|
+
removedJobRecords,
|
|
215
|
+
errors,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=api-run-prune.js.map
|