Skip to content

fix(market): quote @-prefixed patch row ids to avoid invalid YAML - #288

Closed
ump45nose wants to merge 1 commit into
dataelement:mainfrom
ump45nose:fix/market-patch-row-id-quote
Closed

fix(market): quote @-prefixed patch row ids to avoid invalid YAML#288
ump45nose wants to merge 1 commit into
dataelement:mainfrom
ump45nose:fix/market-patch-row-id-quote

Conversation

@ump45nose

Copy link
Copy Markdown
Contributor

Summary

Disabling a @scope/name plugin through the market wrote - id: @scope/name (unquoted) into cordis.patch.yml. Because @ is a reserved YAML indicator, the overlay fails to parse and the profile refuses to boot (issue #241). The existing ROW_ID_RE check only refused the write, which turned disabling scoped plugins into a silent no-op.

This change serializes a non-plain row id as a double-quoted YAML scalar ("@scope/name") and teaches the line scanner to read quoted ids back, so the disable round-trips and the written overlay stays valid YAML.

Changes

  • packages/dshmarket/src/patch.ts (and its compiled lib/patch.js):
    • rowBlock quotes ids that are not plain scalars via a new yamlRowId helper.
    • readUserPatchState parses both plain and double-quoted ids.
    • disableRow / enableRow no longer refuse @-scoped ids.

Validation

  • Standalone round-trip check: @dhicoc/dsh-reverse-skill → written as - id: "@dhicoc/dsh-reverse-skill" and read back as the same id; plain ids (foo, a.b-c_d) stay unquoted; include:foo and @scope/pkg/sub are quoted.
  • node --check passes on lib/patch.js.
  • Full vitest suite not run locally (no node_modules in this checkout).

Fixes #241

`rowBlock` wrote `- id: ${rowId}` verbatim. Loader entry ids may be
npm package names such as `@scope/name`; a leading `@` is a reserved
YAML indicator, so `- id: @scope/name` is not valid YAML and the
profile overlay fails to parse, which stops the Harness from booting.
The previous `ROW_ID_RE` guard merely refused to write such ids, which
silently broke disabling scoped plugins.

Serialize non-plain ids as double-quoted YAML scalars and teach the
line scanner to read them back, so scoped plugins can be disabled
correctly.

Fixes dataelement#241.
@yaojin3616

Copy link
Copy Markdown
Contributor

Thanks for the PR!

After testing enabling and disabling plugins (including scoped packages), we could not reproduce the issue.

Specifically:

  1. Existing protection in codebase: disableRow and enableRow already check ROW_ID_RE = /^[A-Za-z0-9_.-]+$/u. If an ID contains special characters like @ or /, the write to cordis.patch.yml is safely rejected (ok: false, reason: '行 id 含特殊字符,不支持写入补丁层'), preventing any invalid unquoted YAML from being written. The toggle state is instead safely tracked in .dsh-market/state.json.
  2. Investigation into [Bug] macOS 0.7.0:自动迁移 generations 失败(dsh-type-meta 404)后写坏 cordis.patch.yml(@ 开头 id 未加引号),导致 Harness 无法启动 #241: The invalid YAML snippet reported in [Bug] macOS 0.7.0:自动迁移 generations 失败(dsh-type-meta 404)后写坏 cordis.patch.yml(@ 开头 id 未加引号),导致 Harness 无法启动 #241:
    82 | # 2026-08-29: 临时禁用 @dhicoc/dsh-reverse-skill 直至其 peer 依赖与 app 内置版本兼容
    83 | - id: @dhicoc/dsh-reverse-skill
    84 |   disabled: true
    was actually manually added to cordis.patch.yml by the user (as indicated by the dated Chinese comment), rather than generated by the market or migration mechanism.

Closing this PR accordingly. Thank you again for your contribution!

@yaojin3616 yaojin3616 closed this Sep 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants