Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions LifeOS/install/LIFEOS/PULSE/PULSE.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,54 @@

# ── Module Configuration ──

# [modules] is the one place to switch a Pulse surface off. Every key defaults
# to the value shown; delete a line and you get that default back. Disabling a
# module stops it loading, stops its API routes answering, and (via
# /api/config/modules) hides its tab in the dashboard instead of leaving a nav
# entry that opens an empty page.
#
# Infrastructure Pulse needs to serve anything at all — observability, hooks,
# tab-freshness, menubar, siri, doctor — is deliberately not listed: those are
# how Pulse runs, not modules you use.
#
# The older `[section].enabled` flags below still work and still win over these
# defaults, so an existing config needs no changes.
[modules]
# Life surfaces (the top nav)
telos = true
work = true
content = true
health = true
finances = true
business = true
growth = true # audience metrics; needs USER/CUSTOMIZATIONS/TOOLS/Growth.ts
local = true # LocalIntelligence civic digest; needs a Hometown set
gear = true
atlas = true
memory = true
synapse = true
projects = true
books = true
# System surfaces
algorithm = true
bunker = true
conduit = true
upgrades = true
hypotheses = true
ledger = true
usage = true
performance = true
evals = true
threatmodel = true
hermes = true
docs = true
da = true
# Opt-in surfaces (off unless you turn them on)
voice = true
imessage = false
syslog = false


[voice]
enabled = true

Expand Down
1 change: 1 addition & 0 deletions LifeOS/install/LIFEOS/PULSE/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -582,3 +582,4 @@ export async function spawnClaude(prompt: string, opts: { model: string; timeout

return output.trim()
}
export { MODULE_DEFAULTS, resolveModules } from "./lib/modules"
47 changes: 47 additions & 0 deletions LifeOS/install/LIFEOS/PULSE/lib/modules.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// ── Module registry ──
// Every Pulse surface a human can switch off, and the default they ship with.
// Infrastructure the daemon needs in order to serve anything at all —
// observability (the dashboard itself), hooks, tab-freshness, menubar, siri,
// doctor — is deliberately absent: those are not modules you use, they are how
// Pulse runs, and a "disabled" one would leave a dashboard that cannot render.
//
// Keys are the tab/module name. `resolveModules()` layers three sources so
// existing installs keep working untouched: these defaults, then the legacy
// per-section `[x].enabled` flags, then the `[modules]` table (which wins).
export const MODULE_DEFAULTS: Record<string, boolean> = {
telos: true, work: true, content: true, health: true, finances: true,
business: true, growth: true, local: true, gear: true, atlas: true,
memory: true, synapse: true, books: true, conduit: true, projects: true,
ledger: true, upgrades: true, hypotheses: true, usage: true,
performance: true, bunker: true, algorithm: true, evals: true,
threatmodel: true, hermes: true, docs: true,
voice: true, imessage: false, syslog: false, da: true,
}

// Legacy `[section].enabled` flags that predate the `[modules]` table, mapped to
// their module key. Honouring these is what keeps a pre-existing PULSE.toml
// working after an upgrade — notably `[local_intelligence]`, whose flag was
// read by loadModules() but never plumbed through loadPulseConfig(), so setting
// it to false silently did nothing.
const LEGACY_SECTION_KEYS: Record<string, string> = {
local_intelligence: "local", hypotheses: "hypotheses", upgrades: "upgrades",
telos: "telos", work: "work", content: "content", bunker: "bunker",
performance: "performance", syslog: "syslog", voice: "voice",
imessage: "imessage", da: "da",
}

/** Merge defaults ← legacy section flags ← `[modules]` table into one map. */
export function resolveModules(parsed: Record<string, unknown>): Record<string, boolean> {
const modules = { ...MODULE_DEFAULTS }
for (const [section, key] of Object.entries(LEGACY_SECTION_KEYS)) {
const enabled = (parsed[section] as { enabled?: boolean } | undefined)?.enabled
if (typeof enabled === "boolean") modules[key] = enabled
}
const table = parsed.modules as Record<string, unknown> | undefined
if (table) {
for (const [key, value] of Object.entries(table)) {
if (typeof value === "boolean") modules[key] = value
}
}
return modules
}
Loading