Skip to content

feat: add LikeC4 DSL skill with references#2782

Merged
davydkov merged 13 commits intomainfrom
likec4-dsl-skill
Mar 24, 2026
Merged

feat: add LikeC4 DSL skill with references#2782
davydkov merged 13 commits intomainfrom
likec4-dsl-skill

Conversation

@davydkov
Copy link
Copy Markdown
Member

@davydkov davydkov commented Mar 20, 2026

Summary

  • Add LikeC4 DSL skill with comprehensive reference documentation
  • Add skill integration with docs site via astro-skills plugin
  • Reference docs for views, predicates, deployment, dynamic views, and configuration

CLI improvements split into #2790.

Test plan

  • Skill files are correctly structured
  • Docs site builds with astro-skills plugin
  • Skill symlink works for local Claude discovery

🤖 Generated with Claude Code

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 20, 2026

🦋 Changeset detected

Latest commit: e116d90

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 20 packages
Name Type
likec4 Patch
@likec4/docs-astro Patch
likec4-vscode Patch
@likec4/playground Patch
@likec4/style-preset Patch
@likec4/styles Patch
@likec4/config Patch
@likec4/core Patch
@likec4/diagram Patch
@likec4/generators Patch
@likec4/language-server Patch
@likec4/language-services Patch
@likec4/layouts Patch
@likec4/leanix-bridge Patch
@likec4/log Patch
@likec4/mcp Patch
@likec4/react Patch
@likec4/tsconfig Patch
@likec4/vite-plugin Patch
@likec4/vscode-preview Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 20, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This pull request introduces a new LikeC4 DSL skill for Astro documentation integration, including comprehensive skill documentation, Astro integration setup, and targeted updates to language services error handling and CLI environment detection.

Changes

Cohort / File(s) Summary
Astro Integration Setup
apps/docs/astro.config.mjs, apps/docs/src/content.config.ts, apps/docs/package.json
Added astro-skills integration to Astro configuration, created skills content collection with skillsLoader, and added required dependencies to devDependencies.
Workspace & Catalog Configuration
pnpm-workspace.yaml, .claude/skills/likec4-dsl
Added astro-skills: ^0.0.5 to the Astro catalog and created a skills reference file pointing to the likec4-dsl skill directory.
LikeC4 DSL Skill Documentation
skills/likec4-dsl/SKILL.md, skills/likec4-dsl/references/*
Added comprehensive skill documentation including main skill definition (SKILL.md), configuration reference (configuration.md), predicate system (predicates.md), views feature guide (views.md), CLI reference (cli.md), and practical examples (examples.md).
Language Services
packages/language-services/src/common/LikeC4.ts
Removed shared error truncation helper; moved truncation logic into printErrors() method. Added documentCount(): number method to LikeC4 class. Changed error object to contain full diagnostic message instead of pre-truncated version.
CLI Environment Detection
packages/likec4/src/cli/check-update/utils.ts
Modified update notification suppression in notifyAvailableUpdate to return early when running in CI or test environments, in addition to existing check-update environment checks.
Release Management
.changeset/ai-coding-agent-skill.md
Added changeset declaring patch release for likec4 package.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • feat: add format command #2667: Modifies the same LikeC4 class in packages/language-services/src/common/LikeC4.ts with different enhancements (format API vs. error handling changes).
  • Lsp refactor #2681: Updates the same packages/language-services/src/common/LikeC4.ts file with import cleanup changes.
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add LikeC4 DSL skill with references' clearly summarizes the main change: adding a new LikeC4 DSL skill with documentation references to the codebase.
Description check ✅ Passed The PR description covers the main changes (skill addition, documentation, integration), provides a test plan, and acknowledges related work. However, it does not address several checklist items from the template (rebasing, conventional commits, tests added, documentation verification).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch likec4-dsl-skill

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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

🧹 Nitpick comments (8)
skills/likec4-dsl/references/configuration.md (2)

166-170: Clarify extends examples presentation.

Having two separate JSON objects on consecutive lines without explanation may confuse readers. Consider clarifying these are alternative examples.

📝 Suggested improvement
 ### `extends`

 Inherit styles from other config files (JSON only). Single path or array.

+Single path:
+
 ```json
 { "extends": "../shared/likec4.config.json" }
-{ "extends": ["../shared/base.json", "../shared/theme.json"] }
+```
+
+Multiple paths:
+
+```json
+{ "extends": ["../shared/base.json", "../shared/theme.json"] }
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @skills/likec4-dsl/references/configuration.md around lines 166 - 170, The
two consecutive JSON objects shown as examples for "extends" are ambiguous;
update the section in configuration.md so each example is clearly labeled and
separated (e.g., "Single path:" with { "extends": "../shared/likec4.config.json" } and "Multiple paths:" with { "extends": ["../shared/base.json", "../shared/theme.json"] }), wrap each example in its
own JSON code fence, and add a one-line explanatory note that they are
alternative usages of the extends property to avoid confusion.


</details>

---

`214-225`: **Consider adding a language identifier to the directory tree block.**

The directory structure block triggers a markdown lint warning. Using `text` or leaving it as-is are both acceptable, but adding a language identifier improves consistency.

<details>
<summary>📝 Suggested fix</summary>

```diff
-```
+```text
 workspace/
 ├─ project-a/
 │  ├─ likec4.config.json    ← project "a"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/likec4-dsl/references/configuration.md` around lines 214 - 225, Update
the code block in configuration.md that shows the directory tree to include a
language identifier (e.g., change the opening fence from ``` to ```text) so the
markdown linter stops warning about an unspecified language; locate the
directory structure block under the example workspace (the triple-backtick block
containing workspace/, project-a/, project-b/, shared/) and add the language tag
to the opening fence.
skills/likec4-dsl/references/predicates.md (1)

13-18: Consider adding a language identifier to the grammar code block.

The syntax grammar block lacks a language identifier. While BNF/EBNF doesn't have a standard markdown identifier, using text or bnf improves consistency and avoids linter warnings.

📝 Suggested fix
-```
+```text
 BASE_PREDICATE ::= WILDCARD | ELEMENT_EXPRESSION | RELATIONSHIP_EXPRESSION
 FILTER_PREDICATE ::= BASE_PREDICATE where FILTER_CONDITIONS
 CUSTOM_PREDICATE ::= (BASE_PREDICATE | FILTER_PREDICATE) with { ... }
 PREDICATE ::= BASE_PREDICATE | FILTER_PREDICATE | CUSTOM_PREDICATE
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @skills/likec4-dsl/references/predicates.md around lines 13 - 18, Add a
language identifier to the fenced code block containing the grammar (the block
with BASE_PREDICATE, FILTER_PREDICATE, CUSTOM_PREDICATE, PREDICATE) to satisfy
linters and improve consistency; change the opening fence from totext
(or ```bnf) so the grammar lines (BASE_PREDICATE ::= WILDCARD |
ELEMENT_EXPRESSION | RELATIONSHIP_EXPRESSION, FILTER_PREDICATE ::=
BASE_PREDICATE where FILTER_CONDITIONS, CUSTOM_PREDICATE ::= (BASE_PREDICATE |
FILTER_PREDICATE) with { ... }, PREDICATE ::= BASE_PREDICATE | FILTER_PREDICATE
| CUSTOM_PREDICATE) are inside a labeled block.


</details>

</blockquote></details>
<details>
<summary>skills/likec4-dsl/references/views.md (1)</summary><blockquote>

`84-93`: **Align dynamic-view grammar with the ordering explanation.**

The prose explains `exclude` ordering, but `DYNAMIC_VIEW_RULES` only lists `STEP` and style rules. Consider adding `include`/`exclude` entries (or narrowing the prose) to avoid ambiguity.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@skills/likec4-dsl/references/views.md` around lines 84 - 93, The grammar and
prose disagree: the DYNAMIC_VIEW_RULES production lists only STEP and
DYNAMIC_VIEW_STYLE_RULE but the text discusses include/exclude ordering; update
the grammar to reflect the described ordering by adding tokens/productions for
include and exclude (e.g., INCLUDE_STEP / EXCLUDE_STEP or explicit INCLUDE_RULE
/ EXCLUDE_RULE entries) into DYNAMIC_VIEW_RULES so rules are applied in
sequence, or alternatively adjust the prose to remove mention of include/exclude
and describe only the existing STEP/style semantics; reference
DYNAMIC_VIEW_RULES, STEP, and DYNAMIC_VIEW_STYLE_RULE when making the change.
```

</details>

</blockquote></details>
<details>
<summary>packages/language-services/src/common/LikeC4.ts (3)</summary><blockquote>

`21-23`: **Consider documenting the magic number for severity.**

The value `1` corresponds to `DiagnosticSeverity.Error` from `vscode-languageserver-types`. Since the import was removed, consider adding a brief comment to clarify this mapping for future maintainers.

```diff
+// DiagnosticSeverity.Error === 1 (from vscode-languageserver-types)
 const isErrorDiagnostic = (diagnostic: { severity?: number }): boolean => {
   return diagnostic.severity === 1
 }
```

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@packages/language-services/src/common/LikeC4.ts` around lines 21 - 23, The
function isErrorDiagnostic uses a magic number (1) for diagnostic.severity;
document that mapping by adding a brief inline comment near isErrorDiagnostic
explaining that 1 corresponds to DiagnosticSeverity.Error (from
vscode-languageserver-types) so future maintainers understand the value without
the import; keep the function logic unchanged and place the comment next to the
isErrorDiagnostic declaration or the diagnostic.severity comparison.
```

</details>

---

`204-209`: **Simplify `documentCount()` implementation.**

The `toArray()` call creates an intermediate array just to get the length. Consider using a more direct approach if the stream supports it, or document why `toArray()` is necessary.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@packages/language-services/src/common/LikeC4.ts` around lines 204 - 209,
documentCount() builds an intermediate array via
this.LangiumDocuments.all.toArray().length; replace it with a direct count to
avoid allocation: if this.LangiumDocuments.all exposes a size/length property
use return this.LangiumDocuments.all.size (or .length), otherwise iterate the
iterable and increment a counter (e.g. let c=0; for (const _ of
this.LangiumDocuments.all) c++; return c;). Update the documentCount() method
accordingly (referencing documentCount and LangiumDocuments.all).
```

</details>

---

`165-167`: **Use optional chaining for cleaner code.**

As flagged by static analysis, the condition can be simplified using optional chaining.

<details>
<summary>♻️ Proposed fix</summary>

```diff
   hasErrors(): boolean {
     return this.LangiumDocuments.userDocuments.some(doc => {
-      return doc.diagnostics && doc.diagnostics.some(isErrorDiagnostic)
+      return doc.diagnostics?.some(isErrorDiagnostic) ?? false
     })
   }
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@packages/language-services/src/common/LikeC4.ts` around lines 165 - 167,
Replace the manual null-check with optional chaining: in the expression that
inspects this.LangiumDocuments.userDocuments, change the predicate to use
doc.diagnostics?.some(isErrorDiagnostic) so the some() call is only invoked when
diagnostics exists; reference the LangiumDocuments.userDocuments array and the
isErrorDiagnostic function when making this change.
```

</details>

</blockquote></details>
<details>
<summary>packages/likec4/src/cli/validate/index.ts (1)</summary><blockquote>

`146-151`: **Stats `filteredFiles` may be misleading when no filter is applied.**

When `fileFilter` is null, `filteredFiles` is set to `totalFiles` (all workspace files). However, this doesn't represent files with errors—it represents all files. This could confuse consumers expecting `filteredFiles` to mean "files with errors in scope."

Consider renaming or documenting the semantics more clearly, or computing the actual count of files with errors.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@packages/likec4/src/cli/validate/index.ts` around lines 146 - 151, The stats
field currently sets filteredFiles to totalFiles when fileFilter is null, which
misrepresents "files with errors in scope"; change the logic so
stats.filteredFiles always reflects the count of files with errors in scope by
using filteredFileSet.size (i.e., set filteredFiles: filteredFileSet.size)
instead of conditional totalFiles, and ensure filteredFileSet is constructed to
contain only files that have errors (so filteredErrors and filteredFileSet
remain consistent); alternatively, if you prefer to keep the existing semantics,
rename filteredFiles to something explicit (e.g., scopedFileCount) and update
any callers/documentation accordingly.
```

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🤖 Prompt for all review comments with AI agents</summary>

Verify each finding against the current code and only fix it if needed.

Inline comments:
In @packages/language-services/src/common/LikeC4.ts:

  • Around line 172-200: printErrors() currently iterates
    this.LangiumDocuments.all causing inconsistency with getErrors()/hasErrors()
    which use this.LangiumDocuments.userDocuments; change the iteration in
    printErrors() to use this.LangiumDocuments.userDocuments, preserving the
    existing filtering (errors = doc.diagnostics?.filter(isErrorDiagnostic) ?? []),
    message truncation and logging logic so printed errors match what
    getErrors()/hasErrors() report for user documents only.
  • Around line 148-159: The truncation logic builds a messages array but never
    uses it in the errors.map callback, leaving dead code; fix by either removing
    the messages variable and its truncation block, or by returning the truncated
    text (e.g., set the returned object's message to the truncated value built
    from messages, e.g., join with '\n'); locate the callback where errors.map(({ message, range }) => { ... }) and update the message field in the returned
    object (or remove the unused messages block) accordingly, keeping range,
    line, and sourceFsPath: doc.uri.fsPath as-is.

In @packages/likec4/src/cli/validate/index.ts:

  • Around line 111-116: The fallback for resolving the file path creates entries
    like '/workspace/.' when view.sourcePath is undefined; update the resolve call
    in the layout error push (layoutErrors.push block) to use a better fallback than
    '.' — e.g., use an empty string or view.id (resolve(args.path, view.sourcePath
    ?? '', ) or resolve(args.path, view.sourcePath ?? view.id)) so reported file
    paths are meaningful; ensure you update the message/file pair consistently where
    view.sourcePath is referenced.
  • Around line 134-136: The current file filtering logic (building filteredErrors
    from allErrors using fileFilter and e.file.endsWith(f)) can yield false
    positives (e.g., "model.c4" matching "other-model.c4"); update the filter in
    validate/index.ts to perform a path-aware comparison: for each f in fileFilter
    compare against e.file using path utilities (e.g., path.basename(e.file) === f
    or normalize both paths and check equality or check endsWith with a path
    separator like ${path.sep}${f}) so matches respect directory boundaries;
    adjust the filtering loop that constructs filteredErrors (references:
    filteredErrors, fileFilter, allErrors, e.file) to use the chosen path-based
    comparison and ensure both relative and absolute paths are normalized before
    comparison.
  • Around line 119-126: The catch currently lumps all errors into layoutErrors;
    change it so infrastructure errors from ensureProjectId are surfaced as
    fatal/descriptive errors while only actual layout validation failures are pushed
    to layoutErrors. Concretely: in the catch near layoutErrors push, detect
    infrastructure errors from ensureProjectId (preferably by making/using a
    specific error class like ProjectNotRegisteredError or checking e.name/e.message
    for the known ensureProjectId failure texts) and for those call process.exit(1)
    or rethrow a clear Error (e.g., Project ID X is not registered); otherwise
    (non-infrastructure errors) keep the existing behavior of pushing a diagnostic
    into layoutErrors. Update imports/signatures to use the specific error class if
    you add one and reference ensureProjectId, layoutErrors and the current catch
    block when making the change.

In @skills/likec4-dsl/references/configuration.md:

  • Around line 176-185: The code block contains inline JavaScript-style comments
    which are invalid in standard JSON; update the examples around the "landingPage"
    object to either remove the comment lines or mark the fences as json5 if
    comments are intended. Specifically, provide three separate valid code blocks
    showing the "landingPage" examples (one with { "landingPage": { "redirect": true
    } }, one with { "landingPage": { "include": ["overview","cloud-detail"] } }, and
    one with { "landingPage": { "exclude": ["internal-debug"] } }) and remove the
    leading // comments (or change the triple-backtick fence to ```json5 if you want
    to keep comments).

In @skills/likec4-dsl/references/deployment.md:

  • Around line 171-174: The documentation's style block references an undefined
    node "server4" (style server1., server4. { color green }) while the deployment
    example only defines server1, server2, and server3; update the example to
    include a server4 definition or change the style rule to reference an existing
    node (e.g., replace server4._ with server2._ or server3.) so the FQN in the
    style rule matches an actual deployment node (look for the deployment model
    definitions for server1/server2/server3 and the style block containing
    server1.
    , server4._).

In @skills/likec4-dsl/references/dynamic-views.md:

  • Line 3: The fenced code block in dynamic-views.md is missing a language tag
    which triggers MD040; update the opening triple-backtick fence for the
    tree-style block to include the language tag "text" (i.e., change ``` to

In `@skills/likec4-dsl/references/predicates.md`:
- Line 26: The example predicate `include * where tag s `#production`       //
FILTER_PREDICATE` contains a typo; replace `tag s` with `tag is` in the
FILTER_PREDICATE example so the predicate reads `tag is `#production`` (fix the
example line that includes the comment `// FILTER_PREDICATE`).

In `@skills/likec4-dsl/references/views.md`:
- Line 14: Several fenced code blocks in the document are missing language
identifiers (triggering MD040); update the fences so the block containing the
DSL "views { ... }" and the block starting with "include PREDICATE, PREDICATE,
..." use a likec4 fence (```likec4) and the block that defines the grammar "STEP
::=" uses a text fence (```text), ensuring each opening triple-backtick is
followed by the correct language identifier to satisfy markdown linting.

In `@skills/likec4-dsl/SKILL.md`:
- Line 91: Several fenced code blocks in SKILL.md lack language identifiers and
fail MD040; update the unlabeled blocks for decision trees to use the language
tag "text" and the DSL snippets to use "likec4" (specifically the unlabeled
blocks showing the decision tree "What kind of diagram?" and the DSL blocks with
"specification { ... }", "model { ... }", and "views { ... }"), i.e., change the
opening triple-backtick lines so they read ```text for the decision-tree block
and ```likec4 for each DSL snippet (also apply the same change to the other
occurrences noted at lines 104, 124, 138, 152, 210, and 369).

---

Nitpick comments:
In `@packages/language-services/src/common/LikeC4.ts`:
- Around line 21-23: The function isErrorDiagnostic uses a magic number (1) for
diagnostic.severity; document that mapping by adding a brief inline comment near
isErrorDiagnostic explaining that 1 corresponds to DiagnosticSeverity.Error
(from vscode-languageserver-types) so future maintainers understand the value
without the import; keep the function logic unchanged and place the comment next
to the isErrorDiagnostic declaration or the diagnostic.severity comparison.
- Around line 204-209: documentCount() builds an intermediate array via
this.LangiumDocuments.all.toArray().length; replace it with a direct count to
avoid allocation: if this.LangiumDocuments.all exposes a size/length property
use return this.LangiumDocuments.all.size (or .length), otherwise iterate the
iterable and increment a counter (e.g. let c=0; for (const _ of
this.LangiumDocuments.all) c++; return c;). Update the documentCount() method
accordingly (referencing documentCount and LangiumDocuments.all).
- Around line 165-167: Replace the manual null-check with optional chaining: in
the expression that inspects this.LangiumDocuments.userDocuments, change the
predicate to use doc.diagnostics?.some(isErrorDiagnostic) so the some() call is
only invoked when diagnostics exists; reference the
LangiumDocuments.userDocuments array and the isErrorDiagnostic function when
making this change.

In `@packages/likec4/src/cli/validate/index.ts`:
- Around line 146-151: The stats field currently sets filteredFiles to
totalFiles when fileFilter is null, which misrepresents "files with errors in
scope"; change the logic so stats.filteredFiles always reflects the count of
files with errors in scope by using filteredFileSet.size (i.e., set
filteredFiles: filteredFileSet.size) instead of conditional totalFiles, and
ensure filteredFileSet is constructed to contain only files that have errors (so
filteredErrors and filteredFileSet remain consistent); alternatively, if you
prefer to keep the existing semantics, rename filteredFiles to something
explicit (e.g., scopedFileCount) and update any callers/documentation
accordingly.

In `@skills/likec4-dsl/references/configuration.md`:
- Around line 166-170: The two consecutive JSON objects shown as examples for
"extends" are ambiguous; update the section in configuration.md so each example
is clearly labeled and separated (e.g., "Single path:" with `{ "extends":
"../shared/likec4.config.json" }` and "Multiple paths:" with `{ "extends":
["../shared/base.json", "../shared/theme.json"] }`), wrap each example in its
own JSON code fence, and add a one-line explanatory note that they are
alternative usages of the extends property to avoid confusion.
- Around line 214-225: Update the code block in configuration.md that shows the
directory tree to include a language identifier (e.g., change the opening fence
from ``` to ```text) so the markdown linter stops warning about an unspecified
language; locate the directory structure block under the example workspace (the
triple-backtick block containing workspace/, project-a/, project-b/, shared/)
and add the language tag to the opening fence.

In `@skills/likec4-dsl/references/predicates.md`:
- Around line 13-18: Add a language identifier to the fenced code block
containing the grammar (the block with BASE_PREDICATE, FILTER_PREDICATE,
CUSTOM_PREDICATE, PREDICATE) to satisfy linters and improve consistency; change
the opening fence from ``` to ```text (or ```bnf) so the grammar lines
(BASE_PREDICATE ::= WILDCARD | ELEMENT_EXPRESSION | RELATIONSHIP_EXPRESSION,
FILTER_PREDICATE ::= BASE_PREDICATE where FILTER_CONDITIONS, CUSTOM_PREDICATE
::= (BASE_PREDICATE | FILTER_PREDICATE) with { ... }, PREDICATE ::=
BASE_PREDICATE | FILTER_PREDICATE | CUSTOM_PREDICATE) are inside a labeled
block.

In `@skills/likec4-dsl/references/views.md`:
- Around line 84-93: The grammar and prose disagree: the DYNAMIC_VIEW_RULES
production lists only STEP and DYNAMIC_VIEW_STYLE_RULE but the text discusses
include/exclude ordering; update the grammar to reflect the described ordering
by adding tokens/productions for include and exclude (e.g., INCLUDE_STEP /
EXCLUDE_STEP or explicit INCLUDE_RULE / EXCLUDE_RULE entries) into
DYNAMIC_VIEW_RULES so rules are applied in sequence, or alternatively adjust the
prose to remove mention of include/exclude and describe only the existing
STEP/style semantics; reference DYNAMIC_VIEW_RULES, STEP, and
DYNAMIC_VIEW_STYLE_RULE when making the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1f9bbcbb-b68d-4b4d-a80f-ff568ff298ac

📥 Commits

Reviewing files that changed from the base of the PR and between 221dc04 and b268f5a.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (17)
  • .changeset/improve-validate-command.md
  • .claude/skills/likec4-dsl
  • apps/docs/astro.config.mjs
  • apps/docs/package.json
  • apps/docs/src/content.config.ts
  • packages/language-services/src/common/LikeC4.ts
  • packages/likec4/src/cli/check-update/utils.ts
  • packages/likec4/src/cli/index.ts
  • packages/likec4/src/cli/options.ts
  • packages/likec4/src/cli/validate/index.ts
  • pnpm-workspace.yaml
  • skills/likec4-dsl/SKILL.md
  • skills/likec4-dsl/references/configuration.md
  • skills/likec4-dsl/references/deployment.md
  • skills/likec4-dsl/references/dynamic-views.md
  • skills/likec4-dsl/references/predicates.md
  • skills/likec4-dsl/references/views.md

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (1)
packages/likec4/src/cli/validate/index.ts (1)

107-126: ⚠️ Potential issue | 🔴 Critical

Do not turn invalid --project into a filterable validation diagnostic.

packages/language-services/src/common/LikeC4.ts:95-98 resolves the project inside diagrams(). If that throws, this catch wraps the failure as { file: '' }, so a later --file filter can drop it and return valid: true / exit 0 for an invalid project. Re-throw setup/project-resolution failures instead of pushing them into layoutErrors.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/likec4/src/cli/validate/index.ts` around lines 107 - 126, The catch
around languageServices.diagrams(args.project) is turning
project-resolution/setup failures into a filterable validation diagnostic;
instead, detect and re-throw those setup/project-resolution errors (so they
cannot be dropped by a --file filter) and only push true diagram layout
validation errors into layoutErrors. Update the try/catch in index.ts: call
languageServices.diagrams(args.project) inside try, and in the catch rethrow
when the error originates from project resolution (preferably by checking for a
specific error type exported by LikeC4 such as ProjectResolutionError or by
matching a clear marker on the Error), otherwise push the error into
layoutErrors as before; reference symbols: languageServices.diagrams,
layoutErrors, args.project, and the project-resolution error type from LikeC4
(e.g., ProjectResolutionError).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/language-services/src/common/LikeC4.ts`:
- Around line 197-201: The documentCount() helper currently returns
this.LangiumDocuments.all.toArray().length which mismatches the validation
helpers getErrors(), hasErrors(), and printErrors() that operate on
LangiumDocuments.userDocuments; change documentCount() to count userDocuments
instead (e.g. use this.LangiumDocuments.userDocuments.toArray().length) so
total/filtered file counts match validation scope, or alternatively add a new
method like documentCountAll() that explicitly returns the .all count and leave
documentCount() aligned with userDocuments; update references to documentCount()
accordingly to preserve semantics.

In `@packages/likec4/src/cli/validate/index.ts`:
- Around line 86-89: The code currently enables automatic model-error printing
via the fromWorkspace printErrors flag (where languageServices is created)
whenever --json is off, and later logs every layoutErrors entry; change behavior
so when a file filter is provided (args.file or equivalent) you disable
automatic printing by setting printErrors to (!isJson && !args.file) when
calling fromWorkspace/creating languageServices, and modify the diagnostics
rendering block that currently iterates layoutErrors to instead iterate and
render filteredErrors (use filteredErrors for both printed output and exit-code
logic) so only scoped diagnostics are printed when --file is used.
- Line 83: The file filter resolution currently uses resolve(f) which resolves
against process.cwd(), causing mismatches with error paths built from the
workspace; update the fileFilter assignment (the args.file => map) to resolve
each entry against the workspace root (args.path) instead of the CWD (i.e., use
resolve(args.path, f) when mapping args.file). This will align fileFilter with
how error paths are constructed (see doc.uri.fsPath and resolve(args.path,
view.sourcePath)) so filters correctly match reported file paths.

In `@skills/likec4-dsl/references/predicates.md`:
- Line 32: The example uses the wrong predicate name: replace the phrase "and
type is component" with "and kind is component" so it matches the predicate
definition (the DSL predicate defined as "kind is ...") and ensures the example
is valid for copy/paste; search for the string "and type is component" in
predicates.md and update it to "and kind is component" (keeping surrounding
whitespace and punctuation consistent).

---

Duplicate comments:
In `@packages/likec4/src/cli/validate/index.ts`:
- Around line 107-126: The catch around languageServices.diagrams(args.project)
is turning project-resolution/setup failures into a filterable validation
diagnostic; instead, detect and re-throw those setup/project-resolution errors
(so they cannot be dropped by a --file filter) and only push true diagram layout
validation errors into layoutErrors. Update the try/catch in index.ts: call
languageServices.diagrams(args.project) inside try, and in the catch rethrow
when the error originates from project resolution (preferably by checking for a
specific error type exported by LikeC4 such as ProjectResolutionError or by
matching a clear marker on the Error), otherwise push the error into
layoutErrors as before; reference symbols: languageServices.diagrams,
layoutErrors, args.project, and the project-resolution error type from LikeC4
(e.g., ProjectResolutionError).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d2dfecf8-6016-419e-9ac1-e55dddad8a50

📥 Commits

Reviewing files that changed from the base of the PR and between b268f5a and 01aadf0.

📒 Files selected for processing (5)
  • packages/language-services/src/common/LikeC4.ts
  • packages/likec4/src/cli/validate/index.ts
  • skills/likec4-dsl/references/configuration.md
  • skills/likec4-dsl/references/deployment.md
  • skills/likec4-dsl/references/predicates.md
✅ Files skipped from review due to trivial changes (1)
  • skills/likec4-dsl/references/deployment.md

Comment on lines +86 to +89
await using languageServices = await fromWorkspace(args.path, {
watch: false,
printErrors: !isJson,
throwIfInvalid: false,
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot Mar 20, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

--file does not scope text-mode diagnostics.

Line 88 still enables automatic model-error printing whenever --json is off, and Lines 163-165 log every layoutErrors entry instead of the filtered subset. So likec4 validate --file ... can still print diagnostics from unrelated files even when filteredErrors and the exit code say the run was scoped. Disable auto-printing when a file filter is present and render from filteredErrors instead.

Also applies to: 162-165

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/likec4/src/cli/validate/index.ts` around lines 86 - 89, The code
currently enables automatic model-error printing via the fromWorkspace
printErrors flag (where languageServices is created) whenever --json is off, and
later logs every layoutErrors entry; change behavior so when a file filter is
provided (args.file or equivalent) you disable automatic printing by setting
printErrors to (!isJson && !args.file) when calling fromWorkspace/creating
languageServices, and modify the diagnostics rendering block that currently
iterates layoutErrors to instead iterate and render filteredErrors (use
filteredErrors for both printed output and exit-code logic) so only scoped
diagnostics are printed when --file is used.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Intentional — text mode shows all diagnostics during init (useful context), while exit code and summary are scoped to --file. The SKILL uses --json mode which is fully scoped.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@davydkov, understood — the design is clear: text mode surfaces all diagnostics for context (useful when debugging cascading errors), while --file scoping only affects the exit code and summary. --json mode (the primary interface for the SKILL) is fully scoped. I'll withdraw the concern.


✏️ Learnings added
Learnt from: davydkov
Repo: likec4/likec4 PR: 2782
File: packages/likec4/src/cli/validate/index.ts:86-89
Timestamp: 2026-03-20T09:11:24.853Z
Learning: In `packages/likec4/src/cli/validate/index.ts`, text mode intentionally prints ALL diagnostics (model errors via `printErrors` during init, and all layout errors) regardless of the `--file` filter. The `--file` filter only scopes the exit code and the final summary line. The `--json` mode is the fully-scoped output path and is the primary interface consumed by the LikeC4 DSL SKILL. This asymmetry is by design, not a bug.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: CR
Repo: likec4/likec4 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-02-21T16:24:15.549Z
Learning: Applies to **/*.agent.{ts,tsx,js,jsx} : Agents must validate input before processing and provide meaningful error messages

Learnt from: CR
Repo: likec4/likec4 PR: 0
File: packages/core/AGENTS.md:0-0
Timestamp: 2026-02-11T10:07:53.330Z
Learning: Applies to packages/core/src/manual-layout/**/*.{ts,tsx,js,jsx} : When changes relate to views (types or models), update View-drifts detection/auto-applying in `src/manual-layout` accordingly. If unsure what leads to layout drifts or can be auto-applied, ask for confirmation.

Learnt from: davydkov
Repo: likec4/likec4 PR: 2782
File: skills/likec4-dsl/references/dynamic-views.md:3-3
Timestamp: 2026-03-20T08:57:15.663Z
Learning: Files under the `skills/` directory in the `likec4/likec4` repository (e.g., `skills/likec4-dsl/references/`) are LLM skill reference files, not published documentation. Markdown linting rules (such as MD040 for fenced code block language tags) should not be applied to these files during code review.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
packages/language-services/src/common/LikeC4.ts (2)

158-160: Consider using optional chaining for conciseness.

The static analyzer flagged that optional chaining would be more idiomatic here.

♻️ Proposed fix
   hasErrors(): boolean {
     return this.LangiumDocuments.userDocuments.some(doc => {
-      return doc.diagnostics && doc.diagnostics.some(isErrorDiagnostic)
+      return doc.diagnostics?.some(isErrorDiagnostic) ?? false
     })
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/language-services/src/common/LikeC4.ts` around lines 158 - 160,
Replace the verbose null-check in the predicate with optional chaining: inside
the some over this.LangiumDocuments.userDocuments (the arrow function that
currently checks doc.diagnostics && doc.diagnostics.some(isErrorDiagnostic)),
use doc.diagnostics?.some(isErrorDiagnostic) (or
Boolean(doc.diagnostics?.some(isErrorDiagnostic))) so the code is more concise
and idiomatic while still using the existing LangiumDocuments, userDocuments and
isErrorDiagnostic symbols.

197-202: Consider using .toArray().length for consistency and explicitness.

The userDocuments property returns a Stream<LikeC4LangiumDocument> which doesn't expose a direct .length or .size property. While spreading to get the length works, it's slightly inefficient since it forces full array materialization. Other parts of the codebase explicitly call .toArray() (e.g., packages/language-services/src/node/index.ts) before accessing .length. For consistency and clarity, use .toArray().length instead of spreading.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/language-services/src/common/LikeC4.ts` around lines 197 - 202, The
documentCount() method currently computes length by spreading
LangiumDocuments.userDocuments into an array; change it to call
LangiumDocuments.userDocuments.toArray().length for consistency and explicit
materialization (replace [...this.LangiumDocuments.userDocuments].length with
this.LangiumDocuments.userDocuments.toArray().length in the documentCount()
method).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/language-services/src/common/LikeC4.ts`:
- Around line 158-160: Replace the verbose null-check in the predicate with
optional chaining: inside the some over this.LangiumDocuments.userDocuments (the
arrow function that currently checks doc.diagnostics &&
doc.diagnostics.some(isErrorDiagnostic)), use
doc.diagnostics?.some(isErrorDiagnostic) (or
Boolean(doc.diagnostics?.some(isErrorDiagnostic))) so the code is more concise
and idiomatic while still using the existing LangiumDocuments, userDocuments and
isErrorDiagnostic symbols.
- Around line 197-202: The documentCount() method currently computes length by
spreading LangiumDocuments.userDocuments into an array; change it to call
LangiumDocuments.userDocuments.toArray().length for consistency and explicit
materialization (replace [...this.LangiumDocuments.userDocuments].length with
this.LangiumDocuments.userDocuments.toArray().length in the documentCount()
method).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 44caf9e6-ef6b-49d6-8281-ff16a917d88e

📥 Commits

Reviewing files that changed from the base of the PR and between 01aadf0 and 7ccc528.

📒 Files selected for processing (2)
  • packages/language-services/src/common/LikeC4.ts
  • skills/likec4-dsl/references/predicates.md

@davydkov davydkov changed the title feat(cli): improve validate command, add LikeC4 DSL skill feat: add LikeC4 DSL skill with references Mar 20, 2026
davydkov and others added 10 commits March 24, 2026 09:15
- Fix exit code bug (was never set on validation failure)
- Add --json flag for structured JSON output (for tooling/SKILL consumers)
- Add --file flag to scope errors to specific files (handles cascading errors)
- Add --no-layout flag to skip layout drift checks
- Add success/failure summary messages and timing
- Add --project support for multi-project workspaces
- Add documentCount() to LikeC4 language-services class
- Add LikeC4 DSL skill with references for configuration, views, predicates, deployment, dynamic views

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
- Remove dead code: unused message truncation in getErrors()
- Fix printErrors() to iterate userDocuments (consistent with getErrors/hasErrors)
- Fix layout drift file path fallback (avoid '/workspace/.')
- Fix file filter endsWith false positives (require path separator)
- Fix typo 'tag s' → 'tag is' in predicates.md
- Fix undefined server4 → server2 in deployment.md example
- Fix invalid JSON comments in configuration.md landingPage section

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
- Fix documentCount() to use userDocuments (consistent with getErrors/hasErrors/printErrors)
- Fix typo 'type is component' → 'kind is component' in predicates.md

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
The symlink was pointing to ./skills/likec4-dsl/ which resolved
relative to .claude/skills/ directory (wrong path). Fixed to
../../skills/likec4-dsl to correctly traverse up to repo root.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Address remaining review comments from CodeRabbit by adding
language identifiers to all unlabeled fenced code blocks.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Document serve, build, export, codegen, mcp, and format commands
with key options and examples.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Move CLI docs from SKILL.md inline to references/cli.md so it's
only loaded when needed, reducing the default skill context size.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Compact, token-optimized examples covering: extend elements/relations,
view inheritance, groups, global styles/predicates, dynamic views with
parallel/notes/navigateTo, deployment with instanceOf, rank, where
predicates, relationship kinds, and a complete mini-project.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
skills/likec4-dsl/SKILL.md (1)

48-66: ⚠️ Potential issue | 🟡 Minor

json example is invalid due to inline comments.

The stats object uses // comments inside a ```json block, so the example is not valid JSON and can fail copy/paste validation.

🛠️ Proposed fix
   "stats": {
-    "totalFiles": 100, // Total number of files in the project
-    "totalErrors": 500, // Total number of errors in the project
-    "filteredFiles": 1, // Number of files that match the --file filter
-    "filteredErrors": 1 // Number of errors in the filtered files
+    "totalFiles": 100,
+    "totalErrors": 500,
+    "filteredFiles": 1,
+    "filteredErrors": 1
   }
#!/bin/bash
# Read-only check: find JSON-fenced blocks in SKILL.md that contain JS-style comments.
# Expected: no matches after fix.
awk '
  /^```json$/ { in_json=1; next }
  /^```$/ && in_json { in_json=0; next }
  in_json && /\/\// { print FNR ":" $0 }
' skills/likec4-dsl/SKILL.md
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/likec4-dsl/SKILL.md` around lines 48 - 66, The JSON example in the
```json``` block contains JS-style inline comments inside the stats object which
makes it invalid JSON; edit the SKILL.md JSON example to remove the // comments
(or replace them with real numeric values or a separate explanatory field) so
the block is valid JSON, specifically update the "stats" object in the code
fence (the keys "totalFiles", "totalErrors", "filteredFiles", "filteredErrors")
to not include any // comments and ensure the entire fenced block parses as
strict JSON.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@skills/likec4-dsl/references/predicates.md`:
- Around line 9-10: Remove the stray trailing apostrophe from the bullet text
"Custom predicates - used to override properties of elements/relationships (can
be used with `include` only)'" so it reads without the extra quote; update the
string in the predicates.md entry that contains "Custom predicates - used to
override properties of elements/relationships (can be used with `include`
only)'" to remove the final single quote character.

---

Duplicate comments:
In `@skills/likec4-dsl/SKILL.md`:
- Around line 48-66: The JSON example in the ```json``` block contains JS-style
inline comments inside the stats object which makes it invalid JSON; edit the
SKILL.md JSON example to remove the // comments (or replace them with real
numeric values or a separate explanatory field) so the block is valid JSON,
specifically update the "stats" object in the code fence (the keys "totalFiles",
"totalErrors", "filteredFiles", "filteredErrors") to not include any // comments
and ensure the entire fenced block parses as strict JSON.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3dad925e-9997-4e3d-ac8e-83914b0673e6

📥 Commits

Reviewing files that changed from the base of the PR and between 9f403bb and b97e08f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (14)
  • .changeset/ai-coding-agent-skill.md
  • .claude/skills/likec4-dsl
  • apps/docs/astro.config.mjs
  • apps/docs/package.json
  • apps/docs/src/content.config.ts
  • packages/language-services/src/common/LikeC4.ts
  • packages/likec4/src/cli/check-update/utils.ts
  • pnpm-workspace.yaml
  • skills/likec4-dsl/SKILL.md
  • skills/likec4-dsl/references/cli.md
  • skills/likec4-dsl/references/configuration.md
  • skills/likec4-dsl/references/examples.md
  • skills/likec4-dsl/references/predicates.md
  • skills/likec4-dsl/references/views.md
✅ Files skipped from review due to trivial changes (6)
  • .claude/skills/likec4-dsl
  • pnpm-workspace.yaml
  • .changeset/ai-coding-agent-skill.md
  • apps/docs/package.json
  • skills/likec4-dsl/references/cli.md
  • skills/likec4-dsl/references/examples.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/docs/astro.config.mjs
  • apps/docs/src/content.config.ts
  • packages/likec4/src/cli/check-update/utils.ts
  • skills/likec4-dsl/references/views.md

Comment on lines +9 to +10
- Custom predicates - used to override properties of elements/relationships (can be used with `include` only)'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove trailing apostrophe in custom-predicate bullet.

There is an extra ' after “include only)” that reads like a typo in the reference text.

✏️ Proposed fix
-- Custom predicates - used to override properties of elements/relationships (can be used with `include` only)'
+- Custom predicates - used to override properties of elements/relationships (can be used with `include` only)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/likec4-dsl/references/predicates.md` around lines 9 - 10, Remove the
stray trailing apostrophe from the bullet text "Custom predicates - used to
override properties of elements/relationships (can be used with `include`
only)'" so it reads without the extra quote; update the string in the
predicates.md entry that contains "Custom predicates - used to override
properties of elements/relationships (can be used with `include` only)'" to
remove the final single quote character.

davydkov and others added 3 commits March 24, 2026 12:38
Explain Agent Skills Discovery RFC, installation via
`npx skills add https://likec4.dev/`, and skill structure.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
- Rename tooling/mcp.mdx → tooling/ai-tools.mdx
- Add Agent Skills section on top with install command
- Demote MCP content under ## MCP Server heading
- Add /tooling/mcp/ → /tooling/ai-tools/ redirect
- Update editors.mdx link

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@davydkov davydkov enabled auto-merge (squash) March 24, 2026 12:00
@davydkov davydkov disabled auto-merge March 24, 2026 12:09
@davydkov davydkov merged commit d0f38c7 into main Mar 24, 2026
17 checks passed
@davydkov davydkov deleted the likec4-dsl-skill branch March 24, 2026 12:09
@likec4-ci likec4-ci bot mentioned this pull request Mar 24, 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

Development

Successfully merging this pull request may close these issues.

1 participant