lossless-openclaw-orchestrator 1.2.1 → 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 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.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.1`.
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, and 1.2.1 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.
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.1` package is installable, discoverable, public-safe, and honest for global users before broad rollout.
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.1. 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.
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
 
@@ -82,13 +82,13 @@ What a local OpenClaw agent can do today:
82
82
  - Inspect `authorityCoverage` on operating-picture outputs before trusting GitHub, PLAN_STATE, or future P1 source claims.
83
83
  - Classify package and gateway readiness with `loo onboard status`, `loo openclaw dogfood`, `loo openclaw tool-smoke`, and `loo openclaw published-smoke`.
84
84
  - Follow the packaged agent skill and M9 dogfood scenario to produce a public-safe recommendation from source refs, bounded expansion, detail lookups, and dry-run audit hashes.
85
- - Use `loo release general-readiness --strict` to decide whether fresh npm install, clean-profile OpenClaw load, and agent dogfood evidence are enough for a 1.0 claim.
85
+ - Use `loo release general-readiness --strict` to decide whether fresh npm install, clean-profile OpenClaw load, clean-profile gateway readiness, and agent dogfood evidence are enough for a stable/general release claim.
86
86
 
87
87
  ## Completed Proof: Working App Runtime
88
88
 
89
- Completed proof from M7/M9 remains part of the evidence base. Milestone 7 and the [Working App Proof Sprint](docs/WORKING_APP_PROOF_SPRINT.md) moved LCO beyond reduced-scope dry-run claims by proving installed OpenClaw gateway paths, live `loo_*` calls through the same surface an OpenClaw agent uses, approved live Codex action proof where explicitly claimed, post-action refresh reasoning, action-bound desktop collaboration proof gates, connected local search UI contracts, runtime proof gates, and Claude Code adapter inventory boundaries. M9 added the agent handoff lane, first-class OpenClaw agent usage skill, docs truth pass, agent dogfood scenario, fresh npm clean-profile smoke, and 1.0 readiness gate.
89
+ Completed proof from M7/M9 remains part of the evidence base. Milestone 7 and the [Working App Proof Sprint](docs/WORKING_APP_PROOF_SPRINT.md) moved LCO beyond reduced-scope dry-run claims by proving installed OpenClaw gateway paths, live `loo_*` calls through the same surface an OpenClaw agent uses, approved live Codex action proof where explicitly claimed, post-action refresh reasoning, action-bound desktop collaboration proof gates, connected local search UI contracts, runtime proof gates, and Claude Code adapter inventory boundaries. M9 added the agent handoff lane, first-class OpenClaw agent usage skill, docs truth pass, agent dogfood scenario, fresh npm clean-profile smoke, and general-release readiness gate.
90
90
 
91
- Completed proof does not mean 1.0 or broad automation parity. Generic GUI mutation, Codex GUI mutation, Claude Code parity, cloud sync, unattended takeover, and release-grade enterprise security remain excluded until separate issues and evidence prove them.
91
+ Completed proof does not mean broad automation parity. Generic GUI mutation, Codex GUI mutation, Claude Code parity, cloud sync, unattended takeover, and release-grade enterprise security remain excluded until separate issues and evidence prove them.
92
92
 
93
93
  ## Primary User Stories
94
94
 
@@ -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.1 claim:
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
 
@@ -23,6 +23,7 @@ export function createGeneralReleaseReadiness(options) {
23
23
  const packageVersion = readString(packageJson, "version");
24
24
  const expectedDistTag = distTagForVersion(packageVersion ?? "");
25
25
  const expectedPackage = packageName ? `${packageName}@${expectedDistTag}` : null;
26
+ const releaseLabel = formatReleaseLabel(expectedPackage, packageVersion);
26
27
  const freshNpmEvidence = resolveEvidencePath(evidenceDir, options.freshNpmEvidence);
27
28
  const agentDogfoodEvidence = resolveEvidencePath(evidenceDir, options.agentDogfoodEvidence);
28
29
  const checks = {
@@ -56,10 +57,10 @@ export function createGeneralReleaseReadiness(options) {
56
57
  liveCodexControlRun: false,
57
58
  desktopGuiActionRun: false
58
59
  },
59
- proofBoundary: "This gate defines and validates 1.0 general-release readiness evidence; it does not publish 1.0, move npm latest, create a GitHub Release, run live Codex control, mutate a GUI, claim Claude parity, or claim enterprise/customer-ready security.",
60
+ proofBoundary: `This gate defines and validates general-release readiness evidence for ${releaseLabel}; it does not publish npm, move npm dist-tags, create a GitHub Release, run live Codex control, mutate a GUI, claim Claude parity, or claim enterprise/customer-ready security.`,
60
61
  nextAction: blockers.length === 0
61
- ? "Use this packet as one input to a separate explicit stable release issue before any npm latest promotion or GitHub Release."
62
- : "Produce the missing public-safe evidence or update docs before treating 1.0 as ready."
62
+ ? "Use this packet as one input to a separate explicit stable release issue before any npm dist-tag promotion or GitHub Release."
63
+ : "Produce the missing public-safe evidence or update docs before treating this release candidate as generally ready."
63
64
  };
64
65
  writeFileSync(readinessManifestPath, `${JSON.stringify(report, null, 2)}\n`);
65
66
  return report;
@@ -101,8 +102,7 @@ function validateDocsTruth(rootDir) {
101
102
  return check(Boolean(surfaces.every((content) => content
102
103
  && /loo release general-readiness/i.test(content)
103
104
  && /fresh npm/i.test(content)
104
- && /agent dogfood/i.test(content)
105
- && /1\.0/i.test(content))), "README, VISION, and release runbook point to the 1.0 general-readiness gate");
105
+ && /agent dogfood/i.test(content))), "README, VISION, and release runbook point to the general-readiness gate");
106
106
  }
107
107
  function validateFreshNpmEvidence(path, expected) {
108
108
  if (!path || !existsSync(path)) {
@@ -230,6 +230,14 @@ function readString(input, key) {
230
230
  const value = input[key];
231
231
  return typeof value === "string" ? value : null;
232
232
  }
233
+ function formatReleaseLabel(expectedPackage, packageVersion) {
234
+ if (!expectedPackage || !packageVersion)
235
+ return "the current package release";
236
+ const safePackageVersion = /^[0-9A-Za-z.+-]{1,80}$/.test(packageVersion)
237
+ ? packageVersion
238
+ : "untrusted-version";
239
+ return `${expectedPackage} (${safePackageVersion})`;
240
+ }
233
241
  function readNestedString(input, path) {
234
242
  const value = readNested(input, path);
235
243
  return typeof value === "string" ? value : null;
@@ -401,6 +401,8 @@ async function main() {
401
401
  console.log(JSON.stringify(report, null, 2));
402
402
  if (parsed.strict && !report.ok)
403
403
  process.exitCode = 1;
404
+ if (parsed.gatewayReadyStrict && !report.publishedSmokeReady)
405
+ process.exitCode = 1;
404
406
  return;
405
407
  }
406
408
  if (command === "openclaw" && args[0] === "live-control-smoke") {
@@ -1169,7 +1171,7 @@ function printGeneralReleaseReadinessHelp() {
1169
1171
  "Usage:",
1170
1172
  " loo release general-readiness --evidence-dir path [--fresh-npm-evidence path] [--agent-dogfood-evidence path] [--now iso] [--strict]",
1171
1173
  "",
1172
- "Writes a public-safe 1.0 general-release readiness packet without performing release actions.",
1174
+ "Writes a public-safe general-release readiness packet for the current package version without performing release actions.",
1173
1175
  "",
1174
1176
  "Required evidence:",
1175
1177
  " --fresh-npm-evidence points to a public-safe `loo openclaw published-smoke` report with clean-profile gateway status ready.",
@@ -1179,19 +1181,26 @@ function printGeneralReleaseReadinessHelp() {
1179
1181
  " --strict exits non-zero until docs, skill/playbook, M9 scenarios, fresh npm proof, and agent dogfood proof are complete.",
1180
1182
  "",
1181
1183
  "Safety boundary:",
1182
- " The command does not publish npm, does not move npm latest, does not create a GitHub Release, does not run live Codex control, and does not perform desktop GUI mutation."
1184
+ " The command does not publish npm, does not move npm dist-tags, does not create a GitHub Release, does not run live Codex control, and does not perform desktop GUI mutation."
1183
1185
  ].join("\n"));
1184
1186
  }
1185
1187
  function printOpenClawPublishedSmokeHelp() {
1186
1188
  console.log([
1187
1189
  "Usage:",
1188
- " loo openclaw published-smoke --evidence-dir path --dogfood-report path --tool-smoke-report path [--configured-tool-smoke-report path] [--npm-install-diagnostic-report path] [--registry-version version] [--registry-beta-version version] [--root path] [--now iso] [--strict]",
1190
+ " loo openclaw published-smoke --evidence-dir path --dogfood-report path --tool-smoke-report path [--configured-tool-smoke-report path] [--npm-install-diagnostic-report path] [--registry-version version] [--registry-beta-version version] [--root path] [--now iso] [--strict] [--gateway-ready-strict]",
1189
1191
  "",
1190
- "Writes a public-safe summary of the published npm beta install path and gateway setup state.",
1192
+ "Writes a public-safe summary of the published npm package path for the expected dist-tag and gateway setup state.",
1191
1193
  "",
1192
1194
  "This command consumes sanitized reports from `loo openclaw dogfood` and `loo openclaw tool-smoke`.",
1193
1195
  "Optional `--configured-tool-smoke-report` records a separately named configured-profile gateway proof without marking the fresh published profile ready.",
1194
1196
  "Optional `--npm-install-diagnostic-report` records public-safe npm selector drift and tarball fallback proof without storing raw npm output.",
1197
+ "",
1198
+ "Strict mode:",
1199
+ " --strict exits non-zero only when ok/packagePathOk is false; it is package-path strict.",
1200
+ " --gateway-ready-strict exits non-zero unless publishedSmokeReady is true for the clean published profile.",
1201
+ " With both flags, any failed package-path or clean-profile gateway-ready condition exits non-zero.",
1202
+ " A configured gateway proof is recorded separately and never substitutes for fresh-profile gateway readiness.",
1203
+ "",
1195
1204
  "It does not run npm install, does not call OpenClaw, does not run live Codex control, and does not mutate a desktop GUI."
1196
1205
  ].join("\n"));
1197
1206
  }
@@ -2205,7 +2214,7 @@ function parseOpenClawToolSmokeArgs(input) {
2205
2214
  return parsed;
2206
2215
  }
2207
2216
  function parseOpenClawPublishedSmokeArgs(input) {
2208
- const parsed = { strict: false };
2217
+ const parsed = { strict: false, gatewayReadyStrict: false };
2209
2218
  for (let index = 0; index < input.length; index += 1) {
2210
2219
  const arg = input[index];
2211
2220
  if (arg === "--evidence-dir") {
@@ -2238,6 +2247,9 @@ function parseOpenClawPublishedSmokeArgs(input) {
2238
2247
  else if (arg === "--strict") {
2239
2248
  parsed.strict = true;
2240
2249
  }
2250
+ else if (arg === "--gateway-ready-strict") {
2251
+ parsed.gatewayReadyStrict = true;
2252
+ }
2241
2253
  else {
2242
2254
  throw new Error(`Unknown openclaw published-smoke option: ${arg}`);
2243
2255
  }
@@ -2256,7 +2268,8 @@ function parseOpenClawPublishedSmokeArgs(input) {
2256
2268
  toolSmokeReportPath: parsed.toolSmokeReportPath,
2257
2269
  configuredToolSmokeReportPath: parsed.configuredToolSmokeReportPath,
2258
2270
  npmInstallDiagnosticReportPath: parsed.npmInstallDiagnosticReportPath,
2259
- strict: parsed.strict
2271
+ strict: parsed.strict,
2272
+ gatewayReadyStrict: parsed.gatewayReadyStrict
2260
2273
  };
2261
2274
  }
2262
2275
  function parseOpenClawLiveControlSmokeArgs(input) {
@@ -2,6 +2,13 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import { dirname, join, resolve } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { PACKAGE_NAME, distTagForVersion, matchingRegistryStatus, mismatchedRegistryStatus } from "./dist-tag.js";
5
+ const READINESS_SEMANTICS = Object.freeze({
6
+ okField: "packagePathOk",
7
+ strictModeExitsOn: "packagePathOk_false",
8
+ gatewayReadyStrictExitsOn: "publishedSmokeReady_false",
9
+ cleanProfileGatewayReadyField: "publishedSmokeReady",
10
+ configuredGatewayProofSeparate: true
11
+ });
5
12
  export function createPublishedPackageSmokeReport(options) {
6
13
  const rootDir = options.rootDir
7
14
  ? resolve(options.rootDir)
@@ -69,6 +76,7 @@ export function createPublishedPackageSmokeReport(options) {
69
76
  ok: packagePathOk,
70
77
  publishedSmokeReady: packagePathOk && toolSmokeReady,
71
78
  packagePathOk,
79
+ readinessSemantics: READINESS_SEMANTICS,
72
80
  publicSafe: true,
73
81
  localOnly: true,
74
82
  dryRun: true,
@@ -118,7 +126,7 @@ export function createPublishedPackageSmokeReport(options) {
118
126
  "tokens, credentials, API keys, cookies",
119
127
  "private customer data"
120
128
  ],
121
- proofBoundary: `This published package smoke report summarizes public-safe ${expectedDistTag} install and gateway setup evidence only; it does not run live Codex control, mutate a desktop GUI, publish npm, create a GitHub Release, store raw npm output, or store raw OpenClaw gateway output.`
129
+ proofBoundary: `This published package smoke report summarizes public-safe ${expectedDistTag} install and gateway setup evidence only. ok/packagePathOk are package-path claims; publishedSmokeReady is the clean-profile gateway-ready claim. This command does not run live Codex control, mutate a desktop GUI, publish npm, create a GitHub Release, store raw npm output, or store raw OpenClaw gateway output.`
122
130
  };
123
131
  if (options.evidenceDir)
124
132
  writePublishedPackageSmokeReport(report, options.evidenceDir);
@@ -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 { basename, dirname, extname, join, resolve, sep } from "node:path";
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 rawSessionArtifacts = scanRawSessionArtifacts(options.evidenceDir);
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, rawSessionArtifacts.length === 0 ? "no raw session/private DB/screenshot artifacts found" : "raw session/private DB/screenshot artifacts are present"),
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 scanRawSessionArtifacts(evidenceDir) {
194
- if (!evidenceDir || !existsSync(evidenceDir))
195
- return [];
196
- return readdirSync(evidenceDir, { withFileTypes: true })
197
- .filter((entry) => entry.isFile())
198
- .map((entry) => rawArtifactForName(entry.name))
199
- .filter((entry) => entry !== null)
200
- .sort((left, right) => left.name.localeCompare(right.name));
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 extension = extname(name).toLowerCase();
240
+ const normalizedName = normalizePackagePath(name);
241
+ const extension = extname(normalizedName).toLowerCase();
242
+ const lowerName = normalizedName.toLowerCase();
206
243
  if (extension === ".jsonl")
207
- return { name: basename(name), reason: "raw_codex_jsonl" };
208
- if (extension === ".sqlite" || extension === ".sqlite3" || extension === ".db")
209
- return { name: basename(name), reason: "sqlite_database" };
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: basename(name), reason: "screenshot_or_image" };
252
+ return { name: normalizedName, reason: "screenshot_or_image" };
212
253
  if (extension === ".mov" || extension === ".mp4" || extension === ".webm")
213
- return { name: basename(name), reason: "video_capture" };
254
+ return { name: normalizedName, reason: "video_capture" };
214
255
  return null;
215
256
  }
216
257
  function validateApprovedLiveControlProof(path) {
@@ -321,10 +321,11 @@ A release candidate may be announced internally when all of these are true:
321
321
  - no public artifact contains raw Codex JSONL, local SQLite databases, raw
322
322
  prompts, screenshots, credentials, tokens, or private transcripts
323
323
 
324
- ## 1.0 General Readiness Gate
324
+ ## Stable General Readiness Gate
325
325
 
326
- The beta train can publish scoped prereleases without claiming 1.0. A 1.0
327
- candidate must also pass the deeper [Release Checklist](RELEASE_CHECKLIST.md).
326
+ The beta train can publish scoped prereleases without claiming stable/general
327
+ readiness. A stable candidate must also pass the deeper
328
+ [Release Checklist](RELEASE_CHECKLIST.md).
328
329
  Run candidate gates before publication, then run fresh npm `@latest` and agent
329
330
  dogfood evidence after publication before closing the stable issue. The
330
331
  user-facing post-publish command is `loo release general-readiness`; the
@@ -338,13 +339,14 @@ node ./dist/packages/cli/src/index.js release general-readiness \
338
339
  --strict
339
340
  ```
340
341
 
341
- This post-publish gate is intentionally stricter than a beta first-run classifier:
342
- `gateway_setup_required` can be acceptable beta onboarding evidence, but it is
343
- not enough for 1.0. The stable gate requires a fresh npm install, clean-profile
344
- OpenClaw load, agent dogfood through gateway tools, and docs truth. If resume,
345
- steer, or interrupt have not passed live proof on disposable threads, the
346
- release copy must exclude broad live control and name only the proven live send
347
- path.
342
+ This post-publish gate is intentionally stricter than a beta first-run
343
+ classifier: `gateway_setup_required` can be acceptable beta onboarding evidence,
344
+ but it is not enough for a stable/general readiness claim. The stable gate
345
+ requires a fresh npm install, clean-profile OpenClaw load, clean-profile gateway
346
+ tool-smoke readiness, agent dogfood through gateway tools, and docs truth. If
347
+ resume, steer, or interrupt have not passed live proof on disposable threads,
348
+ the release copy must exclude broad live control and name only the proven live
349
+ send path.
348
350
 
349
351
  ## Publication Approval Gates
350
352
 
@@ -382,7 +384,7 @@ Record `npm dist-tag ls lossless-openclaw-orchestrator` in the release evidence
382
384
  after every npm publication. Stable releases publish with
383
385
  `npm publish --tag latest`; public betas publish with `npm publish --tag beta`;
384
386
  release candidates publish with `npm publish --tag next`. The stable channel
385
- currently points at `1.2.1`; future stable releases move `latest` only after the
387
+ currently points at `1.2.3`; future stable releases move `latest` only after the
386
388
  separate stable-promotion gate proves the exact candidate. Keep beta and other
387
389
  prereleases on prerelease tags. Do not publish a fake stable package just to
388
390
  move a dist-tag. Release candidates must publish with `npm publish --tag next`;
@@ -1,6 +1,6 @@
1
1
  # Public Claim Audit
2
2
 
3
- ## Allowed Stable 1.2.1 Claim
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.1`; future stable releases move `latest` only after the
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.
@@ -52,9 +52,9 @@ Every beta, RC, and stable release must have public-safe evidence for:
52
52
  - GitHub issue/tracker updates with evidence path and proof boundary
53
53
  - no open PRs or release-blocking issues for the claimed tier
54
54
 
55
- ## 1.0 General Release
55
+ ## Stable General Release
56
56
 
57
- For 1.0, the release must additionally prove:
57
+ For a stable/general release, the release must additionally prove:
58
58
 
59
59
  - fresh npm stable install from the registry, not a linked repo checkout or a
60
60
  beta/RC substitute
@@ -63,8 +63,8 @@ For 1.0, the release must additionally prove:
63
63
  - if fresh-profile gateway credentials are missing, published-smoke evidence
64
64
  must classify the blocker as setup-required and show token generation,
65
65
  env-ref onboarding, gateway status, and fresh-profile tool-smoke commands
66
- without storing raw tokens; this remains a 1.0 blocker until tool-smoke is
67
- actually ready
66
+ without storing raw tokens; this remains a stable-readiness blocker until
67
+ clean-profile tool-smoke is actually ready
68
68
  - first-class agent skill/playbook is packaged and current
69
69
  - agent dogfood completes the core workflow through gateway tools:
70
70
  doctor, search, describe, expand, plan/final/touched-file lookup, recommend,
@@ -75,8 +75,8 @@ For 1.0, the release must additionally prove:
75
75
  - live control claims name the exact control matrix that passed
76
76
 
77
77
  If resume, steer, or interrupt have not passed live proof on disposable threads,
78
- the 1.0 claim must exclude broad live control and say only the proven live send
79
- path is available.
78
+ the stable/general release claim must exclude broad live control and say only the
79
+ proven live send path is available.
80
80
 
81
81
  ## npm Dist-Tag Boundary
82
82
 
@@ -0,0 +1,94 @@
1
+ # Release Notes 1.2.2
2
+
3
+ `1.2.2` is a patch release for the LCO 1.2 stable train and Codex-first local orchestration.
4
+ It publishes the readiness-smoke semantics clarification from
5
+ #494 / #499 to the npm `latest` channel without widening the 1.2 claim
6
+ boundary.
7
+
8
+ This release is focused on local Codex sessions. Prepared state remains an
9
+ advisory local derived cache, not source authority for PR, CI, release,
10
+ runtime, customer, or business truth.
11
+
12
+ ## What Changed
13
+
14
+ - Clarifies `loo openclaw published-smoke` strictness semantics:
15
+ `ok` / `packagePathOk` are package-path claims, while
16
+ `publishedSmokeReady` is the clean-profile gateway-ready claim.
17
+ - Adds `--gateway-ready-strict` so operators and CI can explicitly fail when a
18
+ fresh published profile still needs gateway credentials or device setup.
19
+ - Documents the combined `--strict` plus `--gateway-ready-strict` behavior:
20
+ either a package-path failure or clean-profile gateway-readiness failure exits
21
+ non-zero.
22
+ - Hardens the public `loo release general-readiness` proof-boundary label so an
23
+ unexpected package version string cannot inject uncontrolled text into the
24
+ public proof boundary.
25
+ - Freezes the `readinessSemantics` metadata object emitted by
26
+ `published-smoke`, keeping machine-readable exit semantics stable for
27
+ release scripts and audits.
28
+ - Carries forward the 1.2.1 facade smoke fix for resume dry-run proof, including
29
+ the distinction between resume packets and message-carrying send/steer
30
+ packets.
31
+ - Carries forward the #160 desktop proof-action release boundary:
32
+ `loo_desktop_proof_action` / `loo desktop proof-action` validates the
33
+ CUA Driver TextEdit scratch proof gate and does not prove generic GUI
34
+ mutation.
35
+ 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.
36
+ Generic gateway invocation without exact proof args fails closed. The desktop
37
+ proof action keeps the same proof boundary as beta.35.
38
+ - Carries forward strict OpenClaw gateway result handling: plugin output with
39
+ `output.details.ok: false` is reported as
40
+ `openclaw_tool_result_not_ok:<tool>` rather than successful tool proof.
41
+
42
+ ## Current Claim Scope
43
+
44
+ Allowed stable claim:
45
+
46
+ > Collaborate with local Codex sessions through OpenClaw using local indexing,
47
+ > prepared-state recall, bounded expansion, and approval-gated dry-run/control
48
+ > boundaries.
49
+
50
+ The stable channel means the scoped prepared-state and cockpit-management
51
+ surface is ready as a public local-Codex release. It does not broaden the
52
+ control, GUI, Claude, customer, or enterprise-security proof boundary.
53
+
54
+ ## Release Gate Notes
55
+
56
+ - Parent 1.2 tracker: #405.
57
+ - GA assurance tracker: #478.
58
+ - Patch-release issue: #503.
59
+ - Readiness-semantics issue: #494.
60
+ - Patch PRs: #499 and the 1.2.2 release PR.
61
+ - Baseline stable release: `v1.2.1`.
62
+ - Candidate package: `lossless-openclaw-orchestrator@1.2.2`.
63
+ - Expected npm dist-tag: `latest`.
64
+ - Expected git tag: `v1.2.2`.
65
+ - Required stable gates: focused release-smoke tests, release claim audit,
66
+ build/typecheck, `npm pack --dry-run`, release bundle/status checks, GitHub
67
+ CI, CodeQL, current-head review threads clear, npm publish to `latest`,
68
+ GitHub Release, and post-publish finalization status.
69
+ - Bundle/status/finalization dry-run checks do not publish to npm and will not create a GitHub Release.
70
+ - Working-app status example:
71
+ `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`
72
+ - Reduced-scope status example:
73
+ `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`
74
+ - `approved_live_control_smoke_missing` remains the expected blocker when a
75
+ working-app or live-control claim is attempted without approved live-control
76
+ smoke evidence for the exact candidate SHA.
77
+
78
+ ## Explicit Non-Claims
79
+
80
+ No new live Codex control smoke is run by this release.
81
+ It does not run generic GUI mutation and does not run Codex GUI mutation.
82
+ No automatic gateway authorization.
83
+ No broad gateway scope approval. No prompt typing. No clicking. No arbitrary app control.
84
+ No screenshots or videos are part of the public release evidence.
85
+ Claude Code remains an adapter stub, not an adapter-equivalence claim.
86
+ No true Codex compaction-summary capture.
87
+ No raw model compaction by default and no default model access to raw transcript
88
+ or current `safe_text`.
89
+ No raw transcript upload and no OpenClaw LCM merge.
90
+ No source-store mutation.
91
+ No Notion, support-control, Stripe, or Company Brain P1 adapter proof.
92
+ No cloud sync.
93
+ No unattended desktop takeover.
94
+ No release-grade enterprise security or customer-ready security claim.
@@ -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/docs/SETUP.md CHANGED
@@ -396,6 +396,10 @@ OpenClaw plugin installs but tools are missing
396
396
  OpenClaw gateway tool smoke reports credential or device blockers
397
397
 
398
398
  - Treat this as first-run gateway setup, not a package failure.
399
+ - In `loo openclaw published-smoke`, `ok`/`packagePathOk` prove package-path
400
+ health only. `publishedSmokeReady` is the clean-profile gateway-ready claim.
401
+ - A configured gateway proof is useful local evidence, but it does not satisfy
402
+ fresh-profile gateway readiness.
399
403
  - Use the recovery commands returned by `loo openclaw published-smoke` or
400
404
  `loo openclaw tool-smoke`.
401
405
 
@@ -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.1",
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.1",
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
  },
@@ -74,6 +74,7 @@ export function createGeneralReleaseReadiness(options: GeneralReleaseReadinessOp
74
74
  const packageVersion = readString(packageJson, "version");
75
75
  const expectedDistTag = distTagForVersion(packageVersion ?? "");
76
76
  const expectedPackage = packageName ? `${packageName}@${expectedDistTag}` : null;
77
+ const releaseLabel = formatReleaseLabel(expectedPackage, packageVersion);
77
78
  const freshNpmEvidence = resolveEvidencePath(evidenceDir, options.freshNpmEvidence);
78
79
  const agentDogfoodEvidence = resolveEvidencePath(evidenceDir, options.agentDogfoodEvidence);
79
80
  const checks: Record<string, GeneralReleaseReadinessCheck> = {
@@ -107,10 +108,10 @@ export function createGeneralReleaseReadiness(options: GeneralReleaseReadinessOp
107
108
  liveCodexControlRun: false,
108
109
  desktopGuiActionRun: false
109
110
  },
110
- proofBoundary: "This gate defines and validates 1.0 general-release readiness evidence; it does not publish 1.0, move npm latest, create a GitHub Release, run live Codex control, mutate a GUI, claim Claude parity, or claim enterprise/customer-ready security.",
111
+ proofBoundary: `This gate defines and validates general-release readiness evidence for ${releaseLabel}; it does not publish npm, move npm dist-tags, create a GitHub Release, run live Codex control, mutate a GUI, claim Claude parity, or claim enterprise/customer-ready security.`,
111
112
  nextAction: blockers.length === 0
112
- ? "Use this packet as one input to a separate explicit stable release issue before any npm latest promotion or GitHub Release."
113
- : "Produce the missing public-safe evidence or update docs before treating 1.0 as ready."
113
+ ? "Use this packet as one input to a separate explicit stable release issue before any npm dist-tag promotion or GitHub Release."
114
+ : "Produce the missing public-safe evidence or update docs before treating this release candidate as generally ready."
114
115
  };
115
116
  writeFileSync(readinessManifestPath, `${JSON.stringify(report, null, 2)}\n`);
116
117
  return report;
@@ -163,9 +164,8 @@ function validateDocsTruth(rootDir: string): GeneralReleaseReadinessCheck {
163
164
  surfaces.every((content) => content
164
165
  && /loo release general-readiness/i.test(content)
165
166
  && /fresh npm/i.test(content)
166
- && /agent dogfood/i.test(content)
167
- && /1\.0/i.test(content))
168
- ), "README, VISION, and release runbook point to the 1.0 general-readiness gate");
167
+ && /agent dogfood/i.test(content))
168
+ ), "README, VISION, and release runbook point to the general-readiness gate");
169
169
  }
170
170
 
171
171
  function validateFreshNpmEvidence(
@@ -327,6 +327,14 @@ function readString(input: JsonObject, key: string): string | null {
327
327
  return typeof value === "string" ? value : null;
328
328
  }
329
329
 
330
+ function formatReleaseLabel(expectedPackage: string | null, packageVersion: string | null): string {
331
+ if (!expectedPackage || !packageVersion) return "the current package release";
332
+ const safePackageVersion = /^[0-9A-Za-z.+-]{1,80}$/.test(packageVersion)
333
+ ? packageVersion
334
+ : "untrusted-version";
335
+ return `${expectedPackage} (${safePackageVersion})`;
336
+ }
337
+
330
338
  function readNestedString(input: JsonObject, path: string[]): string | null {
331
339
  const value = readNested(input, path);
332
340
  return typeof value === "string" ? value : null;
@@ -423,6 +423,7 @@ async function main() {
423
423
  const report = createPublishedPackageSmokeReport(parsed);
424
424
  console.log(JSON.stringify(report, null, 2));
425
425
  if (parsed.strict && !report.ok) process.exitCode = 1;
426
+ if (parsed.gatewayReadyStrict && !report.publishedSmokeReady) process.exitCode = 1;
426
427
  return;
427
428
  }
428
429
  if (command === "openclaw" && args[0] === "live-control-smoke") {
@@ -1206,7 +1207,7 @@ function printGeneralReleaseReadinessHelp(): void {
1206
1207
  "Usage:",
1207
1208
  " loo release general-readiness --evidence-dir path [--fresh-npm-evidence path] [--agent-dogfood-evidence path] [--now iso] [--strict]",
1208
1209
  "",
1209
- "Writes a public-safe 1.0 general-release readiness packet without performing release actions.",
1210
+ "Writes a public-safe general-release readiness packet for the current package version without performing release actions.",
1210
1211
  "",
1211
1212
  "Required evidence:",
1212
1213
  " --fresh-npm-evidence points to a public-safe `loo openclaw published-smoke` report with clean-profile gateway status ready.",
@@ -1216,20 +1217,27 @@ function printGeneralReleaseReadinessHelp(): void {
1216
1217
  " --strict exits non-zero until docs, skill/playbook, M9 scenarios, fresh npm proof, and agent dogfood proof are complete.",
1217
1218
  "",
1218
1219
  "Safety boundary:",
1219
- " The command does not publish npm, does not move npm latest, does not create a GitHub Release, does not run live Codex control, and does not perform desktop GUI mutation."
1220
+ " The command does not publish npm, does not move npm dist-tags, does not create a GitHub Release, does not run live Codex control, and does not perform desktop GUI mutation."
1220
1221
  ].join("\n"));
1221
1222
  }
1222
1223
 
1223
1224
  function printOpenClawPublishedSmokeHelp(): void {
1224
1225
  console.log([
1225
1226
  "Usage:",
1226
- " loo openclaw published-smoke --evidence-dir path --dogfood-report path --tool-smoke-report path [--configured-tool-smoke-report path] [--npm-install-diagnostic-report path] [--registry-version version] [--registry-beta-version version] [--root path] [--now iso] [--strict]",
1227
+ " loo openclaw published-smoke --evidence-dir path --dogfood-report path --tool-smoke-report path [--configured-tool-smoke-report path] [--npm-install-diagnostic-report path] [--registry-version version] [--registry-beta-version version] [--root path] [--now iso] [--strict] [--gateway-ready-strict]",
1227
1228
  "",
1228
- "Writes a public-safe summary of the published npm beta install path and gateway setup state.",
1229
+ "Writes a public-safe summary of the published npm package path for the expected dist-tag and gateway setup state.",
1229
1230
  "",
1230
1231
  "This command consumes sanitized reports from `loo openclaw dogfood` and `loo openclaw tool-smoke`.",
1231
1232
  "Optional `--configured-tool-smoke-report` records a separately named configured-profile gateway proof without marking the fresh published profile ready.",
1232
1233
  "Optional `--npm-install-diagnostic-report` records public-safe npm selector drift and tarball fallback proof without storing raw npm output.",
1234
+ "",
1235
+ "Strict mode:",
1236
+ " --strict exits non-zero only when ok/packagePathOk is false; it is package-path strict.",
1237
+ " --gateway-ready-strict exits non-zero unless publishedSmokeReady is true for the clean published profile.",
1238
+ " With both flags, any failed package-path or clean-profile gateway-ready condition exits non-zero.",
1239
+ " A configured gateway proof is recorded separately and never substitutes for fresh-profile gateway readiness.",
1240
+ "",
1233
1241
  "It does not run npm install, does not call OpenClaw, does not run live Codex control, and does not mutate a desktop GUI."
1234
1242
  ].join("\n"));
1235
1243
  }
@@ -2223,6 +2231,7 @@ function parseOpenClawPublishedSmokeArgs(input: string[]): {
2223
2231
  configuredToolSmokeReportPath?: string;
2224
2232
  npmInstallDiagnosticReportPath?: string;
2225
2233
  strict: boolean;
2234
+ gatewayReadyStrict: boolean;
2226
2235
  } {
2227
2236
  const parsed: {
2228
2237
  evidenceDir?: string;
@@ -2235,7 +2244,8 @@ function parseOpenClawPublishedSmokeArgs(input: string[]): {
2235
2244
  configuredToolSmokeReportPath?: string;
2236
2245
  npmInstallDiagnosticReportPath?: string;
2237
2246
  strict: boolean;
2238
- } = { strict: false };
2247
+ gatewayReadyStrict: boolean;
2248
+ } = { strict: false, gatewayReadyStrict: false };
2239
2249
  for (let index = 0; index < input.length; index += 1) {
2240
2250
  const arg = input[index]!;
2241
2251
  if (arg === "--evidence-dir") {
@@ -2258,6 +2268,8 @@ function parseOpenClawPublishedSmokeArgs(input: string[]): {
2258
2268
  parsed.npmInstallDiagnosticReportPath = requireOptionValue(input[++index], arg);
2259
2269
  } else if (arg === "--strict") {
2260
2270
  parsed.strict = true;
2271
+ } else if (arg === "--gateway-ready-strict") {
2272
+ parsed.gatewayReadyStrict = true;
2261
2273
  } else {
2262
2274
  throw new Error(`Unknown openclaw published-smoke option: ${arg}`);
2263
2275
  }
@@ -2274,7 +2286,8 @@ function parseOpenClawPublishedSmokeArgs(input: string[]): {
2274
2286
  toolSmokeReportPath: parsed.toolSmokeReportPath,
2275
2287
  configuredToolSmokeReportPath: parsed.configuredToolSmokeReportPath,
2276
2288
  npmInstallDiagnosticReportPath: parsed.npmInstallDiagnosticReportPath,
2277
- strict: parsed.strict
2289
+ strict: parsed.strict,
2290
+ gatewayReadyStrict: parsed.gatewayReadyStrict
2278
2291
  };
2279
2292
  }
2280
2293
 
@@ -19,6 +19,13 @@ export type PublishedPackageSmokeReport = {
19
19
  ok: boolean;
20
20
  publishedSmokeReady: boolean;
21
21
  packagePathOk: boolean;
22
+ readinessSemantics: Readonly<{
23
+ okField: "packagePathOk";
24
+ strictModeExitsOn: "packagePathOk_false";
25
+ gatewayReadyStrictExitsOn: "publishedSmokeReady_false";
26
+ cleanProfileGatewayReadyField: "publishedSmokeReady";
27
+ configuredGatewayProofSeparate: true;
28
+ }>;
22
29
  publicSafe: true;
23
30
  localOnly: true;
24
31
  dryRun: true;
@@ -104,6 +111,14 @@ export type PublishedPackageSmokeReport = {
104
111
  proofBoundary: string;
105
112
  };
106
113
 
114
+ const READINESS_SEMANTICS = Object.freeze({
115
+ okField: "packagePathOk",
116
+ strictModeExitsOn: "packagePathOk_false",
117
+ gatewayReadyStrictExitsOn: "publishedSmokeReady_false",
118
+ cleanProfileGatewayReadyField: "publishedSmokeReady",
119
+ configuredGatewayProofSeparate: true
120
+ } as const);
121
+
107
122
  export function createPublishedPackageSmokeReport(options: PublishedPackageSmokeOptions): PublishedPackageSmokeReport {
108
123
  const rootDir = options.rootDir
109
124
  ? resolve(options.rootDir)
@@ -171,6 +186,7 @@ export function createPublishedPackageSmokeReport(options: PublishedPackageSmoke
171
186
  ok: packagePathOk,
172
187
  publishedSmokeReady: packagePathOk && toolSmokeReady,
173
188
  packagePathOk,
189
+ readinessSemantics: READINESS_SEMANTICS,
174
190
  publicSafe: true,
175
191
  localOnly: true,
176
192
  dryRun: true,
@@ -220,7 +236,7 @@ export function createPublishedPackageSmokeReport(options: PublishedPackageSmoke
220
236
  "tokens, credentials, API keys, cookies",
221
237
  "private customer data"
222
238
  ],
223
- proofBoundary: `This published package smoke report summarizes public-safe ${expectedDistTag} install and gateway setup evidence only; it does not run live Codex control, mutate a desktop GUI, publish npm, create a GitHub Release, store raw npm output, or store raw OpenClaw gateway output.`
239
+ proofBoundary: `This published package smoke report summarizes public-safe ${expectedDistTag} install and gateway setup evidence only. ok/packagePathOk are package-path claims; publishedSmokeReady is the clean-profile gateway-ready claim. This command does not run live Codex control, mutate a desktop GUI, publish npm, create a GitHub Release, store raw npm output, or store raw OpenClaw gateway output.`
224
240
  };
225
241
  if (options.evidenceDir) writePublishedPackageSmokeReport(report, options.evidenceDir);
226
242
  return report;
@@ -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 { basename, dirname, extname, join, resolve, sep } from "node:path";
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 rawSessionArtifacts = scanRawSessionArtifacts(options.evidenceDir);
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(rawSessionArtifacts.length === 0, rawSessionArtifacts.length === 0 ? "no raw session/private DB/screenshot artifacts found" : "raw session/private DB/screenshot artifacts are present"),
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 scanRawSessionArtifacts(evidenceDir: string | undefined): RawSessionArtifact[] {
276
- if (!evidenceDir || !existsSync(evidenceDir)) return [];
277
- return readdirSync(evidenceDir, { withFileTypes: true })
278
- .filter((entry) => entry.isFile())
279
- .map((entry) => rawArtifactForName(entry.name))
280
- .filter((entry): entry is RawSessionArtifact => entry !== null)
281
- .sort((left, right) => left.name.localeCompare(right.name));
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 extension = extname(name).toLowerCase();
287
- if (extension === ".jsonl") return { name: basename(name), reason: "raw_codex_jsonl" };
288
- if (extension === ".sqlite" || extension === ".sqlite3" || extension === ".db") return { name: basename(name), reason: "sqlite_database" };
289
- if (extension === ".png" || extension === ".jpg" || extension === ".jpeg" || extension === ".heic" || extension === ".webp") return { name: basename(name), reason: "screenshot_or_image" };
290
- if (extension === ".mov" || extension === ".mp4" || extension === ".webm") return { name: basename(name), reason: "video_capture" };
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.1",
5
+ "version": "1.2.3",
6
6
  "kind": "tool",
7
7
  "tools": {
8
8
  "prefix": "loo_"