cueline 0.2.2 → 0.3.0
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 +35 -0
- package/README.ja.md +12 -12
- package/README.ko.md +12 -12
- package/README.md +12 -12
- package/README.zh-CN.md +12 -12
- package/README.zh-TW.md +12 -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/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.0",
|
|
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.0",
|
|
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,40 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0 - 2026-07-17
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Operator tooling: `runs prune` retention sweep over terminal runs (dry-run
|
|
8
|
+
by default, deletion serialized with the runtime lease lock), `run
|
|
9
|
+
audit-secrets` masked scan of durable events for secret-shaped strings, and
|
|
10
|
+
`run export` one-file sanitized support bundles.
|
|
11
|
+
- Release engineering: `self-test` offline controller-loop check, `upgrade
|
|
12
|
+
preflight` read-only migration report, `npm run release:check` release
|
|
13
|
+
gate, reproducible pack artifacts with SHA-256 verification, a
|
|
14
|
+
documentation version guard, and a Node 22/24/26 support contract in CI.
|
|
15
|
+
- Machine-output contracts: versioned strict JSON Schemas for `doctor`,
|
|
16
|
+
`routing`, `routing explain`, `runs prune`, `run audit-secrets`, and
|
|
17
|
+
`run export`; contract tests reject added fields, nested injection, empty
|
|
18
|
+
sections, and contradictory shapes.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- Run-scoped commands fail closed for an absent run instead of fabricating a
|
|
23
|
+
healthy view; a sweep pins this for every read and mutating surface.
|
|
24
|
+
- Secret audit reports a secret-shaped object key as a finding and masks it
|
|
25
|
+
in the finding path instead of echoing it verbatim.
|
|
26
|
+
- Prune re-reads runtime ownership inside the lease mutation lock before
|
|
27
|
+
deletion, and only a definite ENOENT counts as a completed removal; any
|
|
28
|
+
other filesystem error keeps the run and records the error.
|
|
29
|
+
|
|
30
|
+
### Verification
|
|
31
|
+
|
|
32
|
+
- Verified TypeScript typecheck, build, 532/532 unit/integration/smoke tests,
|
|
33
|
+
plugin validation, pack dry-run, release:check, offline self-test, and
|
|
34
|
+
upgrade preflight on the unified candidate, cross-reviewed adversarially by
|
|
35
|
+
two independent lines (AJV negative oracle: seven malicious mutations all
|
|
36
|
+
rejected).
|
|
37
|
+
|
|
3
38
|
## 0.2.2 - 2026-07-17
|
|
4
39
|
|
|
5
40
|
### Fixed
|
package/README.ja.md
CHANGED
|
@@ -22,15 +22,15 @@
|
|
|
22
22
|
|
|
23
23
|
CueLine は独立した実装で、**ランタイムの npm 依存はゼロ**です。Omnilane のラッパーではありません。
|
|
24
24
|
|
|
25
|
-
## 最新リリース:0.
|
|
25
|
+
## 最新リリース:0.3.0
|
|
26
26
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
27
|
+
- 運用ツールを追加:終了済み run を掃除する `runs prune`(デフォルトは dry-run、削除は runtime lease ロックと直列化)、永続イベント中の秘密情報らしき文字列をマスク付きで走査する `run audit-secrets`、サニタイズ済みサポートバンドルを 1 ファイルで出力する `run export`。
|
|
28
|
+
- リリースエンジニアリングを追加:オフラインで制御ループを検査する `self-test`、読み取り専用の移行レポート `upgrade preflight`、リリースゲート `release:check`、SHA-256 検証付きの再現可能なパッケージ成果物、ドキュメントバージョンガード、CI 上で証拠に裏付けられた Node サポート契約。
|
|
29
|
+
- すべての読み取り専用 `--json` 出力にバージョン付きの厳格な JSON 契約を公開。契約テストは余分なフィールド、ネストされた注入、空セクション、矛盾した形状を拒否します。
|
|
30
|
+
- fail-closed 挙動を強化:敵対的プロトコルファズコーパス、全 run コマンドの欠損 run 掃引、ENOENT のみを削除完了と数える prune 記帳。
|
|
31
|
+
- 統一候補で 532/532 テストと全リリースゲートを検証し、独立した 2 系統が相互に敵対的レビューを実施しました。
|
|
32
32
|
|
|
33
|
-
詳細は [changelog](CHANGELOG.md#
|
|
33
|
+
詳細は [changelog](CHANGELOG.md#030---2026-07-17) またはバージョン指定の [v0.3.0 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.0) を参照してください。
|
|
34
34
|
|
|
35
35
|
## 1 回の実行は実際にどう進むか
|
|
36
36
|
|
|
@@ -71,15 +71,15 @@ ChatGPT Pro のサブスクリプションと、選択された Pro モデルは
|
|
|
71
71
|
npm レジストリからインストールします。
|
|
72
72
|
|
|
73
73
|
```bash
|
|
74
|
-
npm install -g cueline@0.
|
|
74
|
+
npm install -g cueline@0.3.0
|
|
75
75
|
cueline install
|
|
76
76
|
cueline doctor
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
フォールバックとして、[v0.
|
|
79
|
+
フォールバックとして、[v0.3.0 リリース](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.0) のパッケージ済み tarball をインストールすることもできます。同じリリースに `.sha256` チェックサムも置いてあります。
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.
|
|
82
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.3.0/cueline-0.3.0.tgz
|
|
83
83
|
cueline install
|
|
84
84
|
cueline doctor
|
|
85
85
|
```
|
|
@@ -186,7 +186,7 @@ CLI はブラウザーを駆動しません。状態を書き込むコマンド
|
|
|
186
186
|
|
|
187
187
|
```console
|
|
188
188
|
$ cueline doctor
|
|
189
|
-
CueLine 0.
|
|
189
|
+
CueLine 0.3.0
|
|
190
190
|
status ok
|
|
191
191
|
node 22.14.0 ok
|
|
192
192
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -292,7 +292,7 @@ npm pack --dry-run
|
|
|
292
292
|
|
|
293
293
|
## 開発
|
|
294
294
|
|
|
295
|
-
TypeScript、ESM、Node の組み込みモジュールのみ。`npm run build` は `dist/` へコンパイルし、テストは `node --test` でコンパイル済みの成果物に対して実行します。CI は Ubuntu と macOS 上の Node 22 / 24 を対象とします。
|
|
295
|
+
TypeScript、ESM、Node の組み込みモジュールのみ。`npm run build` は `dist/` へコンパイルし、テストは `node --test` でコンパイル済みの成果物に対して実行します。CI は Ubuntu と macOS 上の Node 22 / 24 / 26 を対象とします。
|
|
296
296
|
|
|
297
297
|
CueLine は独立したプロジェクトであり、OpenAI やその他いかなる企業とも提携しておらず、推奨・後援も受けていません。[provenance](docs/provenance.md) と [third-party notices](THIRD_PARTY_NOTICES.md) を参照してください。
|
|
298
298
|
|
package/README.ko.md
CHANGED
|
@@ -22,15 +22,15 @@
|
|
|
22
22
|
|
|
23
23
|
CueLine은 독립적인 구현이며 **런타임 npm 의존성이 전혀 없습니다**. Omnilane을 감싼 래퍼가 아닙니다.
|
|
24
24
|
|
|
25
|
-
## 최신 릴리스: 0.
|
|
25
|
+
## 최신 릴리스: 0.3.0
|
|
26
26
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
27
|
+
- 운영 도구 추가: 종료된 run을 정리하는 `runs prune`(기본 dry-run, 삭제는 runtime lease 잠금과 직렬화), 영속 이벤트에서 비밀 형태 문자열을 마스킹 방식으로 검사하는 `run audit-secrets`, 정제된 지원 번들을 한 파일로 내보내는 `run export`.
|
|
28
|
+
- 릴리스 엔지니어링 추가: 오프라인 제어 루프 점검 `self-test`, 읽기 전용 마이그레이션 리포트 `upgrade preflight`, 릴리스 게이트 `release:check`, SHA-256 검증이 붙은 재현 가능한 패키지 산출물, 문서 버전 가드, CI에서 증거로 뒷받침되는 Node 지원 계약.
|
|
29
|
+
- 모든 읽기 전용 `--json` 출력에 버전이 붙은 엄격한 JSON 계약을 공개. 계약 테스트는 추가 필드, 중첩 주입, 빈 섹션, 모순된 형태를 거부합니다.
|
|
30
|
+
- fail-closed 동작 강화: 적대적 프로토콜 퍼즈 코퍼스, 전체 run 명령의 누락 run 점검, ENOENT만 삭제 완료로 인정하는 prune 회계.
|
|
31
|
+
- 통합 후보에서 532/532 테스트와 모든 릴리스 게이트를 검증했으며, 독립된 두 라인이 상호 적대적 검토를 수행했습니다.
|
|
32
32
|
|
|
33
|
-
전체 내용은 [changelog](CHANGELOG.md#
|
|
33
|
+
전체 내용은 [changelog](CHANGELOG.md#030---2026-07-17) 또는 버전이 지정된 [v0.3.0 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.0)에서 확인할 수 있습니다.
|
|
34
34
|
|
|
35
35
|
## 실행 한 번은 실제로 이렇게 흘러갑니다
|
|
36
36
|
|
|
@@ -71,15 +71,15 @@ ChatGPT Pro 구독과 선택된 Pro 모델은 서로 다른 것입니다. 계정
|
|
|
71
71
|
npm 레지스트리에서 설치합니다:
|
|
72
72
|
|
|
73
73
|
```bash
|
|
74
|
-
npm install -g cueline@0.
|
|
74
|
+
npm install -g cueline@0.3.0
|
|
75
75
|
cueline install
|
|
76
76
|
cueline doctor
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
대안으로, [v0.
|
|
79
|
+
대안으로, [v0.3.0 릴리스](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.0)의 패키지 tarball을 설치할 수도 있습니다. 같은 릴리스에 `.sha256` 체크섬도 함께 있습니다.
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.
|
|
82
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.3.0/cueline-0.3.0.tgz
|
|
83
83
|
cueline install
|
|
84
84
|
cueline doctor
|
|
85
85
|
```
|
|
@@ -186,7 +186,7 @@ CLI는 브라우저를 구동하지 않습니다. 상태를 쓰는 명령 전에
|
|
|
186
186
|
|
|
187
187
|
```console
|
|
188
188
|
$ cueline doctor
|
|
189
|
-
CueLine 0.
|
|
189
|
+
CueLine 0.3.0
|
|
190
190
|
status ok
|
|
191
191
|
node 22.14.0 ok
|
|
192
192
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -292,7 +292,7 @@ npm pack --dry-run
|
|
|
292
292
|
|
|
293
293
|
## 개발
|
|
294
294
|
|
|
295
|
-
TypeScript, ESM, Node 내장 모듈만 사용합니다. `npm run build`는 `dist/`로 컴파일하고, 테스트는 `node --test`로 컴파일된 결과물을 대상으로 실행합니다. CI는 Ubuntu와 macOS의 Node 22
|
|
295
|
+
TypeScript, ESM, Node 내장 모듈만 사용합니다. `npm run build`는 `dist/`로 컴파일하고, 테스트는 `node --test`로 컴파일된 결과물을 대상으로 실행합니다. CI는 Ubuntu와 macOS의 Node 22, 24, 26을 다룹니다.
|
|
296
296
|
|
|
297
297
|
CueLine은 독립 프로젝트이며 OpenAI를 비롯한 어떤 회사와도 제휴하거나 보증·후원을 받지 않았습니다. [provenance](docs/provenance.md)와 [third-party notices](THIRD_PARTY_NOTICES.md)를 참고하세요.
|
|
298
298
|
|
package/README.md
CHANGED
|
@@ -22,15 +22,15 @@ 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.0
|
|
26
26
|
|
|
27
|
-
- Added
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
- Verified
|
|
27
|
+
- Added operator tooling: `runs prune` retention sweep over terminal runs (dry-run by default, deletion serialized with the runtime lease lock), `run audit-secrets` masked scan of durable events for secret-shaped strings, and `run export` one-file sanitized support bundles.
|
|
28
|
+
- Added release engineering: `self-test` offline controller-loop check, `upgrade preflight` read-only migration report, `release:check` gate, reproducible pack artifacts with SHA-256 verification, a documentation version guard, and an evidence-backed Node support contract in CI.
|
|
29
|
+
- Published versioned strict JSON contracts for every read-only `--json` surface; contract tests reject added fields, nested injection, empty sections, and contradictory shapes.
|
|
30
|
+
- Hardened fail-closed behavior: an adversarial protocol fuzz corpus, a missing-run sweep across all run-scoped commands, and ENOENT-only prune removal accounting.
|
|
31
|
+
- Verified 532/532 tests plus all release gates on the unified candidate, cross-reviewed adversarially by two independent lines.
|
|
32
32
|
|
|
33
|
-
Read the complete [changelog](CHANGELOG.md#
|
|
33
|
+
Read the complete [changelog](CHANGELOG.md#030---2026-07-17) or the versioned [v0.3.0 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.0).
|
|
34
34
|
|
|
35
35
|
## How a run actually goes
|
|
36
36
|
|
|
@@ -73,15 +73,15 @@ You need Node.js 22+, Codex with its built-in Browser, and — for the bundled d
|
|
|
73
73
|
Install from the npm registry:
|
|
74
74
|
|
|
75
75
|
```bash
|
|
76
|
-
npm install -g cueline@0.
|
|
76
|
+
npm install -g cueline@0.3.0
|
|
77
77
|
cueline install
|
|
78
78
|
cueline doctor
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
As a fallback, install the packaged tarball from the [v0.
|
|
81
|
+
As a fallback, install the packaged tarball from the [v0.3.0 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.0), which also carries its `.sha256` checksum:
|
|
82
82
|
|
|
83
83
|
```bash
|
|
84
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.
|
|
84
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.3.0/cueline-0.3.0.tgz
|
|
85
85
|
cueline install
|
|
86
86
|
cueline doctor
|
|
87
87
|
```
|
|
@@ -197,7 +197,7 @@ The CLI does not drive the browser. Run `cueline help` for every positional argu
|
|
|
197
197
|
|
|
198
198
|
```console
|
|
199
199
|
$ cueline doctor
|
|
200
|
-
CueLine 0.
|
|
200
|
+
CueLine 0.3.0
|
|
201
201
|
status ok
|
|
202
202
|
node 22.14.0 ok
|
|
203
203
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -301,7 +301,7 @@ See [compatibility](docs/compatibility.md) for the full matrix.
|
|
|
301
301
|
|
|
302
302
|
## Development
|
|
303
303
|
|
|
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
|
|
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, 24, and 26 on Ubuntu and macOS.
|
|
305
305
|
|
|
306
306
|
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
307
|
|
package/README.zh-CN.md
CHANGED
|
@@ -22,15 +22,15 @@
|
|
|
22
22
|
|
|
23
23
|
CueLine 是独立实现,**没有任何运行时 npm 依赖**,也不是 Omnilane 的包装层。
|
|
24
24
|
|
|
25
|
-
## 最新版本:0.
|
|
25
|
+
## 最新版本:0.3.0
|
|
26
26
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
27
|
+
- 新增运维工具:`runs prune` 清理已结束的 run(默认 dry-run,删除与 runtime lease 锁串行化)、`run audit-secrets` 以掩码方式扫描持久事件中的密钥形字符串、`run export` 一键导出脱敏支持包。
|
|
28
|
+
- 新增发布工程:`self-test` 离线控制环检查、`upgrade preflight` 只读升级体检、`release:check` 发布闸门、可复现打包产物与 SHA-256 校验、文档版本守卫、以及 CI 上以证据背书的 Node 支持契约。
|
|
29
|
+
- 为每个只读 `--json` 输出发布带版本的严格 JSON 契约;契约测试拒绝多余字段、嵌套注入、空区段与矛盾形状。
|
|
30
|
+
- 强化 fail-closed 行为:对抗式协议 fuzz 语料、全 run 命令的缺失 run 扫描、prune 仅认 ENOENT 的删除记账。
|
|
31
|
+
- 统一候选完成 532/532 测试与全部发布闸门,并由两条独立线互相对抗式复验。
|
|
32
32
|
|
|
33
|
-
完整内容请查看 [changelog](CHANGELOG.md#
|
|
33
|
+
完整内容请查看 [changelog](CHANGELOG.md#030---2026-07-17) 或版本化的 [v0.3.0 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.0)。
|
|
34
34
|
|
|
35
35
|
## 一次运行实际是怎么走的
|
|
36
36
|
|
|
@@ -71,15 +71,15 @@ ChatGPT Pro 订阅套餐与“选定的 Pro 模型”是两回事。账号或个
|
|
|
71
71
|
从 npm registry 安装:
|
|
72
72
|
|
|
73
73
|
```bash
|
|
74
|
-
npm install -g cueline@0.
|
|
74
|
+
npm install -g cueline@0.3.0
|
|
75
75
|
cueline install
|
|
76
76
|
cueline doctor
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
作为后备,也可以安装 [v0.
|
|
79
|
+
作为后备,也可以安装 [v0.3.0 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.0) 上的打包 tarball,该 release 同时附带它的 `.sha256` 校验值:
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.
|
|
82
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.3.0/cueline-0.3.0.tgz
|
|
83
83
|
cueline install
|
|
84
84
|
cueline doctor
|
|
85
85
|
```
|
|
@@ -188,7 +188,7 @@ CLI 不驱动浏览器。执行写入状态的命令前,先用 `cueline help`
|
|
|
188
188
|
|
|
189
189
|
```console
|
|
190
190
|
$ cueline doctor
|
|
191
|
-
CueLine 0.
|
|
191
|
+
CueLine 0.3.0
|
|
192
192
|
status ok
|
|
193
193
|
node 22.14.0 ok
|
|
194
194
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -294,7 +294,7 @@ npm pack --dry-run
|
|
|
294
294
|
|
|
295
295
|
## 开发
|
|
296
296
|
|
|
297
|
-
TypeScript、ESM,仅使用 Node 内置模块。`npm run build` 编译到 `dist/`;测试以 `node --test` 运行编译产物。CI 覆盖 Ubuntu 与 macOS 上的 Node 22
|
|
297
|
+
TypeScript、ESM,仅使用 Node 内置模块。`npm run build` 编译到 `dist/`;测试以 `node --test` 运行编译产物。CI 覆盖 Ubuntu 与 macOS 上的 Node 22、24、26。
|
|
298
298
|
|
|
299
299
|
CueLine 是独立项目,与 OpenAI 或任何其他公司均无隶属关系,也未获其背书或赞助。见 [provenance](docs/provenance.md) 与 [third-party notices](THIRD_PARTY_NOTICES.md)。
|
|
300
300
|
|
package/README.zh-TW.md
CHANGED
|
@@ -22,15 +22,15 @@
|
|
|
22
22
|
|
|
23
23
|
CueLine 是獨立實作,**沒有任何 runtime npm 相依套件**,也不是 Omnilane 的包裝層。
|
|
24
24
|
|
|
25
|
-
## 最新版本:0.
|
|
25
|
+
## 最新版本:0.3.0
|
|
26
26
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
27
|
+
- 新增操作面工具:`runs prune` 清掃已結束的 run(預設 dry-run,刪除與 runtime lease 鎖序列化)、`run audit-secrets` 以遮罩方式掃描持久事件中的密鑰形字串、`run export` 一鍵匯出去敏支援包。
|
|
28
|
+
- 新增發佈工程:`self-test` 離線控制迴圈檢查、`upgrade preflight` 唯讀升級體檢、`release:check` 發佈閘門、可重現打包產物與 SHA-256 驗證、文件版本守衛、以及 CI 上以證據背書的 Node 支援契約。
|
|
29
|
+
- 為每個唯讀 `--json` 面發佈帶版本的嚴格 JSON 契約;契約測試會拒絕多餘欄位、巢狀注入、空區段與矛盾形狀。
|
|
30
|
+
- 強化 fail-closed 行為:對抗式協定 fuzz 火力網、全 run-scoped 指令的缺失 run 掃描、prune 只認 ENOENT 的刪除記帳。
|
|
31
|
+
- 統一候選完成 532/532 測試與全部發佈閘門,並由兩條獨立線互相對抗式複驗。
|
|
32
32
|
|
|
33
|
-
完整內容請看 [changelog](CHANGELOG.md#
|
|
33
|
+
完整內容請看 [changelog](CHANGELOG.md#030---2026-07-17) 或版本化的 [v0.3.0 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.0)。
|
|
34
34
|
|
|
35
35
|
## 一次執行實際上怎麼跑
|
|
36
36
|
|
|
@@ -71,15 +71,15 @@ ChatGPT Pro 訂閱方案與「選定的 Pro 模型」是兩回事。帳號或個
|
|
|
71
71
|
從 npm registry 安裝:
|
|
72
72
|
|
|
73
73
|
```bash
|
|
74
|
-
npm install -g cueline@0.
|
|
74
|
+
npm install -g cueline@0.3.0
|
|
75
75
|
cueline install
|
|
76
76
|
cueline doctor
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
作為備援,也可以安裝 [v0.
|
|
79
|
+
作為備援,也可以安裝 [v0.3.0 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.3.0) 上的打包 tarball,該 release 同時附上它的 `.sha256` 校驗碼:
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.
|
|
82
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.3.0/cueline-0.3.0.tgz
|
|
83
83
|
cueline install
|
|
84
84
|
cueline doctor
|
|
85
85
|
```
|
|
@@ -197,7 +197,7 @@ CLI 不驅動瀏覽器。執行寫入狀態的命令前,先用 `cueline help`
|
|
|
197
197
|
|
|
198
198
|
```console
|
|
199
199
|
$ cueline doctor
|
|
200
|
-
CueLine 0.
|
|
200
|
+
CueLine 0.3.0
|
|
201
201
|
status ok
|
|
202
202
|
node 22.14.0 ok
|
|
203
203
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -303,7 +303,7 @@ npm pack --dry-run
|
|
|
303
303
|
|
|
304
304
|
## 開發
|
|
305
305
|
|
|
306
|
-
TypeScript、ESM,只用 Node 內建模組。`npm run build` 會編譯到 `dist/`;測試以 `node --test` 跑編譯後的產物。CI 涵蓋 Ubuntu 與 macOS 上的 Node 22
|
|
306
|
+
TypeScript、ESM,只用 Node 內建模組。`npm run build` 會編譯到 `dist/`;測試以 `node --test` 跑編譯後的產物。CI 涵蓋 Ubuntu 與 macOS 上的 Node 22、24、26。
|
|
307
307
|
|
|
308
308
|
CueLine 是獨立專案,與 OpenAI 或任何其他公司皆無隸屬關係,亦未獲其背書或贊助。見 [provenance](docs/provenance.md) 與 [third-party notices](THIRD_PARTY_NOTICES.md)。
|
|
309
309
|
|
|
@@ -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
|