Skip to content

fix: support underscored docs and md URLs#2095

Merged
yottahmd merged 2 commits intomainfrom
codex/docs-underscore-md-routing
May 6, 2026
Merged

fix: support underscored docs and md URLs#2095
yottahmd merged 2 commits intomainfrom
codex/docs-underscore-md-routing

Conversation

@yottahmd
Copy link
Copy Markdown
Collaborator

@yottahmd yottahmd commented May 5, 2026

Summary

  • allow document path segments that start with _ so existing _index.md-style docs are listed and readable
  • normalize docs page URLs that end in .md before opening the document tab
  • add regression coverage for underscored docs, docs URL normalization, and docs path validation

Root cause

Document ID validation required every path segment to start with an alphanumeric character, so _-prefixed Markdown files were treated as non-conforming and skipped or rejected. The docs page also used the raw route path as the document ID, so /docs/foo.md attempted to load foo.md instead of the stored foo document.

Testing

  • go test ./internal/agent ./internal/persis/filedoc ./internal/service/frontend/api/v1
  • pnpm test src/pages/docs/lib/__tests__/doc-url.test.ts src/pages/docs/lib/__tests__/doc-validation.test.ts
  • pnpm typecheck
  • make test TEST_TARGET="./internal/agent ./internal/persis/filedoc ./internal/service/frontend/api/v1"
  • pnpm test
  • make check

Summary by CodeRabbit

  • New Features

    • Documents can now have IDs and path segments starting with underscores (e.g., _index, guides/_partial).
    • Document URLs are automatically normalized by stripping .md extensions when syncing tabs.
  • Tests

    • Added comprehensive tests for underscore-prefixed document operations including creation, retrieval, and tree listing.
    • Added validation tests for document path format rules.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8955fb34-61da-4c78-a25e-9960d90a4bad

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR enables document IDs and paths to start with underscores by updating backend validation regex patterns, adding frontend path normalization to strip .md extensions, and providing comprehensive test coverage across both layers to verify the feature works end-to-end.

Changes

Underscore-Prefixed Document Support

Layer / File(s) Summary
Validation Rules
internal/agent/doc.go
validDocIDRegexp updated to accept leading underscores as the first character of each segment; error message adjusted to reflect the new pattern.
Backend Tests
internal/persis/filedoc/store_test.go
TestValidateDocID extended with _leading-underscore and nested/_partial cases; TestListTreeIncludesLeadingUnderscoreDocs and TestGetLeadingUnderscoreDoc added to verify listing and retrieval of leading-underscore docs.
Frontend Normalization & Validation
ui/src/pages/docs/lib/doc-url.ts, ui/src/pages/docs/lib/doc-validation.ts
normalizeDocPathFromURL exported to strip trailing .md extension (case-insensitive); validateDocPath error formatting adjusted for readability.
Frontend Integration
ui/src/pages/docs/index.tsx
URL-derived doc paths are normalized via normalizeDocPathFromURL before tab sync to remove .md suffixes.
Frontend Tests
ui/src/pages/docs/lib/__tests__/doc-url.test.ts, ui/src/pages/docs/lib/__tests__/doc-validation.test.ts
Test suite for normalizeDocPathFromURL covering .md stripping, underscore preservation, and non-markdown suffix handling; test suite for validateDocPath confirming underscore-prefixed segments are accepted and dot-prefixed hidden files are rejected.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main changes: adding support for underscore-prefixed document files and normalizing markdown URLs, which are the core objectives of the pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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 codex/docs-underscore-md-routing

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

@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: 3

🧹 Nitpick comments (2)
internal/agent/doc.go (1)

141-141: ⚡ Quick win

Avoid hardcoding the regex pattern text in the error message.

ValidateDocID now has the pattern in two places (regexp + error string). Consider deriving the message from validDocIDRegexp.String() (or a shared constant) to prevent silent drift on future edits.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/agent/doc.go` at line 141, The error message in ValidateDocID
hardcodes the regex text causing duplication; change the fmt.Errorf call to
reference the canonical regexp (validDocIDRegexp.String()) or a shared constant
instead of the literal pattern so the message is derived from validDocIDRegexp,
e.g. build the error with fmt.Errorf("%w: must match pattern %s",
ErrInvalidDocID, validDocIDRegexp.String()), keeping ErrInvalidDocID as the
wrapped error.
ui/src/pages/docs/lib/__tests__/doc-url.test.ts (1)

5-20: ⚡ Quick win

Add an explicit uppercase extension case to lock in case-insensitive behavior.

The implementation uses a case-insensitive regex; add a direct .MD assertion so future changes can’t accidentally narrow behavior.

Proposed test addition
   it('strips a markdown extension from URL paths', () => {
     expect(normalizeDocPathFromURL('runbooks/deploy.md')).toBe(
       'runbooks/deploy'
     );
+    expect(normalizeDocPathFromURL('runbooks/DEPLOY.MD')).toBe(
+      'runbooks/DEPLOY'
+    );
   });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui/src/pages/docs/lib/__tests__/doc-url.test.ts` around lines 5 - 20, Add a
test case to doc-url.test.ts that asserts normalizeDocPathFromURL treats
uppercase ".MD" the same as ".md" (e.g.,
expect(normalizeDocPathFromURL('runbooks/deploy.MD')).toBe('runbooks/deploy')),
so the case-insensitive behavior of normalizeDocPathFromURL is locked in; locate
the existing tests in this file that cover lowercase ".md" and the non-markdown
suffix and insert the uppercase ".MD" assertion near them.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ui/src/pages/docs/lib/__tests__/doc-url.test.ts`:
- Around line 1-2: This test file is missing the required GPLv3 license header;
add the project-standard GPLv3 header at the very top of the file (above the
imports) to match other TypeScript sources, then run the repository's license
tool (make addlicense) or commit the exact header used elsewhere so the file
containing imports and symbols like normalizeDocPathFromURL, describe, expect,
and it passes the repository's license checks.

In `@ui/src/pages/docs/lib/__tests__/doc-validation.test.ts`:
- Around line 1-2: This new TypeScript test file is missing the required GPLv3
license header; add the repository's standard GPL v3 header at the very top of
ui/src/pages/docs/lib/__tests__/doc-validation.test.ts (above the imports) so it
matches other *.ts files—either run the repository helper (make addlicense) to
insert the correct header automatically or paste the exact GPLv3 header used
elsewhere in the repo into the top of this file.

In `@ui/src/pages/docs/lib/doc-url.ts`:
- Around line 1-3: This file is missing the repository-required GPLv3 license
header; add the standard GPLv3 header to the top of the TypeScript file (above
the export) so it matches the project's licensing policy, either by running the
repository tool (make addlicense) or by inserting the canonical GPLv3 header
comment manually before the normalizeDocPathFromURL function declaration; ensure
the header format matches other .ts/.tsx files in the repo.

---

Nitpick comments:
In `@internal/agent/doc.go`:
- Line 141: The error message in ValidateDocID hardcodes the regex text causing
duplication; change the fmt.Errorf call to reference the canonical regexp
(validDocIDRegexp.String()) or a shared constant instead of the literal pattern
so the message is derived from validDocIDRegexp, e.g. build the error with
fmt.Errorf("%w: must match pattern %s", ErrInvalidDocID,
validDocIDRegexp.String()), keeping ErrInvalidDocID as the wrapped error.

In `@ui/src/pages/docs/lib/__tests__/doc-url.test.ts`:
- Around line 5-20: Add a test case to doc-url.test.ts that asserts
normalizeDocPathFromURL treats uppercase ".MD" the same as ".md" (e.g.,
expect(normalizeDocPathFromURL('runbooks/deploy.MD')).toBe('runbooks/deploy')),
so the case-insensitive behavior of normalizeDocPathFromURL is locked in; locate
the existing tests in this file that cover lowercase ".md" and the non-markdown
suffix and insert the uppercase ".MD" assertion near them.
🪄 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: 70fc983d-3ba8-405c-bf76-c79fe5476fae

📥 Commits

Reviewing files that changed from the base of the PR and between e29c43e and 3f0c443.

📒 Files selected for processing (7)
  • internal/agent/doc.go
  • internal/persis/filedoc/store_test.go
  • ui/src/pages/docs/index.tsx
  • ui/src/pages/docs/lib/__tests__/doc-url.test.ts
  • ui/src/pages/docs/lib/__tests__/doc-validation.test.ts
  • ui/src/pages/docs/lib/doc-url.ts
  • ui/src/pages/docs/lib/doc-validation.ts

Comment thread ui/src/pages/docs/lib/__tests__/doc-url.test.ts
Comment thread ui/src/pages/docs/lib/__tests__/doc-validation.test.ts
Comment thread ui/src/pages/docs/lib/doc-url.ts
@yottahmd yottahmd force-pushed the main branch 3 times, most recently from a9588c2 to e20ea9a Compare May 6, 2026 02:25
@yottahmd yottahmd force-pushed the codex/docs-underscore-md-routing branch from fbc6e7e to 035bd23 Compare May 6, 2026 02:32
@yottahmd yottahmd merged commit 1808c70 into main May 6, 2026
11 checks passed
@yottahmd yottahmd deleted the codex/docs-underscore-md-routing branch May 6, 2026 03:01
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