lossless-openclaw-orchestrator 1.2.2 → 1.2.3
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/README.md +2 -2
- package/VISION.md +4 -4
- package/dist/packages/cli/src/release-preflight.js +59 -18
- package/docs/BETA_RELEASE_RUNBOOK.md +1 -1
- package/docs/CLAIM_AUDIT.md +2 -2
- package/docs/RELEASE_NOTES_1.2.3.md +84 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +9 -1
- package/packages/cli/src/release-preflight.ts +65 -16
- package/packages/openclaw-plugin/openclaw.plugin.json +1 -1
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ safe action without rereading raw transcripts.
|
|
|
23
23
|
| Approval-gated boundaries | Dry-run Codex actions and verify matching audit ids before any live control. |
|
|
24
24
|
| OpenClaw/MCP tools | Use the same local-first recall and approval-bounded surfaces from agent workflows. |
|
|
25
25
|
|
|
26
|
-
[Setup](docs/SETUP.md) · [Contributing](CONTRIBUTING.md) · [Agent Instructions](AGENTS.md) · [Agent Skill](skills/lossless-openclaw-orchestrator/SKILL.md) · [OpenClaw Plugin](docs/OPENCLAW_PLUGIN.md) · [Security](SECURITY.md) · [Code of Conduct](CODE_OF_CONDUCT.md) · [Vision](VISION.md) · [Privacy](docs/PRIVACY.md) · [Claude Boundary](docs/CLAUDE_ADAPTER_BOUNDARY.md) · [Claim Audit](docs/CLAIM_AUDIT.md) · [Release Notes](docs/RELEASE_NOTES_1.2.2.md) · [1.2.1 Notes](docs/RELEASE_NOTES_1.2.1.md) · [1.2.0 Notes](docs/RELEASE_NOTES_1.2.0.md) · [1.1.4 Notes](docs/RELEASE_NOTES_1.1.4.md) · [1.0 Notes](docs/RELEASE_NOTES_1.0.0.md) · [License](LICENSE)
|
|
26
|
+
[Setup](docs/SETUP.md) · [Contributing](CONTRIBUTING.md) · [Agent Instructions](AGENTS.md) · [Agent Skill](skills/lossless-openclaw-orchestrator/SKILL.md) · [OpenClaw Plugin](docs/OPENCLAW_PLUGIN.md) · [Security](SECURITY.md) · [Code of Conduct](CODE_OF_CONDUCT.md) · [Vision](VISION.md) · [Privacy](docs/PRIVACY.md) · [Claude Boundary](docs/CLAUDE_ADAPTER_BOUNDARY.md) · [Claim Audit](docs/CLAIM_AUDIT.md) · [Release Notes](docs/RELEASE_NOTES_1.2.3.md) · [1.2.2 Notes](docs/RELEASE_NOTES_1.2.2.md) · [1.2.1 Notes](docs/RELEASE_NOTES_1.2.1.md) · [1.2.0 Notes](docs/RELEASE_NOTES_1.2.0.md) · [1.1.4 Notes](docs/RELEASE_NOTES_1.1.4.md) · [1.0 Notes](docs/RELEASE_NOTES_1.0.0.md) · [License](LICENSE)
|
|
27
27
|
|
|
28
28
|
## Why It Matters
|
|
29
29
|
|
|
@@ -325,7 +325,7 @@ The stable public product is Codex-first local orchestration: index, search,
|
|
|
325
325
|
describe, expand, prepared-state recall, OpenClaw/MCP tools, and
|
|
326
326
|
approval-gated dry-run/control boundaries.
|
|
327
327
|
|
|
328
|
-
The 1.2 prepared-state and summary-leaves lane is shipped in stable `1.2.
|
|
328
|
+
The 1.2 prepared-state and summary-leaves lane is shipped in stable `1.2.3`.
|
|
329
329
|
Current launch work is the M11 GA assurance sprint, tracked in GitHub and
|
|
330
330
|
summarized in [VISION.md](VISION.md). Keep sprint and agent-operator details
|
|
331
331
|
there, in [AGENTS.md](AGENTS.md), and in the packaged
|
package/VISION.md
CHANGED
|
@@ -12,11 +12,11 @@ The stable product should feel like a local orchestration cockpit: OpenClaw can
|
|
|
12
12
|
|
|
13
13
|
The current release-readiness lane is Milestone 11: LCO 1.2.0 GA Assurance And Global Launch Readiness. GitHub tracker [#478](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/478) and children [#479](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/479)-[#493](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/493) own implementation truth; this file owns the product and eval boundary.
|
|
14
14
|
|
|
15
|
-
The stable 1.0.0, 1.1.0, 1.1.1, 1.1.2, 1.1.3, 1.1.4, 1.2.0, 1.2.1, and 1.2.
|
|
15
|
+
The stable 1.0.0, 1.1.0, 1.1.1, 1.1.2, 1.1.3, 1.1.4, 1.2.0, 1.2.1, 1.2.2, and 1.2.3 packages have shipped on npm `latest` and their GitHub Releases are published. The post-GA Desktop claim-validation lane [#306](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/306) records that Desktop-visible classification and fallback readiness/status are proven, while actual Codex GUI mutation remains excluded. Desktop parity [#307](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/307) added the coherence classifier; desktop fallback [#308](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/308) added the CUA-first and Peekaboo-secondary readiness report. The 1.1 collaboration cockpit [#309](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/309) is completed proof for read-only collaboration summaries and execute-false next steps, not the current active child-work list.
|
|
16
16
|
|
|
17
17
|
The Codex Autonomy Cockpit [#254](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/254) and Eva Operating Picture [#255](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/255) P0 lanes are completed beta foundation, not the current active child-work list. Completed P0 children include shared contracts [#256](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/256), source authority [#258](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/258), watcher/resume requests [#259](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/259), visible Codex map joins [#260](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/260), deterministic GitHub operating inputs [#264](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/264)/[#265](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/265), current-lane source balancing [#269](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/269), GitHub check-state fidelity [#270](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/270), cockpit card cleanup [#271](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/271), and end-to-end Eva cockpit dogfood [#272](https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues/272). The sprint brief remains the historical handoff for that P0 work: [docs/sprints/brief-lco-codex-autonomy-cockpit-sprint-2026-07-01.md](docs/sprints/brief-lco-codex-autonomy-cockpit-sprint-2026-07-01.md).
|
|
18
18
|
|
|
19
|
-
The core Codex recall, M9 handoff paths, Codex Autonomy Cockpit, Eva Operating Picture P0 paths, 1.1 Desktop collaboration cockpit paths, 1.2 prepared-state and summary-leaf paths, release metadata, package/gateway setup proof, docs truth, release gates, public-safe scorecards, post-publish fresh npm `@latest` install proof, and stable publication lanes are no longer the main product gap. The current gap is no-bug-left-behind launch assurance: prove the published `1.2.
|
|
19
|
+
The core Codex recall, M9 handoff paths, Codex Autonomy Cockpit, Eva Operating Picture P0 paths, 1.1 Desktop collaboration cockpit paths, 1.2 prepared-state and summary-leaf paths, release metadata, package/gateway setup proof, docs truth, release gates, public-safe scorecards, post-publish fresh npm `@latest` install proof, and stable publication lanes are no longer the main product gap. The current gap is no-bug-left-behind launch assurance: prove the published `1.2.3` package is installable, discoverable, public-safe, and honest for global users before broad rollout.
|
|
20
20
|
|
|
21
21
|
The current target is:
|
|
22
22
|
|
|
@@ -38,7 +38,7 @@ The current target is:
|
|
|
38
38
|
- Keep P1 source adapters, including Notion, support-control, Company Brain, Stripe, dashboard/export, and model summarization, behind separate adapters and proof gates; P0 tools report those sources as `not_configured` instead of fabricating summaries.
|
|
39
39
|
- Use the [source authority profile](docs/SOURCE_AUTHORITY_PROFILE.md) to distinguish "this source returned data" from "this source owns the current truth"; unavailable or cache-only sources must degrade claims to `unknown` or low confidence.
|
|
40
40
|
|
|
41
|
-
The sprint remains Codex-first, local-first, read-only-first, and public-safe by default. It does not claim full business truth, customer readiness, Claude Code parity, remote sync, generic GUI mutation, unattended desktop control, permission bypass, or enterprise/customer-ready security. npm `latest` promotion and GitHub Release creation are complete for 1.2.
|
|
41
|
+
The sprint remains Codex-first, local-first, read-only-first, and public-safe by default. It does not claim full business truth, customer readiness, Claude Code parity, remote sync, generic GUI mutation, unattended desktop control, permission bypass, or enterprise/customer-ready security. npm `latest` promotion and GitHub Release creation are complete for 1.2.3. Desktop-visible classification and fallback readiness/status are proven by #307/#308; actual Codex GUI mutation remains excluded until a future action-bound proof gate records the exact backend, target, action hash, approval, and observation.
|
|
42
42
|
|
|
43
43
|
What 1.2 should let a local OpenClaw agent do next:
|
|
44
44
|
|
|
@@ -294,7 +294,7 @@ Release candidates follow [docs/BETA_RELEASE_RUNBOOK.md](docs/BETA_RELEASE_RUNBO
|
|
|
294
294
|
|
|
295
295
|
## Proof Boundary
|
|
296
296
|
|
|
297
|
-
Allowed stable 1.2.
|
|
297
|
+
Allowed stable 1.2.3 claim:
|
|
298
298
|
|
|
299
299
|
> Collaborate with local Codex sessions through OpenClaw using local indexing, prepared-state recall, bounded expansion, and approval-gated dry-run/control boundaries.
|
|
300
300
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
-
import {
|
|
3
|
+
import { dirname, extname, join, relative, resolve, sep } from "node:path";
|
|
4
4
|
import { excludedClaimsForScope, liveControlExcludedDetail, normalizeReleaseClaimScope, releaseClaimScopeRequiresLiveControl, releaseClaimScopeRequiresWorkingAppRuntimeProof } from "./release-claim-scope.js";
|
|
5
5
|
import { validateWorkingAppRuntimeProof } from "./runtime-proof-gate.js";
|
|
6
|
+
const EVIDENCE_SCAN_MAX_DEPTH = 40;
|
|
6
7
|
const forbiddenClaims = [
|
|
7
8
|
"Full Claude Code parity",
|
|
8
9
|
"cloud sync",
|
|
@@ -68,14 +69,18 @@ export function runReleasePreflight(options = {}) {
|
|
|
68
69
|
const workingAppRuntimeProof = workingAppRuntimeProofRequired
|
|
69
70
|
? validateWorkingAppRuntimeProof(options.runtimeProofDir)
|
|
70
71
|
: null;
|
|
71
|
-
const
|
|
72
|
+
const evidenceScan = scanEvidenceArtifacts(options.evidenceDir);
|
|
73
|
+
const rawSessionArtifacts = evidenceScan.rawSessionArtifacts;
|
|
74
|
+
const evidenceScanDepthExceeded = evidenceScan.depthLimitExceeded;
|
|
72
75
|
const checks = {
|
|
73
76
|
packageJson: check(Boolean(!packageJsonRead.error && packageJson?.name && packageJson.version && packageJson.description?.match(/local Codex sessions/i)), packageJsonRead.error ?? "package metadata keeps Codex-first beta positioning"),
|
|
74
77
|
readme: check(Boolean(readme && readmePublicDocsRequiredPatterns.every((pattern) => pattern.test(readme))), "README includes public setup path, OpenClaw/MCP entrypoints, safety boundaries, and forbidden claims"),
|
|
75
78
|
openclawManifest: check(Boolean(!openclawManifestRead.error && openclawPackageMetadataOk && openclawManifest?.id === "lossless-openclaw-orchestrator" && openclawManifest.mcp?.command === "loo-mcp-server" && openclawManifest.mcp.transport === "stdio" && openclawManifest.tools?.prefix === "loo_" && openclawManifest.safety?.localOnlyByDefault === true), openclawManifestRead.error ?? "root OpenClaw manifest and package runtime entry are packageable and local-only by default"),
|
|
76
79
|
claimAudit: check(Boolean(claimAudit?.match(/Forbidden Beta Claims/i) && claimAudit.match(/approved_live_control_smoke_missing/i)), "claim audit records forbidden claims and the live-control blocker code"),
|
|
77
80
|
betaDemo: check(Boolean(betaDemo?.match(/100\+ local Codex sessions/i) && betaDemo.match(/does not run live control/i)), "demo workflow covers 100+ Codex sessions and dry-run-only control boundary"),
|
|
78
|
-
rawArtifacts: check(rawSessionArtifacts.length === 0
|
|
81
|
+
rawArtifacts: check(rawSessionArtifacts.length === 0 && evidenceScanDepthExceeded.length === 0, rawSessionArtifacts.length === 0 && evidenceScanDepthExceeded.length === 0
|
|
82
|
+
? "no raw session/private DB/screenshot artifacts found"
|
|
83
|
+
: "raw artifacts or unsafe evidence tree shape are present"),
|
|
79
84
|
liveControlSmoke: liveControlProof,
|
|
80
85
|
workingAppRuntimeProof: workingAppRuntimeProof
|
|
81
86
|
? check(workingAppRuntimeProof.ok, workingAppRuntimeProof.ok
|
|
@@ -88,6 +93,8 @@ export function runReleasePreflight(options = {}) {
|
|
|
88
93
|
.map(([key]) => `${key}_failed`);
|
|
89
94
|
if (rawSessionArtifacts.length > 0)
|
|
90
95
|
blockers.push("raw_session_artifacts_present");
|
|
96
|
+
if (evidenceScanDepthExceeded.length > 0)
|
|
97
|
+
blockers.push("evidence_scan_depth_exceeded");
|
|
91
98
|
if (liveControlRequired && !checks.liveControlSmoke?.ok)
|
|
92
99
|
blockers.push("approved_live_control_smoke_missing");
|
|
93
100
|
if (workingAppRuntimeProofRequired && workingAppRuntimeProof && !workingAppRuntimeProof.ok) {
|
|
@@ -105,7 +112,8 @@ export function runReleasePreflight(options = {}) {
|
|
|
105
112
|
checks,
|
|
106
113
|
blockers,
|
|
107
114
|
forbiddenClaims,
|
|
108
|
-
rawSessionArtifacts
|
|
115
|
+
rawSessionArtifacts,
|
|
116
|
+
evidenceScanDepthExceeded
|
|
109
117
|
};
|
|
110
118
|
if (report.artifactManifestPath) {
|
|
111
119
|
mkdirSync(options.evidenceDir, { recursive: true });
|
|
@@ -190,27 +198,60 @@ function findPackageRoot(start) {
|
|
|
190
198
|
cursor = parent;
|
|
191
199
|
}
|
|
192
200
|
}
|
|
193
|
-
function
|
|
194
|
-
if (!evidenceDir || !existsSync(evidenceDir))
|
|
195
|
-
return [];
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
+
function scanEvidenceArtifacts(evidenceDir) {
|
|
202
|
+
if (!evidenceDir || !existsSync(evidenceDir)) {
|
|
203
|
+
return { rawSessionArtifacts: [], depthLimitExceeded: [] };
|
|
204
|
+
}
|
|
205
|
+
const root = resolve(evidenceDir);
|
|
206
|
+
const rawSessionArtifacts = [];
|
|
207
|
+
const depthLimitExceeded = [];
|
|
208
|
+
const visit = (dir, depth) => {
|
|
209
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
210
|
+
const absolutePath = join(dir, entry.name);
|
|
211
|
+
const relativePath = normalizePackagePath(relative(root, absolutePath));
|
|
212
|
+
if (entry.isSymbolicLink())
|
|
213
|
+
continue;
|
|
214
|
+
if (entry.isDirectory()) {
|
|
215
|
+
if (depth >= EVIDENCE_SCAN_MAX_DEPTH) {
|
|
216
|
+
depthLimitExceeded.push(relativePath);
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
visit(absolutePath, depth + 1);
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
if (!entry.isFile())
|
|
223
|
+
continue;
|
|
224
|
+
const artifact = rawArtifactForName(relativePath);
|
|
225
|
+
if (artifact)
|
|
226
|
+
rawSessionArtifacts.push(artifact);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
visit(root, 0);
|
|
230
|
+
return {
|
|
231
|
+
rawSessionArtifacts: rawSessionArtifacts
|
|
232
|
+
.filter((entry) => entry !== null)
|
|
233
|
+
.sort((left, right) => left.name.localeCompare(right.name)),
|
|
234
|
+
depthLimitExceeded: depthLimitExceeded.sort((left, right) => left.localeCompare(right))
|
|
235
|
+
};
|
|
201
236
|
}
|
|
202
237
|
function rawArtifactForName(name) {
|
|
203
238
|
if (name === "release-preflight.json")
|
|
204
239
|
return null;
|
|
205
|
-
const
|
|
240
|
+
const normalizedName = normalizePackagePath(name);
|
|
241
|
+
const extension = extname(normalizedName).toLowerCase();
|
|
242
|
+
const lowerName = normalizedName.toLowerCase();
|
|
206
243
|
if (extension === ".jsonl")
|
|
207
|
-
return { name:
|
|
208
|
-
if (extension === ".sqlite" || extension === ".sqlite3" || extension === ".db"
|
|
209
|
-
|
|
244
|
+
return { name: normalizedName, reason: "raw_codex_jsonl" };
|
|
245
|
+
if (extension === ".sqlite" || extension === ".sqlite3" || extension === ".db"
|
|
246
|
+
|| lowerName.endsWith(".sqlite-wal") || lowerName.endsWith(".sqlite-shm")
|
|
247
|
+
|| lowerName.endsWith(".sqlite3-wal") || lowerName.endsWith(".sqlite3-shm")
|
|
248
|
+
|| lowerName.endsWith(".db-wal") || lowerName.endsWith(".db-shm")) {
|
|
249
|
+
return { name: normalizedName, reason: "sqlite_database" };
|
|
250
|
+
}
|
|
210
251
|
if (extension === ".png" || extension === ".jpg" || extension === ".jpeg" || extension === ".heic" || extension === ".webp")
|
|
211
|
-
return { name:
|
|
252
|
+
return { name: normalizedName, reason: "screenshot_or_image" };
|
|
212
253
|
if (extension === ".mov" || extension === ".mp4" || extension === ".webm")
|
|
213
|
-
return { name:
|
|
254
|
+
return { name: normalizedName, reason: "video_capture" };
|
|
214
255
|
return null;
|
|
215
256
|
}
|
|
216
257
|
function validateApprovedLiveControlProof(path) {
|
|
@@ -384,7 +384,7 @@ Record `npm dist-tag ls lossless-openclaw-orchestrator` in the release evidence
|
|
|
384
384
|
after every npm publication. Stable releases publish with
|
|
385
385
|
`npm publish --tag latest`; public betas publish with `npm publish --tag beta`;
|
|
386
386
|
release candidates publish with `npm publish --tag next`. The stable channel
|
|
387
|
-
currently points at `1.2.
|
|
387
|
+
currently points at `1.2.3`; future stable releases move `latest` only after the
|
|
388
388
|
separate stable-promotion gate proves the exact candidate. Keep beta and other
|
|
389
389
|
prereleases on prerelease tags. Do not publish a fake stable package just to
|
|
390
390
|
move a dist-tag. Release candidates must publish with `npm publish --tag next`;
|
package/docs/CLAIM_AUDIT.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Public Claim Audit
|
|
2
2
|
|
|
3
|
-
## Allowed Stable 1.2.
|
|
3
|
+
## Allowed Stable 1.2.3 Claim
|
|
4
4
|
|
|
5
5
|
Collaborate with local Codex sessions through OpenClaw using local indexing, prepared-state recall, bounded expansion, and approval-gated dry-run/control boundaries.
|
|
6
6
|
|
|
@@ -75,7 +75,7 @@ blockers instead of allowing a working-app claim.
|
|
|
75
75
|
|
|
76
76
|
Install stable releases through the `latest` dist-tag, public betas through the
|
|
77
77
|
`beta` dist-tag, and release candidates through `next`. The stable channel
|
|
78
|
-
currently points at `1.2.
|
|
78
|
+
currently points at `1.2.3`; future stable releases move `latest` only after the
|
|
79
79
|
separate stable-promotion gate proves the exact candidate. Keep beta and other
|
|
80
80
|
prereleases on prerelease tags. Do not publish a fake stable package just to
|
|
81
81
|
move a dist-tag.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Release Notes 1.2.3
|
|
2
|
+
|
|
3
|
+
`1.2.3` is the GA-assurance hygiene patch for the LCO 1.2 stable train and Codex-first local orchestration. It fixes the recursive release-evidence scan gap found during M11 adversarial review and keeps the 1.2 claim boundary unchanged.
|
|
4
|
+
|
|
5
|
+
This release is focused on local Codex sessions. Prepared state remains an advisory local derived cache, not source authority for PR, CI, release, runtime, customer, or business truth.
|
|
6
|
+
|
|
7
|
+
## What Changed
|
|
8
|
+
|
|
9
|
+
- Fixes `loo release preflight` raw-artifact detection so it scans nested evidence folders instead of only immediate files in `--evidence-dir`.
|
|
10
|
+
- Adds recursive detection for SQLite sidecars such as `.sqlite-wal`, `.sqlite-shm`, `.sqlite3-wal`, `.sqlite3-shm`, `.db-wal`, and `.db-shm`.
|
|
11
|
+
- Skips symlinked evidence entries and reports `evidence_scan_depth_exceeded`
|
|
12
|
+
when an evidence tree is too deep to scan deterministically.
|
|
13
|
+
- Keeps raw artifact findings public-safe by reporting relative evidence names and blocker reasons, not raw artifact contents.
|
|
14
|
+
- Sanitizes the M11 final evidence packet by removing generated clean-profile runtime HOME/prefix artifacts while preserving public-safe summary reports.
|
|
15
|
+
- Carries forward the 1.2.2 readiness-smoke semantics clarification: `ok` / `packagePathOk` are package-path claims, while `publishedSmokeReady` is the clean-profile gateway-ready claim.
|
|
16
|
+
- Carries forward `--gateway-ready-strict` so operators and CI can explicitly fail when a fresh published profile still needs gateway credentials or device setup.
|
|
17
|
+
- Carries forward the hardened `loo release general-readiness` proof-boundary label so an unexpected package version string cannot inject uncontrolled text into the public proof boundary.
|
|
18
|
+
- Carries forward the frozen `readinessSemantics` metadata object emitted by `published-smoke`, keeping machine-readable exit semantics stable for release scripts and audits.
|
|
19
|
+
- Carries forward the 1.2.1 facade smoke fix for resume dry-run proof, including the distinction between resume packets and message-carrying send/steer packets.
|
|
20
|
+
- Carries forward the #160 desktop proof-action release boundary:
|
|
21
|
+
`loo_desktop_proof_action` / `loo desktop proof-action` validates the
|
|
22
|
+
CUA Driver TextEdit scratch proof gate and does not prove generic GUI
|
|
23
|
+
mutation.
|
|
24
|
+
The proof action still requires exact backend, target app, target window, action hash, approval ref, permission state, scratch file path, and `execute: true` before the backend can run.
|
|
25
|
+
Generic gateway invocation without exact proof args fails closed. The desktop
|
|
26
|
+
proof action keeps the same proof boundary as beta.35.
|
|
27
|
+
- Carries forward strict OpenClaw gateway result handling: plugin output with
|
|
28
|
+
`output.details.ok: false` is reported as
|
|
29
|
+
`openclaw_tool_result_not_ok:<tool>` rather than successful tool proof.
|
|
30
|
+
|
|
31
|
+
## Current Claim Scope
|
|
32
|
+
|
|
33
|
+
Allowed stable claim:
|
|
34
|
+
|
|
35
|
+
> Collaborate with local Codex sessions through OpenClaw using local indexing,
|
|
36
|
+
> prepared-state recall, bounded expansion, and approval-gated dry-run/control
|
|
37
|
+
> boundaries.
|
|
38
|
+
|
|
39
|
+
The stable channel means the scoped prepared-state and cockpit-management
|
|
40
|
+
surface is ready as a public local-Codex release. It does not broaden the
|
|
41
|
+
control, GUI, Claude, customer, or enterprise-security proof boundary.
|
|
42
|
+
|
|
43
|
+
## Release Gate Notes
|
|
44
|
+
|
|
45
|
+
- Parent 1.2 tracker: #405.
|
|
46
|
+
- GA assurance tracker: #478.
|
|
47
|
+
- Hygiene patch issue: #506.
|
|
48
|
+
- Previous patch-release issue: #503.
|
|
49
|
+
- Readiness-semantics issue: #494.
|
|
50
|
+
- Patch PRs: #499, #505, and the 1.2.3 release PR.
|
|
51
|
+
- Baseline stable release: `v1.2.2`.
|
|
52
|
+
- Candidate package: `lossless-openclaw-orchestrator@1.2.3`.
|
|
53
|
+
- Expected npm dist-tag: `latest`.
|
|
54
|
+
- Expected git tag: `v1.2.3`.
|
|
55
|
+
- Required stable gates: focused release-smoke tests, release claim audit,
|
|
56
|
+
build/typecheck, `npm pack --dry-run`, release bundle/status checks, GitHub
|
|
57
|
+
CI, CodeQL, current-head review threads clear, npm publish to `latest`,
|
|
58
|
+
GitHub Release, and post-publish finalization status.
|
|
59
|
+
- Bundle/status/finalization dry-run checks do not publish to npm and will not create a GitHub Release.
|
|
60
|
+
- Working-app status example:
|
|
61
|
+
`loo release status --claim-scope codex-working-app-proof --runtime-proof-dir <path> --approved-live-control-evidence <path> --npm-publish-approval-evidence <path> --github-release-approval-evidence <path> --candidate-sha <sha> --github-ci-evidence <path> --codeql-evidence <path> --evidence-dir <path> --strict`
|
|
62
|
+
- Reduced-scope status example:
|
|
63
|
+
`loo release status --claim-scope codex-read-search-expand-dry-run --npm-publish-approval-evidence <path> --github-release-approval-evidence <path> --candidate-sha <sha> --github-ci-evidence <path> --codeql-evidence <path> --evidence-dir <path> --strict`
|
|
64
|
+
- `approved_live_control_smoke_missing` remains the expected blocker when a
|
|
65
|
+
working-app or live-control claim is attempted without approved live-control
|
|
66
|
+
smoke evidence for the exact candidate SHA.
|
|
67
|
+
|
|
68
|
+
## Explicit Non-Claims
|
|
69
|
+
|
|
70
|
+
No new live Codex control smoke is run by this release.
|
|
71
|
+
It does not run generic GUI mutation and does not run Codex GUI mutation.
|
|
72
|
+
No automatic gateway authorization.
|
|
73
|
+
No broad gateway scope approval. No prompt typing. No clicking. No arbitrary app control.
|
|
74
|
+
No screenshots or videos are part of the public release evidence.
|
|
75
|
+
Claude Code remains an adapter stub, not an adapter-equivalence claim.
|
|
76
|
+
No true Codex compaction-summary capture.
|
|
77
|
+
No raw model compaction by default and no default model access to raw transcript
|
|
78
|
+
or current `safe_text`.
|
|
79
|
+
No raw transcript upload and no OpenClaw LCM merge.
|
|
80
|
+
No source-store mutation.
|
|
81
|
+
No Notion, support-control, Stripe, or Company Brain P1 adapter proof.
|
|
82
|
+
No cloud sync.
|
|
83
|
+
No unattended desktop takeover.
|
|
84
|
+
No release-grade enterprise security or customer-ready security claim.
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "lossless-openclaw-orchestrator",
|
|
3
3
|
"name": "Lossless OpenClaw Orchestrator",
|
|
4
4
|
"description": "Collaborate with local Codex sessions through OpenClaw using local indexing, prepared-state recall, bounded expansion, and approval-gated dry-run/control boundaries.",
|
|
5
|
-
"version": "1.2.
|
|
5
|
+
"version": "1.2.3",
|
|
6
6
|
"kind": "tool",
|
|
7
7
|
"tools": {
|
|
8
8
|
"prefix": "loo_"
|
package/package.json
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lossless-openclaw-orchestrator",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "Index, search, and prepare local Codex sessions for OpenClaw with approval-gated dry-run/control boundaries.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
7
7
|
"private": false,
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/100yenadmin/Lossless-Codex-Orchestrator-LCO/issues"
|
|
15
|
+
},
|
|
8
16
|
"publishConfig": {
|
|
9
17
|
"tag": "latest"
|
|
10
18
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
-
import {
|
|
3
|
+
import { dirname, extname, join, relative, resolve, sep } from "node:path";
|
|
4
4
|
import {
|
|
5
5
|
excludedClaimsForScope,
|
|
6
6
|
liveControlExcludedDetail,
|
|
@@ -39,6 +39,7 @@ export type ReleasePreflightReport = {
|
|
|
39
39
|
blockers: string[];
|
|
40
40
|
forbiddenClaims: string[];
|
|
41
41
|
rawSessionArtifacts: RawSessionArtifact[];
|
|
42
|
+
evidenceScanDepthExceeded: string[];
|
|
42
43
|
};
|
|
43
44
|
|
|
44
45
|
type ApprovedLiveControlSmokeProof = {
|
|
@@ -57,11 +58,18 @@ type RawSessionArtifact = {
|
|
|
57
58
|
reason: "raw_codex_jsonl" | "sqlite_database" | "screenshot_or_image" | "video_capture";
|
|
58
59
|
};
|
|
59
60
|
|
|
61
|
+
type EvidenceScanResult = {
|
|
62
|
+
rawSessionArtifacts: RawSessionArtifact[];
|
|
63
|
+
depthLimitExceeded: string[];
|
|
64
|
+
};
|
|
65
|
+
|
|
60
66
|
type JsonReadResult = {
|
|
61
67
|
value: unknown | null;
|
|
62
68
|
error: string | null;
|
|
63
69
|
};
|
|
64
70
|
|
|
71
|
+
const EVIDENCE_SCAN_MAX_DEPTH = 40;
|
|
72
|
+
|
|
65
73
|
const forbiddenClaims = [
|
|
66
74
|
"Full Claude Code parity",
|
|
67
75
|
"cloud sync",
|
|
@@ -148,14 +156,21 @@ export function runReleasePreflight(options: ReleasePreflightOptions = {}): Rele
|
|
|
148
156
|
const workingAppRuntimeProof = workingAppRuntimeProofRequired
|
|
149
157
|
? validateWorkingAppRuntimeProof(options.runtimeProofDir)
|
|
150
158
|
: null;
|
|
151
|
-
const
|
|
159
|
+
const evidenceScan = scanEvidenceArtifacts(options.evidenceDir);
|
|
160
|
+
const rawSessionArtifacts = evidenceScan.rawSessionArtifacts;
|
|
161
|
+
const evidenceScanDepthExceeded = evidenceScan.depthLimitExceeded;
|
|
152
162
|
const checks: Record<string, ReleasePreflightCheck> = {
|
|
153
163
|
packageJson: check(Boolean(!packageJsonRead.error && packageJson?.name && packageJson.version && packageJson.description?.match(/local Codex sessions/i)), packageJsonRead.error ?? "package metadata keeps Codex-first beta positioning"),
|
|
154
164
|
readme: check(Boolean(readme && readmePublicDocsRequiredPatterns.every((pattern) => pattern.test(readme))), "README includes public setup path, OpenClaw/MCP entrypoints, safety boundaries, and forbidden claims"),
|
|
155
165
|
openclawManifest: check(Boolean(!openclawManifestRead.error && openclawPackageMetadataOk && openclawManifest?.id === "lossless-openclaw-orchestrator" && openclawManifest.mcp?.command === "loo-mcp-server" && openclawManifest.mcp.transport === "stdio" && openclawManifest.tools?.prefix === "loo_" && openclawManifest.safety?.localOnlyByDefault === true), openclawManifestRead.error ?? "root OpenClaw manifest and package runtime entry are packageable and local-only by default"),
|
|
156
166
|
claimAudit: check(Boolean(claimAudit?.match(/Forbidden Beta Claims/i) && claimAudit.match(/approved_live_control_smoke_missing/i)), "claim audit records forbidden claims and the live-control blocker code"),
|
|
157
167
|
betaDemo: check(Boolean(betaDemo?.match(/100\+ local Codex sessions/i) && betaDemo.match(/does not run live control/i)), "demo workflow covers 100+ Codex sessions and dry-run-only control boundary"),
|
|
158
|
-
rawArtifacts: check(
|
|
168
|
+
rawArtifacts: check(
|
|
169
|
+
rawSessionArtifacts.length === 0 && evidenceScanDepthExceeded.length === 0,
|
|
170
|
+
rawSessionArtifacts.length === 0 && evidenceScanDepthExceeded.length === 0
|
|
171
|
+
? "no raw session/private DB/screenshot artifacts found"
|
|
172
|
+
: "raw artifacts or unsafe evidence tree shape are present"
|
|
173
|
+
),
|
|
159
174
|
liveControlSmoke: liveControlProof,
|
|
160
175
|
workingAppRuntimeProof: workingAppRuntimeProof
|
|
161
176
|
? check(
|
|
@@ -171,6 +186,7 @@ export function runReleasePreflight(options: ReleasePreflightOptions = {}): Rele
|
|
|
171
186
|
.filter(([key, value]) => !value.ok && key !== "liveControlSmoke" && key !== "rawArtifacts" && key !== "workingAppRuntimeProof")
|
|
172
187
|
.map(([key]) => `${key}_failed`);
|
|
173
188
|
if (rawSessionArtifacts.length > 0) blockers.push("raw_session_artifacts_present");
|
|
189
|
+
if (evidenceScanDepthExceeded.length > 0) blockers.push("evidence_scan_depth_exceeded");
|
|
174
190
|
if (liveControlRequired && !checks.liveControlSmoke?.ok) blockers.push("approved_live_control_smoke_missing");
|
|
175
191
|
if (workingAppRuntimeProofRequired && workingAppRuntimeProof && !workingAppRuntimeProof.ok) {
|
|
176
192
|
blockers.push(...workingAppRuntimeProof.blockers);
|
|
@@ -188,7 +204,8 @@ export function runReleasePreflight(options: ReleasePreflightOptions = {}): Rele
|
|
|
188
204
|
checks,
|
|
189
205
|
blockers,
|
|
190
206
|
forbiddenClaims,
|
|
191
|
-
rawSessionArtifacts
|
|
207
|
+
rawSessionArtifacts,
|
|
208
|
+
evidenceScanDepthExceeded
|
|
192
209
|
};
|
|
193
210
|
|
|
194
211
|
if (report.artifactManifestPath) {
|
|
@@ -272,22 +289,54 @@ function findPackageRoot(start: string): string | null {
|
|
|
272
289
|
}
|
|
273
290
|
}
|
|
274
291
|
|
|
275
|
-
function
|
|
276
|
-
if (!evidenceDir || !existsSync(evidenceDir))
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
292
|
+
function scanEvidenceArtifacts(evidenceDir: string | undefined): EvidenceScanResult {
|
|
293
|
+
if (!evidenceDir || !existsSync(evidenceDir)) {
|
|
294
|
+
return { rawSessionArtifacts: [], depthLimitExceeded: [] };
|
|
295
|
+
}
|
|
296
|
+
const root = resolve(evidenceDir);
|
|
297
|
+
const rawSessionArtifacts: RawSessionArtifact[] = [];
|
|
298
|
+
const depthLimitExceeded: string[] = [];
|
|
299
|
+
const visit = (dir: string, depth: number): void => {
|
|
300
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
301
|
+
const absolutePath = join(dir, entry.name);
|
|
302
|
+
const relativePath = normalizePackagePath(relative(root, absolutePath));
|
|
303
|
+
if (entry.isSymbolicLink()) continue;
|
|
304
|
+
if (entry.isDirectory()) {
|
|
305
|
+
if (depth >= EVIDENCE_SCAN_MAX_DEPTH) {
|
|
306
|
+
depthLimitExceeded.push(relativePath);
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
visit(absolutePath, depth + 1);
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
if (!entry.isFile()) continue;
|
|
313
|
+
const artifact = rawArtifactForName(relativePath);
|
|
314
|
+
if (artifact) rawSessionArtifacts.push(artifact);
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
visit(root, 0);
|
|
318
|
+
return {
|
|
319
|
+
rawSessionArtifacts: rawSessionArtifacts
|
|
320
|
+
.filter((entry) => entry !== null)
|
|
321
|
+
.sort((left, right) => left.name.localeCompare(right.name)),
|
|
322
|
+
depthLimitExceeded: depthLimitExceeded.sort((left, right) => left.localeCompare(right))
|
|
323
|
+
};
|
|
282
324
|
}
|
|
283
325
|
|
|
284
326
|
function rawArtifactForName(name: string): RawSessionArtifact | null {
|
|
285
327
|
if (name === "release-preflight.json") return null;
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
if (extension === ".
|
|
290
|
-
if (extension === ".
|
|
328
|
+
const normalizedName = normalizePackagePath(name);
|
|
329
|
+
const extension = extname(normalizedName).toLowerCase();
|
|
330
|
+
const lowerName = normalizedName.toLowerCase();
|
|
331
|
+
if (extension === ".jsonl") return { name: normalizedName, reason: "raw_codex_jsonl" };
|
|
332
|
+
if (extension === ".sqlite" || extension === ".sqlite3" || extension === ".db"
|
|
333
|
+
|| lowerName.endsWith(".sqlite-wal") || lowerName.endsWith(".sqlite-shm")
|
|
334
|
+
|| lowerName.endsWith(".sqlite3-wal") || lowerName.endsWith(".sqlite3-shm")
|
|
335
|
+
|| lowerName.endsWith(".db-wal") || lowerName.endsWith(".db-shm")) {
|
|
336
|
+
return { name: normalizedName, reason: "sqlite_database" };
|
|
337
|
+
}
|
|
338
|
+
if (extension === ".png" || extension === ".jpg" || extension === ".jpeg" || extension === ".heic" || extension === ".webp") return { name: normalizedName, reason: "screenshot_or_image" };
|
|
339
|
+
if (extension === ".mov" || extension === ".mp4" || extension === ".webm") return { name: normalizedName, reason: "video_capture" };
|
|
291
340
|
return null;
|
|
292
341
|
}
|
|
293
342
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "lossless-openclaw-orchestrator",
|
|
3
3
|
"name": "Lossless OpenClaw Orchestrator",
|
|
4
4
|
"description": "Collaborate with local Codex sessions through OpenClaw using local indexing, prepared-state recall, bounded expansion, and approval-gated dry-run/control boundaries.",
|
|
5
|
-
"version": "1.2.
|
|
5
|
+
"version": "1.2.3",
|
|
6
6
|
"kind": "tool",
|
|
7
7
|
"tools": {
|
|
8
8
|
"prefix": "loo_"
|