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
2 changes: 1 addition & 1 deletion src/selfhost/config-lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const RETIRED_FIELD_MIGRATION_WARNINGS: Record<string, string> = {
blockedPaths: "blockedPaths is retired; use settings.hardGuardrailGlobs for path holds.",
};

function unknownTopLevelWarnings(text: string | null | undefined): string[] {
export function unknownTopLevelWarnings(text: string | null | undefined): string[] {
const raw = text ?? "";
const trimmed = raw.trim();
if (!trimmed || isOversize(raw)) return [];
Expand Down
6 changes: 5 additions & 1 deletion src/services/focus-manifest-validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
type FocusManifest,
type FocusManifestSource,
} from "../signals/focus-manifest";
import { unknownTopLevelWarnings } from "../selfhost/config-lint";

export type FocusManifestValidationStatus = "ok" | "warn" | "error";

Expand All @@ -28,7 +29,10 @@ export function buildFocusManifestValidation(input: {
source?: FocusManifestSource | undefined;
}): FocusManifestValidationResult {
const manifest = parseFocusManifestContent(input.content, input.source ?? "repo_file");
const warnings = [...manifest.warnings];
// Warn on unrecognized top-level fields (e.g. a typo'd `gates:` instead of `gate:`), matching the
// selfhost config-lint validator — parseFocusManifestContent reads only known fields, so a mistyped
// block is otherwise silently dropped with no warning (#5929).
const warnings = [...manifest.warnings, ...unknownTopLevelWarnings(input.content)];
const normalized = focusManifestToNormalizedJson(manifest);
return {
present: manifest.present,
Expand Down
11 changes: 11 additions & 0 deletions test/unit/focus-manifest-validation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,15 @@ maintainerRecap:
expect(result.status).toBe("error");
expect(result.warnings.join(" ")).toMatch(/must be a mapping/i);
});

it("warns on an unrecognized top-level field (e.g. a typo'd `gates:` for `gate:`), matching config-lint (#5929)", () => {
// A recognized field plus a typo'd block: previously the typo was silently dropped with status "ok".
const result = buildFocusManifestValidation({ content: "wantedPaths:\n - src/\ngates:\n enabled: true\n" });
expect(result.status).toBe("warn");
expect(result.warnings.join(" ")).toMatch(/unknown top-level field/i);
expect(result.warnings.join(" ")).toMatch(/gates/);
// A clean manifest still carries no unknown-field warning.
const clean = buildFocusManifestValidation({ content: "wantedPaths:\n - src/\n" });
expect(clean.warnings.join(" ")).not.toMatch(/unknown top-level field/i);
});
});
Loading