Contributing
Getting started
Section titled “Getting started”- Fork the repository on GitHub
- Clone your fork and set up the development environment
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes
- Run the relevant test suites (see testing)
- Commit and push — no AI attribution (hard rule)
- Open a pull request against
main
Root-level CONTRIBUTING.md in the repo has the quick-start version of the same thing. This page is the longer-form reference with all the conventions.
What you can contribute
Section titled “What you can contribute”Crosswalker has three contribution surfaces, each with its own conventions:
| Surface | Lives in | Tech | Test suite |
|---|---|---|---|
| Plugin code | src/ | TypeScript + Bun + esbuild | Jest unit tests, WebdriverIO E2E |
| Docs site | docs/src/content/docs/ | Astro Starlight, MDX | Playwright E2E |
| Python CLI | frameworks_to_obsidian.py | Python + Pandas | manual |
Most contributions touch the plugin or docs. The Python CLI is the original batch importer and still shipped as a secondary tool, but new capability work happens in the plugin.
Local dev orchestrator — bun run serve
Section titled “Local dev orchestrator — bun run serve”From the repo root, bun run serve is an interactive menu wrapping every local workflow:
Shortcuts that skip the menu:
The orchestrator handles cross-OS node_modules contamination automatically (e.g. rollup native binary mismatches when bouncing between WSL and Windows) and auto-installs docs/node_modules on first run.
Plugin code style
Section titled “Plugin code style”- TypeScript with strict types
- ESLint with
eslint-plugin-obsidianmd— required for community plugin submission - Sentence case for all user-facing UI text (e.g. “Add new rule”, not “Add New Rule”)
- Settings headings: use
Setting.setHeading()instead ofcreateEl('h3') - Don’t include the plugin name in settings section headings (Obsidian provides it)
- Avoid “settings” or “options” in heading text —
"Behavior"not"Behavior settings"
Run the linter before committing:
Commit messages
Section titled “Commit messages”Keep them descriptive, focused on the “why” rather than the “what”. First line is a short summary. Body explains non-obvious context and design rationale. Match the existing commit log style by running git log --oneline -20 before writing yours.
Never include AI attribution (Co-Authored-By: Claude ... or similar) — this is a hard rule in the project’s CLAUDE.md. Commit as the human contributor only.
Adding a new parser
Section titled “Adding a new parser”To add support for a new file format:
- Create
src/import/parsers/<format>-parser.ts - Export a
parse<Format>(content, options)function returningParsedData - Add the format to the file picker in
import-wizard.ts - Add unit tests in
tests/<format>-parser.test.ts - Update
docs/src/content/docs/features/import-wizard.mdxto mention the new format
Editing the documentation
Section titled “Editing the documentation”The docs site is built with Astro Starlight and lives in the docs/ folder.
Quick edits
Section titled “Quick edits”Every docs page has an “Edit page” link in the sidebar. Click it to edit the page directly on GitHub and submit a pull request — no local setup needed.
Local development
Section titled “Local development”For larger changes or new pages:
Edit files in docs/src/content/docs/. Changes hot-reload in the browser.
File format — .mdx, not Obsidian
Section titled “File format — .mdx, not Obsidian”Docs use .mdx (Markdown with JSX components). Standard Markdown works — you only need JSX for Starlight components like <Card>, <Tabs>, or inline HTML/SVG:
The docs/ folder is not an Obsidian vault — the files are .mdx, not .md. For rich editing, use VS Code with the MDX extension.
Frontmatter conventions
Section titled “Frontmatter conventions”Every content page starts with YAML frontmatter. The canonical fields:
date: convention: log files parse the creation date from their YYYY-MM-DD-* filename prefix. Challenge and registry entries use the git first-commit date by convention. The PageTitle override displays a CREATED label pulled from this field, alongside a git-based UPDATED label. Splash pages opt out of the meta row via sidebar.hidden: true.
Tags: must be in docs/tags.yml — unknown tags are rejected at build time by starlight-tags. Common ones: frameworks-mapping, data-model-graph, data-model-evolution, evidence-mapping-links, obsidian-metadata, architecture.
MDX silent-breakage gotchas — two rules you will hit if you write diagrams or code examples
Section titled “MDX silent-breakage gotchas — two rules you will hit if you write diagrams or code examples”Both of these bite agents and humans alike. Both produce cryptic errors (or worse, pages that visually look wrong with no error at all). Internalize the rules before writing any inline SVG, HTML, or <code> blocks containing code examples in an .mdx file.
Rule 1: Inline SVG attributes — kebab-case only
Section titled “Rule 1: Inline SVG attributes — kebab-case only”This is the single most expensive bug to hit in this codebase — it produces no error, just visually broken diagrams. MDX parses inline <svg> subtrees in HTML mode, not JSX mode. The HTML5 parser silently lowercases all attribute names except a small whitelist (viewBox, preserveAspectRatio, baseProfile). So strokeWidth="2" becomes strokewidth="2" — an invalid SVG attribute that browsers silently ignore, leaving the diagram with default 1px strokes, misaligned text, broken dashed borders, and no error message anywhere. You’ll see a diagram that “just looks wrong” and chase CSS for an hour before finding it.
Always use kebab-case for inline SVG attributes:
Exceptions that preserve case (HTML whitelist): viewBox, preserveAspectRatio, baseProfile, attributeName, xlink:href. Everything else: kebab-case.
CSS properties inside style={{...}} JSX object props should use camelCase — those are JavaScript object keys, not HTML attributes. style={{fontSize: '11px', textAlign: 'center'}} is correct in that context.
Rule 2: Curly braces inside HTML tags — escape with HTML entities
Section titled “Rule 2: Curly braces inside HTML tags — escape with HTML entities”MDX parses {...} inside JSX context (including inside HTML elements like <td>, <code>, <span>) as a JSX expression. If you write a code example containing literal braces — a YAML example, a TypeScript object literal, a Bases formula — the parser tries to evaluate the brace contents as JavaScript and crashes at build time with a loud but confusing error:
Braces inside markdown backticks are safe — MDX protects inline code from JSX parsing. Only braces inside HTML element content (<code>...</code>, <td>...</td>, etc.) need escaping. Rule of thumb: if the braces are inside an HTML tag, use { / }. For comparison operators like < and > inside HTML <code> blocks (e.g., a Bases formula), use < / >.
The validation loop — bun run check:mdx
Section titled “The validation loop — bun run check:mdx”A lightweight MDX syntax checker lives at scripts/check-mdx.mjs that parses every .mdx file under docs/src/content/docs/ using @mdx-js/mdx directly — no Astro, no Starlight, no build. Runs in ~1–2 seconds on ~100 files:
Run this after any MDX edit before committing. It catches Rule 2 (curly brace parse errors) reliably, plus unclosed JSX tags, bad template literals inside <style> blocks, and invalid frontmatter YAML. Exit code is non-zero on any failure, so you can wire it into a pre-commit hook or CI.
It does not catch Rule 1 (SVG attribute lowercasing) — that’s HTML parsing that happens at a later stage in the pipeline, not MDX-parse time. For Rule 1 you still need to mentally review inline SVG attributes before committing or run the full dev server (bun run serve:docs). The checker catches MDX syntax errors; the dev server catches rendered output errors.
For full validation coverage (cross-link 404s, tag vocabulary enforcement, Starlight schema validation) you still need bun run serve:docs or bun run build. The check:mdx script is the fast first pass.
Cross-linking convention
Section titled “Cross-linking convention”Links are critical in this knowledge base. Every page should aggressively cross-link to related concepts, decisions, and definitions:
- Link terms to their terminology definitions on first mention
- Link concepts to the pages that explore them deeper (log entries, concept pages)
- Every log page must have a
## Relatedsection at the bottom with links to related pages - Roadmap items should link to their log entries, research pages, and concept pages
- When a term has aliases (e.g., “interlingua / pivot” = “synthetic spine” = “meta-framework”), mention the aliases and link to the terminology entry
- Link to the project’s philosophical pillars (vision, problem, what makes Crosswalker unique) where design decisions connect to them
The goal: a reader should be able to follow any concept from any page to its definition, rationale, and related decisions without dead ends.
The log / challenge / roadmap / decision lifecycle
Section titled “The log / challenge / roadmap / decision lifecycle”The docs site follows a specific lifecycle for research and architectural decisions:
1. Log (agent-context/zz-log/YYYY-MM-DD-topic-slug.mdx)
Section titled “1. Log (agent-context/zz-log/YYYY-MM-DD-topic-slug.mdx)”Dated notes, research synthesis, working ideas, decision records. Write these freely — they’re chronological and permanent. Every significant architectural decision gets a log entry with rationale. Filename prefix parses to the date: frontmatter field automatically.
Structure a typical log as:
2. Challenge (agent-context/zz-challenges/NN-topic-slug.mdx)
Section titled “2. Challenge (agent-context/zz-challenges/NN-topic-slug.mdx)”Fresh-agent research briefs. When you want an independent perspective on an architectural assumption, write a challenge brief and hand it to a new agent with no prior context. Findings flow back as dated log entries, not as edits to the challenge itself — this keeps the challenge re-runnable with different agents.
See Challenges 06 (synthetic spine) and 07 (link metadata edge model) for the current format.
3. Roadmap (reference/roadmap/index.mdx)
Section titled “3. Roadmap (reference/roadmap/index.mdx)”Roadmap items should link to their log entries and challenges for rationale. Every significant item has a “why we picked this” that traces back to a log.
4. Concept page (concepts/*.mdx)
Section titled “4. Concept page (concepts/*.mdx)”Once a decision crystallizes, the stable version lives as a concept page. Concept pages are “here’s how it is now,” not “here’s how we got here” — that stays in the log.
5. Terminology (concepts/terminology.mdx)
Section titled “5. Terminology (concepts/terminology.mdx)”New terms get entries with aliases in the term column. Alias every concept with multiple common names so readers searching any term land on the canonical entry. Example: **Interlingua / pivot** — also: pivot ontology, synthetic spine, hub-and-spoke mapping, meta-framework.
6. Registry (reference/registry/*.mdx)
Section titled “6. Registry (reference/registry/*.mdx)”Canonical facts about external orgs, standards, methodologies, and publications (NIST, SCF, SKOS, SSSOM, STRM, BFO, etc.) that the KB cites in multiple places. Each entry is a compact reference card (~40 lines) with:
See existing registry entries for format.
Testing docs changes
Section titled “Testing docs changes”See the testing page for the full breakdown of the three test surfaces (plugin Jest, plugin WebdriverIO, docs Playwright).
Reporting issues
Section titled “Reporting issues”File issues at github.com/cybersader/crosswalker/issues with:
- Clear title and description
- Steps to reproduce
- Expected vs. actual behavior
- Sample data if relevant (anonymized if sensitive)
- Obsidian version and OS
- Plugin version from
manifest.json