moonkeyguard

    MoonBit-native keyboard shortcut conflict, context, platform, accessibility, and CI analysis toolkit.

    keymap
    keyboard
    shortcut
    static-analysis
    accessibility
    ci
    Download zip
    Version
    0.2.0
    License
    Apache-2.0
    Last updated
    7 days ago
    Downloads
    7

    #MoonKeyguard

    MoonKeyguard 是一个 MoonBit 原生的键盘快捷键静态分析工具包。它把应用的快捷键声明看作一份可审查的策略文件,在不启动 GUI、不依赖操作系统钩子的情况下,发现快捷键冲突、Chord 前缀歧义、上下文继承遮蔽、平台范围重叠、保留快捷键和键盘可访问性风险,并生成可供 CI、代码审查和发布流程使用的报告。

    项目与 8 月项目 MoonBVHKit 完全独立:没有复用 BVH 代码、数据模型或实现范围,也不是拆分、改名或包装旧仓库。MoonKeyguard 的用户是桌面应用、终端工具、编辑器、TUI 和多平台 GUI 的维护者,解决的是“按键声明在合并后是否仍然可达、可发现、可解释”的工程问题。

    #核心价值

    • 用轻量 DSL 表达 bindcontextreservekeymap 声明,代码审查可以直接看到每一条快捷键变更。
    • Ctrl+KCtrl+K,Ctrl+L 这类序列做前缀分析,区分同一上下文、父子上下文和互斥兄弟上下文。
    • allwindowsmaclinux 等平台集合进行重叠计算,避免“平台专用快捷键”被全局 fallback 抢走。
    • 提供保守的系统/终端/焦点导航保留目录,并保留来源说明;团队可以传入自己的 ReservedRule 目录。
    • 输出文本、Markdown、JSON、SARIF 2.1.0、冲突图、迁移 diff、推荐修复和发布门禁。
    • 核心 API 是纯函数式的:分析不会修改调用者持有的数组,结果对相同输入稳定,可用于离线 CI 和 wasm。

    #当前边界

    MoonKeyguard 是声明分析库和 dispatcher 模拟器,不是操作系统级按键 hook、GUI 按键录制器或窗口管理器。它不读取/修改用户的桌面配置,也不会替应用决定最终的人机交互设计。CLI 默认审计仓库内置的演示 keymap;在应用、脚本或 CI 中通过 parse_keymap 传入真实内容。

    #环境

    • MoonBit 0.10.10 或更新版本(本地验收使用 moon 0.1.20260824 / moonc 0.10.10)。
    • 本项目只使用 moonbitlang/core,没有额外运行时依赖。

    #快速开始

    git clone https://github.com/zhangbowen2006/MoonKeyguard.git cd MoonKeyguard moon check --deny-warn moon test --deny-warn moon run cmd/main

    CLI 格式和附加报告:

    moon run cmd/main -- --format json moon run cmd/main -- --format markdown --suggest moon run cmd/main -- --format sarif --fail-on-warning moon run cmd/main -- --metrics moon run cmd/main -- --source "bind save command=save keys=Ctrl+S" --name quick-demo

    --source accepts a small inline keymap for shell smoke tests and demos. For larger files, call parse_keymap from MoonBit and pass the resulting keymap to analyze; this keeps file-system policy in the host application. When --fail-on-warning is supplied, the CLI exits with status 1 for any error or warning so it can be used as a release gate.

    #DSL 示例

    keymap name=editor version=1 context global parent= rank=0 description=all-windows context editor parent=global rank=10 description=text-editor reserve Cmd+Q platform=mac bind save command=editor.save keys=Ctrl+S context=editor platform=all priority=10 description=save-buffer bind jump_line command=editor.jump_line keys=Ctrl+K,Ctrl+L context=editor platform=all priority=5 description=jump-line

    keys 使用 + 表示一个 chord,使用逗号表示连续 chord。context 未填写时为 globalplatform 未填写时为 allpriority 越高,dispatcher 越优先选择。字段值使用无空格的 token,描述可以使用短横线或下划线。

    #MoonBit API

    let parsed = @moonkeyguard.parse_keymap(source, name="editor")
    if !parsed.ok {
    println(@moonkeyguard.parse_diagnostics_to_json(parsed.diagnostics))
    }
    let analysis = @moonkeyguard.analyze(parsed.keymap)
    println(@moonkeyguard.analysis_to_markdown(analysis))
    let suggestions = @moonkeyguard.suggest_all(parsed.keymap, analysis)
    println(@moonkeyguard.suggestions_to_markdown(suggestions))

    主要入口:

    API用途
    parse_keys / canonical_keys解析并规范化快捷键序列
    parse_keymap解析 DSL,返回结构化 parser diagnostics
    analyze / audit运行冲突、上下文、平台、保留键和可访问性规则
    suggest_for / suggest_all生成不占用保留键的替换建议
    analysis_to_text/json/markdown/sarif生成终端、文档、机器和 GitHub 代码扫描报告
    build_conflict_graph计算冲突边、连通分量和 hotspot
    diff_keymaps / migration_plan对两个版本做按 id 的语义 diff
    reachability_matrix / reachability_to_*按 context/platform 证明绑定可达、遮蔽和不可用状态
    compare_baseline / baseline_report_to_*只阻止新增风险,保留历史问题作为可追踪债务

    #Reachability matrix

    冲突分析回答“声明是否可能重叠”,而可达性矩阵回答“在真实的 context/platform 组合中谁会被 dispatcher 选中”。

    let report = @moonkeyguard.reachability_matrix(
    parsed.keymap,
    contexts=["global", "editor"],
    platforms=["all", "mac"],
    )
    println(@moonkeyguard.reachability_to_markdown(report))

    探针数组为空时自动使用 keymap 中声明的 context 和 all 平台;输入会去重、规范化并排序,适合把 JSON 结果作为 CI artifact。子 context 的绑定不会反向泄漏到父 context。

    #Baseline regression gate

    Teams that already have accepted findings can ratchet quality without hiding old debt. Compare two deterministic analyses and fail only when a new error is introduced:

    let baseline = @moonkeyguard.analyze(@moonkeyguard.parse_keymap(old_source).keymap)
    let current = @moonkeyguard.analyze(@moonkeyguard.parse_keymap(new_source).keymap)
    let report = @moonkeyguard.compare_baseline(baseline, current)
    println(@moonkeyguard.baseline_report_to_markdown(report))

    Finding identities omit source line numbers, so moving a declaration does not create a false regression. Set fail_on_warning=true when warnings are also blocking for a release. | import_csv / import_tsv / import_pipe | 导入常见表格或管道格式 | | dispatch / replay | 在纯 MoonBit 模拟器中检查解析结果的可达性 | | audit_with_profile | 应用 desktop、terminal、accessible 或自定义策略 | | release_gate | 汇总结构校验、冲突分析、策略、基准和迁移证据 |

    #可运行示例

    moon run examples/basic

    示例会解析一个 editor/terminal keymap,输出冲突摘要、冲突图热点、dispatcher 回放和建议修复。examples/basic/main.mbt 只依赖公开 API,可以直接复制为集成测试的起点。

    #报告与 CI

    仓库中的 .github/workflows/ci.yml 会在 push、pull request 和手动触发时执行:

    moon check --deny-warn moon build moon test --deny-warn moon fmt --check moon info

    同时运行 CLI、basic example,并检查 pkg.generated.mbti 没有未提交变化。SARIF 输出可以作为 GitHub Code Scanning 的上传输入;项目本身不上传任何键盘记录或用户数据。

    #测试

    当前测试覆盖:

    • 修饰键别名、非法 chord、空输入和连续 chord;
    • parser 的未知 directive、重复 context、保留键和禁用记录;
    • 精确冲突、同命令重复、前缀冲突、父子/兄弟 context 和平台集合;
    • reserved catalog、Accessibility 风险、策略 profile 和自定义项目规则;
    • CSV/TSV/pipe 适配、DSL round-trip、keymap merge 和语义 diff;
    • conflict graph、dispatcher/replay、audit timeline、release gate 和 benchmark;
    • text/Markdown/JSON/SARIF/schema 输出的稳定字段。

    本地运行:

    moon test --deny-warn

    #性能与可扩展性

    当前实现优先保证可解释性和 wasm 可移植性:解析约为 O(lines × attributes),分析约为 O(bindings² + bindings × context-depth),dispatcher 约为 O(bindings × context-depth)complexity_reportrun_benchmark 用于把规模、回归和未来索引优化记录在版本历史中。项目边界明确保留了操作系统 hook 和 GUI 录制功能,避免把静态分析器扩成不可维护的桌面框架。

    #许可证与来源

    源代码采用 Apache-2.0,见 LICENSE。运行时没有复制第三方实现;仅使用 MoonBit 官方 moonbitlang/core。保留快捷键目录中的平台说明和来源链接是政策解释材料,不是从平台代码中移植的实现。更完整的来源记录见 THIRD_PARTY_NOTICES.md

    #AI 使用说明

    开发过程中使用 AI 辅助生成了部分初稿、测试用例和文档草稿,所有内容均由项目维护者在本地 MoonBit 工具链中审阅、修改并通过测试。没有引入来源不明的代码、素材、用户数据或未授权模型输出;AI 不替代许可证审查、测试和发布决定。详见 AI_USAGE.md

    #维护与发布

    • 变更应保持一个有意义的提交一个主题,保留真实 Git 提交、Issue、PR、测试和发布记录。
    • 发布前运行 moon package --list,确认包中没有 _build、临时文件或敏感数据。
    • 只有真实执行 moon publish --frozen 并拿到 Mooncakes 页面后,才在申报材料中填写发布链接;当前仓库尚未声称已发布。
    • 发布流程、验收证据和风险记录见 docs/submission/

    #查重结论(截至 2026-09-13)

    已检索 GitHub 近期 MoonBit 仓库和 Mooncakes API。mooneditproton_global_hotkey 等提供运行时编辑器/桌面按键支持;它们不提供静态 keymap 冲突图、context 继承分析、保留键策略、SARIF/迁移门禁组合。查重范围、检索关键词、排除项和独立价值记录在 docs/DEDUPLICATION.md。这不是“改名避重”:MoonKeyguard 的核心数据模型、规则和测试均为本项目重新设计。

    Analysis

    pub(all) struct Analysis {
    keymap_name : String
    findings : Array[Finding]
    checked_bindings : Int
    enabled_bindings : Int
    error_count : Int
    warning_count : Int
    info_count : Int
    score : Int
    fingerprint : String
    } derive(Eq,
    Debug
    )

    A complete deterministic analysis result.

    Analysis::count_kind

    fn Analysis::count_kind(self : Analysis, kind : IssueKind) -> Int

    Count findings of a particular kind.

    Analysis::ok

    fn Analysis::ok(self : Analysis) -> Bool

    True when the analysis has no error-level findings.

    Analysis::summary

    fn Analysis::summary(self : Analysis) -> String

    Return a compact summary intended for CI logs.

    AuditTimeline

    pub(all) struct AuditTimeline {
    project : String
    events : Array[TimelineEvent]
    baseline : String
    } derive(Eq,
    Debug
    )

    AuditTimeline::new

    fn AuditTimeline::new(project : String, baseline? : String) -> AuditTimeline

    BaselineReport

    pub(all) struct BaselineReport {
    baseline_fingerprint : String
    current_fingerprint : String
    baseline_count : Int
    current_count : Int
    new_findings : Array[Finding]
    resolved_findings : Array[Finding]
    retained_count : Int
    new_error_count : Int
    new_warning_count : Int
    new_info_count : Int
    fail_on_warning : Bool
    passed : Bool
    } derive(Eq,
    Debug
    )

    A differential report for CI baseline checks.

    Existing findings are retained as debt, while only newly introduced findings affect the default gate. Finding identities deliberately omit line and source so that moving a declaration does not look like a new defect.

    BaselineReport::summary

    fn BaselineReport::summary(self : BaselineReport) -> String

    Return a concise baseline summary for CI logs.

    BenchmarkCase

    pub(all) struct BenchmarkCase {
    name : String
    inputs : Array[String]
    context : String
    platform : String
    expected_status : DispatchStatus
    repetitions : Int
    } derive(Eq,
    Debug
    )

    Portable benchmark and regression fixtures without wall-clock dependence.

    BenchmarkResult

    pub(all) struct BenchmarkResult {
    name : String
    operations : Int
    matched : Int
    prefixes : Int
    misses : Int
    mismatches : Int
    score : Int
    notes : Array[String]
    } derive(Eq,
    Debug
    )

    Binding

    pub(all) struct Binding {
    id : String
    command : String
    keys : KeySequence
    context : String
    platform : String
    source : String
    line : Int
    priority : Int
    enabled : Bool
    description : String
    } derive(Eq,
    Debug
    )

    A single shortcut declaration from a keymap file.

    Binding::label

    fn Binding::label(self : Binding) -> String

    Return the stable identifier used in reports.

    Binding::new

    fn Binding::new(id : String, command : String, keys : KeySequence, context? : String, platform? : String, source? : String, line? : Int, priority? : Int, enabled? : Bool, description? : String) -> Binding

    Construct a binding with sensible defaults for programmatic callers.

    BindingChange

    pub(all) struct BindingChange {
    kind : ChangeKind
    id : String
    before : Binding?
    after : Binding?
    summary : String
    risk : Severity
    } derive(Eq,
    Debug
    )

    BindingQuery

    pub(all) struct BindingQuery {
    binding : Binding
    context_distance : Int
    platform_match : Bool
    command_match : Bool
    } derive(Eq,
    Debug
    )

    Query, projection, and deterministic serialization helpers.

    BindingRow

    pub(all) struct BindingRow {
    id : String
    command : String
    keys : String
    context : String
    platform : String
    priority : String
    enabled : String
    description : String
    } derive(Eq,
    Debug
    )

    Dependency-free tabular adapters for importing keymaps from CI artifacts.

    CatalogReport

    pub(all) struct CatalogReport {
    keymap : Keymap
    matched : Array[ReservedRule]
    unmatched : Array[ReservedRule]
    findings : Array[Finding]
    } derive(Eq,
    Debug
    )

    ChangeKind

    pub(all) enum ChangeKind {
    Added
    Removed
    Modified
    Unchanged
    } derive(Eq,
    Debug
    )

    Semantic keymap diffing for review and migration planning.

    ComplexityReport

    pub(all) struct ComplexityReport {
    bindings : Int
    contexts : Int
    findings : Int
    parse_complexity : String
    analysis_complexity : String
    dispatch_complexity : String
    memory_notes : Array[String]
    } derive(Eq,
    Debug
    )

    ConflictEdge

    pub(all) struct ConflictEdge {
    left : String
    right : String
    code : String
    severity : Severity
    weight : Int
    } derive(Eq,
    Debug
    )

    Conflict graph utilities for finding keymap hotspots.

    ConflictGraph

    pub(all) struct ConflictGraph {
    nodes : Array[ConflictNode]
    edges : Array[ConflictEdge]
    components : Array[Array[String]]
    } derive(Eq,
    Debug
    )

    ConflictNode

    pub(all) struct ConflictNode {
    id : String
    command : String
    degree : Int
    error_degree : Int
    warning_degree : Int
    info_degree : Int
    } derive(Eq,
    Debug
    )

    Context

    pub(all) struct Context {
    name : String
    parent : String
    rank : Int
    description : String
    } derive(Eq,
    Debug
    )

    A context declaration. Contexts form a small inheritance tree used when deciding whether one binding shadows another.

    DispatchResult

    pub(all) struct DispatchResult {
    status : DispatchStatus
    input : String
    canonical : String
    command : String
    binding_ids : Array[String]
    context : String
    platform : String
    message : String
    } derive(Eq,
    Debug
    )

    DispatchStatus

    pub(all) enum DispatchStatus {
    Matched
    Prefix
    NoMatch
    Ambiguous
    Disabled
    Invalid
    } derive(Eq,
    Debug
    )

    A small deterministic dispatcher simulation used to validate analyzer assumptions without depending on a GUI or operating-system backend.

    DispatchStep

    pub(all) struct DispatchStep {
    input : String
    result : DispatchResult
    elapsed_ms : Int
    } derive(Eq,
    Debug
    )

    DispatchTrace

    pub(all) struct DispatchTrace {
    context : String
    platform : String
    steps : Array[DispatchStep]
    matched_count : Int
    prefix_count : Int
    no_match_count : Int
    } derive(Eq,
    Debug
    )

    Effort

    pub(all) enum Effort {
    Small
    Medium
    Large
    } derive(Eq,
    Debug
    )

    Human-oriented recommendations derived from machine findings.

    FieldSpec

    pub(all) struct FieldSpec {
    name : String
    required : Bool
    description : String
    example : String
    } derive(Eq,
    Debug
    )

    Machine-readable schema and support matrix for integrations.

    Finding

    pub(all) struct Finding {
    code : String
    kind : IssueKind
    severity : Severity
    message : String
    primary_id : String
    secondary_id : String
    shortcut : String
    context : String
    source : String
    line : Int
    suggestion : String
    } derive(Eq,
    Debug
    )

    A finding emitted by the analyzer.

    Finding::to_line

    fn Finding::to_line(self : Finding) -> String

    Convert a finding into a compact human-readable line.

    GateItem

    pub(all) struct GateItem {
    code : String
    title : String
    passed : Bool
    severity : Severity
    evidence : String
    remediation : String
    } derive(Eq,
    Debug
    )

    Release governance helpers keep the engineering evidence reviewable.

    ImportReport

    pub(all) struct ImportReport {
    keymap : Keymap
    rows_seen : Int
    rows_imported : Int
    diagnostics : Array[ParseDiagnostic]
    } derive(Eq,
    Debug
    )

    IssueKind

    pub(all) enum IssueKind {
    ExactConflict
    PrefixConflict
    ShadowedBinding
    DuplicateCommand
    ReservedShortcut
    AccessibilityRisk
    InvalidKey
    InvalidContext
    InvalidRecord
    DisabledBinding
    PlatformOverlap
    } derive(Eq,
    Debug
    )

    The family of rule that produced a finding.

    IssueKind::name

    fn IssueKind::name(self : IssueKind) -> String

    Return the issue kind as a stable kebab-case code.

    KeySequence

    pub(all) struct KeySequence {
    raw : String
    steps : Array[String]
    canonical : String
    has_modifier : Bool
    modifier_count : Int
    key_count : Int
    } derive(Eq,
    Debug
    )

    A normalized keyboard sequence. The textual form is stable and suitable for reports, while steps keeps each chord available to library consumers.

    KeySequence::new

    fn KeySequence::new(raw : String, steps : Array[String], canonical : String, has_modifier : Bool, modifier_count : Int) -> KeySequence

    Construct a normalized sequence value.

    Keymap

    pub(all) struct Keymap {
    name : String
    version : String
    bindings : Array[Binding]
    contexts : Array[Context]
    reserved : Array[String]
    } derive(Eq,
    Debug
    )

    All data needed to analyze one keymap.

    Keymap::empty

    fn Keymap::empty(name? : String) -> Keymap

    Construct an empty keymap.

    KeymapDiff

    pub(all) struct KeymapDiff {
    from_name : String
    to_name : String
    changes : Array[BindingChange]
    added : Int
    removed : Int
    modified : Int
    unchanged : Int
    context_added : Int
    context_removed : Int
    reserved_added : Int
    reserved_removed : Int
    } derive(Eq,
    Debug
    )

    KeymapMetrics

    pub(all) struct KeymapMetrics {
    binding_count : Int
    enabled_count : Int
    context_count : Int
    platform_count : Int
    command_count : Int
    max_chord_length : Int
    average_chord_length : Int
    modifierless_count : Int
    documented_count : Int
    duplicate_command_count : Int
    density_score : Int
    } derive(Eq,
    Debug
    )

    Keymap metrics used to track maintainability over time.

    KeymapSchema

    pub(all) struct KeymapSchema {
    version : String
    directives : Array[String]
    fields : Array[FieldSpec]
    formats : Array[String]
    guarantees : Array[String]
    } derive(Eq,
    Debug
    )

    KeymapSelection

    pub(all) struct KeymapSelection {
    name : String
    bindings : Array[Binding]
    contexts : Array[Context]
    query : String
    } derive(Eq,
    Debug
    )

    MergeResult

    pub(all) struct MergeResult {
    keymap : Keymap
    conflicts : Array[String]
    adopted : Int
    skipped : Int
    } derive(Eq,
    Debug
    )

    ParseDiagnostic

    pub(all) struct ParseDiagnostic {
    line : Int
    code : String
    message : String
    source : String
    } derive(Eq,
    Debug
    )

    Parse diagnostics are kept separate from policy findings.

    ParseResult

    pub(all) struct ParseResult {
    keymap : Keymap
    diagnostics : Array[ParseDiagnostic]
    ok : Bool
    } derive(Eq,
    Debug
    )

    Result returned by the line-oriented keymap parser.

    PolicyProfile

    pub(all) struct PolicyProfile {
    name : String
    reserved : Array[String]
    max_chord_length : Int
    max_modifier_count : Int
    require_description : Bool
    allow_disabled : Bool
    fail_on_warning : Bool
    allowed_platforms : Array[String]
    } derive(Eq,
    Debug
    )

    Named policy profiles turn the analyzer into a repeatable CI gate.

    ProfileReport

    pub(all) struct ProfileReport {
    profile : PolicyProfile
    parse : ParseResult
    analysis : Analysis
    metrics : KeymapMetrics
    passed : Bool
    gate_messages : Array[String]
    } derive(Eq,
    Debug
    )

    ProjectRules

    pub(all) struct ProjectRules {
    command_prefix : String
    required_contexts : Array[String]
    allowed_platforms : Array[String]
    max_bindings_per_context : Int
    require_modifier : Bool
    require_description : Bool
    fail_on_info : Bool
    } derive(Eq,
    Debug
    )

    Extensible project rules for teams that need conventions beyond built-ins.

    ProjectRules::default

    fn ProjectRules::default() -> ProjectRules

    ReachabilityCell

    pub(all) struct ReachabilityCell {
    binding_id : String
    context : String
    platform : String
    status : ReachabilityStatus
    selected_id : String
    message : String
    } derive(Eq,
    Debug
    )

    ReachabilityReport

    pub(all) struct ReachabilityReport {
    keymap_name : String
    contexts : Array[String]
    platforms : Array[String]
    cells : Array[ReachabilityCell]
    binding_count : Int
    reachable_count : Int
    shadowed_count : Int
    ambiguous_count : Int
    unavailable_count : Int
    disabled_count : Int
    } derive(Eq,
    Debug
    )

    ReachabilityReport::summary

    fn ReachabilityReport::summary(self : ReachabilityReport) -> String

    ReachabilityStatus

    pub(all) enum ReachabilityStatus {
    Reachable
    Shadowed
    Ambiguous
    Unavailable
    Disabled
    } derive(Eq,
    Debug
    )

    A deterministic context/platform probe matrix for shortcut reachability.

    Conflict reports explain that two declarations overlap; this report answers the complementary release question: for a concrete context and platform, which binding actually wins, and which declarations are never selected?

    Recommendation

    pub(all) struct Recommendation {
    code : String
    title : String
    priority : Int
    severity : Severity
    effort : Effort
    affected_ids : Array[String]
    rationale : String
    action : String
    } derive(Eq,
    Debug
    )

    ReleaseGate

    pub(all) struct ReleaseGate {
    project : String
    version : String
    items : Array[GateItem]
    passed : Bool
    score : Int
    } derive(Eq,
    Debug
    )

    ReleaseInput

    pub(all) struct ReleaseInput {
    keymap : Keymap
    analysis : Analysis
    validation : ValidationReport
    profile : ProfileReport?
    benchmark : Array[BenchmarkResult]
    diff : KeymapDiff?
    } derive(Eq,
    Debug
    )

    ReservedRule

    pub(all) struct ReservedRule {
    platform : String
    shortcut : String
    rationale : String
    source : String
    severity : Severity
    } derive(Eq,
    Debug
    )

    Curated reservation catalog with provenance-friendly explanations.

    RuleReport

    pub(all) struct RuleReport {
    rules : ProjectRules
    findings : Array[Finding]
    passed : Bool
    } derive(Eq,
    Debug
    )

    Severity

    pub(all) enum Severity {
    Info
    Warning
    Error
    } derive(Eq,
    Debug
    )

    A severity attached to an analysis finding.

    Severity::name

    fn Severity::name(self : Severity) -> String

    Return the issue severity as a machine-readable string.

    StructuralIssue

    pub(all) struct StructuralIssue {
    kind : StructuralKind
    code : String
    message : String
    id : String
    line : Int
    severity : Severity
    } derive(Eq,
    Debug
    )

    StructuralKind

    pub(all) enum StructuralKind {
    MissingRootContext
    DuplicateId
    EmptyId
    EmptyCommand
    InvalidIdentifier
    MissingParent
    ContextCycle
    NegativeRank
    InvalidPlatform
    InvalidReservedMarker
    InvalidShortcut
    EmptyDescription
    } derive(Eq,
    Debug
    )

    Structural validation runs before policy analysis and gives precise repair locations for malformed keymaps.

    Suggestion

    pub(all) struct Suggestion {
    binding_id : String
    command : String
    current : String
    replacement : String
    reason : String
    confidence : Int
    } derive(Eq,
    Debug
    )

    A candidate replacement suggested for a problematic binding.

    TimelineDelta

    pub(all) struct TimelineDelta {
    previous : TimelineEvent?
    current : TimelineEvent
    score_delta : Int
    errors_delta : Int
    warnings_delta : Int
    regressed : Bool
    } derive(Eq,
    Debug
    )

    TimelineEvent

    pub(all) struct TimelineEvent {
    sequence : Int
    label : String
    actor : String
    kind : TimelineEventKind
    fingerprint : String
    errors : Int
    warnings : Int
    score : Int
    note : String
    } derive(Eq,
    Debug
    )

    TimelineEventKind

    pub(all) enum TimelineEventKind {
    Imported
    Analyzed
    Approved
    Rejected
    Migrated
    } derive(Eq,
    Debug
    )

    Append-only audit timeline for tracking keymap evolution in CI.

    ValidationReport

    pub(all) struct ValidationReport {
    keymap_name : String
    issues : Array[StructuralIssue]
    error_count : Int
    warning_count : Int
    valid : Bool
    } derive(Eq,
    Debug
    )

    accessible_profile

    fn accessible_profile() -> PolicyProfile

    A profile for user-facing tools that prioritizes discoverability.

    active_bindings

    fn active_bindings(keymap : Keymap, context : String, platform : String) -> Array[BindingQuery]

    Resolve bindings active in a context. Parent declarations come first so a caller can apply child-priority rules while streaming the result.

    analysis_exit_code

    fn analysis_exit_code(analysis : Analysis, fail_on_warning? : Bool) -> Int

    Return a conventional process exit code for a CI gate.

    analysis_to_json

    fn analysis_to_json(analysis : Analysis) -> String

    Serialize an analysis without relying on a third-party JSON package.

    analysis_to_markdown

    fn analysis_to_markdown(analysis : Analysis) -> String

    Render a concise Markdown table for documentation and release notes.

    analysis_to_sarif

    fn analysis_to_sarif(analysis : Analysis) -> String

    SARIF 2.1.0 output lets GitHub annotate keymap files in CI.

    analysis_to_text

    fn analysis_to_text(analysis : Analysis) -> String

    Human-readable report suitable for a pull request comment.

    analyze

    fn analyze(keymap : Keymap) -> Analysis

    Analyze declarations using all built-in rules.

    analyze_with_rules

    fn analyze_with_rules(keymap : Keymap, rules : ProjectRules) -> Analysis

    Combine built-in analysis with project rules while preserving evidence.

    apply_keymap_diff

    fn apply_keymap_diff(base : Keymap, target : Keymap, include_removed? : Bool) -> Keymap

    Apply a diff's additions and modifications to a base keymap.

    apply_reserved_catalog

    fn apply_reserved_catalog(keymap : Keymap, rules : Array[ReservedRule]) -> Keymap

    Add the catalog to a keymap's reserved markers without introducing dupes.

    audit

    fn audit(source : String, name? : String) -> (ParseResult, Analysis)

    Parse and analyze in one call for CLI and integrations.

    audit_with_catalog

    fn audit_with_catalog(keymap : Keymap, rules : Array[ReservedRule]) -> CatalogReport

    Audit against an explicit reservation catalog and preserve matched rules.

    audit_with_named_profile

    fn audit_with_named_profile(source : String, name : String, profile_name : String) -> ProfileReport

    Convenience overload using a built-in profile.

    audit_with_profile

    fn audit_with_profile(source : String, name : String, profile : PolicyProfile) -> ProfileReport

    Analyze one source document with a named policy profile.

    baseline_report_to_json

    fn baseline_report_to_json(report : BaselineReport) -> String

    Serialize a baseline result for CI artifacts.

    baseline_report_to_markdown

    fn baseline_report_to_markdown(report : BaselineReport) -> String

    Render a baseline report as Markdown suitable for a pull request comment.

    behavioral_changes

    fn behavioral_changes(diff : KeymapDiff) -> Array[BindingChange]

    Return only changes that may alter runtime behavior.

    benchmark_case

    fn benchmark_case(name : String, inputs : Array[String], context? : String, platform? : String, expected_status? : DispatchStatus, repetitions? : Int) -> BenchmarkCase

    benchmark_result_to_json

    fn benchmark_result_to_json(result : BenchmarkResult) -> String

    benchmark_results_to_markdown

    fn benchmark_results_to_markdown(results : Array[BenchmarkResult]) -> String

    benchmark_suite

    fn benchmark_suite(keymap : Keymap, fixtures : Array[BenchmarkCase]) -> Array[BenchmarkResult]

    build_conflict_graph

    fn build_conflict_graph(keymap : Keymap, analysis : Analysis) -> ConflictGraph

    Build a graph from findings, retaining isolated bindings as nodes.

    canonical_keys

    fn canonical_keys(raw : String) -> String

    Normalize a key sequence for comparisons. Invalid input returns an empty string, which makes it safe to use in diagnostics without throwing.

    catalog_report_to_markdown

    fn catalog_report_to_markdown(report : CatalogReport) -> String

    catalog_to_json

    fn catalog_to_json(rules : Array[ReservedRule]) -> String

    clean_demo_source

    fn clean_demo_source() -> String

    A clean sample useful for embedding in a smoke test.

    compare_baseline

    fn compare_baseline(baseline : Analysis, current : Analysis, fail_on_warning? : Bool) -> BaselineReport

    Compare a current analysis with an accepted baseline.

    By default this is a ratchet: old findings remain visible but do not block a release, while any new error blocks it. Set fail_on_warning when a team wants warnings to be part of its release policy as well.

    complexity_report

    fn complexity_report(keymap : Keymap, analysis : Analysis) -> ComplexityReport

    Explain the current implementation's asymptotic behavior so it can be tracked when a future indexed implementation is introduced.

    complexity_to_markdown

    fn complexity_to_markdown(report : ComplexityReport) -> String

    conflict_component

    fn conflict_component(graph : ConflictGraph, id : String) -> Array[String]

    Return the component containing an id.

    conflict_graph_to_json

    fn conflict_graph_to_json(graph : ConflictGraph) -> String

    conflict_graph_to_markdown

    fn conflict_graph_to_markdown(graph : ConflictGraph, limit? : Int) -> String

    conflict_hotspots

    fn conflict_hotspots(graph : ConflictGraph, limit? : Int) -> Array[ConflictNode]

    Return nodes ranked by conflict degree, with stable id tie-breaking.

    default_reserved_rules

    fn default_reserved_rules() -> Array[ReservedRule]

    The catalog is intentionally conservative: it flags well-known system controls, but the profile can always be customized for a product shell.

    demo_analysis

    fn demo_analysis() -> Analysis

    Run the full sample audit.

    demo_keymap

    fn demo_keymap() -> Keymap

    Build a sample keymap directly, avoiding a parser round trip for embedding.

    demo_source

    fn demo_source() -> String

    The sample intentionally contains one exact conflict, one chord-prefix warning, one reserved shortcut, and one disabled entry.

    desktop_profile

    fn desktop_profile() -> PolicyProfile

    Sensible cross-platform defaults for desktop applications.

    diff_keymaps

    fn diff_keymaps(before : Keymap, after : Keymap) -> KeymapDiff

    Compare declarations by id and retain unchanged entries for auditability.

    dispatch

    fn dispatch(keymap : Keymap, raw : String, context? : String, platform? : String) -> DispatchResult

    Resolve one complete or partial sequence.

    dispatch_result_to_json

    fn dispatch_result_to_json(result : DispatchResult) -> String

    dispatch_trace_to_markdown

    fn dispatch_trace_to_markdown(trace : DispatchTrace) -> String

    evaluate_project_rules

    fn evaluate_project_rules(keymap : Keymap, rules : ProjectRules) -> RuleReport

    Apply project-specific naming, scope, density, and documentation rules.

    explain_reserved

    fn explain_reserved(binding : Binding, rules : Array[ReservedRule]) -> Array[ReservedRule]

    Find catalog rules that explain why a binding is reserved.

    export_csv

    fn export_csv(keymap : Keymap) -> String

    Export a keymap using a stable, documented column order.

    find_binding

    fn find_binding(keymap : Keymap, id : String) -> Binding?

    Look up one binding by its stable id.

    find_command

    fn find_command(keymap : Keymap, command : String) -> Array[Binding]

    Return all bindings belonging to a command, retaining declaration order.

    health_recommendations

    fn health_recommendations(keymap : Keymap, analysis : Analysis) -> Array[Recommendation]

    Add maintainability advice even when no conflict exists.

    import_csv

    fn import_csv(source : String, name? : String) -> ImportReport

    Import the stable CSV schema emitted by export_csv.

    import_pipe

    fn import_pipe(source : String, name? : String) -> ImportReport

    Import a deliberately small VS Code-style line format: command | key | when | platform.

    import_report_to_text

    fn import_report_to_text(report : ImportReport) -> String

    import_rows

    fn import_rows(rows : Array[BindingRow], name? : String) -> ImportReport

    Construct a keymap from rows and preserve row-level diagnostics.

    import_tsv

    fn import_tsv(source : String, name? : String) -> ImportReport

    Import tab-separated rows using the same column names as CSV.

    key_prefix

    fn key_prefix(prefix : KeySequence, full : KeySequence) -> Bool

    True if the first sequence is a strict prefix of the second.

    keymap_diff_to_json

    fn keymap_diff_to_json(diff : KeymapDiff) -> String

    keymap_from_bindings

    fn keymap_from_bindings(name : String, bindings : Array[Binding]) -> Keymap

    Create a minimal valid keymap without writing a DSL document.

    keymap_metrics

    fn keymap_metrics(keymap : Keymap) -> KeymapMetrics

    Calculate counts without relying on hash maps, keeping the library small.

    keymap_schema

    fn keymap_schema() -> KeymapSchema

    Describe the DSL consumed by parse_keymap.

    keymap_to_dsl

    fn keymap_to_dsl(keymap : Keymap) -> String

    Serialize a keymap back to a review-friendly DSL document.

    merge_keymaps

    fn merge_keymaps(base : Keymap, overlay : Keymap) -> MergeResult

    Merge an overlay keymap. Existing ids are replaced only when priority is at least as high; equal ids with a different command are reported.

    metrics_to_json

    fn metrics_to_json(metrics : KeymapMetrics) -> String

    migration_plan

    fn migration_plan(diff : KeymapDiff) -> String

    Render a migration plan that can be copied into a release checklist.

    normalize_keymap

    fn normalize_keymap(keymap : Keymap) -> Keymap

    Return a canonical copy with bindings and contexts sorted by name.

    overlap_explanation

    fn overlap_explanation(keymap : Keymap, left : Binding, right : Binding) -> String

    Explain why two bindings are considered to overlap.

    parse_diagnostics_to_json

    fn parse_diagnostics_to_json(diagnostics : Array[ParseDiagnostic]) -> String

    Serialize parser diagnostics for CI consumers.

    parse_keymap

    fn parse_keymap(source : String, name? : String) -> ParseResult

    Parse a complete keymap document.

    parse_keys

    fn parse_keys(raw : String) -> Result[KeySequence, String]

    Parse a sequence such as Ctrl+K Ctrl+C or cmd+k,cmd+c.

    platforms_overlap

    fn platforms_overlap(left : String, right : String) -> Bool

    Platform names are case-insensitive and can be combined with | or ,.

    primary_commands

    fn primary_commands(keymap : Keymap, context : String, platform : String) -> Array[Binding]

    Return one binding per unique command, choosing the most specific one.

    profile_by_name

    fn profile_by_name(name : String) -> PolicyProfile

    Resolve the built-in profile by name.

    profile_report_to_json

    fn profile_report_to_json(report : ProfileReport) -> String

    profile_report_to_markdown

    fn profile_report_to_markdown(report : ProfileReport) -> String

    project_capabilities

    fn project_capabilities() -> Array[String]

    Explain the design boundary in machine-readable form.

    reachability_matrix

    fn reachability_matrix(keymap : Keymap, contexts? : Array[String], platforms? : Array[String]) -> ReachabilityReport

    Probe every declaration against the requested contexts and platforms.

    Empty probe arrays mean all declared contexts and the all platform. The resulting arrays are sorted and deduplicated so the report fingerprint can be compared in CI without depending on caller order.

    reachability_to_json

    fn reachability_to_json(report : ReachabilityReport) -> String

    reachability_to_markdown

    fn reachability_to_markdown(report : ReachabilityReport) -> String

    recommendations

    fn recommendations(analysis : Analysis) -> Array[Recommendation]

    Build one actionable item per finding, deduplicated by finding code and ids.

    recommendations_to_json

    fn recommendations_to_json(items : Array[Recommendation]) -> String

    recommendations_to_markdown

    fn recommendations_to_markdown(items : Array[Recommendation]) -> String

    release_gate

    fn release_gate(project : String, version : String, input : ReleaseInput) -> ReleaseGate

    Evaluate the evidence that matters before publishing a new keymap policy.

    release_gate_to_json

    fn release_gate_to_json(gate : ReleaseGate) -> String

    release_gate_to_markdown

    fn release_gate_to_markdown(gate : ReleaseGate) -> String

    release_input

    fn release_input(keymap : Keymap, profile? : PolicyProfile?, baseline? : Keymap?) -> ReleaseInput

    Create a complete release input from a keymap and an optional baseline.

    replay

    fn replay(keymap : Keymap, inputs : Array[String], context? : String, platform? : String) -> DispatchTrace

    Replay a sequence of user inputs and count outcomes.

    row

    fn row(id : String, command : String, keys : String, context? : String, platform? : String, priority? : String, enabled? : String, description? : String) -> BindingRow

    A compact row constructor for integrations that already have columns.

    rule_report_to_json

    fn rule_report_to_json(report : RuleReport) -> String

    rule_report_to_markdown

    fn rule_report_to_markdown(report : RuleReport) -> String

    run_benchmark

    fn run_benchmark(keymap : Keymap, fixture : BenchmarkCase) -> BenchmarkResult

    Run a deterministic benchmark fixture and report semantic mismatches.

    schema_to_json

    fn schema_to_json(schema : KeymapSchema) -> String

    schema_to_markdown

    fn schema_to_markdown(schema : KeymapSchema) -> String

    select_bindings

    fn select_bindings(keymap : Keymap, command? : String, context? : String, platform? : String, enabled_only? : Bool) -> KeymapSelection

    Query by optional command, context, platform, and enabled state.

    selection_to_text

    fn selection_to_text(selection : KeymapSelection) -> String

    Produce a compact selection report for API clients.

    shortcut_final_key

    fn shortcut_final_key(sequence : KeySequence) -> String

    Return the final key without modifiers, useful for reserved-key policies.

    shortcut_has_modifier

    fn shortcut_has_modifier(sequence : KeySequence) -> Bool

    Parse a modifier expression and expose a simple risk signal.

    structural_issue_to_json

    fn structural_issue_to_json(issue : StructuralIssue) -> String

    suggest_all

    fn suggest_all(keymap : Keymap, analysis : Analysis, limit? : Int) -> Array[Suggestion]

    Suggest alternatives for every binding carrying a finding.

    suggest_for

    fn suggest_for(keymap : Keymap, binding : Binding, limit? : Int) -> Array[Suggestion]

    Suggest up to limit free alternatives for one binding.

    suggestions_to_markdown

    fn suggestions_to_markdown(suggestions : Array[Suggestion]) -> String

    Render suggestions as a simple Markdown checklist.

    support_matrix

    fn support_matrix() -> Array[(String, String, Bool)]

    Return a stable feature matrix for README and downstream tooling.

    terminal_profile

    fn terminal_profile() -> PolicyProfile

    A stricter profile for terminal and shell applications.

    timeline_append

    fn timeline_append(timeline : AuditTimeline, label : String, actor : String, kind : TimelineEventKind, analysis : Analysis, note? : String) -> AuditTimeline

    Append an event with a monotonically increasing sequence number.

    timeline_delta

    fn timeline_delta(timeline : AuditTimeline) -> TimelineDelta?

    Compare the latest event with the immediately preceding one.

    timeline_latest

    fn timeline_latest(timeline : AuditTimeline) -> TimelineEvent?

    timeline_record_gate

    fn timeline_record_gate(timeline : AuditTimeline, label : String, actor : String, analysis : Analysis, note? : String) -> AuditTimeline

    Record an analysis event and choose Approved/Rejected from the result.

    timeline_regressions

    fn timeline_regressions(timeline : AuditTimeline) -> Array[TimelineDelta]

    Return all regressions after the baseline event.

    timeline_summary

    fn timeline_summary(timeline : AuditTimeline) -> String

    Return a stable summary useful for release notes.

    timeline_to_json

    fn timeline_to_json(timeline : AuditTimeline) -> String

    timeline_to_markdown

    fn timeline_to_markdown(timeline : AuditTimeline) -> String

    unreachable_bindings

    fn unreachable_bindings(keymap : Keymap, context : String, platform : String) -> Array[Binding]

    Return ids that are declared but cannot be reached in a context.

    unreachable_commands

    fn unreachable_commands(keymap : Keymap, context : String, platform : String) -> Array[String]

    Check that every command has at least one dispatchable binding.

    validate_catalog

    fn validate_catalog(rules : Array[ReservedRule]) -> Array[String]

    Validate that every catalog entry itself uses a parseable shortcut.

    validate_keymap

    fn validate_keymap(keymap : Keymap) -> ValidationReport

    Inspect all declarations without applying conflict policy.

    validation_to_json

    fn validation_to_json(report : ValidationReport) -> String

    validation_to_markdown

    fn validation_to_markdown(report : ValidationReport) -> String