Skip to content

fix(cli): preserve trustedFolders comments on save#4746

Open
Zoean-z wants to merge 9 commits into
QwenLM:mainfrom
Zoean-z:fix-trusted-folders-preserve-comments
Open

fix(cli): preserve trustedFolders comments on save#4746
Zoean-z wants to merge 9 commits into
QwenLM:mainfrom
Zoean-z:fix-trusted-folders-preserve-comments

Conversation

@Zoean-z

@Zoean-z Zoean-z commented Jun 3, 2026

Copy link
Copy Markdown

What this PR does

This changes trustedFolders.json saving to preserve existing comments and formatting when trust rules are updated, instead of rewriting the file with plain JSON.stringify.

Why it's needed

trustedFolders.json is currently read with comment-tolerant parsing, so users can maintain it as a commented JSONC-style config file. But when Qwen Code updates trust rules, the save path rewrites the whole file as plain JSON and strips all existing comments. This change makes the write path consistent with the read behavior while preserving the existing full-sync semantics of trusted folder updates.

Reviewer Test Plan

How to verify

  1. Create a trustedFolders.json file with comments, for example:
    {
      // work repos
      "/existing/path": "TRUST_FOLDER"
    }

Trigger a trusted folder update so Qwen Code rewrites the file.
Confirm that:
the existing comment is still present after the write
the updated trust rule is persisted
stale entries are removed rather than left behind
Evidence (Before & After)
N/A

Tested on
OS Status
🍗 macOS ⬜ not tested
🪟 Windows ✅ tested
🐧 Linux ⬜ not tested
Environment (optional)
Local workspace, unit tests only.

Commands run:

npm run test --workspace=packages/cli -- trustedFolders.test.ts
npm run typecheck --workspace=packages/cli
Risk & Scope
Main risk or tradeoff: This changes only the trusted folders save path and keeps the existing secure atomicWriteFileSync(..., noFollow: true) write path.
Not validated / out of scope: No manual end-to-end CLI interaction test was added in this change.
Breaking changes / migration notes: None.
Linked Issues
Fixes #3983

中文说明 这个 PR 做了什么 这个 PR 修改了 trustedFolders.json 的保存逻辑:当 trust rule 被更新时,保留文件里原有的注释和格式,而不是继续用普通 JSON.stringify 把整个文件重写掉。

为什么需要这个改动
当前 trustedFolders.json 在读取时支持带注释的 JSONC 风格内容,因此用户可以把它当作可手动维护的配置文件来写。但 Qwen Code 在更新 trust rule 时,会把整个文件按纯 JSON 重写,导致已有注释全部丢失。这个改动让写入行为和读取行为保持一致,同时保留 trusted folders 现有的“完整同步”语义。

Reviewer Test Plan
如何验证
先创建一个带注释的 trustedFolders.json,例如:
{
// work repos
"/existing/path": "TRUST_FOLDER"
}
触发一次 trusted folder 更新,让 Qwen Code 重写这个文件。
确认:
原有注释在写回后仍然存在
更新后的 trust rule 被正确保存
已被移除的旧条目不会残留在文件里
前后对比证据
N/A

已测试环境
OS Status
🍗 macOS ⬜ not tested
🪟 Windows ✅ tested
🐧 Linux ⬜ not tested
环境说明(可选)
本地工作区,仅运行单元测试。

执行命令:

npm run test --workspace=packages/cli -- trustedFolders.test.ts
npm run typecheck --workspace=packages/cli
风险与范围
主要风险或权衡:这次改动只影响 trusted folders 的保存路径,并保留了现有的 atomicWriteFileSync(..., noFollow: true) 安全写入方式。
未验证 / 不在本次范围内:这次没有补手动的 CLI 端到端交互测试。
Breaking changes / migration notes: None.
关联 Issue
Fixes #3983

let content: string;
if (fs.existsSync(trustedFoldersFile.path)) {
const originalContent = fs.readFileSync(trustedFoldersFile.path, 'utf-8');
const parsed = parse(originalContent) as Record<string, unknown>;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] Self-healing regression: the old save path wrote JSON.stringify(config) unconditionally, which always produced valid JSON — silently repairing a corrupted trustedFolders.json on the next save. The new path calls parse(originalContent) first; if that throws (severe file corruption), the outer catch aborts the entire save and the corrupted file persists. Every subsequent trust decision then fails to persist with only a generic stderr message.

Suggested fix — fall back to a clean write when the comment-preserving round-trip fails:

let content: string;
if (fs.existsSync(trustedFoldersFile.path)) {
  try {
    const originalContent = fs.readFileSync(trustedFoldersFile.path, 'utf-8');
    const parsed = parse(originalContent) as Record<string, unknown>;
    const updated = applyUpdates(
      parsed,
      trustedFoldersFile.config as Record<string, unknown>,
      true,
    );
    content = stringify(updated, null, 2);
    parse(content); // validate
  } catch {
    // Comment-preserving round-trip failed — fall back to clean write
    // so the file self-heals instead of staying broken.
    content = stringify(trustedFoldersFile.config, null, 2);
  }
} else {
  content = stringify(trustedFoldersFile.config, null, 2);
}

— qwen3.7-max via Qwen Code /review

const updated = applyUpdates(
parsed,
trustedFoldersFile.config as Record<string, unknown>,
true,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] sync=true causes applyUpdates to actively delete every key in the on-disk file that is absent from the in-memory config. When multiple Qwen Code processes run concurrently (common — multiple terminal windows), this silently destroys trust entries that another process added between this process's load-time and save-time. The old code (JSON.stringify(config)) had the same blind-overwrite behavior, but the new code's file re-read creates an opportunity to use sync=false for merge semantics, preserving concurrent additions.

Consider changing to sync=false (or omitting the default) and adjusting the second test accordingly.

— qwen3.7-max via Qwen Code /review

);
});

it('setValue should preserve existing comments when rewriting the trust file', () => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] Both new error branches introduced by the comment-preserving save are untested:

  1. parse(originalContent) throwing when the file exists but is corrupted
  2. Validation parse(content) failing after stringify

Without tests, a future refactor could silently remove the validation guard or the fallback behavior without CI catching it. Consider adding tests that mock comment-json's parse to throw on the relevant call and assert that atomicWriteFileSync is not called (error path) or that the fallback clean write is used instead.

— qwen3.7-max via Qwen Code /review

}

let content: string;
if (fs.existsSync(trustedFoldersFile.path)) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The read → parse → applyUpdates → validate → write pipeline here (lines 185-201) is a near-exact duplicate of packages/cli/src/utils/commentJson.ts:updateSettingsFilePreservingFormat (lines 39-82). The only meaningful difference is the write mechanism (atomicWriteFileSync with noFollow vs writeWithBackupSync). A future maintainer who spots this duplication will see an obvious "refactor to reuse" — and by consolidating into updateSettingsFilePreservingFormat (which lacks noFollow), they silently drop the symlink-attack mitigation that is intentional here.

Consider either extracting a shared pure helper that returns prepared content (without writing), or adding a comment at this site documenting why the intentional divergence exists.

— qwen3.7-max via Qwen Code /review

@Zoean-z

Zoean-z commented Jun 4, 2026

Copy link
Copy Markdown
Author

Thanks - I pushed an update.

  • fall back to a clean rewrite if the comment-preserving path fails, so a corrupted rustedFolders.json can still self-heal on save
  • switched away from sync=true so disk-only entries are preserved during an update
  • added tests for the fallback branches
  • documented why this keeps the local round-trip instead of reusing the shared helper directly

Please take another look when you have a chance.

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Downgraded from Approve to Comment: CI still running.

All R1 findings have been addressed in this revision:

  • Self-healing regression → try/catch fallback to clean rewrite ✅
  • sync=true concern → author chose sync=false to preserve disk-only entries, with dedicated test ✅
  • Missing failure-path tests → 4 new tests covering parse failure, validation failure, comment preservation, and disk-only entry preservation ✅
  • Duplication with commentJson.ts → explanatory comment documenting the intentional divergence ✅

Deterministic: tsc ✅, eslint ✅, 25/25 tests ✅, build ✅. 9 review agents + reverse audit: 0 high-confidence Critical or Suggestion findings.

— qwen3.7-max via Qwen Code /review

@Zoean-z

Zoean-z commented Jun 4, 2026

Copy link
Copy Markdown
Author

All requested changes should be addressed now, and the required checks are green. Please take another look when convenient.


it('saveTrustedFolders should fall back to a clean rewrite when preserved output validation fails', () => {
const userPath = getTrustedFoldersPath();
const dirPath = path.dirname(userPath);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] This test does not actually exercise the validation-failure code path. The first mockImplementationOnce replaces parse with JSON.parse, but originalContent contains // work repos — a JSONC comment that JSON.parse cannot handle. So parse(originalContent) throws at the initial parse step (line ~198 of trustedFolders.ts), the catch block fires immediately, and execution never reaches the validation parse(preservedContent) at line ~208. The second mockImplementationOnce is never consumed.

This makes the test a duplicate of test 3 (parse-failure fallback). The validation-failure branch — where the round-trip succeeds but stringify produces unparseable output — remains untested.

Suggested change
const dirPath = path.dirname(userPath);
it('saveTrustedFolders should fall back to a clean rewrite when preserved output validation fails', () => {
const userPath = getTrustedFoldersPath();
const dirPath = path.dirname(userPath);
const originalContent = `{
// work repos
"/existing/path": "TRUST_FOLDER"
}`;
const parseSpy = vi.mocked(commentJson.parse);
(mockFsExistsSync as Mock).mockImplementation(
(p) => p === userPath || p === dirPath,
);
(fs.readFileSync as Mock).mockImplementation((p) => {
if (p === userPath) return originalContent;
return '{}';
});
// Let the first parse() call use the real comment-json parser (handles JSONC).
// Only mock the second call (validation step) to throw.
parseSpy.mockImplementationOnce(() => {
throw new Error('invalid preserved output');
});
saveTrustedFolders({
path: userPath,
config: {
'/new/path': TrustLevel.TRUST_FOLDER,
},
});
expect(atomicWriteFileSync).toHaveBeenCalledTimes(1);
expect(vi.mocked(atomicWriteFileSync).mock.calls[0]?.[1]).toBe(
`{\n "/new/path": "TRUST_FOLDER"\n}`,
);
});

— qwen3.7-max via Qwen Code /review

@Zoean-z

Zoean-z commented Jun 4, 2026

Copy link
Copy Markdown
Author

Thanks - good catch. I updated that test so the first parse call now uses the real comment-json parser, and only the validation-step parse is forced to throw. That means it now actually exercises the preserved-output validation failure branch instead of duplicating the corrupted-input fallback case.

Re-ran:

  • npm run test --workspace=packages/cli -- trustedFolders.test.ts
  • npm run typecheck --workspace=packages/cli

});
parseSpy.mockImplementationOnce(() => {
throw new Error('invalid preserved output');
});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] This mockImplementationOnce intercepts the first parse() call — parse(originalContent) at trustedFolders.ts:196 — not the validation parse(preservedContent) at line 207. Execution throws here and jumps to the catch block before applyUpdates, stringify, or the validation parse are ever reached. This makes test 4 functionally identical to test 3 ("fails during parse"); the validation-failure branch at line 207 remains untested.

To fix: let the first parse call succeed with the real implementation, and throw only on the second call:

Suggested change
});
parseSpy
.mockImplementationOnce((...args: Parameters<typeof commentJson.parse>) =>
commentJson.parse(...args),
)
.mockImplementationOnce(() => {
throw new Error('invalid preserved output');
});

— qwen3.7-max via Qwen Code /review

@Zoean-z

Zoean-z commented Jun 5, 2026

Copy link
Copy Markdown
Author

Thanks - you were right. The previous version still intercepted the first parse() call.

I updated the test so that:

  • the first parse(originalContent) call explicitly uses the real comment-json parser
  • only the second parse(preservedContent) validation call throws

That means this test now actually exercises the validation-failure branch instead of duplicating the corrupted-input fallback case.

Re-ran:

  • npm run test --workspace=packages/cli -- trustedFolders.test.ts
  • npm run typecheck --workspace=packages/cli

);
const parsed = parse(originalContent) as Record<string, unknown>;
const updated = applyUpdates(
parsed,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] Top-level array in trustedFolders.json causes silent trust-data loss, bypassing the self-healing fallback.

parse(originalContent) can return a CommentArray when the file contains [] or [1,2,3]. Unlike the load path (loadTrustedFolders, line 147) which has an explicit Array.isArray(parsed) guard, the save path has no type check. The downstream consequences are:

  1. applyUpdates(array, config, false) sets string keys (e.g. "/home/user/project-a") as non-numeric own properties on the array.
  2. comment-json.stringify(array) only serializes numeric indices, producing [] — all config entries are silently dropped.
  3. The validation parse("[]") succeeds (it is valid JSON), so the catch block is never triggered.
  4. content = "[]" overwrites the correct clean fallback.
  5. atomicWriteFileSync writes [] to disk — all trust decisions are destroyed.

Add the same structural guard the load path uses:

Suggested change
parsed,
const parsed = parse(originalContent);
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
throw new Error('trusted folders file is not a JSON object');
}
const updated = applyUpdates(
parsed as Record<string, unknown>,

— qwen3.7-max via Qwen Code /review

parse(preservedContent);
content = preservedContent;
} catch {
// Fall back to a clean rewrite when comment-preserving round-trip fails.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The catch block is empty, so when comment preservation fails the user's comments are silently stripped with no diagnostic output. The reference implementation updateSettingsFilePreservingFormat() in commentJson.ts (lines 48-55, 71-79) logs via writeStderrLine in every failure branch — writeStderrLine is already imported in this file.

Adding a one-line log makes silent degradation diagnosable (e.g. after a comment-json version bump that changes parser behavior):

Suggested change
// Fall back to a clean rewrite when comment-preserving round-trip fails.
} catch (error) {
// Fall back to a clean rewrite when comment-preserving round-trip fails.
writeStderrLine(
`Falling back to clean rewrite for trusted folders: ${error instanceof Error ? error.message : String(error)}`,
);
}

— qwen3.7-max via Qwen Code /review

@Zoean-z

Zoean-z commented Jun 5, 2026

Copy link
Copy Markdown
Author

Thanks - I pushed another update.

Changes in this revision:

  • added the same JSON-object guard in saveTrustedFolders() that loadTrustedFolders() already uses, so top-level arrays now trigger the clean fallback path instead of silently dropping trust entries
  • added a stderr diagnostic when the comment-preserving round-trip falls back to a clean rewrite
  • added test coverage for the top-level array fallback and the fallback diagnostic

I also re-ran:

  • npm run test --workspace=packages/cli -- trustedFolders.test.ts
  • npm run typecheck --workspace=packages/cli

typeof parsed !== 'object' ||
parsed === null ||
Array.isArray(parsed)
) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] comment-json.parse() wraps JSON primitives ("hello", 42, true) in CommentObject instances that are typeof === 'object', non-null, non-Array — passing all three type-guard checks. When applyUpdates sets string keys on a wrapper like new String("hello") and stringify serializes it, the config entries are silently dropped and only the primitive value is written to disk.

The self-healing fallback is never reached because no exception is thrown — the validation parse(preservedContent) succeeds since the primitive is valid JSON. Verified empirically: parse('"hello"')instanceof String === true, and after mutation + stringify"hello" (all config entries lost).

Suggested change
) {
if (
typeof parsed !== 'object' ||
parsed === null ||
Array.isArray(parsed) ||
parsed instanceof String ||
parsed instanceof Number ||
parsed instanceof Boolean
) {

— qwen3.7-max via Qwen Code /review

);
(fs.readFileSync as Mock).mockImplementation((p) => {
if (p === userPath) return originalContent;
return '{}';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] mockImplementationOnce((...args) => commentJson.parse(...args)) calls the spy itself (since commentJson.parse IS the mock), which consumes the second mockImplementationOnce (the throw). The throw therefore happens during parse(originalContent) — not parse(preservedContent) as the test name claims. The test passes only because both failures hit the same catch block, but the "validation failure" code path at trustedFolders.ts:213 is never actually exercised.

A symptom of this: the test is missing the writeStderrLine assertion that the other two fallback tests include.

Fix: use vi.importActual to get the real parse reference, avoiding the self-call:

const actualCommentJson = await vi.importActual<typeof commentJson>('comment-json');
parseSpy
  .mockImplementationOnce((...args: Parameters<typeof commentJson.parse>) =>
    actualCommentJson.parse(...args),
  )
  .mockImplementationOnce(() => {
    throw new Error('invalid preserved output');
  });

— qwen3.7-max via Qwen Code /review

content,
// noFollow: refuse to follow any pre-placed symlink at the
// config path a redirected write could either leak the
// config path 鈥?a redirected write could either leak the

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The em-dash (U+2014, bytes e2 80 94) was corrupted to mojibake 鈥? (bytes e9 88 a5 3f). On origin/main the line reads // config path — a redirected write but the PR branch reads // config path 鈥?a redirected write. This suggests an encoding conversion error in the editing environment.

Suggested change
// config path 鈥?a redirected write could either leak the
// config path a redirected write could either leak the

The same corruption also appears in trustedFolders.test.ts:222 (// posture 鈥?a pre-placed symlink// posture — a pre-placed symlink).

— qwen3.7-max via Qwen Code /review

@Zoean-z

Zoean-z commented Jun 5, 2026

Copy link
Copy Markdown
Author

Thanks - I pushed another update addressing the latest review points.

Changes in this revision:

  • reject comment-json primitive wrapper outputs (String, Number, Boolean) in saveTrustedFolders() so top-level primitives fall back to a clean rewrite instead of silently dropping trust entries
  • fixed the validation-failure test to call the real comment-json parser via vi.importActual() for the first parse, then fail only the validation parse
  • added coverage for top-level string/number/boolean fallback cases
  • replaced the corrupted comment text with ASCII punctuation to avoid the mojibake issue

Re-ran:

  • npm run test --workspace=packages/cli -- trustedFolders.test.ts (29 passed)
  • npm run typecheck --workspace=packages/cli

);
});

it.each(['"hello"', '42', 'true'])(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The parsed === null branch in the type guard (trustedFolders.ts:199) has no test coverage. comment-json.parse('null') returns literal null (typeof 'object', === null true), which the guard catches — but no test exercises this path.

Suggested change
it.each(['"hello"', '42', 'true'])(
it.each(['"hello"', '42', 'true', 'null'])(

The existing assertion ('trusted folders file is not a JSON object') already matches.

— qwen3.7-max via Qwen Code /review

@Zoean-z

Zoean-z commented Jun 5, 2026

Copy link
Copy Markdown
Author

Thanks - added null to the top-level primitive fallback coverage.

Re-ran:

  • npm run test --workspace=packages/cli -- trustedFolders.test.ts (30 passed)
  • npm run typecheck --workspace=packages/cli

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No review findings — code looks good. Downgraded from Approve to Comment: CI failing (Test on ubuntu/macos/windows, Lint). — qwen3.7-max via Qwen Code /review

@wenshao

wenshao commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

Local Verification Report

Branch: fix-trusted-folders-preserve-commentsmain
Environment: macOS Darwin 25.4.0, Node.js local

TypeScript Compilation (tsc --noEmit)

Package PR Branch main Status
packages/core 7 errors 7 errors ✅ No new errors
packages/cli 81 errors 109 errors ✅ No new errors (fewer than main due to branch divergence)

All errors are pre-existing (vite plugin type mismatches in sdk-typescript, check-i18n.ts script issues, @modelcontextprotocol/sdk resolution).

Unit Tests (vitest)

Test File PR Branch main Status
trustedFolders.test.ts 30 passed 21 passed ✅ All pass (+9 new tests)

New tests cover:

  • Preserving existing comments when rewriting trusted folders
  • Preserving disk-only entries when updating
  • Fallback to clean rewrite on parse failure
  • Fallback on validation failure
  • Handling of array/primitive top-level files gracefully

CI Failure Analysis

CI build fails on src/tools/skill.ts(465,30): error TS2322 — this file is NOT modified by this PR. The error is a pre-existing type assignment issue unrelated to this change. See branch fix/skill-ts-type-error for the fix.

Code Review Notes

  • saveTrustedFolders() now preserves comments via comment-json parse/stringify with applyUpdates() round-trip
  • Validates serialized output before writing — falls back to clean rewrite on any failure (self-healing)
  • Maintains security posture: atomicWriteFileSync with noFollow: true and mode: 0o600
  • No new dependencies added (comment-json and applyUpdates already used elsewhere in the codebase)

Verdict

Ready to merge — No regressions introduced. All new tests pass. CI failure is unrelated pre-existing issue.

xaelistic pushed a commit to xaelistic/qwen-code that referenced this pull request Jun 7, 2026
@tanzhenxin tanzhenxin added the type/bug Something isn't working as expected label Jun 8, 2026

@DragonnZhang DragonnZhang left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Verdict: No new findings. Code looks good.

This revision addresses all 12 prior inline comments from the previous review rounds:

  • Self-healing regression -- resolved via try/catch fallback to clean rewrite with stderr diagnostic.
  • sync=true concern -- resolved by choosing sync=false to preserve concurrent-process disk entries.
  • Untested error branches -- resolved with comprehensive tests for parse failure, validation failure, top-level array, and top-level primitives (including null).
  • Duplication with updateSettingsFilePreservingFormat -- acceptable; inline comment explains the rationale (must use atomicWriteFileSync with noFollow:true).
  • Test mock ordering issues -- resolved; first mockImplementationOnce now correctly delegates to the real comment-json.parse.
  • Top-level array/primitive bypass -- resolved with Array.isArray, === null, and instanceof String/Number/Boolean guards.
  • Empty catch block -- resolved with writeStderrLine diagnostic.
  • Em-dash mojibake -- changed to plain hyphen (minor style regression from original em-dash, but acceptable).

Deterministic checks: tsc and eslint produced 0 findings on changed files.

Downgraded from Approve to Comment: CI still failing (Test on ubuntu/macos/windows, Lint). Once CI is green, this should be ready to merge.

— qwen-code via Qwen Code /review

@DragonnZhang DragonnZhang left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No review findings. Downgraded from Approve to Comment: CI failing (Test on ubuntu/macos/windows, Lint). — qwen3-coder-480b-a35b-instruct via Qwen Code /review

@Zoean-z

Zoean-z commented Jun 10, 2026

Copy link
Copy Markdown
Author

The current failing CI run appears to be stale. It started before #4804 was merged and fails during install/build on packages/core/src/tools/skill.ts(465,30), before lint/tests run. That file is not touched by this PR, and #4804 fixed that build break afterward.

Could you please rerun the checks when convenient?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type/bug Something isn't working as expected

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chore(cli): trustedFolders.json writer strips user comments (follow-up from #3861)

4 participants