fdeops 3.6.1 → 3.7.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.
- package/README.md +8 -6
- package/bin/check.js +2 -2
- package/bin/fde.js +835 -300
- package/bin/install.js +1 -1
- package/package.json +1 -1
- package/skills/fde/SKILL.md +2 -2
- package/skills/fde/references/multi-customer-ops.md +8 -8
- package/skills/fde/references/red-team.md +3 -3
package/bin/fde.js
CHANGED
|
@@ -132,6 +132,10 @@ function readEng(eng, f) {
|
|
|
132
132
|
try { return fs.readFileSync(path.join(eng, f), 'utf8') } catch (_) { return '' }
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
// Read + redact in one step - the default way dashboard code should ever touch
|
|
136
|
+
// a markdown file, so a forgotten stripPrivate() call can't leak a <private> block.
|
|
137
|
+
function readClean(eng, f) { return stripPrivate(readEng(eng, f)) }
|
|
138
|
+
|
|
135
139
|
// Pull the body under a "## Heading" up to the next "##" (or EOF).
|
|
136
140
|
function sectionBody(md, heading) {
|
|
137
141
|
const lines = md.split('\n')
|
|
@@ -187,6 +191,221 @@ function computeSignals(eng) {
|
|
|
187
191
|
return { phase, trust, signalAge, stale, topRisk, updated, ageDays }
|
|
188
192
|
}
|
|
189
193
|
|
|
194
|
+
// ---------- dashboard content extractors (best-effort, read-only) ----------
|
|
195
|
+
// The fieldbook's structured widgets (stakeholders, risks, log, stats) want
|
|
196
|
+
// data shapes that .fde/ markdown does not literally carry - it is written by
|
|
197
|
+
// hand, in slightly different shapes engagement to engagement. Same spirit as
|
|
198
|
+
// computeSignals() above: keyword/pattern heuristics, commented as heuristics,
|
|
199
|
+
// degrading to "nothing found" rather than guessing when the shape does not
|
|
200
|
+
// match. Never fabricate a number, a name, or a signal that is not in the text.
|
|
201
|
+
|
|
202
|
+
const PHASE_LABELS = {
|
|
203
|
+
land: 'Embed & Trust', discover: 'Discover & Diagnose', plan: 'Plan & Align',
|
|
204
|
+
build: 'Build & Guard', ship: 'Ship & Verify', close: 'Operate & Close',
|
|
205
|
+
}
|
|
206
|
+
function phaseLabel(phase) { return PHASE_LABELS[String(phase).toLowerCase()] || phase }
|
|
207
|
+
|
|
208
|
+
// First real (non-blank, non-heading) line of a prose file, bold-label prefix
|
|
209
|
+
// stripped ("**Confirmed:** text..." -> "text...") - same spirit as the
|
|
210
|
+
// existing topRisk extraction above, just for brief.md/reality.md one-liners.
|
|
211
|
+
// An unfilled template line ("**Stated problem:**" with nothing after the
|
|
212
|
+
// colon) collapses to '' here, which callers treat as "nothing to show".
|
|
213
|
+
function firstLine(md, maxLen) {
|
|
214
|
+
for (const raw of md.split('\n')) {
|
|
215
|
+
const l = raw.trim()
|
|
216
|
+
if (!l || /^#{1,6}\s/.test(l)) continue
|
|
217
|
+
const clean = l.replace(/^\*\*[^*]+:\*\*\s*/, '').replace(/\*\*/g, '').replace(/^["']|["']$/g, '').trim()
|
|
218
|
+
if (!clean) continue
|
|
219
|
+
return clean.length > maxLen ? clean.slice(0, maxLen - 1).trim() + '…' : clean
|
|
220
|
+
}
|
|
221
|
+
return ''
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Engagement age from the .fde/ directory's own birth time - hidden (not
|
|
225
|
+
// fabricated as 0) on filesystems that do not report birthtime.
|
|
226
|
+
function daysElapsed(eng) {
|
|
227
|
+
try {
|
|
228
|
+
const b = fs.statSync(eng).birthtimeMs
|
|
229
|
+
if (!b) return null
|
|
230
|
+
return Math.max(0, Math.floor((Date.now() - b) / 86400000))
|
|
231
|
+
} catch (_) { return null }
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Sector/overlay badge: only shown when trust-profile.md or context.md name an
|
|
235
|
+
// explicit overlay in so many words - never inferred from the business domain,
|
|
236
|
+
// so a fintech-sounding name with no stated overlay stays badge-less.
|
|
237
|
+
const OVERLAY_WORDS = [['fintech', 'fintech'], ['healthcare', 'healthcare'], ['government', 'gov compliance'], ['gov compliance', 'gov compliance']]
|
|
238
|
+
function detectOverlay(eng) {
|
|
239
|
+
const text = (readClean(eng, 'trust-profile.md') + ' ' + readClean(eng, 'context.md')).toLowerCase()
|
|
240
|
+
for (const [needle, label] of OVERLAY_WORDS) if (text.includes(needle)) return label
|
|
241
|
+
return ''
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Generic "first pipe-table in this markdown" parser - structured rows, not
|
|
245
|
+
// HTML. Stops at the first non-table line once the table has started, so a
|
|
246
|
+
// prose section (e.g. risks.md's "## Retired") after the table is never
|
|
247
|
+
// swept in as rows.
|
|
248
|
+
function parseMdTable(md) {
|
|
249
|
+
const cells = r => r.replace(/^\s*\|/, '').replace(/\|\s*$/, '').split('|').map(c => c.trim())
|
|
250
|
+
const isSep = r => r.includes('-') && /^\|?[\s:|-]+\|?$/.test(r.trim())
|
|
251
|
+
let headers = null
|
|
252
|
+
const rows = []
|
|
253
|
+
for (const raw of md.split('\n')) {
|
|
254
|
+
const t = raw.trim()
|
|
255
|
+
if (!/^\|.*\|/.test(t)) { if (headers) break; continue }
|
|
256
|
+
if (isSep(t)) continue
|
|
257
|
+
const cs = cells(t)
|
|
258
|
+
if (!headers) headers = cs
|
|
259
|
+
else if (cs.some(c => c)) rows.push(cs)
|
|
260
|
+
}
|
|
261
|
+
return headers ? { headers, rows } : null
|
|
262
|
+
}
|
|
263
|
+
function colIndex(headers, rx) { return headers.findIndex(h => rx.test(h)) }
|
|
264
|
+
|
|
265
|
+
// Stakeholders: columns are matched by header wording, not position - real
|
|
266
|
+
// files use "Name" or "Name / role", "Stance" or "Signal", with or without a
|
|
267
|
+
// separate Role column (see examples/garvey-payments vs examples/kesterman-
|
|
268
|
+
// freight). Per-person signal color: FIRST try a dated [signal:x] token from
|
|
269
|
+
// "## Signal history" whose bullet text mentions the person's name (latest
|
|
270
|
+
// date wins) - this is a best-effort text match, not a guaranteed link between
|
|
271
|
+
// a person and a bullet that happens to name them. No token match -> keyword
|
|
272
|
+
// heuristic on the stance/signal cell. No table at all -> empty, never
|
|
273
|
+
// fabricated.
|
|
274
|
+
function extractStakeholders(eng) {
|
|
275
|
+
const md = readClean(eng, 'stakeholders.md')
|
|
276
|
+
const table = parseMdTable(md)
|
|
277
|
+
if (!table) return []
|
|
278
|
+
const { headers, rows } = table
|
|
279
|
+
const nameIdx = colIndex(headers, /name/i)
|
|
280
|
+
if (nameIdx === -1) return []
|
|
281
|
+
const roleIdx = colIndex(headers, /^role$/i)
|
|
282
|
+
const stanceIdx = colIndex(headers, /stance|signal/i)
|
|
283
|
+
const notesIdx = colIndex(headers, /notes?/i)
|
|
284
|
+
|
|
285
|
+
const history = []
|
|
286
|
+
sectionBody(md, 'Signal history').split('\n').forEach(l => {
|
|
287
|
+
const m = l.trim().match(/^-\s*\[(\d{4}-\d{2}-\d{2})\]\s*\[signal:(red|amber|green)\]\s*(.+)$/i)
|
|
288
|
+
if (m) history.push({ date: m[1], signal: m[2].toLowerCase(), text: m[3] })
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
return rows.map(cs => {
|
|
292
|
+
const name = (cs[nameIdx] || '').trim()
|
|
293
|
+
if (!name) return null
|
|
294
|
+
const role = roleIdx !== -1 ? (cs[roleIdx] || '').trim() : ''
|
|
295
|
+
const stance = stanceIdx !== -1 ? (cs[stanceIdx] || '').trim() : ''
|
|
296
|
+
const note = notesIdx !== -1 ? (cs[notesIdx] || '').trim() : ''
|
|
297
|
+
|
|
298
|
+
// naive match fragment: first real word of the name, skipping honorifics,
|
|
299
|
+
// so "Dr. Anand Mehta" matches signal-history prose on "Anand", not "Dr."
|
|
300
|
+
const words = name.replace(/\([^)]*\)/g, '').split(/\s+/).filter(w => w && !/^(dr|mr|mrs|ms)\.?$/i.test(w))
|
|
301
|
+
const frag = (words[0] || '').replace(/[^a-z0-9]/gi, '')
|
|
302
|
+
|
|
303
|
+
// Match the SUBJECT of the entry, not anyone it mentions in passing -
|
|
304
|
+
// "Renata declined... told Sam..." is Renata's signal, not Sam's, even
|
|
305
|
+
// though "Sam" appears in the text. Every real signal-history line in
|
|
306
|
+
// this codebase's own examples is written subject-first ("Denise skipped
|
|
307
|
+
// Thursday demo", "Randy opened the sheet..."), so requiring the name at
|
|
308
|
+
// the START of the entry (not .includes() anywhere in it) is the fix,
|
|
309
|
+
// not a stricter rule invented for its own sake.
|
|
310
|
+
let signal = null, matchedDate = null
|
|
311
|
+
if (frag.length >= 3) {
|
|
312
|
+
for (const h of history) {
|
|
313
|
+
if (h.text.trim().toLowerCase().startsWith(frag.toLowerCase()) && (!matchedDate || h.date >= matchedDate)) {
|
|
314
|
+
signal = h.signal; matchedDate = h.date
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
if (!signal) {
|
|
319
|
+
const s = stance.toLowerCase()
|
|
320
|
+
signal = /champion|steady|\bgreen\b/.test(s) ? 'green'
|
|
321
|
+
: /resistant|hostile|blocker|\bred\b/.test(s) ? 'red'
|
|
322
|
+
: 'amber' // neutral / cooling / warming / not met / unknown / no signal cell at all
|
|
323
|
+
}
|
|
324
|
+
return { name, role, note, signal }
|
|
325
|
+
}).filter(Boolean)
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Risks: same table parser, matched on a "Risk" column. Real files carry no
|
|
329
|
+
// severity field, so severity is a coarse high/med keyword guess on the risk
|
|
330
|
+
// text itself - a guess, same honesty as computeSignals()'s trust fallback,
|
|
331
|
+
// not a claim of real triage. "## Retired" rows are prose bullets, not table
|
|
332
|
+
// rows, so the table parser above already stops before them - they feed the
|
|
333
|
+
// log instead (see extractLog).
|
|
334
|
+
function extractRisks(eng) {
|
|
335
|
+
const md = readClean(eng, 'risks.md')
|
|
336
|
+
const table = parseMdTable(md)
|
|
337
|
+
if (!table) return []
|
|
338
|
+
const riskIdx = colIndex(table.headers, /^risk$/i)
|
|
339
|
+
if (riskIdx === -1) return []
|
|
340
|
+
const HIGH = /critical|blocker|exposure|breach|urgent|at risk|at stake|\brace\b/i
|
|
341
|
+
return table.rows.map(cs => {
|
|
342
|
+
const text = (cs[riskIdx] || '').trim()
|
|
343
|
+
return text ? { text, severity: HIGH.test(text) ? 'high' : 'med' } : null
|
|
344
|
+
}).filter(Boolean)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Best-effort scan for "before -> after" metric callouts in delivery/decisions
|
|
348
|
+
// prose (e.g. "94.1% row parity day one -> 98.8% by ..."). Only kept when both
|
|
349
|
+
// sides look like real numbers/percentages, deduped by value pair, capped at
|
|
350
|
+
// 4; nothing reliable found -> the widget stays empty, never an invented number.
|
|
351
|
+
function extractStats(eng) {
|
|
352
|
+
const text = readClean(eng, 'delivery.md') + '\n' + readClean(eng, 'decisions.md')
|
|
353
|
+
const patterns = [
|
|
354
|
+
/(\d+(?:\.\d+)?%)[^\n%]{0,40}?(?:→|->)[^\n%]{0,20}?(\d+(?:\.\d+)?%)/g, // "X% ... -> Y%"
|
|
355
|
+
/(\d+(?:\.\d+)?%)\s+to\s+(\d+(?:\.\d+)?%)/gi, // "X% to Y%"
|
|
356
|
+
/from\s+([\d.]+\s?[a-zA-Z]{0,6}%?)\s+to\s+([\d.]+\s?[a-zA-Z]{0,6}%?)/gi, // "from X to Y" / "reduced from X to Y"
|
|
357
|
+
]
|
|
358
|
+
const seen = new Set(); const stats = []
|
|
359
|
+
for (const rx of patterns) {
|
|
360
|
+
let m
|
|
361
|
+
while ((m = rx.exec(text))) {
|
|
362
|
+
const from = m[1].trim(), to = m[2].trim()
|
|
363
|
+
if (!from || !to || from === to) continue
|
|
364
|
+
const key = from + '→' + to
|
|
365
|
+
if (seen.has(key)) continue
|
|
366
|
+
seen.add(key)
|
|
367
|
+
const pre = text.slice(Math.max(0, m.index - 40), m.index)
|
|
368
|
+
const label = pre.split(/\s+/).filter(Boolean).slice(-3).join(' ').replace(/^[,:;.\-]+|[,:;.\-]+$/g, '') || 'metric'
|
|
369
|
+
stats.push({ label, from, to })
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return stats.slice(0, 4)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Unified dated log: merges (a) plain "- [date] text" bullets - the exact
|
|
376
|
+
// shape `fde log`/`fde debrief` write mechanically, so this MUST be supported
|
|
377
|
+
// - found in decisions.md, delivery.md, risks.md's "## Retired" section and
|
|
378
|
+
// stakeholders.md's "## Signal history" section; with (b) the human-authored
|
|
379
|
+
// "### [date] title" / "## date - title" decision headers seen in real
|
|
380
|
+
// decisions.md files. Sorted newest first, capped for the panel.
|
|
381
|
+
function extractLog(eng) {
|
|
382
|
+
const FLAT = /^-\s*\[(\d{4}-\d{2}-\d{2})\]\s*(.+)$/
|
|
383
|
+
const entries = []
|
|
384
|
+
const push = (date, text, kind) => {
|
|
385
|
+
text = text.replace(/\[signal:(red|amber|green)\]\s*/i, '').trim()
|
|
386
|
+
if (date && text) entries.push({ date, text, kind })
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
readClean(eng, 'decisions.md').split('\n').forEach(l => {
|
|
390
|
+
const t = l.trim()
|
|
391
|
+
const fm = t.match(FLAT); if (fm) { push(fm[1], fm[2], 'decision'); return }
|
|
392
|
+
const bm = t.match(/^#{2,3}\s*\[(\d{4}-\d{2}-\d{2})\]\s*(.+)$/); if (bm) { push(bm[1], bm[2], 'decision'); return }
|
|
393
|
+
const dm = t.match(/^#{2,3}\s*(\d{4}-\d{2}-\d{2})\s*-\s*(.+)$/); if (dm) push(dm[1], dm[2], 'decision')
|
|
394
|
+
})
|
|
395
|
+
readClean(eng, 'delivery.md').split('\n').forEach(l => {
|
|
396
|
+
const m = l.trim().match(FLAT); if (m) push(m[1], m[2], 'receipt')
|
|
397
|
+
})
|
|
398
|
+
sectionBody(readClean(eng, 'risks.md'), 'Retired').split('\n').forEach(l => {
|
|
399
|
+
const m = l.trim().match(FLAT); if (m) push(m[1], m[2], 'receipt')
|
|
400
|
+
})
|
|
401
|
+
sectionBody(readClean(eng, 'stakeholders.md'), 'Signal history').split('\n').forEach(l => {
|
|
402
|
+
const m = l.trim().match(FLAT); if (m) push(m[1], m[2], 'note')
|
|
403
|
+
})
|
|
404
|
+
|
|
405
|
+
entries.sort((a, b) => b.date.localeCompare(a.date))
|
|
406
|
+
return entries.slice(0, 15)
|
|
407
|
+
}
|
|
408
|
+
|
|
190
409
|
// ---------- commands ----------
|
|
191
410
|
|
|
192
411
|
function cmdScan() {
|
|
@@ -517,26 +736,14 @@ function inlineMd(s) {
|
|
|
517
736
|
.replace(/`([^`]+)`/g, '<code>$1</code>')
|
|
518
737
|
}
|
|
519
738
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
html += '<thead><tr>' + cs.map(c => '<th>' + inlineMd(c) + '</th>').join('') + '</tr></thead><tbody>'
|
|
529
|
-
headerDone = true
|
|
530
|
-
} else {
|
|
531
|
-
if (cs.every(c => !c)) continue
|
|
532
|
-
html += '<tr>' + cs.map(c => '<td>' + inlineMd(c) + '</td>').join('') + '</tr>'
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
return html + '</tbody></table>'
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
function mdToHtml(md) {
|
|
539
|
-
const lines = stripPrivate(md).split('\n')
|
|
739
|
+
// Generic markdown -> HTML for the three .fde files that are reference
|
|
740
|
+
// documents, not logs (success.md, terrain.md, trust-profile.md): they don't
|
|
741
|
+
// fit the structured stakeholder/risk/log widgets, but they're real content
|
|
742
|
+
// (trust-profile.md especially - sacred data and AI policy) and must stay
|
|
743
|
+
// visible in the fieldbook, not silently dropped. Headings, tables, bullet
|
|
744
|
+
// lists, and paragraphs only - matches what these files actually contain.
|
|
745
|
+
function mdBlockHtml(md) {
|
|
746
|
+
const lines = md.split('\n')
|
|
540
747
|
const out = []; let i = 0
|
|
541
748
|
while (i < lines.length) {
|
|
542
749
|
const t = lines[i].trim()
|
|
@@ -544,32 +751,38 @@ function mdToHtml(md) {
|
|
|
544
751
|
if (/^\|.*\|/.test(t)) {
|
|
545
752
|
const tbl = []
|
|
546
753
|
while (i < lines.length && /^\s*\|.*\|/.test(lines[i])) { tbl.push(lines[i]); i++ }
|
|
547
|
-
|
|
754
|
+
const parsed = parseMdTable(tbl.join('\n'))
|
|
755
|
+
if (parsed) {
|
|
756
|
+
out.push('<table class="fb-table"><thead><tr>' + parsed.headers.map(h => '<th>' + inlineMd(h) + '</th>').join('') + '</tr></thead><tbody>' +
|
|
757
|
+
parsed.rows.map(r => '<tr>' + r.map(c => '<td>' + inlineMd(c) + '</td>').join('') + '</tr>').join('') + '</tbody></table>')
|
|
758
|
+
}
|
|
759
|
+
continue
|
|
548
760
|
}
|
|
549
761
|
const h = t.match(/^(#{1,6})\s+(.*)$/)
|
|
550
|
-
if (h) { out.push('<
|
|
762
|
+
if (h) { out.push('<div class="fb-sec">' + inlineMd(h[2]) + '</div>'); i++; continue }
|
|
551
763
|
if (/^[-*]\s+/.test(t)) {
|
|
552
764
|
const items = []
|
|
553
765
|
while (i < lines.length && /^\s*[-*]\s+/.test(lines[i])) { items.push('<li>' + inlineMd(lines[i].trim().replace(/^[-*]\s+/, '')) + '</li>'); i++ }
|
|
554
|
-
out.push('<ul>' + items.join('') + '</ul>'); continue
|
|
766
|
+
out.push('<ul class="fb-plain-list">' + items.join('') + '</ul>'); continue
|
|
555
767
|
}
|
|
556
768
|
const para = []
|
|
557
769
|
while (i < lines.length && lines[i].trim() && !/^\s*\|.*\|/.test(lines[i]) && !/^#{1,6}\s/.test(lines[i].trim()) && !/^[-*]\s+/.test(lines[i].trim())) {
|
|
558
770
|
para.push(lines[i].trim()); i++
|
|
559
771
|
}
|
|
560
|
-
out.push('<p>' + inlineMd(para.join(' ')) + '</p>')
|
|
772
|
+
out.push('<p class="fb-plain-p">' + inlineMd(para.join(' ')) + '</p>')
|
|
561
773
|
}
|
|
562
774
|
return out.join('\n')
|
|
563
775
|
}
|
|
564
776
|
|
|
565
|
-
// True if a file has real content beyond headings,
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
.replace(
|
|
570
|
-
.replace(/^\s*\|[\s
|
|
571
|
-
.replace(
|
|
572
|
-
.replace(
|
|
777
|
+
// True if a file has real content beyond headings, empty table cells, and
|
|
778
|
+
// blank bullets - same heuristic the old dashboard used to skip empty files.
|
|
779
|
+
function hasRealContent(md) {
|
|
780
|
+
const txt = md
|
|
781
|
+
.replace(/^#{1,6}\s.*$/gm, '')
|
|
782
|
+
.replace(/^\s*\|[\s:|-]+\|\s*$/gm, '')
|
|
783
|
+
.replace(/^\s*\|[\s|]*\|\s*$/gm, '')
|
|
784
|
+
.replace(/\*\*[^*]+:\*\*\s*$/gm, '')
|
|
785
|
+
.replace(/[-*]\s*$/gm, '')
|
|
573
786
|
.replace(/\s+/g, ' ')
|
|
574
787
|
.trim()
|
|
575
788
|
return txt.length > 0
|
|
@@ -587,182 +800,518 @@ function gatherEngagements() {
|
|
|
587
800
|
return list
|
|
588
801
|
}
|
|
589
802
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
['delivery.md', 'Delivery log'],
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
803
|
+
// Geist (400-700 variable weight) + Geist Mono (400-600 variable weight),
|
|
804
|
+
// latin subset only, base64-embedded woff2 - zero network calls, still opens
|
|
805
|
+
// fully offline. Spliced in verbatim by the build step below; never fetched.
|
|
806
|
+
const FONT_FACE_CSS = `@font-face {
|
|
807
|
+
font-family: 'Geist';
|
|
808
|
+
font-style: normal;
|
|
809
|
+
font-weight: 400 700;
|
|
810
|
+
font-display: swap;
|
|
811
|
+
src: url(data:font/woff2;base64,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) format('woff2');
|
|
812
|
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
813
|
+
}
|
|
814
|
+
@font-face {
|
|
815
|
+
font-family: 'Geist Mono';
|
|
816
|
+
font-style: normal;
|
|
817
|
+
font-weight: 400 600;
|
|
818
|
+
font-display: swap;
|
|
819
|
+
src: url(data:font/woff2;base64,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) format('woff2');
|
|
820
|
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
821
|
+
}`
|
|
602
822
|
|
|
823
|
+
const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
|
824
|
+
const WEEKDAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
|
|
825
|
+
function formatToday(d) { return `${WEEKDAYS[d.getDay()]}, ${MONTHS[d.getMonth()]} ${d.getDate()}` }
|
|
826
|
+
function formatLogDate(iso) {
|
|
827
|
+
const m = String(iso).match(/^(\d{4})-(\d{2})-(\d{2})$/)
|
|
828
|
+
return m ? `${MONTHS[parseInt(m[2], 10) - 1]} ${parseInt(m[3], 10)}` : iso
|
|
829
|
+
}
|
|
830
|
+
function trustWord(t) { return t === 'green' ? 'steady' : t === 'amber' ? 'watch' : 'at risk' }
|
|
831
|
+
function dotClassFor(trust) { return trust === 'RED' ? 'red' : trust }
|
|
832
|
+
|
|
833
|
+
// Two-pane fieldbook: left rail (search + today + per-client nav), right main
|
|
834
|
+
// panel with a Today queue view and a per-client detail view, plus a command
|
|
835
|
+
// palette overlay. Light + dark are both full, real token sets (not one
|
|
836
|
+
// derived from the other) - translated 1:1 from the design's THEMES object
|
|
837
|
+
// into the file's existing :root / html[data-fde-theme="dark"] mechanism.
|
|
603
838
|
function dashStyles() {
|
|
604
|
-
return
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
839
|
+
return `
|
|
840
|
+
:root{--bg:#f7f7f6;--panel:#eceae7;--rowhover:#e4e2de;--ink:#14140f;--ink-soft:#4a4942;--ink-faint:#7c7a71;--line:#dedcd6;--accent:#12885c;--accent-bg:#dcf1e6;--green:#12885c;--amber:#a56a19;--red:#b23e2b;--shadow:0 12px 48px rgba(0,0,0,.18)}
|
|
841
|
+
html[data-fde-theme="dark"]{--bg:#0a0a09;--panel:#151513;--rowhover:#1c1c19;--ink:#f2f1ec;--ink-soft:#b0ada2;--ink-faint:#726f64;--line:#232320;--accent:#3ddc97;--accent-bg:#132420;--green:#3ddc97;--amber:#f0b860;--red:#ff8f83;--shadow:0 12px 48px rgba(0,0,0,.5)}
|
|
842
|
+
${FONT_FACE_CSS}
|
|
843
|
+
*,*::before,*::after{box-sizing:border-box}
|
|
844
|
+
html,body{margin:0;padding:0;height:100%}
|
|
845
|
+
body{font-family:'Geist',system-ui,-apple-system,sans-serif;color:var(--ink);background:var(--bg);-webkit-font-smoothing:antialiased;transition:background .15s,color .15s}
|
|
846
|
+
::selection{background:var(--accent-bg)}
|
|
847
|
+
button,input{font-family:inherit}
|
|
848
|
+
code{background:var(--panel);padding:1px 5px;border-radius:4px;font-size:12px;color:var(--ink-soft);font-family:'Geist Mono',monospace}
|
|
849
|
+
strong{font-weight:600}
|
|
850
|
+
.empty{color:var(--ink-faint);font-style:italic;font-size:13px}
|
|
851
|
+
.fb-app{height:100vh;display:flex;flex-direction:column;overflow:hidden}
|
|
852
|
+
.fb-scroll::-webkit-scrollbar{width:7px;height:7px}
|
|
853
|
+
.fb-scroll::-webkit-scrollbar-thumb{background:var(--line);border-radius:7px}
|
|
854
|
+
.fb-scroll::-webkit-scrollbar-track{background:transparent}
|
|
855
|
+
.fb-header{flex:0 0 auto;display:flex;align-items:center;gap:18px;padding:14px 24px;background:var(--bg);border-bottom:1px solid var(--line)}
|
|
856
|
+
.fb-brand{display:flex;align-items:baseline;gap:9px}
|
|
857
|
+
.fb-wordmark{font-family:'Geist Mono',monospace;font-size:14px;font-weight:700;letter-spacing:.01em}
|
|
858
|
+
.fb-tagline{font-family:'Geist Mono',monospace;font-size:12px;color:var(--ink-faint)}
|
|
859
|
+
.fb-need{font-family:'Geist Mono',monospace;font-size:11.5px;color:var(--accent);margin-left:8px}
|
|
860
|
+
.fb-spacer{flex:1 1 auto}
|
|
861
|
+
.fb-today{font-family:'Geist Mono',monospace;font-size:11.5px;color:var(--ink-faint)}
|
|
862
|
+
.fb-btn{border:1px solid var(--line);border-radius:6px;padding:5px 10px;background:transparent;color:var(--ink-faint);font-family:'Geist Mono',monospace;font-size:11px;cursor:pointer;line-height:1.4}
|
|
863
|
+
.fb-btn:hover{color:var(--ink);border-color:var(--accent)}
|
|
864
|
+
.fb-body{flex:1 1 auto;display:flex;min-height:0}
|
|
865
|
+
.fb-rail{flex:0 0 288px;display:flex;flex-direction:column;background:var(--bg);border-right:1px solid var(--line)}
|
|
866
|
+
.fb-rail-search{flex:0 0 auto;padding:12px 14px}
|
|
867
|
+
.fb-search{width:100%;padding:6px 9px;border:1px solid var(--line);border-radius:6px;background:var(--panel);color:var(--ink);font-family:'Geist Mono',monospace;font-size:12px;outline:none}
|
|
868
|
+
.fb-search:focus{border-color:var(--accent)}
|
|
869
|
+
.fb-search::placeholder{color:var(--ink-faint)}
|
|
870
|
+
.fb-rail-list{flex:1 1 auto;overflow-y:auto;padding:0 8px 16px}
|
|
871
|
+
.fb-nav{width:100%;text-align:left;display:block;padding:9px 10px;border:none;border-left:2px solid transparent;border-radius:0 5px 5px 0;background:transparent;cursor:pointer;color:inherit;margin-bottom:2px}
|
|
872
|
+
.fb-nav:hover{background:var(--panel)}
|
|
873
|
+
.fb-nav.active{background:var(--panel);border-left-color:var(--accent)}
|
|
874
|
+
.fb-nav.hide{display:none}
|
|
875
|
+
.fb-nav-row{display:flex;align-items:center;gap:8px}
|
|
876
|
+
.fb-nav-name,.fb-nav-today{font-family:'Geist Mono',monospace;font-size:12.5px;font-weight:500;color:var(--ink);flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
877
|
+
.fb-nav.active .fb-nav-name{font-weight:600}
|
|
878
|
+
.fb-nav-today{color:var(--accent);font-weight:600}
|
|
879
|
+
.fb-nav-count{margin-left:auto;font-family:'Geist Mono',monospace;font-size:10.5px;color:var(--ink-faint)}
|
|
880
|
+
.fb-nav-meta{margin-top:3px;padding-left:14px;font-family:'Geist Mono',monospace;font-size:10.5px;color:var(--ink-faint)}
|
|
881
|
+
.fb-nav-reason{margin-top:3px;padding-left:14px;font-size:12px;line-height:1.35;color:var(--ink-soft)}
|
|
882
|
+
.fb-nav-reason.hide{display:none}
|
|
883
|
+
.fb-nav-reason mark{background:var(--accent-bg);color:inherit;border-radius:2px;padding:0 1px}
|
|
884
|
+
.fb-main{flex:1 1 auto;overflow-y:auto;background:var(--bg)}
|
|
885
|
+
.fb-main-inner{max-width:1440px;margin:0 auto;padding:28px 48px 64px}
|
|
886
|
+
.fb-grid-wrap{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:22px 40px;margin-top:22px}
|
|
887
|
+
.fb-grid-wrap .fb-block{margin-top:0}
|
|
888
|
+
.fb-top-grid{display:grid;grid-template-columns:1fr 280px;gap:0 32px;align-items:stretch}
|
|
889
|
+
.fb-vitals{display:flex;flex-direction:column;margin-top:22px;padding:16px 18px;background:var(--panel);border:1px solid var(--line);border-radius:8px}
|
|
890
|
+
.fb-vital-row{display:flex;justify-content:space-between;gap:10px;padding:5px 0;font-size:12.5px}
|
|
891
|
+
.fb-vital-row+.fb-vital-row{border-top:1px solid var(--line)}
|
|
892
|
+
.fb-vital-label{font-family:'Geist Mono',monospace;font-size:10.5px;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-faint)}
|
|
893
|
+
.fb-vital-val{color:var(--ink);font-weight:600;text-align:right}
|
|
894
|
+
.fb-vital-div{margin:4px 0;border-top:1px solid var(--line)}
|
|
895
|
+
@media(max-width:920px){.fb-top-grid{grid-template-columns:1fr}.fb-vitals{max-width:400px}}
|
|
896
|
+
.fb-view[hidden]{display:none}
|
|
897
|
+
.fb-eyebrow{font-family:'Geist Mono',monospace;font-size:11px;color:var(--ink-faint)}
|
|
898
|
+
.fb-h1{font-family:'Geist Mono',monospace;font-size:26px;font-weight:600;letter-spacing:-.01em;margin:6px 0 0}
|
|
899
|
+
.fb-title-row{display:flex;align-items:baseline;gap:10px;margin-top:6px}
|
|
900
|
+
.fb-title-row .fb-h1{margin-top:0}
|
|
901
|
+
.fb-trust{display:flex;align-items:center;gap:6px;font-family:'Geist Mono',monospace;font-size:12px}
|
|
902
|
+
.fb-meta-line{margin-top:5px;font-family:'Geist Mono',monospace;font-size:12px;color:var(--ink-faint)}
|
|
903
|
+
.fb-block{margin-top:22px;padding-top:18px;border-top:1px solid var(--line)}
|
|
904
|
+
.fb-sec{font-family:'Geist Mono',monospace;font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--accent);margin:0 0 8px}
|
|
905
|
+
.fb-sec-row{display:flex;align-items:baseline;gap:8px}
|
|
906
|
+
.fb-sec-row .fb-sec{margin:0}
|
|
907
|
+
.fb-count{font-family:'Geist Mono',monospace;font-size:10.5px;color:var(--ink-faint)}
|
|
908
|
+
.fb-now-action{font-size:16.5px;font-weight:600;line-height:1.5;color:var(--ink)}
|
|
909
|
+
.fb-now-session{margin-top:10px;font-size:14.5px;line-height:1.6;color:var(--ink-soft)}
|
|
910
|
+
.fb-why{margin:0;font-size:14.5px;line-height:1.6;color:var(--ink)}
|
|
911
|
+
.fb-why-reality{margin-top:8px}
|
|
912
|
+
.fb-accent-label{color:var(--accent);font-weight:600}
|
|
913
|
+
.fb-stats{display:flex;gap:22px;flex-wrap:wrap;font-family:'Geist Mono',monospace;font-size:13.5px}
|
|
914
|
+
.fb-stat{display:inline-flex;align-items:baseline;gap:6px;padding:2px 0}
|
|
915
|
+
.fb-arrow{color:var(--ink-faint)}
|
|
916
|
+
.fb-stat-to{color:var(--ink);font-weight:600}
|
|
917
|
+
.fb-list{margin-top:2px}
|
|
918
|
+
.fb-row{display:flex;align-items:baseline;gap:10px;padding:7px 8px;margin:0 -8px;border-radius:5px}
|
|
919
|
+
.fb-list .fb-row:nth-child(even){background:var(--panel)}
|
|
920
|
+
.fb-row:hover{background:var(--rowhover)!important}
|
|
921
|
+
.fb-person-name{font-size:14px;font-weight:600;color:var(--ink);flex:0 0 150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
922
|
+
.fb-person-role{font-family:'Geist Mono',monospace;font-size:11.5px;color:var(--ink-faint);flex:0 0 130px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
923
|
+
.fb-person-note{font-size:13px;color:var(--ink-soft);flex:1 1 auto}
|
|
924
|
+
.fb-risk-sev{font-family:'Geist Mono',monospace;font-size:10.5px;letter-spacing:.04em;text-transform:uppercase;flex:0 0 38px}
|
|
925
|
+
.fb-risk-text{font-size:14px;line-height:1.4;color:var(--ink);flex:1 1 auto}
|
|
926
|
+
.fb-log-date{font-family:'Geist Mono',monospace;font-size:11.5px;color:var(--ink-faint);flex:0 0 48px}
|
|
927
|
+
.fb-log-kind{font-family:'Geist Mono',monospace;font-size:10px;letter-spacing:.03em;text-transform:uppercase;flex:0 0 62px}
|
|
928
|
+
.fb-log-text{flex:1 1 auto;font-size:14px;line-height:1.5;color:var(--ink)}
|
|
929
|
+
.fb-more{border-top:1px solid var(--line);padding:12px 0}
|
|
930
|
+
.fb-more:first-child{border-top:none;padding-top:0}
|
|
931
|
+
.fb-more-sum{cursor:pointer;list-style:none;display:flex;align-items:center;gap:6px}
|
|
932
|
+
.fb-more-sum::-webkit-details-marker{display:none}
|
|
933
|
+
.fb-more-sum::before{content:'\\2023';color:var(--ink-faint);transition:transform .12s}
|
|
934
|
+
.fb-more[open] .fb-more-sum::before{transform:rotate(90deg)}
|
|
935
|
+
.fb-more-body{margin-top:10px}
|
|
936
|
+
.fb-plain-p{font-size:14px;line-height:1.55;color:var(--ink-soft);margin:0 0 10px}
|
|
937
|
+
.fb-plain-list{margin:0 0 10px;padding-left:18px}
|
|
938
|
+
.fb-plain-list li{font-size:14px;line-height:1.55;color:var(--ink-soft);margin:2px 0}
|
|
939
|
+
.fb-table{border-collapse:collapse;width:100%;margin:0 0 12px;font-size:13px}
|
|
940
|
+
.fb-table th,.fb-table td{padding:6px 9px;text-align:left;vertical-align:top;border-bottom:1px solid var(--line)}
|
|
941
|
+
.fb-table th{font-family:'Geist Mono',monospace;font-size:10px;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-faint)}
|
|
942
|
+
.fb-table tr:last-child td{border-bottom:none}
|
|
943
|
+
.fb-queue-row,.fb-flag-row{cursor:pointer}
|
|
944
|
+
.fb-queue-row:nth-child(even),.fb-flag-row:nth-child(even){background:var(--panel)}
|
|
945
|
+
.fb-queue-slug{font-family:'Geist Mono',monospace;font-size:12px;color:var(--ink-faint);flex:0 0 130px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
946
|
+
.fb-queue-action{font-size:14px;line-height:1.45;color:var(--ink);flex:1 1 auto}
|
|
947
|
+
.fb-queue-touched{font-family:'Geist Mono',monospace;font-size:10.5px;color:var(--ink-faint);flex:0 0 auto}
|
|
948
|
+
.fb-flag-slug{font-family:'Geist Mono',monospace;font-size:12px;color:var(--ink-faint);flex:0 0 130px}
|
|
949
|
+
.fb-flag-text{font-family:'Geist Mono',monospace;font-size:12.5px}
|
|
950
|
+
.dot{display:inline-block;flex:0 0 auto;border-radius:50%;box-sizing:border-box}
|
|
951
|
+
.dot.green{background:var(--green)}
|
|
952
|
+
.dot.amber{background:var(--amber);border-radius:2px}
|
|
953
|
+
.dot.red{background:transparent;border:1.5px solid var(--red)}
|
|
954
|
+
.dot-sm{width:7px;height:7px}
|
|
955
|
+
.dot-md{width:8px;height:8px}
|
|
956
|
+
.dot-lg{width:9px;height:9px}
|
|
957
|
+
.t-green{color:var(--green)}.t-amber{color:var(--amber)}.t-red{color:var(--red)}.t-accent{color:var(--accent)}.t-faint{color:var(--ink-faint)}.t-soft{color:var(--ink-soft)}
|
|
958
|
+
.fb-hints{margin-top:26px;display:flex;gap:14px;flex-wrap:wrap;font-family:'Geist Mono',monospace;font-size:10.5px;color:var(--ink-faint);border-top:1px solid var(--line);padding-top:12px}
|
|
959
|
+
.fb-hints-spacer{margin-left:auto}
|
|
960
|
+
.fb-palette-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:60;display:none;align-items:flex-start;justify-content:center;padding-top:12vh}
|
|
961
|
+
.fb-palette-backdrop.open{display:flex}
|
|
962
|
+
.fb-palette{width:480px;max-width:90vw;background:var(--bg);border:1px solid var(--line);border-radius:10px;overflow:hidden;box-shadow:var(--shadow)}
|
|
963
|
+
.fb-palette-input{width:100%;padding:12px 14px;border:none;border-bottom:1px solid var(--line);background:transparent;color:var(--ink);font-family:'Geist Mono',monospace;font-size:13.5px;outline:none;box-sizing:border-box}
|
|
964
|
+
.fb-palette-list{max-height:300px;overflow-y:auto}
|
|
965
|
+
.fb-palette-item{display:flex;gap:10px;align-items:baseline;padding:9px 14px;cursor:pointer}
|
|
966
|
+
.fb-palette-item.active{background:var(--panel)}
|
|
967
|
+
.fb-palette-item.hide{display:none}
|
|
968
|
+
.fb-palette-kind{font-family:'Geist Mono',monospace;font-size:10px;letter-spacing:.04em;color:var(--ink-faint);flex:0 0 52px;text-transform:uppercase}
|
|
969
|
+
.fb-palette-label{font-family:'Geist Mono',monospace;font-size:13px;color:var(--ink)}
|
|
970
|
+
.fb-palette-hint{margin-left:auto;font-family:'Geist Mono',monospace;font-size:11px;color:var(--ink-faint)}
|
|
971
|
+
@media(max-width:760px){.fb-rail{flex:0 0 220px}.fb-main-inner{padding:20px}}
|
|
972
|
+
@media(max-width:640px){.fb-body{flex-direction:column}.fb-rail{flex:0 0 auto;max-height:40vh;border-right:none;border-bottom:1px solid var(--line)}.fb-main-inner{padding:16px}}
|
|
973
|
+
`
|
|
716
974
|
}
|
|
717
975
|
|
|
976
|
+
// Vanilla DOM only - no framework. Read-only: view selection (today vs a
|
|
977
|
+
// client) is a plain show/hide over pre-rendered panels, not a re-render.
|
|
978
|
+
// Search filters the rail (hide + match-snippet, same mechanic the old
|
|
979
|
+
// dashboard used); keyboard nav (j/k/arrows, /, Escape, cmd/ctrl+K) and the
|
|
980
|
+
// command palette are wired the same way the theme toggle already was here -
|
|
981
|
+
// addEventListener, guarded null checks, no inline handlers.
|
|
718
982
|
function dashScript() {
|
|
719
983
|
return [
|
|
720
|
-
"
|
|
721
|
-
"
|
|
984
|
+
"(function(){",
|
|
985
|
+
"'use strict';",
|
|
986
|
+
"var SEL_KEY='fde-fieldbook-sel';",
|
|
722
987
|
"function esc(s){return s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');}",
|
|
723
|
-
|
|
988
|
+
"function all(sel){return Array.prototype.slice.call(document.querySelectorAll(sel));}",
|
|
989
|
+
"",
|
|
990
|
+
"var views=all('.fb-view');",
|
|
991
|
+
"var navItems=all('.fb-nav');",
|
|
992
|
+
"var searchInput=document.getElementById('fb-search');",
|
|
993
|
+
"",
|
|
994
|
+
"function selectView(id){",
|
|
995
|
+
" if(!document.getElementById('view-'+id))return;",
|
|
996
|
+
" views.forEach(function(v){v.hidden=(v.id!=='view-'+id);});",
|
|
997
|
+
" navItems.forEach(function(n){n.classList.toggle('active',n.getAttribute('data-target')===id);});",
|
|
998
|
+
" try{localStorage.setItem(SEL_KEY,id);}catch(e){}",
|
|
999
|
+
"}",
|
|
1000
|
+
"navItems.forEach(function(n){n.addEventListener('click',function(){selectView(n.getAttribute('data-target'));});});",
|
|
1001
|
+
"all('[data-nav]').forEach(function(n){n.addEventListener('click',function(){selectView(n.getAttribute('data-nav'));});});",
|
|
1002
|
+
"",
|
|
1003
|
+
"var startSel='today';",
|
|
1004
|
+
"try{var s=localStorage.getItem(SEL_KEY);if(s&&document.getElementById('view-'+s))startSel=s;}catch(e){}",
|
|
1005
|
+
"selectView(startSel);",
|
|
1006
|
+
"",
|
|
1007
|
+
"// search: filters the rail, shows a match snippet in place of the default reason line",
|
|
1008
|
+
"// NOTE: snippetFor() below returns a string built ONLY from esc()-escaped",
|
|
1009
|
+
"// fragments plus hardcoded '<mark>' literals - never raw untrusted markup -",
|
|
1010
|
+
"// so assigning it via innerHTML cannot inject a tag from engagement content.",
|
|
724
1011
|
"function snippetFor(raw,term){",
|
|
725
1012
|
" var i=raw.indexOf(term);",
|
|
726
1013
|
" if(i<0)return '';",
|
|
727
|
-
" var start=Math.max(0,i-
|
|
1014
|
+
" var start=Math.max(0,i-24),end=Math.min(raw.length,i+term.length+40);",
|
|
728
1015
|
" var pre=esc(raw.slice(start,i)),hit=esc(raw.slice(i,i+term.length)),post=esc(raw.slice(i+term.length,end));",
|
|
729
|
-
" return (start>0?'
|
|
1016
|
+
" return (start>0?'\\u2026':'')+pre+'<mark>'+hit+'</mark>'+post+(end<raw.length?'\\u2026':'');",
|
|
730
1017
|
"}",
|
|
731
|
-
"if(
|
|
732
|
-
" var term=
|
|
733
|
-
"
|
|
734
|
-
"
|
|
1018
|
+
"if(searchInput){searchInput.addEventListener('input',function(){",
|
|
1019
|
+
" var term=searchInput.value.trim().toLowerCase();",
|
|
1020
|
+
" navItems.forEach(function(n){",
|
|
1021
|
+
" if(n.getAttribute('data-target')==='today')return;",
|
|
1022
|
+
" var raw=(n.getAttribute('data-search')||'').toLowerCase();",
|
|
735
1023
|
" var hit=!term||raw.indexOf(term)>-1;",
|
|
736
|
-
"
|
|
737
|
-
" var
|
|
738
|
-
" if(
|
|
1024
|
+
" n.classList.toggle('hide',!hit);",
|
|
1025
|
+
" var reason=n.querySelector('.fb-nav-reason');",
|
|
1026
|
+
" if(!reason)return;",
|
|
1027
|
+
" if(term&&hit){var snip=snippetFor(raw,term);reason.innerHTML=snip;reason.classList.toggle('hide',!snip);}",
|
|
1028
|
+
" else{reason.innerHTML=n.getAttribute('data-default-reason')||'';reason.classList.toggle('hide',!reason.innerHTML);}",
|
|
739
1029
|
" });",
|
|
740
1030
|
"});}",
|
|
741
|
-
"
|
|
742
|
-
"
|
|
743
|
-
"
|
|
744
|
-
"
|
|
745
|
-
"
|
|
1031
|
+
"",
|
|
1032
|
+
"// keyboard: j/k/arrows move rail selection, / focuses search, Esc blurs/closes",
|
|
1033
|
+
"function visibleIds(){return navItems.filter(function(n){return !n.classList.contains('hide');}).map(function(n){return n.getAttribute('data-target');});}",
|
|
1034
|
+
"function currentId(){var v=document.querySelector('.fb-view:not([hidden])');return v?v.id.replace('view-',''):'today';}",
|
|
1035
|
+
"document.addEventListener('keydown',function(ev){",
|
|
1036
|
+
" if((ev.metaKey||ev.ctrlKey)&&(ev.key==='k'||ev.key==='K')){ev.preventDefault();openPalette();return;}",
|
|
1037
|
+
" if(paletteIsOpen()){if(ev.key==='Escape'){ev.preventDefault();closePalette();}return;}",
|
|
1038
|
+
" var t=ev.target,typing=t&&(t.tagName==='INPUT'||t.tagName==='TEXTAREA'||t.isContentEditable);",
|
|
1039
|
+
" if(typing){if(ev.key==='Escape')t.blur();return;}",
|
|
1040
|
+
" if(ev.key==='/'){ev.preventDefault();if(searchInput)searchInput.focus();return;}",
|
|
1041
|
+
" var down=ev.key==='ArrowDown'||ev.key==='j',up=ev.key==='ArrowUp'||ev.key==='k';",
|
|
1042
|
+
" if(down||up){",
|
|
1043
|
+
" ev.preventDefault();",
|
|
1044
|
+
" var ids=visibleIds();",
|
|
1045
|
+
" var idx=ids.indexOf(currentId());",
|
|
1046
|
+
" var next=ids[Math.min(ids.length-1,Math.max(0,idx+(down?1:-1)))];",
|
|
1047
|
+
" if(next)selectView(next);",
|
|
1048
|
+
" }",
|
|
746
1049
|
"});",
|
|
747
|
-
|
|
748
|
-
"
|
|
749
|
-
"
|
|
750
|
-
"
|
|
1050
|
+
"",
|
|
1051
|
+
"// command palette: search-filterable nav (today + each client + theme toggle)",
|
|
1052
|
+
"var paletteBackdrop=document.getElementById('fb-palette-backdrop');",
|
|
1053
|
+
"var paletteInput=document.getElementById('fb-palette-input');",
|
|
1054
|
+
"var paletteInner=document.querySelector('.fb-palette');",
|
|
1055
|
+
"var paletteItems=all('.fb-palette-item');",
|
|
1056
|
+
"var pActive=0;",
|
|
1057
|
+
"function paletteIsOpen(){return !!(paletteBackdrop&&paletteBackdrop.classList.contains('open'));}",
|
|
1058
|
+
"function visiblePaletteItems(){return paletteItems.filter(function(it){return !it.classList.contains('hide');});}",
|
|
1059
|
+
"function highlightPalette(){",
|
|
1060
|
+
" var visible=visiblePaletteItems();",
|
|
1061
|
+
" paletteItems.forEach(function(it){it.classList.remove('active');});",
|
|
1062
|
+
" if(visible[pActive]){visible[pActive].classList.add('active');visible[pActive].scrollIntoView({block:'nearest'});}",
|
|
1063
|
+
"}",
|
|
1064
|
+
"function filterPalette(q){",
|
|
1065
|
+
" q=q.toLowerCase();",
|
|
1066
|
+
" paletteItems.forEach(function(it){",
|
|
1067
|
+
" var label=(it.getAttribute('data-label')||'').toLowerCase();",
|
|
1068
|
+
" var kind=(it.getAttribute('data-kind')||'').toLowerCase();",
|
|
1069
|
+
" it.classList.toggle('hide',!(!q||label.indexOf(q)>-1||kind.indexOf(q)>-1));",
|
|
1070
|
+
" });",
|
|
1071
|
+
" pActive=0;highlightPalette();",
|
|
1072
|
+
"}",
|
|
1073
|
+
"function openPalette(){",
|
|
1074
|
+
" if(!paletteBackdrop)return;",
|
|
1075
|
+
" paletteBackdrop.classList.add('open');",
|
|
1076
|
+
" if(paletteInput){paletteInput.value='';paletteInput.focus();}",
|
|
1077
|
+
" filterPalette('');",
|
|
1078
|
+
"}",
|
|
1079
|
+
"function closePalette(){if(paletteBackdrop)paletteBackdrop.classList.remove('open');}",
|
|
1080
|
+
"function runActive(){",
|
|
1081
|
+
" var it=visiblePaletteItems()[pActive];",
|
|
1082
|
+
" if(!it)return;",
|
|
1083
|
+
" var target=it.getAttribute('data-target');",
|
|
1084
|
+
" if(target==='__theme__')toggleTheme();",
|
|
1085
|
+
" else if(target)selectView(target);",
|
|
1086
|
+
" closePalette();",
|
|
1087
|
+
"}",
|
|
1088
|
+
"if(paletteBackdrop)paletteBackdrop.addEventListener('click',function(ev){if(ev.target===paletteBackdrop)closePalette();});",
|
|
1089
|
+
"if(paletteInner)paletteInner.addEventListener('click',function(ev){ev.stopPropagation();});",
|
|
1090
|
+
"var paletteBtn=document.getElementById('fb-palette-btn');",
|
|
1091
|
+
"if(paletteBtn)paletteBtn.addEventListener('click',openPalette);",
|
|
1092
|
+
"paletteItems.forEach(function(it){",
|
|
1093
|
+
" it.addEventListener('click',function(){pActive=visiblePaletteItems().indexOf(it);runActive();});",
|
|
1094
|
+
" it.addEventListener('mouseenter',function(){var v=visiblePaletteItems();var i=v.indexOf(it);if(i>-1){pActive=i;highlightPalette();}});",
|
|
751
1095
|
"});",
|
|
752
|
-
|
|
1096
|
+
"if(paletteInput){",
|
|
1097
|
+
" paletteInput.addEventListener('input',function(){filterPalette(paletteInput.value);});",
|
|
1098
|
+
" paletteInput.addEventListener('keydown',function(ev){",
|
|
1099
|
+
" if(ev.key==='Escape'){closePalette();return;}",
|
|
1100
|
+
" if(ev.key==='ArrowDown'){ev.preventDefault();pActive=Math.min(visiblePaletteItems().length-1,pActive+1);highlightPalette();return;}",
|
|
1101
|
+
" if(ev.key==='ArrowUp'){ev.preventDefault();pActive=Math.max(0,pActive-1);highlightPalette();return;}",
|
|
1102
|
+
" if(ev.key==='Enter'){ev.preventDefault();runActive();}",
|
|
1103
|
+
" });",
|
|
1104
|
+
"}",
|
|
1105
|
+
"",
|
|
1106
|
+
"// theme toggle - local only, no network; pre-paint script in <head> avoids a flash",
|
|
753
1107
|
"var themeBtn=document.getElementById('fde-theme-btn');",
|
|
754
1108
|
"function currentTheme(){return document.documentElement.getAttribute('data-fde-theme')==='dark'?'dark':'light';}",
|
|
755
|
-
"function setThemeLabel(){if(themeBtn)themeBtn.textContent=(currentTheme()==='dark'?'light':'dark')
|
|
756
|
-
"
|
|
757
|
-
"if(themeBtn){themeBtn.addEventListener('click',function(){",
|
|
1109
|
+
"function setThemeLabel(){if(themeBtn)themeBtn.textContent=(currentTheme()==='dark'?'light':'dark');}",
|
|
1110
|
+
"function toggleTheme(){",
|
|
758
1111
|
" var next=currentTheme()==='dark'?'light':'dark';",
|
|
759
|
-
" try{localStorage.setItem('fde-fieldbook-theme',next);}catch(
|
|
1112
|
+
" try{localStorage.setItem('fde-fieldbook-theme',next);}catch(e){}",
|
|
760
1113
|
" document.documentElement.setAttribute('data-fde-theme',next);",
|
|
761
1114
|
" setThemeLabel();",
|
|
762
|
-
"}
|
|
1115
|
+
"}",
|
|
1116
|
+
"setThemeLabel();",
|
|
1117
|
+
"if(themeBtn)themeBtn.addEventListener('click',toggleTheme);",
|
|
1118
|
+
"})();",
|
|
763
1119
|
].join('\n')
|
|
764
1120
|
}
|
|
765
1121
|
|
|
1122
|
+
// ---- HTML builders (one per fieldbook widget) - kept small and named so the
|
|
1123
|
+
// structured extractors above and the markup below stay easy to trace. ----
|
|
1124
|
+
|
|
1125
|
+
function railItemHtml(e) {
|
|
1126
|
+
const dotClass = dotClassFor(e.signals.trust)
|
|
1127
|
+
const touchedClass = e.quiet ? 't-amber' : 't-faint'
|
|
1128
|
+
const preview = e.next.length > 58 ? e.next.slice(0, 56) + '…' : e.next
|
|
1129
|
+
const defaultReason = e.signals.trust !== 'green' && preview ? escapeHtml(preview) : ''
|
|
1130
|
+
return `<button class="fb-nav" data-target="eng-${e.slug}" data-search="${e.searchBlob}" data-default-reason="${defaultReason}">
|
|
1131
|
+
<div class="fb-nav-row"><span class="dot dot-sm ${dotClass}"></span><span class="fb-nav-name">${inlineMd(e.name)}</span></div>
|
|
1132
|
+
<div class="fb-nav-meta">${escapeHtml(e.phaseLabel)} · <span class="${touchedClass}">${escapeHtml(e.signals.updated)}</span></div>
|
|
1133
|
+
<div class="fb-nav-reason${defaultReason ? '' : ' hide'}">${defaultReason}</div>
|
|
1134
|
+
</button>`
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
function queueRowHtml(e) {
|
|
1138
|
+
const dotClass = dotClassFor(e.signals.trust)
|
|
1139
|
+
const noAction = !e.hasNext
|
|
1140
|
+
const actionText = noAction ? 'no next action set - open and add one' : e.next
|
|
1141
|
+
const touchedClass = e.quiet ? 't-amber' : 't-faint'
|
|
1142
|
+
return `<div class="fb-row fb-queue-row" data-nav="eng-${e.slug}">
|
|
1143
|
+
<span class="dot dot-md ${dotClass}"></span>
|
|
1144
|
+
<span class="fb-queue-slug">${inlineMd(e.name)}</span>
|
|
1145
|
+
<span class="fb-queue-action${noAction ? ' t-amber' : ''}">${inlineMd(actionText)}</span>
|
|
1146
|
+
<span class="fb-queue-touched ${touchedClass}">${escapeHtml(e.signals.updated)}</span>
|
|
1147
|
+
</div>`
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
function flagRowHtml(e, text, colorClass) {
|
|
1151
|
+
return `<div class="fb-row fb-flag-row" data-nav="eng-${e.slug}">
|
|
1152
|
+
<span class="fb-flag-slug">${inlineMd(e.name)}</span>
|
|
1153
|
+
<span class="fb-flag-text t-${colorClass}">${escapeHtml(text)}</span>
|
|
1154
|
+
</div>`
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
function todayViewHtml({ today, total, attentionCount, highRiskTotal, todayQueue, flagsHtml, hasEngagements }) {
|
|
1158
|
+
if (!hasEngagements) {
|
|
1159
|
+
return `<div id="view-today" class="fb-view">
|
|
1160
|
+
<div class="fb-eyebrow">portfolio</div>
|
|
1161
|
+
<h1 class="fb-h1">Today</h1>
|
|
1162
|
+
<p class="empty">No engagements yet. Start one with <code>fde resume --init <client-name></code>, then re-run <code>fde dashboard</code>.</p>
|
|
1163
|
+
</div>`
|
|
1164
|
+
}
|
|
1165
|
+
return `<div id="view-today" class="fb-view">
|
|
1166
|
+
<div class="fb-eyebrow">portfolio</div>
|
|
1167
|
+
<h1 class="fb-h1">Today</h1>
|
|
1168
|
+
<div class="fb-meta-line">${escapeHtml(today)} · ${total} engagement${total === 1 ? '' : 's'} · ${attentionCount} need you · ${highRiskTotal} high risk${highRiskTotal === 1 ? '' : 's'} open</div>
|
|
1169
|
+
<div class="fb-block">
|
|
1170
|
+
<div class="fb-sec">Queue — next action per client, worst first</div>
|
|
1171
|
+
${todayQueue}
|
|
1172
|
+
</div>
|
|
1173
|
+
${flagsHtml ? `<div class="fb-block">
|
|
1174
|
+
<div class="fb-sec">Flags</div>
|
|
1175
|
+
${flagsHtml}
|
|
1176
|
+
</div>` : ''}
|
|
1177
|
+
</div>`
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
function clientViewHtml(e) {
|
|
1181
|
+
const dotClass = dotClassFor(e.signals.trust)
|
|
1182
|
+
const sectorLine = [
|
|
1183
|
+
e.overlay ? escapeHtml(e.overlay) : '',
|
|
1184
|
+
escapeHtml(e.phaseLabel),
|
|
1185
|
+
e.days != null ? `day ${e.days}` : '',
|
|
1186
|
+
`touched ${escapeHtml(e.signals.updated)}`,
|
|
1187
|
+
].filter(Boolean).join(' · ')
|
|
1188
|
+
|
|
1189
|
+
const nowBlock = `<div class="fb-block">
|
|
1190
|
+
<div class="fb-sec">Now</div>
|
|
1191
|
+
<div class="fb-now-action${e.hasNext ? '' : ' t-amber'}">${e.hasNext ? inlineMd(e.next) : 'next action not set'}</div>
|
|
1192
|
+
${e.lastSession ? `<div class="fb-now-session">${inlineMd(e.lastSession)}</div>` : ''}
|
|
1193
|
+
</div>`
|
|
1194
|
+
|
|
1195
|
+
// Brief vs reality is the whole point of "discover" - what they said they
|
|
1196
|
+
// needed vs what's actually true. Squeezed onto one truncated line, that
|
|
1197
|
+
// contrast disappears. Each gets its own line, its own room to finish a
|
|
1198
|
+
// thought, not a race to fit before an ellipsis.
|
|
1199
|
+
const whyBlock = (e.brief || e.reality) ? `<div class="fb-block">
|
|
1200
|
+
<div class="fb-sec">Why</div>
|
|
1201
|
+
${e.brief ? `<p class="fb-why"><span class="t-faint">What they asked for:</span> ${inlineMd(e.brief)}</p>` : ''}
|
|
1202
|
+
${e.reality ? `<p class="fb-why fb-why-reality"><span class="fb-accent-label">What's actually true:</span> ${inlineMd(e.reality)}</p>` : ''}
|
|
1203
|
+
</div>` : ''
|
|
1204
|
+
|
|
1205
|
+
// Vitals: a fixed field-facing gut-check panel, not a Movement block that
|
|
1206
|
+
// only exists when text mining finds numbers. Every row here is already
|
|
1207
|
+
// computed elsewhere in this file for other purposes (status/dashboard
|
|
1208
|
+
// triage, receipts, signals) - never a new fabricated field, just the
|
|
1209
|
+
// existing facts surfaced where an FDE's eye lands first. Sits beside
|
|
1210
|
+
// Now/Why so that column's natural reading width doesn't leave the top of
|
|
1211
|
+
// the page empty on a wide screen, and carries enough real rows to earn
|
|
1212
|
+
// roughly the same height instead of floating short beside a tall column.
|
|
1213
|
+
// Plain English, not fdeops shorthand - a junior FDE reading this for the
|
|
1214
|
+
// first time gets the same clear meaning as someone who wrote the CLI.
|
|
1215
|
+
// "signal" (the --signal flag's own word) becomes "trust"; a bare day
|
|
1216
|
+
// count becomes "started: 3 days ago" in the same relative-time phrasing
|
|
1217
|
+
// as everything else here, so there's one pattern to learn, not several.
|
|
1218
|
+
const dotGlyph = sig => sig === 'green' ? '●' : sig === 'red' ? '○' : '■' // filled circle / hollow ring / filled square - same shapes as the People list below
|
|
1219
|
+
const signalColor = sig => sig === 'green' ? '#12885c' : sig === 'red' ? '#b23e2b' : '#a56a19'
|
|
1220
|
+
const teamStatus = e.stakeholders.length
|
|
1221
|
+
? ['green', 'amber', 'red'].map(sig => e.stakeholders.filter(p => p.signal === sig).length)
|
|
1222
|
+
.map((n, i) => n ? `<span style="color:${signalColor(['green', 'amber', 'red'][i])}">${dotGlyph(['green', 'amber', 'red'][i])} ${n}</span>` : null)
|
|
1223
|
+
.filter(Boolean).join(' ')
|
|
1224
|
+
: ''
|
|
1225
|
+
const vitalsRows = [
|
|
1226
|
+
['trust', trustWord(e.signals.trust), dotClass],
|
|
1227
|
+
e.signals.signalAge != null ? ['trust confirmed', e.signals.signalAge === 0 ? 'today' : `${e.signals.signalAge} days ago${e.signals.stale ? ' - recheck' : ''}`, e.signals.stale ? 'red' : ''] : null,
|
|
1228
|
+
['phase', e.phaseLabel, ''],
|
|
1229
|
+
e.days != null ? ['started', e.days === 0 ? 'today' : `${e.days} days ago`, ''] : null,
|
|
1230
|
+
['last updated', e.signals.updated, e.quiet ? 'amber' : ''],
|
|
1231
|
+
e.log.length ? ['last note', formatLogDate(e.log[0].date), ''] : null,
|
|
1232
|
+
e.risks.length ? ['open risks', `${e.risks.length}${e.highRisks ? ` (${e.highRisks} urgent)` : ''}`, e.highRisks ? 'red' : ''] : null,
|
|
1233
|
+
e.stakeholders.length ? ['people', `${e.stakeholders.length}`, ''] : null,
|
|
1234
|
+
].filter(Boolean)
|
|
1235
|
+
const vitalsBlock = `<div class="fb-vitals">
|
|
1236
|
+
${vitalsRows.map(([label, val, tone]) => `<div class="fb-vital-row"><span class="fb-vital-label">${escapeHtml(label)}</span><span class="fb-vital-val${tone ? ' t-' + tone : ''}">${escapeHtml(val)}</span></div>`).join('\n')}
|
|
1237
|
+
${teamStatus ? `<div class="fb-vital-row"><span class="fb-vital-label">team status</span><span class="fb-vital-val">${teamStatus}</span></div>` : ''}
|
|
1238
|
+
${e.stats.length ? `<div class="fb-vital-div"></div>${e.stats.map(s => `<div class="fb-vital-row"><span class="fb-vital-label">${inlineMd(s.label)}</span><span class="fb-vital-val">${inlineMd(s.from)} <span class="fb-arrow">→</span> <span class="fb-stat-to">${inlineMd(s.to)}</span></span></div>`).join('\n')}` : ''}
|
|
1239
|
+
</div>`
|
|
1240
|
+
|
|
1241
|
+
const peopleBlock = e.stakeholders.length ? `<div class="fb-block">
|
|
1242
|
+
<div class="fb-sec">People</div>
|
|
1243
|
+
<div class="fb-list">
|
|
1244
|
+
${e.stakeholders.map(p => `<div class="fb-row fb-person">
|
|
1245
|
+
<span class="dot dot-sm ${p.signal}" title="${trustWord(p.signal)}"></span>
|
|
1246
|
+
<span class="fb-person-name">${inlineMd(p.name)}</span>
|
|
1247
|
+
<span class="fb-person-role">${inlineMd(p.role)}</span>
|
|
1248
|
+
<span class="fb-person-note">${inlineMd(p.note)}</span>
|
|
1249
|
+
</div>`).join('\n')}
|
|
1250
|
+
</div>
|
|
1251
|
+
</div>` : ''
|
|
1252
|
+
|
|
1253
|
+
const riskBlock = e.risks.length ? `<div class="fb-block">
|
|
1254
|
+
<div class="fb-sec-row"><div class="fb-sec">Risk</div><span class="fb-count">${e.risks.length} open</span></div>
|
|
1255
|
+
<div class="fb-list">
|
|
1256
|
+
${e.risks.map(r => `<div class="fb-row fb-risk">
|
|
1257
|
+
<span class="fb-risk-sev t-${r.severity === 'high' ? 'red' : 'amber'}">${escapeHtml(r.severity)}</span>
|
|
1258
|
+
<span class="fb-risk-text">${inlineMd(r.text)}</span>
|
|
1259
|
+
</div>`).join('\n')}
|
|
1260
|
+
</div>
|
|
1261
|
+
</div>` : ''
|
|
1262
|
+
|
|
1263
|
+
const logBlock = e.log.length ? `<div class="fb-block">
|
|
1264
|
+
<div class="fb-sec">Log</div>
|
|
1265
|
+
<div class="fb-list">
|
|
1266
|
+
${e.log.map(g => `<div class="fb-row fb-log">
|
|
1267
|
+
<span class="fb-log-date">${escapeHtml(formatLogDate(g.date))}</span>
|
|
1268
|
+
<span class="fb-log-kind t-${g.kind === 'receipt' ? 'green' : g.kind === 'decision' ? 'accent' : 'faint'}">${escapeHtml(g.kind)}</span>
|
|
1269
|
+
<span class="fb-log-text">${inlineMd(g.text)}</span>
|
|
1270
|
+
</div>`).join('\n')}
|
|
1271
|
+
</div>
|
|
1272
|
+
</div>` : ''
|
|
1273
|
+
|
|
1274
|
+
// reference docs (success/terrain/trust-profile) - collapsed by default,
|
|
1275
|
+
// never hidden entirely: trust-profile.md carries the data boundary
|
|
1276
|
+
const moreBlock = e.moreSections.length ? `<div class="fb-block">
|
|
1277
|
+
${e.moreSections.map(s => `<details class="fb-more"><summary class="fb-sec fb-more-sum">${escapeHtml(s.title)}</summary><div class="fb-more-body">${s.html}</div></details>`).join('\n')}
|
|
1278
|
+
</div>` : ''
|
|
1279
|
+
|
|
1280
|
+
// People + Risk pair naturally (who's involved / what's at stake) and read
|
|
1281
|
+
// well side by side on a wide screen - a single 760px column left half the
|
|
1282
|
+
// window empty. Stats stays full width (it's already a wrapping strip of
|
|
1283
|
+
// small tiles that benefits from horizontal room); Log stays full width
|
|
1284
|
+
// (a chronological list reads better long than squeezed into a column).
|
|
1285
|
+
const pairedBlock = (peopleBlock || riskBlock) ? `<div class="fb-grid-wrap">${peopleBlock}${riskBlock}</div>` : ''
|
|
1286
|
+
|
|
1287
|
+
return `<div id="view-eng-${e.slug}" class="fb-view" hidden>
|
|
1288
|
+
<div class="fb-eyebrow">.fde/${escapeHtml(e.slug)}</div>
|
|
1289
|
+
<div class="fb-title-row">
|
|
1290
|
+
<h1 class="fb-h1">${inlineMd(e.name)}</h1>
|
|
1291
|
+
<span class="fb-trust"><span class="dot dot-lg ${dotClass}"></span><span class="t-${dotClass}">${trustWord(e.signals.trust)}</span></span>
|
|
1292
|
+
</div>
|
|
1293
|
+
<div class="fb-meta-line">${sectorLine}</div>
|
|
1294
|
+
<div class="fb-top-grid">
|
|
1295
|
+
<div>${nowBlock}${whyBlock}</div>
|
|
1296
|
+
${vitalsBlock}
|
|
1297
|
+
</div>
|
|
1298
|
+
${pairedBlock}${logBlock}${moreBlock}
|
|
1299
|
+
</div>`
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
function paletteItemsHtml(ordered) {
|
|
1303
|
+
const items = [
|
|
1304
|
+
{ kind: 'view', label: 'today', hint: 'portfolio queue', target: 'today' },
|
|
1305
|
+
...ordered.map(e => ({ kind: 'open', label: e.slug, hint: trustWord(e.signals.trust), target: 'eng-' + e.slug })),
|
|
1306
|
+
{ kind: 'action', label: 'toggle theme', hint: 'light / dark', target: '__theme__' },
|
|
1307
|
+
]
|
|
1308
|
+
return items.map(it => `<div class="fb-palette-item" data-target="${escapeHtml(it.target)}" data-label="${escapeHtml(it.label)}" data-kind="${escapeHtml(it.kind)}">
|
|
1309
|
+
<span class="fb-palette-kind">${escapeHtml(it.kind)}</span>
|
|
1310
|
+
<span class="fb-palette-label">${escapeHtml(it.label)}</span>
|
|
1311
|
+
<span class="fb-palette-hint">${escapeHtml(it.hint)}</span>
|
|
1312
|
+
</div>`).join('\n')
|
|
1313
|
+
}
|
|
1314
|
+
|
|
766
1315
|
function cmdDashboard(args) {
|
|
767
1316
|
const outIdx = args.indexOf('--out')
|
|
768
1317
|
const outPath = outIdx !== -1 && args[outIdx + 1]
|
|
@@ -771,131 +1320,117 @@ function cmdDashboard(args) {
|
|
|
771
1320
|
const engagements = gatherEngagements()
|
|
772
1321
|
const counts = { green: 0, amber: 0, RED: 0 }
|
|
773
1322
|
engagements.forEach(e => { counts[e.signals.trust]++ })
|
|
774
|
-
const
|
|
775
|
-
const stamp = now.toISOString().slice(0, 16).replace('T', ' ') + ' UTC'
|
|
1323
|
+
const today = formatToday(new Date())
|
|
776
1324
|
|
|
777
|
-
// enrich each engagement
|
|
1325
|
+
// enrich each engagement with everything the read-only fieldbook renders -
|
|
1326
|
+
// next action + last-session excerpt (reused from context.md), brief/reality
|
|
1327
|
+
// one-liners, sector/overlay, days elapsed, and the four structured widgets.
|
|
778
1328
|
engagements.forEach(e => {
|
|
779
|
-
const ctx =
|
|
1329
|
+
const ctx = readClean(e.dir, 'context.md')
|
|
780
1330
|
e.next = (sectionBody(ctx, 'Next action').split('\n').find(l => l.trim()) || '').trim()
|
|
781
1331
|
e.hasNext = !!e.next
|
|
782
|
-
e.
|
|
1332
|
+
e.lastSession = firstLine(sectionBody(ctx, 'Current state'), 240)
|
|
1333
|
+
// 220, not 140 - now that brief/reality each get their own full-width
|
|
1334
|
+
// line instead of sharing one, a shorter cap just meant more sentences
|
|
1335
|
+
// cut off mid-thought for no reason.
|
|
1336
|
+
e.brief = firstLine(readClean(e.dir, 'brief.md'), 220)
|
|
1337
|
+
e.reality = firstLine(readClean(e.dir, 'reality.md'), 220)
|
|
1338
|
+
e.overlay = detectOverlay(e.dir)
|
|
1339
|
+
e.days = daysElapsed(e.dir)
|
|
1340
|
+
e.phaseLabel = phaseLabel(e.signals.phase)
|
|
1341
|
+
e.stakeholders = extractStakeholders(e.dir)
|
|
1342
|
+
e.risks = extractRisks(e.dir)
|
|
1343
|
+
e.log = extractLog(e.dir)
|
|
1344
|
+
e.stats = extractStats(e.dir)
|
|
1345
|
+
e.highRisks = e.risks.filter(r => r.severity === 'high').length
|
|
1346
|
+
e.quiet = e.signals.ageDays !== Infinity && e.signals.ageDays >= 3
|
|
1347
|
+
e.slug = slugify(e.name)
|
|
1348
|
+
// reference documents, not logs - shown collapsed in a "More" block so
|
|
1349
|
+
// trust-profile.md (sacred data, AI policy) stays visible, never dropped
|
|
1350
|
+
e.moreSections = [
|
|
1351
|
+
['success.md', 'Success & scope'],
|
|
1352
|
+
['terrain.md', 'Terrain'],
|
|
1353
|
+
['trust-profile.md', 'Trust profile'],
|
|
1354
|
+
].map(([f, title]) => [title, readClean(e.dir, f)])
|
|
1355
|
+
.filter(([, md]) => hasRealContent(md))
|
|
1356
|
+
.map(([title, md]) => ({ title, html: mdBlockHtml(md) }))
|
|
1357
|
+
e.searchBlob = escapeHtml([
|
|
1358
|
+
e.name, e.next, e.lastSession, e.reality, e.brief,
|
|
1359
|
+
...e.log.map(g => g.text), ...e.risks.map(r => r.text),
|
|
1360
|
+
...e.stakeholders.map(p => `${p.name} ${p.role} ${p.note}`),
|
|
1361
|
+
...e.moreSections.map(s => s.title),
|
|
1362
|
+
].join(' ').toLowerCase())
|
|
783
1363
|
})
|
|
784
1364
|
|
|
785
|
-
//
|
|
1365
|
+
// rail + Today queue share one order: trust-first (red, amber, green)
|
|
786
1366
|
const tierRank = { RED: 0, amber: 1, green: 2 }
|
|
787
|
-
const ordered = engagements.slice().sort((a, b) =>
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|| ((b.signals.ageDays || 0) - (a.signals.ageDays || 0))
|
|
791
|
-
|| a.name.localeCompare(b.name))
|
|
792
|
-
const reds = ordered.filter(e => e.signals.trust === 'RED')
|
|
793
|
-
const rest = ordered.filter(e => e.signals.trust !== 'RED')
|
|
794
|
-
|
|
795
|
-
// one directive line: where the FDE starts today, and why
|
|
796
|
-
const lead = reds[0] || rest.find(e => e.signals.trust === 'amber' && e.hasNext) || rest[0]
|
|
797
|
-
let directive = '', directiveClass = 'directive'
|
|
798
|
-
if (lead) {
|
|
799
|
-
const why = stripPrivate(lead.signals.topRisk || lead.next || (lead.signals.trust === 'RED' ? 'trust signal is red' : 'oldest open thread')).trim().slice(0, 90)
|
|
800
|
-
const age = lead.signals.ageDays != null ? `${lead.signals.ageDays}d since touched` : ''
|
|
801
|
-
directive = `Start here: <b>${inlineMd(lead.name)}</b> - ${inlineMd(why)}${age ? ' · ' + age : ''}`
|
|
802
|
-
directiveClass = reds.length ? 'directive' : 'directive amber'
|
|
803
|
-
}
|
|
1367
|
+
const ordered = engagements.slice().sort((a, b) => tierRank[a.signals.trust] - tierRank[b.signals.trust])
|
|
1368
|
+
const attentionCount = engagements.filter(e => e.signals.trust !== 'green').length
|
|
1369
|
+
const highRiskTotal = engagements.reduce((n, e) => n + e.highRisks, 0)
|
|
804
1370
|
|
|
805
|
-
|
|
806
|
-
const
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
const emptyState = '<p class="empty">No engagements yet. Start one with <code>fde resume --init <client-name></code>, then re-run <code>fde dashboard</code>.</p>'
|
|
870
|
-
|
|
871
|
-
const html = [
|
|
872
|
-
'<!doctype html><html lang="en"><head><meta charset="utf-8">',
|
|
873
|
-
'<meta name="viewport" content="width=device-width,initial-scale=1">',
|
|
874
|
-
// pre-paint theme: read the one localStorage key before first render so there is no flash.
|
|
875
|
-
// No network calls - this file still opens and works fully offline.
|
|
876
|
-
'<script>try{var t=localStorage.getItem("fde-fieldbook-theme");if(t==="dark"||(!t&&window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches))document.documentElement.setAttribute("data-fde-theme","dark");}catch(e){}</script>',
|
|
877
|
-
'<title>FDE Fieldbook</title><style>' + dashStyles() + '</style></head><body>',
|
|
878
|
-
'<header><div class="inner"><div class="brand"><h1>FDE Fieldbook</h1>',
|
|
879
|
-
`<span class="tagline">${engagements.length} engagement${engagements.length === 1 ? '' : 's'}</span></div>`,
|
|
880
|
-
'<div class="stats">',
|
|
881
|
-
`<span class="stat"><span class="sdot green"></span> <b>${counts.green}</b> green</span>`,
|
|
882
|
-
`<span class="stat"><span class="sdot amber"></span> <b>${counts.amber}</b> amber</span>`,
|
|
883
|
-
`<span class="stat"><span class="sdot red"></span> <b>${counts.RED}</b> red</span>`,
|
|
884
|
-
'<button id="fde-theme-btn" class="theme-toggle" type="button">dark mode</button>',
|
|
885
|
-
'</div></div></header>',
|
|
886
|
-
'<div class="wrap">',
|
|
887
|
-
engagements.length ? '<div class="search-wrap"><svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg><input id="q" class="search" placeholder="Search across all engagements..."></div>' : '',
|
|
888
|
-
engagements.length ? '<span class="search-hint">press <kbd>/</kbd> to search - a matching card shows why, right on the card</span>' : '',
|
|
889
|
-
directive ? `<div class="${directiveClass}"><span class="directive-dot"></span><span>${directive}</span></div>` : '',
|
|
890
|
-
reds.length ? '<h2 class="section">Needs attention</h2><div class="attn-stack">' + attention + '</div>' : '',
|
|
891
|
-
engagements.length ? `<h2 class="section">${reds.length ? 'Rest of portfolio' : 'Portfolio'}</h2>` : '',
|
|
892
|
-
engagements.length ? (rest.length ? `<div class="grid">${cards}</div>` : '<p class="empty">Every active engagement needs attention - see above.</p>') : emptyState,
|
|
893
|
-
engagements.length ? '<h2 class="section">Engagement detail</h2>' + details : '',
|
|
894
|
-
'</div>',
|
|
895
|
-
`<footer>fdeops · fieldbook is a deterministic render of your <code>.fde/</code> memory - edit the markdown, re-run <code>fde dashboard</code>. Source of truth stays in the files.</footer>`,
|
|
896
|
-
'<script>' + dashScript() + '</script>',
|
|
897
|
-
'</body></html>',
|
|
898
|
-
].join('\n')
|
|
1371
|
+
const railItems = ordered.map(railItemHtml).join('\n')
|
|
1372
|
+
const todayQueue = ordered.map(queueRowHtml).join('\n') || '<p class="empty">No engagements yet.</p>'
|
|
1373
|
+
const flagRows = []
|
|
1374
|
+
ordered.forEach(e => {
|
|
1375
|
+
if (e.quiet) flagRows.push(flagRowHtml(e, `quiet - last touched ${e.signals.updated}`, 'amber'))
|
|
1376
|
+
if (e.highRisks) flagRows.push(flagRowHtml(e, `${e.highRisks} high risk${e.highRisks > 1 ? 's' : ''} open`, 'red'))
|
|
1377
|
+
})
|
|
1378
|
+
|
|
1379
|
+
const todayView = todayViewHtml({
|
|
1380
|
+
today, total: engagements.length, attentionCount, highRiskTotal,
|
|
1381
|
+
todayQueue, flagsHtml: flagRows.join('\n'), hasEngagements: engagements.length > 0,
|
|
1382
|
+
})
|
|
1383
|
+
const clientViews = ordered.map(clientViewHtml).join('\n')
|
|
1384
|
+
const paletteItems = paletteItemsHtml(ordered)
|
|
1385
|
+
|
|
1386
|
+
const html = `<!doctype html><html lang="en"><head><meta charset="utf-8">
|
|
1387
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
1388
|
+
<script>try{var t=localStorage.getItem("fde-fieldbook-theme");if(t==="dark"||(!t&&window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches))document.documentElement.setAttribute("data-fde-theme","dark");}catch(e){}</script>
|
|
1389
|
+
<title>FDE Fieldbook</title><style>${dashStyles()}</style></head><body>
|
|
1390
|
+
<div class="fb-app">
|
|
1391
|
+
<header class="fb-header">
|
|
1392
|
+
<div class="fb-brand">
|
|
1393
|
+
<span class="fb-wordmark">FDEOPS</span>
|
|
1394
|
+
<span class="fb-tagline">fieldbook</span>
|
|
1395
|
+
${engagements.length ? `<span class="fb-need">${attentionCount}/${engagements.length} need you</span>` : ''}
|
|
1396
|
+
</div>
|
|
1397
|
+
<div class="fb-spacer"></div>
|
|
1398
|
+
<span class="fb-today">${escapeHtml(today)}</span>
|
|
1399
|
+
<button id="fb-palette-btn" class="fb-btn" type="button" title="Command palette (Ctrl/Cmd+K)">⌘K</button>
|
|
1400
|
+
<button id="fde-theme-btn" class="fb-btn" type="button">dark</button>
|
|
1401
|
+
</header>
|
|
1402
|
+
<div class="fb-body">
|
|
1403
|
+
<aside class="fb-rail">
|
|
1404
|
+
<div class="fb-rail-search"><input id="fb-search" class="fb-search" placeholder="search clients, notes, risks…" spellcheck="false"></div>
|
|
1405
|
+
<div class="fb-rail-list fb-scroll">
|
|
1406
|
+
<button class="fb-nav" data-target="today">
|
|
1407
|
+
<div class="fb-nav-row"><span class="fb-nav-today">today</span>${engagements.length ? `<span class="fb-nav-count">${attentionCount} need you</span>` : ''}</div>
|
|
1408
|
+
</button>
|
|
1409
|
+
${railItems}
|
|
1410
|
+
</div>
|
|
1411
|
+
</aside>
|
|
1412
|
+
<main class="fb-main fb-scroll">
|
|
1413
|
+
<div class="fb-main-inner">
|
|
1414
|
+
${todayView}
|
|
1415
|
+
${clientViews}
|
|
1416
|
+
<div class="fb-hints">
|
|
1417
|
+
<span><span class="t-soft">↑↓ / j k</span> client</span>
|
|
1418
|
+
<span><span class="t-soft">/</span> search</span>
|
|
1419
|
+
<span><span class="t-soft">⌘K</span> palette</span>
|
|
1420
|
+
<span class="fb-hints-spacer">deterministic render of .fde/ - edit the markdown, re-run fde dashboard</span>
|
|
1421
|
+
</div>
|
|
1422
|
+
</div>
|
|
1423
|
+
</main>
|
|
1424
|
+
</div>
|
|
1425
|
+
<div id="fb-palette-backdrop" class="fb-palette-backdrop">
|
|
1426
|
+
<div class="fb-palette">
|
|
1427
|
+
<input id="fb-palette-input" class="fb-palette-input" placeholder="jump to client or action…" spellcheck="false">
|
|
1428
|
+
<div class="fb-palette-list fb-scroll">${paletteItems}</div>
|
|
1429
|
+
</div>
|
|
1430
|
+
</div>
|
|
1431
|
+
</div>
|
|
1432
|
+
<script>${dashScript()}</script>
|
|
1433
|
+
</body></html>`
|
|
899
1434
|
|
|
900
1435
|
fs.mkdirSync(path.dirname(outPath), { recursive: true })
|
|
901
1436
|
fs.writeFileSync(outPath, html)
|