# Default-option snapshot — see default_options_snapshot.rs

=== kind: command | id: shellcheck-shell-scripts ===
CommandRule {
    id: "shellcheck-shell-scripts",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    argv: [
        "shellcheck",
    ],
    timeout: 30s,
}

=== kind: commented_out_code | id: no-commented-code ===
CommentedOutCodeRule {
    id: "no-commented-code",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    language: Auto,
    min_lines: 3,
    threshold: 0.5,
    skip_leading_lines: 30,
}

=== kind: content_forbidden | id: content-forbidden-alias ===
FileContentForbiddenRule {
    id: "content-forbidden-alias",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    pattern_src: "unimplemented!",
    pattern: Regex(
        "unimplemented!",
    ),
}

=== kind: content_matches | id: content-matches-alias ===
FileContentMatchesRule {
    id: "content-matches-alias",
    level: Info,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    pattern_src: "version\\s*=",
    pattern: Regex(
        "version\\s*=",
    ),
    fixer: None,
}

=== kind: dir_absent | id: no-target ===
DirAbsentRule {
    id: "no-target",
    level: Error,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    patterns: [
        "**/target",
    ],
    git_tracked_only: false,
}

=== kind: dir_contains | id: packages-have-readme-and-license ===
DirContainsRule {
    id: "packages-have-readme-and-license",
    level: Error,
    policy_url: None,
    message: None,
    select_scope: Scope { ... },
    require_globs: [
        "README.md",
        "LICENSE*",
    ],
    require_matchers: [
        GlobMatcher { ... },
        GlobMatcher { ... },
    ],
}

=== kind: dir_exists | id: docs-dir ===
DirExistsRule {
    id: "docs-dir",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    patterns: [
        "docs/**",
    ],
    git_tracked_only: false,
}

=== kind: dir_only_contains | id: src-only-rs ===
DirOnlyContainsRule {
    id: "src-only-rs",
    level: Error,
    policy_url: None,
    message: Some(
        "{{ctx.basename}} not allowed under {{ctx.dir}}",
    ),
    select_scope: Scope { ... },
    allow_globs: [
        "*.rs",
        "mod.rs",
    ],
    allow_matcher: GlobSet { ... },
}

=== kind: every_matching_has | id: every-pkg-has-src ===
EveryMatchingHasRule {
    id: "every-pkg-has-src",
    level: Error,
    policy_url: None,
    select_scope: Scope { ... },
    when_iter: None,
    require: [
        CompiledNestedSpec {
            spec: NestedRuleSpec {
                kind: "file_exists",
                paths: Some(
                    Single(
                        "{path}/package.json",
                    ),
                ),
                message: None,
                policy_url: None,
                when: None,
                scope_filter: None,
                extra: Mapping {},
            },
            when: None,
        },
    ],
}

=== kind: executable_bit | id: scripts-executable ===
ExecutableBitRule {
    id: "scripts-executable",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    require_exec: true,
}

=== kind: executable_has_shebang | id: exec-needs-shebang ===
ExecutableHasShebangRule {
    id: "exec-needs-shebang",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
}

=== kind: file_absent | id: no-lockfile-bak ===
FileAbsentRule {
    id: "no-lockfile-bak",
    level: Error,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    patterns: [
        "**/Cargo.lock.bak",
        "**/package-lock.json.bak",
    ],
    git_tracked_only: false,
    fixer: Some(
        FileRemoveFixer,
    ),
}

=== kind: file_content_forbidden | id: content-forbidden-todo ===
FileContentForbiddenRule {
    id: "content-forbidden-todo",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    pattern_src: "\\bTODO\\b",
    pattern: Regex(
        "\\bTODO\\b",
    ),
}

=== kind: file_content_forbidden | id: no-todos ===
FileContentForbiddenRule {
    id: "no-todos",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    pattern_src: "\\b(TODO|FIXME|XXX)\\b",
    pattern: Regex(
        "\\b(TODO|FIXME|XXX)\\b",
    ),
}

=== kind: file_content_matches | id: content-matches-spdx ===
FileContentMatchesRule {
    id: "content-matches-spdx",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    pattern_src: "SPDX-License-Identifier",
    pattern: Regex(
        "SPDX-License-Identifier",
    ),
    fixer: None,
}

=== kind: file_content_matches | id: license-header ===
FileContentMatchesRule {
    id: "license-header",
    level: Error,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    pattern_src: "(?i)copyright",
    pattern: Regex(
        "(?i)copyright",
    ),
    fixer: Some(
        FileAppendFixer {
            source: Inline(
                "\n// Copyright (c) 2026\n",
            ),
        },
    ),
}

=== kind: file_ends_with | id: text-files-end-with-newline ===
FileEndsWithRule {
    id: "text-files-end-with-newline",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    suffix: [
        10,
    ],
}

=== kind: file_exists | id: has-editorconfig ===
FileExistsRule {
    id: "has-editorconfig",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    patterns: [
        ".editorconfig",
    ],
    literal_paths: Some(
        [
            ".editorconfig",
        ],
    ),
    root_only: true,
    git_tracked_only: false,
    fixer: Some(
        FileCreateFixer {
            path: ".editorconfig",
            source: Inline(
                "root = true\n[*]\nend_of_line = lf\nindent_style = space\nindent_size = 2\n",
            ),
            create_parents: true,
        },
    ),
}

=== kind: file_exists | id: readme-exists ===
FileExistsRule {
    id: "readme-exists",
    level: Error,
    policy_url: Some(
        "https://example.com/policies/readme",
    ),
    message: Some(
        "README required",
    ),
    scope: Scope { ... },
    patterns: [
        "README.md",
    ],
    literal_paths: Some(
        [
            "README.md",
        ],
    ),
    root_only: true,
    git_tracked_only: false,
    fixer: None,
}

=== kind: file_footer | id: rust-final-line ===
FileFooterRule {
    id: "rust-final-line",
    level: Info,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    pattern_src: "}$",
    pattern: Regex(
        "}$",
    ),
    lines: 20,
    fixer: None,
}

=== kind: file_hash | id: rust-fixture-hash ===
FileHashRule {
    id: "rust-fixture-hash",
    level: Error,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    expected: [
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
    ],
}

=== kind: file_header | id: java-header ===
FileHeaderRule {
    id: "java-header",
    level: Error,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    pattern_src: "(?s)Copyright",
    pattern: Regex(
        "(?s)Copyright",
    ),
    lines: 20,
    fixer: Some(
        FilePrependFixer {
            source: Inline(
                "// Copyright (c) 2026 Acme Corp\n// SPDX-License-Identifier: Apache-2.0\n",
            ),
        },
    ),
}

=== kind: file_header | id: rust-spdx-header ===
FileHeaderRule {
    id: "rust-spdx-header",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    pattern_src: "^// SPDX-License-Identifier:",
    pattern: Regex(
        "^// SPDX-License-Identifier:",
    ),
    lines: 20,
    fixer: None,
}

=== kind: file_is_ascii | id: rust-must-be-ascii ===
FileIsAsciiRule {
    id: "rust-must-be-ascii",
    level: Info,
    policy_url: None,
    message: None,
    scope: Scope { ... },
}

=== kind: file_is_text | id: all-text ===
FileIsTextRule {
    id: "all-text",
    level: Error,
    policy_url: None,
    message: None,
    scope: Scope { ... },
}

=== kind: file_is_text | id: rust-must-be-text ===
FileIsTextRule {
    id: "rust-must-be-text",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
}

=== kind: file_max_lines | id: changelog-max-lines ===
FileMaxLinesRule {
    id: "changelog-max-lines",
    level: Info,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    max_lines: 10000,
}

=== kind: file_max_size | id: max-content-size ===
FileMaxSizeRule {
    id: "max-content-size",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    max_bytes: 10485760,
}

=== kind: file_max_size | id: max-size ===
FileMaxSizeRule {
    id: "max-size",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    max_bytes: 10485760,
}

=== kind: file_min_lines | id: readme-min-lines ===
FileMinLinesRule {
    id: "readme-min-lines",
    level: Info,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    min_lines: 5,
}

=== kind: file_min_size | id: readme-min-size ===
FileMinSizeRule {
    id: "readme-min-size",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    min_bytes: 200,
}

=== kind: file_shebang | id: scripts-have-shebang ===
FileShebangRule {
    id: "scripts-have-shebang",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    pattern_src: "^#!/(usr/)?bin/(env )?(ba)?sh",
    pattern: Regex(
        "^#!/(usr/)?bin/(env )?(ba)?sh",
    ),
}

=== kind: file_starts_with | id: rust-starts-with-spdx ===
FileStartsWithRule {
    id: "rust-starts-with-spdx",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    prefix: [
        47,
        47,
        32,
        83,
        80,
        68,
        88,
        45,
        76,
        105,
        99,
        101,
        110,
        115,
        101,
        45,
        73,
        100,
        101,
        110,
        116,
        105,
        102,
        105,
        101,
        114,
    ],
}

=== kind: filename_case | id: components-pascal ===
FilenameCaseRule {
    id: "components-pascal",
    level: Error,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    case: Pascal,
    fixer: Some(
        FileRenameFixer {
            case: Pascal,
        },
    ),
}

=== kind: filename_regex | id: tests-pattern ===
FilenameRegexRule {
    id: "tests-pattern",
    level: Error,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    pattern_src: "^test_[a-z0-9_]+$",
    pattern: Regex(
        "^^test_[a-z0-9_]+$$",
    ),
    stem: true,
}

=== kind: final_newline | id: rust-final-newline ===
FinalNewlineRule {
    id: "rust-final-newline",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    fixer: None,
}

=== kind: footer | id: footer-alias ===
FileFooterRule {
    id: "footer-alias",
    level: Info,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    pattern_src: "$",
    pattern: Regex(
        "$",
    ),
    lines: 20,
    fixer: None,
}

=== kind: for_each_dir | id: every-module-has-mod ===
ForEachDirRule {
    id: "every-module-has-mod",
    level: Error,
    policy_url: None,
    select_scope: Scope { ... },
    when_iter: None,
    require: [
        CompiledNestedSpec {
            spec: NestedRuleSpec {
                kind: "file_exists",
                paths: Some(
                    Single(
                        "{path}/mod.rs",
                    ),
                ),
                message: None,
                policy_url: None,
                when: None,
                scope_filter: None,
                extra: Mapping {},
            },
            when: None,
        },
    ],
}

=== kind: for_each_file | id: unit-has-snapshot ===
ForEachFileRule {
    id: "unit-has-snapshot",
    level: Warning,
    policy_url: None,
    select_scope: Scope { ... },
    when_iter: None,
    require: [
        CompiledNestedSpec {
            spec: NestedRuleSpec {
                kind: "file_exists",
                paths: Some(
                    Single(
                        "tests/snapshots/{stem}.snap",
                    ),
                ),
                message: None,
                policy_url: None,
                when: None,
                scope_filter: None,
                extra: Mapping {},
            },
            when: None,
        },
    ],
}

=== kind: git_blame_age | id: stale-todos ===
GitBlameAgeRule {
    id: "stale-todos",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    pattern: Regex(
        "\\b(TODO|FIXME)\\b",
    ),
    max_age: 15552000s,
}

=== kind: git_commit_message | id: conventional-commit ===
GitCommitMessageRule {
    id: "conventional-commit",
    level: Warning,
    policy_url: None,
    message_override: None,
    pattern: Some(
        Regex(
            "^(feat|fix|chore): ",
        ),
    ),
    subject_max_length: None,
    requires_body: false,
}

=== kind: git_no_denied_paths | id: no-tracked-secrets ===
GitNoDeniedPathsRule {
    id: "no-tracked-secrets",
    level: Error,
    policy_url: None,
    message: None,
    denied_set: GlobSet { ... },
    denied_src: [
        "*.env",
        "*.pem",
        "id_rsa",
    ],
}

=== kind: header | id: header-alias ===
FileHeaderRule {
    id: "header-alias",
    level: Info,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    pattern_src: "^# ",
    pattern: Regex(
        "^# ",
    ),
    lines: 20,
    fixer: None,
}

=== kind: indent_style | id: indent-style ===
IndentStyleRule {
    id: "indent-style",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    style: Spaces,
    width: Some(
        4,
    ),
}

=== kind: is_text | id: is-text-alias ===
FileIsTextRule {
    id: "is-text-alias",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
}

=== kind: json_path_equals | id: package-name-matches ===
StructuredPathRule {
    id: "package-name-matches",
    level: Error,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    literal_paths: Some(
        [
            "package.json",
        ],
    ),
    format: Json,
    path_expr: JsonPath(
        Query {
            kind: Root,
            segments: [
                QuerySegment {
                    kind: Child,
                    segment: DotName(
                        "name",
                    ),
                },
            ],
        },
    ),
    path_src: "$.name",
    op: Equals(
        String("demo"),
    ),
    if_present: false,
}

=== kind: json_path_matches | id: package-version-matches ===
StructuredPathRule {
    id: "package-version-matches",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    literal_paths: Some(
        [
            "package.json",
        ],
    ),
    format: Json,
    path_expr: JsonPath(
        Query {
            kind: Root,
            segments: [
                QuerySegment {
                    kind: Child,
                    segment: DotName(
                        "version",
                    ),
                },
            ],
        },
    ),
    path_src: "$.version",
    op: Matches(
        Regex(
            "^\\d+\\.\\d+\\.\\d+$",
        ),
    ),
    if_present: false,
}

=== kind: json_schema_passes | id: package-conforms-to-schema ===
JsonSchemaPassesRule {
    id: "package-conforms-to-schema",
    level: Error,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    schema_path: "schemas/package.schema.json",
    format_override: None,
    compiled: OnceLock(
        <uninit>,
    ),
}

=== kind: line_endings | id: line-endings-lf ===
LineEndingsRule {
    id: "line-endings-lf",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    target: Lf,
    fixer: None,
}

=== kind: line_max_width | id: line-max-width ===
LineMaxWidthRule {
    id: "line-max-width",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    max_width: 100,
}

=== kind: markdown_paths_resolve | id: agents-md-paths-resolve ===
MarkdownPathsResolveRule {
    id: "agents-md-paths-resolve",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    prefixes: [
        "src/",
        "crates/",
        "docs/",
    ],
    ignore_template_vars: true,
}

=== kind: max_consecutive_blank_lines | id: max-blank-lines ===
MaxConsecutiveBlankLinesRule {
    id: "max-blank-lines",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    max: 2,
    fixer: None,
}

=== kind: max_directory_depth | id: max-dir-depth ===
MaxDirectoryDepthRule {
    id: "max-dir-depth",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    max_depth: 12,
}

=== kind: max_files_per_directory | id: max-files-per-dir ===
MaxFilesPerDirectoryRule {
    id: "max-files-per-dir",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    max_files: 500,
}

=== kind: max_lines | id: max-lines-alias ===
FileMaxLinesRule {
    id: "max-lines-alias",
    level: Info,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    max_lines: 5000,
}

=== kind: max_size | id: max-size-alias ===
FileMaxSizeRule {
    id: "max-size-alias",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    max_bytes: 5242880,
}

=== kind: min_lines | id: min-lines-alias ===
FileMinLinesRule {
    id: "min-lines-alias",
    level: Info,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    min_lines: 3,
}

=== kind: min_size | id: min-size-alias ===
FileMinSizeRule {
    id: "min-size-alias",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    min_bytes: 100,
}

=== kind: no_bidi_controls | id: no-bidi-controls ===
NoBidiControlsRule {
    id: "no-bidi-controls",
    level: Error,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    fixer: None,
}

=== kind: no_bom | id: no-bom ===
NoBomRule {
    id: "no-bom",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    fixer: None,
}

=== kind: no_case_conflicts | id: no-case-conflicts ===
NoCaseConflictsRule {
    id: "no-case-conflicts",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
}

=== kind: no_empty_files | id: no-empty-files ===
NoEmptyFilesRule {
    id: "no-empty-files",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    fixer: None,
}

=== kind: no_illegal_windows_names | id: no-illegal-windows-names ===
NoIllegalWindowsNamesRule {
    id: "no-illegal-windows-names",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
}

=== kind: no_merge_conflict_markers | id: no-merge-conflict-markers ===
NoMergeConflictMarkersRule {
    id: "no-merge-conflict-markers",
    level: Error,
    policy_url: None,
    message: None,
    scope: Scope { ... },
}

=== kind: no_submodules | id: no-submodules ===
NoSubmodulesRule {
    id: "no-submodules",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    fixer: None,
}

=== kind: no_symlinks | id: no-symlinks ===
NoSymlinksRule {
    id: "no-symlinks",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    fixer: None,
}

=== kind: no_trailing_whitespace | id: no-trailing-ws ===
NoTrailingWhitespaceRule {
    id: "no-trailing-ws",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    fixer: None,
}

=== kind: no_zero_width_chars | id: no-zero-width ===
NoZeroWidthCharsRule {
    id: "no-zero-width",
    level: Error,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    fixer: None,
}

=== kind: pair | id: c-requires-h ===
PairRule {
    id: "c-requires-h",
    level: Error,
    policy_url: None,
    message: Some(
        "{{ctx.primary}} has no matching header at {{ctx.partner}}",
    ),
    primary_scope: Scope { ... },
    partner_template: "{dir}/{stem}.h",
}

=== kind: shebang | id: shebang-alias ===
FileShebangRule {
    id: "shebang-alias",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    pattern_src: "^#!/(usr/)?bin/(env )?python3?",
    pattern: Regex(
        "^#!/(usr/)?bin/(env )?python3?",
    ),
}

=== kind: shebang_has_executable | id: shebang-needs-exec ===
ShebangHasExecutableRule {
    id: "shebang-needs-exec",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
}

=== kind: toml_path_equals | id: cargo-edition-2024 ===
StructuredPathRule {
    id: "cargo-edition-2024",
    level: Error,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    literal_paths: Some(
        [
            "Cargo.toml",
        ],
    ),
    format: Toml,
    path_expr: JsonPath(
        Query {
            kind: Root,
            segments: [
                QuerySegment {
                    kind: Child,
                    segment: DotName(
                        "package",
                    ),
                },
                QuerySegment {
                    kind: Child,
                    segment: DotName(
                        "edition",
                    ),
                },
            ],
        },
    ),
    path_src: "$.package.edition",
    op: Equals(
        String("2024"),
    ),
    if_present: false,
}

=== kind: toml_path_matches | id: rust-version-floor ===
StructuredPathRule {
    id: "rust-version-floor",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    literal_paths: Some(
        [
            "Cargo.toml",
        ],
    ),
    format: Toml,
    path_expr: JsonPath(
        Query {
            kind: Root,
            segments: [
                QuerySegment {
                    kind: Child,
                    segment: DotName(
                        "package",
                    ),
                },
                QuerySegment {
                    kind: Child,
                    segment: LongHand(
                        [
                            Name(
                                Name(
                                    "rust-version",
                                ),
                            ),
                        ],
                    ),
                },
            ],
        },
    ),
    path_src: "$.package['rust-version']",
    op: Matches(
        Regex(
            "^1\\.\\d+$",
        ),
    ),
    if_present: true,
}

=== kind: unique_by | id: unique-rs-stems ===
UniqueByRule {
    id: "unique-rs-stems",
    level: Warning,
    policy_url: None,
    message: Some(
        "{{ctx.count}} files share stem {{ctx.key}}: {{ctx.paths}}",
    ),
    select_scope: Scope { ... },
    key_template: "{stem}",
}

=== kind: yaml_path_equals | id: workflow-uses-checkout ===
StructuredPathRule {
    id: "workflow-uses-checkout",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    literal_paths: None,
    format: Yaml,
    path_expr: JsonPath(
        Query {
            kind: Root,
            segments: [
                QuerySegment {
                    kind: Child,
                    segment: DotName(
                        "jobs",
                    ),
                },
                QuerySegment {
                    kind: Child,
                    segment: DotName(
                        "build",
                    ),
                },
                QuerySegment {
                    kind: Child,
                    segment: DotName(
                        "steps",
                    ),
                },
                QuerySegment {
                    kind: Child,
                    segment: LongHand(
                        [
                            Index(
                                Index(
                                    Integer(
                                        0,
                                    ),
                                ),
                            ),
                        ],
                    ),
                },
                QuerySegment {
                    kind: Child,
                    segment: DotName(
                        "uses",
                    ),
                },
            ],
        },
    ),
    path_src: "$.jobs.build.steps[0].uses",
    op: Equals(
        String("actions/checkout@v4"),
    ),
    if_present: true,
}

=== kind: yaml_path_matches | id: workflow-permissions-shape ===
StructuredPathRule {
    id: "workflow-permissions-shape",
    level: Warning,
    policy_url: None,
    message: None,
    scope: Scope { ... },
    literal_paths: None,
    format: Yaml,
    path_expr: JsonPath(
        Query {
            kind: Root,
            segments: [
                QuerySegment {
                    kind: Child,
                    segment: DotName(
                        "permissions",
                    ),
                },
                QuerySegment {
                    kind: Child,
                    segment: LongHand(
                        [
                            Name(
                                Name(
                                    "contents",
                                ),
                            ),
                        ],
                    ),
                },
            ],
        },
    ),
    path_src: "$.permissions['contents']",
    op: Matches(
        Regex(
            "^read$",
        ),
    ),
    if_present: true,
}

