chainlesschain 0.166.140 → 0.166.141

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
@@ -2,25 +2,43 @@
2
2
 
3
3
  Command-line interface for installing, configuring, and managing [ChainlessChain](https://www.chainlesschain.com), including the coding agent, governed tools, sessions, memory, and IDE integrations.
4
4
 
5
+ <!-- release141-pairing:start -->
6
+
7
+ ## CLI 0.166.141 / complete source preview recovery
8
+
9
+ Release candidate **0.166.141** preserves legitimate source spread expressions in complete file-read previews and keeps read-recovery guidance actionable. Launcher-owned hermetic evaluations use the same exact mutation scope through the CLI and IDE gateway; ordinary interactive permissions and the IDE protocol retain their existing behavior.
10
+
11
+ The intended pairing is VS Code **0.37.177** and JetBrains **0.4.194**. Child npm versions are unchanged. Publication remains pending until this exact source passes every configured Linux, Windows and macOS CLI CI / CLI Strict Sandbox job, then GitHub Actions OIDC publishes and verifies the public npm archive. IDE publication follows verified CLI installation.
12
+
13
+ After public availability is verified, install `npm i -g chainlesschain@0.166.141 --registry https://registry.npmjs.org`, restart the CLI and IDE hosts, and run `cc --version` and `cc doctor`.
14
+
15
+ This release does not run additional model-task retests or rescore historical results. Volcengine historical coverage remains 36/45 with its original qualification limits; the latest complete round is 24/45. Sol original-project history is 41/45, the latest repaired-source four-case cohort is 2/4, and cross-version coverage is 45/45. Diagnostic future budgets remain finite; these are not automatic increases to ordinary user requests.
16
+
17
+ <!-- release141-pairing:end -->
18
+
5
19
  <!-- release140-pairing:start -->
6
20
 
7
21
  ## CLI 0.166.140 / rejected tool argument recovery
8
22
 
9
- This package is CLI **0.166.140**, paired with Open VSX **0.37.176** and JetBrains **0.4.193**. Install `npm i -g chainlesschain@0.166.140 --registry https://registry.npmjs.org`, restart the CLI and IDE chat hosts, then check `cc --version` and `cc doctor`.
23
+ As checked at **2026-11-03T11:42:31.329Z**, CLI **0.166.140** is verified public through [GitHub Actions OIDC](https://github.com/chainlesschain/chainlesschain/actions/runs/41610020835) from exact source `e2a91bf54332ff3d252c40ecc25c5887e0f0430d`. Public npm bytes, signed provenance, installation and startup have been verified. The same source passed every configured Linux, Windows and macOS CLI CI / CLI Strict Sandbox job.
10
24
 
11
- Malformed provider tool arguments are rejected before tool execution. A uniquely paired pre-execution rejection produces a model-only placeholder so the next turn can continue through strict self-evolution projection. Legacy run_code snapshot rejections can resume without replaying the rejected call; original durable history stays unchanged. Valid object arguments, duplicate-key rejection, nested JSON checks, redaction and decoding budgets retain their existing boundaries.
25
+ Open VSX **0.37.176** is public, listed and downloadable; its VSIX matches the official build byte for byte. JetBrains **0.4.193** has been uploaded and awaits Marketplace review or public indexing; public availability has not been verified. The previously verified public JetBrains release remains **0.4.192**, whose recommendation is CLI **0.166.139**. Both new IDE versions recommend CLI **0.166.140**.
26
+
27
+ [Publication and channel receipts](../../docs/research/cli/evidence/release140-public/publication-readback.json) · [Exact-source gates](../../docs/research/cli/evidence/release140-public/gates.json) · [CLI public readback](../../docs/research/cli/evidence/release140-public/cli.json) · [Open VSX readback](../../docs/research/cli/evidence/release140-public/open-vsx.json) · [JetBrains status](../../docs/research/cli/evidence/release140-public/jetbrains.json)
12
28
 
13
- Publication uses GitHub Actions OIDC after the exact release commit passes CLI CI and CLI Strict Sandbox on every configured Linux, Windows and macOS runner. IDE publication follows verified public CLI installation and its own exact-source host gates. JetBrains upload, Marketplace approval and public availability are reported separately.
29
+ Install `npm i -g chainlesschain@0.166.140 --registry https://registry.npmjs.org`, restart the CLI and IDE chat hosts, then run `cc --version` and `cc doctor`.
30
+
31
+ Malformed provider tool arguments are rejected before tool execution. A uniquely paired pre-execution rejection produces a model-only placeholder so the next turn can continue through strict self-evolution projection. Legacy run_code snapshot rejections can resume without replaying the rejected call; original durable history stays unchanged. Valid object arguments, duplicate-key rejection, nested JSON checks, redaction and decoding budgets retain their existing boundaries.
14
32
 
15
- The focused Windows checks passed 129 tests. Two bounded real Volcengine recovery scenarios passed through the installed runtime with five physical requests and 6,401 tokens; the first scenario explicitly injected the exact logged malformed argument into one inbound model response. These results cover this recovery defect and do not rescore historical model-task acceptance. SDK 0.2.17, Protocol 0.1.12, Kernel 0.1.11 and the other child packages retain their published versions. Microsoft Marketplace and the independent PC/mobile product release are outside this patch.
33
+ Agent projection v10 also prevents genuine image and reasoning transport SHA-256 digests from being mistaken for phone numbers. Only authenticated protocol metadata uses the scan view; the original digest and byte-length restoration binding is unchanged. Real phone numbers, user-supplied digest-like text and forged markers retain their existing checks, and v1–v9 historical rules are preserved.
16
34
 
17
- [Focused live recovery evidence](../../docs/research/cli/evidence/tool-argument-recovery-20261103/live-volcengine.json).
35
+ The focused Windows checks passed **129 tests**. The earlier v9 recovery check used **five real Volcengine requests and 6,401 tokens**; its first scenario explicitly injected the exact logged malformed argument into one inbound model response. [Original scoped evidence](../../docs/research/cli/evidence/tool-argument-recovery-20261103/live-volcengine.json). The separate v10 check passed both recovery scenarios with **five real Volcengine requests and 6,501 tokens**, with runtime source hashes matching this release. [Additional scoped evidence](../../docs/research/cli/evidence/tool-argument-recovery-20261103/live-volcengine-v10.json). The complete related projector/agent-model tests passed **393/393**. These runs remain separate and add no historical model-task acceptance.
18
36
 
19
- Agent projection v10 also prevents genuine image and reasoning transport SHA-256 digests from being mistaken for phone numbers. Only authenticated protocol metadata uses the scan view; the original digest and byte-length restoration binding is unchanged. Real phone numbers, user-supplied digest-like text and forged markers retain their existing checks, and v1-v9 historical rules are preserved.
37
+ Earlier candidate `eb0fe7a8a1` failed at the Windows ArtifactStore post-index integrity guard, then passed a complete three-OS loopback rerun. The exact rejected condition remains unresolved; the guard stays enforced. The [original failure](../../docs/research/cli/evidence/tool-argument-recovery-20261103/windows-eb-trajectory-attempt1-failure.json) and [complete rerun](../../docs/research/cli/evidence/tool-argument-recovery-20261103/windows-eb-trajectory-attempt2-aggregate.json) retain their historical source scope. The final release source separately passed 100 loopback runs on each of three operating systems; these 300 structural-envelope-only runs are not paid-provider task acceptance or a replacement for CLI CI / Strict Sandbox. Local composition runs timed out on both the v10 source and the earlier baseline and are not counted as passing.
20
38
 
21
- The v10 candidate passed both recovery scenarios again with **five real Volcengine requests and 6,501 tokens**, using runtime source hashes matching this candidate. See the [additional live evidence](https://github.com/chainlesschain/chainlesschain/blob/main/docs/research/cli/evidence/tool-argument-recovery-20261103/live-volcengine-v10.json).
39
+ Agent SDK **0.2.17**, Protocol **0.1.12**, Kernel **0.1.11** and the other child packages retain their published versions; required upstream packages were fetched and dependency alignment verified before CLI publication. Microsoft Marketplace remains deferred. PC/mobile **v5.0.3.144** is already public as an independent release; this CLI/IDE follow-up does not republish clients. Historical .138 **2/4**, .137 **0/5** and cumulative **41/45** retain separate scopes.
22
40
 
23
- Earlier candidate `eb0fe7a8a1` stopped at a Windows ArtifactStore post-index integrity guard, then passed a complete three-OS loopback rerun. The exact rejected condition remains unresolved, and the guard stays enforced. The [original failure](https://github.com/chainlesschain/chainlesschain/blob/main/docs/research/cli/evidence/tool-argument-recovery-20261103/windows-eb-trajectory-attempt1-failure.json) and [complete rerun](https://github.com/chainlesschain/chainlesschain/blob/main/docs/research/cli/evidence/tool-argument-recovery-20261103/windows-eb-trajectory-attempt2-aggregate.json) retain their historical source scope.
41
+ Documentation reviewed against `main@d62866538c` on **2026-11-03**. The later read-recovery hint and Web Panel bundle fixes are outside the immutable CLI .140 release source. The .140 full 36+9 Volcengine campaign has no verified final score yet; the internal-output-limit adapter repair is tracked separately. Historical original-project **41/45**, .138 **2/4**, and Sol cross-revision coverage **45/45** (including repaired project sources) retain separate scopes. [Current design](../../docs/design/release-runtime-update-2026-11-03-140.md) · [Upgrade guide](https://docs.chainlesschain.com/chainlesschain/cli-ide-update-2026-11-03-140.html).
24
42
 
25
43
  <!-- release140-pairing:end -->
26
44
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chainlesschain",
3
- "version": "0.166.140",
3
+ "version": "0.166.141",
4
4
  "description": "CLI for ChainlessChain - install, configure, and manage your personal AI management system",
5
5
  "type": "module",
6
6
  "bin": {
@@ -6,5 +6,5 @@
6
6
  "imageDigest": "sha256:6395a47a5bd9b038303e94a5e93754258c8480dab64635460f973eb93dc6f4d8",
7
7
  "bytes": 778808,
8
8
  "linkage": "static",
9
- "commit": "e2a91bf54332ff3d252c40ecc25c5887e0f0430d"
9
+ "commit": "df9295e33ad04aec0aa74cab4dd242766d5556a4"
10
10
  }
@@ -6,5 +6,5 @@
6
6
  "imageDigest": "sha256:f162e55ad3f3f72f8a52e9d7f12b5b8db44506c2ca66a14d7d62d5cd4f12498e",
7
7
  "bytes": 934160,
8
8
  "linkage": "static",
9
- "commit": "e2a91bf54332ff3d252c40ecc25c5887e0f0430d"
9
+ "commit": "df9295e33ad04aec0aa74cab4dd242766d5556a4"
10
10
  }
@@ -1,6 +1,19 @@
1
1
  {
2
2
  "source": "CHANGELOG.md",
3
3
  "releases": [
4
+ {
5
+ "productVersion": null,
6
+ "cliVersion": "0.166.141",
7
+ "cliVersions": ["0.166.141"],
8
+ "date": "2026-11-04",
9
+ "title": "",
10
+ "sections": [
11
+ {
12
+ "heading": "Fixed - cc CLI 0.166.141: preserve complete source previews and evaluation entry scope (2026-11-04)",
13
+ "body": "- Preserve legitimate bounded source spread expressions in host-created read previews instead of omitting valid code. Keep strict JSON, sensitive-data and source-identity checks enforced.\n- Keep focused read recovery instructions actionable and retain the existing shared author/review turn budget.\n- Bind launcher-owned hermetic evaluation file scope consistently at the shared CLI/IDE agent loop, preserving caller narrowing and empty/read-only tool sets. Ordinary interactive permissions and the IDE protocol retain their existing behavior.\n- Reject diagnostic broker construction under a formal budget before reading its options, while preserving the existing finite diagnostic limits.\n- Pair with Open VSX 0.37.177 and JetBrains 0.4.194 after verified CLI publication. Child npm packages are unchanged; require their public-byte reuse checks and the complete exact-source CLI CI / Strict Sandbox matrices.\n- Preserve the recorded Volcengine full-round results and OpenAI four-case results. Engineering checks and publication add no model-task acceptance; already tested samples are not retested."
14
+ }
15
+ ]
16
+ },
4
17
  {
5
18
  "productVersion": null,
6
19
  "cliVersion": "0.166.140",
@@ -3131,11 +3131,74 @@ export class EvolutionArtifactPorts {
3131
3131
  createdAtMs < core.issuedAtMs ||
3132
3132
  !storeRetentionIsAdmissible
3133
3133
  ) {
3134
- throw artifactError(
3134
+ const error = artifactError(
3135
3135
  EVOLUTION_ARTIFACT_INTEGRITY_FAILED_CODE,
3136
3136
  "ArtifactStore index entry is not exactly admissible for this envelope",
3137
3137
  { artifactId: id },
3138
3138
  );
3139
+ // Diagnostic branch only: observe the already-rejected guard without
3140
+ // retaining any entry values or changing its decision or original error.
3141
+ try {
3142
+ if (process.env.CC_R140_STORAGE_DIAGNOSTIC) {
3143
+ const failures = [
3144
+ ["file", file !== `${id}.json` || path.basename(file) !== file],
3145
+ [
3146
+ "title",
3147
+ ownData(entry, "title", "ArtifactStore index entry") !==
3148
+ `Evolution ${core.type} artifact`,
3149
+ ],
3150
+ [
3151
+ "kind",
3152
+ ownData(entry, "kind", "ArtifactStore index entry") !== "data",
3153
+ ],
3154
+ [
3155
+ "mime",
3156
+ ownData(entry, "mime", "ArtifactStore index entry") !==
3157
+ "application/json",
3158
+ ],
3159
+ [
3160
+ "size",
3161
+ !Number.isSafeInteger(size) ||
3162
+ size < 1 ||
3163
+ size > EVOLUTION_ARTIFACT_MAX_CANONICAL_BYTES,
3164
+ ],
3165
+ [
3166
+ "hash",
3167
+ ownData(entry, "sha256", "ArtifactStore index entry") !==
3168
+ core.recordDigest.slice("sha256:".length),
3169
+ ],
3170
+ [
3171
+ "sourcePath",
3172
+ ownData(entry, "sourcePath", "ArtifactStore index entry") !==
3173
+ null,
3174
+ ],
3175
+ [
3176
+ "sessionId",
3177
+ ownData(entry, "sessionId", "ArtifactStore index entry") !== null,
3178
+ ],
3179
+ [
3180
+ "immutable",
3181
+ ownData(entry, "immutable", "ArtifactStore index entry") !== true,
3182
+ ],
3183
+ [
3184
+ "recordDigest",
3185
+ ownData(entry, "recordDigest", "ArtifactStore index entry") !==
3186
+ core.recordDigest,
3187
+ ],
3188
+ ["expiry-order", storeExpiresAtMs <= createdAtMs],
3189
+ ["created-before-issued", createdAtMs < core.issuedAtMs],
3190
+ ["retention", !storeRetentionIsAdmissible],
3191
+ ]
3192
+ .filter(([, failed]) => failed)
3193
+ .map(([label]) => label);
3194
+ Object.defineProperty(error, "r140IndexFailures", {
3195
+ value: Object.freeze(failures),
3196
+ });
3197
+ }
3198
+ } catch {
3199
+ // Observation must never replace the original rejection.
3200
+ }
3201
+ throw error;
3139
3202
  }
3140
3203
  const lineage = this.#validateLineage(
3141
3204
  ownData(entry, "lineage", "ArtifactStore index entry"),
@@ -26,6 +26,13 @@ function mergeSpan(spans, span) {
26
26
  return merged;
27
27
  }
28
28
 
29
+ function rereadFingerprint(span, restoring) {
30
+ return (
31
+ (restoring ? "restore:" : "review:") +
32
+ createHash("sha256").update(JSON.stringify(span)).digest("hex")
33
+ );
34
+ }
35
+
29
36
  /** Per-run read coverage and recovery, independent of compacted transcripts. */
30
37
  export class ReadFileLoopGuard {
31
38
  constructor() {
@@ -309,9 +316,7 @@ export class ReadFileLoopGuard {
309
316
  this.visiblePages !== null &&
310
317
  entry.lastReadRequest < this.visibleRequest &&
311
318
  !this.isPageVisible(page);
312
- const fingerprint =
313
- (restoring ? "restore:" : "review:") +
314
- createHash("sha256").update(JSON.stringify(span)).digest("hex");
319
+ const fingerprint = rereadFingerprint(span, restoring);
315
320
  if (
316
321
  targeted &&
317
322
  !entry.rereads.has(fingerprint) &&
@@ -354,6 +359,40 @@ export class ReadFileLoopGuard {
354
359
  hint: "This range has a read pending in the current tool batch. Historical source coverage is recorded only after content reaches the model.",
355
360
  };
356
361
  }
362
+ const recoveryRead = {
363
+ path: filePath,
364
+ offset: explicitRange ? page.range.startLine : 1,
365
+ limit: 80,
366
+ ...(args.hashed === true ? { hashed: true } : {}),
367
+ ...(args.raw === true ? { raw: true } : {}),
368
+ };
369
+ const recoveryPage = readPage(recoveryRead);
370
+ const validRecoveryPage =
371
+ !recoveryPage.error &&
372
+ !!recoveryPage.readSpan &&
373
+ !recoveryPage.truncated;
374
+ const recoveryCovered =
375
+ validRecoveryPage &&
376
+ entry.spans.some(
377
+ ([start, end]) =>
378
+ start <= recoveryPage.readSpan.start &&
379
+ end >= recoveryPage.readSpan.end,
380
+ );
381
+ const recoveryRestoring =
382
+ validRecoveryPage &&
383
+ this.visiblePages !== null &&
384
+ entry.lastReadRequest < this.visibleRequest &&
385
+ !this.isPageVisible(recoveryPage);
386
+ // A recovery hint is a contract. Do not prescribe a read that this
387
+ // same guard would immediately omit again. This checks a pure page
388
+ // from the already-authorized file without minting a new allowance.
389
+ const canRecover =
390
+ validRecoveryPage &&
391
+ (!recoveryCovered ||
392
+ (entry.rereads.size < 3 &&
393
+ !entry.rereads.has(
394
+ rereadFingerprint(recoveryPage.readSpan, recoveryRestoring),
395
+ )));
357
396
  return {
358
397
  path: filePath,
359
398
  fileVersion,
@@ -367,14 +406,10 @@ export class ReadFileLoopGuard {
367
406
  ...(entry.summary?.outline
368
407
  ? { outline: entry.summary.outline }
369
408
  : {}),
370
- recoveryRead: {
371
- path: filePath,
372
- offset: explicitRange ? page.range.startLine : 1,
373
- limit: 80,
374
- ...(args.hashed === true ? { hashed: true } : {}),
375
- ...(args.raw === true ? { raw: true } : {}),
376
- },
377
- hint: "This requested range was read earlier, but historical coverage does not mean its source is visible now. The runtime has not substituted an unrelated file range. Use source actually present in this request; recover missing details with a focused search or the bounded recoveryRead. Reading the file is not task completion.",
409
+ ...(canRecover ? { recoveryRead } : {}),
410
+ hint: canRecover
411
+ ? "This requested range was read earlier, but historical coverage does not mean its source is visible now. Recover missing details with a focused search or the bounded recoveryRead. Reading the file is not task completion."
412
+ : "This unchanged range cannot be reread within the remaining read allowance. Do not repeat it. Use source still visible in this request, or search_files for a precise symbol (set regex:true when using a regular expression). If required source is unavailable, report the limitation instead of guessing APIs.",
378
413
  };
379
414
  }
380
415
  }
@@ -36,6 +36,7 @@ const PREVIEW_HINT =
36
36
  export function canProjectHostToolExcerpt(text, tool) {
37
37
  const scan = createEvidenceJsonTextBoundary((message) => new Error(message), {
38
38
  ...EVIDENCE_JSON_POLICY,
39
+ sourceExpressionPolicy: "bounded-source-tokens-v1",
39
40
  sourceLiteralPolicy: "explicit-source-containers-v1",
40
41
  maxSourceTokens: 32768,
41
42
  });
@@ -7,6 +7,12 @@ import {
7
7
  requireUnscopedToolExecution,
8
8
  } from "../lib/formal-budget-provider-scope.js";
9
9
  import { isFormalBudgetError } from "../lib/formal-budget-errors.js";
10
+ import {
11
+ FORMAL_QUALITY_ALLOWED_FILES_ENV,
12
+ FORMAL_QUALITY_FILE_TOOLS,
13
+ formalQualityAllowedFiles,
14
+ isFormalQualityHermeticRuntime,
15
+ } from "../lib/formal-quality-eval-runtime.js";
10
16
  import { normalizeOllamaBaseUrl } from "../lib/ollama-base-url.js";
11
17
  import { ollamaProviderFetch } from "../lib/ollama-provider-fetch.js";
12
18
  import {
@@ -14987,7 +14993,59 @@ function permissionDecision(callId, tool, result) {
14987
14993
  });
14988
14994
  }
14989
14995
 
14996
+ function bindFormalQualityLoopOptions(options) {
14997
+ // The launcher owns this binding. Apply it at the shared loop so direct
14998
+ // gateway/IDE callers receive the same schema and execution guard as CLI.
14999
+ // Legacy hermetic callers without a file binding retain their own boundary.
15000
+ if (
15001
+ !isFormalQualityHermeticRuntime(process.env) ||
15002
+ !Object.hasOwn(process.env, FORMAL_QUALITY_ALLOWED_FILES_ENV)
15003
+ ) {
15004
+ return options;
15005
+ }
15006
+ const allowedPaths = formalQualityAllowedFiles(process.env);
15007
+ const cwd = options.cwd || process.cwd();
15008
+ const launcherScope = normalizeExactFileMutationScope(
15009
+ { exact: true, worktreeRoot: canonicalRealpath(cwd), allowedPaths },
15010
+ { cwd },
15011
+ );
15012
+ const callerScope = normalizeExactFileMutationScope(
15013
+ options.fileMutationScope,
15014
+ {
15015
+ cwd,
15016
+ },
15017
+ );
15018
+ if (
15019
+ callerScope &&
15020
+ callerScope.allowedPaths.some((file) => !allowedPaths.includes(file))
15021
+ ) {
15022
+ throw new Error("mutation scope widens the formal quality file binding");
15023
+ }
15024
+ if (
15025
+ options.enabledToolNames != null &&
15026
+ !Array.isArray(options.enabledToolNames)
15027
+ ) {
15028
+ throw new Error("formal quality enabled tool names must be an array");
15029
+ }
15030
+ return {
15031
+ ...options,
15032
+ fileMutationScope: callerScope || launcherScope,
15033
+ hermeticExecution: true,
15034
+ exactToolNames: true,
15035
+ // Hermetic execution ignores host executors. Match that on the provider
15036
+ // side too: a same-named host executor must not suppress the path enum
15037
+ // for the built-in mutation tool that will actually execute.
15038
+ externalToolExecutors: null,
15039
+ enabledToolNames: Object.freeze(
15040
+ (options.enabledToolNames ?? FORMAL_QUALITY_FILE_TOOLS).filter((name) =>
15041
+ FORMAL_QUALITY_FILE_TOOLS.includes(name),
15042
+ ),
15043
+ ),
15044
+ };
15045
+ }
15046
+
14990
15047
  export async function* agentLoop(messages, options) {
15048
+ options = bindFormalQualityLoopOptions(options);
14991
15049
  // Bind the actual task before compaction, runtime nudges or provider projection.
14992
15050
  // A new host-admitted user turn starts a new loop and receives its own binding.
14993
15051
  const currentUserTask = messages.findLast(