Skip to content

chore: Auto-generate bundled help skill references from docs/ at build time#562

Merged
allenhutchison merged 9 commits intomasterfrom
claude/fix-issue-560-NEh3b
Apr 7, 2026
Merged

chore: Auto-generate bundled help skill references from docs/ at build time#562
allenhutchison merged 9 commits intomasterfrom
claude/fix-issue-560-NEh3b

Conversation

@allenhutchison
Copy link
Copy Markdown
Owner

@allenhutchison allenhutchison commented Apr 7, 2026

Replace manual import/map/table maintenance in bundled-skills.ts and
SKILL.md with a build-time code generation script. New or removed
markdown files in docs/guide/ and docs/reference/ are automatically
picked up — zero manual edits needed.

  • Add scripts/generate-help-references.mjs that scans docs/ and
    generates src/services/generated-help-references.ts
  • Update bundled-skills.ts to import from the generated module
  • Replace hardcoded references table in SKILL.md with a placeholder
    that gets injected at build time
  • Add generate-refs step to dev/build scripts in package.json
  • Add tests for both the generation script and table injection
  • Picks up 2 previously missing references: projects.md, loop-detection.md

Fixes #560

https://claude.ai/code/session_017jehiYdzcBfEigEFkJetEx

Summary by CodeRabbit

  • New Features

    • Help references are now auto-generated from docs and injected into bundled help content at build time.
  • Bug Fixes / Improvements

    • Bundled help no longer relies on a hardcoded references table; updates to docs are reflected automatically.
    • Help content now includes a generated references table placeholder replacement.
  • Chores

    • Dev, build, and test scripts now run the reference-generation step automatically.
  • Tests

    • Added tests for generator output, idempotency, and injection into bundled help.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 7, 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

Adds a build-time generator that scans docs/guide/ and docs/reference/, emits src/services/generated-help-references.ts (Map + markdown table), runs it from dev/build/test scripts, and updates the gemini-scribe-help bundled skill to consume generated references and replace a <!-- REFERENCES_TABLE --> placeholder.

Changes

Cohort / File(s) Summary
Build Automation
package.json, AGENTS.md
Added generate-refs script (node scripts/generate-help-references.mjs) and invoked it from dev, build, and test; documented generation step in AGENTS.md.
Generator Script
scripts/generate-help-references.mjs
New Node ES module that globs eligible docs/guide and docs/reference markdown, extracts first # heading as topic, detects basename/import identifier collisions, and emits src/services/generated-help-references.ts only when content changes.
Generated Module
src/services/generated-help-references.ts
New auto-generated file exporting helpResources: Map<string,string> and helpReferencesTable: string (markdown table) containing static imports of scanned docs.
Bundled Skills Refactor
src/services/bundled-skills.ts
Replaced manual markdown imports and Map construction with imports from the generated module; gemini-scribe-help now injects helpReferencesTable into SKILL content and reads helpResources from the generated module.
Skill Prompt Placeholder
prompts/bundled-skills/gemini-scribe-help/SKILL.md
Removed the hardcoded "Available References" table and left a <!-- REFERENCES_TABLE --> placeholder for build-time injection.
Tests
test/scripts/generate-help-references.test.ts, test/services/bundled-skills.test.ts
Added generator tests (file created, includes all docs, exports symbols, idempotency) and a bundled-skill test asserting the references table is injected into gemini-scribe-help content.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant DevCI as Dev/CI
  participant Gen as Generator\nscripts/generate-help-references.mjs
  participant FS as File System\n(docs/, src/)
  participant Bundler as Bundler\n(tsc/esbuild)
  DevCI->>Gen: run `npm run generate-refs` (pre-build)
  Gen->>FS: glob `docs/guide/*.md` & `docs/reference/*.md`
  Gen->>FS: read files, extract first `#` heading, detect basename/import collisions
  Gen->>FS: write `src/services/generated-help-references.ts` (if changed)
  DevCI->>Bundler: run `npm run build` / dev flow (includes generate-refs)
  Bundler->>FS: import `src/services/generated-help-references.ts`
  Bundler->>FS: bundle code (gemini-scribe-help receives injected table)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I nibble through markdown, hop from file to file,
I gather headings, stitch a table with a smile,
I tuck it in the skill at build-time with care,
No more manual wires — the docs live everywhere,
Hooray — I bounce, generate, and smile! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: automating build-time generation of bundled help skill references from docs/.
Description check ✅ Passed The description covers key changes, implementation approach, linked issue #560, and includes testing verification of the solution.
Linked Issues check ✅ Passed The PR implements all objectives from issue #560: automated discovery of docs via build-time generation script, elimination of manual wiring, and automatic inclusion of previously missing references (projects.md, loop-detection.md).
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #560's objectives: the new generation script, updated bundled-skills.ts, SKILL.md placeholder injection, package.json script updates, and tests all address the stated requirements.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/fix-issue-560-NEh3b

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

Comment thread scripts/generate-help-references.mjs Fixed
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: 2

🧹 Nitpick comments (1)
test/scripts/generate-help-references.test.ts (1)

34-46: Cover the escaping path with a regression test.

These assertions prove generation/idempotency, but they never exercise headings containing backslashes, backticks, or ${...}—the exact branch scripts/generate-help-references.mjs now escapes. A small fixture-based case here would keep that fix from regressing silently.

As per coding guidelines, "Assert observable behavior of prompts, services, and tool orchestration; add regression coverage for bugs".

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

In `@test/scripts/generate-help-references.test.ts` around lines 34 - 46, Add a
regression test that exercises the escaping branch by creating a small fixture
markdown with headings containing backslashes, backticks, and a `${...}`
sequence, run the script "node scripts/generate-help-references.mjs" (use the
same execSync pattern and ROOT constant), read GENERATED_FILE with
fs.readFileSync, and assert the generated output contains the correctly
escaped/encoded representation (and re-run to assert idempotency). Locate the
new test near the existing blocks in generate-help-references.test.ts so it uses
execSync and fs.readFileSync and verifies both the presence of escaped content
and that running the script twice produces the same output.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/generate-help-references.mjs`:
- Line 15: Remove the unsupported and unused globSync import from the top-level
import list (the "import { globSync } from 'fs';" statement) in the
generate-help-references.mjs module; simply delete the globSync import so the
file only imports supported symbols and CI on Node.js 18 no longer fails.

In `@src/services/bundled-skills.ts`:
- Line 45: The replace call building helpContent uses String.prototype.replace
with a string replacement which can interpret $ tokens; update the expression
creating helpContent so that stripFrontmatter(helpSkillMd).replace('<!--
REFERENCES_TABLE -->', helpReferencesTable) uses a replacer callback instead
(e.g., .replace('<!-- REFERENCES_TABLE -->', () => helpReferencesTable)) to
ensure helpReferencesTable is injected verbatim and prevent accidental token
expansion; locate the usage of helpContent and the symbols stripFrontmatter,
helpSkillMd, and helpReferencesTable to make this change.

---

Nitpick comments:
In `@test/scripts/generate-help-references.test.ts`:
- Around line 34-46: Add a regression test that exercises the escaping branch by
creating a small fixture markdown with headings containing backslashes,
backticks, and a `${...}` sequence, run the script "node
scripts/generate-help-references.mjs" (use the same execSync pattern and ROOT
constant), read GENERATED_FILE with fs.readFileSync, and assert the generated
output contains the correctly escaped/encoded representation (and re-run to
assert idempotency). Locate the new test near the existing blocks in
generate-help-references.test.ts so it uses execSync and fs.readFileSync and
verifies both the presence of escaped content and that running the script twice
produces the same output.
🪄 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: ec23e3b0-915b-4188-8d5c-0ae6bfd93f48

📥 Commits

Reviewing files that changed from the base of the PR and between 351392a and 480d7fd.

📒 Files selected for processing (8)
  • AGENTS.md
  • package.json
  • prompts/bundled-skills/gemini-scribe-help/SKILL.md
  • scripts/generate-help-references.mjs
  • src/services/bundled-skills.ts
  • src/services/generated-help-references.ts
  • test/scripts/generate-help-references.test.ts
  • test/services/bundled-skills.test.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
AGENTS.md

📄 CodeRabbit inference engine (CLAUDE.md)

AGENTS.md: Document agent definitions and responsibilities in AGENTS.md
Maintain clear descriptions of agent responsibilities and interactions in AGENTS.md

Maintain AGENTS.md as the central documentation for all agent definitions and their usage patterns

Files:

  • AGENTS.md
test/**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

test/**/*.test.ts: Unit tests should live in the test/ directory mirroring src/ structure as *.test.ts files
Use Jest with ts-jest for TypeScript support, JSDOM environment for DOM testing, and test pattern **/?(*.)+(spec|test).[tj]s. Keep unit tests next to implementations and name them after the unit
Assert observable behavior of prompts, services, and tool orchestration; add regression coverage for bugs

Files:

  • test/services/bundled-skills.test.ts
  • test/scripts/generate-help-references.test.ts
**/*.{ts,tsx,js,jsx,json}

📄 CodeRabbit inference engine (AGENTS.md)

Format code with Prettier using 2-space indent, 120-column width, semicolons, single quotes, and trailing commas

Files:

  • test/services/bundled-skills.test.ts
  • src/services/bundled-skills.ts
  • test/scripts/generate-help-references.test.ts
  • src/services/generated-help-references.ts
  • package.json
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.ts: Plugin entry point should be in src/main.ts with domain folders such as agent/, api/, tools/, ui/, and services/, plus shared utilities in utils/
Use camelCase for variables and functions, PascalCase for classes and types, and kebab-case for filenames
Use Obsidian API functions when available instead of low-level operations: vault.getMarkdownFiles() instead of vault.adapter.list(), app.fileManager.processFrontMatter() for frontmatter, vault.getAbstractFileByPath() for file operations, app.metadataCache for metadata, app.fileManager.renameFile() for renaming, and app.workspace.openLinkText() for clickable links
Never use native console.log() or console.debug() directly; use the Logger service (src/utils/logger.ts) with this.plugin.logger in components, context.plugin.logger in tools, or pass logger as a parameter to utility functions. Use logger.log() and logger.debug() for debug information (filtered by debugMode), and logger.error() and logger.warn() for always-visible errors and warnings
Handle TypeScript errors properly and ensure all properties are correctly typed
Use proper async/await patterns for all asynchronous operations instead of promises and callbacks
Always use Obsidian's normalized paths and metadata cache for file operations
Always exclude system folders from file operations: the plugin state folder (settings.historyFolder) and .obsidian configuration folder
Group modules by domain and add barrel exports only when they simplify imports in TypeScript files
Use .editorconfig to enforce LF endings for code and CRLF handling for other files; avoid hand-editing generated bundles

Files:

  • src/services/bundled-skills.ts
  • src/services/generated-help-references.ts
🧠 Learnings (16)
📓 Common learnings
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-05T19:58:54.181Z
Learning: Write concise, imperative commit subjects (e.g., 'Fix agent session cleanup', 'Improve prompt builder'), reference issues/PRs with `#123`, and commit generated artifacts alongside source changes
📚 Learning: 2025-12-06T03:43:40.257Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-06T03:43:40.257Z
Learning: Applies to AGENTS.md : Maintain AGENTS.md as the central documentation for all agent definitions and their usage patterns

Applied to files:

  • prompts/bundled-skills/gemini-scribe-help/SKILL.md
  • AGENTS.md
📚 Learning: 2025-12-06T03:43:40.257Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-06T03:43:40.257Z
Learning: Applies to **/*agent*.{ts,tsx,js,jsx} : Document agent implementations with clear purpose, capabilities, and usage examples in AGENTS.md

Applied to files:

  • AGENTS.md
  • src/services/generated-help-references.ts
📚 Learning: 2025-12-06T03:43:36.306Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T03:43:36.306Z
Learning: Applies to AGENTS.md : Document agent definitions and responsibilities in AGENTS.md

Applied to files:

  • AGENTS.md
📚 Learning: 2025-12-06T03:43:36.306Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T03:43:36.306Z
Learning: Applies to AGENTS.md : Maintain clear descriptions of agent responsibilities and interactions in AGENTS.md

Applied to files:

  • AGENTS.md
📚 Learning: 2026-04-05T19:58:54.181Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-05T19:58:54.181Z
Learning: Write concise, imperative commit subjects (e.g., 'Fix agent session cleanup', 'Improve prompt builder'), reference issues/PRs with `#123`, and commit generated artifacts alongside source changes

Applied to files:

  • AGENTS.md
📚 Learning: 2026-04-05T19:58:54.181Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-05T19:58:54.181Z
Learning: Always run `npm install` first if encountering TypeScript errors or missing module errors during build to ensure all dependencies in `node_modules` are present

Applied to files:

  • AGENTS.md
📚 Learning: 2026-04-05T19:58:54.181Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-05T19:58:54.181Z
Learning: Applies to src/services/skill-manager.ts : Skills are self-contained packages stored in `[state-folder]/Skills/<skill-name>/SKILL.md` following the agentskills.io specification. Skill names must be lowercase alphanumeric with hyphens, 1-64 characters, with no consecutive/leading/trailing hyphens

Applied to files:

  • AGENTS.md
  • test/services/bundled-skills.test.ts
  • src/services/bundled-skills.ts
📚 Learning: 2026-04-05T19:58:54.181Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-05T19:58:54.181Z
Learning: Applies to src/tools/**/*.ts : YAML frontmatter must start with `---` on line 1 and end with `---`, and content placed by AI tools should go after frontmatter blocks unless explicitly instructed otherwise

Applied to files:

  • AGENTS.md
📚 Learning: 2026-04-05T19:58:54.181Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-05T19:58:54.181Z
Learning: Applies to {main.js,manifest.json,styles.css} : Generate artifacts (`main.js`, `manifest.json`, `styles.css`) stay in the repo root for Obsidian and should be committed alongside source changes

Applied to files:

  • AGENTS.md
  • package.json
📚 Learning: 2026-04-05T19:58:54.181Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-05T19:58:54.181Z
Learning: Applies to src/**/*.ts : Use Obsidian API functions when available instead of low-level operations: `vault.getMarkdownFiles()` instead of `vault.adapter.list()`, `app.fileManager.processFrontMatter()` for frontmatter, `vault.getAbstractFileByPath()` for file operations, `app.metadataCache` for metadata, `app.fileManager.renameFile()` for renaming, and `app.workspace.openLinkText()` for clickable links

Applied to files:

  • AGENTS.md
📚 Learning: 2025-12-29T00:49:29.597Z
Learnt from: allenhutchison
Repo: allenhutchison/obsidian-gemini PR: 277
File: src/services/rag-indexing.ts:459-512
Timestamp: 2025-12-29T00:49:29.597Z
Learning: Guideline: When using the Obsidian API in TypeScript code, import the standalone setTooltip from 'obsidian' and call setTooltip(element, tooltip, options?) instead of using a component method like component.setTooltip(tooltip, options). This applies to any TypeScript file (not just UI components) and helps avoid confusion between the standalone API and component-specific methods. Ensure the import is: import { setTooltip } from 'obsidian'; and use the signature setTooltip(element: HTMLElement, tooltip: string, options?: { placement?: 'top' | 'bottom' | 'left' | 'right' });

Applied to files:

  • test/services/bundled-skills.test.ts
  • src/services/bundled-skills.ts
  • test/scripts/generate-help-references.test.ts
  • src/services/generated-help-references.ts
📚 Learning: 2026-03-01T22:53:18.726Z
Learnt from: allenhutchison
Repo: allenhutchison/obsidian-gemini PR: 380
File: src/main.ts:856-868
Timestamp: 2026-03-01T22:53:18.726Z
Learning: For Obsidian's SecretStorage API (v1.11.4+), setSecret(id, secret) and getSecret(id) are synchronous. Do not use await with these calls. After calling setSecret(id, secret), immediately call getSecret(id) and verify the value to confirm storage succeeded before proceeding. If getSecret returns null or a different value, handle the failure. This guideline applies to all code paths in the codebase that use this API.

Applied to files:

  • src/services/bundled-skills.ts
  • src/services/generated-help-references.ts
📚 Learning: 2026-04-05T19:58:54.181Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-05T19:58:54.181Z
Learning: Applies to test/**/*.test.ts : Use Jest with ts-jest for TypeScript support, JSDOM environment for DOM testing, and test pattern `**/?(*.)+(spec|test).[tj]s`. Keep unit tests next to implementations and name them after the unit

Applied to files:

  • test/scripts/generate-help-references.test.ts
📚 Learning: 2026-04-05T19:58:54.181Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-05T19:58:54.181Z
Learning: Applies to test/**/*.test.ts : Assert observable behavior of prompts, services, and tool orchestration; add regression coverage for bugs

Applied to files:

  • test/scripts/generate-help-references.test.ts
📚 Learning: 2026-04-05T19:58:54.181Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-05T19:58:54.181Z
Learning: Applies to test/**/*.test.ts : Unit tests should live in the `test/` directory mirroring `src/` structure as `*.test.ts` files

Applied to files:

  • test/scripts/generate-help-references.test.ts
🪛 GitHub Actions: CI
test/scripts/generate-help-references.test.ts

[error] 10-10: Test failed: should generate the references file. Command failed: node scripts/generate-help-references.mjs (SyntaxError about missing 'fs' export 'globSync').


[error] 41-41: Test failed: should be idempotent (running twice produces same output). Command failed: node scripts/generate-help-references.mjs (SyntaxError about missing 'fs' export 'globSync').

scripts/generate-help-references.mjs

[error] 15-15: SyntaxError: The requested module 'fs' does not provide an export named 'globSync' (import { globSync } from 'fs';). Node.js v18.20.8.

Comment thread scripts/generate-help-references.mjs Outdated
Comment thread src/services/bundled-skills.ts Outdated
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

🧹 Nitpick comments (1)
scripts/generate-help-references.mjs (1)

31-35: Add a guard for generated import variable-name collisions.

toVarName() can map different filenames to the same identifier in edge cases, which would generate duplicate imports and break TypeScript compilation. Consider validating varName uniqueness alongside basename checks.

Proposed fix
 const imports = [];
 const mapEntries = [];
 const tableRows = [];
+const seenVarNames = new Map();
@@
 	const varName = toVarName(basename);
+	if (seenVarNames.has(varName)) {
+		console.error(
+			`ERROR: Import variable collision "${varName}" between "${seenVarNames.get(varName)}" and "${relPath}". ` +
+				`Rename one of the files to avoid generated identifier conflicts.`
+		);
+		process.exit(1);
+	}
+	seenVarNames.set(varName, relPath);

Also applies to: 84-95

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

In `@scripts/generate-help-references.mjs` around lines 31 - 35, toVarName() can
produce duplicate identifiers for different filenames; update the generation
flow to detect and prevent varName collisions by tracking used names (e.g. a Set
or Map) when creating imports and, on collision, derive a unique fallback
(append a numeric suffix or short hash) and return that instead; update all
places that call toVarName (and the import-generation loop around the block
referenced at lines 84-95) to validate uniqueness against the tracker before
emitting import statements so TypeScript identifiers never collide.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/generate-help-references.mjs`:
- Around line 41-44: Headings are inserted raw into Markdown table cells which
breaks tables when they contain '|' or line breaks; create a small helper (e.g.,
escapeMarkdownCell) that replaces pipe characters with '\|' and collapses or
replaces newlines with a safe token (space or '<br>') and trim, then call that
helper from extractHeading and from the row-generation code that writes titles
into table cells (the table/row generation block currently around the other
insertion sites) so all cell content is escaped before being concatenated into
table rows.

---

Nitpick comments:
In `@scripts/generate-help-references.mjs`:
- Around line 31-35: toVarName() can produce duplicate identifiers for different
filenames; update the generation flow to detect and prevent varName collisions
by tracking used names (e.g. a Set or Map) when creating imports and, on
collision, derive a unique fallback (append a numeric suffix or short hash) and
return that instead; update all places that call toVarName (and the
import-generation loop around the block referenced at lines 84-95) to validate
uniqueness against the tracker before emitting import statements so TypeScript
identifiers never collide.
🪄 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: 3591088a-ee94-42c4-aba0-817d073bdc81

📥 Commits

Reviewing files that changed from the base of the PR and between 480d7fd and d97a934.

📒 Files selected for processing (2)
  • scripts/generate-help-references.mjs
  • src/services/bundled-skills.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/services/bundled-skills.ts
📜 Review details
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-05T19:58:54.181Z
Learning: Write concise, imperative commit subjects (e.g., 'Fix agent session cleanup', 'Improve prompt builder'), reference issues/PRs with `#123`, and commit generated artifacts alongside source changes
📚 Learning: 2026-04-05T19:58:54.181Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-05T19:58:54.181Z
Learning: Applies to src/**/*.ts : Use Obsidian API functions when available instead of low-level operations: `vault.getMarkdownFiles()` instead of `vault.adapter.list()`, `app.fileManager.processFrontMatter()` for frontmatter, `vault.getAbstractFileByPath()` for file operations, `app.metadataCache` for metadata, `app.fileManager.renameFile()` for renaming, and `app.workspace.openLinkText()` for clickable links

Applied to files:

  • scripts/generate-help-references.mjs
🔇 Additional comments (1)
scripts/generate-help-references.mjs (1)

65-77: Good defensive check for reference key collisions.

Failing fast on duplicate basenames in the references/<basename> namespace prevents silent overwrites and stale/ambiguous resource lookups.

Comment thread scripts/generate-help-references.mjs
Comment thread scripts/generate-help-references.mjs Fixed
@allenhutchison allenhutchison force-pushed the claude/fix-issue-560-NEh3b branch from 6c59264 to 2087c10 Compare April 7, 2026 03:35
@allenhutchison
Copy link
Copy Markdown
Owner Author

@CodeRabbit review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 7, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@package.json`:
- Around line 14-16: Update the package.json "test" script to run the
generate-refs step before tests: modify the scripts.test entry so it invokes
"npm run generate-refs" (or "npm run generate-refs && <existing test command>")
so the generated file used by bundled-skills.ts (./generated-help-references)
exists prior to running tests; ensure you reference the existing "generate-refs"
script rather than duplicating logic.
🪄 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: 68fb0bce-e9c8-466f-8680-4f590bb1ba0f

📥 Commits

Reviewing files that changed from the base of the PR and between d97a934 and 2087c10.

📒 Files selected for processing (8)
  • AGENTS.md
  • package.json
  • prompts/bundled-skills/gemini-scribe-help/SKILL.md
  • scripts/generate-help-references.mjs
  • src/services/bundled-skills.ts
  • src/services/generated-help-references.ts
  • test/scripts/generate-help-references.test.ts
  • test/services/bundled-skills.test.ts
✅ Files skipped from review due to trivial changes (6)
  • test/services/bundled-skills.test.ts
  • prompts/bundled-skills/gemini-scribe-help/SKILL.md
  • src/services/generated-help-references.ts
  • AGENTS.md
  • src/services/bundled-skills.ts
  • scripts/generate-help-references.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/scripts/generate-help-references.test.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx,json}

📄 CodeRabbit inference engine (AGENTS.md)

Format code with Prettier using 2-space indent, 120-column width, semicolons, single quotes, and trailing commas

Files:

  • package.json
🧠 Learnings (1)
📚 Learning: 2026-04-05T19:58:54.181Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-05T19:58:54.181Z
Learning: Applies to {main.js,manifest.json,styles.css} : Generate artifacts (`main.js`, `manifest.json`, `styles.css`) stay in the repo root for Obsidian and should be committed alongside source changes

Applied to files:

  • package.json
🔇 Additional comments (1)
package.json (1)

14-14: The generate-refs script integration looks good.

The approach of separating the generation into its own npm script and composing it with && in dev and build is clean and follows npm script best practices.

One operational note: per context snippet 3, the generator silently skips missing docs/guide/ or docs/reference/ directories rather than failing. If these directories are accidentally removed or renamed, the build will succeed but produce an incomplete generated file, leading to confusing runtime errors rather than an actionable build-time message.

Comment thread package.json
claude added 8 commits April 7, 2026 03:58
…d time

Replace manual import/map/table maintenance in bundled-skills.ts and
SKILL.md with a build-time code generation script. New or removed
markdown files in docs/guide/ and docs/reference/ are automatically
picked up — zero manual edits needed.

- Add scripts/generate-help-references.mjs that scans docs/ and
  generates src/services/generated-help-references.ts
- Update bundled-skills.ts to import from the generated module
- Replace hardcoded references table in SKILL.md with a placeholder
  that gets injected at build time
- Add generate-refs step to dev/build scripts in package.json
- Add tests for both the generation script and table injection
- Picks up 2 previously missing references: projects.md, loop-detection.md

Fixes #560

https://claude.ai/code/session_017jehiYdzcBfEigEFkJetEx
Address CodeQL alert about incomplete string escaping when embedding
the references table into a JS template literal. Now escapes
backslashes, backticks, and ${ sequences.

https://claude.ai/code/session_017jehiYdzcBfEigEFkJetEx
The generated file must be checked in so that tsc and jest in CI
can resolve the module without running the generate script first.
The file is deterministic, so it only changes when docs are
added or removed.

https://claude.ai/code/session_017jehiYdzcBfEigEFkJetEx
…nfig

The generate script was producing 2-space indents for map entries, but
Prettier (via .editorconfig indent_style: tab) converts to tabs. This
mismatch caused the idempotency test to fail in CI since the first test
run overwrote the committed (tab) file with the script's (space) output.

https://claude.ai/code/session_017jehiYdzcBfEigEFkJetEx
- Remove `import { globSync } from 'fs'` which is unused and only
  available in Node.js v22+, breaking CI on Node.js 18
- Use a replacer callback in String.replace() to prevent $ token
  expansion when injecting the references table

https://claude.ai/code/session_017jehiYdzcBfEigEFkJetEx
- Detect duplicate import variable names from toVarName() and fail
  fast, complementing the existing basename collision check
- Escape pipe characters and newlines in headings before inserting
  into markdown table cells to prevent malformed tables

https://claude.ai/code/session_017jehiYdzcBfEigEFkJetEx
Address CodeQL alert about incomplete string escaping in
escapeMarkdownTableCell by escaping backslashes before pipes.

https://claude.ai/code/session_017jehiYdzcBfEigEFkJetEx
Ensures the generated help references file is up-to-date before
running jest, protecting against stale or missing files when
contributors run npm test without building first.

https://claude.ai/code/session_017jehiYdzcBfEigEFkJetEx
@allenhutchison allenhutchison force-pushed the claude/fix-issue-560-NEh3b branch from 27ecd54 to d016db2 Compare April 7, 2026 03:59
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 (1)
scripts/generate-help-references.mjs (1)

31-35: Consider hardening identifier generation in toVarName for edge cases.

The function currently handles kebab-case normalization but could generate invalid TypeScript identifiers for filenames with dots, spaces, or other special characters. While current docs filenames don't trigger this, adding defensive sanitization would prevent breakage if future documentation naming changes are made.

♻️ Suggested improvement
 function toVarName(filename) {
 	const base = path.basename(filename, '.md');
-	const camel = base.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
-	return 'ref' + camel.charAt(0).toUpperCase() + camel.slice(1);
+	const normalized = base.replace(/[^A-Za-z0-9_$]+/g, '_');
+	const safe = /^[A-Za-z_$]/.test(normalized) ? normalized : `_${normalized}`;
+	return `ref${safe.charAt(0).toUpperCase()}${safe.slice(1)}`;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/generate-help-references.mjs` around lines 31 - 35, toVarName
currently only normalizes kebab-case and can produce invalid TypeScript
identifiers for filenames with dots, spaces, or special chars; update toVarName
to first strip the extension, then sanitize the base by replacing any
non-alphanumeric characters (including dots, spaces, punctuation) with a
separator or removing them, convert to camelCase (preserving existing
kebab/camel rules), ensure the resulting identifier does not start with a digit
(prefix with underscore if it does), and finally prepend the "ref" prefix and
capitalize the first letter as before; reference the toVarName function and
adjust its regex/logic to perform these sanitization steps defensively.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@scripts/generate-help-references.mjs`:
- Around line 31-35: toVarName currently only normalizes kebab-case and can
produce invalid TypeScript identifiers for filenames with dots, spaces, or
special chars; update toVarName to first strip the extension, then sanitize the
base by replacing any non-alphanumeric characters (including dots, spaces,
punctuation) with a separator or removing them, convert to camelCase (preserving
existing kebab/camel rules), ensure the resulting identifier does not start with
a digit (prefix with underscore if it does), and finally prepend the "ref"
prefix and capitalize the first letter as before; reference the toVarName
function and adjust its regex/logic to perform these sanitization steps
defensively.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bfe4452f-b98c-4c69-b392-b9e8f4c0eba5

📥 Commits

Reviewing files that changed from the base of the PR and between 27ecd54 and 531be8d.

📒 Files selected for processing (8)
  • AGENTS.md
  • package.json
  • prompts/bundled-skills/gemini-scribe-help/SKILL.md
  • scripts/generate-help-references.mjs
  • src/services/bundled-skills.ts
  • src/services/generated-help-references.ts
  • test/scripts/generate-help-references.test.ts
  • test/services/bundled-skills.test.ts
✅ Files skipped from review due to trivial changes (3)
  • prompts/bundled-skills/gemini-scribe-help/SKILL.md
  • src/services/generated-help-references.ts
  • test/scripts/generate-help-references.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • test/services/bundled-skills.test.ts
  • src/services/bundled-skills.ts
  • AGENTS.md
📜 Review details
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-07T03:51:10.557Z
Learning: Applies to src/services/bundled-skills.ts : Wire new documentation files in `docs/` into the `gemini-scribe-help` bundled skill by adding imports in `src/services/bundled-skills.ts`, entries in the `helpResources` Map, and rows in the references table in `prompts/bundled-skills/gemini-scribe-help/SKILL.md`
📚 Learning: 2026-04-07T03:51:10.557Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-07T03:51:10.557Z
Learning: Applies to {main.js,manifest.json,versions.json} : Commit generated artifacts (`main.js`, `manifest.json`, `versions.json`) alongside source changes using `npm run version` for releases

Applied to files:

  • package.json
📚 Learning: 2026-04-07T03:51:10.557Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-07T03:51:10.557Z
Learning: Applies to test-scripts/**/*.mjs : Run all Jest tests with `npm test` before each PR and execute relevant `test-scripts/*.mjs` after touching agent or tool code

Applied to files:

  • package.json
📚 Learning: 2026-04-07T03:51:10.557Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-07T03:51:10.557Z
Learning: Applies to src/services/bundled-skills.ts : Wire new documentation files in `docs/` into the `gemini-scribe-help` bundled skill by adding imports in `src/services/bundled-skills.ts`, entries in the `helpResources` Map, and rows in the references table in `prompts/bundled-skills/gemini-scribe-help/SKILL.md`

Applied to files:

  • package.json
  • scripts/generate-help-references.mjs
📚 Learning: 2026-04-07T03:51:10.557Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-07T03:51:10.557Z
Learning: Applies to test/**/*.test.ts : Assert observable behavior of prompts, services, and tool orchestration in tests; add regression coverage for bugs

Applied to files:

  • package.json
📚 Learning: 2026-04-07T03:51:10.556Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-07T03:51:10.556Z
Learning: Applies to test/**/*.test.ts : Create unit tests in the `test/` directory mirroring `src/` structure with `*.test.ts` naming pattern using Jest and ts-jest

Applied to files:

  • package.json
📚 Learning: 2026-04-07T03:51:10.556Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-07T03:51:10.556Z
Learning: Applies to src/**/*.ts : Use Obsidian API functions when available instead of low-level operations (e.g., `vault.getMarkdownFiles()` over `vault.adapter.list()`, `app.fileManager.processFrontMatter()` for frontmatter manipulation, `vault.getAbstractFileByPath()` for file operations, `app.metadataCache` for file metadata)

Applied to files:

  • scripts/generate-help-references.mjs
📚 Learning: 2026-04-07T03:51:10.557Z
Learnt from: CR
Repo: allenhutchison/obsidian-gemini PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-07T03:51:10.557Z
Learning: Applies to src/**/*.ts : Use proper Obsidian file operations with normalized paths and metadata cache for all file operations

Applied to files:

  • scripts/generate-help-references.mjs
🔇 Additional comments (2)
scripts/generate-help-references.mjs (1)

72-84: Good guardrails and idempotent generation flow.

Collision checks plus write-on-change behavior are clean and reduce stale-file churn in CI/dev workflows.

Also applies to: 98-148

package.json (1)

14-16: Nice build/test orchestration update.

Running generate-refs before dev/build/test is the right dependency ordering for generated skill references.

Also applies to: 21-21

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.

chore: Auto-generate bundled help skill references from docs/ at build time

3 participants