Skip to content
Merged
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
16 changes: 13 additions & 3 deletions src/db/repositories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5286,6 +5286,13 @@ export async function getLatestPublishedLinkedIssueSatisfaction(
* miss. Unlike linked_issue_satisfaction_cache, every stored row is durable with NO input-fingerprint
* dimension -- file content at an immutable head SHA has exactly one correct value, so a hit is always safe
* to reuse verbatim. A nullish head SHA is always a miss (mirrors the sibling caches' contract). */
// #7481-class fix: bounds how long a row can be served once written, as a safety net against a caller passing
// a mutable ref (a branch name) instead of a genuine commit SHA -- see schema.ts's fuller comment on
// groundingFileContentCache. Generous enough that it never affects the cache's real purpose (reusing a
// commit's content across review lanes / re-runs within the same PR, which happens within minutes), but bounds
// worst-case staleness for a misused mutable ref to hours, not indefinitely.
const GROUNDING_CACHE_TTL_MS = 24 * 60 * 60 * 1000;

export async function getCachedGroundingFileContent(
env: Env,
repoFullName: string,
Expand All @@ -5294,10 +5301,13 @@ export async function getCachedGroundingFileContent(
): Promise<string | null> {
if (!headSha) return null;
const row = await env.DB
.prepare("SELECT content FROM grounding_file_content_cache WHERE repo_full_name = ? AND path = ? AND head_sha = ?")
.prepare("SELECT content, fetched_at FROM grounding_file_content_cache WHERE repo_full_name = ? AND path = ? AND head_sha = ?")
.bind(repoFullName, path, headSha)
.first<{ content: string }>();
return row?.content ?? null;
.first<{ content: string; fetched_at: string }>();
if (!row) return null;
const fetchedMs = Date.parse(row.fetched_at);
if (!Number.isFinite(fetchedMs) || Date.now() - fetchedMs > GROUNDING_CACHE_TTL_MS) return null;
return row.content;
}

/** #4499 (grounding-file-content-cache): upsert the fetched file content for (repo, path, head SHA). A
Expand Down
9 changes: 9 additions & 0 deletions src/db/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1426,6 +1426,15 @@ export const linkedIssueSatisfactionCache = sqliteTable(
// immutable commit, so it's safe to cache durably. NOT scoped to pullNumber (unlike linkedIssueSatisfactionCache
// above) -- file content at a given head SHA is universal, not PR-specific. Only a successful fetch is ever
// stored; a transient failure must never be cached as if it were a confirmed-permanent one.
// #7481-class fix: that immutability assumption holds only when `headSha` is genuinely a commit SHA -- a caller
// that instead passes a mutable ref (content-lane-wire.ts's base-content check uses the PR's base BRANCH NAME
// when no commit SHA is known) can poison a row forever, since the literal ref string never itself changes as
// the branch advances (confirmed empirically: a real metagraphed registry-file row keyed by the branch name
// "main" sat stale for over a week on the ORB server, silently serving every subsequent PR's base-content check
// a snapshot from before that window). getCachedGroundingFileContent now enforces a TTL (GROUNDING_CACHE_TTL_MS)
// at read time as a safety net against ANY caller violating the immutability assumption, current or future --
// harmless for a true SHA (an occasional extra re-fetch of content that never changes), but bounds the
// worst-case staleness for a mutable ref to that TTL instead of indefinitely.
export const groundingFileContentCache = sqliteTable(
"grounding_file_content_cache",
{
Expand Down
2 changes: 1 addition & 1 deletion src/queue/processors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7577,7 +7577,7 @@ export async function runContentLaneDeliverableCheckForAdvisory(
.join("\n\n");
if (!issueText.trim()) return;
const changedFiles = args.files.map((file) => file.path);
const result = checkContentLaneDeliverable(spec, issueText, changedFiles);
const result = checkContentLaneDeliverable(spec, issueText, changedFiles, issueFetch.facts.title ?? undefined);
if (result.verdict !== "missing") return;
args.advisory.findings.push({
code: "content_lane_deliverable_missing",
Expand Down
15 changes: 14 additions & 1 deletion src/review/content-lane-wire.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { runSurfaceReview, type SurfaceReviewInput, type SurfaceReviewResult } f
import type { RegistryLaneSpec } from "./content-lane/registry-logic";
import { registeredValidatorIds, resolveRegistryLaneSpec, unregisteredValidatorId } from "./content-lane/spec-resolver";
import { makeGithubFileFetcher } from "./grounding-wire";
import { MAX_FETCH_CHARS } from "./review-grounding";
import type { FocusManifest } from "../signals/focus-manifest";
import { loadRepoFocusManifest } from "../signals/focus-manifest-loader";
import type { AdvisoryFinding, AdvisorySeverity } from "../types";
Expand Down Expand Up @@ -184,7 +185,19 @@ export async function runRegistrySurfaceGate(
const githubLoad = async (path: string, ref: "head" | "base"): Promise<string | null> => {
fetcherPromise ??= makeGithubFileFetcher(env, args.repoFullName, args.installationId);
const fetcher = await fetcherPromise;
return fetcher.getFileContent(path, ref === "head" ? args.pr.headSha : args.pr.baseRef);
const content = await fetcher.getFileContent(path, ref === "head" ? args.pr.headSha : args.pr.baseRef, MAX_FETCH_CHARS);
// #7481-class fix: unlike AI-review grounding (which tolerates a partial sample), this lane parses the
// fetched body as JSON and diffs its surfaces[] array deterministically -- a TRUNCATED body (the fetcher's
// maxChars+1-length signal, same convention patchless-secret-scan.ts relies on) is invalid JSON, which
// safeParseJson silently swallows into `null`, which reads as "surfaces: null" -- indistinguishable from a
// genuinely malformed submission. Without MAX_FETCH_CHARS above, the fetcher's small 24_001-char default
// truncated any registry file past that size (a metagraphed subnet manifest routinely exceeds it once it
// accumulates enough entries), and this file's own null-only unreadable check below never caught it, since
// a truncated fetch returns a non-null (just incomplete) string -- so a fully valid, large surfaces[] append
// silently misread as "zero entries appended" and one-shot closed. Converting it to a null return here
// routes it through the SAME defer-to-generic-gate guard as a real unreadable fetch, instead of a wrong close.
if (content !== null && content.length > MAX_FETCH_CHARS) return null;
return content;
};
const baseLoad = loadFileOverride ?? githubLoad;
const statusByPath = new Map(args.files.map((file) => [file.path, file.status ?? null]));
Expand Down
72 changes: 59 additions & 13 deletions src/review/content-lane/registry-logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,22 @@ export interface RegistryLaneSpec {
* domain-specific check, analogous to `assessAppendedEntry` but for the provider-file scope. Omitted ⇒ the
* orchestrator returns "manual" for provider submissions to this registry. */
assessProviderEntry?: (document: unknown, opts?: { secretsScan?: boolean; sourceUrlValidation?: boolean }) => ProviderAssessment;
/** Optional (#content-lane-deliverable follow-up): a regex tested against a linked issue's TITLE (not body)
* that, when it matches, marks the issue as requiring an entry/provider-file edit even when
* `checkContentLaneDeliverable`'s own literal-path scan of the issue BODY finds nothing to check against.
* Exists for a KNOWN, confirmed gap: metagraphed's ~120 "MCP execute: verify + wire SN<netuid> (<name>)"
* issues (#7017-#7136) ask a contributor to add missing surfaces to `registry/subnets/<slug>.json`, but their
* bodies write that path with the LITERAL, generic `<slug>` placeholder (a documentation convention, not a
* template variable meant to be filled in), never the real resolved filename — confirmed empirically against
* issue #7060's actual body, which contains zero `registry/subnets/*.json`-shaped tokens at all. Without this
* field, the literal-path-only check returns "not-applicable" for the ENTIRE family, providing no protection
* against exactly the anti-pattern it exists to catch (a merged PR that adds only a test file, zero registry
* changes — confirmed live 2026-07-21, see metagraphed's own contributor-pipeline-gardening skill). Omitted
* ⇒ only the literal-path signal applies (today's behavior for any spec that doesn't opt in). Deliberately a
* TITLE match, not a fuzzy body/slug inference — a specific, known issue-title shape is a safe, zero-
* hallucination signal; guessing a subnet's file name from its display name is not, and a false "missing" on
* a genuinely-delivered PR is the more expensive mistake here. */
issueTitleImpliesEntryPattern?: RegExp;
}

export type RegistryPrScope = "entry-submission" | "provider-submission" | "mixed-files" | "not-direct-submission";
Expand Down Expand Up @@ -847,26 +863,47 @@ export function extractPathTokens(text: string): string[] {
return [...new Set(text.match(PATH_TOKEN_PATTERN) ?? [])];
}

/** `not-applicable`: the issue text names no path matching this spec's own patterns at all — nothing to check
* (an unrelated issue, e.g. a docs or code-fix issue, on the same content-lane repo). `delivered`: the issue
* names such a path AND the PR's changed files touch at least one file matching the spec — the common,
* expected case for a real contribution. `missing`: the issue names such a path but the PR touches NONE
* matching — the gap this check exists to catch, independent of AI judgment, CI status, or a closing keyword. */
/** `not-applicable`: the issue names no path matching this spec's own patterns AND (when the spec opts into
* `issueTitleImpliesEntryPattern`) the issue's title doesn't match that pattern either — nothing to check (an
* unrelated issue, e.g. a docs or code-fix issue, on the same content-lane repo). `delivered`: the issue names
* such a path (or its title matches the spec's title pattern) AND the PR's changed files touch at least one
* file matching the spec — the common, expected case for a real contribution. `missing`: the issue implies a
* delivery (by either signal) but the PR touches NONE matching — the gap this check exists to catch,
* independent of AI judgment, CI status, or a closing keyword. `mentionedPath` is the literal path found in
* the body when that signal fired, or a description of the spec's expected file when only the title signal
* fired (no literal path was ever found in that case — see checkContentLaneDeliverable). */
export type ContentLaneDeliverableCheck = { verdict: "not-applicable" } | { verdict: "delivered" } | { verdict: "missing"; mentionedPath: string };

/**
* Determine whether a PR's changed files deliver the content-lane file its linked issue's own text names.
* PURE — no I/O, no registry-specific hardcoding; entirely driven by `spec` (the caller's already-resolved
* RegistryLaneSpec) and the two text inputs. `changedFiles` are matched the SAME way classifyRegistryPrScope
* matches them (canonicalized: lowercased + `./`-stripped + `\`→`/`), so an uppercase / `./`-prefixed /
* `\`-separated changed path is recognized identically to how the rest of the content lane already treats it.
* Determine whether a PR's changed files deliver the content-lane file its linked issue implies. PURE — no I/O,
* no registry-specific hardcoding; entirely driven by `spec` (the caller's already-resolved RegistryLaneSpec)
* and the text inputs. `changedFiles` are matched the SAME way classifyRegistryPrScope matches them
* (canonicalized: lowercased + `./`-stripped + `\`→`/`), so an uppercase / `./`-prefixed / `\`-separated
* changed path is recognized identically to how the rest of the content lane already treats it.
*
* Two independent, deterministic signals decide whether the issue implies a delivery, checked in this order:
* 1. A literal path in the issue BODY matching the spec (the general case — works for any hand-written issue
* that names the real file).
* 2. Failing that, `issueTitle` against the spec's OWN `issueTitleImpliesEntryPattern` (when configured) — a
* narrow, opt-in fallback for a KNOWN issue-title shape whose body only ever contains a generic path
* placeholder, never the real resolved filename (see that field's own doc comment for why this exists as a
* separate, deliberately non-fuzzy signal rather than inferring a slug from the issue's prose).
* Neither signal firing ⇒ "not-applicable". `issueTitle` is optional so an existing caller that doesn't pass
* one keeps today's literal-path-only behavior verbatim.
*/
export function checkContentLaneDeliverable(spec: RegistryLaneSpec, issueText: string, changedFiles: readonly string[]): ContentLaneDeliverableCheck {
export function checkContentLaneDeliverable(
spec: RegistryLaneSpec,
issueText: string,
changedFiles: readonly string[],
issueTitle?: string,
): ContentLaneDeliverableCheck {
const matchesSpec = (candidate: string): boolean => spec.entryFilePattern.test(candidate) || (spec.providerFilePattern?.test(candidate) ?? false);
const mentionedPath = extractPathTokens(issueText).find(matchesSpec);
if (!mentionedPath) return { verdict: "not-applicable" };
const titleImplies = !mentionedPath && Boolean(issueTitle && spec.issueTitleImpliesEntryPattern?.test(issueTitle));
if (!mentionedPath && !titleImplies) return { verdict: "not-applicable" };
const delivered = changedFiles.some((file) => matchesSpec(canonicalize(file)));
return delivered ? { verdict: "delivered" } : { verdict: "missing", mentionedPath };
if (delivered) return { verdict: "delivered" };
return { verdict: "missing", mentionedPath: mentionedPath ?? `a registry entry file matching ${spec.entryFilePattern} (implied by this issue's title)` };
}

// metagraphed's spec — the first RegistryLaneSpec. surfaces[] live in registry/subnets/<slug>.json; providers
Expand All @@ -893,4 +930,13 @@ export const METAGRAPHED_LANE_SPEC: RegistryLaneSpec = {
// checks) — supplied here, not hardcoded into the orchestrator, so a different registry can supply its own.
assessAppendedEntry: assessSubnetDocument,
assessProviderEntry: assessProviderDocument,
// #content-lane-deliverable follow-up: metagraphed's ~120 "MCP execute: verify + wire SN<netuid> (<name>)
// once Phase 1 ships" issues (#7017-#7136, tracked under epic #7013/#7014) ask a contributor to add missing
// surfaces to registry/subnets/<slug>.json, but their bodies spell that path with the literal, generic
// `<slug>` placeholder — never the real resolved filename — so checkContentLaneDeliverable's own literal-
// path scan of the body finds nothing to check against for this entire family (confirmed empirically against
// issue #7060's actual body). Matches metagraphed's own contributor-pipeline-gardening skill's documented
// title convention for this exact family; deliberately anchored + narrow so it can't accidentally match an
// unrelated issue.
issueTitleImpliesEntryPattern: /^MCP execute:\s*verify\s*\+\s*wire\s+SN\d+/i,
};
Loading