index.html
file-level
1
files
1
commits
0
hotspots
0
🧊 dead
0
💥 blast risk
| 1 | <!DOCTYPE html> |
| 2 | <html lang="en"> |
| 3 | <head> |
| 4 | <meta charset="UTF-8"> |
| 5 | <meta name="viewport" content="width=device-width, initial-scale=1"> |
| 6 | <meta name="theme-color" content="#050505"> |
| 7 | <link rel="icon" href="/assets/favicon.png" type="image/png" sizes="32x32"> |
| 8 | <title>Knowtation Hub</title> |
| 9 | <link rel="stylesheet" href="hub.css?v=20260526a"> |
| 10 | </head> |
| 11 | <body> |
| 12 | <div id="app"> |
| 13 | <header class="hub-header"> |
| 14 | <h1>Knowtation Hub</h1> |
| 15 | <div class="hub-auth" id="hub-auth-buttons"> |
| 16 | <label for="vault-switcher" class="vault-switcher-label hidden" id="vault-switcher-wrap"> |
| 17 | <span class="vault-switcher-text">Vault</span> |
| 18 | <select id="vault-switcher" class="vault-switcher-select" aria-label="Current vault"></select> |
| 19 | </label> |
| 20 | <button type="button" id="btn-how-to-use" class="hidden btn-secondary">How to use</button> |
| 21 | <button type="button" id="btn-settings" class="hidden btn-secondary">Settings</button> |
| 22 | <button type="button" id="btn-new-note" class="hidden btn-new-note">+ New note</button> |
| 23 | <button type="button" id="btn-import" class="hidden btn-secondary">Import</button> |
| 24 | <button type="button" id="btn-header-suggested" class="hidden btn-primary" title="Review proposals waiting for approval">Suggested</button> |
| 25 | <span id="user-name" class="muted"></span> |
| 26 | <span id="login-buttons-wrap" class="login-buttons-wrap hidden"></span> |
| 27 | <button id="btn-login-google" type="button" class="hidden btn-provider">Continue with Google</button> |
| 28 | <button id="btn-login-github" type="button" class="hidden btn-provider">Continue with GitHub</button> |
| 29 | <button id="btn-logout" type="button" class="hidden btn-secondary">Log out</button> |
| 30 | </div> |
| 31 | </header> |
| 32 | |
| 33 | <div id="hub-api-base-footgun-banner" class="hub-api-footgun-banner hidden" role="alert" aria-live="polite"></div> |
| 34 | |
| 35 | <div id="login-required" class="panel login-first-screen"> |
| 36 | <div id="login-invite-banner" class="login-invite-banner hidden" role="status"></div> |
| 37 | <div class="login-hero"> |
| 38 | <h2 class="login-title login-title-main-only">Knowtation</h2> |
| 39 | <p class="login-tagline">Your notes, searchable. One place for you and your agents.</p> |
| 40 | <p class="login-tagline login-tagline-sub">Precise token use mean speed & savings.</p> |
| 41 | </div> |
| 42 | <div class="login-two-paths" role="region" aria-label="Two ways to use Knowtation"> |
| 43 | <p class="login-two-paths-title">Two ways to use Knowtation</p> |
| 44 | <ul class="login-two-paths-list"> |
| 45 | <li><strong>Use in the decentralized cloud (beta)</strong> — Sign in with Google or GitHub; we host your vault. Open usage during beta while we learn.</li> |
| 46 | <li><strong>Run it locally</strong> — Clone, set <code>KNOWTATION_VAULT_PATH</code> and <code>HUB_JWT_SECRET</code>, <code>npm run hub</code>. <a href="https://github.com/aaronrene/knowtation/blob/main/docs/TWO-PATHS-HOSTED-AND-SELF-HOSTED.md#quick-start-self-hosted" target="_blank" rel="noopener" class="btn-link">Quick start (self-hosted)</a>.</li> |
| 47 | </ul> |
| 48 | </div> |
| 49 | <div class="login-cta-block"> |
| 50 | <p id="hub-beta-note" class="login-cta-label muted" style="font-size: 0.8rem; margin-top: 0;">Beta: open usage for now. Later: free tier + paid plans, dollar-clear credits (1 = $1), metering focused on <strong>index + search + writes</strong> (no hosted transcription—bring Markdown or exports). Rollover add-ons and usage charts when billing ships.</p> |
| 51 | <p class="login-how-to-wrap"><button type="button" id="btn-login-how-to-use" class="btn-link">New here? How to use</button> — setup and how agents use your vault.</p> |
| 52 | </div> |
| 53 | <div class="hub-ecosystem" aria-label="Knowtation at the center of your connections"> |
| 54 | <div class="hub-ecosystem-rings"> |
| 55 | <svg class="hub-ecosystem-svg" viewBox="0 0 320 320" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> |
| 56 | <circle class="hub-ring hub-ring-1" cx="160" cy="160" r="90" fill="none" stroke="var(--border)" stroke-width="1"/> |
| 57 | <circle class="hub-ring hub-ring-2" cx="160" cy="160" r="135" fill="none" stroke="var(--border)" stroke-width="1"/> |
| 58 | <circle class="hub-ring hub-ring-3" cx="160" cy="160" r="158" fill="none" stroke="var(--accent)" stroke-width="1" opacity="0.6"/> |
| 59 | </svg> |
| 60 | <div class="hub-ecosystem-center"> |
| 61 | <span class="hub-ecosystem-core-icon" aria-hidden="true">📁</span> |
| 62 | <span class="hub-ecosystem-core-label">Knowtation</span> |
| 63 | </div> |
| 64 | <div class="hub-ecosystem-icon hub-ecosystem-icon-1" title="Cursor">✏️</div> |
| 65 | <div class="hub-ecosystem-icon hub-ecosystem-icon-2" title="Claude">🤖</div> |
| 66 | <div class="hub-ecosystem-icon hub-ecosystem-icon-3" title="DeerFlow">🦌</div> |
| 67 | <div class="hub-ecosystem-icon hub-ecosystem-icon-4" title="Windsurf">🏄</div> |
| 68 | <div class="hub-ecosystem-icon hub-ecosystem-icon-5" title="MCP">🔌</div> |
| 69 | <div class="hub-ecosystem-icon hub-ecosystem-icon-6" title="CLI">💻</div> |
| 70 | <div class="hub-ecosystem-icon hub-ecosystem-icon-7" title="Search">🔍</div> |
| 71 | <div class="hub-ecosystem-icon hub-ecosystem-icon-8" title="Import">📥</div> |
| 72 | <div class="hub-ecosystem-icon hub-ecosystem-icon-9" title="Tags">🏷️</div> |
| 73 | <div class="hub-ecosystem-icon hub-ecosystem-icon-10" title="Project">📂</div> |
| 74 | <div class="hub-ecosystem-icon hub-ecosystem-icon-11" title="Causal chain">🔗</div> |
| 75 | <div class="hub-ecosystem-icon hub-ecosystem-icon-12" title="Time">⏱️</div> |
| 76 | <div class="hub-ecosystem-icon hub-ecosystem-icon-13" title="Proposals">📋</div> |
| 77 | <div class="hub-ecosystem-icon hub-ecosystem-icon-14" title="GitHub">🐙</div> |
| 78 | <div class="hub-ecosystem-icon hub-ecosystem-icon-15" title="API">📡</div> |
| 79 | <div class="hub-ecosystem-icon hub-ecosystem-icon-16" title="Vault">🔐</div> |
| 80 | <div class="hub-ecosystem-icon hub-ecosystem-icon-17" title="Transcription">🎙️</div> |
| 81 | <div class="hub-ecosystem-icon hub-ecosystem-icon-18" title="Sync">🔄</div> |
| 82 | <div class="hub-ecosystem-icon hub-ecosystem-icon-19" title="Notes">📝</div> |
| 83 | <div class="hub-ecosystem-icon hub-ecosystem-icon-20" title="Export">📤</div> |
| 84 | </div> |
| 85 | </div> |
| 86 | <div id="oauth-not-configured" class="oauth-setup hidden"> |
| 87 | <p><strong>OAuth is not configured yet.</strong> The Hub only accepts login through Google or GitHub. Add credentials to your project <code>.env</code>, then restart the Hub.</p> |
| 88 | <ul class="oauth-steps"> |
| 89 | <li><strong>Google:</strong> Cloud Console → OAuth client (Web) → redirect URI <code>http://localhost:3333/api/v1/auth/callback/google</code> → set <code>GOOGLE_CLIENT_ID</code> and <code>GOOGLE_CLIENT_SECRET</code>.</li> |
| 90 | <li><strong>GitHub:</strong> OAuth App → <strong>Authorization callback URLs</strong> (add <em>both</em> for local Hub): <code>http://localhost:3333/api/v1/auth/callback/github</code> (login) and <code>http://localhost:3333/api/v1/auth/callback/github-connect</code> (<strong>Connect GitHub</strong> for backup). Set <code>GITHUB_CLIENT_ID</code> and <code>GITHUB_CLIENT_SECRET</code> in <code>.env</code>.</li> |
| 91 | </ul> |
| 92 | <p class="muted">See <code>hub/README.md</code> (section “Log in (OAuth)”).</p> |
| 93 | <p class="hosted-note muted">If you're on a hosted Knowtation site, the provider has already set this up—just sign in above.</p> |
| 94 | </div> |
| 95 | </div> |
| 96 | |
| 97 | <main id="main" class="hidden"> |
| 98 | <section class="search-section"> |
| 99 | <div id="hub-index-stale-banner" class="hub-index-stale-banner hidden" role="status" aria-live="polite"> |
| 100 | <span class="hub-index-stale-banner-text">Notes changed since the last <strong>Re-index</strong>. <strong>Meaning</strong> search may be out of date until you run it again.</span> |
| 101 | <div class="hub-index-stale-banner-actions"> |
| 102 | <button type="button" id="hub-index-stale-run" class="btn-secondary btn-small">Re-index now</button> |
| 103 | <button type="button" id="hub-index-stale-dismiss" class="btn-link btn-link-small">Dismiss</button> |
| 104 | </div> |
| 105 | </div> |
| 106 | <div class="search-row search-row-filters" role="group" aria-label="Search query and filters"> |
| 107 | <input type="text" id="search-query" placeholder="Search…" autocomplete="off" aria-label="Search query"> |
| 108 | <select id="search-mode" class="search-mode-select" title="Meaning = similar ideas (indexed). Keyword = text in path, body, and key frontmatter fields." aria-label="Search mode"> |
| 109 | <option value="semantic">Meaning</option> |
| 110 | <option value="keyword">Keyword</option> |
| 111 | </select> |
| 112 | <div class="filter-project-wrap"> |
| 113 | <select id="filter-project"> |
| 114 | <option value="">All projects</option> |
| 115 | </select> |
| 116 | <button type="button" id="btn-projects-help" class="btn-inline-field-help hidden" title="How projects work on hosted" aria-label="How projects work on hosted"> |
| 117 | <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg> |
| 118 | </button> |
| 119 | </div> |
| 120 | <select id="filter-tag"> |
| 121 | <option value="">All tags</option> |
| 122 | </select> |
| 123 | <select id="filter-folder"> |
| 124 | <option value="">All folders</option> |
| 125 | </select> |
| 126 | <select id="filter-content-scope" title="Applies to the Notes list and to Search. Search results always open under Notes—not Activity." aria-label="Content type: all notes, exclude approval logs, or approval logs only"> |
| 127 | <option value="">All content</option> |
| 128 | <option value="notes">Notes only</option> |
| 129 | <option value="approval_logs">Approval logs only</option> |
| 130 | </select> |
| 131 | <select id="filter-network" class="filter-blockchain hidden" title="Filter by blockchain network (e.g. icp, ethereum). Only shown when vault has notes with network frontmatter." aria-label="Filter by blockchain network"> |
| 132 | <option value="">All networks</option> |
| 133 | </select> |
| 134 | <select id="filter-wallet" class="filter-blockchain hidden" title="Filter by wallet address. Only shown when vault has notes with wallet_address frontmatter." aria-label="Filter by wallet address"> |
| 135 | <option value="">All wallets</option> |
| 136 | </select> |
| 137 | </div> |
| 138 | <div class="search-row search-row-dates-actions" role="group" aria-label="Date range and search actions"> |
| 139 | <label for="filter-since" class="filter-date-label">Since</label> |
| 140 | <input type="date" id="filter-since" aria-label="Filter notes from this date"> |
| 141 | <label for="filter-until" class="filter-date-label">Until</label> |
| 142 | <input type="date" id="filter-until" aria-label="Filter notes until this date"> |
| 143 | <button id="btn-search" type="button" class="btn-primary" title="Run search (mode from dropdown: Meaning or Keyword). Results appear under the Notes tab. Respects filters. Enter also runs search." aria-label="Search vault">Search</button> |
| 144 | <button id="btn-clear-search" type="button" class="btn-secondary" title="Clear search, list filters (project/tag/folder/etc.), and content scope — show the full note list" aria-label="Clear search and list filters">Clear</button> |
| 145 | <button id="btn-apply-filters" type="button" class="btn-secondary">Apply filters</button> |
| 146 | <button id="btn-reindex" type="button" class="btn-secondary" title="Re-run indexer so search reflects new or changed notes">Re-index</button> |
| 147 | <span id="hub-index-status" class="hub-index-status" aria-live="polite" aria-atomic="true"></span> |
| 148 | </div> |
| 149 | </section> |
| 150 | |
| 151 | <section class="browse-toolbar hidden" id="browse-toolbar"> |
| 152 | <div class="view-modes"> |
| 153 | <span class="toolbar-label">Browse</span> |
| 154 | <button type="button" class="view-tab active" data-view="list">List</button> |
| 155 | <button type="button" class="view-tab" data-view="calendar">Calendar</button> |
| 156 | <button type="button" class="view-tab" data-view="graph">Overview</button> |
| 157 | <div class="browse-key-wrap"> |
| 158 | <details id="search-key-help" class="browse-toolbar-key-details"> |
| 159 | <summary class="search-key-summary" aria-label="At-a-glance key: connection helpers, notes, proposals, agents, memory, and search. Click again to close." title="At-a-glance: connection helpers, notes & import, proposals & agents, memory, attestation"> |
| 160 | <svg class="search-key-icon" viewBox="0 0 24 24" width="31" height="31" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> |
| 161 | <circle cx="7.5" cy="12.5" r="3.5"/> |
| 162 | <path d="M10.5 12.5H21"/> |
| 163 | <path d="M16.5 12.5v3"/> |
| 164 | <path d="M19.5 12.5v1.5"/> |
| 165 | </svg> |
| 166 | <span class="search-key-collapse-cue" aria-hidden="true">▲</span> |
| 167 | </summary> |
| 168 | <div class="search-key-body"> |
| 169 | <p class="search-key-lede">One vault for <strong class="search-key-term">people</strong> and <strong class="search-key-term">agents</strong> (Hub UI, CLI, MCP, API). The same notes, imports, and proposal queues apply to both; what you can open follows your <strong class="search-key-term">role</strong> and tokens. Use whichever you prefer.</p> |
| 170 | <div class="search-key-columns" role="presentation"> |
| 171 | <div class="search-key-col"> |
| 172 | <p class="search-key-col-title">Notes & import</p> |
| 173 | <ul class="search-key-list"> |
| 174 | <li><strong class="search-key-term">Notes</strong> — Markdown files in your vault (List / Calendar / Overview). Search results land under <strong class="search-key-term">Notes</strong>.</li> |
| 175 | <li><strong class="search-key-term">Import</strong> — Brings chats, exports, and files in as normal notes (same search and filters afterward).</li> |
| 176 | <li><strong class="search-key-term">Quick</strong> — Next to the browse key; click the <strong class="search-key-term">arrow</strong> to show or hide chips (projects, tags, folders, nets). Row filters and <strong class="search-key-term">content</strong> scope apply either way.</li> |
| 177 | <li><strong class="search-key-term">All</strong> / <strong class="search-key-term">Clear</strong> — Reset Quick and filters to see the full list again.</li> |
| 178 | <li><strong class="search-key-term">Meaning</strong> — Semantic search over the index; <strong class="search-key-term">Keyword</strong> scans note text on the server.</li> |
| 179 | <li><strong class="search-key-term">Images & video</strong> — Use links or uploads per your setup; media files live with the vault and can be included when you <strong class="search-key-term">back up to GitHub</strong> (paths stay consistent in the repo).</li> |
| 180 | </ul> |
| 181 | </div> |
| 182 | <div class="search-key-col"> |
| 183 | <p class="search-key-col-title">Proposals & agents</p> |
| 184 | <ul class="search-key-list"> |
| 185 | <li><strong class="search-key-term">Suggested</strong> — Proposals waiting for review (from you, CLI, or agents). Open one to <strong class="search-key-term">Evaluate</strong> (pass / fail / needs changes), then <strong class="search-key-term">Approve</strong> (writes the vault) or <strong class="search-key-term">Discard</strong>.</li> |
| 186 | <li><strong class="search-key-term">Activity</strong> — Timeline of proposal events (created, approved, discarded). The Notes search bar does <em>not</em> filter this tab.</li> |
| 187 | <li><strong class="search-key-term">Discarded</strong> — Rejected proposals for reference; not applied to the vault.</li> |
| 188 | <li><strong class="search-key-term">Evaluations</strong> — Policy and optional <strong class="search-key-term">review hints</strong> / enrich (LLM) tie to the same Suggested queue; admins may require evaluation before approve (see Settings → Proposal policy).</li> |
| 189 | <li><strong class="search-key-term">Agents</strong> — Use the same APIs as humans: search, read notes, create proposals. Nothing merges to canonical notes until approval when you use the proposal flow.</li> |
| 190 | </ul> |
| 191 | </div> |
| 192 | </div> |
| 193 | <p class="search-key-reindex"><strong class="search-key-term">Re-index</strong> rebuilds the search index from your vault. Run it after large imports, many edits, or path renames so <strong class="search-key-term">Meaning</strong> search and snippets match what is stored.</p> |
| 194 | <div class="search-key-meta"> |
| 195 | <p class="search-key-col-title search-key-meta-heading">Memory</p> |
| 196 | <ul class="search-key-list"> |
| 197 | <li><strong class="search-key-term">Memory consolidation</strong> — Optional jobs that merge memory events into compact facts so future agent context stays smaller; scheduled or triggered outside the Notes list (see docs / Settings).</li> |
| 198 | <li><strong class="search-key-term">Discover</strong> — Optional pass during consolidation that adds cross-topic “insight” links between themes; augments memory, not a separate Hub screen.</li> |
| 199 | <li><strong class="search-key-term">Attestation</strong> — Signing (and optional Internet Computer anchoring) for audit trails on approved changes; complements proposals after commit, not day-to-day browsing.</li> |
| 200 | </ul> |
| 201 | </div> |
| 202 | <div class="search-key-assist search-key-assist-after-memory" role="region" aria-label="Connection helpers: Copy prime and knowtation doctor"> |
| 203 | <p class="search-key-col-title search-key-assist-title">Connection helpers</p> |
| 204 | <div class="search-key-assist-pair"> |
| 205 | <p><strong class="search-key-term">Copy prime</strong> — <strong>Settings → Integrations → Hub API</strong> → <strong>Copy prime</strong>. A short “you are here” for your tool after it connects; not your login token.</p> |
| 206 | <p><strong class="search-key-term">Doctor</strong> — With the CLI on your computer: <code>knowtation doctor</code> checks the vault folder and (optionally) the Hub. See <code>docs/RETRIEVAL-AND-CLI-REFERENCE.md</code>.</p> |
| 207 | </div> |
| 208 | </div> |
| 209 | </div> |
| 210 | </details> |
| 211 | </div> |
| 212 | <div id="filter-chips" class="filter-chips" aria-label="Quick filters"></div> |
| 213 | </div> |
| 214 | <div class="presets-row"> |
| 215 | <input type="text" id="preset-name" placeholder="Save view as…" maxlength="40"> |
| 216 | <button type="button" id="btn-save-preset">Save preset</button> |
| 217 | <div id="presets-list" class="presets-list"></div> |
| 218 | </div> |
| 219 | </section> |
| 220 | |
| 221 | <section id="hub-empty-vault-strip" class="hub-empty-vault-strip hidden" role="region" aria-label="Getting started after skipping the walkthrough"> |
| 222 | <div class="hub-empty-vault-strip-inner"> |
| 223 | <p class="hub-empty-vault-strip-lede">Your vault is empty. Pick up where the walkthrough left off — same three moves as on the homepage:</p> |
| 224 | <ol class="hub-empty-vault-steps" role="list"> |
| 225 | <li><span class="hub-empty-vault-num">1</span><span class="hub-empty-vault-step-body"><strong>Note / import</strong> — capture or import into your indexed vault.</span></li> |
| 226 | <li><span class="hub-empty-vault-num">2</span><span class="hub-empty-vault-step-body"><strong>Add agents</strong> — MCP or Hub API from Settings → Integrations.</span></li> |
| 227 | <li><span class="hub-empty-vault-num">3</span><span class="hub-empty-vault-step-body"><strong>Ask your AI</strong> — phased prompts in the docs when you want your assistant to drive setup.</span></li> |
| 228 | </ol> |
| 229 | <div class="hub-empty-vault-actions"> |
| 230 | <button type="button" id="btn-empty-strip-wizard" class="btn-primary">Open setup walkthrough</button> |
| 231 | <button type="button" id="btn-empty-strip-getting-started" class="btn-secondary">Getting started (How to use)</button> |
| 232 | </div> |
| 233 | </div> |
| 234 | </section> |
| 235 | |
| 236 | <section class="tabs" aria-label="Main sections"> |
| 237 | <div class="tabs-inner"> |
| 238 | <div class="tabs-buttons"> |
| 239 | <button type="button" data-tab="notes" class="tab active" title="Vault markdown + approval log files; Search shows results here">Notes</button> |
| 240 | <button type="button" data-tab="activity" class="tab" title="Proposals: proposed → approved/discarded (not the same as vault approval log search)">Activity</button> |
| 241 | <button type="button" data-tab="suggested" class="tab" title="Proposals waiting for review">Suggested</button> |
| 242 | <button type="button" data-tab="problem" class="tab" title="Discarded proposals">Discarded</button> |
| 243 | </div> |
| 244 | <div class="tabs-list-controls"> |
| 245 | <label class="hub-sort-label" for="hub-list-sort">Sort</label> |
| 246 | <select id="hub-list-sort" aria-label="Sort list"></select> |
| 247 | </div> |
| 248 | </div> |
| 249 | </section> |
| 250 | <div id="proposal-filters-bar" class="proposal-filters-bar hidden" role="region" aria-label="Proposal filters"> |
| 251 | <div class="proposal-list-filters" id="proposal-list-filters"> |
| 252 | <label class="proposal-filter-label">Label <input type="text" id="proposal-filter-label" placeholder="e.g. review" autocomplete="off" /></label> |
| 253 | <label class="proposal-filter-label">Source <input type="text" id="proposal-filter-source" placeholder="e.g. agent" autocomplete="off" /></label> |
| 254 | <label class="proposal-filter-label">Path prefix <input type="text" id="proposal-filter-path-prefix" placeholder="e.g. inbox" autocomplete="off" /></label> |
| 255 | <label class="proposal-filter-label proposal-filter-checkbox"><input type="checkbox" id="proposal-filter-pending-eval" /> Pending evaluation only</label> |
| 256 | <label class="proposal-filter-label">Review queue <input type="text" id="proposal-filter-review-queue" placeholder="e.g. legal" autocomplete="off" /></label> |
| 257 | <label class="proposal-filter-label">Severity <input type="text" id="proposal-filter-review-severity" placeholder="standard or elevated" autocomplete="off" /></label> |
| 258 | <button type="button" id="proposal-filter-apply" class="btn-secondary">Apply filters</button> |
| 259 | <button type="button" id="proposal-filter-clear" class="btn-secondary">Clear</button> |
| 260 | <button type="button" id="btn-new-proposal" class="btn-secondary hidden">New proposal</button> |
| 261 | </div> |
| 262 | </div> |
| 263 | |
| 264 | <section id="tab-notes" class="tab-panel"> |
| 265 | <div id="notes-view-list" class="notes-view-panel"> |
| 266 | <div id="notes-list" class="list"></div> |
| 267 | <div id="notes-total" class="muted total"></div> |
| 268 | </div> |
| 269 | <div id="notes-view-calendar" class="notes-view-panel hidden"> |
| 270 | <div class="calendar-nav" id="calendar-nav"> |
| 271 | <button type="button" id="cal-prev" aria-label="Previous month">←</button> |
| 272 | <h3 id="cal-title"></h3> |
| 273 | <button type="button" id="cal-next" aria-label="Next month">→</button> |
| 274 | </div> |
| 275 | <div class="calendar-weekdays"> |
| 276 | <span>Sun</span><span>Mon</span><span>Tue</span><span>Wed</span><span>Thu</span><span>Fri</span><span>Sat</span> |
| 277 | </div> |
| 278 | <div id="calendar-grid" class="calendar-grid"></div> |
| 279 | <div id="calendar-day-list" class="calendar-day-list hidden"> |
| 280 | <button type="button" id="cal-back" class="btn-secondary">← Back to month</button> |
| 281 | <h4 id="cal-day-title"></h4> |
| 282 | <div id="calendar-day-notes" class="list"></div> |
| 283 | </div> |
| 284 | </div> |
| 285 | <div id="notes-view-graph" class="notes-view-panel hidden"> |
| 286 | <div class="dashboard-cards" id="dashboard-cards"></div> |
| 287 | |
| 288 | <div id="consolidation-card" class="consol-dashboard-card" style="display:none;"> |
| 289 | <div class="consol-card-header"> |
| 290 | <h4 style="margin: 0; font-size: 0.95rem;">Memory Consolidation</h4> |
| 291 | <span id="consol-status-badge" class="consol-badge consol-badge-neutral">● Not configured</span> |
| 292 | </div> |
| 293 | <div class="consol-card-body"> |
| 294 | <div id="consol-last-pass" class="muted small">Last pass: —</div> |
| 295 | <div id="consol-next-pass" class="muted small">Next pass: —</div> |
| 296 | <div id="consol-quota-meter" class="consol-cost-meter" style="display:none;"> |
| 297 | <span id="consol-quota-label" class="muted small"></span> |
| 298 | <div class="billing-usage-bar-track" style="max-width: 12rem;"> |
| 299 | <div id="consol-quota-fill" class="billing-usage-bar-fill" style="width:0%;"></div> |
| 300 | </div> |
| 301 | </div> |
| 302 | </div> |
| 303 | <div class="consol-card-actions"> |
| 304 | <button type="button" id="btn-consol-now">Consolidate Now</button> |
| 305 | <button type="button" id="btn-consol-history">History</button> |
| 306 | <button type="button" id="btn-consol-settings">Settings ⚙</button> |
| 307 | </div> |
| 308 | </div> |
| 309 | |
| 310 | <div class="chart-row"> |
| 311 | <div class="chart-box"><canvas id="chart-projects"></canvas></div> |
| 312 | <div class="chart-box"><canvas id="chart-tags"></canvas></div> |
| 313 | </div> |
| 314 | <div class="chart-box chart-wide"><canvas id="chart-timeline"></canvas></div> |
| 315 | <p class="muted dashboard-footnote" id="dashboard-footnote"></p> |
| 316 | </div> |
| 317 | </section> |
| 318 | <section id="tab-activity" class="tab-panel hidden"> |
| 319 | <p class="muted"><strong>Activity</strong> lists proposal records (same data as Approve/Discard)—not semantic search hits. Vault <code>approvals/*.md</code> logs: open <strong>Notes</strong>, set content to <strong>Approval logs only</strong>, Apply filters or Search.</p> |
| 320 | <p class="muted">Use the <strong>proposal filters</strong> row (shown above when this tab, Suggested, or Discarded is active) to narrow by label, source, path, evaluation, queue, or severity. <strong>Sort</strong> (top right) applies here too.</p> |
| 321 | <p class="muted">Sources: Hub (<strong>New proposal</strong> / <strong>Propose change</strong>), CLI, API.</p> |
| 322 | <div id="proposals-activity" class="list activity-timeline"></div> |
| 323 | </section> |
| 324 | <section id="tab-suggested" class="tab-panel hidden"> |
| 325 | <p class="muted">Proposals needing your review. Create one with <strong>New proposal</strong> or from a note (<strong>Propose change</strong> in the detail panel); the CLI and agents can still create them via the API. Open a row, then Approve (writes to vault) or Discard.</p> |
| 326 | <div id="proposals-suggested" class="list"></div> |
| 327 | </section> |
| 328 | <section id="tab-problem" class="tab-panel hidden"> |
| 329 | <p class="muted">Proposals you (or someone) discarded. They were not applied to the vault. You can still open them to read.</p> |
| 330 | <div id="proposals-problem" class="list"></div> |
| 331 | </section> |
| 332 | |
| 333 | <aside id="detail-panel" class="detail-panel hidden" aria-labelledby="detail-title"> |
| 334 | <div class="detail-header"> |
| 335 | <h2 id="detail-title"></h2> |
| 336 | <div class="detail-header-actions"> |
| 337 | <button |
| 338 | type="button" |
| 339 | id="btn-detail-path-info" |
| 340 | class="detail-header-info" |
| 341 | aria-label="About note paths. Paths do not change after save. Use Duplicate (in the note actions) to pick a new path with the same project picker as New note; you may delete the original after save if you intend to replace it—agents, automation, or bookmarks may still rely on the old path, so you can leave both copies. Cross-vault copy keeps the same vault-relative path in the target vault (not inbox)." |
| 342 | title="Paths stay fixed after save. Duplicate to place a copy at a new path, then delete the old note only if you mean to replace it—agents or scripts may still use the old path."> |
| 343 | <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg> |
| 344 | </button> |
| 345 | <button type="button" id="btn-copy-path" class="hidden">Copy path</button> |
| 346 | <button type="button" id="detail-close">Close</button> |
| 347 | </div> |
| 348 | </div> |
| 349 | <div class="detail-body-wrap"> |
| 350 | <button |
| 351 | type="button" |
| 352 | id="btn-detail-copy-body" |
| 353 | class="detail-copy-body-btn hidden" |
| 354 | aria-label="Copy note body as Markdown" |
| 355 | title="Copy note body (Markdown)"> |
| 356 | <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg> |
| 357 | </button> |
| 358 | <div id="detail-body"></div> |
| 359 | </div> |
| 360 | <div id="detail-actions" class="detail-actions"></div> |
| 361 | <div class="detail-footer"> |
| 362 | <div class="detail-footer-row"> |
| 363 | <button type="button" class="btn-secondary detail-close-bottom" data-hub-detail-close aria-label="Close panel">Close</button> |
| 364 | <p class="detail-footer-hint muted small">Use Escape button also, or click on any other item.</p> |
| 365 | </div> |
| 366 | </div> |
| 367 | </aside> |
| 368 | </main> |
| 369 | |
| 370 | <div id="modal-create" class="modal hidden" aria-modal="true" role="dialog" aria-labelledby="modal-create-title"> |
| 371 | <div class="modal-backdrop" id="modal-create-backdrop"></div> |
| 372 | <div class="modal-card"> |
| 373 | <div class="modal-header"> |
| 374 | <h2 id="modal-create-title">Add to vault</h2> |
| 375 | <button type="button" id="modal-create-close" class="modal-close">×</button> |
| 376 | </div> |
| 377 | <div class="modal-tabs"> |
| 378 | <button type="button" class="modal-tab active" data-create-tab="quick">Quick capture</button> |
| 379 | <button type="button" class="modal-tab" data-create-tab="full">New note</button> |
| 380 | </div> |
| 381 | <div id="create-quick" class="create-panel"> |
| 382 | <textarea id="quick-body" rows="6" placeholder="Type or paste anything…"></textarea> |
| 383 | <label for="quick-project">Project (optional)</label> |
| 384 | <input type="text" id="quick-project" placeholder="e.g. myproject" aria-describedby="quick-project-hint"> |
| 385 | <p id="quick-project-hint" class="muted small">If set, saves under <code>projects/<slug>/inbox/…</code> and sets <code>project</code> in frontmatter. Leave empty to save to <code>inbox/</code> only.</p> |
| 386 | <p class="muted small">Saves to inbox with today’s date.</p> |
| 387 | <button type="button" id="btn-quick-save" class="btn-primary">Save to inbox</button> |
| 388 | <p id="create-msg-quick" class="create-msg"></p> |
| 389 | </div> |
| 390 | <div id="create-full" class="create-panel hidden"> |
| 391 | <div id="duplicate-source-banner" class="duplicate-source-banner hidden" role="region" aria-label="Duplicate note"> |
| 392 | <p class="muted small duplicate-source-banner-lede">Duplicating from <code id="duplicate-source-path"></code>. Choose a <strong>new</strong> path (same pickers as New note). Saving at the same path would overwrite the original.</p> |
| 393 | <label class="duplicate-delete-label"> |
| 394 | <input type="checkbox" id="duplicate-delete-after-save" /> |
| 395 | <span>After a successful save, delete the original note</span> |
| 396 | </label> |
| 397 | <p class="muted small duplicate-delete-hint">Uncheck to keep two copies if agents, automation, or bookmarks might still need the old path.</p> |
| 398 | </div> |
| 399 | <div class="create-path-group" role="group" aria-label="Note path"> |
| 400 | <label for="full-create-project-slug"><strong class="create-label-em">Project</strong> in vault</label> |
| 401 | <select id="full-create-project-slug" class="settings-input-inline" style="width: 100%; max-width: 22rem; margin-bottom: 0.35rem;" aria-describedby="full-create-project-slug-hint"></select> |
| 402 | <p id="full-create-project-slug-hint" class="muted small" style="margin-top: 0; margin-bottom: 0.5rem;">Choose a <strong class="create-hint-em">Project</strong> or use <strong class="create-hint-em">Custom</strong> (type full path) for anything else.</p> |
| 403 | <div id="full-create-project-subroot-wrap" class="hidden"> |
| 404 | <label for="full-create-project-subroot">Subfolder under project</label> |
| 405 | <select id="full-create-project-subroot" class="settings-input-inline" style="width: 100%; max-width: 22rem; margin-bottom: 0.35rem;" aria-describedby="full-create-project-subroot-hint"></select> |
| 406 | <p id="full-create-project-subroot-hint" class="muted small" style="margin-top: 0; margin-bottom: 0.5rem;">Choose a subfolder or use <strong class="create-hint-em">Custom</strong> to type any path.</p> |
| 407 | </div> |
| 408 | <div id="full-create-nonproject-folder-wrap"> |
| 409 | <label for="full-path-folder"><strong class="create-label-em">Folder</strong> in vault (when not using a project above)</label> |
| 410 | <select id="full-path-folder" class="settings-input-inline" style="width: 100%; max-width: 22rem; margin-bottom: 0.35rem;" aria-describedby="full-path-folder-hint"></select> |
| 411 | <p id="full-path-folder-hint" class="muted small" style="margin-top: 0; margin-bottom: 0.5rem;">Choose a <strong class="create-hint-em">Folder</strong> on this vault. Pick <strong class="create-hint-em">Custom</strong> to type any path.</p> |
| 412 | </div> |
| 413 | </div> |
| 414 | <label for="full-path"><strong class="create-label-em">Path</strong> (vault-relative)</label> |
| 415 | <input type="text" id="full-path" placeholder="inbox/my-note.md or projects/my-slug/inbox/note.md" autocomplete="off" spellcheck="false" aria-describedby="full-path-folder-caption full-path-project-typo-hint full-path-similar-hint"> |
| 416 | <p id="full-path-folder-caption" class="muted small" style="margin-top: 0.15rem; margin-bottom: 0.35rem;">Choose ‘Custom’ in <strong class="create-hint-em">Project</strong>, <strong class="create-hint-em">Folder</strong>, or <strong class="create-hint-em">Path</strong> to change your final path.</p> |
| 417 | <p id="full-path-project-typo-hint" class="muted small detail-project-hint hidden" role="status"></p> |
| 418 | <p style="margin: 0 0 0.5rem 0;"><button type="button" id="btn-full-path-fix-typo" class="btn-link btn-link-small hidden">Use suggested path</button></p> |
| 419 | <p id="full-path-similar-hint" class="muted small detail-project-hint hidden" role="status" aria-live="polite"></p> |
| 420 | <p style="margin: 0 0 0.5rem 0;"><button type="button" id="btn-full-path-use-similar-project" class="btn-link btn-link-small hidden">Use suggested project slug</button></p> |
| 421 | <label>Title</label> |
| 422 | <input type="text" id="full-title" placeholder="Note title"> |
| 423 | <label>Body (Markdown)</label> |
| 424 | <textarea id="full-body" rows="8" placeholder="Content…"></textarea> |
| 425 | <label>Date (optional)</label> |
| 426 | <input type="date" id="full-date" placeholder="YYYY-MM-DD"> |
| 427 | <label for="full-project">Project (optional)</label> |
| 428 | <input type="text" id="full-project" placeholder="slug" aria-describedby="full-project-field-intro"> |
| 429 | <p id="full-project-field-intro" class="muted small" style="margin-top: 0; margin-bottom: 0.35rem;">Frontmatter <code>project</code> for filters and charts. If your path starts with <code>projects/slug/</code>, this field follows that slug automatically.</p> |
| 430 | <p style="margin: 0 0 0.5rem 0;"><button type="button" id="btn-full-project-help" class="btn-link btn-link-small">How projects work</button></p> |
| 431 | <label>Tags (comma-separated)</label> |
| 432 | <input type="text" id="full-tags" placeholder="tag1, tag2"> |
| 433 | <p class="muted small" style="margin-top: 0.5rem;">Temporal and hierarchical (optional):</p> |
| 434 | <label>Causal chain ID</label> |
| 435 | <input type="text" id="full-causal-chain" placeholder="e.g. auth-decisions"> |
| 436 | <label>Entity (comma-separated)</label> |
| 437 | <input type="text" id="full-entity" placeholder="e.g. alice, auth"> |
| 438 | <label>Episode ID</label> |
| 439 | <input type="text" id="full-episode" placeholder="e.g. planning-2025-03"> |
| 440 | <label>Follows (vault path this note follows)</label> |
| 441 | <input type="text" id="full-follows" placeholder="e.g. inbox/prior-note.md"> |
| 442 | <button type="button" id="btn-full-save" class="btn-primary">Create note</button> |
| 443 | <p id="create-msg-full" class="create-msg"></p> |
| 444 | </div> |
| 445 | </div> |
| 446 | </div> |
| 447 | |
| 448 | <div id="modal-create-similar-project" class="modal hidden" aria-modal="true" role="dialog" aria-labelledby="modal-create-similar-project-title"> |
| 449 | <div class="modal-backdrop" id="modal-create-similar-project-backdrop"></div> |
| 450 | <div class="modal-card modal-card-narrow"> |
| 451 | <div class="modal-header"> |
| 452 | <h2 id="modal-create-similar-project-title">Similar project already exists</h2> |
| 453 | <button type="button" id="modal-create-similar-project-close" class="modal-close" aria-label="Close">×</button> |
| 454 | </div> |
| 455 | <div class="create-panel"> |
| 456 | <p id="modal-create-similar-project-body" class="muted small"></p> |
| 457 | <div class="modal-create-similar-actions" style="display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem;"> |
| 458 | <button type="button" id="btn-modal-create-similar-use-existing" class="btn-primary">Use existing</button> |
| 459 | <button type="button" id="btn-modal-create-similar-keep" class="btn-secondary">Keep my path</button> |
| 460 | </div> |
| 461 | </div> |
| 462 | </div> |
| 463 | </div> |
| 464 | |
| 465 | <div id="modal-create-proposal" class="modal hidden" aria-modal="true" role="dialog" aria-labelledby="modal-create-proposal-title"> |
| 466 | <div class="modal-backdrop" id="modal-create-proposal-backdrop"></div> |
| 467 | <div class="modal-card"> |
| 468 | <div class="modal-header"> |
| 469 | <h2 id="modal-create-proposal-title">New proposal</h2> |
| 470 | <button type="button" id="modal-create-proposal-close" class="modal-close" aria-label="Close">×</button> |
| 471 | </div> |
| 472 | <div class="create-panel"> |
| 473 | <p class="muted small" id="modal-create-proposal-hint">Submit a proposed file change for review (same as <code>POST /api/v1/proposals</code>). Admins approve in this tab.</p> |
| 474 | <label for="proposal-create-path">Path (vault-relative)</label> |
| 475 | <input type="text" id="proposal-create-path" placeholder="inbox/my-change.md" autocomplete="off" spellcheck="false" /> |
| 476 | <label for="proposal-create-intent">Intent (optional)</label> |
| 477 | <input type="text" id="proposal-create-intent" placeholder="e.g. Add section on rollout" autocomplete="off" /> |
| 478 | <label for="proposal-create-body">Proposed body (Markdown)</label> |
| 479 | <textarea id="proposal-create-body" rows="12" placeholder="Proposed note content…"></textarea> |
| 480 | <button type="button" id="btn-proposal-create-submit" class="btn-primary">Submit proposal</button> |
| 481 | <p id="proposal-create-msg" class="create-msg"></p> |
| 482 | </div> |
| 483 | </div> |
| 484 | </div> |
| 485 | |
| 486 | <div id="modal-import" class="modal hidden" aria-modal="true" role="dialog"> |
| 487 | <div class="modal-backdrop" id="modal-import-backdrop"></div> |
| 488 | <div class="modal-card"> |
| 489 | <div class="modal-header"> |
| 490 | <h2>Import into vault</h2> |
| 491 | <button type="button" id="modal-import-close" class="modal-close">×</button> |
| 492 | </div> |
| 493 | <div class="create-panel"> |
| 494 | <p class="muted small import-modal-lead">Pick a <strong>source type</strong>, then a URL and/or <strong>files</strong> (dashed area or <strong>Choose folder</strong>). <strong>Sign in</strong> first. <strong>~100 MB</strong> per request.</p> |
| 495 | <label for="import-source-type">Source type</label> |
| 496 | <select id="import-source-type"> |
| 497 | <option value="url">URL (https — article or bookmark)</option> |
| 498 | <option value="markdown">Markdown (file or folder)</option> |
| 499 | <option value="pdf">PDF (text extraction)</option> |
| 500 | <option value="docx">DOCX (Word → Markdown)</option> |
| 501 | <option value="chatgpt-export">ChatGPT export (ZIP or folder)</option> |
| 502 | <option value="claude-export">Claude export</option> |
| 503 | <option value="mem0-export">Mem0 export (JSON)</option> |
| 504 | <option value="mif">MIF (Memory Interchange Format)</option> |
| 505 | <option value="notebooklm">NotebookLM</option> |
| 506 | <option value="notion">Notion (API; page IDs)</option> |
| 507 | <option value="gdrive">Google Drive (Markdown folder)</option> |
| 508 | <option value="generic-csv">Generic CSV (one note per row)</option> |
| 509 | <option value="jira-export">Jira CSV export</option> |
| 510 | <option value="linear-export">Linear CSV export</option> |
| 511 | <option value="audio">Audio (transcribe)</option> |
| 512 | <option value="wallet-csv">Wallet / exchange CSV (transaction history)</option> |
| 513 | <option value="json-rows">JSON array (one object per note)</option> |
| 514 | <option value="excel-xlsx">Excel .xlsx (first sheet, one note per row)</option> |
| 515 | <option value="vcf">vCard / .vcf (contacts, one note per card)</option> |
| 516 | <option value="google-sheets">Google Sheets (API — id only, no file)</option> |
| 517 | </select> |
| 518 | <div id="import-sheets-block" class="import-sheets-block" hidden> |
| 519 | <label for="import-spreadsheet-id">Google Sheets — spreadsheet id (from the URL)</label> |
| 520 | <input type="text" id="import-spreadsheet-id" placeholder="Long id in sheets.google.com/d/…" autocomplete="off" spellcheck="false"> |
| 521 | <label for="import-sheets-range">Range (optional, A1 notation)</label> |
| 522 | <input type="text" id="import-sheets-range" placeholder="e.g. Sheet1!A1:E100 (omit for first tab A1:ZZ)"> |
| 523 | <p class="muted small" id="import-sheets-hint">No file upload. The bridge must have a Google service account; share the sheet with that account (Viewer). See <a href="https://github.com/aaronrene/knowtation/blob/main/docs/IMPORT-SOURCES.md" target="_blank" rel="noopener noreferrer">IMPORT-SOURCES</a>.</p> |
| 524 | </div> |
| 525 | <label for="import-url">Import from URL (https only)</label> |
| 526 | <input type="url" id="import-url" placeholder="https://example.com/article" autocomplete="off"> |
| 527 | <label for="import-url-mode">URL capture mode</label> |
| 528 | <select id="import-url-mode" aria-describedby="import-url-mode-hint"> |
| 529 | <option value="auto">Auto (extract article when possible)</option> |
| 530 | <option value="bookmark">Bookmark only (save link)</option> |
| 531 | <option value="extract">Extract only (fail if not readable HTML)</option> |
| 532 | </select> |
| 533 | <p id="import-url-mode-hint" class="muted small">Use <strong>Bookmark</strong> for paywalled or login-only pages. <strong>Extract</strong> requires readable HTML.</p> |
| 534 | <div |
| 535 | id="import-drop-zone" |
| 536 | class="import-drop-zone" |
| 537 | tabindex="0" |
| 538 | role="group" |
| 539 | aria-label="Drop files or a folder to import. Chromium recommended for full folder tree paths."> |
| 540 | <p class="import-drop-zone-text"><strong>Drop</strong> files or a <strong>folder</strong> here, or use the file picker below.</p> |
| 541 | <p id="import-drop-status" class="import-drop-status muted small" hidden></p> |
| 542 | </div> |
| 543 | <div class="import-file-row import-file-row-actions"> |
| 544 | <label for="import-file">File(s) or ZIP</label> |
| 545 | <p class="muted small">Multi-select or folder. See <strong>More</strong> under the form for batch limits.</p> |
| 546 | <input type="file" id="import-file" multiple accept=".md,.markdown,.json,.csv,.zip,.txt,.pdf,.doc,.docx,.xlsx,.vcf,.vcard,audio/*,video/*"> |
| 547 | <input type="file" id="import-file-folder" class="sr-only" tabindex="-1" webkitdirectory> |
| 548 | <div class="import-aux-btns"> |
| 549 | <button type="button" id="btn-import-choose-folder" class="btn-secondary" title="Pick a directory; the Hub can ZIP it in the browser for tree-shaped source types.">Choose folder (ZIP in browser)</button> |
| 550 | <button type="button" id="import-batch-cancel" class="btn-secondary hidden">Stop batch</button> |
| 551 | </div> |
| 552 | <p class="import-folder-hint muted small hidden" id="import-folder-hint">Folder selection will build one in-browser ZIP (folder-shaped source types only, not PDF/DOCX).</p> |
| 553 | </div> |
| 554 | <p id="import-batch-aria" class="sr-only" aria-live="polite" aria-atomic="true"></p> |
| 555 | <div id="import-create-path-block" class="create-path-group" role="group" aria-label="Import destination"> |
| 556 | <label for="import-create-project-slug"><strong class="create-label-em">Project</strong> in vault</label> |
| 557 | <select id="import-create-project-slug" class="settings-input-inline" style="width: 100%; max-width: 22rem; margin-bottom: 0.35rem;" aria-describedby="import-create-project-slug-hint"></select> |
| 558 | <p id="import-create-project-slug-hint" class="muted small" style="margin-top: 0; margin-bottom: 0.5rem;">Choose a <strong class="create-hint-em">Project</strong> or use <strong class="create-hint-em">Custom</strong> (type full path) for anything else.</p> |
| 559 | <div id="import-create-project-subroot-wrap" class="hidden"> |
| 560 | <label for="import-create-project-subroot">Subfolder under project</label> |
| 561 | <select id="import-create-project-subroot" class="settings-input-inline" style="width: 100%; max-width: 22rem; margin-bottom: 0.35rem;" aria-describedby="import-create-project-subroot-hint"></select> |
| 562 | <p id="import-create-project-subroot-hint" class="muted small" style="margin-top: 0; margin-bottom: 0.5rem;">Choose a subfolder or use <strong class="create-hint-em">Custom</strong> to type any path.</p> |
| 563 | </div> |
| 564 | <div id="import-nonproject-folder-wrap"> |
| 565 | <label for="import-vault-folder"><strong class="create-label-em">Folder</strong> in vault (when not using a project above)</label> |
| 566 | <select id="import-vault-folder" class="settings-input-inline" style="width: 100%; max-width: 22rem; margin-bottom: 0.35rem;" aria-describedby="import-vault-folder-hint"></select> |
| 567 | <p id="import-vault-folder-hint" class="muted small" style="margin-top: 0; margin-bottom: 0.5rem;">Choose a <strong class="create-hint-em">Folder</strong> on this vault. Pick <strong class="create-hint-em">Custom</strong> to type any path.</p> |
| 568 | </div> |
| 569 | <label for="import-output-dir"><strong class="create-label-em">Path</strong> (vault-relative)</label> |
| 570 | <input type="text" id="import-output-dir" placeholder="inbox or projects/my-slug/inbox" autocomplete="off" spellcheck="false" aria-describedby="import-output-dir-caption"> |
| 571 | <p id="import-output-dir-caption" class="muted small" style="margin-top: 0.15rem; margin-bottom: 0.35rem;">Choose ‘Custom’ in <strong class="create-hint-em">Project</strong>, <strong class="create-hint-em">Folder</strong>, or <strong class="create-hint-em">Path</strong> to change your final path.</p> |
| 572 | </div> |
| 573 | <label for="import-tags">Tags (comma-separated, optional)</label> |
| 574 | <input type="text" id="import-tags" placeholder="tag1, tag2"> |
| 575 | <details class="modal-projects-help-details import-modal-help" id="import-modal-help"> |
| 576 | <summary>More: folder/ZIP, multi-file, PDF, audio, and hosted</summary> |
| 577 | <p class="small muted">Tree-style source types (e.g. <strong>Markdown</strong>, <strong>ChatGPT</strong>, many exports) can use a <code>.zip</code>, the <strong>drop</strong> zone, <strong>Choose folder</strong> (in-browser ZIP), or multi-file. <strong>PDF</strong> and <strong>DOCX</strong> are <em>one file per import</em> (use multiple files for many documents). <strong>Audio</strong> needs a transcribe-capable Hub; <strong>~25 MB</strong> per file for OpenAI. <strong>Video</strong> is not in this dialog; use the CLI.</p> |
| 578 | <p class="small muted"><strong>Hosted</strong> import needs the operator to set <code>BRIDGE_URL</code> on the gateway. If you see that import is unavailable, ask your host or use self-hosted Hub. Full options and limits: <a href="https://github.com/aaronrene/knowtation/blob/main/docs/IMPORT-SOURCES.md" target="_blank" rel="noopener noreferrer">IMPORT-SOURCES</a>.</p> |
| 579 | </details> |
| 580 | <button type="button" id="btn-import-submit" class="btn-primary">Import</button> |
| 581 | <p id="import-msg" class="create-msg"></p> |
| 582 | </div> |
| 583 | </div> |
| 584 | </div> |
| 585 | |
| 586 | <div id="modal-onboarding" class="modal hidden" aria-modal="true" role="dialog" aria-labelledby="onboarding-title" aria-describedby="onboarding-live"> |
| 587 | <div class="modal-backdrop" id="modal-onboarding-backdrop"></div> |
| 588 | <div class="modal-card modal-onboarding-card"> |
| 589 | <div class="modal-header"> |
| 590 | <h2 id="onboarding-title">Get started</h2> |
| 591 | <button type="button" id="modal-onboarding-close" class="modal-close" aria-label="Close">×</button> |
| 592 | </div> |
| 593 | <div id="onboarding-progress" class="onboarding-progress" aria-label="Progress"></div> |
| 594 | <div id="onboarding-step-body" class="onboarding-step-body"></div> |
| 595 | <p id="onboarding-live" class="sr-only" aria-live="polite"></p> |
| 596 | <div id="onboarding-secondary-actions" class="onboarding-secondary-actions"></div> |
| 597 | <div class="onboarding-footer"> |
| 598 | <button type="button" id="btn-onboarding-skip" class="btn-link">Skip for now</button> |
| 599 | <div class="onboarding-nav"> |
| 600 | <button type="button" id="btn-onboarding-back" class="btn-secondary">Back</button> |
| 601 | <button type="button" id="btn-onboarding-next" class="btn-primary">Next</button> |
| 602 | </div> |
| 603 | </div> |
| 604 | <p class="onboarding-resume-hint muted small"><strong>Prefer an AI assistant?</strong> <a href="https://github.com/aaronrene/knowtation/blob/main/docs/AI-ASSISTED-SETUP.md" target="_blank" rel="noopener">AI-assisted setup</a> — phased, copy-paste prompts for Cursor, Windsurf, and similar tools.</p> |
| 605 | </div> |
| 606 | </div> |
| 607 | |
| 608 | <div id="modal-projects-help" class="modal hidden" aria-modal="true" role="dialog" aria-labelledby="modal-projects-help-title"> |
| 609 | <div class="modal-backdrop" id="modal-projects-help-backdrop"></div> |
| 610 | <div class="modal-card modal-card-projects-help"> |
| 611 | <div class="modal-header"> |
| 612 | <h2 id="modal-projects-help-title">Projects on hosted Knowtation</h2> |
| 613 | <button type="button" id="modal-projects-help-close" class="modal-close" aria-label="Close">×</button> |
| 614 | </div> |
| 615 | <div class="modal-projects-help-body"> |
| 616 | <p style="margin-top:0;">On hosted Knowtation, a <strong>project</strong> is just a name you put on your notes so they stay grouped together.</p> |
| 617 | <p><strong>To start a project:</strong> create a note (for example with <strong>+ New note</strong>) and add a <strong>project name</strong> on that note. That first note starts the project. Add the same project name on other notes to keep them in the same group.</p> |
| 618 | <p class="small muted" style="margin-bottom:0;">The name then shows up in the <strong>project</strong> menu and in quick filter chips. It is not a folder path like on self-hosted.</p> |
| 619 | <details class="modal-projects-help-details" style="margin-top: 0.75rem;"> |
| 620 | <summary>Self-hosted: path <code>projects/</code> vs field <code>project</code></summary> |
| 621 | <p class="small muted">On disk, many vaults group files under <code>projects/<slug>/…</code> (note the plural <strong>projects</strong>). In the Hub, if a note’s path starts with <code>projects/<slug>/</code>, the <strong>Project</strong> field stays aligned with that folder name on save.</p> |
| 622 | <p class="small muted">You can also set <code>project</code> in frontmatter on notes anywhere (for example <code>inbox/idea.md</code>) — that label is for filters and charts and does not create a folder. A common typo is typing <code>project/…</code> instead of <code>projects/…</code> in the path; the Hub warns you when that happens.</p> |
| 623 | </details> |
| 624 | <details class="modal-projects-help-details"> |
| 625 | <summary>Technical: YAML <code>project</code> field</summary> |
| 626 | <p class="small muted">In the note editor, the project is stored as a <code>project</code> field in the YAML block at the top of the file (frontmatter). Example:</p> |
| 627 | <pre>--- |
| 628 | project: my-team |
| 629 | title: Kickoff |
| 630 | --- |
| 631 | |
| 632 | Your note body here.</pre> |
| 633 | </details> |
| 634 | </div> |
| 635 | </div> |
| 636 | </div> |
| 637 | |
| 638 | <div id="modal-settings" class="modal hidden" aria-modal="true" role="dialog" aria-labelledby="settings-title"> |
| 639 | <div class="modal-backdrop" id="modal-settings-backdrop"></div> |
| 640 | <div class="modal-card modal-card-settings"> |
| 641 | <div class="modal-header"> |
| 642 | <h2 id="settings-title">Settings</h2> |
| 643 | <div class="modal-header-actions"> |
| 644 | <button type="button" id="btn-settings-help" class="btn-link btn-link-small" aria-label="Open How to use">How to use</button> |
| 645 | <button type="button" id="modal-settings-close" class="modal-close" aria-label="Close">×</button> |
| 646 | </div> |
| 647 | </div> |
| 648 | <nav class="settings-tabs" role="tablist" aria-label="Settings sections"> |
| 649 | <button type="button" class="settings-tab active" role="tab" aria-selected="true" data-settings-tab="backup">Backup</button> |
| 650 | <button type="button" class="settings-tab hidden" id="settings-tab-team" role="tab" aria-selected="false" data-settings-tab="team">Team</button> |
| 651 | <button type="button" class="settings-tab hidden" id="settings-tab-vaults" role="tab" aria-selected="false" data-settings-tab="vaults">Vaults</button> |
| 652 | <button type="button" class="settings-tab" role="tab" aria-selected="false" data-settings-tab="integrations">Integrations</button> |
| 653 | <button type="button" class="settings-tab" role="tab" aria-selected="false" data-settings-tab="appearance">Appearance</button> |
| 654 | <button type="button" class="settings-tab" role="tab" aria-selected="false" data-settings-tab="billing">Billing</button> |
| 655 | <button type="button" class="settings-tab" role="tab" aria-selected="false" data-settings-tab="consolidation">Consolidation</button> |
| 656 | </nav> |
| 657 | <div id="settings-panel-backup" class="settings-panel active" role="tabpanel"> |
| 658 | <div class="settings-body"> |
| 659 | <p class="settings-intro"><strong>Hosted users:</strong> we keep your notes in the cloud; GitHub is an <em>optional</em> copy so you “own the repo” and have history. <strong>Self-hosted users:</strong> the vault is a folder on this machine, and the same screen wires Git. Status below always shows <strong>Mode</strong> so you know which world you are in.</p> |
| 660 | <h3 class="settings-h3">Setup checklist</h3> |
| 661 | <p class="settings-intro small">Get from zero to using the Hub and (optionally) backing up. Complete each step; optional steps can be skipped.</p> |
| 662 | <p class="settings-intro small"><button type="button" id="btn-settings-setup-guide" class="btn-link btn-link-small">Setup guide</button> — short walkthrough (hosted and self-hosted).</p> |
| 663 | <ul class="setup-checklist" aria-label="Setup progress"> |
| 664 | <li id="setup-step-1" class="setup-step"> |
| 665 | <span class="setup-step-icon" aria-hidden="true"></span> |
| 666 | <span id="setup-step-1-label" class="setup-step-label">Vault path set</span> |
| 667 | <span id="setup-step-1-hint" class="setup-step-hint">Set below under Configure backup</span> |
| 668 | </li> |
| 669 | <li id="setup-step-2" class="setup-step setup-step-done"> |
| 670 | <span class="setup-step-icon" aria-hidden="true">✓</span> |
| 671 | <span class="setup-step-label">Hub is running</span> |
| 672 | <span class="setup-step-hint">You’re here</span> |
| 673 | </li> |
| 674 | <li id="setup-step-3" class="setup-step setup-step-done"> |
| 675 | <span class="setup-step-icon" aria-hidden="true">✓</span> |
| 676 | <span class="setup-step-label">Logged in</span> |
| 677 | <span class="setup-step-hint">You’re here</span> |
| 678 | </li> |
| 679 | <li id="setup-step-4" class="setup-step"> |
| 680 | <span class="setup-step-icon" aria-hidden="true"></span> |
| 681 | <span class="setup-step-label">Backup configured (optional)</span> |
| 682 | <span class="setup-step-hint">Git enabled + remote below; then Connect GitHub and Back up now</span> |
| 683 | </li> |
| 684 | </ul> |
| 685 | <hr class="settings-hr"> |
| 686 | <div class="settings-two-paths-intro" role="region" aria-label="Two options"> |
| 687 | <p class="settings-intro small"><strong>At a glance:</strong> <strong>Hosted (beta)</strong> — “Canister” in the Vault line means cloud-stored; optional GitHub export. <strong>Self-hosted</strong> — Vault line shows a disk path. Admins: expand <em>How to connect backup</em> for the Git path + remote you maintain.</p> |
| 688 | </div> |
| 689 | <h3 class="settings-h3">Status</h3> |
| 690 | <p class="settings-intro small">Current vault and backup state.</p> |
| 691 | <div class="settings-row"> |
| 692 | <span class="settings-label">Your role</span> |
| 693 | <span id="settings-role-display" class="settings-value">—</span> |
| 694 | </div> |
| 695 | <div class="settings-row"> |
| 696 | <span class="settings-label">Your user ID</span> |
| 697 | <span id="settings-user-id-wrap" class="settings-value-wrap"> |
| 698 | <code id="settings-user-id" class="settings-code">—</code> |
| 699 | <button type="button" id="btn-copy-user-id" class="btn-copy-small" title="Copy">Copy</button> |
| 700 | </span> |
| 701 | </div> |
| 702 | <p class="settings-intro small" id="settings-user-id-hint">Admins set roles in <strong>Team</strong>. Your ID is <em>provider:id</em> (e.g. <code>google:…</code>) — it is <strong>not</strong> your email.</p> |
| 703 | <details class="settings-json-details"> |
| 704 | <summary class="settings-json-details-summary">Self-hosted — optional roles on disk</summary> |
| 705 | <p class="settings-intro small" style="margin:0.5rem 0 0;">Some installs also read <code>data/hub_roles.json</code>.</p> |
| 706 | </details> |
| 707 | <div class="settings-row"> |
| 708 | <span class="settings-label">Mode</span> |
| 709 | <span id="settings-mode-display" class="settings-value">—</span> |
| 710 | </div> |
| 711 | <div class="settings-row"> |
| 712 | <span class="settings-label">Vault</span> |
| 713 | <span id="settings-vault-display" class="settings-value">—</span> |
| 714 | </div> |
| 715 | <div class="settings-row"> |
| 716 | <span class="settings-label">Git backup</span> |
| 717 | <span id="settings-git-status" class="settings-value">—</span> |
| 718 | </div> |
| 719 | <div class="settings-row" id="settings-proposal-eval-row"> |
| 720 | <span class="settings-label">Proposal evaluation gate</span> |
| 721 | <span id="settings-proposal-eval-required" class="settings-value">—</span> |
| 722 | </div> |
| 723 | <div class="settings-row" id="settings-proposal-hints-row"> |
| 724 | <span class="settings-label">Review hints (LLM)</span> |
| 725 | <span id="settings-proposal-hints-enabled" class="settings-value">—</span> |
| 726 | </div> |
| 727 | <div class="settings-row" id="settings-proposal-enrich-row"> |
| 728 | <span class="settings-label">Proposal enrich (LLM)</span> |
| 729 | <span id="settings-proposal-enrich-enabled" class="settings-value">—</span> |
| 730 | </div> |
| 731 | <div class="settings-row" id="settings-evaluator-approve-row"> |
| 732 | <span class="settings-label">You may approve proposals</span> |
| 733 | <span id="settings-evaluator-may-approve" class="settings-value">—</span> |
| 734 | </div> |
| 735 | <div id="settings-proposal-policy-admin" class="settings-form settings-form-compact hidden" role="region" aria-label="Proposal policy (admin)"> |
| 736 | <p class="settings-intro small"><strong>Admins:</strong> Turn proposal features on or off here when they are not forced by server environment variables (disabled checkboxes are env-locked on the host).</p> |
| 737 | <label class="settings-check-row" style="display: flex; align-items: center; gap: 0.5rem; margin: 0.35rem 0;"><input type="checkbox" id="settings-policy-eval" /> <span>Require evaluation before approve (gate)</span></label> |
| 738 | <label class="settings-check-row" style="display: flex; align-items: center; gap: 0.5rem; margin: 0.35rem 0;"><input type="checkbox" id="settings-policy-hints" /> <span>Review hints after new proposals (LLM)</span></label> |
| 739 | <label class="settings-check-row" style="display: flex; align-items: center; gap: 0.5rem; margin: 0.35rem 0;"><input type="checkbox" id="settings-policy-enrich" /> <span>Allow Enrich (summary + suggested labels)</span></label> |
| 740 | <div class="settings-proposal-policy-actions"> |
| 741 | <button type="button" id="btn-proposal-policy-save" class="btn-primary btn-proposal-policy-save">Save proposal policy</button> |
| 742 | <span id="settings-proposal-policy-msg" class="settings-msg" role="status"></span> |
| 743 | </div> |
| 744 | </div> |
| 745 | <div id="settings-proposal-eval-explainer" class="settings-proposal-eval-explainer-block"> |
| 746 | <p class="settings-intro small"><strong>Proposal review:</strong> Suggested edits from people or tools wait in the <strong>Suggested</strong> tab. When the <strong>evaluation gate</strong> is on, a reviewer records pass / fail / needs work before (most) approves. <strong>Review hints</strong> and <strong>Enrich</strong> are optional assistive text — never merge gates, and on some hosts proposal text is sent to a model. <strong>Evaluator may approve</strong> is set in <strong>Team</strong> and shown in Status. More context: <strong>How to use</strong> → <strong>Knowledge & agents</strong> and <code>docs/TEAMS-AND-COLLABORATION.md</code>.</p> |
| 747 | <details class="settings-json-details"> |
| 748 | <summary class="settings-json-details-summary">Technical details — env and file locations</summary> |
| 749 | <p class="settings-intro small" style="margin:0.5rem 0 0;"><strong>Grade</strong> is for your records only. <strong>Evaluator fallback:</strong> server may use <code>HUB_EVALUATOR_MAY_APPROVE=1</code> if no per-user flag exists. <strong>Self-hosted files:</strong> <code>data/hub_evaluator_may_approve.json</code>, <code>data/hub_proposal_policy.json</code>. Greyed checkboxes in policy usually mean the host set <code>HUB_PROPOSAL_*</code> or <code>KNOWTATION_HUB_PROPOSAL_*</code> environment variables.</p> |
| 750 | </details> |
| 751 | </div> |
| 752 | <div class="settings-row hidden" id="settings-api-base-row" title="Shown on localhost for self-hosted debugging"> |
| 753 | <span class="settings-label">API base</span> |
| 754 | <span class="settings-value"><code id="settings-api-base-display" class="settings-code">—</code></span> |
| 755 | </div> |
| 756 | <div class="settings-row settings-github-connect-row" id="settings-github-connect-row"> |
| 757 | <span class="settings-label">GitHub</span> |
| 758 | <span id="settings-github-status" class="settings-value">—</span> |
| 759 | <button type="button" id="btn-connect-github" class="btn-primary hidden">Connect GitHub</button> |
| 760 | </div> |
| 761 | <p class="settings-intro small hidden" id="settings-hosted-connect-github-hint">Connects in <strong>this browser tab</strong> (you may leave Settings). Each signed-in user authorizes their own GitHub account for pushes. You need an empty GitHub repo and its <code>owner/repo</code> in the field below before <strong>Back up now</strong>.</p> |
| 762 | <div id="settings-hosted-backup-repo-section" class="settings-hosted-repo-block hidden" role="region" aria-label="Hosted backup repository"> |
| 763 | <p class="settings-intro small">For <strong>hosted</strong> backup, enter the GitHub repository as <code>owner/repo</code>. A <strong>brand-new empty</strong> repo (no README yet) is fine — the first <strong>Back up now</strong> creates the initial commit. This is sent with <strong>Back up now</strong>; after a successful push the repo is remembered for next time.</p> |
| 764 | <div class="settings-form settings-form-compact"> |
| 765 | <label for="settings-hosted-repo">Backup repo <span class="settings-label-hint">(owner/repo-name)</span></label> |
| 766 | <input type="text" id="settings-hosted-repo" placeholder="e.g. myuser/my-notes" autocomplete="off"> |
| 767 | </div> |
| 768 | </div> |
| 769 | <div class="settings-actions"> |
| 770 | <button type="button" id="btn-settings-sync" class="btn-primary" disabled title="Self-hosted: vault folder must be a Git repo (git init). Connect GitHub stores a push token only.">Back up now</button> |
| 771 | <button type="button" id="btn-vault-git-init" class="btn-secondary hidden" title="Run git init in the current vault folder (self-hosted only)">Initialize Git in this vault</button> |
| 772 | <span id="settings-sync-msg" class="settings-msg"></span> |
| 773 | <p class="settings-intro small" style="margin-top: 0.5rem;">Back up now backs up the <strong>currently selected vault</strong> (use the Vault dropdown in the header to switch). Each vault can have its own Git remote.</p> |
| 774 | <p class="settings-intro small"><strong>Self-hosted:</strong> <em>Connect GitHub</em> saves a token so pushes can authenticate — it does <em>not</em> run <code>git init</code> in your vault. If backup says the folder is not a Git repo, click <strong>Initialize Git in this vault</strong> (appears after a failed backup) or run <code>git init</code> manually in that folder.</p> |
| 775 | </div> |
| 776 | <div id="settings-danger-zone-panel" class="hidden" style="margin-top: 1.25rem; padding: 1rem; border: 1px solid color-mix(in srgb, var(--err, #c44) 35%, transparent); border-radius: 8px; background: color-mix(in srgb, var(--err, #c44) 8%, transparent);"> |
| 777 | <h3 class="settings-h3">Danger zone</h3> |
| 778 | <p class="settings-intro small">These actions <strong>permanently remove</strong> data from Knowtation. There is no undo.</p> |
| 779 | <div id="settings-danger-zone-projects" role="region" aria-label="Project bulk operations"> |
| 780 | <h4 class="settings-h4">Projects</h4> |
| 781 | <p class="settings-intro small"><strong>Path prefix</strong> is the note’s <strong>file path</strong> in the vault (same string as in <code>POST /notes</code>), not the Hub <strong>Project</strong> filter. Example: notes in <code>inbox/foo.md</code> match prefix <code>inbox</code>, not your frontmatter <code>project:</code> slug. On hosted (canister), paths are still stored strings — there is no disk folder, but the rule is the same.</p> |
| 782 | <p class="settings-intro small"><strong>Delete by project slug</strong> removes every note whose <strong>effective project</strong> matches (frontmatter <code>project:</code> and/or path under <code>projects/<slug>/</code>, same as list/search). <strong>Rename project</strong> and delete-by-project slug run on <strong>hosted</strong> (gateway) and self-hosted Hub. <strong>Delete by path prefix</strong> below needs the Node Hub with a filesystem vault — not the hosted gateway. See <code>docs/HUB-METADATA-BULK-OPS.md</code>.</p> |
| 783 | <div class="settings-form-row" style="display: flex; flex-wrap: wrap; gap: 0.75rem 1rem; align-items: flex-end; margin-top: 0.5rem;"> |
| 784 | <div style="min-width: 14rem; max-width: 100%;"> |
| 785 | <label for="settings-bulk-path-prefix-preset">Path prefix</label> |
| 786 | <select id="settings-bulk-path-prefix-preset" class="settings-input-inline" style="display: block; width: 100%; max-width: 22rem; margin-bottom: 0.35rem;" aria-describedby="settings-bulk-path-hint"></select> |
| 787 | <input type="text" id="settings-delete-prefix" class="settings-input-inline" placeholder="e.g. inbox or projects/acme" autocomplete="off" spellcheck="false" style="width: 100%; max-width: 22rem;"> |
| 788 | <p id="settings-bulk-path-hint" class="muted small" style="margin: 0.25rem 0 0 0;">Pick from disk + note paths, or choose Custom and type the exact prefix.</p> |
| 789 | </div> |
| 790 | <div> |
| 791 | <label for="settings-delete-confirm">Type DELETE to confirm</label> |
| 792 | <input type="text" id="settings-delete-confirm" class="settings-input-inline" placeholder="DELETE" autocomplete="off" spellcheck="false" style="min-width: 7rem;"> |
| 793 | </div> |
| 794 | <button type="button" id="btn-settings-delete-prefix" class="btn-secondary" style="border-color: var(--err, #c44); color: var(--err, #c44);">Delete by path prefix</button> |
| 795 | </div> |
| 796 | <span id="settings-delete-prefix-msg" class="settings-msg" role="status"></span> |
| 797 | <div id="settings-bulk-metadata-self-only"> |
| 798 | <div class="settings-form-row" style="display: flex; flex-wrap: wrap; gap: 0.75rem 1rem; align-items: flex-end; margin-top: 1rem; padding-top: 1rem; border-top: 1px solid color-mix(in srgb, var(--border, #444) 60%, transparent);"> |
| 799 | <div style="min-width: 14rem; max-width: 100%;"> |
| 800 | <label for="settings-bulk-delete-project-preset">Project slug (metadata)</label> |
| 801 | <select id="settings-bulk-delete-project-preset" class="settings-input-inline" style="display: block; width: 100%; max-width: 22rem; margin-bottom: 0.35rem;" aria-describedby="settings-bulk-project-delete-hint"></select> |
| 802 | <input type="text" id="settings-delete-project-slug" class="settings-input-inline" placeholder="e.g. delete-project" autocomplete="off" spellcheck="false" style="width: 100%; max-width: 22rem;"> |
| 803 | <p id="settings-bulk-project-delete-hint" class="muted small" style="margin: 0.25rem 0 0 0;">Projects from this vault’s notes (facets). Custom if yours is not listed.</p> |
| 804 | </div> |
| 805 | <div> |
| 806 | <label for="settings-delete-project-confirm">Type DELETE to confirm</label> |
| 807 | <input type="text" id="settings-delete-project-confirm" class="settings-input-inline" placeholder="DELETE" autocomplete="off" spellcheck="false" style="min-width: 7rem;"> |
| 808 | </div> |
| 809 | <button type="button" id="btn-settings-delete-by-project" class="btn-secondary" style="border-color: var(--err, #c44); color: var(--err, #c44);">Delete all notes in this project</button> |
| 810 | </div> |
| 811 | <span id="settings-delete-by-project-msg" class="settings-msg" role="status"></span> |
| 812 | <div class="settings-form-row" style="display: flex; flex-wrap: wrap; gap: 0.75rem 1rem; align-items: flex-end; margin-top: 1rem; padding-top: 1rem; border-top: 1px solid color-mix(in srgb, var(--border, #444) 60%, transparent);"> |
| 813 | <div style="min-width: 14rem; max-width: 100%;"> |
| 814 | <label for="settings-bulk-rename-from-preset">Rename project: from slug</label> |
| 815 | <select id="settings-bulk-rename-from-preset" class="settings-input-inline" style="display: block; width: 100%; max-width: 22rem; margin-bottom: 0.35rem;" aria-describedby="settings-bulk-rename-from-hint"></select> |
| 816 | <input type="text" id="settings-rename-project-from" class="settings-input-inline" placeholder="old-slug" autocomplete="off" spellcheck="false" style="width: 100%; max-width: 22rem;"> |
| 817 | <p id="settings-bulk-rename-from-hint" class="muted small" style="margin: 0.25rem 0 0 0;">Same project list as above. <strong>To slug</strong> is still typed (new name).</p> |
| 818 | </div> |
| 819 | <div> |
| 820 | <label for="settings-rename-project-to">To slug</label> |
| 821 | <input type="text" id="settings-rename-project-to" class="settings-input-inline" placeholder="new-slug" autocomplete="off" spellcheck="false" style="min-width: 10rem;"> |
| 822 | </div> |
| 823 | <div> |
| 824 | <label for="settings-rename-project-confirm">Type RENAME to confirm</label> |
| 825 | <input type="text" id="settings-rename-project-confirm" class="settings-input-inline" placeholder="RENAME" autocomplete="off" spellcheck="false" style="min-width: 7rem;"> |
| 826 | </div> |
| 827 | <button type="button" id="btn-settings-rename-project" class="btn-secondary">Rewrite project slug (frontmatter)</button> |
| 828 | </div> |
| 829 | <span id="settings-rename-project-msg" class="settings-msg" role="status"></span> |
| 830 | <p class="settings-intro small muted" style="margin-top: 0.5rem;">Path-prefix and project-slug deletes discard matching <strong>proposed</strong> proposals (same vault). Rename-project only updates YAML frontmatter <code>project:</code>; it does not move files between folders. On hosted, the gateway runs these against your canister vault (same effective-project rules as list/search).</p> |
| 831 | </div> |
| 832 | </div> |
| 833 | <div id="settings-danger-zone-vault" class="hidden" role="region" aria-label="Delete vault" style="margin-top: 1.25rem; padding-top: 1.25rem; border-top: 1px solid color-mix(in srgb, var(--border, #444) 60%, transparent);"> |
| 834 | <h4 class="settings-h4">Vault</h4> |
| 835 | <p class="settings-intro small"><strong>Deleting a vault</strong> removes <strong>everything</strong> stored in that notebook: all notes, project labels and paths, media and other files in that vault, and related Hub data (including search index entries for that vault). The <strong>default</strong> vault cannot be deleted. This does <em>not</em> delete your GitHub backup repository — only the copy Knowtation holds.</p> |
| 836 | <div class="settings-form-row" style="display: flex; flex-wrap: wrap; gap: 0.75rem 1rem; align-items: flex-end; margin-top: 0.5rem;"> |
| 837 | <div style="min-width: 14rem; max-width: 100%;"> |
| 838 | <label for="settings-delete-vault-select">Vault to delete</label> |
| 839 | <select id="settings-delete-vault-select" class="settings-input-inline" style="display: block; width: 100%; max-width: 22rem;" aria-describedby="settings-delete-vault-hint"></select> |
| 840 | <p id="settings-delete-vault-hint" class="muted small" style="margin: 0.25rem 0 0 0;">Only non-default vaults are listed. Self-hosted: admins only. Hosted: same rules as creating a new cloud vault (workspace owner when a shared workspace is set).</p> |
| 841 | </div> |
| 842 | <div> |
| 843 | <label for="settings-delete-vault-confirm">Type DELETE VAULT to confirm</label> |
| 844 | <input type="text" id="settings-delete-vault-confirm" class="settings-input-inline" placeholder="DELETE VAULT" autocomplete="off" spellcheck="false" style="min-width: 9rem;"> |
| 845 | </div> |
| 846 | <button type="button" id="btn-settings-delete-vault" class="btn-secondary" style="border-color: var(--err, #c44); color: var(--err, #c44);">Delete vault permanently</button> |
| 847 | </div> |
| 848 | <span id="settings-delete-vault-msg" class="settings-msg" role="status"></span> |
| 849 | </div> |
| 850 | </div> |
| 851 | <hr class="settings-hr" id="settings-hr-configure"> |
| 852 | <div id="settings-configure-backup-section"> |
| 853 | <h3 class="settings-h3">How to connect backup</h3> |
| 854 | <p class="settings-intro small">To turn on Git backup, follow these steps:</p> |
| 855 | <ol class="settings-steps-list"> |
| 856 | <li>Create a new repository on GitHub. <strong>Leave it empty</strong> (do not add README, .gitignore, or license). Use the <strong>HTTPS</strong> URL (e.g. <code>https://github.com/you/repo-name.git</code>) so Connect GitHub can push; private is recommended for notes.</li> |
| 857 | <li>Ensure your vault folder is a Git repo. With the default path <code>./vault</code>, run once from project root: <code>cd vault && git init && git add -A && git commit -m "Initial vault"</code>. If you use a different folder that is already a Git repo, skip this.</li> |
| 858 | <li>Below, check <em>Git backup enabled</em> and paste that repo’s URL into <em>Git remote URL</em>.</li> |
| 859 | <li>Click <strong>Save setup</strong>. Optionally click <strong>Connect GitHub</strong> (under Status) so the Hub can push with your token. Then use <strong>Back up now</strong>.</li> |
| 860 | </ol> |
| 861 | <p class="settings-intro small" id="settings-setup-admin-hint">Only admins can save setup. Your role is shown under Status above.</p> |
| 862 | <p class="settings-intro small">Changes are saved to <code>data/hub_setup.yaml</code> and applied immediately. Vault path can be absolute or relative to the project root.</p> |
| 863 | <div class="settings-form"> |
| 864 | <label for="setup-vault-path">Vault path</label> |
| 865 | <input type="text" id="setup-vault-path" placeholder="e.g. ./vault or /path/to/vault"> |
| 866 | <label class="settings-checkbox-label"><input type="checkbox" id="setup-git-enabled"> Git backup enabled</label> |
| 867 | <label for="setup-git-remote">Git remote URL <span class="settings-label-hint">(paste the repo you created on GitHub)</span></label> |
| 868 | <input type="text" id="setup-git-remote" placeholder="https://github.com/you/your-repo.git"> |
| 869 | <div class="settings-form-actions"> |
| 870 | <button type="button" id="btn-settings-save" class="btn-primary">Save setup</button> |
| 871 | <span id="settings-save-msg" class="settings-msg"></span> |
| 872 | </div> |
| 873 | </div> |
| 874 | </div> |
| 875 | </div> |
| 876 | </div> |
| 877 | <div id="settings-panel-team" class="settings-panel" role="tabpanel"> |
| 878 | <div class="settings-body"> |
| 879 | <p class="settings-intro">Team lets you invite others and set roles (viewer, editor, admin, evaluator). Only admins see this tab. Use User ID or invite links to connect teammates.</p> |
| 880 | <h3 class="settings-h3">How to add someone</h3> |
| 881 | <p class="settings-intro small">Add a user by their <strong>User ID</strong> (e.g. <code>github:12345</code>). They find it in their own Settings → Backup under "Your user ID" — they copy it and send it to you.</p> |
| 882 | <div class="settings-form"> |
| 883 | <label for="team-user-id">User ID</label> |
| 884 | <input type="text" id="team-user-id" placeholder="e.g. github:12345678"> |
| 885 | <div class="settings-form-actions" style="margin: 0.35rem 0 0.5rem;"> |
| 886 | <button type="button" id="btn-team-user-use-me" class="btn-secondary">Use my User ID</button> |
| 887 | </div> |
| 888 | <label for="team-role">Role</label> |
| 889 | <select id="team-role"> |
| 890 | <option value="viewer">Viewer (read only)</option> |
| 891 | <option value="editor">Editor (read, write, propose)</option> |
| 892 | <option value="evaluator">Evaluator (evaluate proposals; optional per-user approve below)</option> |
| 893 | <option value="admin">Admin (full access)</option> |
| 894 | </select> |
| 895 | <label id="team-add-evaluator-may-approve-wrap" class="hidden team-evaluator-approve-add"> |
| 896 | <input type="checkbox" id="team-add-evaluator-may-approve" /> |
| 897 | <span>May approve proposals (for this user when role is Evaluator)</span> |
| 898 | </label> |
| 899 | <div class="settings-form-actions"> |
| 900 | <button type="button" id="btn-team-save" class="btn-primary">Add / update role</button> |
| 901 | <span id="team-save-msg" class="settings-msg"></span> |
| 902 | </div> |
| 903 | </div> |
| 904 | <h4 class="settings-h4">How to invite by link</h4> |
| 905 | <p class="settings-intro small">Create a link to invite someone. They sign in with Google or GitHub and get the role you choose. Link expires in 7 days. Share the link; they open it, sign in, and are added.</p> |
| 906 | <div class="settings-form"> |
| 907 | <label for="invite-role">Role for invite</label> |
| 908 | <select id="invite-role"> |
| 909 | <option value="viewer">Viewer (read only)</option> |
| 910 | <option value="editor">Editor (read, write, propose)</option> |
| 911 | <option value="evaluator">Evaluator (evaluate proposals)</option> |
| 912 | <option value="admin">Admin (full access)</option> |
| 913 | </select> |
| 914 | <div class="settings-form-actions"> |
| 915 | <button type="button" id="btn-invite-create" class="btn-primary">Create invite link</button> |
| 916 | <span id="invite-create-msg" class="settings-msg"></span> |
| 917 | </div> |
| 918 | <div id="invite-link-block" class="invite-link-block hidden"> |
| 919 | <label class="settings-label-hint">Link (copy and share)</label> |
| 920 | <div class="invite-link-row"> |
| 921 | <input type="text" id="invite-link-url" readonly class="invite-link-input"> |
| 922 | <button type="button" id="btn-invite-copy" class="btn-secondary">Copy</button> |
| 923 | </div> |
| 924 | </div> |
| 925 | </div> |
| 926 | <h4 class="settings-h4">Pending invites</h4> |
| 927 | <div id="invites-pending-list" class="team-roles-list muted small">Loading…</div> |
| 928 | <h4 class="settings-h4">Current roles</h4> |
| 929 | <div id="team-roles-list" class="team-roles-list muted small">Loading…</div> |
| 930 | </div> |
| 931 | </div> |
| 932 | <div id="settings-panel-vaults" class="settings-panel" role="tabpanel"> |
| 933 | <div class="settings-body"> |
| 934 | <div class="settings-vaults-lead-row"> |
| 935 | <p class="settings-vaults-lead">Vaults, access, and scope <span class="settings-vaults-lead-sub muted">· admin</span></p> |
| 936 | <button type="button" class="btn-settings-info" id="btn-vaults-overview-help" data-settings-info-target="vaults-overview-help" aria-label="Help: overview" aria-expanded="false" title="Explain this tab"> |
| 937 | <svg class="btn-settings-info-svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7S1 12 1 12z"/><circle cx="12" cy="12" r="3"/></svg> |
| 938 | </button> |
| 939 | </div> |
| 940 | <div id="vaults-overview-help" class="settings-info-panel hidden" role="region" aria-label="Vaults tab help"> |
| 941 | <div id="vaults-help-hosted-block" class="hidden"> |
| 942 | <p class="small"><strong>Hosted (cloud)</strong> — A <strong>vault id</strong> is a separate cloud notebook (not a folder on your computer). The header <strong>Vault</strong> menu switches notebooks you’re allowed to open.</p> |
| 943 | <p class="small"><strong>Shared workspace</strong> — One setting: <strong>workspace owner</strong> (whose cloud notes the team uses). This deployment does not offer multiple separate “workspaces” in the UI—one owner id, many vault ids inside that cloud. Teammates: <strong>Team</strong> → roles, then <strong>Vault access</strong> (and optional <strong>Scope</strong>).</p> |
| 944 | <p class="small"><strong>Who creates vaults?</strong> If a workspace owner is set, <strong>only that person</strong> can create <em>new</em> vault ids here; admins still assign who may open which vault. Solo / no owner: you can add vaults yourself.</p> |
| 945 | <p class="small"><strong>Projects</strong> — A <strong>project</strong> is a label on notes (for filters and grouping). It is not the same as a vault. Notes still have paths like <code>inbox/…</code> in the cloud; you don’t browse a real disk—use project names and filters the same way you use tags.</p> |
| 946 | </div> |
| 947 | <div id="vaults-help-self-block" class="hidden"> |
| 948 | <p class="small"><strong>Self-hosted</strong> — Each <strong>vault</strong> is a <strong>folder on this machine</strong> (<code>data/hub_vaults.yaml</code> lists id + path). Use <strong>Vault list</strong> or <strong>Advanced</strong> JSON. There is <strong>no</strong> cloud “workspace owner” field here—this install is your environment.</p> |
| 949 | <p class="small"><strong>Who adds vaults?</strong> Any user with <strong>admin</strong> role can add or change vault folders and save the vault list.</p> |
| 950 | <p class="small"><strong>Projects</strong> — Same idea as hosted: group notes by <code>project:</code> in frontmatter <em>and/or</em> by putting files under <code>projects/<name>/</code> on disk. Paths are real folders you can open in the OS.</p> |
| 951 | </div> |
| 952 | <p class="small muted" style="margin-bottom: 0;">Header <strong>Vault</strong> menu appears when you have two or more vault ids you’re allowed to use. Another “world” entirely = another sign-in (Google/GitHub) or another Hub deployment—not a second workspace row here.</p> |
| 953 | </div> |
| 954 | <div id="vaults-hub-yaml-only" class="hidden settings-vaults-vault-list-block"> |
| 955 | <div class="settings-h3-row"> |
| 956 | <h3 class="settings-h3">Vault list</h3> |
| 957 | <button type="button" class="btn-settings-info" data-settings-info-target="vault-list-help" aria-label="Help: vault list"> |
| 958 | <svg class="btn-settings-info-svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7S1 12 1 12z"/><circle cx="12" cy="12" r="3"/></svg> |
| 959 | </button> |
| 960 | </div> |
| 961 | <div id="vault-list-help" class="settings-info-panel settings-info-panel--section hidden">Keep id <code>default</code> for your primary vault. <strong>Folder path</strong> is the note directory on disk (absolute or relative). Save after editing.</div> |
| 962 | <div id="vaults-list-container" class="settings-vaults-list"></div> |
| 963 | <div class="vault-list-simple-form"> |
| 964 | <div class="settings-form-row" style="display: flex; flex-wrap: wrap; gap: 0.75rem 1rem; align-items: flex-end;"> |
| 965 | <div> |
| 966 | <label for="vault-list-form-existing">Pick vault</label> |
| 967 | <select id="vault-list-form-existing" class="settings-select-inline" aria-label="Existing vault or new vault"></select> |
| 968 | </div> |
| 969 | </div> |
| 970 | <p class="settings-intro small muted" style="margin: 0.35rem 0 0.45rem;"><strong>New vault:</strong> choose <em>New vault</em>, then id + path. <strong>Edit:</strong> pick a row, change path or label, then <strong>Add or update in list</strong>.</p> |
| 971 | <div class="settings-form-row" style="display: flex; flex-wrap: wrap; gap: 0.75rem 1rem; align-items: flex-end;"> |
| 972 | <div> |
| 973 | <label for="vault-list-form-id">Vault id</label> |
| 974 | <input type="text" id="vault-list-form-id" class="settings-input-inline" placeholder="e.g. work" autocomplete="off" spellcheck="false" style="min-width: 12rem;"> |
| 975 | </div> |
| 976 | <div> |
| 977 | <label for="vault-list-form-path">Folder path</label> |
| 978 | <input type="text" id="vault-list-form-path" class="settings-input-inline" placeholder="/path/to/folder or ./vault" autocomplete="off" spellcheck="false" style="min-width: 18rem; max-width: 100%;"> |
| 979 | </div> |
| 980 | <div> |
| 981 | <label for="vault-list-form-label">Label <span class="muted">(optional)</span></label> |
| 982 | <input type="text" id="vault-list-form-label" class="settings-input-inline" placeholder="Menu name" style="min-width: 10rem;"> |
| 983 | </div> |
| 984 | <button type="button" id="btn-vault-list-form-apply" class="btn-secondary">Add or update in list</button> |
| 985 | </div> |
| 986 | <span id="vault-list-form-msg" class="settings-msg" role="status"></span> |
| 987 | </div> |
| 988 | <div class="settings-form-actions settings-vaults-save-row"> |
| 989 | <button type="button" id="btn-vaults-save" class="btn-primary">Save vault list</button> |
| 990 | <span id="vaults-save-msg" class="settings-msg"></span> |
| 991 | </div> |
| 992 | <details id="vault-list-json-details" class="settings-json-details"> |
| 993 | <summary class="settings-json-details-summary">Advanced: edit vault list as JSON</summary> |
| 994 | <div class="settings-form" style="margin-top: 0.75rem;"> |
| 995 | <label for="vaults-json">Vaults (JSON array)</label> |
| 996 | <textarea id="vaults-json" class="settings-json-textarea" rows="6" placeholder='[{"id":"default","path":"./vault","label":"My vault"}]'></textarea> |
| 997 | </div> |
| 998 | </details> |
| 999 | </div> |
| 1000 | <div id="vaults-server-view" class="settings-vaults-server-view muted small" aria-live="polite">Loading…</div> |
| 1001 | <div id="vaults-hosted-create" class="hidden" style="margin: 1rem 0 1.25rem;"> |
| 1002 | <h3 class="settings-h3">Add a vault (hosted)</h3> |
| 1003 | <p class="settings-intro small">A <strong>vault id</strong> is a separate notebook in the cloud (different from a <em>project</em> folder inside a vault). Use letters, numbers, hyphens, and underscores only. You already have <code>default</code> — pick another id (e.g. <code>work</code>).</p> |
| 1004 | <div class="settings-form-row" style="display: flex; flex-wrap: wrap; gap: 0.75rem 1rem; align-items: flex-end; margin-top: 0.5rem;"> |
| 1005 | <div> |
| 1006 | <label for="vaults-hosted-new-id">New vault id</label> |
| 1007 | <input type="text" id="vaults-hosted-new-id" class="settings-input-inline" placeholder="e.g. work" maxlength="64" autocomplete="off" spellcheck="false" style="min-width: 14rem;" aria-describedby="vaults-hosted-create-hint"> |
| 1008 | </div> |
| 1009 | <button type="button" id="btn-vaults-hosted-create" class="btn-primary">Create vault</button> |
| 1010 | </div> |
| 1011 | <p id="vaults-hosted-create-hint" class="settings-intro small muted" style="margin-top: 0.35rem;">Creates one starter note under <code>inbox/</code> in the new vault. Agents can also use header <code>X-Vault-Id</code> with the same id.</p> |
| 1012 | <span id="vaults-hosted-create-msg" class="settings-msg" role="status"></span> |
| 1013 | </div> |
| 1014 | <div id="vaults-hosted-create-non-owner" class="settings-info-panel settings-info-panel--section hidden" role="status"> |
| 1015 | <p class="small" style="margin:0;">You’re using a <strong>shared workspace</strong>. Only the <strong>workspace owner</strong> can create new cloud vault ids (separate notebooks). Ask them to add the vault here, then an admin can grant access under <strong>Vault access</strong> below.</p> |
| 1016 | </div> |
| 1017 | <div id="vaults-hosted-workspace" class="hidden" style="margin: 1.25rem 0; padding: 1rem 0; border-top: 1px solid var(--border, #333); border-bottom: 1px solid var(--border, #333);"> |
| 1018 | <h3 class="settings-h3">Shared workspace owner (hosted teams)</h3> |
| 1019 | <p class="settings-intro small">Imagine one shared filing cabinet in the cloud. The <strong>workspace owner</strong> is whose cabinet everyone opens when they’re on the team. Paste the owner’s User ID (same format as <strong>Settings → Backup → Your user ID</strong>—usually <em>your</em> ID if you’re the lead). Until this is set, each person only sees their <em>own</em> empty cloud space. After you set it, invited teammates (with roles from <strong>Team</strong>) read and write <strong>that</strong> owner’s notes.</p> |
| 1020 | <div class="settings-form" style="margin-top: 0.75rem;"> |
| 1021 | <label for="workspace-owner-input">Workspace owner user ID</label> |
| 1022 | <input type="text" id="workspace-owner-input" class="settings-input-inline" placeholder="e.g. google:104164334692309763642" autocomplete="off" spellcheck="false" style="min-width: 20rem; max-width: 100%; display: block; margin: 0.35rem 0 0.5rem;"> |
| 1023 | <div class="settings-form-actions" style="display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center;"> |
| 1024 | <button type="button" id="btn-workspace-use-me" class="btn-secondary">Use my User ID</button> |
| 1025 | <button type="button" id="btn-workspace-save" class="btn-primary">Save workspace owner</button> |
| 1026 | <button type="button" id="btn-workspace-clear" class="btn-secondary">Clear — solo mode</button> |
| 1027 | </div> |
| 1028 | <span id="workspace-save-msg" class="settings-msg" role="status"></span> |
| 1029 | </div> |
| 1030 | </div> |
| 1031 | <div id="vaults-self-hosted-editors"> |
| 1032 | <div class="settings-h3-row settings-vaults-gap-before-access"> |
| 1033 | <h3 class="settings-h3">Vault access</h3> |
| 1034 | <button type="button" class="btn-settings-info" data-settings-info-target="vault-access-help" aria-label="Help: vault access"> |
| 1035 | <svg class="btn-settings-info-svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7S1 12 1 12z"/><circle cx="12" cy="12" r="3"/></svg> |
| 1036 | </button> |
| 1037 | </div> |
| 1038 | <div id="vault-access-help" class="settings-info-panel settings-info-panel--section hidden">People not listed only get the <code>default</code> vault. Use <strong>Team</strong> roles to fill the Person menu. Tick vaults · <strong>Apply to rules</strong> · then click <strong>Save vault access</strong> (required — rules are not saved until then).</div> |
| 1039 | <p class="settings-intro small settings-intro-tight">Who may open which vault.</p> |
| 1040 | <div id="vaults-access-simple-form"> |
| 1041 | <p class="settings-intro small muted" style="margin-bottom: 0.5rem;">From <strong>Team</strong> · Apply, then save below.</p> |
| 1042 | <div class="settings-form-row" style="display: flex; flex-wrap: wrap; gap: 0.75rem 1rem; align-items: flex-end;"> |
| 1043 | <div> |
| 1044 | <label for="access-form-user-select">Person</label> |
| 1045 | <select id="access-form-user-select" class="settings-select-inline" aria-label="Teammate for vault access"></select> |
| 1046 | </div> |
| 1047 | <div id="access-form-user-other-wrap" class="hidden"> |
| 1048 | <label for="access-form-user-other">Their User ID</label> |
| 1049 | <input type="text" id="access-form-user-other" class="settings-input-inline" placeholder="e.g. google:…" autocomplete="off" spellcheck="false" style="min-width: 16rem;"> |
| 1050 | </div> |
| 1051 | </div> |
| 1052 | <fieldset class="settings-fieldset-compact" style="margin: 0.85rem 0; padding: 0.65rem 1rem; border: 1px solid var(--border, #444); border-radius: 6px;"> |
| 1053 | <legend class="small" style="padding: 0 0.35rem;">Vaults they can open</legend> |
| 1054 | <div id="access-form-vault-checkboxes" class="access-vault-checkboxes" role="group" aria-label="Vaults allowed for this person"></div> |
| 1055 | </fieldset> |
| 1056 | <div class="settings-form-actions" style="display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center;"> |
| 1057 | <button type="button" id="btn-access-form-apply" class="btn-secondary">Apply to rules</button> |
| 1058 | <button type="button" id="btn-access-form-remove-user" class="btn-secondary">Remove this person</button> |
| 1059 | </div> |
| 1060 | <span id="access-form-msg" class="settings-msg" role="status"></span> |
| 1061 | <p class="settings-intro small muted" style="margin-top: 0.65rem;">Preview</p> |
| 1062 | <ul id="access-rules-summary" class="settings-list small access-rules-summary"></ul> |
| 1063 | </div> |
| 1064 | <details id="vault-access-json-details" class="settings-json-details"> |
| 1065 | <summary class="settings-json-details-summary">Advanced: edit access as JSON</summary> |
| 1066 | <div class="settings-form" style="margin-top: 0.75rem;"> |
| 1067 | <label for="vault-access-json">Access (JSON)</label> |
| 1068 | <textarea id="vault-access-json" class="settings-json-textarea" rows="8" placeholder='{"github:123": ["default", "work"]}'></textarea> |
| 1069 | </div> |
| 1070 | </details> |
| 1071 | <div class="settings-form-actions settings-vaults-after-access-save"> |
| 1072 | <button type="button" id="btn-vault-access-save" class="btn-primary btn-vault-access-save-emphasis">Save vault access</button> |
| 1073 | <span id="vault-access-save-msg" class="settings-msg"></span> |
| 1074 | </div> |
| 1075 | <div class="settings-h3-row settings-vaults-scope-heading"> |
| 1076 | <h3 class="settings-h3">Scope (per user per vault)</h3> |
| 1077 | <button type="button" class="btn-settings-info" data-settings-info-target="vault-scope-help" aria-label="Help: scope"> |
| 1078 | <svg class="btn-settings-info-svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7S1 12 1 12z"/><circle cx="12" cy="12" r="3"/></svg> |
| 1079 | </button> |
| 1080 | </div> |
| 1081 | <div id="vault-scope-help" class="settings-info-panel settings-info-panel--section hidden">Optional limits inside a vault (projects / folders). Leave empty for full vault. Same person picker as access; then <strong>Save scope</strong>.</div> |
| 1082 | <p class="settings-intro small settings-intro-tight">Limit folders or projects per person.</p> |
| 1083 | <div class="settings-form scope-form-simple"> |
| 1084 | <p class="settings-intro small muted" style="margin-bottom: 0.5rem;">Fill fields · <strong>Add to scope</strong> · then save.</p> |
| 1085 | <div id="vaults-scope-user-picker" class="settings-form-row" style="display: flex; flex-wrap: wrap; gap: 0.75rem 1rem; align-items: flex-end;"> |
| 1086 | <div> |
| 1087 | <label for="scope-form-user-select">Person</label> |
| 1088 | <select id="scope-form-user-select" class="settings-select-inline" aria-label="Teammate for scope"></select> |
| 1089 | </div> |
| 1090 | </div> |
| 1091 | <div class="settings-form-row" style="display: flex; flex-wrap: wrap; gap: 0.75rem 1rem; align-items: center;"> |
| 1092 | <label for="scope-form-user-id">User ID</label> |
| 1093 | <input type="text" id="scope-form-user-id" class="settings-input-inline" placeholder="e.g. google:123" style="min-width: 12rem;"> |
| 1094 | <label for="scope-form-vault-id">Vault</label> |
| 1095 | <select id="scope-form-vault-id" class="settings-select-inline" aria-label="Vault for scope"></select> |
| 1096 | <label for="scope-form-projects">Projects (comma-separated)</label> |
| 1097 | <input type="text" id="scope-form-projects" class="settings-input-inline" placeholder="Launch, Q1" style="min-width: 10rem;"> |
| 1098 | <label for="scope-form-folders">Folders (comma-separated)</label> |
| 1099 | <input type="text" id="scope-form-folders" class="settings-input-inline" placeholder="inbox, imports" style="min-width: 10rem;"> |
| 1100 | <button type="button" id="btn-scope-form-apply" class="btn-secondary">Add to scope</button> |
| 1101 | </div> |
| 1102 | <span id="scope-form-msg" class="settings-msg"></span> |
| 1103 | </div> |
| 1104 | <details id="scope-json-details" class="settings-json-details"> |
| 1105 | <summary class="settings-json-details-summary">Advanced: edit scope as JSON</summary> |
| 1106 | <div class="settings-form" style="margin-top: 0.75rem;"> |
| 1107 | <label for="scope-json">Scope (JSON)</label> |
| 1108 | <textarea id="scope-json" class="settings-json-textarea" rows="8" placeholder='{"github:123": {"default": {"projects": ["my-project"], "folders": ["inbox"]}}}'></textarea> |
| 1109 | </div> |
| 1110 | </details> |
| 1111 | <div class="settings-form-actions" style="margin-top: 0.5rem;"> |
| 1112 | <button type="button" id="btn-scope-save" class="btn-primary">Save scope</button> |
| 1113 | <span id="scope-save-msg" class="settings-msg"></span> |
| 1114 | </div> |
| 1115 | </div> |
| 1116 | <hr class="settings-hr"> |
| 1117 | <p class="settings-intro small"><strong>Hub as a flexible network:</strong> Many users, many vaults, many repos, and agents (MCP, AgentCeption, and <em>optionally</em> linked tools such as Muse) from one Hub—Knowtation does not require Muse to be running. <button type="button" id="btn-how-to-flexible-network" class="btn-link btn-link-small">How to use → Hub as a flexible network</button></p> |
| 1118 | </div> |
| 1119 | </div> |
| 1120 | <div id="settings-panel-integrations" class="settings-panel" role="tabpanel"> |
| 1121 | <div class="settings-body"> |
| 1122 | <div class="settings-intro settings-intro-integrations-lede"> |
| 1123 | Integrations connect external tools to your vault: capture (Slack, Discord, etc.), imports (ChatGPT, Notion, etc.), and agents. <strong>Hub API</strong> (REST + optional MCP) |
| 1124 | <details class="settings-integ-how-inline"> |
| 1125 | <summary class="settings-integ-how-inline-summary"><span class="settings-integ-how-inline-label">How?</span></summary> |
| 1126 | <div class="settings-integ-how-inline-body"> |
| 1127 | <p class="settings-intro small" style="margin-top: 0.35rem;">Uses the <strong>same sign-in as this tab</strong> on <strong>hosted and self-hosted</strong> gateways—copy URL, JWT, and vault id for scripts and tools outside the browser.</p> |
| 1128 | <p class="settings-intro small" style="margin-bottom: 0;">The <strong>Hub API</strong> block is at the <strong>bottom</strong> of this tab (above Agent Configuration). <strong>Advanced Ecosystems</strong> (Muse, AgentCeption) stay collapsed until you open them.</p> |
| 1129 | </div> |
| 1130 | </details> |
| 1131 | </div> |
| 1132 | <h3 class="settings-h3 integ-section-heading"> |
| 1133 | <span class="integ-section-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v4"/><path d="M12 18v4"/><path d="m4.93 4.93 2.83 2.83"/><path d="m16.24 16.24 2.83 2.83"/><path d="M2 12h4"/><path d="M18 12h4"/><path d="m4.93 19.07 2.83-2.83"/><path d="m16.24 7.76 2.83-2.83"/></svg></span> |
| 1134 | AI model provider |
| 1135 | </h3> |
| 1136 | <p class="settings-intro small"><strong>What this is:</strong> the model service that powers Knowtation's AI features — note summaries and proposal review hints (the <code>completeChat</code> lane). It is separate from <strong>embeddings</strong> (Agent Configuration, below) and from <strong>Memory Consolidation</strong> (Settings → Consolidation). <strong>Local/in-browser and BYO-key lanes keep your note text private;</strong> managed providers send note text to a third party.</p> |
| 1137 | <div id="settings-chat-provider" class="settings-form" style="border: 1px solid var(--border); border-radius: 8px; padding: 0.75rem 1rem; margin: 0;"> |
| 1138 | <label for="chat-provider-select" style="font-weight: 500;">Chat model provider</label> |
| 1139 | <select id="chat-provider-select" class="settings-select-inline" style="display: block; margin-top: 0.25rem; max-width: 22rem;"> |
| 1140 | <option value="">Auto-detect (default)</option> |
| 1141 | <option value="openai">OpenAI (managed)</option> |
| 1142 | <option value="anthropic">Anthropic (managed)</option> |
| 1143 | <option value="deepinfra">DeepInfra (managed)</option> |
| 1144 | <option value="openrouter">OpenRouter (your key, BYO)</option> |
| 1145 | <option value="ollama">Ollama (local, free, private)</option> |
| 1146 | </select> |
| 1147 | <p id="chat-provider-key-hint" class="settings-intro small muted" style="margin: 0.35rem 0 0;"></p> |
| 1148 | <p id="chat-provider-env-hint" class="settings-intro small hidden" style="margin: 0.35rem 0 0; color: var(--muted, #888);"></p> |
| 1149 | <p id="chat-provider-admin-hint" class="settings-intro small hidden" style="margin: 0.35rem 0 0; color: var(--muted, #888);">Only a workspace <strong>admin</strong> can change the model provider.</p> |
| 1150 | <div class="settings-form-actions" style="margin-top: 0.5rem;"> |
| 1151 | <button type="button" id="btn-chat-provider-save" class="btn-primary">Save provider</button> |
| 1152 | <span id="chat-provider-msg" class="settings-msg"></span> |
| 1153 | </div> |
| 1154 | </div> |
| 1155 | <div class="integ-source-grid" id="integ-model-grid" style="margin-top: 0.65rem;"> |
| 1156 | <button type="button" class="integ-source-tile" data-integ-id="openrouter" aria-label="OpenRouter — setup details"> |
| 1157 | <span class="integ-source-tile-icon">🧭</span> |
| 1158 | <span class="integ-source-tile-name">OpenRouter</span> |
| 1159 | <span class="integ-source-tile-desc">BYO key; many models</span> |
| 1160 | </button> |
| 1161 | </div> |
| 1162 | <hr class="settings-hr"> |
| 1163 | <h3 class="settings-h3 integ-section-heading"> |
| 1164 | <span class="integ-section-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></span> |
| 1165 | Capture (messages → inbox) |
| 1166 | </h3> |
| 1167 | <p class="settings-intro small"><strong>What this is:</strong> turns chats and automations into new notes in your Inbox. Most teams set up a small <strong>bridge</strong> (or Zapier/n8n) once. Walkthrough: <strong>How to use → Setup → Self-hosted setup → Step 5</strong> (same capture path on hosted; only the host URL changes).</p> |
| 1168 | <div class="integ-source-grid integ-capture-grid" id="integ-capture-grid"> |
| 1169 | <button type="button" class="integ-source-tile" data-integ-id="slack" aria-label="Slack — setup details"> |
| 1170 | <span class="integ-source-tile-icon">💬</span> |
| 1171 | <span class="integ-source-tile-name">Slack</span> |
| 1172 | <span class="integ-source-tile-desc">Team chat → Inbox</span> |
| 1173 | </button> |
| 1174 | <button type="button" class="integ-source-tile" data-integ-id="discord" aria-label="Discord — setup details"> |
| 1175 | <span class="integ-source-tile-icon">🎮</span> |
| 1176 | <span class="integ-source-tile-name">Discord</span> |
| 1177 | <span class="integ-source-tile-desc">Server messages → Inbox</span> |
| 1178 | </button> |
| 1179 | <button type="button" class="integ-source-tile" data-integ-id="telegram" aria-label="Telegram — setup details"> |
| 1180 | <span class="integ-source-tile-icon">✈️</span> |
| 1181 | <span class="integ-source-tile-name">Telegram</span> |
| 1182 | <span class="integ-source-tile-desc">Bot or webhook → Inbox</span> |
| 1183 | </button> |
| 1184 | <button type="button" class="integ-source-tile" data-integ-id="whatsapp" aria-label="WhatsApp — setup details"> |
| 1185 | <span class="integ-source-tile-icon">📱</span> |
| 1186 | <span class="integ-source-tile-name">WhatsApp</span> |
| 1187 | <span class="integ-source-tile-desc">Automation → Inbox</span> |
| 1188 | </button> |
| 1189 | </div> |
| 1190 | <details class="settings-json-details" style="margin-top:0.5rem;"> |
| 1191 | <summary class="settings-json-details-summary">Technical: capture API, ports, and secrets</summary> |
| 1192 | <p class="settings-intro small" style="margin:0.5rem 0 0.35rem;">Endpoint: <code>POST /api/v1/capture</code> with JSON <code>{"body": "text", "source": "slack", …}</code>. Optional shared secret: <code>CAPTURE_WEBHOOK_SECRET</code> + <code>X-Webhook-Secret</code> header. Default adapter examples in the repo: Slack <strong>3132</strong> (<code>SLACK_SIGNING_SECRET</code>), Discord <strong>3133</strong>, Telegram <strong>3134</strong>. See <code>docs/MESSAGING-INTEGRATION.md</code>.</p> |
| 1193 | </details> |
| 1194 | <hr class="settings-hr"> |
| 1195 | <h3 class="settings-h3 integ-section-heading"> |
| 1196 | <span class="integ-section-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg></span> |
| 1197 | Import sources (files → vault) |
| 1198 | </h3> |
| 1199 | <p class="settings-intro small"><strong>What this is:</strong> one-time (or scheduled) <strong>imports from files and apps</strong> (Chat exports, Notion, CSV, and more) into your vault. Use the Hub <strong>Import</strong> button when available, or the CLI for large batches. Full list: <code>docs/IMPORT-SOURCES.md</code>.</p> |
| 1200 | <details class="settings-json-details" style="margin:0.35rem 0 0.5rem;"> |
| 1201 | <summary class="settings-json-details-summary">CLI pattern <code>knowtation import …</code></summary> |
| 1202 | <p class="settings-intro small" style="margin:0.5rem 0 0.25rem;">Common options: <code>--project</code>, <code>--output-dir</code>, <code>--tags</code>. Exact source names: see the doc above.</p> |
| 1203 | </details> |
| 1204 | <div class="integ-source-grid" id="integ-import-grid"> |
| 1205 | <button type="button" class="integ-source-tile" data-integ-id="chatgpt-export" aria-label="ChatGPT — import details"> |
| 1206 | <span class="integ-source-tile-icon">🤖</span> |
| 1207 | <span class="integ-source-tile-name">ChatGPT</span> |
| 1208 | <span class="integ-source-tile-desc">ZIP or folder export</span> |
| 1209 | </button> |
| 1210 | <button type="button" class="integ-source-tile" data-integ-id="claude-export" aria-label="Claude — import details"> |
| 1211 | <span class="integ-source-tile-icon">🧠</span> |
| 1212 | <span class="integ-source-tile-name">Claude</span> |
| 1213 | <span class="integ-source-tile-desc">Chat + memory export</span> |
| 1214 | </button> |
| 1215 | <button type="button" class="integ-source-tile" data-integ-id="mem0-export" aria-label="Mem0 — import details"> |
| 1216 | <span class="integ-source-tile-icon">💾</span> |
| 1217 | <span class="integ-source-tile-name">Mem0</span> |
| 1218 | <span class="integ-source-tile-desc">JSON memory export</span> |
| 1219 | </button> |
| 1220 | <button type="button" class="integ-source-tile" data-integ-id="notion" aria-label="Notion — import details"> |
| 1221 | <span class="integ-source-tile-icon">📝</span> |
| 1222 | <span class="integ-source-tile-name">Notion</span> |
| 1223 | <span class="integ-source-tile-desc">API; page IDs + key</span> |
| 1224 | </button> |
| 1225 | <button type="button" class="integ-source-tile" data-integ-id="jira-export" aria-label="Jira — import details"> |
| 1226 | <span class="integ-source-tile-icon">🎫</span> |
| 1227 | <span class="integ-source-tile-name">Jira</span> |
| 1228 | <span class="integ-source-tile-desc">CSV export</span> |
| 1229 | </button> |
| 1230 | <button type="button" class="integ-source-tile" data-integ-id="notebooklm" aria-label="NotebookLM — import details"> |
| 1231 | <span class="integ-source-tile-icon">📓</span> |
| 1232 | <span class="integ-source-tile-name">NotebookLM</span> |
| 1233 | <span class="integ-source-tile-desc">Markdown or JSON</span> |
| 1234 | </button> |
| 1235 | <button type="button" class="integ-source-tile" data-integ-id="gdrive" aria-label="Google Drive — import details"> |
| 1236 | <span class="integ-source-tile-icon">📁</span> |
| 1237 | <span class="integ-source-tile-name">Google Drive</span> |
| 1238 | <span class="integ-source-tile-desc">Markdown folder</span> |
| 1239 | </button> |
| 1240 | <button type="button" class="integ-source-tile" data-integ-id="linear-export" aria-label="Linear — import details"> |
| 1241 | <span class="integ-source-tile-icon">📋</span> |
| 1242 | <span class="integ-source-tile-name">Linear</span> |
| 1243 | <span class="integ-source-tile-desc">CSV export</span> |
| 1244 | </button> |
| 1245 | <button type="button" class="integ-source-tile" data-integ-id="mif" aria-label="MIF — import details"> |
| 1246 | <span class="integ-source-tile-icon">🔗</span> |
| 1247 | <span class="integ-source-tile-name">MIF</span> |
| 1248 | <span class="integ-source-tile-desc">Memory Interchange Format</span> |
| 1249 | </button> |
| 1250 | <button type="button" class="integ-source-tile" data-integ-id="markdown" aria-label="Markdown — import details"> |
| 1251 | <span class="integ-source-tile-icon">📄</span> |
| 1252 | <span class="integ-source-tile-name">Markdown</span> |
| 1253 | <span class="integ-source-tile-desc">File or folder</span> |
| 1254 | </button> |
| 1255 | <button type="button" class="integ-source-tile" data-integ-id="audio" aria-label="Audio — import details"> |
| 1256 | <span class="integ-source-tile-icon">🎙️</span> |
| 1257 | <span class="integ-source-tile-name">Audio</span> |
| 1258 | <span class="integ-source-tile-desc">Whisper transcription</span> |
| 1259 | </button> |
| 1260 | <button type="button" class="integ-source-tile" data-integ-id="wallet-csv" aria-label="Wallet CSV — import details"> |
| 1261 | <span class="integ-source-tile-icon">💰</span> |
| 1262 | <span class="integ-source-tile-name">Wallet CSV</span> |
| 1263 | <span class="integ-source-tile-desc">Tx history; 11 formats</span> |
| 1264 | </button> |
| 1265 | <button type="button" class="integ-source-tile" data-integ-id="supabase-memory" aria-label="Supabase — import details"> |
| 1266 | <span class="integ-source-tile-icon">🗄️</span> |
| 1267 | <span class="integ-source-tile-name">Supabase</span> |
| 1268 | <span class="integ-source-tile-desc">Memory table import</span> |
| 1269 | </button> |
| 1270 | <button type="button" class="integ-source-tile" data-integ-id="openclaw" aria-label="OpenClaw — import details"> |
| 1271 | <span class="integ-source-tile-icon">🦞</span> |
| 1272 | <span class="integ-source-tile-name">OpenClaw</span> |
| 1273 | <span class="integ-source-tile-desc">Agent memory + chats</span> |
| 1274 | </button> |
| 1275 | <button type="button" class="integ-source-tile" data-integ-id="hermes" aria-label="Hermes Agent — import details"> |
| 1276 | <span class="integ-source-tile-icon">🪶</span> |
| 1277 | <span class="integ-source-tile-name">Hermes Agent</span> |
| 1278 | <span class="integ-source-tile-desc">Agent memory + profile</span> |
| 1279 | </button> |
| 1280 | <button type="button" class="integ-source-tile" data-integ-id="imports" aria-label="Imports — local and team upload details"> |
| 1281 | <span class="integ-source-tile-icon">📥</span> |
| 1282 | <span class="integ-source-tile-name">Imports</span> |
| 1283 | <span class="integ-source-tile-desc">Local files & team uploads</span> |
| 1284 | </button> |
| 1285 | </div> |
| 1286 | <hr class="settings-hr"> |
| 1287 | <div class="settings-callout settings-integ-post-import-callout" style="border: 1px solid var(--border); border-radius: 8px; padding: 0.75rem 1rem; margin: 0.75rem 0 0.65rem; background: var(--surface-elevated, rgba(255,255,255,0.03));"> |
| 1288 | <p class="settings-intro small" style="margin: 0 0 0.5rem 0;"><strong>Token savings:</strong> Use <strong>memory consolidation</strong> (Settings → Consolidation) to compress activity into facts. Use <strong>tiered retrieval</strong> in agents—search with a small limit and short fields, then open only the notes you need. Optional <strong>Discover</strong> adds cross-topic insights inside the <em>same</em> consolidation run on hosted plans (one pass per run, not two).</p> |
| 1289 | <button type="button" id="btn-integrations-how-token-savings" class="btn-link btn-link-small">How to use → Token savings</button> |
| 1290 | </div> |
| 1291 | <p class="settings-intro small"><strong>Meetings and transcripts:</strong> Hosted Knowtation does not run transcription for you. Export text or Markdown from your recorder (Otter, Zoom, Granola, etc.) or paste into a note, then index—same outcome for search and agents.</p> |
| 1292 | <details class="settings-json-details"> |
| 1293 | <summary class="settings-json-details-summary">Self-hosted only — long audio and ffmpeg</summary> |
| 1294 | <p class="settings-intro small" style="margin:0.5rem 0 0;">Whisper is limited to about <strong>25 MB</strong> per file. If <code>ffmpeg</code> is installed on the host (<a href="https://ffmpeg.org/download.html" target="_blank" rel="noopener">ffmpeg.org</a>, or the Docker image we ship), very large files can be compressed first. Toggles: <code>transcription.transcode_oversized: false</code> in <code>config/local.yaml</code> or <code>KNOWTATION_TRANSCODE_OVERSIZED=0</code>; <code>FFMPEG_PATH</code> if not on <code>PATH</code>. Hosted: export transcript text; we do not run this pipeline in the browser.</p> |
| 1295 | </details> |
| 1296 | <details class="settings-json-details settings-advanced-ecosystems-details"> |
| 1297 | <summary class="settings-json-details-summary">Advanced Ecosystems</summary> |
| 1298 | <div class="settings-advanced-ecosystems-body"> |
| 1299 | <h3 class="settings-h3 integ-section-heading" style="margin-top: 0.75rem;"> |
| 1300 | <span class="integ-section-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg></span> |
| 1301 | Muse (optional link) |
| 1302 | </h3> |
| 1303 | <div id="settings-muse-panel" class="settings-form" style="margin-top: 0.35rem;"> |
| 1304 | <p class="settings-intro small" style="margin-top: 0;">When enabled on the <strong>server</strong>, Knowtation can attach a small <strong>cross-reference id</strong> (<code>external_ref</code>) to <strong>approved proposals</strong> so the same change can be looked up in <strong>Muse / MuseHub</strong> (structure, lineage, blast radius). Your notes still live in Knowtation; nothing is moved automatically.</p> |
| 1305 | <p class="settings-intro small"><strong>Not your Git backup URL.</strong> Enter the <strong>HTTP base URL of the Muse service</strong> (the API root your operator exposes), e.g. <code>https://muse.yourcompany.com</code> — same host that serves <code>GET …/knowtation/v1/lineage-ref</code> per <code>docs/MUSE-THIN-BRIDGE.md</code>. The ref stored on the proposal is a <strong>short opaque string</strong> (letters, numbers, common safe punctuation; no control characters), up to 512 characters.</p> |
| 1306 | <p id="settings-muse-status" class="settings-intro small" style="margin: 0.35rem 0 0 0;">—</p> |
| 1307 | <p id="settings-muse-env-hint" class="settings-intro small hidden" style="margin: 0.25rem 0 0 0; color: var(--muted, #888);"></p> |
| 1308 | <label for="settings-muse-url" style="margin-top: 0.65rem;">Muse base URL <span class="settings-label-hint">(self-hosted admins; saved to <code>config/local.yaml</code>)</span></label> |
| 1309 | <input type="url" id="settings-muse-url" class="settings-input-wide" placeholder="https://your-muse-host.example" autocomplete="off" spellcheck="false"> |
| 1310 | <div class="settings-form-actions" style="margin-top: 0.5rem;"> |
| 1311 | <button type="button" id="btn-settings-muse-save" class="btn-primary hidden">Save Muse URL</button> |
| 1312 | <span id="settings-muse-msg" class="settings-msg"></span> |
| 1313 | </div> |
| 1314 | </div> |
| 1315 | <hr class="settings-hr settings-advanced-ecosystems-inner-hr"> |
| 1316 | <h3 class="settings-h3 integ-section-heading"> |
| 1317 | <span class="integ-section-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></span> |
| 1318 | AgentCeption <span class="settings-label-hint">(self-hosted — shared disk vault)</span> |
| 1319 | </h3> |
| 1320 | <p class="settings-intro small"><strong>Hosted beta users:</strong> you typically connect tools with Hub API above; skip this unless you run multi-agent setups against a shared local vault path.</p> |
| 1321 | <p class="settings-intro small"><strong>Self-hosted:</strong> Use Knowtation as shared context for planner and engineer agents — one on-disk vault path for the whole setup.</p> |
| 1322 | <h4 class="settings-h4">How to connect AgentCeption</h4> |
| 1323 | <p class="settings-intro small">Set the same vault path in the planner and every engineer. Copy the env snippet below into each environment.</p> |
| 1324 | <div class="settings-form"> |
| 1325 | <label for="integrations-agentception-env">Env snippet (copy)</label> |
| 1326 | <div class="settings-value-wrap" style="margin-top: 0.25rem;"> |
| 1327 | <code id="integrations-agentception-env" class="settings-code">KNOWTATION_VAULT_PATH=/path/to/shared/vault</code> |
| 1328 | <button type="button" id="btn-copy-agentception-env" class="btn-copy-small" title="Copy">Copy</button> |
| 1329 | </div> |
| 1330 | </div> |
| 1331 | <p class="settings-intro small" style="margin-bottom: 0;"><button type="button" id="btn-integrations-how-to-agentception" class="btn-link btn-link-small">Full setup → How to use (AgentCeption)</button></p> |
| 1332 | </div> |
| 1333 | </details> |
| 1334 | <hr class="settings-hr"> |
| 1335 | <h3 class="settings-h3 integ-section-heading"> |
| 1336 | <span class="integ-section-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 7h3a5 5 0 0 1 0 10h-3"/><path d="M9 17H6a5 5 0 0 1 0-10h3"/><line x1="8" y1="12" x2="16" y2="12"/></svg></span> |
| 1337 | Hub API |
| 1338 | <span id="integ-api-status" class="integ-status-dot" title="No token copied yet"></span> |
| 1339 | </h3> |
| 1340 | <p class="settings-intro small">There is no separate “API signup.” You already signed in above — tools outside the browser (Cursor, scripts, curl, API clients) need a <strong>copy-paste block</strong> from this page. After you log in, click <strong>Copy Hub URL, token & vault</strong> and treat that paste like a <strong>password</strong> (do not share it). The same token works for <strong>Hub REST</strong> and for <strong>remote MCP</strong> (with the same headers); the paste includes a <strong>link to the full guide</strong> (not a long comment block in the clipboard).</p> |
| 1341 | <details class="how-to-details"> |
| 1342 | <summary>Technical details — Hub URL vs MCP URL, Bearer, hosted vs self-hosted</summary> |
| 1343 | <div class="how-to-details-body"> |
| 1344 | <p class="settings-intro small" style="margin: 0;">REST and MCP are explained in the doc linked from the copy button (and on this project’s <code>docs/AGENT-INTEGRATION.md</code>). In short: <code>KNOWTATION_HUB_URL</code> is the REST API; <code>KNOWTATION_MCP_URL</code> (when your host sets it) is the remote MCP endpoint; the token is the same JWT with <code>Authorization: Bearer …</code> and <code>X-Vault-Id</code>. Your <strong>browser</strong> session is separate from the pasted API block.</p> |
| 1345 | </div> |
| 1346 | </details> |
| 1347 | <details class="settings-json-details settings-hub-api-troubleshoot"> |
| 1348 | <summary class="settings-json-details-summary">Troubleshoot: API token, automations, and HTTP headers</summary> |
| 1349 | <div class="settings-troubleshoot-body"> |
| 1350 | <p class="settings-intro small" style="margin-top: 0.5rem;">The copied <strong>JWT expires on a schedule</strong> (security). <strong>Automations</strong> (cron, CI, static MCP JSON) fail with <strong>401</strong> only if they still send an <strong>old pasted token</strong> after expiry—click <strong>Copy Hub URL, token & vault</strong> again and update the secret where you pasted it. Your <strong>browser session</strong> in this Hub tab is separate and usually keeps working.</p> |
| 1351 | <p class="settings-intro small"><strong>Reduce surprises:</strong> Prefer <code>${env:KNOWTATION_HUB_TOKEN}</code> in MCP config (see <code>docs/AGENT-INTEGRATION.md</code>) so you rotate one env var instead of editing JSON. Long-running servers may need an occasional re-copy after policy or rotation changes.</p> |
| 1352 | <p class="settings-intro small">For HTTP calls, send <code>Authorization: Bearer …</code> and <code>X-Vault-Id</code> on vault-scoped routes. JSON MCP <code>headers</code> must use the <strong>full</strong> <code>Authorization</code> value: <code>Bearer <KNOWTATION_HUB_TOKEN></code>, not the token alone. Full shapes: <code>docs/AGENT-INTEGRATION.md</code>.</p> |
| 1353 | </div> |
| 1354 | </details> |
| 1355 | <div class="settings-actions settings-hub-api-copy-actions" style="margin-top: 0.65rem;"> |
| 1356 | <button type="button" id="btn-copy-hub-api-env" class="btn-primary">Copy Hub URL, token & vault</button> |
| 1357 | <button type="button" id="btn-copy-mcp-prime" class="btn-secondary">Copy prime</button> |
| 1358 | <span id="integrations-hub-api-copy-msg" class="settings-msg"></span> |
| 1359 | </div> |
| 1360 | <p class="settings-intro small"><strong>Copy prime</strong> saves a small JSON <strong>reminder</strong> to the clipboard: which Hub you are on and which vault. It does <strong>not</strong> contain your sign-in secret — use <strong>Copy Hub URL, token & vault</strong> for that.</p> |
| 1361 | <details class="how-to-details"> |
| 1362 | <summary>Technical details — MCP <code>readResource</code> and prime URI</summary> |
| 1363 | <div class="how-to-details-body"> |
| 1364 | <p class="settings-intro small" style="margin: 0;">The JSON includes the MCP <code>readResource</code> URI <code>knowtation://hosted/prime</code>, this gateway’s base URL, and the current vault id — <strong>not</strong> your JWT. After your MCP client connects with valid <code>Authorization</code> and <code>X-Vault-Id</code> headers, it may read that resource for session context and which MCP prompt names are registered for your role (or use <code>prompts/list</code>).</p> |
| 1365 | </div> |
| 1366 | </details> |
| 1367 | <p class="settings-intro small settings-hub-api-doc-ref">Full agent reference (CLI, MCP, Hub API, no separate signup): <code>docs/AGENT-INTEGRATION.md</code>.</p> |
| 1368 | <hr class="settings-hr"> |
| 1369 | <h3 class="settings-h3 integ-section-heading"> |
| 1370 | <span class="integ-section-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="16" height="16" rx="2" ry="2"/><rect x="9" y="9" width="6" height="6"/><line x1="9" y1="1" x2="9" y2="4"/><line x1="15" y1="1" x2="15" y2="4"/><line x1="9" y1="20" x2="9" y2="23"/><line x1="15" y1="20" x2="15" y2="23"/><line x1="20" y1="9" x2="23" y2="9"/><line x1="20" y1="14" x2="23" y2="14"/><line x1="1" y1="9" x2="4" y2="9"/><line x1="1" y1="14" x2="4" y2="14"/></svg></span> |
| 1371 | Agent Configuration |
| 1372 | </h3> |
| 1373 | <p class="settings-intro small">Embedding config the Hub uses. Match this in your agent runtime so search behaves the same.</p> |
| 1374 | <div class="settings-row"> |
| 1375 | <span class="settings-label">Provider</span> |
| 1376 | <span id="agents-embedding-provider" class="settings-value">—</span> |
| 1377 | </div> |
| 1378 | <div class="settings-row"> |
| 1379 | <span class="settings-label">Model</span> |
| 1380 | <span id="agents-embedding-model" class="settings-value">—</span> |
| 1381 | </div> |
| 1382 | <div class="settings-row" id="agents-ollama-row"> |
| 1383 | <span class="settings-label">Ollama URL</span> |
| 1384 | <span id="agents-embedding-ollama-url" class="settings-value">—</span> |
| 1385 | </div> |
| 1386 | <p class="settings-intro small">Use <strong>Copy Hub URL, token & vault</strong> (Hub API section above) for connection secrets. The button below copies <em>only</em> embedding-related lines so a local indexer matches this Hub.</p> |
| 1387 | <details class="how-to-details"> |
| 1388 | <summary>Technical details — embedding env lines</summary> |
| 1389 | <div class="how-to-details-body"> |
| 1390 | <p class="settings-intro small" style="margin: 0;">Those lines align Ollama / provider URL and model with this deployment; they are separate from <code>KNOWTATION_HUB_URL</code> / token / vault id.</p> |
| 1391 | </div> |
| 1392 | </details> |
| 1393 | <div class="settings-actions" style="margin-top: 0.5rem;"> |
| 1394 | <button type="button" id="btn-copy-env-agentception" class="btn-secondary">Copy embedding env</button> |
| 1395 | <span id="agents-copy-msg" class="settings-msg"></span> |
| 1396 | </div> |
| 1397 | </div> |
| 1398 | </div> |
| 1399 | <div id="settings-panel-appearance" class="settings-panel" role="tabpanel"> |
| 1400 | <div class="settings-body"> |
| 1401 | <h3 class="settings-h3">Theme</h3> |
| 1402 | <div class="theme-section-row"> |
| 1403 | <div class="theme-toggle" id="theme-toggle" role="group" aria-label="Night or day"> |
| 1404 | <button type="button" class="theme-btn" data-theme="dark" aria-pressed="true">Night</button> |
| 1405 | <button type="button" class="theme-btn" data-theme="light" aria-pressed="false">Day</button> |
| 1406 | </div> |
| 1407 | <button type="button" class="btn-secondary theme-dashboard-colors-link" id="btn-scroll-dashboard-color-theme" aria-label="Scroll to dashboard color theme">Colors</button> |
| 1408 | </div> |
| 1409 | <hr class="settings-hr"> |
| 1410 | <h3 class="settings-h3">Accent color</h3> |
| 1411 | <p class="settings-intro small">Choose an accent for links, buttons, and highlights. Presets on the left; any exact color on the right.</p> |
| 1412 | <div class="accent-color-layout"> |
| 1413 | <div class="accent-preset-groups"> |
| 1414 | <div class="accent-preset-group"> |
| 1415 | <p class="accent-preset-group-label">Classic</p> |
| 1416 | <div class="accent-presets" role="group" aria-label="Classic accent colors"> |
| 1417 | <button type="button" class="accent-swatch" data-accent="#89cff0" title="Baby blue (default)" aria-label="Baby blue default"></button> |
| 1418 | <button type="button" class="accent-swatch" data-accent="#22c55e" title="Green" aria-label="Green"></button> |
| 1419 | <button type="button" class="accent-swatch" data-accent="#eab308" title="Amber" aria-label="Amber"></button> |
| 1420 | <button type="button" class="accent-swatch" data-accent="#f43f5e" title="Rose" aria-label="Rose"></button> |
| 1421 | <button type="button" class="accent-swatch" data-accent="#a855f7" title="Violet" aria-label="Violet"></button> |
| 1422 | <button type="button" class="accent-swatch" data-accent="#0ea5e9" title="Sky" aria-label="Sky"></button> |
| 1423 | </div> |
| 1424 | </div> |
| 1425 | <div class="accent-preset-group"> |
| 1426 | <p class="accent-preset-group-label">Pastels</p> |
| 1427 | <div class="accent-presets" role="group" aria-label="Pastel accent colors"> |
| 1428 | <button type="button" class="accent-swatch" data-accent="#f9a8d4" title="Pink pastel" aria-label="Pink pastel"></button> |
| 1429 | <button type="button" class="accent-swatch" data-accent="#6ee7b7" title="Mint" aria-label="Mint pastel"></button> |
| 1430 | <button type="button" class="accent-swatch" data-accent="#93c5fd" title="Baby blue" aria-label="Baby blue pastel"></button> |
| 1431 | <button type="button" class="accent-swatch" data-accent="#fcd34d" title="Butter yellow" aria-label="Butter yellow pastel"></button> |
| 1432 | <button type="button" class="accent-swatch" data-accent="#c4b5fd" title="Lilac" aria-label="Lilac pastel"></button> |
| 1433 | <button type="button" class="accent-swatch" data-accent="#bfdbfe" title="Soft sky" aria-label="Soft sky pastel"></button> |
| 1434 | </div> |
| 1435 | </div> |
| 1436 | <div class="accent-preset-group"> |
| 1437 | <p class="accent-preset-group-label">Earth</p> |
| 1438 | <div class="accent-presets" role="group" aria-label="Earth tone accent colors"> |
| 1439 | <button type="button" class="accent-swatch" data-accent="#c2410c" title="Terracotta" aria-label="Terracotta"></button> |
| 1440 | <button type="button" class="accent-swatch" data-accent="#4d7c0f" title="Moss green" aria-label="Moss green"></button> |
| 1441 | <button type="button" class="accent-swatch" data-accent="#a16207" title="Amber brown" aria-label="Amber brown"></button> |
| 1442 | <button type="button" class="accent-swatch" data-accent="#0f766e" title="Teal earth" aria-label="Teal earth"></button> |
| 1443 | <button type="button" class="accent-swatch" data-accent="#57534e" title="Stone" aria-label="Stone"></button> |
| 1444 | <button type="button" class="accent-swatch" data-accent="#6b5344" title="Coffee" aria-label="Coffee earth"></button> |
| 1445 | </div> |
| 1446 | </div> |
| 1447 | <div class="accent-preset-group"> |
| 1448 | <p class="accent-preset-group-label">Vivid</p> |
| 1449 | <div class="accent-presets" role="group" aria-label="Vivid accent colors"> |
| 1450 | <button type="button" class="accent-swatch" data-accent="#e11d48" title="Ruby" aria-label="Ruby"></button> |
| 1451 | <button type="button" class="accent-swatch" data-accent="#84cc16" title="Lime" aria-label="Lime"></button> |
| 1452 | <button type="button" class="accent-swatch" data-accent="#2563eb" title="Royal blue" aria-label="Royal blue"></button> |
| 1453 | <button type="button" class="accent-swatch" data-accent="#ea580c" title="Tangerine" aria-label="Tangerine"></button> |
| 1454 | <button type="button" class="accent-swatch" data-accent="#d946ef" title="Fuchsia" aria-label="Fuchsia"></button> |
| 1455 | <button type="button" class="accent-swatch" data-accent="#14b8a6" title="Teal" aria-label="Teal vivid"></button> |
| 1456 | </div> |
| 1457 | </div> |
| 1458 | <div class="accent-preset-group"> |
| 1459 | <p class="accent-preset-group-label">Muted</p> |
| 1460 | <div class="accent-presets" role="group" aria-label="Muted accent colors"> |
| 1461 | <button type="button" class="accent-swatch" data-accent="#64748b" title="Slate" aria-label="Slate muted"></button> |
| 1462 | <button type="button" class="accent-swatch" data-accent="#8b7355" title="Taupe" aria-label="Taupe muted"></button> |
| 1463 | <button type="button" class="accent-swatch" data-accent="#6b9080" title="Sage" aria-label="Sage muted"></button> |
| 1464 | <button type="button" class="accent-swatch" data-accent="#78716b" title="Warm gray" aria-label="Warm gray muted"></button> |
| 1465 | <button type="button" class="accent-swatch" data-accent="#7c6f9c" title="Dusty purple" aria-label="Dusty purple muted"></button> |
| 1466 | <button type="button" class="accent-swatch" data-accent="#4b5563" title="Blue gray" aria-label="Blue gray muted"></button> |
| 1467 | </div> |
| 1468 | </div> |
| 1469 | </div> |
| 1470 | <div class="accent-custom-column" aria-label="Custom accent color"> |
| 1471 | <p class="accent-preset-group-label accent-custom-heading">Custom</p> |
| 1472 | <div id="accent-iro-root" class="accent-iro-root"></div> |
| 1473 | <p class="accent-custom-hex-row"><code class="accent-custom-hex" id="accent-custom-hex">#89CFF0</code></p> |
| 1474 | </div> |
| 1475 | </div> |
| 1476 | <hr class="settings-hr"> |
| 1477 | <h3 class="settings-h3" id="settings-dashboard-color-theme">Dashboard color theme</h3> |
| 1478 | <p class="settings-intro small">Each preview is Night (left) then Day (right), four bands each: background, surface, border, secondary text—so you can see the real tint.</p> |
| 1479 | <div id="dashboard-theme-grid" class="dashboard-theme-grid" role="radiogroup" aria-label="Dashboard color theme"> |
| 1480 | <button type="button" class="dashboard-theme-card" role="radio" data-palette="default" aria-checked="true"> |
| 1481 | <span class="dashboard-theme-preview dashboard-theme-preview--classic" aria-hidden="true"></span> |
| 1482 | <span class="dashboard-theme-name">Classic</span> |
| 1483 | </button> |
| 1484 | <button type="button" class="dashboard-theme-card" role="radio" data-palette="ocean" aria-checked="false"> |
| 1485 | <span class="dashboard-theme-preview dashboard-theme-preview--ocean" aria-hidden="true"></span> |
| 1486 | <span class="dashboard-theme-name">Ocean</span> |
| 1487 | </button> |
| 1488 | <button type="button" class="dashboard-theme-card" role="radio" data-palette="forest" aria-checked="false"> |
| 1489 | <span class="dashboard-theme-preview dashboard-theme-preview--forest" aria-hidden="true"></span> |
| 1490 | <span class="dashboard-theme-name">Forest</span> |
| 1491 | </button> |
| 1492 | <button type="button" class="dashboard-theme-card" role="radio" data-palette="sunset" aria-checked="false"> |
| 1493 | <span class="dashboard-theme-preview dashboard-theme-preview--sunset" aria-hidden="true"></span> |
| 1494 | <span class="dashboard-theme-name">Sunset</span> |
| 1495 | </button> |
| 1496 | <button type="button" class="dashboard-theme-card" role="radio" data-palette="lavender" aria-checked="false"> |
| 1497 | <span class="dashboard-theme-preview dashboard-theme-preview--lavender" aria-hidden="true"></span> |
| 1498 | <span class="dashboard-theme-name">Lavender</span> |
| 1499 | </button> |
| 1500 | <button type="button" class="dashboard-theme-card" role="radio" data-palette="ember" aria-checked="false"> |
| 1501 | <span class="dashboard-theme-preview dashboard-theme-preview--ember" aria-hidden="true"></span> |
| 1502 | <span class="dashboard-theme-name">Ember</span> |
| 1503 | </button> |
| 1504 | <button type="button" class="dashboard-theme-card" role="radio" data-palette="arctic" aria-checked="false"> |
| 1505 | <span class="dashboard-theme-preview dashboard-theme-preview--arctic" aria-hidden="true"></span> |
| 1506 | <span class="dashboard-theme-name">Arctic</span> |
| 1507 | </button> |
| 1508 | <button type="button" class="dashboard-theme-card" role="radio" data-palette="slate" aria-checked="false"> |
| 1509 | <span class="dashboard-theme-preview dashboard-theme-preview--slate" aria-hidden="true"></span> |
| 1510 | <span class="dashboard-theme-name">Slate</span> |
| 1511 | </button> |
| 1512 | <button type="button" class="dashboard-theme-card" role="radio" data-palette="midnight" aria-checked="false"> |
| 1513 | <span class="dashboard-theme-preview dashboard-theme-preview--midnight" aria-hidden="true"></span> |
| 1514 | <span class="dashboard-theme-name">Midnight</span> |
| 1515 | </button> |
| 1516 | <button type="button" class="dashboard-theme-card" role="radio" data-palette="sakura" aria-checked="false"> |
| 1517 | <span class="dashboard-theme-preview dashboard-theme-preview--sakura" aria-hidden="true"></span> |
| 1518 | <span class="dashboard-theme-name">Sakura</span> |
| 1519 | </button> |
| 1520 | <button type="button" class="dashboard-theme-card" role="radio" data-palette="sand" aria-checked="false"> |
| 1521 | <span class="dashboard-theme-preview dashboard-theme-preview--sand" aria-hidden="true"></span> |
| 1522 | <span class="dashboard-theme-name">Sand</span> |
| 1523 | </button> |
| 1524 | <button type="button" class="dashboard-theme-card" role="radio" data-palette="mint" aria-checked="false"> |
| 1525 | <span class="dashboard-theme-preview dashboard-theme-preview--mint" aria-hidden="true"></span> |
| 1526 | <span class="dashboard-theme-name">Mint</span> |
| 1527 | </button> |
| 1528 | </div> |
| 1529 | </div> |
| 1530 | </div> |
| 1531 | <div id="settings-panel-billing" class="settings-panel" role="tabpanel"> |
| 1532 | <div class="settings-body"> |
| 1533 | <p class="settings-intro">Your Knowtation plan and usage. Indexing tokens are consumed each time you Re-index your vault. Semantic search is included on all plans.</p> |
| 1534 | <p class="settings-intro small muted" id="billing-panel-msg"></p> |
| 1535 | |
| 1536 | <!-- Plan badge + renewal --> |
| 1537 | <div class="settings-row" style="align-items: center; gap: 0.6rem; flex-wrap: wrap;"> |
| 1538 | <span class="settings-label">Plan</span> |
| 1539 | <span id="billing-tier" class="billing-plan-badge tier-beta">—</span> |
| 1540 | <span id="billing-renewal" class="muted small" style="margin-left: 0.25rem;"></span> |
| 1541 | </div> |
| 1542 | |
| 1543 | <!-- Plan comparison grid (populated by hub.js) --> |
| 1544 | <div id="billing-plan-grid" class="billing-plan-grid"></div> |
| 1545 | |
| 1546 | <!-- Action row: Manage portal + Refresh --> |
| 1547 | <div class="billing-cta-row" style="margin-top: 0.5rem;"> |
| 1548 | <button type="button" id="btn-billing-manage" class="btn-secondary" style="display:none;">Manage billing →</button> |
| 1549 | <button type="button" id="btn-billing-refresh" class="btn-secondary">Refresh</button> |
| 1550 | </div> |
| 1551 | <!-- Legacy upgrade button — hidden, kept so startup JS listener attaches without null-check error --> |
| 1552 | <button type="button" id="btn-billing-upgrade" style="display:none;" aria-hidden="true"></button> |
| 1553 | |
| 1554 | <hr class="settings-hr"> |
| 1555 | |
| 1556 | <!-- Usage this period: searches + index jobs --> |
| 1557 | <div class="settings-row" style="flex-direction: column; align-items: flex-start; gap: 0.55rem;"> |
| 1558 | <span class="settings-label">Usage this period</span> |
| 1559 | <!-- Searches --> |
| 1560 | <div class="billing-op-row"> |
| 1561 | <span class="billing-op-label">Searches</span> |
| 1562 | <div class="billing-usage-bar-wrap"> |
| 1563 | <div class="billing-usage-bar-track"> |
| 1564 | <div id="billing-searches-bar-fill" class="billing-usage-bar-fill" style="width: 0%;"></div> |
| 1565 | </div> |
| 1566 | <div class="billing-usage-bar-label"> |
| 1567 | <span id="billing-searches-used">—</span> / <span id="billing-searches-included">—</span> |
| 1568 | </div> |
| 1569 | </div> |
| 1570 | </div> |
| 1571 | <!-- Index jobs --> |
| 1572 | <div class="billing-op-row"> |
| 1573 | <span class="billing-op-label">Index jobs</span> |
| 1574 | <div class="billing-usage-bar-wrap"> |
| 1575 | <div class="billing-usage-bar-track"> |
| 1576 | <div id="billing-index-jobs-bar-fill" class="billing-usage-bar-fill" style="width: 0%;"></div> |
| 1577 | </div> |
| 1578 | <div class="billing-usage-bar-label"> |
| 1579 | <span id="billing-index-jobs-used">—</span> / <span id="billing-index-jobs-included">—</span> |
| 1580 | </div> |
| 1581 | </div> |
| 1582 | </div> |
| 1583 | <!-- Consolidation jobs --> |
| 1584 | <div class="billing-op-row"> |
| 1585 | <span class="billing-op-label">Consolidations</span> |
| 1586 | <div class="billing-usage-bar-wrap"> |
| 1587 | <div class="billing-usage-bar-track"> |
| 1588 | <div id="billing-consol-bar-fill" class="billing-usage-bar-fill" style="width: 0%;"></div> |
| 1589 | </div> |
| 1590 | <div class="billing-usage-bar-label"> |
| 1591 | <span id="billing-consol-used">—</span> / <span id="billing-consol-included">—</span> |
| 1592 | </div> |
| 1593 | </div> |
| 1594 | </div> |
| 1595 | <!-- Pack balance (secondary) --> |
| 1596 | <div class="billing-usage-bar-label muted" id="billing-pack-balance-row" style="display:none;"> |
| 1597 | Pack balance: <span id="billing-pack-balance">0</span> |
| 1598 | </div> |
| 1599 | </div> |
| 1600 | |
| 1601 | <!-- Note count --> |
| 1602 | <div class="settings-row" style="margin-top: 0.5rem;"> |
| 1603 | <span class="settings-label">Notes</span> |
| 1604 | <span id="billing-note-cap" class="settings-value muted small">—</span> |
| 1605 | </div> |
| 1606 | |
| 1607 | <!-- Period --> |
| 1608 | <div class="settings-row"> |
| 1609 | <span class="settings-label">Period</span> |
| 1610 | <span id="billing-period" class="settings-value muted small">—</span> |
| 1611 | </div> |
| 1612 | |
| 1613 | <!-- Legacy credits row (hidden when 0) --> |
| 1614 | <div class="settings-row" id="billing-credits-row" style="display:none;"> |
| 1615 | <span class="settings-label">Legacy credits</span> |
| 1616 | <span id="billing-credits-used" class="settings-value muted small">—</span> |
| 1617 | </div> |
| 1618 | |
| 1619 | <hr class="settings-hr"> |
| 1620 | |
| 1621 | <!-- Token pack purchase (hidden until loadBillingPanel decides user may purchase; avoids flash on beta/free) --> |
| 1622 | <div id="billing-pack-section" style="display:none;"> |
| 1623 | <h3 class="settings-h3">Token pack add-ons</h3> |
| 1624 | <p class="settings-intro small muted">Extra indexing tokens that roll over. Consumed after your monthly grant runs out. Available on paid plans.</p> |
| 1625 | <div class="billing-pack-grid" id="billing-pack-grid"> |
| 1626 | <button type="button" class="billing-pack-card" id="btn-pack-small" data-pack="small"> |
| 1627 | <div class="billing-pack-name">Small pack</div> |
| 1628 | <div class="billing-pack-price">$10</div> |
| 1629 | <div class="billing-pack-tokens">+20M indexing tokens</div> |
| 1630 | <div class="billing-pack-equiv">≈ 400 index jobs or 20,000 searches</div> |
| 1631 | <div class="billing-pack-equiv">+50 memory consolidations</div> |
| 1632 | </button> |
| 1633 | <button type="button" class="billing-pack-card" id="btn-pack-medium" data-pack="medium"> |
| 1634 | <div class="billing-pack-name">Medium pack</div> |
| 1635 | <div class="billing-pack-price">$25</div> |
| 1636 | <div class="billing-pack-tokens">+60M indexing tokens</div> |
| 1637 | <div class="billing-pack-equiv">≈ 1,200 index jobs or 60,000 searches</div> |
| 1638 | <div class="billing-pack-equiv">+150 memory consolidations</div> |
| 1639 | </button> |
| 1640 | <button type="button" class="billing-pack-card" id="btn-pack-large" data-pack="large"> |
| 1641 | <div class="billing-pack-name">Large pack</div> |
| 1642 | <div class="billing-pack-price">$50</div> |
| 1643 | <div class="billing-pack-tokens">+150M indexing tokens</div> |
| 1644 | <div class="billing-pack-equiv">≈ 3,000 index jobs or 150,000 searches</div> |
| 1645 | <div class="billing-pack-equiv">+350 memory consolidations</div> |
| 1646 | </button> |
| 1647 | </div> |
| 1648 | <p class="settings-intro small muted" id="billing-pack-msg" style="margin-top: 0.5rem;"></p> |
| 1649 | </div> |
| 1650 | |
| 1651 | <hr class="settings-hr"> |
| 1652 | <p class="settings-intro small" id="billing-indexing-policy" style="display:none;"></p> |
| 1653 | <p class="settings-intro small muted">Self-hosted Hub (no gateway) does not expose this API — use the hosted Hub or <code>GET /api/v1/billing/summary</code> for operators.</p> |
| 1654 | |
| 1655 | <!-- Born Free blurb --> |
| 1656 | <p class="billing-bornfree-blurb">Knowtation is presented by <a href="https://bornfree.io" target="_blank" rel="noopener">Born Free Communities</a>. We developed this for our use and thought we should share it with everyone.</p> |
| 1657 | </div> |
| 1658 | </div> |
| 1659 | <div id="settings-panel-consolidation" class="settings-panel" role="tabpanel"> |
| 1660 | <div class="settings-body"> |
| 1661 | <h3 class="settings-h3">Memory Consolidation</h3> |
| 1662 | <p class="settings-intro small">Knowtation is built to reduce wasted context: consolidation merges noisy memory events into facts; agents should search narrowly then open specific notes. <button type="button" id="btn-consol-how-token-savings" class="btn-link btn-link-small">How to use → Token savings</button> · <a href="https://github.com/aaronrene/knowtation/blob/main/docs/TOKEN-SAVINGS.md" target="_blank" rel="noopener">docs/TOKEN-SAVINGS.md</a> (repo)</p> |
| 1663 | |
| 1664 | <div class="settings-form" style="gap: 0.75rem;"> |
| 1665 | <div> |
| 1666 | <label style="font-weight: 600; margin-bottom: 0.35rem; display: block;">Mode</label> |
| 1667 | <div class="consol-radio-group"> |
| 1668 | <label class="settings-checkbox-label"><input type="radio" name="consol-mode" value="daemon"> Self-Hosted (daemon)</label> |
| 1669 | <label class="settings-checkbox-label"><input type="radio" name="consol-mode" value="hosted"> Hosted (Hub)</label> |
| 1670 | <label class="settings-checkbox-label"><input type="radio" name="consol-mode" value="off" checked> Off</label> |
| 1671 | </div> |
| 1672 | <p class="settings-intro small muted" style="margin-top: 0.35rem;">Self-hosted runs on your machine. Hosted uses the Hub's LLM (included in your plan).</p> |
| 1673 | </div> |
| 1674 | |
| 1675 | <div id="consol-daemon-settings" class="consol-mode-section" style="display:none;"> |
| 1676 | <div style="display: flex; flex-direction: column; gap: 0.5rem;"> |
| 1677 | <div> |
| 1678 | <label for="consol-interval" style="font-weight: 500;">Interval <span class="muted small">(minutes between passes)</span></label> |
| 1679 | <input type="number" id="consol-interval" class="settings-input-inline" value="120" min="30" max="10080" style="width: 7rem; display: block; margin-top: 0.25rem;"> |
| 1680 | </div> |
| 1681 | <label class="settings-checkbox-label"> |
| 1682 | <input type="checkbox" id="consol-idle-only" checked> Idle only <span class="muted small">— only run when inactive</span> |
| 1683 | </label> |
| 1684 | <div> |
| 1685 | <label for="consol-idle-threshold" style="font-weight: 500;">Idle threshold <span class="muted small">(minutes of inactivity)</span></label> |
| 1686 | <input type="number" id="consol-idle-threshold" class="settings-input-inline" value="15" min="1" style="width: 5rem; display: block; margin-top: 0.25rem;"> |
| 1687 | </div> |
| 1688 | <label class="settings-checkbox-label"> |
| 1689 | <input type="checkbox" id="consol-run-on-start"> Run on start <span class="muted small">— run one pass when daemon starts</span> |
| 1690 | </label> |
| 1691 | <fieldset style="border: 1px solid var(--border); border-radius: 8px; padding: 0.75rem 1rem; margin: 0.5rem 0 0 0;"> |
| 1692 | <legend style="font-weight: 600; font-size: 0.9rem; padding: 0 0.35rem;">Advanced <span class="muted small">(pass scope — saved to local.yaml)</span></legend> |
| 1693 | <p class="settings-intro small muted" style="margin: 0 0 0.5rem 0;">Tune how much each pass reads and how long model replies can be. See <a href="https://github.com/aaronrene/knowtation/blob/main/docs/TOKEN-SAVINGS.md" target="_blank" rel="noopener">TOKEN-SAVINGS.md</a>.</p> |
| 1694 | <div style="display: flex; flex-direction: column; gap: 0.5rem;"> |
| 1695 | <div> |
| 1696 | <label for="consol-lookback-hours" style="font-weight: 500;">Lookback <span class="muted small">(hours)</span></label> |
| 1697 | <input type="number" id="consol-lookback-hours" class="settings-input-inline" value="24" min="1" max="8760" style="width: 6rem; display: block; margin-top: 0.25rem;"> |
| 1698 | </div> |
| 1699 | <div> |
| 1700 | <label for="consol-max-events" style="font-weight: 500;">Max events per pass</label> |
| 1701 | <input type="number" id="consol-max-events" class="settings-input-inline" value="200" min="1" max="10000" style="width: 7rem; display: block; margin-top: 0.25rem;"> |
| 1702 | </div> |
| 1703 | <div> |
| 1704 | <label for="consol-max-topics" style="font-weight: 500;">Max topics per pass</label> |
| 1705 | <input type="number" id="consol-max-topics" class="settings-input-inline" value="10" min="1" max="500" style="width: 6rem; display: block; margin-top: 0.25rem;"> |
| 1706 | </div> |
| 1707 | <div> |
| 1708 | <label for="consol-llm-max-tokens" style="font-weight: 500;">Max LLM output tokens <span class="muted small">(per call)</span></label> |
| 1709 | <input type="number" id="consol-llm-max-tokens" class="settings-input-inline" value="1024" min="64" max="8192" style="width: 7rem; display: block; margin-top: 0.25rem;"> |
| 1710 | </div> |
| 1711 | </div> |
| 1712 | </fieldset> |
| 1713 | </div> |
| 1714 | </div> |
| 1715 | |
| 1716 | <div id="consol-hosted-settings" class="consol-mode-section" style="display:none;"> |
| 1717 | <div> |
| 1718 | <label for="consol-hosted-interval" style="font-weight: 500;">Schedule <span class="muted small">(Hub runs automatically)</span></label> |
| 1719 | <select id="consol-hosted-interval" class="settings-select-inline" style="display: block; margin-top: 0.25rem;"> |
| 1720 | <option value="30">Every 30 minutes</option> |
| 1721 | <option value="60">Every hour</option> |
| 1722 | <option value="120" selected>Every 2 hours</option> |
| 1723 | <option value="360">Every 6 hours</option> |
| 1724 | <option value="720">Every 12 hours</option> |
| 1725 | <option value="1440">Daily</option> |
| 1726 | <option value="10080">Weekly</option> |
| 1727 | </select> |
| 1728 | </div> |
| 1729 | </div> |
| 1730 | |
| 1731 | <fieldset style="border: 1px solid var(--border); border-radius: 8px; padding: 0.75rem 1rem; margin: 0;"> |
| 1732 | <legend style="font-weight: 600; font-size: 0.9rem; padding: 0 0.35rem;">Passes</legend> |
| 1733 | <div style="display: flex; flex-direction: column; gap: 0.35rem;"> |
| 1734 | <label class="settings-checkbox-label"><input type="checkbox" id="pass-consolidate" checked> Consolidate — merge & deduplicate events (recommended)</label> |
| 1735 | <label class="settings-checkbox-label"><input type="checkbox" id="pass-verify" checked> Verify — detect stale note references (recommended)</label> |
| 1736 | <label class="settings-checkbox-label"><input type="checkbox" id="pass-discover"> Discover — cross-topic insights (optional, off by default)</label> |
| 1737 | </div> |
| 1738 | <p class="settings-intro small muted" style="margin: 0.5rem 0 0 0;">Discover runs an <strong>extra AI step</strong> after Consolidate when topics were merged. On <strong>hosted</strong> plans it still counts as <strong>one consolidation pass per run</strong> (same allowance entry as without Discover)—you are not charged two passes. It increases provider token use; leave it off unless you want linkages and open questions across topics.</p> |
| 1739 | </fieldset> |
| 1740 | |
| 1741 | <fieldset id="consol-llm-settings" style="border: 1px solid var(--border); border-radius: 8px; padding: 0.75rem 1rem; margin: 0; display:none;"> |
| 1742 | <legend style="font-weight: 600; font-size: 0.9rem; padding: 0 0.35rem;">LLM Override <span class="muted small">(self-hosted only — optional)</span></legend> |
| 1743 | <div style="display: flex; flex-direction: column; gap: 0.5rem;"> |
| 1744 | <div> |
| 1745 | <label for="consol-llm-provider" style="font-weight: 500;">Provider</label> |
| 1746 | <select id="consol-llm-provider" class="settings-select-inline" style="display: block; margin-top: 0.25rem;"> |
| 1747 | <option value="">auto-detect</option> |
| 1748 | <option value="openai">OpenAI</option> |
| 1749 | <option value="anthropic">Anthropic</option> |
| 1750 | <option value="ollama">Ollama (local, free)</option> |
| 1751 | <option value="openrouter">OpenRouter</option> |
| 1752 | </select> |
| 1753 | </div> |
| 1754 | <div> |
| 1755 | <label for="consol-llm-model" style="font-weight: 500;">Model</label> |
| 1756 | <input type="text" id="consol-llm-model" class="settings-input-inline" placeholder="e.g. gpt-4o-mini" style="display: block; margin-top: 0.25rem; width: 100%; max-width: 18rem;"> |
| 1757 | </div> |
| 1758 | <div> |
| 1759 | <label for="consol-llm-base-url" style="font-weight: 500;">Base URL <span class="muted small">(for OpenAI-compatible endpoints)</span></label> |
| 1760 | <input type="text" id="consol-llm-base-url" class="settings-input-inline" placeholder="https://openrouter.ai/api/v1" style="display: block; margin-top: 0.25rem; width: 100%; max-width: 22rem;"> |
| 1761 | </div> |
| 1762 | </div> |
| 1763 | </fieldset> |
| 1764 | |
| 1765 | <fieldset id="consol-cost-guard" style="border: 1px solid var(--border); border-radius: 8px; padding: 0.75rem 1rem; margin: 0; display:none;"> |
| 1766 | <legend style="font-weight: 600; font-size: 0.9rem; padding: 0 0.35rem;">Cost Guard <span class="muted small">(self-hosted only)</span></legend> |
| 1767 | <div> |
| 1768 | <label for="consol-cost-cap" style="font-weight: 500;">Daily cap (USD) <span class="muted small">— leave blank for no limit</span></label> |
| 1769 | <input type="number" id="consol-cost-cap" class="settings-input-inline" placeholder="no limit" min="0" step="0.01" style="display: block; margin-top: 0.25rem; width: 8rem;"> |
| 1770 | </div> |
| 1771 | </fieldset> |
| 1772 | |
| 1773 | <div class="settings-form-actions"> |
| 1774 | <button type="button" id="btn-consol-save" class="btn-primary">Save Settings</button> |
| 1775 | <span id="consol-save-status" class="settings-msg"></span> |
| 1776 | </div> |
| 1777 | <p class="settings-intro small muted" style="margin-top: 0;"><a href="#" id="link-consol-help" class="btn-link btn-link-small">Learn more about Memory Consolidation ↗</a></p> |
| 1778 | </div> |
| 1779 | </div> |
| 1780 | </div> |
| 1781 | </div> |
| 1782 | </div> |
| 1783 | |
| 1784 | <div id="modal-how-to-use" class="modal hidden" aria-modal="true" role="dialog" aria-labelledby="how-to-use-title"> |
| 1785 | <div class="modal-backdrop" id="modal-how-to-use-backdrop"></div> |
| 1786 | <div class="modal-card modal-card-how-to-use"> |
| 1787 | <div class="modal-header"> |
| 1788 | <h2 id="how-to-use-title">How to use Knowtation Hub</h2> |
| 1789 | <button type="button" id="modal-how-to-use-close" class="modal-close" aria-label="Close">×</button> |
| 1790 | </div> |
| 1791 | <nav class="how-to-tabs" role="tablist" aria-label="How to use sections"> |
| 1792 | <button type="button" class="how-to-tab active" role="tab" aria-selected="true" data-how-to-tab="setup">Setup</button> |
| 1793 | <button type="button" class="how-to-tab" role="tab" aria-selected="false" data-how-to-tab="getting-started">Getting started</button> |
| 1794 | <button type="button" class="how-to-tab" role="tab" aria-selected="false" data-how-to-tab="knowledge-agents">Knowledge & agents</button> |
| 1795 | <button type="button" class="how-to-tab" role="tab" aria-selected="false" data-how-to-tab="media">Media & images</button> |
| 1796 | <button type="button" class="how-to-tab" role="tab" aria-selected="false" data-how-to-tab="consolidation">Memory consolidation</button> |
| 1797 | <button type="button" class="how-to-tab" role="tab" aria-selected="false" data-how-to-tab="token-savings">Token savings</button> |
| 1798 | </nav> |
| 1799 | <div id="how-to-panel-getting-started" class="how-to-panel" role="tabpanel"> |
| 1800 | <div class="how-to-use-body"> |
| 1801 | <p class="how-to-intro">Open the in-app walkthrough to create your first notes, see optional GitHub backup, and learn where AI-suggested edits appear (<strong>Suggested</strong>). Best for <strong>hosted</strong> users; self-hosted operators can use it too, then read <strong>Setup → Self-hosted setup</strong> for machine install details.</p> |
| 1802 | <p><button type="button" id="btn-how-to-open-onboarding" class="btn-primary">Open setup walkthrough</button></p> |
| 1803 | <p class="how-to-note small" style="margin-bottom:0;">Start over from step 1: <strong>Settings → Backup → Setup guide</strong>.</p> |
| 1804 | </div> |
| 1805 | </div> |
| 1806 | <div id="how-to-panel-setup" class="how-to-panel active" role="tabpanel"> |
| 1807 | <div class="how-to-use-body"> |
| 1808 | <div class="how-to-two-paths-box how-to-hosted-lead" role="region" aria-label="Hosted Hub"> |
| 1809 | <h3 class="how-to-two-paths-title">Hosted Hub — start here</h3> |
| 1810 | <p class="how-to-note small" style="margin-top:0;">If <strong>Settings → Backup → Mode</strong> shows <strong>Hosted (beta)</strong>, you do <em>not</em> install a server or pick a folder on your laptop. Your vault lives in the cloud; we handle search indexing.</p> |
| 1811 | <ol class="how-to-steps-list" style="margin: 0.5rem 0 0;"> |
| 1812 | <li><strong>Notes</strong> — Import or write notes; use the header <strong>Vault</strong> menu if you have more than one notebook.</li> |
| 1813 | <li><strong>Optional backup</strong> — Create an <em>empty</em> GitHub repo, connect your account under Backup, enter <code>owner/repo</code>, then <strong>Back up now</strong>.</li> |
| 1814 | <li><strong>Connect an AI assistant</strong> — <strong>Settings → Integrations → Hub API</strong> has copy buttons. Read <strong>Knowledge & agents</strong> for a plain-English explanation of the two copy types.</li> |
| 1815 | <li><strong>Edits from tools</strong> — Appear under <strong>Suggested</strong> until you approve (nothing applies to your vault until you approve).</li> |
| 1816 | </ol> |
| 1817 | <p class="how-to-note small" style="margin:0.75rem 0 0;">Running the Hub on your own machine instead? Open <strong>Self-hosted setup</strong> below.</p> |
| 1818 | </div> |
| 1819 | |
| 1820 | <details class="how-to-details how-to-selfhosted-details"> |
| 1821 | <summary>Self-hosted setup — install the Hub on your computer</summary> |
| 1822 | <div class="how-to-details-body"> |
| 1823 | <div class="how-to-two-paths-box" role="region" aria-label="Self-hosted summary"> |
| 1824 | <h3 class="how-to-two-paths-title">Self-hosted in one sentence</h3> |
| 1825 | <p class="how-to-note small" style="margin-bottom:0;">You run <code>npm run hub</code>, point it at a <strong>folder of Markdown notes</strong> on disk, sign in with OAuth you configure, and (for meaning-based search) run an indexer once. <strong>Settings → Backup → Mode</strong> shows “Self-hosted”.</p> |
| 1826 | </div> |
| 1827 | <details class="how-to-details"> |
| 1828 | <summary>Full developer docs (install, config, MCP, checklist)</summary> |
| 1829 | <div class="how-to-details-body"> |
| 1830 | <ul class="how-to-two-paths-list" style="margin:0;"> |
| 1831 | <li><a href="https://github.com/aaronrene/knowtation/blob/main/docs/GETTING-STARTED.md" target="_blank" rel="noopener">GETTING-STARTED.md</a> — install → search → optional Hub.</li> |
| 1832 | <li><a href="https://github.com/aaronrene/knowtation/blob/main/docs/setup.md" target="_blank" rel="noopener">setup.md</a> — embeddings, transcription, MCP, Hub.</li> |
| 1833 | <li><a href="https://github.com/aaronrene/knowtation/blob/main/docs/SELF-HOSTED-SETUP-CHECKLIST.md" target="_blank" rel="noopener">SELF-HOSTED-SETUP-CHECKLIST.md</a> — one-page checklist.</li> |
| 1834 | </ul> |
| 1835 | </div> |
| 1836 | </details> |
| 1837 | <p class="how-to-intro" style="margin-top:1rem;"><strong>Self-hosted:</strong> follow the numbered steps below in order. Skip this whole block if you are on <strong>hosted</strong> only.</p> |
| 1838 | |
| 1839 | <div class="how-to-flow" aria-hidden="true"> |
| 1840 | <div class="flow-step"><span class="flow-num">1</span><span>Vault & config</span></div> |
| 1841 | <span class="flow-arrow">→</span> |
| 1842 | <div class="flow-step"><span class="flow-num">2</span><span>Run Hub</span></div> |
| 1843 | <span class="flow-arrow">→</span> |
| 1844 | <div class="flow-step"><span class="flow-num">3</span><span>Log in</span></div> |
| 1845 | <span class="flow-arrow">→</span> |
| 1846 | <div class="flow-step"><span class="flow-num">4</span><span>Index & search</span></div> |
| 1847 | <span class="flow-arrow">→</span> |
| 1848 | <div class="flow-step"><span class="flow-num">5</span><span>Import data</span></div> |
| 1849 | <span class="flow-arrow">→</span> |
| 1850 | <div class="flow-step"><span class="flow-num">6</span><span>Use & automate</span></div> |
| 1851 | <span class="flow-arrow">→</span> |
| 1852 | <div class="flow-step"><span class="flow-num">7</span><span>GitHub backup</span></div> |
| 1853 | </div> |
| 1854 | |
| 1855 | <section class="how-to-step"> |
| 1856 | <h3><span class="step-num">Step 1</span> Vault and config</h3> |
| 1857 | <p class="step-what">What this does: Tells Knowtation where your notes live so the Hub and CLI read and write the same folder. The vault is just Markdown files — not the Knowtation source code.</p> |
| 1858 | <ul> |
| 1859 | <li>Create a folder for notes (any path you like). Example in your home directory:</li> |
| 1860 | </ul> |
| 1861 | <div class="example-block"> |
| 1862 | <span class="example-label">Terminal</span> |
| 1863 | <pre>mkdir -p ~/knowtation-vault</pre> |
| 1864 | </div> |
| 1865 | <ul> |
| 1866 | <li>Set <strong>the same absolute path</strong> in two places: (1) env var <code>KNOWTATION_VAULT_PATH</code> in <code>.env</code> at the project root, and (2) <code>vault_path:</code> in <code>config/local.yaml</code> (so CLI, indexer, and Hub agree).</li> |
| 1867 | <li>For <strong>semantic search</strong> without a separate database server, add <code>vector_store: sqlite-vec</code> and <code>data_dir: data/</code> — vectors are stored in a local SQLite file under <code>data/</code>, not in Qdrant. (Optional: use <code>qdrant</code> + <code>qdrant_url</code> if you run Qdrant yourself.)</li> |
| 1868 | </ul> |
| 1869 | <div class="example-block"> |
| 1870 | <span class="example-label">Example <code>config/local.yaml</code> (paths must be absolute)</span> |
| 1871 | <pre>vault_path: /Users/you/knowtation-vault |
| 1872 | data_dir: data/ |
| 1873 | vector_store: sqlite-vec |
| 1874 | embedding: |
| 1875 | provider: ollama |
| 1876 | model: nomic-embed-text</pre> |
| 1877 | </div> |
| 1878 | <p class="how-to-note"><strong>Already developing Knowtation?</strong> You can skip <code>git clone</code> — use your existing repo. Create the vault folder outside the repo (e.g. <code>~/knowtation-vault</code>) so your personal notes stay separate from the app source.</p> |
| 1879 | </section> |
| 1880 | <section class="how-to-step"> |
| 1881 | <h3><span class="step-num">Step 2</span> Run the Hub</h3> |
| 1882 | <p class="step-what">What this does: Starts the web app (this UI) and the API on your machine. You do <strong>not</strong> clone a separate “site” — the Hub process serves both.</p> |
| 1883 | <ul> |
| 1884 | <li>One-time: <code>cd hub && npm install && cd ..</code> from the Knowtation project root.</li> |
| 1885 | <li>From the project root run <code>npm run hub</code>.</li> |
| 1886 | <li>Open <code>http://localhost:3333</code> (or the port you set with <code>HUB_PORT</code>). Use <code>http://</code> — not <code>https://localhost</code>.</li> |
| 1887 | </ul> |
| 1888 | <div class="example-block"> |
| 1889 | <span class="example-label">Example</span> |
| 1890 | <pre>$ npm run hub |
| 1891 | Knowtation Hub listening on http://localhost:3333</pre> |
| 1892 | </div> |
| 1893 | </section> |
| 1894 | |
| 1895 | <section id="how-to-step-selfhosted-oauth" class="how-to-step"> |
| 1896 | <h3><span class="step-num">Step 3</span> Log in (OAuth)</h3> |
| 1897 | <p class="step-what">What this does: Proves who you are so the Hub can show your vault and let you approve proposals.</p> |
| 1898 | <ul> |
| 1899 | <li>Click “Continue with Google” or “Continue with GitHub” on the login screen.</li> |
| 1900 | <li><strong>No OAuth secrets ship in the repo.</strong> Each self-hosted install registers its own Google/GitHub OAuth app and puts <code>GOOGLE_CLIENT_ID</code>, <code>GOOGLE_CLIENT_SECRET</code>, and/or <code>GITHUB_CLIENT_ID</code>, <code>GITHUB_CLIENT_SECRET</code> in <code>.env</code>. Add redirect URIs in the provider’s console (e.g. <code>http://localhost:3333/api/v1/auth/callback/google</code>).</li> |
| 1901 | <li>If you see “OAuth is not configured”, add those variables, restart the Hub, and try again.</li> |
| 1902 | </ul> |
| 1903 | <p class="how-to-note"><strong>Hosted users</strong> (knowtation.store) use our gateway’s OAuth — you do not add client IDs on your machine.</p> |
| 1904 | </section> |
| 1905 | |
| 1906 | <section id="how-to-step-selfhosted-index" class="how-to-step"> |
| 1907 | <h3><span class="step-num">Step 4</span> Index and semantic search (self-hosted)</h3> |
| 1908 | <p class="step-what">What this does: Turns your notes into searchable vectors. <strong>Listing and opening notes</strong> works without this. <strong>Search vault</strong> in the Hub (and CLI <code>knowtation search</code>) needs an index.</p> |
| 1909 | <p class="how-to-note"><strong>Hosted:</strong> skip this — we run indexing for you.</p> |
| 1910 | <h4 class="how-to-sub">Two separate choices (simple mental model)</h4> |
| 1911 | <ul> |
| 1912 | <li><strong>Where vectors are stored:</strong> <code>sqlite-vec</code> (default in examples) = one SQLite file under <code>data/</code>, no extra server. <strong>Or</strong> <code>qdrant</code> + <code>qdrant_url</code> = a separate Qdrant service (Docker or cloud). Same job; different deployment.</li> |
| 1913 | <li><strong>How text becomes vectors (embeddings):</strong> <strong>Ollama</strong> locally (e.g. <code>ollama pull nomic-embed-text</code>) <strong>or</strong> <strong>OpenAI</strong> (<code>OPENAI_API_KEY</code> in <code>.env</code> + <code>embedding.provider: openai</code> in config). This is not a chat “LLM” — it’s the model that encodes text for search.</li> |
| 1914 | </ul> |
| 1915 | <p>After <code>config/local.yaml</code> matches Step 1, run once from project root:</p> |
| 1916 | <div class="example-block"> |
| 1917 | <span class="example-label">Terminal</span> |
| 1918 | <pre>npm run index</pre> |
| 1919 | </div> |
| 1920 | <p>Or in the Hub: <strong>Re-index</strong> (same operation). After big imports, run index again. Full detail: <a href="https://github.com/aaronrene/knowtation/blob/main/docs/setup.md" target="_blank" rel="noopener">setup.md</a> § Index.</p> |
| 1921 | </section> |
| 1922 | |
| 1923 | <section class="how-to-step"> |
| 1924 | <h3><span class="step-num">Step 5</span> Import data into the vault</h3> |
| 1925 | <p class="step-what">What this does: Brings in notes from Slack, files, ChatGPT, or other tools into your <strong>vault folder</strong> as Markdown. They show up in the Hub list immediately. For <strong>semantic search</strong> to include new files, run Step 4 again (index or Re-index).</p> |
| 1926 | <h4 class="how-to-sub">Integrations at a glance</h4> |
| 1927 | <p class="how-to-note" style="margin-bottom: 0.5rem;"><strong>Capture (messages → vault):</strong> Slack, Discord, Telegram, WhatsApp (via webhook or Zapier/n8n). <strong>Import (exports → vault):</strong> ChatGPT, Claude, Mem0, Notion, Jira, NotebookLM, Google Drive, Linear, and generic Markdown/files. Expand each source below for setup steps.</p> |
| 1928 | <div class="diagram-box"> |
| 1929 | <div class="diagram-title">Where data comes from → where it goes</div> |
| 1930 | <svg class="diagram-svg" viewBox="0 0 540 80" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> |
| 1931 | <defs><marker id="arrow-data" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto"><path d="M0 0 L8 4 L0 8 Z" fill="var(--accent)"/></marker></defs> |
| 1932 | <!-- Source box wide enough that text never reaches the arrow; smaller font so it fits --> |
| 1933 | <rect x="10" y="4" width="148" height="48" rx="4" fill="var(--surface)" stroke="var(--border)" stroke-width="1"/> |
| 1934 | <text x="84" y="26" class="diagram-text" text-anchor="middle" style="font-size: 9px;">Slack / Discord / File / ChatGPT</text> |
| 1935 | <text x="84" y="44" class="diagram-text-small" text-anchor="middle">Webhook or script</text> |
| 1936 | <path d="M 161 24 L 198 24" stroke="var(--accent)" stroke-width="2" fill="none" marker-end="url(#arrow-data)"/> |
| 1937 | <rect x="203" y="8" width="90" height="32" rx="4" fill="var(--surface)" stroke="var(--accent)" stroke-width="1.5"/> |
| 1938 | <text x="248" y="28" class="diagram-text" text-anchor="middle">Capture</text> |
| 1939 | <path d="M 296 24 L 332 24" stroke="var(--accent)" stroke-width="2" fill="none" marker-end="url(#arrow-data)"/> |
| 1940 | <rect x="337" y="8" width="70" height="32" rx="4" fill="var(--surface)" stroke="var(--accent)" stroke-width="1.5"/> |
| 1941 | <text x="372" y="28" class="diagram-text" text-anchor="middle">Vault</text> |
| 1942 | <path d="M 410 24 L 446 24" stroke="var(--accent)" stroke-width="2" fill="none" marker-end="url(#arrow-data)"/> |
| 1943 | <rect x="451" y="8" width="78" height="32" rx="4" fill="var(--surface)" stroke="var(--accent)" stroke-width="1.5"/> |
| 1944 | <text x="490" y="28" class="diagram-text" text-anchor="middle">Hub UI / API</text> |
| 1945 | </svg> |
| 1946 | </div> |
| 1947 | <p class="how-to-note">Hub capture (easiest): POST to <code>/api/v1/capture</code> with JSON <code>{"body": "your text", "source": "slack", "project": "myproject"}</code>. Optional: <code>CAPTURE_WEBHOOK_SECRET</code> and header <code>X-Webhook-Secret</code>. Per-service steps below.</p> |
| 1948 | <h4 class="how-to-sub">Capture (messages → vault)</h4> |
| 1949 | <details class="how-to-details"> |
| 1950 | <summary>Slack</summary> |
| 1951 | <div class="how-to-details-body"> |
| 1952 | <p>Run <code>node scripts/capture-slack-adapter.mjs --port 3132</code>. Set <code>CAPTURE_URL</code> (default Hub), <code>SLACK_SIGNING_SECRET</code>, and optionally <code>CAPTURE_WEBHOOK_SECRET</code>. Point Slack Events API at the adapter URL; it responds to <code>url_verification</code> and forwards message events to capture. Or use Zapier/n8n: Slack trigger → HTTP POST to <code>/api/v1/capture</code>.</p> |
| 1953 | </div> |
| 1954 | </details> |
| 1955 | <details class="how-to-details"> |
| 1956 | <summary>Discord</summary> |
| 1957 | <div class="how-to-details-body"> |
| 1958 | <p>Run <code>node scripts/capture-discord-adapter.mjs --port 3133</code>. POST with JSON <code>{ "content": "message text", "id?", "channel_id?", "project?", "tags?" }</code>. Set <code>CAPTURE_URL</code> and <code>CAPTURE_WEBHOOK_SECRET</code>. Or Zapier/n8n: Discord trigger → HTTP POST to Hub capture.</p> |
| 1959 | </div> |
| 1960 | </details> |
| 1961 | <details class="how-to-details"> |
| 1962 | <summary>Telegram</summary> |
| 1963 | <div class="how-to-details-body"> |
| 1964 | <p>Run <code>node scripts/capture-telegram-adapter.mjs --port 3134</code>. Accepts Telegram Bot API webhook payloads or simplified <code>{ "body": "message text", "source_id?", "project?", "tags?" }</code>. Set <code>CAPTURE_URL</code> and <code>CAPTURE_WEBHOOK_SECRET</code>. Or any bot that POSTs to <code>/api/v1/capture</code> with <code>source: telegram</code>.</p> |
| 1965 | </div> |
| 1966 | </details> |
| 1967 | <details class="how-to-details"> |
| 1968 | <summary>WhatsApp</summary> |
| 1969 | <div class="how-to-details-body"> |
| 1970 | <p>No dedicated adapter. Use Zapier/n8n: WhatsApp trigger → HTTP POST to <code>https://your-hub.example.com/api/v1/capture</code> with <code>{"body": "<message text>", "source": "whatsapp", "source_id": "<id>"}</code>. Or run a small webhook that normalizes WhatsApp payloads and POSTs to capture. See Settings → Integrations and <code>docs/MESSAGING-INTEGRATION.md</code>.</p> |
| 1971 | </div> |
| 1972 | </details> |
| 1973 | <h4 class="how-to-sub">Import (LLM / platform exports → vault)</h4> |
| 1974 | <details class="how-to-details"> |
| 1975 | <summary>ChatGPT export</summary> |
| 1976 | <div class="how-to-details-body"> |
| 1977 | <p>Export from ChatGPT: Settings → Data Controls → Export Data. Extract the ZIP; then <code>knowtation import chatgpt-export /path/to/extracted-folder --output-dir imports/chatgpt --tags chatgpt</code>. Folder must contain <code>conversations.json</code>.</p> |
| 1978 | </div> |
| 1979 | </details> |
| 1980 | <details class="how-to-details"> |
| 1981 | <summary>Claude export</summary> |
| 1982 | <div class="how-to-details-body"> |
| 1983 | <p>Export chat history from Claude (Settings → Privacy → Export). If you have a folder of .md or JSON from a third-party exporter: <code>knowtation import claude-export /path/to/folder --project myproject</code>.</p> |
| 1984 | </div> |
| 1985 | </details> |
| 1986 | <details class="how-to-details"> |
| 1987 | <summary>Mem0 export</summary> |
| 1988 | <div class="how-to-details-body"> |
| 1989 | <p><code>knowtation import mem0-export /path/to/mem0-export.json --project memories</code>. Each memory becomes a vault note with <code>source: mem0</code>.</p> |
| 1990 | </div> |
| 1991 | </details> |
| 1992 | <details class="how-to-details"> |
| 1993 | <summary>Notion, Jira, NotebookLM, GDrive, Linear</summary> |
| 1994 | <div class="how-to-details-body"> |
| 1995 | <p>CLI: <code>knowtation import <source-type> <input></code> with <code>notion</code>, <code>jira-export</code>, <code>notebooklm</code>, <code>gdrive</code>, <code>linear-export</code>. See <code>docs/IMPORT-SOURCES.md</code> and Settings → Integrations for full list and options (<code>--project</code>, <code>--output-dir</code>, <code>--tags</code>).</p> |
| 1996 | </div> |
| 1997 | </details> |
| 1998 | <details class="how-to-details"> |
| 1999 | <summary>Transcripts, meetings, and video (bring text in)</summary> |
| 2000 | <div class="how-to-details-body"> |
| 2001 | <p><strong>Hosted:</strong> We do not transcribe audio or video in the cloud. Get a transcript from your tool (Otter, Zoom, Granola, Descript, etc.), save as <strong>Markdown</strong> or paste into a note, then <strong>re-index</strong> so search and agents can use it.</p> |
| 2002 | <p><strong>Self-hosted:</strong> You can use <code>knowtation import audio …</code> with your own <code>OPENAI_API_KEY</code> (Whisper). <code>video</code> is CLI-first; Hub UI for video is planned.</p> |
| 2003 | <p><strong>Why:</strong> Fewer moving parts, predictable costs, and you keep control of where transcription happens.</p> |
| 2004 | </div> |
| 2005 | </details> |
| 2006 | <p class="how-to-note"><strong>Files / generic:</strong> <code>scripts/capture-file.mjs</code> for stdin or files. Or drop Markdown into <code>vault/inbox/</code> or <code>vault/imports/</code> with frontmatter <code>source</code>, <code>date</code>, <code>project</code>, <code>tags</code>. <code>knowtation import markdown <path></code> for folders.</p> |
| 2007 | </section> |
| 2008 | <section class="how-to-step"> |
| 2009 | <h3><span class="step-num">Step 6</span> Use the Hub and automate with agents</h3> |
| 2010 | <p class="step-what">What this does: You browse and filter notes here; agents and LLMs can read and propose changes via the API or CLI, and you approve in the Hub.</p> |
| 2011 | <p class="how-to-note"><strong>Vault and backup:</strong> You have one vault (your notes) and optionally one GitHub repo to back it up (Settings → Backup). Projects are folders or tags <em>inside</em> the vault so you and agents can filter—they are not separate GitHub repos. <strong>Agents</strong> read and write the vault (CLI/MCP/API); they do not push to GitHub. You approve their changes (proposals) in the Hub and you control backup (Back up now or auto-sync).</p> |
| 2012 | <p class="how-to-note"><strong>Projects and filters:</strong> Organize notes by project (e.g. <code>vault/projects/myapp/</code> or frontmatter <code>project: myapp</code>) and tags. Agents use <code>--project</code> and <code>--tag</code> to read only what’s relevant. See the <strong>Knowledge & agents</strong> tab above for the full picture.</p> |
| 2013 | <h4 class="how-to-sub">Notes: project, path, and tags (two ways)</h4> |
| 2014 | <p><strong>Project</strong> can come from (1) <strong>path</strong> — a note under <code>vault/projects/Launch/</code> is in project “Launch”; or (2) <strong>frontmatter</strong> — <code>project: Launch</code> in the note’s YAML. Both count for filters and scope. <strong>Tags</strong> and <code>date</code>, <code>causal_chain_id</code>, <code>entity</code>, <code>episode_id</code> go in frontmatter (or are set in the Hub when you create the note).</p> |
| 2015 | <p><strong>Where the file lives:</strong> <strong>Quick capture</strong> always saves to <code>inbox/</code>; you can set project and tags in the form — they’re written into frontmatter, so the note is “in” that project for filtering even though the file is in inbox. To put the <strong>file</strong> in a specific folder, use <strong>+ New note</strong> → <strong>New note</strong> (not Quick capture): choose <strong>Folder</strong> (lists directories under your vault, including empty ones) or <strong>Custom</strong> and edit the full path — e.g. <code>projects/Launch/my-note.md</code>. Then fill title, body, project, tags as needed. So: project from path = file under <code>projects/<name>/</code>; project from frontmatter = file anywhere (e.g. inbox) with <code>project: <name></code> in the note.</p> |
| 2016 | <h4 class="how-to-sub">Multiple vaults and multiple users</h4> |
| 2017 | <p>On <strong>self-hosted</strong> you can have multiple vaults (Settings → Vaults): define a vault list (<code>data/hub_vaults.yaml</code>), then map each <strong>user</strong> to the vaults they can see (<code>data/hub_vault_access.json</code>). Optionally restrict a user to certain projects or folders within a vault (<code>data/hub_scope.json</code>). See <code>docs/MULTI-VAULT-AND-SCOPED-ACCESS.md</code> for full setup.</p> |
| 2018 | <p><strong>User ID</strong> is <code>provider:id</code> — e.g. <code>google:104164334692309763642</code> if you signed in with Google, or <code>github:12345678</code> if you signed in with GitHub. You see yours in Settings → Backup (“Your user ID”). Each sign-in identity is one user; if you have several Gmail or GitHub accounts, each account that signs in gets its own user ID. Admins add each ID to roles and vault access as needed. So the same Hub can serve many users, each with access to their assigned vaults (and optionally scoped to certain projects/folders).</p> |
| 2019 | <h4 class="how-to-sub">Hosted vs self-hosted: workspace, vaults, projects</h4> |
| 2020 | <p><strong>Self-hosted</strong> — One Hub install (often one machine) with one or more <strong>vaults</strong>, each vault = a <strong>folder on disk</strong>. There is no “shared workspace owner” setting. Any <strong>admin</strong> can add or change vault folders in Settings → Vaults. <strong>Projects</strong> group notes by path (e.g. <code>projects/Launch/…</code>) and/or by <code>project:</code> in note frontmatter.</p> |
| 2021 | <p><strong>Hosted (beta)</strong> — Vaults live in the <strong>cloud</strong> (vault ids like <code>default</code>, <code>work</code>), not as folders on your laptop. <strong>Workspace owner</strong> (Settings → Vaults) is optional: if set, the team shares <em>that person’s</em> cloud notes; only <strong>that owner</strong> can create <em>new</em> vault ids, while admins still control <strong>Vault access</strong> / <strong>Scope</strong> for others. This site has <strong>one</strong> workspace-owner setting—not multiple separate workspaces in the UI. A fully separate “world” = another Google/GitHub account or another deployment.</p> |
| 2022 | <p><strong>Projects on hosted</strong> — Same <em>idea</em> as self-hosted (group and filter notes), but you don’t rely on OS folders: put a <strong>project name</strong> on the note (see the <strong>(i)</strong> next to the project filter). Notes still have paths like <code>inbox/note.md</code> in storage—that’s not the same as picking a separate vault.</p> |
| 2023 | <p class="how-to-note"><strong>Why not identical to self-hosted?</strong> Cloud storage is keyed by user and vault id; letting every admin spawn new partitions without tying it to the account that “owns” that data would blur ownership and backups. Self-hosted is just files—any admin may point the Hub at another folder. See Settings → Vaults → <strong>(i)</strong> for the short version anytime.</p> |
| 2024 | <p><strong>Backup:</strong> “Connect GitHub” and “Back up now” are per <strong>logged-in user</strong>. Each user can connect their own GitHub account and push to their own repo (or to the repo configured for the vault they’re in). Different users can back up to different repositories; they could also point to the same repo if you set remotes that way (e.g. different branches), but the Hub UI stores one token per user and pushes the current vault’s folder to that vault’s remote.</p> |
| 2025 | <section id="how-to-flexible-network" class="how-to-step" style="margin-top: 1.5rem;"> |
| 2026 | <h4 class="how-to-sub">Hub as a flexible network</h4> |
| 2027 | <p>One Hub can coordinate <strong>many users</strong> (each sign-in = one identity), <strong>many vaults</strong> (each with its own path and optional scope), and <strong>many backup repos</strong> (per user or per vault). The same Hub is flexible enough for <strong>many agents to use it in many different ways</strong>: different agents or workflows can talk to different vaults, or the same vault, while you keep one coordination layer and one URL.</p> |
| 2028 | <p><strong>Why multiple vaults and scoped access help</strong></p> |
| 2029 | <p>You keep all information under your control in separate vaults (e.g. personal vs team, or project A vs project B).</p> |
| 2030 | <p><strong>Filter access</strong> so each user only sees the vaults they're allowed. <strong>Scope</strong> so a user or agent only sees certain projects or folders within a vault. The right people—and the right agents—get only the context they need.</p> |
| 2031 | <p><strong>Examples:</strong> A planner agent uses vault A for product context while engineer agents use vault B for technical decisions. Or one vault for personal notes and another for the team, with scope so each identity sees only the right one. Or one vault with projects "Launch" and "Q1 roadmap," and agents filtered by <code>--project</code> so they only read what's relevant.</p> |
| 2032 | |
| 2033 | <p style="margin-top: 1.25rem;"><strong>AgentCeption and Muse</strong></p> |
| 2034 | <p><strong>Today:</strong> AgentCeption’s planner and engineer agents use the same Hub API and proposals as other clients; proposal payloads use Muse-<em>aligned</em> fields (<code>base_state_id</code>, <code>intent</code>, optional <code>external_ref</code>) without running Muse on the Hub.</p> |
| 2035 | <p><strong>Optional:</strong> If you operate a Muse instance, you can use a <em>thin bridge</em> for read-only structural / Git-replayed history and set <code>external_ref</code> when approving proposals—canonical vault and login still live in Knowtation. See <code>docs/AGENT-INTEGRATION.md</code> §4 (<em>Optional external lineage</em>).</p> |
| 2036 | <p><strong>Advanced / deferred:</strong> A full Knowtation domain plugin inside Muse (Muse as the variation backend) is a separate, heavy integration; see the same doc §6.2.</p> |
| 2037 | <p>Point different AgentCeption agents at different vaults for different issues—all through the same Hub. One Hub URL, one coordination layer so you don’t run separate systems per vault or per tool.</p> |
| 2038 | <div class="diagram-box"> |
| 2039 | <div class="diagram-title">Many users, many vaults, many repos, many agents</div> |
| 2040 | <svg class="diagram-svg diagram-svg-network" viewBox="0 0 380 240" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> |
| 2041 | <defs><marker id="arrow-flex" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto"><path d="M0 0 L8 4 L0 8 Z" fill="var(--accent)"/></marker></defs> |
| 2042 | <!-- Center: Hub (wider box so label fits inside) --> |
| 2043 | <rect x="128" y="92" width="124" height="44" rx="6" fill="var(--surface)" stroke="var(--accent)" stroke-width="1.5"/> |
| 2044 | <text x="190" y="114" class="diagram-text" text-anchor="middle">Knowtation Hub</text> |
| 2045 | <!-- Users --> |
| 2046 | <rect x="120" y="12" width="140" height="36" rx="4" fill="var(--surface)" stroke="var(--border)" stroke-width="1"/> |
| 2047 | <text x="190" y="32" class="diagram-text" text-anchor="middle">Users (Google / GitHub)</text> |
| 2048 | <text x="190" y="44" class="diagram-text-small" text-anchor="middle">Many identities → one Hub</text> |
| 2049 | <path d="M 190 48 L 190 90" stroke="var(--accent)" stroke-width="1.5" marker-end="url(#arrow-flex)"/> |
| 2050 | <!-- Vaults --> |
| 2051 | <rect x="288" y="84" width="92" height="56" rx="4" fill="var(--surface)" stroke="var(--border)" stroke-width="1"/> |
| 2052 | <text x="334" y="104" class="diagram-text" text-anchor="middle">Vaults</text> |
| 2053 | <text x="334" y="118" class="diagram-text-small" text-anchor="middle">Multi-vault</text> |
| 2054 | <text x="334" y="132" class="diagram-text-small" text-anchor="middle">Scope by project</text> |
| 2055 | <path d="M 252 114 L 286 114" stroke="var(--accent)" stroke-width="1.5" marker-end="url(#arrow-flex)"/> |
| 2056 | <!-- Repos (more vertical room) --> |
| 2057 | <rect x="120" y="184" width="140" height="44" rx="4" fill="var(--surface)" stroke="var(--border)" stroke-width="1"/> |
| 2058 | <text x="190" y="206" class="diagram-text" text-anchor="middle">Repos (backup)</text> |
| 2059 | <text x="190" y="220" class="diagram-text-small" text-anchor="middle">Per user / per vault</text> |
| 2060 | <path d="M 190 136 L 190 184" stroke="var(--accent)" stroke-width="1.5" marker-end="url(#arrow-flex)"/> |
| 2061 | <!-- Agents: layers that can target different vaults --> |
| 2062 | <rect x="0" y="84" width="100" height="56" rx="4" fill="var(--surface)" stroke="var(--border)" stroke-width="1"/> |
| 2063 | <text x="50" y="104" class="diagram-text" text-anchor="middle">Agents</text> |
| 2064 | <text x="50" y="118" class="diagram-text-small" text-anchor="middle">MCP, CLI</text> |
| 2065 | <text x="50" y="132" class="diagram-text-small" text-anchor="middle">AgentCeption, Muse (opt.)</text> |
| 2066 | <path d="M 100 112 L 126 112" stroke="var(--accent)" stroke-width="1.5" marker-end="url(#arrow-flex)"/> |
| 2067 | </svg> |
| 2068 | </div> |
| 2069 | </section> |
| 2070 | |
| 2071 | <div class="diagram-box"> |
| 2072 | <div class="diagram-title">Agents and LLMs → Hub → you</div> |
| 2073 | <svg class="diagram-svg" viewBox="0 0 530 72" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> |
| 2074 | <!-- Box 1: wider so "Open CLAW / Abacus / LLM" fits inside --> |
| 2075 | <rect x="10" y="8" width="152" height="32" rx="4" fill="var(--surface)" stroke="var(--accent)" stroke-width="1.5"/> |
| 2076 | <text x="86" y="28" class="diagram-text" text-anchor="middle">Open CLAW / Abacus / LLM</text> |
| 2077 | <path d="M 164 24 L 178 24" stroke="var(--accent)" stroke-width="2" fill="none"/> |
| 2078 | <rect x="180" y="8" width="118" height="32" rx="4" fill="var(--surface)" stroke="var(--accent)" stroke-width="1.5"/> |
| 2079 | <text x="239" y="28" class="diagram-text" text-anchor="middle">Hub API or MCP / CLI</text> |
| 2080 | <path d="M 300 24 L 316 24" stroke="var(--accent)" stroke-width="2" fill="none"/> |
| 2081 | <rect x="318" y="8" width="96" height="32" rx="4" fill="var(--surface)" stroke="var(--accent)" stroke-width="1.5"/> |
| 2082 | <text x="366" y="28" class="diagram-text" text-anchor="middle">Proposals</text> |
| 2083 | <path d="M 416 24 L 432 24" stroke="var(--accent)" stroke-width="2" fill="none"/> |
| 2084 | <rect x="434" y="8" width="92" height="32" rx="4" fill="var(--surface)" stroke="var(--accent)" stroke-width="1.5"/> |
| 2085 | <text x="480" y="28" class="diagram-text" text-anchor="middle">You</text> |
| 2086 | <text x="265" y="58" class="diagram-text-small" text-anchor="middle">Approve or discard in Hub (Suggested / Discarded)</text> |
| 2087 | </svg> |
| 2088 | </div> |
| 2089 | <h4 class="how-to-sub">Proposals: where they come from and where to see them</h4> |
| 2090 | <p>You <strong>review</strong> proposals in the Hub. They can come from the <strong>Suggested</strong> tab actions (<strong>New proposal</strong>, or <strong>Propose change</strong> on an open note), from the CLI, or from an agent calling <code>POST /api/v1/proposals</code>.</p> |
| 2091 | <ul> |
| 2092 | <li><strong>Create a proposal:</strong> In the Hub: <strong>Suggested → New proposal</strong>, or open a note and click <strong>Propose change</strong>. From a terminal: <code>knowtation propose --hub http://localhost:3333 --path inbox/idea.md --body "..."</code> with <code>KNOWTATION_HUB_TOKEN</code> set (copy from <strong>Settings → Integrations → Hub API</strong>). Agents use the same API with <code>Authorization: Bearer …</code> and <code>X-Vault-Id</code>.</li> |
| 2093 | <li><strong>Suggested tab:</strong> Lists proposals waiting for your decision. Click one to open it. Use <strong>Evaluation</strong> to record a pass, fail, or needs-changes outcome (checklist + optional grade + comment). Then <strong>Approve</strong> writes the content to the vault, or <strong>Discard</strong> rejects it. If your Hub requires evaluation before approve, you must pass or enter an <strong>approve waiver reason</strong>. Filter with <em>Pending evaluation only</em> when triaging.</li> |
| 2094 | <li><strong>Discarded tab:</strong> Lists proposals you (or someone) discarded. You can open them to read; they are not applied to the vault.</li> |
| 2095 | <li><strong>Activity tab:</strong> Timeline of all proposals (proposed, approved, discarded) so you can see what changed and when.</li> |
| 2096 | </ul> |
| 2097 | <p class="how-to-note">Nothing is written to the vault until you <strong>Approve</strong> (or an admin does). Human-created proposals use the same queue as CLI and agent proposals.</p> |
| 2098 | <h4 class="how-to-sub">Reviewing proposals (evaluation, triggers, roles)</h4> |
| 2099 | <ul> |
| 2100 | <li><strong>Outcome vs grade:</strong> Saving evaluation uses an <em>outcome</em> (pass / fail / needs changes) plus checklist; optional <em>grade</em> is for culture or reporting and does not replace outcome.</li> |
| 2101 | <li><strong>Pending:</strong> New proposals may start as pending when your Hub requires evaluation for every proposal, or when <strong>review triggers</strong> match (phrases, path prefixes, labels). Filter with <em>Pending evaluation</em>, <em>Review queue</em>, or <em>Severity</em> on the Suggested tab.</li> |
| 2102 | <li><strong>Who does what:</strong> <code>evaluator</code> users record evaluation; <code>admin</code> always approves and discards. Evaluators may approve only when an admin grants it per user in <strong>Team</strong> (or the host sets <code>HUB_EVALUATOR_MAY_APPROVE=1</code> as a fallback when no per-user entry exists). Waivers on approve remain admin-side when evaluation has not passed.</li> |
| 2103 | <li><strong>LLM review hints:</strong> If enabled on the Hub, short async hints may appear on a proposal. They are not a merge gate; treat them as untrusted.</li> |
| 2104 | </ul> |
| 2105 | |
| 2106 | <h4 class="how-to-sub">Hub UI: filters and views</h4> |
| 2107 | <ul> |
| 2108 | <li><strong>Projects, tags, folders:</strong> Notes can have <code>project: slug</code> and <code>tags: [a, b]</code> in frontmatter, or live under <code>projects/slug/</code>. Use the project, tag, and folder dropdowns, then <strong>Apply filters</strong>. <strong>Quick</ |
File truncated at 200 KB — view full file ↗