Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This repository uses Turborepo.

- apps/website: The public-facing website for Discourse Graphs, Uses Next.js.
- apps/roam: The Roam Research extension that implements the Discourse Graph protocol.
- apps/obsidian: The Obsidian plugin that implements the Discourse Graph protocol.
- apps/obsidian: The Obsidian plugin that implements the Discourse Graph protocol. See `apps/obsidian/AGENTS.md` for Obsidian-specific lint workflow.

`packages`

Expand Down
14 changes: 14 additions & 0 deletions apps/obsidian/AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
You are working on the Obsidian plugin that implements the Discourse Graph protocol.

## Linting

After editing any Obsidian plugin code, run lint before finishing:

```bash
pnpm --dir apps/obsidian lint
```

Fix all reported warnings and errors. Pay special attention to `obsidianmd/*` rule violations — these indicate Obsidian plugin store review risks. The obsidianmd rules fire as warnings (due to the shared `eslint-plugin-only-warn` preset), but they still fail lint and block commits via lint-staged.

For manifest and store checks that ESLint does not cover (description wording, funding URL, etc.), use the `obsidian-plugin-guidelines` skill.

Note: `apps/obsidian` uses ESLint 9 with `eslint-plugin-obsidianmd` layered on top of the monorepo's shared React/TS rules. Other apps (roam, website) use ESLint 8 and are unaffected.

## Dependencies

Prefer existing dependencies from package.json.
Expand Down
19 changes: 19 additions & 0 deletions apps/obsidian/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
import { config } from "@repo/eslint-config/react-internal";

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.

🚩 ESLint major version mismatch between shared config package and obsidian app

The shared @repo/eslint-config package declares eslint: catalog: which resolves to ESLint 8.57.1 (pnpm-workspace.yaml:30), while apps/obsidian now uses eslint: catalog:obsidian resolving to ESLint ^9.30.0 (pnpm-workspace.yaml:47). Similarly, typescript-eslint is at ^7.18.0 in the shared package (packages/eslint-config/package.json:26) but ^8.35.1 in obsidian (pnpm-workspace.yaml:51). The obsidian eslint config imports and spreads the shared config (apps/obsidian/eslint.config.mjs:1,15), so the shared config's code (written for ESLint 8 / typescript-eslint 7) runs under ESLint 9 / typescript-eslint 8 at runtime. This works today because ESLint 9 flat config is backward-compatible with the patterns used, but it's fragile — a future change to the shared config could break obsidian's lint, or vice versa. Worth considering whether the shared config should be upgraded to ESLint 9 monorepo-wide or whether obsidian should have a fully independent config.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

import obsidianmd from "eslint-plugin-obsidianmd";

// Extract only obsidianmd/* rules from the recommended config.
// Spreading obsidianmd.configs.recommended directly re-registers @typescript-eslint,
// which conflicts with react-internal. This approach picks up all obsidianmd rules
// (including future additions) without touching the TS plugin registration.
const obsidianmdRules = Object.fromEntries(
obsidianmd.configs.recommended
.flatMap((c) => Object.entries(c.rules ?? {}))
.filter(([key]) => key.startsWith("obsidianmd/")),
);

export default [
...config,
{
plugins: { obsidianmd },
rules: {
...obsidianmdRules,
"obsidianmd/prefer-active-doc": "off",
"obsidianmd/prefer-file-manager-trash-file": "off",
},
},
{
languageOptions: {
parserOptions: {
Expand Down
6 changes: 5 additions & 1 deletion apps/obsidian/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@
"builtin-modules": "3.3.0",
"dotenv": "^16.4.5",
"esbuild": "0.17.3",
"eslint": "catalog:",
"@eslint/js": "catalog:obsidian",
"@eslint/json": "catalog:obsidian",
"eslint": "catalog:obsidian",
"eslint-plugin-obsidianmd": "catalog:obsidian",
"typescript-eslint": "catalog:obsidian",
"obsidian": "^1.7.2",
"postcss": "^8.5.3",
"tailwindcss": "^3.4.17",
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"tailwindConfig": "./packages/tailwind-config/tailwind.config.ts"
},
"lint-staged": {
"*.{js,mjs,ts,tsx,md,mdx}": "prettier -w"
"*.{js,mjs,ts,tsx,md,mdx}": "prettier -w",
"apps/obsidian/**/*.{ts,tsx}": "pnpm --dir apps/obsidian exec eslint --fix"

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.

🔴 Obsidian lint rules silently pass instead of blocking commits as intended

The commit-hook linter is run without a --max-warnings flag (eslint --fix at package.json:38), so rule violations downgraded to warnings by the shared only-warn plugin exit with code 0 instead of failing, and the new AGENTS.md incorrectly states they "still fail lint and block commits."

Impact: Obsidian plugin store guideline violations slip through commits undetected, contrary to what the documentation promises.

Mechanism: eslint-plugin-only-warn + missing --max-warnings 0

The shared ESLint base config at packages/eslint-config/base.js:5-6 loads eslint-plugin-only-warn, which converts every ESLint error into a warning. The obsidianmd rules are layered on top of this shared config (apps/obsidian/eslint.config.mjs:14-23), so they also become warnings.

ESLint's default behavior is to exit with code 0 when only warnings are present (exit code 1 requires at least one error). Neither the lint script ("lint": "eslint ." in apps/obsidian/package.json:10) nor the lint-staged command (pnpm --dir apps/obsidian exec eslint --fix in package.json:38) passes --max-warnings 0.

As a result, obsidianmd rule violations produce warnings that ESLint silently accepts, and the lint-staged pre-commit hook succeeds. The claim in apps/obsidian/AGENTS.md:11 that warnings "still fail lint and block commits via lint-staged" is incorrect.

To fix, add --max-warnings 0 to both the lint script and the lint-staged command, or remove eslint-plugin-only-warn from the obsidian config chain.

Suggested change
"apps/obsidian/**/*.{ts,tsx}": "pnpm --dir apps/obsidian exec eslint --fix"
"apps/obsidian/**/*.{ts,tsx}": "pnpm --dir apps/obsidian exec eslint --max-warnings 0 --fix"
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

},
"dependencies": {
"posthog-js": "catalog:"
Expand Down
Loading