Skip to content

fix(config): name the offending rules item when a list is malformed - #1984

Merged
clay-good merged 2 commits into
Fission-AI:mainfrom
Yi-111-a:fix/config-rules-name-offending-item
Sep 29, 2026
Merged

clay-good merged 2 commits into
Fission-AI:mainfrom
Yi-111-a:fix/config-rules-name-offending-item

Conversation

@Yi-111-a

@Yi-111-a Yi-111-a commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

A rule item containing an unquoted ": " is valid-looking YAML, but YAML parses it as a mapping. The list then stops being an array of strings, the artifact's entire rule set is dropped, and the only signal is a warning on stderr that names the artifact but not the item — so the bad entry has to be found by bisecting the list by hand.

This takes the first of the three suggestions in #1891 and makes the warning point at the exact item and how to fix it:

-Rules for 'proposal' must be an array of strings, ignoring this artifact's rules
+Rules for 'proposal' must be an array of strings, ignoring this artifact's rules. rules.proposal[0] is a mapping — an unquoted ": " makes YAML read the item as a key/value pair; quote the whole scalar to keep it a string.

Every offending index is named with the shape YAML produced there (a mapping, a number, a nested list, null), so a list with more than one bad item doesn't need re-bisecting either.

Parsing behavior is unchanged — the malformed artifact's rules are still dropped wholesale, and well-formed sibling artifacts are still loaded. Only the warning text is more precise, so this is a diagnostic fix and not a change of contract. Deciding whether validate should surface config problems too, and whether a single bad item should still take out its siblings, are the other two suggestions from #1891; those are behavior changes and belong in their own PR after the maintainers weigh in.

Closes #1891

Changes

  • src/core/project-config.ts — new describeRulesShapeError() builds the warning and describeYamlType() names a value's YAML shape. The existing console.warn call site is unchanged apart from delegating to the helper, so the original sentence is still a prefix of every message.
  • test/core/project-config.test.ts — two regression tests: the reported mapping case (asserting the drop behavior is unchanged alongside the new index/shape/hint in the message), and a mixed list with two mappings and a number. The pre-existing "filter out invalid rules" test gained one assertion for the non-list case.
  • .changeset/tidy-moons-tap.md — patch changeset.

Testing

pnpm exec tsc --noEmit, pnpm lint, and pnpm build are clean. test/core/project-config.test.ts passes at 57/57.

I reproduced the report against a built CLI first, and confirmed the advice is correct: on the issue's exact config.yaml, new change printed the improved warning naming rules.proposal[0], and after quoting that scalar the same config loads all 3 rules with no warning.

Full pnpm test on this branch: 5937 passed, 4 failed. All 4 are unrelated to this change:

  • test/package-install-scripts.test.ts (3) — run npm install against the network. Confirmed failing identically on a clean main with my changes stashed.
  • test/commands/artifact-workflow.test.ts (1) and test/commands/store-references.test.ts (1) — 10s timeouts under full-suite parallel load. Both pass in isolation with this branch built.

AI Disclosure

Written with OpenCode (opencode/space-bunny-free). I ran the gate above and verified the before/after against a real CLI build rather than only through the unit tests.

Summary by CodeRabbit

  • Bug Fixes
    • Improved warnings for invalid artifact rules. Messages now identify malformed items by their zero-based index and parsed YAML shape, and explain when quoting : can prevent an item from being interpreted as a mapping.

A rule item containing an unquoted ": " is valid-looking YAML but parses as
a mapping, so the artifact's whole rule set is dropped. The warning named only
the artifact, so the bad item had to be found by bisecting the list by hand.

Name every offending index with the shape YAML produced there, and point at the
quoting fix when a mapping is the cause. Parsing behavior is unchanged.
@Yi-111-a
Yi-111-a requested a review from a team as a code owner September 26, 2026 01:18
@Yi-111-a
Yi-111-a requested review from clay-good and removed request for a team September 26, 2026 01:18
@coderabbitai

coderabbitai Bot commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: Fission-AI/OpenSpec/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 41dfc7b4-47db-4b71-b5aa-b3a77fc49090

📥 Commits

Reviewing files that changed from the base of the PR and between f63692c and 0c47e15.

📒 Files selected for processing (1)
  • test/core/project-config.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review.


📝 Walkthrough

Walkthrough

Artifact rule warnings now describe invalid YAML values and identify each non-string list item by index and shape. For a mapping item, the warning includes a quoting hint. Tests cover malformed items and valid sibling rules.

Changes

Artifact rule diagnostics

Layer / File(s) Summary
Report malformed artifact rules
src/core/project-config.ts, test/core/project-config.test.ts, .changeset/tidy-moons-tap.md
Warnings describe non-array rule values by shape and identify each non-string list item by index and shape. Mapping items trigger a hint about quoting the scalar. Tests check these warnings and confirm valid sibling artifacts remain.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 0c47e

This change improves malformed-rule warnings without changing which artifacts load; valid sibling rules remain available. No merge-blocking concern is evident, subject to normal checks.

Architecture Summary

Architecture risk: 🔵 Low · up to 0c47e

The change affects 2 systems.

Changed systems: src, test

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — src (service) was modified; 1 changed file maps to changed impact.
  • observed — test (service) was modified; 1 changed file maps to changed impact.

Before / after behavior

  • observed — Modified behavior in src/core/project-config.ts: Added helpers that describe YAML value shapes and construct artifact-rules warnings. Non-arrays are reported by shape; arrays with non-string entries report each offending index and shape, with a quoting hint when an invalid entry is a mapping.
  • observed — Modified behavior in src/core/project-config.ts: Invalid artifact rules now use the detailed shape diagnostic instead of the previous generic warning.
  • observed — Modified behavior in test/core/project-config.test.ts: Added an assertion that a string-valued rules.specs warning identifies the parsed shape as a string.
  • observed — Modified behavior in test/core/project-config.test.ts: Added coverage for a rule parsed as a mapping: its artifact’s rule set is omitted while valid rules for another artifact remain, and the warning identifies the index and mapping shape, explains the unquoted ": " parsing issue, and recommends quoting the scalar.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: malformed rules lists now identify the offending item. It is concise and specific.
Linked Issues check ✅ Passed The PR meets the relevant coding objective in issue #1891. src/core/project-config.ts identifies each invalid item as rules.<artifact>[<index>], reports its parsed YAML shape, and suggests quoting…
Out of Scope Changes check ✅ Passed The source change improves diagnostics for the malformed rules: condition from issue #1891. The tests verify the diagnostic and preserve existing parsing behavior. The changeset documents the same u…
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 2 files.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@clay-good

Copy link
Copy Markdown
Collaborator

Maintainer validation on 0c47e15:

  • Added regression assertions for null and nested-list rule items, matching the warning shapes promised in the PR description.
  • Project-config regression suite: 57/57 passed.
  • TypeScript type-check, ESLint, production build, and diff check passed.
  • Full suite: 5,937/5,941 passed. The 4 failures are unrelated tooling tests and reproduce identically on the base commit 79b6aa9; this PR introduces no new failures.
  • Diff is scoped to the config warning, its tests, and the patch changeset. Parsing behavior remains unchanged.

Ready for maintainer approval and merge.

@alfred-openspec alfred-openspec 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.

Approved at 0c47e15. The diagnostic now identifies every malformed rules item by zero-based index and parsed YAML shape, adds the useful quoting fix for mappings, and leaves parsing behavior unchanged. The focused project-config suite passes locally: 57 tests.

@clay-good
clay-good added this pull request to the merge queue Sep 29, 2026
Merged via the queue into Fission-AI:main with commit 42671df Sep 29, 2026
14 checks passed
clay-good added a commit to TigerkidYang/OpenSpec that referenced this pull request Oct 1, 2026
…ommands

Rebased onto main, where Fission-AI#1984 already names the offending rules item but
keeps dropping the whole artifact. This PR's per-item parsing supersedes it,
so the Fission-AI#1984 tests now assert the per-item result and its leftover helpers
are removed.

Hardening for configs every command already tolerates:
- An empty or comment-only config.yaml parses to null. It was reported as
  "not a valid YAML object" and failed `validate --all`; it is now treated
  like a missing config.
- A key left empty in YAML (`rules:` with its entries commented out, a bare
  `-` item, `context:`) and empty-string rules or guidance lose nothing the
  author wrote, so they are warnings (fail only under --strict), not errors.
- Unknown top-level keys are reported only by inspectProjectConfig
  (validate). readProjectConfig keeps ignoring them silently, so other
  commands do not start printing new stderr warnings.

Documents the config check under `openspec validate` in docs/cli.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Config rules: an unquoted ": " in a rules item silently drops the artifact's entire rule set

4 participants