// schema.el — Forge shared constants and helper functions. // // Provides the engram URL resolver, API key accessors, and JSON template // builders used by all pipeline stages (probe, compiler, install). // ── Constants ───────────────────────────────────────────────────────────────── let ENGRAM_DEFAULT_URL: String = "http://localhost:8742" let FORGE_VERSION: String = "0.1.0" // Absolute forge root — used by daemon.el and install.el for launchd plists // and per-soul data paths that must be absolute even when invoked from a // different working directory. let FORGE_DIR: String = "/Users/will/Development/neuron-technologies/forge" // Canonical directory layout — enforced by the tool, not by convention. let FORGE_SEEDS_DIR: String = "seeds" // compiled seed JSON files let FORGE_PROBES_DIR: String = "probes" // raw .forge interview responses let FORGE_LOG_DIR: String = "log" // session and event logs let FORGE_LOG_FILE: String = "log/sessions.jsonl" // append-only session log // ── Environment accessors ────────────────────────────────────────────────────── fn engram_url() -> String { let u: String = env("ENGRAM_URL") if str_eq(u, "") { return ENGRAM_DEFAULT_URL } return u } fn engram_key() -> String { let k: String = env("ENGRAM_API_KEY") if str_eq(k, "") { return "" } return k } fn anthropic_key() -> String { let k: String = env("ANTHROPIC_API_KEY") if str_eq(k, "") { return "" } return k } // ── Directory helpers ───────────────────────────────────────────────────────── // ensure_dirs — create canonical forge directories if they don't exist. // Call once at startup from any command that writes files. fn ensure_dirs() -> Void { if !fs_exists(FORGE_SEEDS_DIR) { fs_mkdir(FORGE_SEEDS_DIR) } if !fs_exists(FORGE_PROBES_DIR) { fs_mkdir(FORGE_PROBES_DIR) } if !fs_exists(FORGE_LOG_DIR) { fs_mkdir(FORGE_LOG_DIR) } } // log_event — append a JSON-lines entry to log/sessions.jsonl. // event: "research" | "install" | "summon" | "probe" | "compile" // subject: display name or comma-joined list for multi-summon // detail: arbitrary context string (root_id, conv_id, file path, etc.) fn log_event(event: String, subject: String, detail: String) -> Void { ensure_dirs() let ts: Int = unix_timestamp() let entry: String = "{\"ts\":" + int_to_str(ts) + ",\"event\":\"" + str_escape_json(event) + "\",\"subject\":\"" + str_escape_json(subject) + "\",\"detail\":\"" + str_escape_json(detail) + "\"}\n" // Read existing log and append (EL has fs_write but not fs_append natively) let existing: String = fs_read(FORGE_LOG_FILE) fs_write(FORGE_LOG_FILE, existing + entry) } // ── String utilities ────────────────────────────────────────────────────────── // str_escape_json — escape a string for safe embedding in a JSON value. // Handles: backslash, double-quote, newline, tab, carriage return. fn str_escape_json(s: String) -> String { let r: String = str_replace(s, "\\", "\\\\") let r = str_replace(r, "\"", "\\\"") let r = str_replace(r, "\n", "\\n") let r = str_replace(r, "\t", "\\t") let r = str_replace(r, "\r", "\\r") return r } // ── JSON template builders ──────────────────────────────────────────────────── // probe_response_template — builds the initial shell written to .forge. // The sections and responses fields are populated by probe_main() at runtime. fn probe_response_template(subject: String) -> String { "{\"subject\":\"" + subject + "\",\"version\":\"1.0\",\"sections\":{},\"responses\":[]}" } // seed_template — builds the shell written to seed.json after compilation. // Patterns are merged into this structure by compile_main(). fn seed_template(subject: String) -> String { "{\"subject\":\"" + subject + "\",\"version\":\"1.0\",\"values\":[],\"voice_profile\":{},\"biography\":[],\"reasoning_patterns\":[],\"relationships\":[]}" }