moflo 4.10.9 → 4.10.10

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.
@@ -0,0 +1,66 @@
1
+ ---
2
+ name: luminarium
3
+ description: |
4
+ Print the localhost URL for The Luminarium — moflo's daemon dashboard — for the current project.
5
+ Use when the user asks for "the luminarium link", "the moflo dashboard", "the daemon UI", or anything synonymous.
6
+ Each project gets a deterministic port in 33000–33999; the actual bound port is recorded in `.moflo/daemon.lock`.
7
+ ---
8
+
9
+ # /luminarium — Project Dashboard Link
10
+
11
+ Surface the URL for The Luminarium (the moflo daemon's localhost UI) for the project that this session is running in. No prompts, no confirmations — print the link and stop.
12
+
13
+ ## Procedure
14
+
15
+ 1. **Find the project root.** Walk up from `process.cwd()` looking for a `.moflo/` directory. The session's cwd is almost always the project root, so check there first.
16
+
17
+ 2. **Read `.moflo/daemon.lock`.** It's a JSON file written by the daemon at bind time. The dashboard port is the `port` field:
18
+
19
+ ```json
20
+ { "pid": 12345, "port": 33421, "startedAt": "...", ... }
21
+ ```
22
+
23
+ - If the file exists and `port` is a valid number → the daemon is running and bound. Use that port.
24
+ - If the file is missing or `port` is absent/invalid → the daemon is not running. See step 4.
25
+
26
+ 3. **Print the link** in a single line, with the path verbatim — Claude Code renders it as clickable:
27
+
28
+ ```
29
+ The Luminarium: http://localhost:<port>
30
+ ```
31
+
32
+ Nothing else. No banner, no follow-up question, no "what would you like to do?".
33
+
34
+ 4. **If the daemon isn't running** (no lock file, or unparseable), say so in one line and offer the start command — don't run it:
35
+
36
+ ```
37
+ The moflo daemon isn't running for this project. Start it with: npx flo daemon start
38
+ ```
39
+
40
+ ## Why read the lock, not compute the port
41
+
42
+ The port is project-deterministic (sha256(projectRoot) mapped into 33000–33999), but if the deterministic port was already taken at bind time the daemon scans forward and binds an alternate. The lock file is the only source of truth for what's actually bound. Do not compute the hash yourself — read the file.
43
+
44
+ ## Don't
45
+
46
+ - Don't fall back to any hardcoded port — there is no project-agnostic dashboard port; a literal would route to a foreign daemon on a multi-project machine. If the lock is missing, report "not running".
47
+ - Don't compute the deterministic port and report it as the link when the lock is missing — the daemon may be down, or bound to an alternate port. Report "not running" instead.
48
+ - Don't run `flo daemon start` automatically — the user asked for a link, not for daemon management. Leave starting to `/healer` or the user.
49
+ - Don't open a browser. Print the URL; let the user click.
50
+
51
+ ## Output
52
+
53
+ A single line. Examples:
54
+
55
+ ```
56
+ The Luminarium: http://localhost:33421
57
+ ```
58
+
59
+ ```
60
+ The moflo daemon isn't running for this project. Start it with: npx flo daemon start
61
+ ```
62
+
63
+ ## See Also
64
+
65
+ - `/healer` — diagnoses and (with `--fix`) starts the daemon if it's not running.
66
+ - `src/cli/services/daemon-port.ts` (and its JS twin `bin/lib/daemon-port.mjs`) — canonical port-resolution helpers; `resolveClientPort()` is what the rest of moflo uses.
@@ -35,6 +35,7 @@ export const SKILLS_MAP = {
35
35
  'guidance',
36
36
  'healer',
37
37
  'flo-simplify',
38
+ 'luminarium',
38
39
  'reasoningbank-intelligence',
39
40
  ],
40
41
  memory: [
@@ -798,6 +798,14 @@ const DASHBOARD_HTML = `<!DOCTYPE html>
798
798
  .btn-primary { background: #238636; border-color: #2ea043; color: #fff; }
799
799
  .btn-primary:hover { background: #2ea043; border-color: #3fb950; }
800
800
  .dim { color: #484f58; font-size: 0.75rem; font-style: italic; }
801
+ /* Loading state for tabs whose data is slow on first paint (currently
802
+ Claude Stats, which walks the user's transcript dir — can take 10–15s
803
+ on a long history). Pure-CSS spinner; no image, no framework. */
804
+ .loading-block { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; padding: 48px 16px; color: #8b949e; }
805
+ .loading-block .spinner { width: 28px; height: 28px; border: 3px solid #30363d; border-top-color: #58a6ff; border-radius: 50%; animation: lum-spin 0.85s linear infinite; }
806
+ .loading-block .msg { font-size: 0.9rem; color: #c9d1d9; }
807
+ .loading-block .hint { font-size: 0.8rem; color: #8b949e; font-style: italic; max-width: 480px; text-align: center; line-height: 1.5; }
808
+ @keyframes lum-spin { to { transform: rotate(360deg); } }
801
809
  </style>
802
810
  </head>
803
811
  <body>
@@ -811,7 +819,7 @@ const DASHBOARD_HTML = `<!DOCTYPE html>
811
819
  <div id="panel-schedules" class="panel" style="display:none"><div id="schedules-active"></div><div id="schedules-events"></div></div>
812
820
  <div id="panel-executions" class="panel" style="display:none"></div>
813
821
  <div id="panel-memory" class="panel" style="display:none"></div>
814
- <div id="panel-claude-stats" class="panel" style="display:none"></div>
822
+ <div id="panel-claude-stats" class="panel" style="display:none"><div class="loading-block" role="status" aria-label="Loading Claude Code transcripts"><div class="spinner"></div><div class="msg">Reading Claude Code transcripts…</div><div class="hint">First load can take 10–15 seconds — moflo walks every session file in this project's transcript directory. Subsequent loads in this tab are much faster.</div></div></div>
815
823
  <div id="poll-indicator" class="poll-indicator"></div>
816
824
  <script>
817
825
  // Tab navigation — plain DOM, no framework
@@ -1139,7 +1147,19 @@ const DASHBOARD_HTML = `<!DOCTYPE html>
1139
1147
  };
1140
1148
  function renderClaudeStats(cs) {
1141
1149
  const el = document.getElementById('panel-claude-stats');
1142
- if (!cs) { el.innerHTML = '<div class="empty">Loading...</div>'; return; }
1150
+ // cs is null on first paint AND on fetch error (Promise chain uses
1151
+ // .catch(() => null)). Render the spinner block on both so the user
1152
+ // sees motion during the 10–15s transcript walk and during a transient
1153
+ // network blip — better than a static "Loading..." that looks frozen.
1154
+ if (!cs) {
1155
+ el.innerHTML =
1156
+ '<div class="loading-block" role="status" aria-label="Loading Claude Code transcripts">' +
1157
+ '<div class="spinner"></div>' +
1158
+ '<div class="msg">Reading Claude Code transcripts…</div>' +
1159
+ '<div class="hint">First load can take 10–15 seconds — moflo walks every session file in this project\\'s transcript directory. Subsequent loads in this tab are much faster.</div>' +
1160
+ '</div>';
1161
+ return;
1162
+ }
1143
1163
 
1144
1164
  // Always-visible disclaimer banner — keeps the scope and limits in
1145
1165
  // view so the numbers aren't read as account-wide truth.
@@ -2,5 +2,5 @@
2
2
  * Auto-generated by build. Do not edit manually.
3
3
  * Source of truth: root package.json → scripts/sync-version.mjs
4
4
  */
5
- export const VERSION = '4.10.9';
5
+ export const VERSION = '4.10.10';
6
6
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moflo",
3
- "version": "4.10.9",
3
+ "version": "4.10.10",
4
4
  "description": "MoFlo — AI agent orchestration for Claude Code. A standalone, opinionated toolkit with semantic memory, learned routing, gates, spells, and the /flo issue-execution skill.",
5
5
  "main": "dist/src/cli/index.js",
6
6
  "type": "module",
@@ -95,7 +95,7 @@
95
95
  "@typescript-eslint/eslint-plugin": "^7.18.0",
96
96
  "@typescript-eslint/parser": "^7.18.0",
97
97
  "eslint": "^8.0.0",
98
- "moflo": "^4.10.8",
98
+ "moflo": "^4.10.9",
99
99
  "tsx": "^4.21.0",
100
100
  "typescript": "^5.9.3",
101
101
  "vitest": "^4.0.0"