/** * detector capability 表 — engine が「何を実装しているか」の単一ソース。 * * 実測(Phase 2)で、detector の全集合は 5 箇所に重複定義されていた * (rule.schema.json / types.ts の union 2 箇所 / server.ts の MCP enum / validate.ts)。 * 現時点では全部一致しているが同期機構はゼロで、派生述語(matcher の * AUTO_DETECTABLE_DETECTORS)とコメントは既にズレていた。 * * ここを唯一の真理にして、consumer は導出で追従する。 * S0 では matcher と ruleset 検証をここに寄せ、 * types.ts / server.ts / validate.ts の導出は S1 で行う。 * * 汎用化(第三者 ruleset)の観点では、この表は * 「engine v1 が評価できる detector と、その detector が実際に参照するフィールド」の宣言。 * ここに無い detector や、宣言しても参照されないフィールドは * **黙って素通りさせず診断で落とす**(G-C)。 */ /** * engine が解釈できる bundle schema のバージョン。 * bundle 側が宣言した値がこれと違えば、黙って古い/新しい解釈で動かず fail-fast する。 * 宣言が無い bundle は「1(初版)」とみなす(既存 melta との互換)。 */ export declare const BUNDLE_SCHEMA_VERSION = 1; /** matcher.matches() が参照しうる pattern 系フィールド */ export type MatchSource = "pattern" | "matchPatterns" | "prefixPatterns"; /** * engine が解釈できる severity。ruleset 側がこれ以外を書いたら評価不能。 * 型・MCP の enum・validate・ランタイム検証はすべてここから導出する。 */ export declare const KNOWN_SEVERITIES: readonly ["error", "warn"]; export type KnownSeverity = (typeof KNOWN_SEVERITIES)[number]; export declare function isKnownSeverity(value: unknown): value is KnownSeverity; export interface DetectorCapability { /** class 文字列マッチ(matcher.matches)で判定できるか */ autoDetectable: boolean; /** * この detector の matches() が実際に参照するフィールド。 * 宣言されていても**ここに無いフィールドは読まれない**(= 書いても効かない)。 * autoDetectable=false の detector では空。 * * **並び順は matches() の評価順**。ただし各フィールドの終端条件は同じではない * (prefixPatterns は miss なら次へ進み、matchPatterns は存在するだけで終端する)。 * 正確な意味論は matcher.matches() の doc comment を正とする。 * 順序だけでこの非対称を表現できないことが、S1+S2 で「必須性ごと再定義」する理由。 */ matchSources: readonly MatchSource[]; /** * この detector の検査を駆動する check spec のフィールド名。不要なら null。 * 「所有関係」であって必須性ではない(specRequired を参照)。 */ specField: "htmlAttrCheck" | "compositionCheck" | null; /** * spec が無いルールを不正とみなすか。 * 実測: melta の html-attr 11 件中 4 件は意図的に spec を持たない * (文脈依存で静的表現できないものを「宣言だけ残す」既存イディオム)。 * よって現状は全 detector で false。「許容するが未検査」は S3 の capability 診断で露出させる。 */ specRequired: boolean; /** 何を見る detector か(診断メッセージ用) */ summary: string; } export declare const DETECTOR_CAPABILITIES: { readonly "tailwind-class": { readonly autoDetectable: true; readonly matchSources: readonly ["matchPatterns", "pattern"]; readonly specField: null; readonly specRequired: false; readonly summary: "class token の完全一致"; }; readonly "tailwind-class-prefix": { readonly autoDetectable: true; readonly matchSources: readonly ["prefixPatterns", "matchPatterns", "pattern"]; readonly specField: null; readonly specRequired: false; readonly summary: "class token の前方一致(+ opacity modifier)"; }; readonly "tailwind-class-segment": { readonly autoDetectable: true; readonly matchSources: readonly ["matchPatterns"]; readonly specField: null; readonly specRequired: false; readonly summary: "class token を区切りで分割した segment の一致"; }; readonly "html-attr": { readonly autoDetectable: false; readonly matchSources: readonly []; readonly specField: "htmlAttrCheck"; readonly specRequired: false; readonly summary: "属性の有無・値(htmlAttrCheck spec があるものだけ検査される)"; }; readonly composition: { readonly autoDetectable: false; readonly matchSources: readonly []; readonly specField: "compositionCheck"; readonly specRequired: false; readonly summary: "DOM 上の要素間の関係(compositionCheck spec があるものだけ検査される)"; }; readonly manual: { readonly autoDetectable: false; readonly matchSources: readonly []; readonly specField: null; readonly specRequired: false; readonly summary: "静的検査の対象外(人間 / テストが担保)"; }; }; export type KnownDetector = keyof typeof DETECTOR_CAPABILITIES; /** engine v1 が解釈できる detector の全集合 */ export declare const KNOWN_DETECTORS: KnownDetector[]; /** class 文字列マッチで自動検出できる detector(AUTO_DETECTABLE_DETECTORS の実体) */ export declare const AUTO_DETECTABLE_DETECTORS: ("tailwind-class" | "tailwind-class-prefix" | "tailwind-class-segment" | "html-attr" | "composition" | "manual")[]; /** * check spec の kind ごとに、engine の実装が実際に読むフィールド。 * ここも capability 表の一部(= engine が何を実装しているかの宣言)。 * * required を欠くと「undefined を埋め込んだ正規表現を無言で実行」や * 「空配列で全件違反」になるため、load 時に検証する。 * string = 空でない文字列 / stringArray = 空でない文字列の非空配列。 */ export interface CheckKindShape { /** 必須・空でない文字列 */ string?: readonly string[]; /** 必須・空でない文字列の非空配列 */ stringArray?: readonly string[]; /** * 必須・非空配列で、要素は**空白を含まない** token。 * class 名 / 属性名は空白で分割された単位と完全一致で比較されるため、 * "h-11 after:h-11" のような複数 token をまとめた値は決して一致しない。 */ tokenArray?: readonly string[]; /** 省略可。あれば空でない文字列 */ optionalString?: readonly string[]; /** 省略可。あれば空でない文字列の非空配列 */ optionalStringArray?: readonly string[]; /** * 省略可。あれば非空配列で、要素は**1 コードポイントの文字**。 * 実装は対象テキストを 1 コードポイントずつ照合するため、 * 2 文字以上の要素("×✕")や空白入り(" × ")は永久に一致しない。 */ charArray?: readonly string[]; /** 省略可。あればこの値のいずれか(engine が分岐に使う述語・スコープ) */ enums?: Readonly>; /** 条件付き必須(field が equals のとき requires が必要) */ requiredWhen?: readonly { field: string; equals: string; requires: string; }[]; } /** 合成 lint の候補述語(composition-lint.qualifies が実装しているもの) */ export declare const COMPOSITION_PREDICATES: readonly ["icon-only", "text-glyph"]; /** 合成 lint の探索スコープ */ export declare const COMPOSITION_SCOPES: readonly ["self", "ancestor-or-self"]; export declare const HTML_ATTR_CHECK_KINDS: { readonly "attr-value-forbidden": { readonly string: readonly ["attr", "valueRegex"]; }; readonly "attr-value-contains": { readonly string: readonly ["attr", "valueRegex"]; }; readonly "attr-present": { readonly string: readonly ["attr"]; readonly optionalString: readonly ["tag"]; }; readonly "tag-present": { readonly string: readonly ["tag"]; }; readonly "tag-missing-attr": { readonly string: readonly ["tag", "requiredAttr"]; }; readonly "element-present": { readonly string: readonly ["tag", "attr", "attrValue"]; }; }; export declare const COMPOSITION_CHECK_KINDS: { readonly "nested-selector": { readonly string: readonly ["selector"]; }; readonly "dom-class-required": { readonly string: readonly ["selector"]; readonly tokenArray: readonly ["requireAnyClass"]; readonly charArray: readonly ["glyphs"]; readonly enums: { readonly excludeWhen: readonly ["icon-only", "text-glyph"]; }; readonly requiredWhen: readonly [{ readonly field: "excludeWhen"; readonly equals: "text-glyph"; readonly requires: "glyphs"; }]; }; readonly "dom-attr-required": { readonly string: readonly ["selector"]; readonly tokenArray: readonly ["requireAnyAttr"]; readonly charArray: readonly ["glyphs"]; readonly enums: { readonly when: readonly ["icon-only", "text-glyph"]; readonly scope: readonly ["self", "ancestor-or-self"]; }; readonly requiredWhen: readonly [{ readonly field: "when"; readonly equals: "text-glyph"; readonly requires: "glyphs"; }]; }; }; /** spec フィールド名 → その kind 表 */ export declare const CHECK_KIND_SHAPES: Record>; /** pattern 系フィールドの全集合(「宣言したのに読まれない」判定に使う) */ export declare const ALL_MATCH_SOURCES: readonly MatchSource[]; /** spec フィールド名 → それを所有する detector の逆引き */ export declare const SPEC_OWNER: Record; /** * 既知 detector 判定。 * `in` 演算子は prototype chain も見るため、detector: "constructor" / "toString" が * 既知扱いになって「検査されないまま合格」に戻ってしまう。自前プロパティだけを見る。 */ export declare function isKnownDetector(value: unknown): value is KnownDetector; /** その detector の検査を駆動する spec フィールド名(無ければ null) */ export declare function specFieldFor(detector: unknown): "htmlAttrCheck" | "compositionCheck" | null; /** * spec 駆動の detector が、実際に走る spec を持っているか。 * 「宣言はあるが評価されない」(spec 無しの html-attr 等)を false 側に落とす。 * types.ts に依存しないよう構造的な型で受ける(types.ts → detectors.ts の一方向を保つため)。 */ export declare function hasRunnableSpec(rule: { detector?: unknown; } & Record): boolean;