Skip to content

readRealmFile: fetch file-meta for .md files, raw source for everything else#5484

Open
lukemelia wants to merge 2 commits into
mainfrom
cs-12045-readrealmfile-file-meta-for-md
Open

readRealmFile: fetch file-meta for .md files, raw source for everything else#5484
lukemelia wants to merge 2 commits into
mainfrom
cs-12045-readrealmfile-file-meta-for-md

Conversation

@lukemelia

@lukemelia lukemelia commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Linear: CS-12045

The pull model's second leg (independent of the index-time schema stamping — it reads whatever frontmatter.tools the index serves, and behaves as today until that enrichment lands). executeReadRealmFile now branches per URL on file type: markdown fetches the indexed file-meta document; every other file keeps requesting raw source, byte-identical to before. The auth/realm-discovery flow (header probe, delegated token, retry-on-revoke) is shared — only the Accept header and result handling differ.

Behavior

  • Markdown path: Accept: application/vnd.card.file-meta+json. From the document, attributes.content (the frontmatter-stripped body) becomes the attached content — the downstream prompt-inlining path is unchanged — and attributes.frontmatter.tools (index-stamped definition, resolved codeRef, functionName, requiresApproval) are returned structurally on the result as tools for the fulfillment layer. Relative links keep absolutizing against the attachment's sourceUrl, which remains the file URL (indexed content is as-authored).
  • Fallback: when the index can't serve a usable document — 404 (no row yet for a just-written file), an error-state row, or a document without a content string — the read degrades to the raw-source fetch and returns instructions-only. Index lag never fails a read. Auth and network failures skip the fallback: raw source would fail identically, so the error surfaces directly.
  • One markdown predicate: isMarkdownFile lives in runtime-common (paths.ts); the host's isMarkdownSkillId, prompt assembly's isMarkdownSkillFile, and this read path all delegate to it.
  • Tool description: now tells the model that reading a skill's markdown file makes that skill's tools callable on the next turn — the injection leg consumes this.

Landable before the indexer enrichment serves stamped schemas: tools simply come back absent and reads behave as today.

Testing

pnpm test in ai-bot: the new executeReadRealmFile markdown file-meta module covers the happy path (body + stamped tools, single fetch), a plain markdown file (body, no tools), fallback on 404 / contentless document / non-JSON body, the gated-skill token flow on the file-meta Accept type, fallback re-running the auth flow, and no-fallback on access failure. The transport/auth-flow tests now exercise a non-markdown URL, pinning the raw-source path unchanged. 232/234 pass locally — the two failures are the pre-existing locking tests needing a CI-provisioned Postgres role, untouched by this change.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Preview deployments

Host Test Results

    1 files      1 suites   3h 1m 56s ⏱️
3 470 tests 3 455 ✅ 15 💤 0 ❌
3 489 runs  3 474 ✅ 15 💤 0 ❌

Results for commit 80149da.

Realm Server Test Results

    1 files      1 suites   11m 50s ⏱️
1 816 tests 1 816 ✅ 0 💤 0 ❌
1 895 runs  1 895 ✅ 0 💤 0 ❌

Results for commit 80149da.

…ng else

A markdown file read now requests the indexed file-meta document, yielding
the frontmatter-stripped body as the attached content plus the skill's
frontmatter tools (with index-stamped definition, resolved codeRef,
functionName, requiresApproval) returned structurally for the fulfillment
layer. When the index can't serve a usable document — no row yet, an
error-state row, or a document without content — the read degrades to raw
source and returns instructions-only, so index lag never fails a read.
Auth and network failures skip the fallback since raw source would fail
identically. Non-markdown files keep the raw-source path byte-identical.

The markdown predicate is hoisted to runtime-common (isMarkdownFile) so the
host's isMarkdownSkillId, prompt assembly's isMarkdownSkillFile, and the
ai-bot read path share one definition. The tool description now tells the
model that reading a skill file unlocks its tools on the next turn.

CS-12045

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@lukemelia lukemelia force-pushed the cs-12045-readrealmfile-file-meta-for-md branch from e4c1d56 to e782e42 Compare July 13, 2026 19:52
@lukemelia lukemelia changed the base branch from cs-12044-tool-schemas-in-fromfrontmatter to main July 13, 2026 19:52
@github-actions

Copy link
Copy Markdown
Contributor

Observability diff (vs staging)

Show diff
diff --git a/tmp/remote-canon.v6M2Wx/dashboards/boxel-status/indexing.json b/tmp/committed-canon.qhiVzR/dashboards/boxel-status/indexing.json
index fd785f2..d7bf03e 100644
--- a/tmp/remote-canon.v6M2Wx/dashboards/boxel-status/indexing.json
+++ b/tmp/committed-canon.qhiVzR/dashboards/boxel-status/indexing.json
@@ -80,6 +80,10 @@
           "uid": "cef5v5sl9k7i8f"
         },
         "description": "System-wide operator action: queue a full reindex across every realm. The button disables itself while a `full-reindex` orchestration job is already pending or running. Per-realm reindex moved to the Realms dashboard. Click POSTs with `Authorization: Bearer ${grafana_secret}` (substituted from SSM at apply time, CS-10929).",
+        "fieldConfig": {
+          "defaults": {},
+          "overrides": []
+        },
         "gridPos": {
           "h": 8,
           "w": 24,

(Run: https://github.com/cardstack/boxel/actions/runs/29280170242)

@github-actions

Copy link
Copy Markdown
Contributor

Grafana preview

Preview deployed for 1 dashboard in the staging Grafana.
Cross-dashboard drill-throughs still point at the canonical staging dashboards.

Dashboards:

Preview is torn down automatically when this PR is closed or merged.

(Run: https://github.com/cardstack/boxel/actions/runs/29280170231)

Copilot AI left a comment

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.

Pull request overview

This PR updates executeReadRealmFile (ai-bot) to treat markdown URLs specially: markdown reads prefer the indexed file-meta document (to return frontmatter-stripped body plus stamped tool metadata), while all other files continue to fetch raw source byte-identically to the prior behavior. It also centralizes “is this markdown?” detection into a shared isMarkdownFile helper in runtime-common, and wires callers to use it.

Changes:

  • Add isMarkdownFile() in packages/runtime-common/paths.ts and switch prompt/host markdown detection to use it.
  • Update ai-bot executeReadRealmFile to request file-meta for markdown, parse attributes.content + attributes.frontmatter.tools, and fall back to raw source on HTTP/unusable file-meta bodies.
  • Add/adjust ai-bot tests to cover markdown file-meta behavior (happy path, gating/auth flow, and fallback scenarios) and to pin the raw-source path for non-markdown URLs.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/runtime-common/paths.ts Introduces shared isMarkdownFile() predicate for consistent markdown detection across packages.
packages/runtime-common/ai/prompt.ts Switches markdown-skill-file detection to delegate to isMarkdownFile().
packages/host/app/lib/skill-tools.ts Removes local markdown predicate and uses isMarkdownFile() for markdown skill IDs.
packages/ai-bot/lib/read-realm-file.ts Implements markdown=file-meta branching + parsing + fallback behavior; extends result shape with optional tools.
packages/ai-bot/tests/read-realm-file-test.ts Adds a dedicated markdown file-meta test module and updates existing tests to use a non-markdown URL for raw-source transport/auth invariants.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/ai-bot/lib/read-realm-file.ts
typeof [] === 'object', so a malformed tools array whose entries are
themselves arrays would have passed the object filter and reached the
fulfillment layer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

3 participants