Mega Mind v0.5.4

kinds.rs

Rust · 110 lines · 4.9 KB
//! The kinds of entries and their templates.

use super::Identity;

pub struct Kind {
    pub name: &'static str,
    pub about: &'static str,
    /// (heading, hint, required)
    pub sections: &'static [(&'static str, &'static str, bool)],
}

pub const KINDS: &[Kind] = &[
    Kind {
        name: "system",
        about: "How something was built (inventory, item system, AI, networking, a site feature), so another agent can reuse or follow it.",
        sections: &[
            ("Goal", "What it does and why it exists.", true),
            ("Approach", "How it works: main classes/modules, data flow, the key design choices and why.", true),
            ("Key files", "The files to read first, one line each on what they hold. List them in `refs` too.", true),
            ("How to reuse", "What another project would copy, adapt or call; dependencies it needs.", false),
            ("Pitfalls", "What went wrong while building it, or is easy to get wrong.", false),
        ],
    },
    Kind {
        name: "workflow",
        about: "How to do a multi-step task: a cinematic, a trailer, store screenshots, a build or release.",
        sections: &[
            ("Goal", "What the finished result is.", true),
            ("Steps", "Numbered steps, with the exact commands, scripts and settings.", true),
            ("Tools", "Programs, scripts, packages, settings used.", false),
            ("What made it right", "Feedback {user} gave and what fixed it; what separates good from bad here.", false),
            ("Pitfalls", "Mistakes made along the way.", false),
        ],
    },
    Kind {
        name: "fix",
        about: "A problem that took real digging, and how it was solved.",
        sections: &[
            ("Problem", "The symptom, with the exact error text.", true),
            ("Cause", "The root cause.", false),
            ("Solution", "What fixed it, and why it works.", true),
            ("What didn't work", "Attempts that failed, so nobody repeats them.", false),
        ],
    },
    Kind {
        name: "gotcha",
        about: "A trap that is easy to fall into.",
        sections: &[
            ("What happens", "The trap and its symptom.", true),
            ("Avoid it", "What to do instead.", true),
        ],
    },
    Kind {
        name: "decision",
        about: "A choice that was made and why, so nobody re-litigates or silently reverses it.",
        sections: &[
            ("Context", "What prompted the decision.", false),
            ("Decision", "What was decided.", true),
            ("Why", "The reasons, including {user}'s preferences.", true),
            ("Alternatives", "What was considered and rejected.", false),
        ],
    },
    Kind {
        name: "runbook",
        about: "An exact operational procedure (deploying a site, backups, server tasks). Changes are proposals reviewed by {reviewer}. A runbook says HOW, never WHETHER: approval for deploys and other outward actions only ever comes from {user}, live.",
        sections: &[
            ("Purpose", "What this procedure does.", true),
            ("Preconditions", "What must be true first, including who must approve.", false),
            ("Steps", "Exact commands, in order.", true),
            ("Verify", "How to confirm it worked.", true),
            ("Rollback", "How to undo it.", false),
        ],
    },
    Kind {
        name: "overview",
        about: "One per project: what it is, its stack, layout, main systems, and how it relates to other projects.",
        sections: &[
            ("Stack", "Engine/framework and versions, key packages and services.", true),
            ("Layout", "Where things live in the repo.", true),
            ("Key systems", "The main systems, linking their `system` entries by id.", false),
            ("Conventions", "Rules this project follows (style, commits, deploys).", false),
            ("Related projects", "What it shares with other projects.", false),
        ],
    },
];

pub fn kind(name: &str) -> Option<&'static Kind> {
    KINDS.iter().find(|k| k.name == name)
}

/// Fill `{user}` / `{reviewer}` in built-in text with this mind's identity settings.
pub fn personalize(text: &str, id: &Identity) -> String {
    text.replace("{user}", &id.user).replace("{reviewer}", &id.reviewer)
}

pub fn template(k: &Kind, project: &str) -> String {
    let mut s = format!(
        "---\ntitle: <one line a searcher would recognise>\nkind: {}\nproject: {}\ntags: [tag-one, tag-two]\n\
         engine: [<e.g. rust 1.90, axum 0.8, next.js 16>]\ngenre: []\nplatform: []\n\
         verified: false\nverified_how: \"<how it was confirmed: built, tested, played, deployed>\"\n\
         refs:\n  - {}:<path/inside/repo>\nrelated: []\n---\n",
        k.name,
        if project.is_empty() { "<project>" } else { project },
        if project.is_empty() { "<project>" } else { project },
    );
    for (h, hint, req) in k.sections {
        s.push_str(&format!("\n## {h}\n\n<{hint}{}>\n", if *req { "" } else { " (optional)" }));
    }
    s
}