@dall337/lore 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/License.md +21 -0
  2. package/README.md +210 -2
  3. package/bin/lore.mjs +187 -0
  4. package/hud/dist/client/assets/index-BA5GHj6l.css +1 -0
  5. package/hud/dist/client/assets/index-C1P2dBAT.js +7 -0
  6. package/hud/dist/client/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
  7. package/hud/dist/client/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
  8. package/hud/dist/client/assets/jetbrains-mono-cyrillic-600-normal-8K4wrrwR.woff +0 -0
  9. package/hud/dist/client/assets/jetbrains-mono-cyrillic-600-normal-EVf6-Yzo.woff2 +0 -0
  10. package/hud/dist/client/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
  11. package/hud/dist/client/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
  12. package/hud/dist/client/assets/jetbrains-mono-greek-600-normal-H7WoG9Et.woff2 +0 -0
  13. package/hud/dist/client/assets/jetbrains-mono-greek-600-normal-mc2nkWzM.woff +0 -0
  14. package/hud/dist/client/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
  15. package/hud/dist/client/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  16. package/hud/dist/client/assets/jetbrains-mono-latin-600-normal-BfsvjouI.woff +0 -0
  17. package/hud/dist/client/assets/jetbrains-mono-latin-600-normal-C8RAYTDA.woff2 +0 -0
  18. package/hud/dist/client/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
  19. package/hud/dist/client/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
  20. package/hud/dist/client/assets/jetbrains-mono-latin-ext-600-normal-BfB_LPfz.woff2 +0 -0
  21. package/hud/dist/client/assets/jetbrains-mono-latin-ext-600-normal-DObL3zCW.woff +0 -0
  22. package/hud/dist/client/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
  23. package/hud/dist/client/assets/jetbrains-mono-vietnamese-600-normal-OWROknRo.woff +0 -0
  24. package/hud/dist/client/index.html +17 -0
  25. package/hud/dist/client/licenses/JetBrainsMono-OFL.txt +93 -0
  26. package/hud/dist/server/main.js +1287 -0
  27. package/package.json +52 -4
  28. package/suite/AGENTS.md +228 -0
  29. package/suite/CLAUDE.md +19 -0
  30. package/suite/claude-settings-additions.json +16 -0
  31. package/suite/gitignore-additions.txt +17 -0
  32. package/suite/memory/INDEX.md +41 -0
  33. package/suite/policies/adversarial-check.md +169 -0
  34. package/suite/policies/board.md +103 -0
  35. package/suite/policies/creative.md +92 -0
  36. package/suite/policies/documentation.md +100 -0
  37. package/suite/policies/git.md +105 -0
  38. package/suite/policies/implementation.md +100 -0
  39. package/suite/policies/memory.md +453 -0
  40. package/suite/policies/orchestration.md +184 -0
  41. package/suite/policies/release.md +56 -0
  42. package/suite/policies/research.md +133 -0
  43. package/suite/policies/reserved/failure-and-recovery.md +6 -0
  44. package/suite/policies/reserved/migration.md +6 -0
  45. package/suite/policies/reserved/planning.md +6 -0
  46. package/suite/policies/reserved/review.md +6 -0
  47. package/suite/policies/reserved/test-authoring.md +6 -0
  48. package/suite/policies/security.md +85 -0
  49. package/suite/policies/tooling.md +153 -0
  50. package/suite/policies/verification.md +60 -0
  51. package/suite/scripts/agents-md-budget.mjs +71 -0
  52. package/suite/scripts/memory-lint.mjs +117 -0
  53. package/suite/scripts/provider-memory.mjs +298 -0
package/License.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 LORE contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,211 @@
1
- # Temporary Holding Version
1
+ # LORE — Living Operational Rules & Evidence
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Every mature project develops institutional lore — why a strange guard
4
+ exists, what once broke, where the bodies are buried. Normally that lore
5
+ lives in one person's head and disappears when they leave. Coding agents
6
+ have it worse: they start every session with no memory at all, so the
7
+ same lesson gets re-learned, or re-broken, forever.
8
+
9
+ **LORE** makes that lore explicit, persistent, navigable, and
10
+ enforceable. It is a read-and-adapt governance suite for agent-driven
11
+ development, giving agents a walkable web of repository knowledge with
12
+ configurable storage, scoped policy dispatch, claim-based coordination,
13
+ and a path for lessons to mature into automated guards — built so that agents
14
+ learn and build policy *with* their developers, not for them.
15
+
16
+ The name is the design brief, letter by letter: **Living** — each
17
+ repository adapts and grows its own version. **Operational** — these
18
+ rules govern actual work. **Rules** — earned through incidents and
19
+ ratified by the owner. **Evidence** — provenance, journals, ledgers,
20
+ registers, and guards.
21
+
22
+ ## Try it
23
+
24
+ LORE's command line ships as an npm package (Node 20+):
25
+
26
+ ```sh
27
+ npx @dall337/lore hud # open the HUD for the repository in this folder
28
+ npm i -g @dall337/lore # or install it, then: lore hud · lore hud status · lore hud stop · lore brief
29
+ ```
30
+
31
+ `lore hud` runs a local, private page for the repository: its board, its
32
+ research journals, and its open GitHub work (see [The HUD](#the-hud)).
33
+ Add `--data <folder>` to keep the board outside the repository and leave
34
+ the repository untouched while you try it.
35
+
36
+ *Early release (0.1).* `lore init`, which sets LORE up in a repository in
37
+ one command, is next. Until then, adopt the suite by copying it, as
38
+ described under [Adopting](#adopting).
39
+
40
+ ## Where this came from
41
+
42
+ LORE was not designed up front. It accumulated — rule by rule, on a
43
+ working repository, each one written the day something went wrong that a
44
+ rule would have prevented. Some were cheap to learn. Others were not.
45
+ The pattern never changed: the lesson was real, it was obvious in
46
+ hindsight, and then a later session made the same mistake anyway —
47
+ because the lesson had been learned by a person, or by a context window,
48
+ and lived nowhere durable enough to outlast either.
49
+
50
+ None of those incidents are in here. They belonged to that project, and
51
+ handing them to you would produce rules you inherited rather than earned
52
+ — which is the exact failure this suite exists to prevent. So what ships
53
+ is the shape of the lessons with the stories removed, plus the machinery
54
+ for your own to accumulate in their place.
55
+
56
+ This is the thing I wish had existed on the first day of that project.
57
+ Not a set of answers — somewhere for answers to go, and the habit of
58
+ putting them there. Take it and let it fill up with yours.
59
+
60
+ The transferable part is the method — dispatch-table policy loading,
61
+ provenance-carrying rules, append-only memory, claim-based orchestration
62
+ — not the specifics. Copy it into a project, point agents at
63
+ `AGENTS.md`, and let it diverge.
64
+
65
+ ## Adopting
66
+
67
+ **Copy the contents of `suite/` into your repository root** — with two
68
+ exceptions. `claude-settings-additions.json` is merged into
69
+ `.claude/settings.json` when Claude Code works in the repository (see
70
+ Choose the Memory Home). `gitignore-additions.txt` holds default-location
71
+ rules you *append* to the `.gitignore` you already have when those
72
+ locations are used:
73
+
74
+ ```gitignore
75
+ /memory/ # agent memory web (policies/memory.md §5)
76
+ /.research/ # research journals (policies/research.md)
77
+ ```
78
+
79
+ Keep the leading slashes. Unanchored, `memory/` matches at every level
80
+ and would silently ignore a `src/memory/` module in your own source tree.
81
+
82
+ Then:
83
+
84
+ 1. Read `AGENTS.md` §5 and fill the adopt-time slots, including the memory
85
+ backend and entry point. Use an established company or agent memory
86
+ system when one is already chosen.
87
+ 2. Greenfield project: run the tooling bootstrap (`policies/tooling.md`
88
+ §1). Existing project: seed the register per `policies/tooling.md` §6
89
+ — load-bearing decisions now, the rest by contact — then orient through
90
+ the configured memory. Bootstrap the bundled web when it is selected.
91
+ 3. Delete what doesn't fit. Keep the dispatch table true.
92
+
93
+ ### Choose the Memory Home
94
+
95
+ *Added 2026-10-02.* The bundled memory module is optional. Point LORE at
96
+ the agent's existing memory, a company memory system, the bundled link
97
+ web, or a separate shared file, document, or service. Record the entry
98
+ point and access method in `AGENTS.md` §5, or point that section at the
99
+ existing configuration document.
100
+
101
+ Existing company and provider conventions continue to govern their stores.
102
+ LORE does not require a replacement module or a duplicate map. When agent
103
+ memory is private, choose a shared coordination location for claims and
104
+ handoffs. Full selection and coexistence rules: `policies/memory.md` §0.
105
+
106
+ > **Clarification (2026-10-02, owner definition of the web):** Preserve the
107
+ > navigation: a repository hub leads through relevant categories, with
108
+ > each ring becoming more specific until it points to the needed artifacts
109
+ > and status. Agents walk the relevant branch instead of loading everything.
110
+ > Storage can be the bundled files, the existing provider's linked records,
111
+ > or another location. If the provider cannot expose those routes directly,
112
+ > a thin index can point into it while leaving its records authoritative.
113
+
114
+ > **Addendum (2026-10-17, provider memory):** Each harness's own memory,
115
+ > such as Claude Code's auto memory or Codex memories, stays in place as a
116
+ > private layer under its provider's rules. LORE writes only pointers into
117
+ > it and keeps shared knowledge out of it. List each harness in the
118
+ > provider memory table in `AGENTS.md` §5.
119
+ >
120
+ > Where the agent writes that memory's always-loaded index (Claude Code's
121
+ > `MEMORY.md`, capped at 200 lines or 25KB), the index is a links-only
122
+ > hub over areas named for the policies, reserved scopes included. Seed
123
+ > it with `node scripts/provider-memory.mjs init <memory-dir>`, then merge
124
+ > `claude-settings-additions.json` into `.claude/settings.json` so each
125
+ > memory write is checked. An existing index with prose in it is migrated
126
+ > first; `init` refuses to touch one.
127
+
128
+ The ignore snippet above describes the default local directories; append
129
+ the rules needed for the locations you use. The shipped memory guard checks
130
+ the bundled web's format; it does not validate a different provider.
131
+
132
+ ## What's in `suite/` — the part you copy
133
+
134
+ - **`AGENTS.md`** — the agent entry point: authority order, the
135
+ greenfield map (PRD → tooling research → memory selection → scaffold),
136
+ the steady-state dispatch table, the rule-accumulation loop, reserved
137
+ scopes, and the adopt-time slots.
138
+ - **`CLAUDE.md`** — imports `AGENTS.md` (`@AGENTS.md`) so Claude Code
139
+ loads it; Claude Code reads `AGENTS.md` on its own only when no
140
+ `CLAUDE.md` exists.
141
+ - **`policies/`** — scoped procedures, loaded per-task:
142
+ research · implementation · git · verification · documentation ·
143
+ release · security · **orchestration** (multi-agent coordination) ·
144
+ **memory** (walkable repository web with configurable storage) ·
145
+ **tooling** (PRD-driven stack research + the living tooling register).
146
+ - **`policies/creative.md`** — collaborative exploration of unfinished
147
+ ideas and connections across disciplines, following the owner's pace
148
+ (added 2026-10-01).
149
+ - **`policies/adversarial-check.md`** — deep tracing of concrete
150
+ guarantees, deliberate counterexamples, and evidence-qualified findings
151
+ (added 2026-10-01).
152
+ - **`policies/board.md`** — the LORE board as the work-status record:
153
+ keeping it current, bootstrapping an empty one, and the board file's
154
+ shape (added 2026-10-17).
155
+ - **`policies/reserved/`** — empty scopes that accumulate rules as
156
+ lessons are learned.
157
+ - **`scripts/memory-lint.mjs`** — the suite's first guard: checks
158
+ memory-web form (dated ledgers, stamped strikes, well-formed claims,
159
+ multiple-live-claim detection). Zero-dependency Node; the checks are
160
+ the policy, the implementation is fungible — port it if your stack
161
+ lacks Node.
162
+ - **`scripts/provider-memory.mjs`** — the second guard: seeds and checks
163
+ a harness's own memory index as a links-only hub over policy areas,
164
+ with a hook mode that checks each memory write in Claude Code (added
165
+ 2026-10-17).
166
+ - **`claude-settings-additions.json`** — the hook that runs that check,
167
+ as a snippet to merge into `.claude/settings.json`.
168
+ - **`scripts/agents-md-budget.mjs`** — the third guard: holds every chain
169
+ of `AGENTS.md` files under 30 KiB, inside the 32 KiB Codex reads
170
+ (added 2026-10-17).
171
+ - **`memory/INDEX.md`** — a seeded, empty hub for the optional bundled web.
172
+ - **`gitignore-additions.txt`** — the two ignore rules, as a snippet that
173
+ cannot clobber your `.gitignore` by being copied.
174
+
175
+ ## The HUD
176
+
177
+ *Added 2026-10-17.* `lore hud` opens a local, private page for one
178
+ repository: the board agents keep current (`policies/board.md`), the
179
+ research journals with their status and policy tags, and an Inbox of open
180
+ PRs, issues, and journals no card tracks yet. Edits agents make to the
181
+ board file show up live. It writes only to `<repo>/.lore/`, or with
182
+ `--data` to a folder outside the repository, which leaves the repository
183
+ untouched. It needs Node 20+; GitHub data comes from the `gh` CLI when it
184
+ is available.
185
+ Details: [`hud/README.md`](hud/README.md).
186
+
187
+ ## The philosophy in one paragraph
188
+
189
+ This suite ships with no incident history, deliberately. Rules are earned:
190
+ when something goes wrong, the agent drafts the rule where the next agent
191
+ will look for it, carrying the date and the incident, and the owner
192
+ ratifies it. A rule whose origin you can read is a rule you can argue
193
+ with when it stops fitting. Agents learn and build policy *with* their
194
+ developers — the suite is the place that learning accumulates.
195
+
196
+ ## License, and what it's actually meant to mean
197
+
198
+ MIT — see `License.md`. Because MIT's notice-retention clause was never
199
+ the point, here is the intent stated plainly, as an explicit additional
200
+ grant from the copyright holder:
201
+
202
+ > **Take it. Change it. Ship it.** You do not need to carry this
203
+ > license, this copyright notice, or any attribution into your
204
+ > repository, your `AGENTS.md`, or your policy files. Adopt it whole,
205
+ > adopt one policy, gut it and keep only the dispatch table — no
206
+ > credit required, no notice required, no obligations back.
207
+
208
+ Nothing in LORE is meant to constrain the next person. It is a thing that
209
+ helped one project; use it, learn your own lessons, and codify them your
210
+ own way. If you keep the tree wholesale and want to leave `License.md` in
211
+ place, that's welcome — but it is a courtesy, not a condition.
package/bin/lore.mjs ADDED
@@ -0,0 +1,187 @@
1
+ #!/usr/bin/env node
2
+ // lore — LORE's command line.
3
+ //
4
+ // lore hud [--repo <path>] [--data <dir>] [--port <n>] [--no-open] [--foreground]
5
+ // lore hud status [--repo <path>] [--data <dir>]
6
+ // lore hud stop [--repo <path>] [--data <dir>]
7
+ // lore brief [--repo <path>] [--data <dir>]
8
+ //
9
+ // `lore hud` runs the HUD in the background (one per repository) and opens
10
+ // it; run again, it reopens the one already running. --foreground keeps it
11
+ // in this terminal instead. --data keeps the board and settings in a folder
12
+ // outside the repository, so the HUD only reads the repository.
13
+ // The HUD runs from its prebuilt files in hud/dist (npm run build).
14
+
15
+ import { spawn } from 'node:child_process';
16
+ import { closeSync, existsSync, mkdirSync, openSync, readFileSync, statSync, truncateSync, writeSync } from 'node:fs';
17
+ import path from 'node:path';
18
+ import { fileURLToPath } from 'node:url';
19
+
20
+ const root = fileURLToPath(new URL('..', import.meta.url));
21
+ const self = fileURLToPath(import.meta.url);
22
+ const { version } = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
23
+ const [command, ...args] = process.argv.slice(2);
24
+ const sub = command === 'hud' && (args[0] === 'stop' || args[0] === 'status') ? args[0] : null;
25
+
26
+ const flag = (name) => args.includes(name);
27
+ function option(name) {
28
+ const i = args.indexOf(name);
29
+ if (i < 0) return undefined;
30
+ const value = args[i + 1];
31
+ if (value === undefined || value.startsWith('--')) fail(`${name} needs a value`);
32
+ return value;
33
+ }
34
+ function fail(message) {
35
+ console.error(`lore: ${message}`);
36
+ process.exit(1);
37
+ }
38
+ const wait = (ms) => new Promise((r) => setTimeout(r, ms));
39
+
40
+ async function loadServer() {
41
+ const built = new URL('../hud/dist/server/main.js', import.meta.url);
42
+ if (!existsSync(built)) fail(`the HUD is not built yet — run \`npm run build\` in ${root}`);
43
+ return import(built.href);
44
+ }
45
+
46
+ function openBrowser(url) {
47
+ const [cmd, cmdArgs] =
48
+ process.platform === 'win32' ? ['cmd', ['/c', 'start', '""', url]] : process.platform === 'darwin' ? ['open', [url]] : ['xdg-open', [url]];
49
+ const child = spawn(cmd, cmdArgs, { stdio: 'ignore', detached: true, windowsHide: true });
50
+ child.on('error', () => console.log(`Open ${url} in your browser.`));
51
+ child.unref();
52
+ }
53
+
54
+ const target = () => ({ repo: path.resolve(option('--repo') ?? process.cwd()), data: option('--data') && path.resolve(option('--data')) });
55
+
56
+ function portOption() {
57
+ const text = option('--port');
58
+ const port = text === undefined ? undefined : Number(text);
59
+ if (port !== undefined && !(Number.isInteger(port) && port >= 0 && port < 65536)) fail('--port must be a port number');
60
+ return port;
61
+ }
62
+
63
+ async function describe(url) {
64
+ const { getJson } = await loadServer();
65
+ const meta = await getJson(`${url}/api/meta`).catch(() => null);
66
+ if (!meta) return;
67
+ console.log(` board ${meta.boardFile}`);
68
+ console.log(` journals ${meta.journals}`);
69
+ if (meta.boardIgnored === false) {
70
+ console.log(` note git would show ${meta.boardFile} as untracked: add /.lore/ to .git/info/exclude to keep it private`);
71
+ }
72
+ }
73
+
74
+ /** Run the server here, recorded so `lore hud` and `lore hud stop` can find it. */
75
+ async function foreground() {
76
+ const { startHud } = await loadServer();
77
+ const { repo, data } = target();
78
+ const hud = await startHud({ repo, data, port: portOption(), version, register: true }).catch((err) => fail(err.message));
79
+ console.log(`LORE HUD · ${hud.config.repoName} → ${hud.url} (pid ${process.pid}, started ${new Date().toISOString()})`);
80
+ await describe(hud.url);
81
+ console.log('Ctrl+C to stop.');
82
+ if (!flag('--no-open')) openBrowser(hud.url);
83
+ const stop = () => hud.close().then(() => process.exit(0));
84
+ process.on('SIGINT', stop);
85
+ process.on('SIGTERM', stop);
86
+ }
87
+
88
+ /** Start (or reuse) the repository's HUD in the background, then open it. */
89
+ async function background() {
90
+ const { findHud } = await loadServer();
91
+ const { repo, data } = target();
92
+ const port = portOption();
93
+ const found = await findHud({ repo, data }).catch((err) => fail(err.message));
94
+ if (found.live) {
95
+ console.log(`LORE HUD · ${found.config.repoName} is already running → ${found.live.url}`);
96
+ if (port !== undefined && port !== found.live.port) console.log(` note it is on port ${found.live.port}; \`lore hud stop\` first to move it to ${port}`);
97
+ if (!flag('--no-open')) openBrowser(found.live.url);
98
+ return;
99
+ }
100
+
101
+ // The server's output goes to a small log in the data folder.
102
+ const { dataDir } = found.config;
103
+ mkdirSync(dataDir, { recursive: true });
104
+ const logPath = path.join(dataDir, 'hud.log');
105
+ if (existsSync(logPath) && statSync(logPath).size > 256 * 1024) truncateSync(logPath, 0);
106
+ const log = openSync(logPath, 'a');
107
+ writeSync(log, `\n── ${new Date().toISOString()} lore hud ${version}\n`);
108
+ const childArgs = [self, 'hud', '--foreground', '--no-open', '--repo', repo, ...(data ? ['--data', data] : []), ...(port !== undefined ? ['--port', String(port)] : [])];
109
+ const child = spawn(process.execPath, childArgs, { detached: true, stdio: ['ignore', log, log], windowsHide: true });
110
+ closeSync(log);
111
+ let exited = null;
112
+ child.on('exit', (code) => (exited = code ?? 1));
113
+ child.unref();
114
+
115
+ for (let i = 0; i < 80; i++) {
116
+ await wait(125);
117
+ if (exited !== null) {
118
+ const tail = readFileSync(logPath, 'utf8').trim().split('\n').slice(-6).join('\n');
119
+ fail(`the HUD stopped while starting (exit ${exited}). From ${logPath}:\n${tail}`);
120
+ }
121
+ const now = await findHud({ repo, data });
122
+ if (now.live?.pid === child.pid) {
123
+ console.log(`LORE HUD · ${now.config.repoName} → ${now.live.url} (in the background, pid ${child.pid})`);
124
+ await describe(now.live.url);
125
+ console.log(` stop lore hud stop · log ${logPath}`);
126
+ if (!flag('--no-open')) openBrowser(now.live.url);
127
+ // Nothing holds the event loop (the server is detached and unreferenced),
128
+ // so returning ends this process cleanly.
129
+ child.removeAllListeners('exit');
130
+ return;
131
+ }
132
+ }
133
+ fail(`the HUD did not come up within 10s; see ${logPath}`);
134
+ }
135
+
136
+ async function status() {
137
+ const { findHud } = await loadServer();
138
+ const { config, live } = await findHud(target()).catch((err) => fail(err.message));
139
+ if (!live) {
140
+ console.log(`LORE HUD · ${config.repoName}: not running. \`lore hud\` starts it.`);
141
+ return;
142
+ }
143
+ console.log(`LORE HUD · ${config.repoName}: running → ${live.url}`);
144
+ console.log(` pid ${live.pid} · version ${live.version} · since ${live.startedAt}`);
145
+ }
146
+
147
+ async function stop() {
148
+ const { stopHud, findHud } = await loadServer();
149
+ const { config } = await findHud(target()).catch((err) => fail(err.message));
150
+ const stopped = await stopHud(target());
151
+ console.log(stopped ? `LORE HUD · ${config.repoName}: stopped (was ${stopped.url}, pid ${stopped.pid}).` : `LORE HUD · ${config.repoName}: was not running.`);
152
+ }
153
+
154
+ const USAGE = `lore ${version}
155
+
156
+ lore hud open the HUD for a repository (starts it in the background, or reopens it)
157
+ lore hud status say whether this repository's HUD is running, and where
158
+ lore hud stop stop it
159
+ lore brief print the board summary for an agent
160
+
161
+ --repo <path> the repository (default: the current folder)
162
+ --data <dir> keep the board and settings outside the repository (default <main checkout>/.lore)
163
+ --port <n> exact port (default: the repository's own stable port)
164
+ --no-open don't open the browser
165
+ --foreground keep the HUD in this terminal (Ctrl+C stops it)`;
166
+
167
+ if (command === 'hud' && sub === 'status') {
168
+ await status();
169
+ } else if (command === 'hud' && sub === 'stop') {
170
+ await stop();
171
+ } else if (command === 'hud') {
172
+ await (flag('--foreground') ? foreground() : background());
173
+ } else if (command === 'brief') {
174
+ const { brief } = await loadServer();
175
+ // A brief must never block a session: report and exit 0.
176
+ try {
177
+ console.log(await brief(target()));
178
+ } catch (err) {
179
+ console.log(`LORE board brief unavailable: ${err.message}`);
180
+ }
181
+ } else if (!command || command === '--help' || command === '-h' || command === 'help') {
182
+ console.log(USAGE);
183
+ } else if (command === '--version' || command === '-v') {
184
+ console.log(version);
185
+ } else {
186
+ fail(`unknown command "${command}"\n\n${USAGE}`);
187
+ }
@@ -0,0 +1 @@
1
+ @font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(data:font/woff2;base64,d09GMgABAAAAAASIABAAAAAACQQAAAQuAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhwbHhwoBmA/U1RBVF4AdBEICoRkhAALIAABNgIkAzoEIAWFAAeBFAwHG2oHKJ6DceNW4lJEFHn9tEOE37LNsvkjHr7f739rn3u+OSrSxLQytE91Dw2PYtNVq3Qaw/vJ7fUBMdOj/u2ImB98cT5WUx9F13ZKt06mU7tG1sAYcM26yCRX4f/0904bmwq8hwkUUMTRX61pa9C3xlpAGYw1vOu8C2SBZZFlld7DAW82RJWmwYMI1AJCKBNCIASqdZGFmtPSNQRhMpR0EKjWTwm6z6sJ+4jqhxjovTinVdRpZaQjaQzAYjI8NgAKDJCokgunCn9oUQE8VZd/F//+v6P4F1U9gLr58yNI/dJX9BAshEoJbTDogz7ocKoUsPvES8UK/aQIUQgpGgECBVLkOEV6iASTYgNAPKdNXayhDPL7IJuAZnEYSZ0eOLc9i5Rv5/+lEi3sW/kfnCf/+fTe0sxS7CKLx5erRJkKOixEqQaoqrvx5HN4iz4VhX0gS6DjFIWUzn/fIXJRVFY1NFRVNVeFt+SYmrK6vCU6eJsnKnJj5HTESMTQZOTI3Y/tzr3rUcOsiRy/ciP50s3Mycgxmhz9GMXhjzVH30ut796NHP0UUa31/Zoa6vCH6iPvdIM0IRANaT60FablmZlZd+UKNFy9NrvnFGxb5NC2CRxR0/rIyF/WNn+35sv9r+tHVhkseuWGKkCPPh96+GXt8Lc/Sh24ujfjf+tNw1lZWreiPuHb/PSpyjdv2rf/++ZE5TSKjFdZxYsBvr1sEHl5STuHZqYR7jGYGvGBBdjcaB5bODY1GAxMjsd0wDMIzXAXODRd74DxNMtO4YuYHclgLQRzp9KlUmxptCwv9bYgvWGD2xBW7r9413fdJu+mxzvzAUYeeONQvZP4kgfqZle4jhH/MWh+UbxgtJdrLdXLymNL53PRU0D3Q6FcXTfGqGcul6vrqhgLGAVSv+IVIfZOHpu+mlLqSlnj903j8mazXDsba/wbxhS/4Oubh1c5/uXDgt4j5KtnGEy5BIJHo0ur+jD+r2qCkuP1aRVM8EpUoRYSJyqNRA38uwDvHBNo0AejO2Z+ZYLLal1QiFyFh1EDQOgSCSCpjwwKU8yDbIjroEwne0G5Qca49cYp4AlqtQNZfWTQoFb1tRpFYAmRD+HXTkV4uQhG2bg4OKmyoypAsUGtWgQXyFxYrkpODeUxvGqIZA61erXo0sFG1UBGuPgpuon8RNUG2DhovAjZCBuZwtXrU3mQGki9+pm0eVZAXoWxLWTQoYHBPrJR4WunNxIFbCHfkTyPK+sqxjxDmGArZvf79JGJ3GwEqjwc7a7NIrl/7bJ7Nzu4+n1Ow6shEPnUrtVo7cnd5Wi5qCUbBIQbNKCP95FMCSZylEV5VCiiMqqiOmrKZ/I/C0gI1fyuulVcM2E1r4MhtcV/fbCD+HwEvVzH1dGNAzFE0FTbKzyQz3gootrNbN2a4PuG0j0JOgE=)format("woff2"),url(data:font/woff;base64,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)format("woff");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2)format("woff2"),url(/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff)format("woff");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2)format("woff2"),url(/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff)format("woff");unicode-range:U+370-377,U+37A-37F,U+384-38A,U+38C,U+38E-3A1,U+3A3-3FF}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(data:font/woff2;base64,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)format("woff2"),url(/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:600;src:url(data:font/woff2;base64,d09GMgABAAAAAASIABAAAAAACQAAAAQtAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhwbHhwoBmA/U1RBVDYAdBEICoRkg3gLIAABNgIkAzoEIAWFIgeBFAwHG1wHKI7DuPEacDIiFJ/g+f47+1/7dIcdXTlD8DKqmcw4eIC+AOCPf6+qiWq3h6+aSCLNJDnkqX9Xl+rv/6dSBcwSBCzEoVqxNbp5SqPMYdKBQhBq1dK9ggSsgYUoGnHOqttMECvWjIJfPA8cjQAuAEAQLAiClASc7M6OkfbO/nHs6ACmCYBxZXKP4s9uXIHECh4AdEhX0yIHC6jzgAb65sshStMMChwEfWVjZe8Anset/6H93x8jOyL5fuS67z4Dlam+BPyH/pV2FLCZAOnU0XPzCQGiJ7AkXgSFhqDEB4AAoAAN2ExDgM10joCNfDQUbvxaXM8LovT79D9MEyYU9+q/myT9p/m8uWi2mLJBPbzcih2wYIPzBDFNvABt315OXwy8BaRnbo5hXsOS5taknX4FguiaZnd4vQ7HxnBnm3SPYXHrQbclvOgyDhsHnZPO8f3G5I2fbr34Y7+hzRozVzyw5bKHdu03plXgvE9FO/Uz4/xPUKd8/PHk+R+JODnlg1lDTv3Qed77zDNqRszaqHUQT248kUPGzBXXXHGFnHrVVdft2m8c4PhpjB+/QEqMU54xruc6m3w8++XNXx4sya9rMvNq88m6X1zeOMlRuQ+/nvNw4+ZrCt58yDdSVOQdfoi/jc/ePfZY+1taYaH21FH2Y4fGG+RVNJkIN4SSiWj3ZKGG1oojoYr2SNWFVbHvY1XX1PR+H6y+oKrqgmryqj1UXnmk5cKWysPM3R4Uh5svYo6saAtU3V297+d91U/X/frzLvUdqiqfruKvhx5+OeOYxbHI7SenQum+PTw/fvRLGQ/jiufOn3/S+vlsfGn9h4Zb96fekZ7xRups68FhVCYCWHHvZVIPxjanr3NABSALqkR7FMBOulF9ScHvV3np+6pK/eEzRx877K3/z65pvwN89eGtV3Ly5ft/25ngaiSYDVYUAAKvIKimMdLO6YBQEY+aZpbXZ5WinTBQXwAA4LMAXuNUBPCSTmMfjd6jpNLNjbToDuBpaR9AoTBbUeERO2o0erNeR6KFne5HK/nOQA+VBtFnt1LtBj6pJQIutnLwipz/Ix9OYNSqZQEreiQELIkKmRIRNWdewpiIZVGtVi0J6xWR0ComIGpFnN+AVStWzUtIWBNXq0iRuJCYqDUJcYXiopYUWhUzp8iQTv20dtO84Agw6YrhuOijfqUKlSpRAruvTq9WdeQw2vs5SUsCYhdt7icIt1nNkseKPZzgV6q4FfYbH4ZIBcThYTEgLIgIkYRbJLl7/rks+ObZDxydE8W9LymoUMiqZUVbtVv0GNkcispQM0IpEG7sBdK9IYr6aKKLRaxiQxO7OMQphrUlGIscFbElV6LF5S0dQN5RbRoUdRbWWOYCy8sB83RxS7FqG/UEQslE5Nsd5v93uF3T0bLiypD/uJhn3q9fCAA=)format("woff2"),url(data:font/woff;base64,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)format("woff");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/jetbrains-mono-cyrillic-600-normal-EVf6-Yzo.woff2)format("woff2"),url(/assets/jetbrains-mono-cyrillic-600-normal-8K4wrrwR.woff)format("woff");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/jetbrains-mono-greek-600-normal-H7WoG9Et.woff2)format("woff2"),url(/assets/jetbrains-mono-greek-600-normal-mc2nkWzM.woff)format("woff");unicode-range:U+370-377,U+37A-37F,U+384-38A,U+38C,U+38E-3A1,U+3A3-3FF}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:600;src:url(data:font/woff2;base64,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)format("woff2"),url(/assets/jetbrains-mono-vietnamese-600-normal-OWROknRo.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/jetbrains-mono-latin-ext-600-normal-BfB_LPfz.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-ext-600-normal-DObL3zCW.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/jetbrains-mono-latin-600-normal-C8RAYTDA.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-600-normal-BfsvjouI.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--cm-indigo:#5c6bc0;--cm-indigo-light:#7986cb;--cm-electric-blue:#2979ff;--cm-electric-bright:#448aff;--cm-purple:#b39ddb;--cm-navy:#3949ab;--cm-glow-hover:#7986cb4d;--cm-glow-active:#2979ff59;--cm-glow-close:#e5393566;--cm-surface-card:#1e1e23eb;--cm-text-muted:#949494;--cm-transition-fast:.15s ease;--drawer-transition:.28s;--canvas:#0d0f14;--node-tint:#141824;--node-text:#f3f6ff;--node-selected:#00bfff;--glass-rim:#ffffff26;--radius:12px;--led-empty:#b4b4be80;--led-blue:#3c8cfff2;--led-green:#32cd64e6;--led-amber:#f0b428e6;--led-red:#f03c3cf2;--glass:#1418249e;--text-dim:#f3f6ffb8;--hairline:#ffffff14;--mono:"JetBrains Mono", ui-monospace, Menlo, Consolas, monospace;--sans:"Segoe UI", system-ui, sans-serif}*{box-sizing:border-box}html{scroll-behavior:smooth;scroll-padding-top:72px}body{min-height:100vh;color:var(--node-text);font:13.5px/1.45 var(--sans);background-color:var(--canvas);background-image:linear-gradient(135deg, var(--canvas) 0%, var(--node-tint) 100%);background-attachment:fixed;margin:0}a{color:inherit}h1,h2,h3{margin:0}.mono{font-family:var(--mono)}.muted{color:var(--cm-text-muted)}.small{font-size:12px}.spacer{flex:1}:focus-visible{outline:2px solid var(--node-selected);outline-offset:2px}.topbar{z-index:10;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-bottom:1px solid var(--hairline);background:#0d0f14c7;flex-wrap:wrap;align-items:center;gap:10px 18px;padding:10px 20px;display:flex;position:sticky;top:0}.brand{align-items:center;gap:9px;display:flex}.brand-mark{align-items:flex-start;gap:2px;height:18px;display:inline-flex}.brand-mark i{border-radius:2px;width:5px}.brand-mark i:first-child{background:var(--cm-indigo);height:18px}.brand-mark i:nth-child(2){background:var(--cm-electric-blue);height:12px}.brand-mark i:nth-child(3){background:var(--led-green);height:7px}.brand-name{font:600 15px var(--mono);letter-spacing:.04em}.brand-sub{font:400 12px var(--mono);color:var(--cm-text-muted);text-transform:uppercase;letter-spacing:.12em}.nav{flex-wrap:wrap;gap:4px;display:flex}.nav-link{font:12px var(--mono);color:var(--text-dim);cursor:pointer;transition:background var(--cm-transition-fast), color var(--cm-transition-fast), border-color var(--cm-transition-fast);background:0 0;border:1px solid #0000;border-radius:999px;align-items:center;gap:6px;padding:4px 9px;display:inline-flex}.nav-link:hover{color:#fff;background:#5c6bc040}.nav-link[aria-expanded=true]{color:#fff;border-color:var(--cm-indigo-light);background:#5c6bc04d}.nav-badge{font:600 11px var(--mono);color:var(--node-text);align-items:center;gap:4px;display:inline-flex}.nav-badge .led{width:7px;height:7px}.stat-btn{font:inherit;color:inherit;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:999px;margin:-3px -6px;padding:2px 6px}.stat-btn:hover{border-color:var(--cm-indigo-light);background:#5c6bc02e}.status{flex-wrap:wrap;align-items:center;gap:6px 14px;margin-left:auto;display:flex}.stat{white-space:nowrap;align-items:center;gap:6px;display:inline-flex}.stat-value{font:600 13px var(--mono)}.stat-label{color:var(--cm-text-muted);font-size:12px}.sep{background:var(--hairline);width:1px;height:16px}.pill{font:12px var(--mono);color:#e0e0e0;background:var(--cm-surface-card);border:1px solid var(--cm-indigo);cursor:pointer;transition:background var(--cm-transition-fast), color var(--cm-transition-fast), box-shadow var(--cm-transition-fast), border-color var(--cm-transition-fast);border-radius:999px;padding:5px 13px}.pill:hover{color:#fff;background:var(--cm-indigo);border-color:var(--cm-indigo-light);box-shadow:0 0 6px 0 var(--cm-glow-hover)}.pill-primary{color:#fff;background:var(--cm-navy)}.pill-quiet{background:0 0;border-color:#ffffff24}.pill-danger{border-color:#e5393599}.pill-danger:hover{box-shadow:0 0 6px 0 var(--cm-glow-close);background:#c62828;border-color:#e53935}.pill[data-busy]{opacity:.6;cursor:progress}.icon-btn{width:24px;height:24px;font:16px/1 var(--mono);color:var(--text-dim);cursor:pointer;transition:all var(--cm-transition-fast);background:0 0;border:1px solid #0000;border-radius:999px;place-items:center;display:inline-grid}.icon-btn:hover{color:#fff;background:var(--cm-indigo);box-shadow:0 0 6px 0 var(--cm-glow-hover)}.icon-btn-ring{border-color:var(--cm-indigo);background:var(--cm-surface-card);width:28px;height:28px;font-size:15px}.icon-btn-ring[data-busy]{animation:.9s linear infinite spin}@keyframes spin{to{transform:rotate(360deg)}}.chip{max-width:100%;font:11px/1.2 var(--mono);color:var(--text-dim);white-space:nowrap;text-overflow:ellipsis;background:#ffffff0a;border:1px solid #ffffff1f;border-radius:999px;align-items:center;gap:5px;padding:3px 8px;text-decoration:none;display:inline-flex;overflow:hidden}button.chip,a.chip{cursor:pointer}button.chip:hover,a.chip:hover{color:#fff;border-color:var(--cm-indigo-light);box-shadow:0 0 6px 0 var(--cm-glow-hover)}.chip-gh[data-state=OPEN]{color:#8ab4ff;border-color:#448aff80}.chip-gh[data-state=MERGED]{color:var(--cm-purple);border-color:#b39ddb73}.chip-gh[data-state=CLOSED]{color:#ef9a9a;border-color:#f03c3c66}.chip-gh[data-state=MIXED]{color:#ffd479;border-color:#f0b42873}.chip-gh[data-state=UNKNOWN]{opacity:.7;border-style:dashed}.chip-journal .dot{background:var(--led-empty);border-radius:50%;flex:none;width:7px;height:7px}.chip-journal[data-status=open] .dot{background:var(--led-blue);box-shadow:0 0 5px var(--led-blue)}.chip-journal[data-status=stale] .dot{background:var(--led-amber);box-shadow:0 0 5px var(--led-amber)}.chip-journal[data-status=concluded] .dot{background:var(--led-green);box-shadow:0 0 5px var(--led-green)}.chip-journal[data-status=missing]{color:#ef9a9a;border-style:dashed}.chip-journal[data-status=missing] .dot{background:var(--led-red)}.chip-quiet{color:var(--cm-text-muted);border-color:#0000}.chip-card{color:#c5cae9;background:#5c6bc01f;border-color:#5c6bc080}.chip-git .dirty{color:#ffd479}.led{--c:var(--led-empty);background:radial-gradient(circle at 35% 30%, #ffffffbf 0 14%, var(--c) 46%, color-mix(in srgb, var(--c) 55%, #000) 100%);width:10px;height:10px;box-shadow:0 0 7px var(--c);border-radius:50%;flex:none}.led[data-led=empty]{--c:var(--led-empty);box-shadow:none}.led[data-led=blue],.led[data-led=pulse]{--c:var(--led-blue)}.led[data-led=green]{--c:var(--led-green)}.led[data-led=amber]{--c:var(--led-amber)}.led[data-led=red]{--c:var(--led-red);animation:2s ease-in-out infinite led-pulse}.led[data-led=pulse]{animation:2.5s ease-in-out infinite led-pulse}@keyframes led-pulse{50%{box-shadow:0 0 1px var(--c);filter:brightness(.7)}}main{padding:18px 20px 64px}.section-head{flex-wrap:wrap;align-items:baseline;gap:6px 14px;margin-bottom:12px;display:flex}.section-head h1,.panel-head h2{font:600 13px var(--mono);text-transform:uppercase;letter-spacing:.12em}.banner{border-radius:8px;margin-bottom:10px;padding:9px 12px;font-size:12.5px}.banner-error{color:#ffcdd2;background:#f03c3c1f;border:1px solid #f03c3c73}.inbox{background:var(--glass);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);border-radius:var(--radius);border:1.5px solid #f0b42859;margin-bottom:12px;padding:10px 12px}.inbox-clear{-webkit-backdrop-filter:none;backdrop-filter:none;background:0 0;border:none;align-items:center;gap:8px;padding:6px 4px;display:flex}.inbox-head{flex-wrap:wrap;align-items:center;gap:6px 10px;margin-bottom:4px;display:flex}.inbox-heading{font:600 12px var(--mono);text-transform:uppercase;letter-spacing:.08em}.inbox-row{border-top:1px solid var(--hairline);grid-template-columns:64px auto minmax(0,1fr) auto auto;align-items:center;gap:10px;padding:7px 2px;display:grid}.inbox-kind{font:600 10px var(--mono);text-transform:uppercase;letter-spacing:.06em;color:#c5cae9;background:#5c6bc038;border-radius:4px;justify-self:start;padding:2px 6px}.inbox-row[data-kind=pr] .inbox-kind{color:#8ab4ff;background:#3c8cff29}.inbox-row[data-kind=issue] .inbox-kind{color:#ffd479;background:#f0b42824}.inbox-label{font-size:11.5px}.inbox-title{min-width:0;font:inherit;color:var(--node-text);text-align:left;white-space:nowrap;text-overflow:ellipsis;cursor:pointer;background:0 0;border:none;padding:0;font-size:13px;text-decoration:none;overflow:hidden}.inbox-title:hover{text-decoration:underline}.inbox-actions{gap:6px;display:flex}.inbox-actions .pill{padding:3px 11px;font-size:11.5px}.link-btn{font:11.5px var(--mono);color:#9fa8da;cursor:pointer;background:0 0;border:none;padding:0}.link-btn:hover{color:#fff;text-decoration:underline}.inbox-more{margin:6px auto 0;display:block}.board{grid-template-columns:repeat(6,minmax(232px,1fr));align-items:start;gap:12px;padding-bottom:8px;display:grid;overflow-x:auto}.col{background:var(--glass);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);border:1.5px solid var(--glass-rim);border-radius:var(--radius);flex-direction:column;gap:8px;min-width:0;padding:10px;display:flex}.col-head{align-items:center;gap:8px;padding:2px 2px 0 4px;display:flex}.col-head h2{min-width:0;font:600 12px/1.3 var(--mono);text-transform:uppercase;letter-spacing:.08em;overflow-wrap:anywhere;flex:1}.count{font:11px var(--mono);color:var(--cm-text-muted);background:#ffffff0f;border-radius:999px;padding:1px 7px}.col-hint{color:var(--cm-text-muted);margin:-4px 0 0 22px;font-size:11.5px}.col-body{min-height:72px;transition:background var(--cm-transition-fast);border-radius:10px;flex-direction:column;gap:8px;padding:2px;display:flex}.col-body.drop-target{background:#2979ff12;outline:1px dashed #448aff66}.col-empty{text-align:center;font:11px var(--mono);color:#94949499;margin:0;padding:18px 0}.drop-line{background:var(--cm-electric-bright);height:3px;box-shadow:0 0 8px var(--cm-glow-active);border-radius:2px;flex:none}.col-more{align-self:center}.card{border:1.5px solid var(--glass-rim);border-radius:var(--radius);cursor:grab;transition:border-color var(--cm-transition-fast), box-shadow var(--cm-transition-fast), transform var(--cm-transition-fast);background:#141824db;flex-direction:column;gap:6px;padding:10px 11px 10px 14px;display:flex;position:relative}.card:before{content:"";background:color-mix(in srgb, var(--led) 70%, #fff 30%);opacity:.85;border-radius:2px;width:3px;position:absolute;top:12px;bottom:12px;left:5px}.card:hover{box-shadow:0 0 10px 0 var(--cm-glow-hover);border-color:#7986cbb3}.card.dragging{opacity:.35;transform:scale(.98)}.card-areas{gap:4px;display:flex}.area{font:600 10px/1 var(--mono);color:#c5cae9;background:#5c6bc038;border:none;border-radius:4px;padding:3px 5px}button.area{cursor:pointer;transition:background var(--cm-transition-fast), color var(--cm-transition-fast), box-shadow var(--cm-transition-fast)}button.area:hover{color:#fff;box-shadow:0 0 6px 0 var(--cm-glow-hover);background:#5c6bc08c}button.area[aria-pressed=true],.area-static{color:#fff;background:var(--cm-indigo);box-shadow:0 0 6px 0 var(--cm-glow-hover)}.card.is-dim,.jrow.is-dim{opacity:.4;transition:opacity var(--cm-transition-fast), border-color var(--cm-transition-fast)}.card.is-dim:hover,.card.is-dim:focus-visible,.card.is-dim:focus-within,.jrow.is-dim:hover,.jrow.is-dim:focus-visible,.jrow.is-dim:focus-within{opacity:1}.card.is-match,.jrow.is-match{box-shadow:0 0 10px 0 var(--cm-glow-hover);border-color:#7986cbbf}.policy-chips{flex-wrap:wrap;gap:4px;display:inline-flex}.chip-policy{color:#c5cae9;background:#5c6bc024;border-color:#7986cb99}.chip-policy:before{content:"§";opacity:.65}.chip-policy[data-kind=mentioned]{color:var(--text-dim);background:0 0;border-style:dotted}.chip-policy[data-unknown=true]{color:var(--cm-text-muted);border-color:#ffffff2e}.chip-policy[aria-pressed=true]{color:#fff;background:var(--cm-indigo);border-color:var(--cm-indigo-light);box-shadow:0 0 6px 0 var(--cm-glow-hover)}.welcome{margin-bottom:14px}.welcome h2{margin-bottom:6px;font-size:14px}.welcome ul{color:var(--text-dim);gap:4px;margin:0;padding-left:18px;display:grid}.banner-note{margin-bottom:12px}.banner-note code{font-family:var(--mono);font-size:11.5px}.count.count-match{color:#fff;background:#5c6bc066}.filter-slot:empty{display:none}.filter-pill{border:1px solid var(--cm-indigo);box-shadow:0 0 8px 0 var(--cm-glow-hover);background:#3949ab40;border-radius:999px;align-items:center;gap:8px;padding:3px 4px 3px 6px;font-size:12.5px;display:inline-flex}.filter-clear{width:20px;height:20px;font:11px/1 var(--mono);color:var(--text-dim);cursor:pointer;background:0 0;border:none;border-radius:999px;place-items:center;display:inline-grid}.filter-clear:hover{color:#fff;background:var(--cm-indigo)}.card-title{font-size:13.5px;font-weight:600;line-height:1.35}.card-notes{color:var(--text-dim);-webkit-line-clamp:2;white-space:pre-line;-webkit-box-orient:vertical;margin:0;font-size:12.5px;display:-webkit-box;overflow:hidden}.card-links{flex-wrap:wrap;gap:4px;display:flex}.chip-more{color:var(--text-dim);cursor:help;border-style:dashed}.col-body.is-stacked{gap:0}.card-more-body{flex-direction:column;gap:6px;display:flex}.card-fulltitle{margin:0;font-size:13px;font-weight:600;line-height:1.35;display:none}.card.is-strip{flex-flow:wrap;align-items:center;gap:0 6px;padding-top:7px;padding-bottom:8px;box-shadow:0 -4px 10px #00000059}.card.is-strip>.card-title{white-space:nowrap;text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.card.is-strip>.card-more{opacity:0;flex-basis:100%;grid-template-rows:0fr;transition:grid-template-rows .3s cubic-bezier(.4,0,.2,1) .15s,opacity .2s .15s;display:grid}.card.is-strip .card-more-inner{min-height:0;overflow:hidden}.card.is-strip .card-more-body{padding-top:6px}.card.is-strip.is-truncated .card-fulltitle{display:block}.card.is-strip:not(.is-truncated) .card-more-body:has(>.card-fulltitle:only-child){padding-top:0}.card.is-strip:hover>.card-more,.card.is-strip:focus-visible>.card-more,.card.is-strip:focus-within>.card-more{opacity:1;grid-template-rows:1fr}.card.is-strip:hover>.card-more{transition:grid-template-rows .42s cubic-bezier(.25,.8,.25,1) .35s,opacity .3s .47s}.card.is-strip:focus-visible>.card-more,.card.is-strip:focus-within>.card-more{transition:grid-template-rows .42s cubic-bezier(.25,.8,.25,1),opacity .3s .12s}.card.is-strip+.card.is-strip{margin-top:-6px}.card.is-strip:before{top:9px;bottom:9px}.card.is-strip:hover,.card.is-strip:focus-visible,.card.is-strip:focus-within{z-index:2}.stack-icon{flex-direction:column;gap:2px;display:inline-flex}.stack-icon i{background:currentColor;border-radius:1px;width:11px;height:2px;display:block}.stack-icon i:nth-child(2){margin-left:2px}.stack-icon i:nth-child(3){margin-left:4px}.stack-toggle[aria-pressed=true]{color:#fff;border-color:#7986cb80}.hint{color:#a5e8bd;border-left:2px solid var(--led-green);background:#32cd6414;border-radius:4px;margin:0;padding:4px 8px;font-size:12px}.hint-amber{color:#ffd479;border-left-color:var(--led-amber);background:#f0b42814}.hint-row{flex-wrap:wrap;align-items:center;gap:8px;margin-top:6px;display:flex}.hint-row .pill{padding:2px 10px}.panel{background:var(--glass);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);border:1.5px solid var(--glass-rim);border-radius:var(--radius);padding:14px 16px 16px}.panel-head{flex-wrap:wrap;align-items:baseline;gap:4px 12px;margin-bottom:10px;display:flex}.panel-tools{flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:10px;display:flex}.filters{flex-wrap:wrap;gap:4px;display:flex}.filter{font:11.5px var(--mono);color:var(--text-dim);cursor:pointer;background:0 0;border:1px solid #ffffff1a;border-radius:999px;align-items:center;gap:6px;padding:4px 10px;display:inline-flex}.filter:hover{border-color:var(--cm-indigo-light)}.filter[aria-selected=true]{color:#fff;background:var(--cm-navy);border-color:var(--cm-indigo)}.search{min-width:180px;margin-left:auto}input,select,textarea{font:13px var(--sans);color:var(--node-text);width:100%;transition:border-color var(--cm-transition-fast), box-shadow var(--cm-transition-fast);background:#ffffff0a;border:1px solid #ffffff24;border-radius:8px;padding:7px 9px}.search{border-radius:999px;width:auto;padding:5px 10px}input:focus,select:focus,textarea:focus{border-color:var(--cm-electric-bright);box-shadow:0 0 0 3px var(--cm-glow-active);outline:none}select option{background:#16181f}textarea{resize:vertical;font-family:var(--sans)}.jlist{flex-direction:column;gap:5px;display:flex}.jrow{cursor:pointer;transition:background var(--cm-transition-fast), border-color var(--cm-transition-fast);background:#ffffff06;border:1px solid #0000;border-radius:10px;grid-template-columns:12px minmax(0,1fr);gap:10px;padding:10px 12px;display:grid}.jrow:hover{border-color:var(--glass-rim);background:#ffffff0b}.jrow>.led{margin-top:5px}.jrow-top{align-items:baseline;gap:10px;min-width:0;display:flex}.jrow-top time{flex:none;font-size:11.5px}.jrow-top h3{white-space:nowrap;text-overflow:ellipsis;flex:1;min-width:0;font-size:13.5px;font-weight:600;overflow:hidden}.status-tag{font:600 10px var(--mono);text-transform:uppercase;letter-spacing:.08em;color:var(--cm-text-muted);border:1px solid #ffffff1f;border-radius:4px;flex:none;padding:2px 6px}.status-tag[data-status=open]{color:#8ab4ff;border-color:#3c8cff80}.status-tag[data-status=stale]{color:#ffd479;border-color:#f0b42880}.status-tag[data-status=concluded]{color:#8be0a8;border-color:#32cd6473}.jrow-obj,.jrow-next{-webkit-line-clamp:2;-webkit-box-orient:vertical;margin:4px 0 0;font-size:12.5px;display:-webkit-box;overflow:hidden}.jrow-obj{color:var(--cm-text-muted)}.jrow-next{color:var(--text-dim)}.jrow-next .mono{color:#8ab4ff;font-size:11px}.jrow-meta{flex-wrap:wrap;align-items:center;gap:5px 10px;margin-top:7px;display:flex}.empty{text-align:center;padding:18px 0}.list-more{align-self:center;margin-top:6px}.gh-group+.gh-group{margin-top:16px}.gh-group h3{font:600 11.5px var(--mono);text-transform:uppercase;letter-spacing:.08em;color:var(--text-dim);align-items:center;gap:8px;margin-bottom:6px;display:flex}.gh-group p{margin:0}.gh-item{border-radius:8px;grid-template-columns:auto minmax(0,1fr);column-gap:10px;padding:6px 8px;text-decoration:none;display:grid}.gh-item:hover{background:#ffffff0b}.gh-num{color:var(--cm-purple);font-size:12px}.gh-item[data-state=OPEN] .gh-num{color:#8ab4ff}.gh-title{white-space:nowrap;text-overflow:ellipsis;font-size:13px;overflow:hidden}.gh-meta{grid-column:2}:root{--drawer-w:min(540px, 100vw)}main{transition:margin-right var(--drawer-transition) ease}body.drawer-push main{margin-right:var(--drawer-w)}.drawer{top:var(--topbar-h,0px);z-index:20;width:var(--drawer-w);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-left:1.5px solid var(--glass-rim);visibility:hidden;transition:transform var(--drawer-transition) ease, visibility 0s linear var(--drawer-transition);background:#101013f2;flex-direction:column;display:flex;position:fixed;bottom:0;right:0;transform:translate(104%);box-shadow:-24px 0 48px #00000080}.drawer.open{visibility:visible;transition:transform var(--drawer-transition) ease;transform:none}.drawer[data-mode=push]{box-shadow:none}.drawer-head{border-bottom:1px solid var(--hairline);align-items:center;gap:10px;padding:10px 14px 10px 18px;display:flex}.drawer-back{flex:none;padding:3px 10px}.segmented{border:1px solid #ffffff1f;border-radius:999px;flex:none;padding:2px;display:inline-flex}.seg{font:11px var(--mono);color:var(--text-dim);cursor:pointer;background:0 0;border:none;border-radius:999px;padding:3px 9px}.seg[aria-pressed=true]{color:#fff;background:var(--cm-indigo)}.seg:disabled{cursor:not-allowed;opacity:.45}.drawer .panel-head{margin-bottom:10px}.drawer .search{width:100%;margin-left:0}.drawer .jrow-top{flex-wrap:wrap}.drawer .jrow-top h3{white-space:normal;flex-basis:100%;order:3}.drawer-title{min-width:0;font:600 13px var(--mono);white-space:nowrap;text-overflow:ellipsis;flex:1;overflow:hidden}.drawer-body{flex:1;padding:16px 18px 40px;overflow:auto}.editor{flex-direction:column;gap:12px;display:flex}.field{flex-direction:column;gap:5px;min-width:0;display:flex}.field-label{font:600 11px var(--mono);text-transform:uppercase;letter-spacing:.08em;color:var(--text-dim)}.field-hint{color:var(--cm-text-muted);font-size:11.5px}.field-row{grid-template-columns:1fr 1fr;gap:12px;display:grid}.field-error{color:#ef9a9a;min-height:1em;margin:0;font-size:12.5px}.stack{flex-direction:column;gap:6px;display:flex}.editor-actions{align-items:center;gap:8px;display:flex}.jmeta{flex-wrap:wrap;align-items:center;gap:8px 12px;margin-bottom:12px;display:flex}.jmeta-actions{gap:6px;margin-left:auto;display:flex}.jmeta-cards{flex-wrap:wrap;align-items:center;gap:6px;margin:10px 0;display:flex}.drawer-body>.card-links{margin-bottom:8px}.md{border-top:1px solid var(--hairline);color:#dfe3ee;overflow-wrap:anywhere;margin-top:14px;padding-top:6px;font-size:13px;line-height:1.55}.md h2,.md h3,.md h4,.md h5,.md h6{font-family:var(--mono);color:var(--node-text);margin:20px 0 8px;font-weight:600}.md h2{font-size:15px}.md h3{text-transform:uppercase;letter-spacing:.08em;color:#9fa8da;font-size:13px}.md h4,.md h5,.md h6{font-size:12.5px}.md p{margin:8px 0}.md code{font:12px var(--mono);background:#ffffff0f;border-radius:4px;padding:1px 5px}.md pre{border:1px solid var(--hairline);background:#00000059;border-radius:8px;padding:10px 12px;overflow:auto}.md pre code{background:0 0;padding:0}.md-li{padding-left:calc(var(--depth) * 18px);gap:8px;margin:3px 0;display:flex}.md-mark{min-width:1.2em;font-family:var(--mono);color:var(--cm-indigo-light);flex:none}.md-ref{color:#9fa8da;border-bottom:1px dotted #9fa8da99}.md a{color:#8ab4ff}.md blockquote{border-left:3px solid var(--cm-indigo);color:var(--text-dim);margin:8px 0;padding:2px 12px}.md hr{border:none;border-top:1px solid var(--hairline);margin:16px 0}.md-table{margin:10px 0;overflow-x:auto}.md table{border-collapse:collapse;font-size:12px}.md th,.md td{border:1px solid var(--hairline);text-align:left;vertical-align:top;padding:5px 8px}.md th{background:#ffffff0a}#toasts{z-index:30;flex-direction:column;align-items:flex-end;gap:8px;display:flex;position:fixed;bottom:18px;right:18px}.toast{font:12px var(--mono);background:var(--cm-surface-card);border:1px solid var(--cm-indigo);border-radius:999px;padding:8px 14px;transition:opacity .3s,transform .3s;box-shadow:0 6px 18px #0006}.toast-error{color:#ffcdd2;border-color:#e53935;border-radius:10px;max-width:min(520px,90vw)}.toast-out{opacity:0;transform:translateY(6px)}@media (max-width:640px){main{padding:14px 16px 48px}.board{scroll-snap-type:x mandatory;grid-template-columns:repeat(6,82vw)}.col{scroll-snap-align:start}.topbar{padding:10px 16px;position:static}.drawer{top:0}.status{margin-left:0}.field-row{grid-template-columns:1fr}.search{width:100%;margin-left:0}.jrow-top{flex-wrap:wrap}.inbox-row{grid-template-columns:auto auto minmax(0,1fr)}.inbox-when{display:none}.inbox-actions{grid-column:1/-1}.jrow-top h3{white-space:normal;flex-basis:100%;order:3}}@media (prefers-reduced-motion:reduce){*,:before{scroll-behavior:auto!important;transition:none!important;animation:none!important}}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-thumb{background:#ffffff1f padding-box padding-box;border:2px solid #0000;border-radius:999px}::-webkit-scrollbar-track{background:0 0}
@@ -0,0 +1,7 @@
1
+ (function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();function e(e,t,n,r,i){let a=e.cards.find(e=>e.id===t);if(!a)throw Error(`no card with id "${t}"`);if(!e.columns.some(e=>e.id===n))throw Error(`unknown column "${n}"`);e.cards.splice(e.cards.indexOf(a),1);let o=e.cards.filter(e=>e.column===n),s=Math.max(0,Math.min(Number.isFinite(r)?r:o.length,o.length));a.column!==n&&(a.updated=i),a.column=n,s<o.length?e.cards.splice(e.cards.indexOf(o[s]),0,a):o.length>0?e.cards.splice(e.cards.indexOf(o[o.length-1])+1,0,a):e.cards.push(a)}var t=(e,t)=>e.columns.find(e=>e.role===t),n=(e,t)=>e.columns.find(e=>e.id===t)?.role;async function r(e,t,n){let r=await fetch(`/api${t}`,{method:e,headers:n===void 0?void 0:{"Content-Type":`application/json`},body:n===void 0?void 0:JSON.stringify(n)}),i=await r.json().catch(()=>({error:`HTTP ${r.status}`}));if(!r.ok)throw Error(i.error??`HTTP ${r.status}`);return i}var i={meta:()=>r(`GET`,`/meta`),board:()=>r(`GET`,`/board`),move:(e,t,n)=>r(`POST`,`/board/move`,{id:e,column:t,index:n}),saveCard:e=>r(`POST`,`/board/card`,{card:e}),deleteCard:e=>r(`POST`,`/board/delete`,{id:e}),inboxDismiss:(e,t)=>r(`POST`,`/board/inbox`,{key:e,dismissed:t}),closeJournal:(e,t)=>r(`POST`,`/board/journal`,{file:e,state:t?`closed`:null}),journals:()=>r(`GET`,`/journals`),journal:e=>r(`GET`,`/journal?file=${encodeURIComponent(e)}`),repo:(e=!1)=>r(`GET`,e?`/repo?force=1`:`/repo`)};function a(e,t,...n){let r=document.createElement(e);for(let[e,n]of Object.entries(t??{}))n!=null&&n!==!1&&(e.startsWith(`on`)&&typeof n==`function`?r.addEventListener(e.slice(2).toLowerCase(),n):e===`class`?r.className=String(n):e===`value`||e===`checked`||e===`selected`?r[e]=n:r.setAttribute(e,n===!0?``:String(n)));return o(r,n),r}function o(e,t){for(let n of t)n!=null&&n!==!1&&(Array.isArray(n)?o(e,n):e.appendChild(typeof n==`object`?n:document.createTextNode(String(n))))}function s(e,...t){e.replaceChildren(),o(e,t)}function c(e){if(!e)return``;let t=Date.now()-new Date(e).getTime(),n=Math.round(t/6e4);if(n<1)return`just now`;if(n<60)return`${n}m ago`;let r=Math.round(n/60);if(r<24)return`${r}h ago`;let i=Math.round(r/24);return i<60?`${i}d ago`:`${Math.round(i/30)}mo ago`}var l=()=>new Date().toISOString().slice(0,10);function u(e){if(!e||/^\d{4}-\d{2}-\d{2}$/.test(e))return e??``;let t=new Date(e);if(Number.isNaN(t.getTime()))return e;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}`}var d=e=>e&&!e.startsWith(`0001`)?e:null,f=(e,t)=>new Date(Date.parse(e)+t*864e5).toISOString().slice(0,10);function p(e,t){let n=f(e.date,-1),r=f(e.date,21),i=[];for(let a of e.prRefs){let e=t.get(a),o=e?.createdAt?.slice(0,10);e&&o&&o>=n&&o<=r&&i.push(e)}return i}function ee(e){let t=e.replace(/^[a-z]+(\([^)]*\))?!?:\s*/i,``).trim()||e;return t.charAt(0).toUpperCase()+t.slice(1)}function te(e){return e.replace(/^\d{4}-\d{2}-\d{2}\s*[—–-]\s*/,``).replace(/\s*[—–-]\s*\(?\d{4}-\d{2}-\d{2}\)?\s*$/,``).replace(/\s*\(\d{4}-\d{2}-\d{2}\)\s*$/,``).replace(/`/g,``).trim()||e}function m(e,n){for(let r of n){let n=t(e,r);if(n)return n.id}return e.columns[0].id}function h(e,t,n,r){let i=new Map(n.map(e=>[e.number,e])),a=new Set(e.inboxDismissed??[]),o=new Set,s=new Set,c=new Set;for(let t of e.cards)t.links?.prs?.forEach(e=>o.add(e)),t.links?.issues?.forEach(e=>s.add(e)),t.links?.journals?.forEach(e=>c.add(e));let l=new Map(t.map(e=>[e.file,p(e,i)]));for(let e of c)l.get(e)?.forEach(e=>o.add(e.number));let u=m(e,[`review`,`active`]),d=m(e,[`active`]),f=m(e,[`intake`]),h=t.filter(e=>e.status===`open`),g=[],_=new Set;for(let e of n){if(e.state!==`OPEN`||o.has(e.number)||a.has(`pr:${e.number}`))continue;let t=h.filter(t=>l.get(t.file)?.some(t=>t.number===e.number)).map(e=>e.file);_.add(e.number),g.push({key:`pr:${e.number}`,kind:`pr`,label:`#${e.number}`,title:e.title,when:e.updatedAt,url:e.url,suggest:{title:ee(e.title),column:u,links:{prs:[e.number],...t.length?{journals:t}:{}}}})}for(let e of h){if(c.has(e.file)||a.has(`journal:${e.file}`))continue;let t=l.get(e.file)??[];t.some(e=>o.has(e.number)||_.has(e.number))||g.push({key:`journal:${e.file}`,kind:`journal`,label:e.date,title:e.title,when:e.modified,file:e.file,suggest:{title:te(e.title),column:d,links:{journals:[e.file],...t.length?{prs:t.map(e=>e.number)}:{}}}})}for(let e of r)e.state!==`OPEN`||s.has(e.number)||a.has(`issue:${e.number}`)||g.push({key:`issue:${e.number}`,kind:`issue`,label:`#${e.number}`,title:e.title,when:e.updatedAt,url:e.url,suggest:{title:e.title,column:f,links:{issues:[e.number]}}});return g.sort((e,t)=>t.when.localeCompare(e.when))}var g={meta:null,board:null,boardError:null,journals:[],journalsLoaded:!1,journalsError:null,repo:null,repoLoading:!1,journalFilter:`attention`,journalQuery:``,showAllJournals:!1,showAllDone:!1,areaFilter:null,policyFilter:null,dragging:null,drawerMode:_(`drawer-mode`)===`overlay`?`overlay`:`push`,stackOverrides:{}};function _(e){try{return localStorage.getItem(`lore-hud:${e}`)}catch{return null}}function v(e,t){try{localStorage.setItem(`lore-hud:${e}`,t)}catch{}}var y=()=>{},b=!1;function ne(e){y=e}function x(){g.dragging?b=!0:(b=!1,y())}function re(){b&&x()}function ie(e){let t,n;return r=>((r!==t||n===void 0)&&(t=r,n=e(r)),n)}var ae=ie(e=>new Map((e?.prs??[]).map(e=>[e.number,e]))),oe=ie(e=>new Map((e?.issues??[]).map(e=>[e.number,e]))),se=ie(e=>new Map(e.map(e=>[e.file,e]))),S=e=>ae(g.repo).get(e),ce=e=>oe(g.repo).get(e),le=e=>se(g.journals).get(e),C=()=>`${g.meta?.journals??`.research`}/`;function ue(e){return(g.board?.cards??[]).filter(t=>t.links?.journals?.includes(e))}var de=e=>p(e,ae(g.repo));function fe(){return!g.board||!g.journalsLoaded?[]:h(g.board,g.journals,g.repo?.prs??[],g.repo?.issues??[])}function pe(e){if(e.status===`concluded`||e.status===`closed`)return!1;let t=de(e);return t.length>0&&t.every(e=>e.state!==`OPEN`)&&t.some(e=>e.state===`MERGED`)}function me(e){if(!g.board)return!1;let t=n(g.board,e.column);if(t===`done`||t===`review`)return!1;let r=e.links?.prs??[];return r.length>0&&r.every(e=>S(e)?.state===`MERGED`)}function he(e){if(e in g.stackOverrides)return g.stackOverrides[e];let t=g.board?n(g.board,e):void 0;return t===`intake`||t===`done`}function ge(){try{let e=_(`stacked:${g.meta?.repo??``}`),t=e?JSON.parse(e):{};g.stackOverrides=t&&typeof t==`object`?t:{}}catch{g.stackOverrides={}}}function _e(e,t){g.stackOverrides={...g.stackOverrides,[e]:t},v(`stacked:${g.meta?.repo??``}`,JSON.stringify(g.stackOverrides)),x()}var ve=(e,t)=>e.policies.declared.includes(t)||e.policies.mentioned.includes(t),w=e=>e instanceof Error?e.message:String(e);function T(e,t=`info`){let n=document.getElementById(`toasts`);n||(n=a(`div`,{id:`toasts`,"aria-live":`polite`}),document.body.append(n));let r=a(`div`,{class:`toast toast-${t}`},e);n.append(r),setTimeout(()=>r.classList.add(`toast-out`),t===`error`?6e3:2600),setTimeout(()=>r.remove(),t===`error`?6400:3e3)}async function ye(){try{g.meta=await i.meta(),document.title=`${g.meta.repo} · LORE HUD`,ge()}catch(e){T(`HUD: ${w(e)}`,`error`)}x()}async function be(){try{g.board=await i.board(),g.boardError=null}catch(e){g.boardError=w(e)}x()}async function E(){try{g.journals=await i.journals(),g.journalsError=null}catch(e){g.journalsError=w(e)}g.journalsLoaded=!0,x()}async function D(e=!1){g.repoLoading=!0,x();try{g.repo=await i.repo(e)}catch(e){T(`GitHub: ${w(e)}`,`error`)}g.repoLoading=!1,x()}async function xe(t,n,r){if(!g.board)return;let a=structuredClone(g.board),o=g.board.cards.find(e=>e.id===t)?.column;try{e(g.board,t,n,r,l())}catch{return}x();try{g.board=await i.move(t,n,r),o!==n&&T(`Moved to ${g.board.columns.find(e=>e.id===n)?.title??n}`)}catch(e){g.board=a,T(`Move failed: ${w(e)}`,`error`)}x()}async function Se(e){g.board=await i.saveCard(e),x()}async function Ce(e){g.board=await i.deleteCard(e),x()}function we(e,t){let n=new URL(location.href);t?n.searchParams.set(e,t):n.searchParams.delete(e),history.replaceState(null,``,n)}function Te(e){g.areaFilter=e,we(`area`,e),x()}var Ee=e=>Te(g.areaFilter===e?null:e);function De(e){g.policyFilter=e,we(`policy`,e),x()}var Oe=e=>De(g.policyFilter===e?null:e);async function ke(e){try{g.board=await i.saveCard({...e.suggest}),x(),T(`Added to ${g.board.columns.find(t=>t.id===e.suggest.column)?.title??e.suggest.column}. Click the card to edit it.`)}catch(e){T(w(e),`error`)}}async function Ae(e,t){try{g.board=await i.inboxDismiss(e,t),x()}catch(e){T(w(e),`error`)}}async function O(e,t){try{g.board=await i.closeJournal(e,t),await E(),T(t?`Journal marked closed`:`Journal reopened`)}catch(e){T(w(e),`error`)}}var je=()=>g.board?.areas??{},Me=e=>je()[e]??e;function Ne(e){let t=Object.keys(je()),n=[];for(let r of e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean)){let e=t.find(e=>e.toLowerCase()===r.toLowerCase())??r;n.includes(e)||n.push(e)}return n}var Pe=e=>e===`pulse`?`blue`:e;function k(e,t,n=`pr`){let r=g.repo?`#${e} not found on GitHub`:`#${e}: GitHub data still loading`;return a(t?`a`:`span`,{class:`chip chip-gh`,"data-state":t?.state??`UNKNOWN`,href:t?.url,target:t?`_blank`:void 0,rel:t?`noreferrer`:void 0,title:t?`${n===`pr`?`PR`:`Issue`} #${e}: ${t.title}`:r,onclick:e=>e.stopPropagation()},a(`span`,{class:`mono`},`#${e}`),t?` ${t.state.toLowerCase()}`:``)}function Fe(e){let t=new Set((g.meta?.policies??[]).map(e=>e.name)),n=(e,n)=>{let r=g.policyFilter===e,i=!t.has(e);return a(`button`,{type:`button`,class:`chip chip-policy`,"data-kind":n,"data-unknown":i?`true`:void 0,"aria-pressed":String(r),title:(n===`declared`?`Declared on the journal's Policies: line`:`Mentioned in the journal, not declared`)+(i?` — no ${e}.md among the repository's policies`:``)+(r?`. Click to clear the filter.`:`. Click to show journals that use ${e}.`),onclick:t=>{t.stopPropagation(),Oe(e)}},e)},r=[...e.policies.declared.map(e=>n(e,`declared`)),...e.policies.mentioned.map(e=>n(e,`mentioned`))];return r.length?a(`span`,{class:`policy-chips`},r):null}function Ie(e,t){return a(`a`,{class:`gh-item`,href:e.url,target:`_blank`,rel:`noreferrer`,"data-state":e.state},a(`span`,{class:`mono gh-num`},`#${e.number}`),a(`span`,{class:`gh-title`},e.title),a(`span`,{class:`muted small gh-meta`},t))}function Le(e,t,n){return a(`div`,{class:`gh-group`},a(`h3`,null,e,a(`span`,{class:`count`},String(t.length))),t.length?t:a(`p`,{class:`muted small`},n))}function Re(){let e=g.repo;return a(`div`,{class:`panel-head`},a(`span`,{class:`muted small`},g.repoLoading?`asking GitHub…`:e?.error&&!e.lastGood?`unavailable`:e?`fetched ${c(e.fetchedAt)}`:``),a(`button`,{type:`button`,class:`link-btn`,disabled:g.repoLoading,onclick:()=>void D(!0)},`Refresh`))}function ze(e){let t=g.repo;if(!t){s(e,Re(),a(`p`,{class:`muted`},g.repoLoading?`Asking GitHub…`:`No GitHub data yet.`));return}if(t.error&&!t.lastGood){s(e,Re(),a(`p`,{class:`muted`},`No GitHub data: ${t.error}.`),a(`p`,{class:`muted small`},`The board and journals work without it; PR and issue chips and the Inbox fill in once gh can reach the repository.`));return}let n=t.prs.filter(e=>e.state===`OPEN`),r=t.issues.filter(e=>e.state===`OPEN`),i=t.prs.filter(e=>e.state===`MERGED`&&d(e.mergedAt)).sort((e,t)=>t.mergedAt.localeCompare(e.mergedAt)).slice(0,10);s(e,Re(),t.error?a(`div`,{class:`banner banner-error`,role:`alert`},`GitHub refresh failed: ${t.error}. Showing the last good fetch.`):null,Le(`Open pull requests`,n.map(e=>Ie(e,`${e.isDraft?`draft · `:``}${e.headRefName??``} · ${c(e.updatedAt)}`)),`None open.`),Le(`Open issues`,r.map(e=>Ie(e,`${(e.labels??[]).join(`, `)||`unlabeled`} · ${c(e.updatedAt)}`)),`None open.`),Le(`Recently merged`,i.map(e=>Ie(e,c(e.mergedAt))),`Nothing merged yet.`))}var A=15,Be={open:`pulse`,stale:`amber`,concluded:`green`,closed:`empty`},j=[{id:`attention`,label:`Needs attention`,test:e=>e.status===`open`||e.status===`stale`},{id:`open`,label:`Open`,test:e=>e.status===`open`},{id:`stale`,label:`Stale`,test:e=>e.status===`stale`},{id:`concluded`,label:`Concluded`,test:e=>e.status===`concluded`},{id:`closed`,label:`Closed`,test:e=>e.status===`closed`},{id:`all`,label:`All`,test:()=>!0}],M=null;function Ve(e){let t=a(`div`,{class:`filters`,role:`tablist`,"aria-label":`Journal filter`}),n=a(`input`,{type:`search`,class:`search`,placeholder:`Filter journals…`,"aria-label":`Filter journals`,value:g.journalQuery,oninput:()=>{g.journalQuery=n.value,x()}}),r=a(`span`,{class:`muted small`}),i=a(`span`,{class:`filter-slot`}),o=a(`div`,{class:`jlist`});s(e,a(`div`,{class:`panel-head`},r,i),a(`div`,{class:`panel-tools`},t,n),o),M={root:e,note:r,pill:i,filters:t,list:o}}var He=e=>!g.policyFilter||ve(e,g.policyFilter);function Ue(){let e=new URL(location.href);g.journalFilter===`attention`?e.searchParams.delete(`jf`):e.searchParams.set(`jf`,g.journalFilter),history.replaceState(null,``,e)}function We(e,t){let n=g.policyFilter;if(!n){s(e);return}let r=t.filter(He).length,i=g.journals.filter(He).length;s(e,a(`span`,{class:`filter-pill`,role:`status`},a(`span`,null,`Policy: `,a(`strong`,null,n)),a(`span`,{class:`muted`},`· ${r} here`),r===0&&i>0&&g.journalFilter!==`all`?a(`button`,{type:`button`,class:`link-btn`,onclick:()=>{g.journalFilter=`all`,Ue(),x()}},`${i} in All`):null,a(`button`,{type:`button`,class:`filter-clear`,title:`Clear the filter (Esc)`,"aria-label":`Clear the policy filter`,onclick:()=>De(null)},`✕`)))}function Ge(e){let t=de(e),n=ue(e.file),r=pe(e),i=e.status===`open`||e.status===`stale`;return a(`article`,{class:`jrow${g.policyFilter?He(e)?` is-match`:` is-dim`:``}`,tabindex:`0`,"data-status":e.status,"aria-label":`${e.title}, ${e.status}`,onclick:()=>void Y(e.file),onkeydown:t=>{t.target===t.currentTarget&&t.key===`Enter`&&Y(e.file)}},a(`span`,{class:`led`,"data-led":Be[e.status],"aria-hidden":`true`}),a(`div`,{class:`jrow-main`},a(`div`,{class:`jrow-top`},a(`time`,{class:`mono muted`,datetime:e.date},e.date),a(`h3`,null,e.title),a(`span`,{class:`status-tag`,"data-status":e.status},e.status)),e.objective?a(`p`,{class:`jrow-obj`},e.objective):null,i&&e.nextActions[0]?a(`p`,{class:`jrow-next`},a(`span`,{class:`mono`},`next → `),e.nextActions[0]):null,!i&&e.conclusion?a(`p`,{class:`jrow-next`},a(`span`,{class:`mono`},`concluded → `),e.conclusion):null,a(`div`,{class:`jrow-meta`},a(`span`,{class:`muted small`},`touched ${c(e.modified)}`),i&&e.nextActions.length?a(`span`,{class:`muted small`},`${e.nextActions.length} next`):null,i&&e.openQuestions?a(`span`,{class:`muted small`},`${e.openQuestions} open questions`):null,t.slice(0,4).map(e=>k(e.number,e)),Fe(e),n.map(e=>a(`button`,{type:`button`,class:`chip chip-card`,title:`Open the board card`,onclick:t=>{t.stopPropagation(),J(e)}},e.title))),e.editedAfterClose&&i?a(`div`,{class:`hint hint-amber hint-row`},`Reopened: edited after you closed it on ${u(e.override?.at)}.`,a(`button`,{type:`button`,class:`pill pill-quiet`,onclick:t=>{t.stopPropagation(),O(e.file,!0)}},`Close again`)):r?a(`div`,{class:`hint hint-row`},`Its PRs are merged but the journal has no Final Conclusions.`,a(`button`,{type:`button`,class:`pill pill-quiet`,onclick:t=>{t.stopPropagation(),O(e.file,!0)}},`Mark closed`)):null))}function Ke(e){(!M||M.root!==e)&&Ve(e);let{note:t,pill:n,filters:r,list:i}=M,o=g.journals,c=j.find(e=>e.id===g.journalFilter)??j[0],l=g.journalQuery.trim().toLowerCase(),u=o.filter(e=>c.test(e)&&(!l||`${e.file} ${e.title} ${e.objective}`.toLowerCase().includes(l)));if(t.textContent=`${C()} — open = touched in the last 7 days`,We(n,u),s(r,j.map(e=>a(`button`,{type:`button`,role:`tab`,class:`filter`,"aria-selected":String(g.journalFilter===e.id),onclick:()=>{g.journalFilter=e.id,Ue(),x()}},e.label,a(`span`,{class:`count`},String(o.filter(e.test).length))))),g.journalsError){s(i,a(`div`,{class:`banner banner-error`,role:`alert`},g.journalsError));return}if(!g.journalsLoaded){s(i,a(`p`,{class:`muted`},`Reading ${C()}…`));return}if(!o.length){s(i,a(`p`,{class:`muted empty`},`No journals in ${C()} yet. Agents write one per investigation (research policy); they show up here as they are saved.`));return}let d=!g.showAllJournals&&u.length>A;s(i,u.length?(d?u.slice(0,A):u).map(Ge):a(`p`,{class:`muted empty`},`No journals match.`),u.length>A?a(`button`,{type:`button`,class:`pill pill-quiet list-more`,onclick:()=>{g.showAllJournals=!g.showAllJournals,x()}},d?`Show all ${u.length}`:`Show fewer`):null)}var N=e=>e.replace(/[&<>"']/g,e=>({"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`})[e]);function P(e){return e.split(/(`[^`]+`)/g).map(e=>e.length>1&&e.startsWith("`")&&e.endsWith("`")?`<code>${N(e.slice(1,-1))}</code>`:N(e).replace(/\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g,`<a href="$2" target="_blank" rel="noreferrer">$1</a>`).replace(/\[([^\]]+)\]\(([^)\s]+)\)/g,`<span class="md-ref" title="$2">$1</span>`).replace(/\*\*([^*]+)\*\*/g,`<strong>$1</strong>`).replace(/~~([^~]+)~~/g,`<del>$1</del>`)).join(``)}var qe=e=>e.trim().replace(/^\||\|$/g,``).split(`|`).map(e=>e.trim());function Je(e){let t=e.split(/\r?\n/),n=[],r=[],i=[],a=null,o=()=>{r.length&&n.push(`<p>${P(r.join(` `))}</p>`),i.length&&n.push(`<blockquote>${i.map(P).join(`<br>`)}</blockquote>`),a&&n.push(`<div class="md-li" style="--depth:${a.depth}"><span class="md-mark">${a.mark}</span><span>${P(a.body)}</span></div>`),r=[],i=[],a=null};for(let e=0;e<t.length;e++){let s=t[e];if(a&&/^\s{2,}\S/.test(s)&&!/^\s*([-*+]|\d+[.)])\s/.test(s)){a.body+=` ${s.trim()}`;continue}if(/^\s*```/.test(s)){o();let r=[];for(;++e<t.length&&!/^\s*```/.test(t[e]);)r.push(t[e]);n.push(`<pre><code>${N(r.join(`
2
+ `))}</code></pre>`);continue}let c=/^(#{1,6})\s+(.*)$/.exec(s);if(c){o();let e=Math.min(c[1].length+1,6);n.push(`<h${e}>${P(c[2])}</h${e}>`);continue}if(/^\s*\|.*\|\s*$/.test(s)){o();let r=[];for(;e<t.length&&/^\s*\|.*\|\s*$/.test(t[e]);e++)r.push(t[e]);e--;let[i,...a]=r.filter(e=>!/^\s*\|?[\s:|-]+\|?\s*$/.test(e));if(!i)continue;n.push(`<div class="md-table"><table><thead><tr>${qe(i).map(e=>`<th>${P(e)}</th>`).join(``)}</tr></thead><tbody>${a.map(e=>`<tr>${qe(e).map(e=>`<td>${P(e)}</td>`).join(``)}</tr>`).join(``)}</tbody></table></div>`);continue}let l=/^(\s*)([-*+]|\d+[.)])\s+(.*)$/.exec(s);if(l){o();let e=l[3],t=/\d/.test(l[2])?N(l[2]):`•`,n=/^\[([ xX])\]\s*/.exec(e);n&&(t=n[1]===` `?`☐`:`☑`,e=e.slice(n[0].length)),a={depth:Math.floor(l[1].replace(/\t/g,` `).length/2),mark:t,body:e}}else/^>/.test(s)?(i.length||o(),i.push(s.replace(/^>\s?/,``))):/^\s*(---|\*\*\*|___)\s*$/.test(s)?(o(),n.push(`<hr>`)):s.trim()?((a||i.length)&&o(),r.push(s.trim())):o()}return o(),n.join(`
3
+ `)}var Ye={journals:`Journals`,github:`GitHub`},Xe=1200,F=[],I=null,Ze,L,Qe=null,R=window.matchMedia(`(min-width: ${Xe}px)`),z={journals:a(`div`,{class:`panel-body`}),github:a(`div`,{class:`panel-body`})},B=()=>F[F.length-1],V=e=>e?.kind===`journals`||e?.kind===`github`,$e=()=>I?.classList.contains(`open`)&&V(F[0])?F[0].kind:null;function et(){I||(Ze=a(`header`,{class:`drawer-head`}),L=a(`div`,{class:`drawer-body`}),I=a(`aside`,{id:`drawer`,class:`drawer`,"aria-hidden":`true`,"aria-label":`Details`},Ze,L),document.body.append(I),document.addEventListener(`keydown`,e=>{e.key===`Escape`&&I?.classList.contains(`open`)&&(e.preventDefault(),G())}),R.addEventListener(`change`,()=>{H(),I?.classList.contains(`open`)&&it()}))}function H(){let e=!!I?.classList.contains(`open`)&&g.drawerMode===`push`&&R.matches;document.body.classList.toggle(`drawer-push`,e),I?.setAttribute(`data-mode`,e?`push`:`overlay`)}function tt(){let e=R.matches?g.drawerMode:`overlay`,t=(t,n,r)=>a(`button`,{type:`button`,class:`seg`,"aria-pressed":String(e===t),disabled:!R.matches,title:R.matches?r:`Push needs a wider window; the drawer overlays here`,onclick:()=>{g.drawerMode=t,v(`drawer-mode`,t),H(),it()}},n);return a(`span`,{class:`segmented`,role:`group`,"aria-label":`Drawer placement`},t(`push`,`Push`,`Narrow the board beside the drawer; nothing is covered`),t(`overlay`,`Overlay`,`Cover the board’s right edge; the board keeps its width`))}function nt(e){switch(e.kind){case`journals`:case`github`:return Ye[e.kind];case`journal`:return a(`span`,{class:`mono`},e.file);case`card`:return e.card?`Edit card`:`New card`}}function rt(e){return V(e)?Ye[e.kind]:e.kind===`journal`?`Journal`:`Card`}function it(){let e=F[F.length-2];s(Ze,e?a(`button`,{type:`button`,class:`pill pill-quiet drawer-back`,title:`Back (Esc)`,onclick:G},`← ${rt(e)}`):null,a(`div`,{class:`drawer-title`},nt(B())),tt(),a(`button`,{type:`button`,class:`icon-btn`,"aria-label":`Close`,title:`Close`,onclick:K},`×`)),I.setAttribute(`aria-label`,typeof nt(B())==`string`?nt(B()):`Journal`)}function at(){let e=new URL(location.href),t=$e();t?e.searchParams.set(`panel`,t):e.searchParams.delete(`panel`),t===`journals`&&g.journalFilter!==`attention`?e.searchParams.set(`jf`,g.journalFilter):e.searchParams.delete(`jf`),history.replaceState(null,``,e)}function U(){et(),I.classList.contains(`open`)||(Qe=document.activeElement),I.classList.add(`open`),I.setAttribute(`aria-hidden`,`false`);let e=B();switch(it(),e.kind){case`journals`:Ke(z.journals),s(L,z.journals);break;case`github`:ze(z.github),s(L,z.github);break;case`journal`:ft(e.file);break;case`card`:dt(e.card,e.column)}V(e)||(L.scrollTop=0),H(),at(),x()}function ot(e){$e()===e&&F.length===1?K():W(e)}function W(e){F.length=0,F.push({kind:e}),U()}function G(){F.pop(),F.length?U():K()}function K(){F.length=0,I&&(I.classList.remove(`open`),I.setAttribute(`aria-hidden`,`true`),H(),at(),Qe?.focus?.(),x())}function st(){let e=B();I?.classList.contains(`open`)&&V(e)&&(e.kind===`journals`?Ke(z.journals):ze(z.github))}function ct(e){let t=[];for(let n of e.split(/[\s,]+/)){let e=/^#?(\d+)\s*[-–]\s*#?(\d+)$/.exec(n);if(e){let[n,r]=[Number(e[1]),Number(e[2])];for(let e=Math.min(n,r);e<=Math.max(n,r)&&t.length<500;e++)t.push(e)}else{let e=Number(n.replace(/^#/,``));Number.isInteger(e)&&e>0&&t.push(e)}}return[...new Set(t)]}function lt(e=[]){let t=[...e].sort((e,t)=>e-t),n=[];for(let e=0;e<t.length;e++){let r=e;for(;r+1<t.length&&t[r+1]===t[r]+1;)r++;n.push(r-e>=2?`${t[e]}-${t[r]}`:t.slice(e,r+1).join(`, `)),e=r}return n.join(`, `)}var ut=e=>e.split(/[\n,]+/).map(e=>e.trim()).filter(Boolean);function q(e,t,n){return a(`label`,{class:`field`},a(`span`,{class:`field-label`},e),t,n?a(`span`,{class:`field-hint`},n):null)}function J(e,t){g.board&&(B()?.kind===`card`&&I?.classList.contains(`open`)&&F.pop(),F.push({kind:`card`,card:e,column:t}),U())}function dt(e,t){let n=g.board;if(!n)return;let r=e?.links??{},i=je(),o=Object.keys(i),c=a(`input`,{name:`title`,required:!0,value:e?.title??``,placeholder:`What needs doing?`}),l=a(`select`,{name:`column`},n.columns.map(r=>a(`option`,{value:r.id,selected:r.id===(e?.column??t??n.columns[0].id)},r.title))),u=a(`input`,{name:`area`,value:(e?.area??[]).join(` `),placeholder:o.slice(0,2).join(` `)||`api ui`}),d=a(`textarea`,{name:`notes`,rows:`5`,value:e?.notes??``}),f=a(`textarea`,{name:`journals`,rows:`2`,value:(r.journals??[]).join(`
4
+ `),placeholder:`2026-10-07-search-index.md`}),p=a(`select`,{class:`pick`,"aria-label":`Link a journal`,onchange:()=>{if(!p.value)return;let e=ut(f.value);e.includes(p.value)||(f.value=[...e,p.value].join(`
5
+ `)),p.value=``}},a(`option`,{value:``},`Link a recent journal…`),g.journals.slice(0,60).map(e=>a(`option`,{value:e.file},`${e.date} ${e.title}`))),ee=a(`input`,{name:`prs`,value:lt(r.prs),placeholder:`108, 76-83`}),te=a(`input`,{name:`issues`,value:lt(r.issues),placeholder:`12`}),m=a(`input`,{name:`docs`,value:(r.docs??[]).join(`, `),placeholder:`docs/adrs/012-storage.md`}),h=a(`p`,{class:`field-error`,role:`alert`}),_=async()=>{let t=Ne(u.value),n={journals:ut(f.value),prs:ct(ee.value),issues:ct(te.value),docs:ut(m.value)};for(let[e,t]of Object.entries(n))t.length||delete n[e];let r={...e,title:c.value.trim(),column:l.value,area:t.length?t:null,notes:d.value.trim()||null,links:Object.keys(n).length?n:null};try{await Se(r),G(),T(e?`Card saved`:`Card added`)}catch(e){h.textContent=e instanceof Error?e.message:String(e)}},v=!1,y=e?a(`button`,{type:`button`,class:`pill pill-danger`,onclick:async()=>{if(!v)v=!0,y.textContent=`Click again to delete`;else try{await Ce(e.id),G(),T(`Card deleted`)}catch(e){h.textContent=e instanceof Error?e.message:String(e)}}},`Delete`):null,b=a(`form`,{class:`editor`,onsubmit:e=>{e.preventDefault(),_()},onkeydown:e=>{e.key===`Enter`&&(e.ctrlKey||e.metaKey)&&(e.preventDefault(),_())}},q(`Title`,c),a(`div`,{class:`field-row`},q(`Column`,l),q(`Areas`,u,o.length?Object.entries(i).map(([e,t])=>`${e} ${t.split(`:`)[0]}`).join(` · `):`No areas yet: add them under "areas" in ${g.meta?.boardFile??`the board file`}`)),q(`Notes`,d),q(`Journals`,a(`div`,{class:`stack`},f,p),`One filename per line, from ${C()}`),a(`div`,{class:`field-row`},q(`PRs`,ee,`Ranges work: 76-83`),q(`Issues`,te)),q(`Docs`,m,`Repo-relative paths, comma-separated`),h,a(`div`,{class:`editor-actions`},a(`button`,{type:`submit`,class:`pill pill-primary`},e?`Save`:`Add card`),a(`button`,{type:`button`,class:`pill`,onclick:G},`Cancel`),a(`span`,{class:`spacer`}),y),e?.updated?a(`p`,{class:`muted small`},`Created ${e.created??`—`} · updated ${e.updated} · id ${e.id}`):null);s(L,b),c.focus()}function Y(e){B()?.kind===`journal`&&I?.classList.contains(`open`)&&F.pop(),F.push({kind:`journal`,file:e}),U()}async function ft(e){let t=le(e);s(L,a(`p`,{class:`muted`},`Loading…`));let n;try{n=(await i.journal(e)).text}catch(e){s(L,a(`div`,{class:`banner banner-error`},e instanceof Error?e.message:String(e)));return}let r=B();if(r?.kind!==`journal`||r.file!==e)return;let o=ue(e),l=t?de(t):[],d=t&&(t.status===`open`||t.status===`stale`),f=a(`div`,{class:`md`});f.innerHTML=Je(n),s(L,a(`div`,{class:`jmeta`},t?a(`span`,{class:`status-tag`,"data-status":t.status},t.status):null,t?a(`span`,{class:`muted`},`started ${t.date} · touched ${c(t.modified)}`):null,a(`span`,{class:`jmeta-actions`},a(`button`,{type:`button`,class:`pill pill-quiet`,onclick:()=>{navigator.clipboard?.writeText(`${C()}${e}`).then(()=>T(`Path copied`))}},`Copy path`),d?a(`button`,{type:`button`,class:`pill`,onclick:async()=>{await O(e,!0),U()}},`Mark closed`):null,t?.status===`closed`?a(`button`,{type:`button`,class:`pill`,onclick:async()=>{await O(e,!1),U()}},`Reopen`):null)),t?.editedAfterClose?a(`p`,{class:`hint hint-amber`},`Reopened: edited after you closed it on ${u(t.override?.at)}.`):null,l.length?a(`div`,{class:`card-links`},l.slice(0,8).map(e=>k(e.number,e))):null,t?Fe(t):null,o.length?a(`div`,{class:`jmeta-cards`},a(`span`,{class:`muted small`},`On the board:`),o.map(e=>a(`button`,{type:`button`,class:`chip chip-card`,onclick:()=>J(e)},e.title))):null,f)}var pt=8,mt=15,ht=3,gt=e=>{let t=e.replace(/\.md$/,``).replace(/^\d{4}-\d{2}-\d{2}-/,``);return t.length>26?`${t.slice(0,25)}…`:t};function _t(e){let t=e.links??{},n=[];for(let e of t.journals??[]){let t=le(e);n.push(a(`button`,{type:`button`,class:`chip chip-journal`,"data-status":g.journalsLoaded?t?.status??`missing`:`loading`,title:t?`${t.title} — ${t.status}`:`${e} — not in ${C()}`,onclick:t=>{t.stopPropagation(),Y(e)}},a(`span`,{class:`dot`,"aria-hidden":`true`}),gt(e)))}let r=t.prs??[];if(r.length>3&&!g.repo)n.push(a(`span`,{class:`chip chip-gh`,"data-state":`UNKNOWN`,title:`GitHub data still loading`},a(`span`,{class:`mono`},`${r.length} PRs`)));else if(r.length>3){let e=r.filter(e=>S(e)?.state===`MERGED`).length,t=r.some(e=>S(e)?.state===`OPEN`);n.push(a(`span`,{class:`chip chip-gh`,"data-state":t?`OPEN`:e===r.length?`MERGED`:`MIXED`,title:r.map(e=>`#${e} ${S(e)?.state.toLowerCase()??`?`} ${S(e)?.title??``}`).join(`
6
+ `)},a(`span`,{class:`mono`},`${r.length} PRs`),` ${e}/${r.length} merged`))}else for(let e of r)n.push(k(e,S(e)));for(let e of t.issues??[])n.push(k(e,ce(e),`issue`));for(let e of t.docs??[])n.push(a(`span`,{class:`chip chip-quiet`,title:e},e.split(`/`).pop()??e));if(!n.length)return null;let i=n.length>4?n.slice(0,ht):n,o=n.slice(i.length);return a(`div`,{class:`card-links`},i,o.length?a(`span`,{class:`chip chip-more`,title:o.map(e=>e.getAttribute(`title`)??e.textContent).join(`
7
+ `)},`+${o.length}`):null)}var X=null,vt=()=>X??=a(`div`,{class:`drop-line`,"aria-hidden":`true`});function yt(e,t){let n=[...e.querySelectorAll(`.card:not(.dragging)`)];for(let e=0;e<n.length;e++){let r=n[e].getBoundingClientRect();if(t<r.top+r.height/2)return{index:e,before:n[e]}}return{index:n.length,before:null}}function bt(e,t){e.addEventListener(`dragover`,t=>{if(!g.dragging)return;t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect=`move`),e.classList.add(`drop-target`);let{before:n}=yt(e,t.clientY),r=vt();n?r.nextSibling!==n&&e.insertBefore(r,n):e.lastElementChild!==r&&e.append(r)}),e.addEventListener(`dragleave`,t=>{e.contains(t.relatedTarget)||(e.classList.remove(`drop-target`),X?.parentElement===e&&X.remove())}),e.addEventListener(`drop`,n=>{n.preventDefault();let r=g.dragging??n.dataTransfer?.getData(`text/plain`),{index:i}=yt(e,n.clientY);e.classList.remove(`drop-target`),X?.remove(),g.dragging=null,r&&xe(r,t,i)})}async function xt(e,t){let n=g.board;if(!n)return;let r=n.columns.map(e=>e.id),i=n.cards.filter(t=>t.column===e.column),a=i.indexOf(e),o=null;if(t.key===`ArrowLeft`||t.key===`ArrowRight`){let n=r[r.indexOf(e.column)+(t.key===`ArrowLeft`?-1:1)];n&&(o=[n,0])}else t.key===`ArrowUp`&&a>0?o=[e.column,a-1]:t.key===`ArrowDown`&&a<i.length-1&&(o=[e.column,a+1]);o&&(t.preventDefault(),await xe(e.id,...o),document.querySelector(`.card[data-id="${CSS.escape(e.id)}"]`)?.focus())}var St=e=>!g.areaFilter||!!e.area?.includes(g.areaFilter);function Ct(e){let t=g.areaFilter===e,n=Me(e);return a(`button`,{type:`button`,class:`area`,"aria-pressed":String(t),title:t?`${n}. Click to clear the filter.`:`${n}. Click to filter the board to ${e}.`,onclick:t=>{t.stopPropagation(),Ee(e)}},e)}function wt(e,t){let n=[t?a(`p`,{class:`card-fulltitle`},e.title):null,e.notes?a(`p`,{class:`card-notes`},e.notes):null,_t(e),me(e)?a(`p`,{class:`hint`},`Every linked PR is merged. Move to Done?`):null].filter(e=>e!==null);return n.length?a(`div`,{class:`card-more`},a(`div`,{class:`card-more-inner`},a(`div`,{class:`card-more-body`},n))):null}var Tt=!1;function Et(e){Tt||(Tt=!0,new ResizeObserver(()=>Et(e)).observe(e)),requestAnimationFrame(()=>{for(let t of e.querySelectorAll(`.card.is-strip`)){let e=t.querySelector(`.card-title`);e&&t.classList.toggle(`is-truncated`,e.scrollWidth>e.clientWidth+1)}})}function Dt(e,t){let n=!!g.areaFilter,r=a(`article`,{class:`card${t?` is-strip`:``}${n?St(e)?` is-match`:` is-dim`:``}`,tabindex:`0`,draggable:`true`,"data-id":e.id,"aria-label":`${e.title}. Enter to open, Alt+arrows to move.`,onclick:()=>J(e),onkeydown:t=>{t.target===t.currentTarget&&(t.altKey?xt(e,t):t.key===`Enter`&&J(e))}},e.area?.length?a(`div`,{class:`card-areas`},e.area.map(Ct)):null,a(`h3`,{class:`card-title`},e.title),wt(e,t));return r.addEventListener(`dragstart`,t=>{g.dragging=e.id,t.dataTransfer?.setData(`text/plain`,e.id),t.dataTransfer&&(t.dataTransfer.effectAllowed=`move`),requestAnimationFrame(()=>r.classList.add(`dragging`))}),r.addEventListener(`dragend`,()=>{r.classList.remove(`dragging`),X?.remove(),document.querySelectorAll(`.drop-target`).forEach(e=>e.classList.remove(`drop-target`)),g.dragging=null,re()}),r}function Ot(e){let t=g.board.cards.filter(t=>t.column===e.id),r=g.areaFilter,i=r?t.filter(St).length:t.length,o=n(g.board,e.id)===`done`,s=he(e.id),c=s?mt:pt,l=o&&t.length>c&&!g.showAllDone&&!r?t.slice(0,c):t,u=a(`div`,{class:`col-body${s?` is-stacked`:``}`,"data-column":e.id},l.map(e=>Dt(e,s)),t.length===0?a(`p`,{class:`col-empty`},`Nothing here`):null);return bt(u,e.id),a(`section`,{class:`col`,style:`--led: var(--led-${Pe(e.led)})`,"aria-label":e.title},a(`header`,{class:`col-head`},a(`span`,{class:`led`,"data-led":e.led,"aria-hidden":`true`}),a(`h2`,null,e.title),r?a(`span`,{class:`count${i?` count-match`:``}`,title:`${i} of ${t.length} cards in ${e.title} are ${r}`},`${i} / ${t.length}`):a(`span`,{class:`count`},String(t.length)),a(`button`,{type:`button`,class:`icon-btn stack-toggle`,"aria-pressed":String(s),title:s?`Deal out ${e.title}: show whole cards`:`Stack ${e.title}: title strips that open on hover or focus`,"aria-label":s?`Deal out ${e.title}`:`Stack ${e.title}`,onclick:()=>_e(e.id,!s)},a(`span`,{class:`stack-icon`,"aria-hidden":`true`},a(`i`),a(`i`),a(`i`))),a(`button`,{type:`button`,class:`icon-btn`,title:`Add a card to ${e.title}`,"aria-label":`Add a card to ${e.title}`,onclick:()=>J(null,e.id)},`+`)),e.hint?a(`p`,{class:`col-hint`},e.hint):null,u,o&&t.length>c&&!r?a(`button`,{type:`button`,class:`pill pill-quiet col-more`,onclick:()=>{g.showAllDone=!g.showAllDone,x()}},g.showAllDone?`Show fewer`:`Show all ${t.length}`):null)}function kt(e){let t=g.areaFilter;if(!t||!g.board){s(e);return}let n=g.board.cards.filter(St).length,r=Me(t).split(`:`)[0];s(e,a(`span`,{class:`filter-pill`,role:`status`},a(`span`,{class:`area area-static`,"aria-hidden":`true`},t),a(`span`,null,`Filtering: `,a(`strong`,null,r)),a(`span`,{class:`muted`},`· ${n} card${n===1?``:`s`}`),a(`button`,{type:`button`,class:`filter-clear`,title:`Clear the filter (Esc)`,"aria-label":`Clear the filter`,onclick:()=>Te(null)},`✕`)))}function At(){return a(`section`,{class:`welcome panel`,"aria-label":`Getting started`},a(`h2`,null,`This board is empty`),a(`ul`,null,a(`li`,null,a(`strong`,null,`Tracked work: `),`the Inbox above lists open PRs, open issues and active journals. `,a(`em`,null,`Make card`),` turns each into a card. Journals and GitHub open from the bar at the top.`),a(`li`,null,a(`strong`,null,`Everything else: `),`ask your agent to bootstrap the board. It reads the repository, proposes areas and cards, and writes the ones you approve.`),a(`li`,null,a(`strong`,null,`By hand: `),a(`em`,null,`New card`),`, or the + on any column.`)))}function jt(){let e=g.meta;return!e||e.boardIgnored!==!1?null:a(`p`,{class:`hint hint-amber banner-note`,role:`note`},`git would show ${e.boardFile} as untracked. To keep the board private, add `,a(`code`,null,`/.lore/`),` to `,a(`code`,null,`.git/info/exclude`),`.`)}function Mt(e){let t=g.boardError?a(`div`,{class:`banner banner-error`,role:`alert`},g.boardError):null;g.board?(s(e,t,jt(),g.board.cards.length===0?At():null,a(`div`,{class:`board`},g.board.columns.map(Ot))),Et(e)):s(e,t??a(`p`,{class:`muted`},`Loading board…`))}var Nt={pr:`PR`,journal:`Journal`,issue:`Issue`},Pt=6,Z=!1;function Ft(e){let t=g.board?.columns.find(t=>t.id===e.suggest.column)?.title??e.suggest.column,n=e.kind===`journal`?e.suggest.title:e.title,r=e.url?a(`a`,{class:`inbox-title`,href:e.url,target:`_blank`,rel:`noreferrer`,title:e.title},n):a(`button`,{type:`button`,class:`inbox-title`,title:`Read the journal`,onclick:()=>e.file&&void Y(e.file)},n);return a(`div`,{class:`inbox-row`,"data-kind":e.kind},a(`span`,{class:`inbox-kind`},Nt[e.kind]),a(`span`,{class:`mono muted inbox-label`},e.label),r,a(`span`,{class:`muted small inbox-when`},c(e.when)),a(`span`,{class:`inbox-actions`},a(`button`,{type:`button`,class:`pill pill-primary`,title:`Create a card in ${t}, linked to this ${Nt[e.kind].toLowerCase()}`,onclick:()=>void ke(e)},`Make card → ${t}`),a(`button`,{type:`button`,class:`pill pill-quiet`,title:`Not board-worthy: hide it from the Inbox (restorable)`,onclick:()=>void Ae(e.key,!0)},`Dismiss`)))}function It(e){if(!g.board||!g.journalsLoaded){s(e);return}let t=fe(),n=g.board.inboxDismissed?.length??0,r=n>0?a(`button`,{type:`button`,class:`link-btn`,title:`Bring every dismissed item back into the Inbox`,onclick:()=>void Ae(`*`,!1)},`restore ${n} dismissed`):null;if(!t.length){s(e,a(`div`,{class:`inbox inbox-clear`},a(`span`,{class:`led`,"data-led":`green`,"aria-hidden":`true`}),a(`span`,{class:`inbox-heading`},`Inbox`),a(`span`,{class:`muted small`},g.repo?`Everything active is on the board.`:`Everything active is on the board (GitHub still loading).`),r));return}let i=Z?t:t.slice(0,Pt);s(e,a(`section`,{class:`inbox`,"aria-label":`Inbox: work not on the board yet`},a(`header`,{class:`inbox-head`},a(`span`,{class:`led`,"data-led":`amber`,"aria-hidden":`true`}),a(`span`,{class:`inbox-heading`},`Inbox`),a(`span`,{class:`count`},String(t.length)),a(`span`,{class:`muted small`},`Open PRs, active journals and open issues that no card links to yet.`),a(`span`,{class:`spacer`}),r),i.map(Ft),t.length>Pt?a(`button`,{type:`button`,class:`link-btn inbox-more`,onclick:()=>{Z=!Z,It(e)}},Z?`Show fewer`:`Show all ${t.length}`):null))}var Lt=12e4,Rt=[`attention`,`open`,`stale`,`concluded`,`closed`,`all`],zt=a(`div`,{class:`status`}),Bt=a(`nav`,{class:`nav`,"aria-label":`Sections`}),Vt=a(`button`,{type:`button`,class:`icon-btn icon-btn-ring`,title:`Refresh: re-read the board and journals, ask GitHub again`,"aria-label":`Refresh`,onclick:()=>void Promise.all([ye(),be(),E(),D(!0)])},`↻`),Ht=a(`span`,{class:`brand-name`},`…`),Ut=a(`header`,{class:`topbar`},a(`div`,{class:`brand`},a(`span`,{class:`brand-mark`,"aria-hidden":`true`},a(`i`),a(`i`),a(`i`)),Ht,a(`span`,{class:`brand-sub`},`LORE HUD`)),Bt,zt,Vt),Wt=a(`div`,{id:`inbox`}),Gt=a(`span`,{class:`filter-slot`}),Kt=a(`div`,{id:`board`});s(document.getElementById(`app`),Ut,a(`main`,null,a(`section`,{id:`board-section`,"aria-label":`Board`},a(`div`,{class:`section-head`},a(`h1`,null,`Board`),Gt,a(`p`,{class:`muted small`},`Drag cards between columns. Alt+arrow keys move a focused card. Click an area chip to filter by area.`),a(`span`,{class:`spacer`}),a(`button`,{type:`button`,class:`pill pill-primary`,onclick:()=>{let e=g.board,n=e?t(e,`intake`):void 0,r=e&&n?e.columns.indexOf(n)+1:0;J(null,e?.columns[r]?.id??e?.columns[0]?.id)}},`New card`)),Wt,Kt))),new ResizeObserver(()=>{document.documentElement.style.setProperty(`--topbar-h`,`${Ut.offsetHeight}px`)}).observe(Ut);function qt(e){g.journalFilter=e,W(`journals`)}function Jt(e,t,n){return e>0?a(`span`,{class:`nav-badge`,title:n},t?a(`span`,{class:`led`,"data-led":t,"aria-hidden":`true`}):null,String(e)):null}function Yt(){let e=$e(),t=g.journals.filter(e=>e.status===`open`).length,n=g.journals.filter(e=>e.status===`stale`).length,r=g.repo?.prs.filter(e=>e.state===`OPEN`).length??0,i=(t,n,...r)=>a(`button`,{type:`button`,class:`nav-link`,"data-panel":t,"aria-expanded":String(e===t),"aria-controls":`drawer`,title:e===t?`Close ${n}`:`Open ${n}`,onclick:()=>ot(t)},n,r);s(Bt,a(`button`,{type:`button`,class:`nav-link`,title:`Back to the board`,onclick:()=>{K(),window.scrollTo({top:0})}},`Board`),i(`journals`,`Journals`,Jt(t,`pulse`,`${t} open`),Jt(n,`amber`,`${n} stale`)),i(`github`,`GitHub`,Jt(r,void 0,`${r} open PRs`)))}function Q(e,t,n,r,i){return a(i?`button`:`span`,{class:`stat${i?` stat-btn`:``}`,type:i?`button`:void 0,title:r,onclick:i},n?a(`span`,{class:`led`,"data-led":n,"aria-hidden":`true`}):null,a(`span`,{class:`stat-value`},String(t)),a(`span`,{class:`stat-label`},e))}var Xt=[`active`,`review`,`blocked`];function Zt(){let e=g.board,n=g.journals,r=g.repo,i=r?.git,o=new Date(Date.now()-6048e5).toISOString(),l=r?.prs.filter(e=>(d(e.mergedAt)??``)>=o).length??0;Ht.textContent=g.meta?.repo??`…`,s(zt,e?Xt.map(n=>t(e,n)).filter(e=>e!==void 0).map(t=>Q(t.title.toLowerCase(),e.cards.filter(e=>e.column===t.id).length,t.led)):null,a(`span`,{class:`sep`,"aria-hidden":`true`}),Q(`journals open`,n.filter(e=>e.status===`open`).length,`pulse`,`Show the open journals`,()=>qt(`open`)),Q(`stale`,n.filter(e=>e.status===`stale`).length,`amber`,`Journals not concluded and untouched for over 7 days — show them`,()=>qt(`stale`)),a(`span`,{class:`sep`,"aria-hidden":`true`}),r?Q(`open PRs`,r.prs.filter(e=>e.state===`OPEN`).length,void 0,`Show GitHub`,()=>W(`github`)):null,r?Q(`merged in 7d`,l,`green`,`Show GitHub`,()=>W(`github`)):null,i?a(`span`,{class:`chip chip-git`,title:i.subject},a(`span`,{class:`mono`},`${i.branch} @ ${i.head}`),i.dirty?a(`span`,{class:`dirty`},` · ${i.dirty} changed`):` · clean`):null,r?.release?a(`a`,{class:`chip chip-release`,href:r.release.url,target:`_blank`,rel:`noreferrer`},a(`span`,{class:`mono`},r.release.tag),` · ${c(r.release.publishedAt)}`):null),Vt.toggleAttribute(`data-busy`,g.repoLoading)}ne(()=>{Yt(),Zt(),It(Wt),kt(Gt),Mt(Kt),st()});var $=new URLSearchParams(location.search);g.areaFilter=$.get(`area`),g.policyFilter=$.get(`policy`);var Qt=$.get(`jf`);Qt&&Rt.includes(Qt)&&(g.journalFilter=Qt),document.addEventListener(`keydown`,e=>{e.key!==`Escape`||document.querySelector(`.drawer.open`)||(g.areaFilter?Te(null):g.policyFilter&&De(null))}),ye(),be(),E(),D();var $t=$.get(`panel`);($t===`journals`||$t===`github`)&&W($t);var en=new EventSource(`/api/events`);en.addEventListener(`board`,()=>{be(),E()}),en.addEventListener(`journals`,()=>void E()),setInterval(()=>void D(),Lt),document.addEventListener(`visibilitychange`,()=>{document.visibilityState===`visible`&&D()});