fdeops 3.5.6 → 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/bin/fde.js CHANGED
@@ -13,6 +13,7 @@
13
13
  * fde resume --full same, but the complete context.md (no bound)
14
14
  * fde resume --init <n> create + bind an engagement for this workspace
15
15
  * fde log <type> <text> structured append (decision|risk|delivery|contact)
16
+ * fde debrief [file] meeting notes → structured memory (stdin if no file)
16
17
  * fde receipts <term> "what did we agree?" - search memory with dates
17
18
  * fde capture session-end snapshot → context.md (hooks use this)
18
19
  * fde status portfolio across ~/fde-engagements (red/amber/green)
@@ -28,6 +29,8 @@ const ENGAGEMENTS_ROOT = path.join(HOME, 'fde-engagements')
28
29
  const REGISTRY = path.join(ENGAGEMENTS_ROOT, '.registry')
29
30
  const CODE_EXT = ['.js', '.ts', '.tsx', '.jsx', '.py', '.java', '.go', '.rb', '.cs', '.php']
30
31
  const CONF_EXT = CODE_EXT.concat(['.env', '.yaml', '.yml', '.json'])
32
+ // one routing table for structured appends - cmdLog and cmdDebrief share it
33
+ const LOG_FILES = { decision: 'decisions.md', risk: 'risks.md', delivery: 'delivery.md', contact: 'stakeholders.md' }
31
34
 
32
35
  // constant-command runner - never receives user input
33
36
  function sh(cmd, cwd) {
@@ -129,6 +132,10 @@ function readEng(eng, f) {
129
132
  try { return fs.readFileSync(path.join(eng, f), 'utf8') } catch (_) { return '' }
130
133
  }
131
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
+
132
139
  // Pull the body under a "## Heading" up to the next "##" (or EOF).
133
140
  function sectionBody(md, heading) {
134
141
  const lines = md.split('\n')
@@ -143,12 +150,34 @@ function sectionBody(md, heading) {
143
150
  }
144
151
 
145
152
  // phase / trust / top risk / freshness - identical heuristic for status + dashboard.
153
+ // Trust resolution: structured [signal:red|amber|green] tokens in stakeholders.md
154
+ // (written by `fde log contact --signal` and `fde debrief`) win - the latest dated
155
+ // one. Older than 21 days → stale: shown with a "?" marker + age so a forgotten
156
+ // signal never silently drives triage. The keyword grep survives only as the
157
+ // zero-effort floor when NO token exists anywhere - prose like "escalated to CTO,
158
+ // resolved amicably" must not flip a client amber forever.
146
159
  function computeSignals(eng) {
147
160
  const ctx = readEng(eng, 'context.md'); const stake = readEng(eng, 'stakeholders.md'); const risks = readEng(eng, 'risks.md')
148
161
  const phase = (ctx.match(/phase[:* ]+\**([a-z-]+)/i) || [])[1] || '?'
149
- const sLines = stake.split('\n').filter(l => !(/green/i.test(l) && /red|amber/i.test(l)))
150
- const trust = sLines.some(l => /\bred\b/i.test(l)) ? 'RED'
151
- : sLines.some(l => /amber|gone quiet|routing around|escalat/i.test(l)) ? 'amber' : 'green'
162
+ let latest = null
163
+ for (const l of stake.split('\n')) {
164
+ const sm = l.match(/\[signal:(red|amber|green)\]/i)
165
+ if (!sm) continue
166
+ const date = (l.match(/\[(\d{4}-\d{2}-\d{2})\]/) || [])[1] || ''
167
+ if (!latest || date >= latest.date) latest = { date, sig: sm[1].toLowerCase() }
168
+ }
169
+ let trust, signalAge = null, stale = false
170
+ if (latest) {
171
+ trust = latest.sig === 'red' ? 'RED' : latest.sig
172
+ if (latest.date) {
173
+ signalAge = Math.max(0, Math.floor((Date.now() - Date.parse(latest.date)) / 86400000))
174
+ stale = signalAge > 21
175
+ }
176
+ } else {
177
+ const sLines = stake.split('\n').filter(l => !(/green/i.test(l) && /red|amber/i.test(l)))
178
+ trust = sLines.some(l => /\bred\b/i.test(l)) ? 'RED'
179
+ : sLines.some(l => /amber|gone quiet|routing around|escalat/i.test(l)) ? 'amber' : 'green'
180
+ }
152
181
  const topRisk = (risks.split('\n').find(l => {
153
182
  const t = l.trim()
154
183
  return /^[-|]/.test(t) && t.length > 20 && !/^\|?[-\s|]+$/.test(t) &&
@@ -159,7 +188,222 @@ function computeSignals(eng) {
159
188
  ageDays = Math.floor((Date.now() - fs.statSync(path.join(eng, 'context.md')).mtimeMs) / 86400000)
160
189
  updated = ageDays === 0 ? 'today' : `${ageDays}d ago`
161
190
  } catch (_) {}
162
- return { phase, trust, topRisk, updated, ageDays }
191
+ return { phase, trust, signalAge, stale, topRisk, updated, ageDays }
192
+ }
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)
163
407
  }
164
408
 
165
409
  // ---------- commands ----------
@@ -183,6 +427,7 @@ function cmdScan() {
183
427
 
184
428
  // churn × tests = the load-bearing walls
185
429
  out.push('\nHOTSPOTS (churn 90d × test coverage) - handle with care:')
430
+ let firstUntested = ''
186
431
  if (isGit) {
187
432
  const churn = sh("git log --since='90 days ago' --name-only --pretty=format:") || ''
188
433
  const counts = {}
@@ -193,6 +438,7 @@ function cmdScan() {
193
438
  for (const [f, n] of top) {
194
439
  const base = path.basename(f).replace(/\.[^.]+$/, '')
195
440
  const tested = testFiles.some(t => t.includes(base))
441
+ if (!tested && !firstUntested) firstUntested = f
196
442
  out.push(` ${String(n).padStart(3)} commits/90d ${f} ${tested ? '' : '⚠ NO TEST NEIGHBOR'}`)
197
443
  }
198
444
  } else out.push(' (not a git repo - churn unavailable)')
@@ -205,7 +451,10 @@ function cmdScan() {
205
451
 
206
452
  // AI components - they fail silently
207
453
  out.push('\nAI COMPONENTS (no exception fires when these drift):')
208
- const ai = grepFiles(codeFiles, /openai|anthropic|\bllm\b|gpt-|claude|embedding|vector store|inference/i, 10)
454
+ // NOTE: bare "inference" is banned from this regex - TypeScript codebases are
455
+ // full of "type inference" comments and the false positives poison the day-1
456
+ // questions. Model inference only, in explicit forms.
457
+ const ai = grepFiles(codeFiles, /openai|anthropic|\bllm\b|gpt-|claude|embedding|vector store|model inference|inference (?:api|endpoint|server|engine)/i, 10)
209
458
  ai.length ? ai.forEach(h => out.push(` ${h.file}:${h.line} ${h.text}`)) : out.push(' none found')
210
459
 
211
460
  // secrets (redacted)
@@ -216,6 +465,7 @@ function cmdScan() {
216
465
  sec.length
217
466
  ? sec.forEach(h => out.push(` ${h.file}:${h.line} ${h.text.replace(/(['"])([^'"]{4})[^'"]+(['"])/, '$1$2…REDACTED$3')}`))
218
467
  : out.push(' none found')
468
+ out.push(' (grep-grade check - run gitleaks or trufflehog for real secret coverage)')
219
469
 
220
470
  // previous attempts - the political archaeology
221
471
  out.push('\nPREVIOUS ATTEMPTS (ask who ran these, and what happened):')
@@ -229,6 +479,18 @@ function cmdScan() {
229
479
  const testCount = files.filter(f => /test|spec/i.test(f)).length
230
480
  out.push(`\nTEST LANDSCAPE ${testCount} test file(s) across ${codeFiles.length} code files`)
231
481
 
482
+ // day-1 questions - each one earned by a finding above, skipped when empty
483
+ out.push('\nASK ON DAY 1:')
484
+ const asks = []
485
+ if (reverts || readmeHits.length) asks.push('Who ran the previous attempt(s), and what happened to them?')
486
+ if (firstUntested) asks.push(`What breaks when ${firstUntested} changes, and who owns it?`)
487
+ if (ai.length) asks.push(`How would anyone notice if ${ai[0].file}'s model output drifted?`)
488
+ if (sec.length) asks.push('What is the secret-rotation story?')
489
+ if (tmp.length) asks.push("Which of these 'temporary' fixes are now load-bearing contracts?")
490
+ asks.length
491
+ ? asks.slice(0, 5).forEach((q, i) => out.push(` ${i + 1}. ${q}`))
492
+ : out.push(' (clean scan - ask what the last engineer wished they had known)')
493
+
232
494
  out.push('\n' + '-'.repeat(60))
233
495
  out.push("Facts only - interpretation is the FDE's (or @fde's) job.")
234
496
  console.log(out.join('\n'))
@@ -250,11 +512,30 @@ function cmdResume(args) {
250
512
  else if (!fs.existsSync(dst)) fs.copyFileSync(src, dst)
251
513
  }
252
514
  fs.mkdirSync(path.join(fdeDir, 'retrospectives'), { recursive: true })
253
- // bind THIS workspace to the engagement (zero ceremony next time)
254
- const line = `${process.cwd()} ${slug}\n`
255
- const reg = fs.existsSync(REGISTRY) ? fs.readFileSync(REGISTRY, 'utf8') : ''
256
- if (!reg.includes(line.trim())) fs.appendFileSync(REGISTRY, line)
257
- console.log(`ENGAGEMENT READY: ${fdeDir}\nbound to workspace: ${process.cwd()}`)
515
+ // bind THIS workspace to the engagement (zero ceremony next time).
516
+ // A workspace binds to exactly ONE engagement: rebinding REPLACES the old
517
+ // line - resolution is first-match-wins, so appending a second line would
518
+ // leave the stale binding winning and silently write to the wrong client.
519
+ const cwd = process.cwd()
520
+ const prev = readRegistry().find(r => r.workspace === cwd)
521
+ const kept = readRegistry().filter(r => r.workspace !== cwd).map(r => `${r.workspace} ${r.slug}`)
522
+ kept.push(`${cwd} ${slug}`)
523
+ fs.writeFileSync(REGISTRY, kept.join('\n') + '\n')
524
+ console.log(`ENGAGEMENT READY: ${fdeDir}\nbound to workspace: ${cwd}`)
525
+ if (prev && prev.slug !== slug) console.log(`rebound: this workspace previously wrote to "${prev.slug}" - that memory is untouched; sessions here now write to "${slug}"`)
526
+ // NDA surface: engagement notes must not silently leave the machine via file sync
527
+ const syncHit = /icloud|mobile documents|dropbox|onedrive|google drive|box sync/i.exec(ENGAGEMENTS_ROOT)
528
+ if (syncHit) console.log(`⚠ engagements root is inside a synced folder ("${syncHit[0]}") - client notes will leave this machine via sync. See PRIVACY.md.`)
529
+ return
530
+ }
531
+ if (args[0] === '--bind') {
532
+ // inspection: what does THIS workspace resolve to, and why
533
+ const cwd = process.cwd()
534
+ const reg = readRegistry().find(r => r.workspace === cwd)
535
+ const eng = resolveEngagement()
536
+ console.log(`workspace: ${cwd}`)
537
+ console.log(`registry: ${reg ? `${reg.slug} (${path.join(ENGAGEMENTS_ROOT, reg.slug, '.fde')})` : '(not bound)'}`)
538
+ console.log(`resolves: ${eng || '(nothing - run: fde resume --init <client>)'}`)
258
539
  return
259
540
  }
260
541
  const eng = resolveEngagement()
@@ -296,14 +577,77 @@ function resumeView(md) {
296
577
  }
297
578
 
298
579
  function cmdLog(args) {
299
- const map = { decision: 'decisions.md', risk: 'risks.md', delivery: 'delivery.md', contact: 'stakeholders.md' }
580
+ args = args.slice()
581
+ // --signal red|amber|green (contact only) → structured token computeSignals trusts
582
+ let signal = ''
583
+ const sigIdx = args.indexOf('--signal')
584
+ if (sigIdx !== -1) {
585
+ signal = (args[sigIdx + 1] || '').toLowerCase()
586
+ if (!['red', 'amber', 'green'].includes(signal)) { console.error('usage: fde log contact <text> --signal red|amber|green'); process.exit(1) }
587
+ args.splice(sigIdx, 2)
588
+ }
300
589
  const type = args[0]; const text = args.slice(1).join(' ')
301
- if (!map[type] || !text) { console.error('usage: fde log <decision|risk|delivery|contact> <text>'); process.exit(1) }
590
+ if (!LOG_FILES[type] || !text) { console.error('usage: fde log <decision|risk|delivery|contact> <text> [--signal red|amber|green]'); process.exit(1) }
591
+ if (signal && type !== 'contact') { console.error('--signal only applies to: fde log contact'); process.exit(1) }
302
592
  const eng = resolveEngagement()
303
593
  if (!eng) { console.error('no engagement - run: fde resume --init <name>'); process.exit(2) }
304
594
  const date = new Date().toISOString().slice(0, 10)
305
- fs.appendFileSync(path.join(eng, map[type]), `\n- [${date}] ${text}\n`)
306
- console.log(`logged → ${map[type]}`)
595
+ fs.appendFileSync(path.join(eng, LOG_FILES[type]), `\n- [${date}] ${signal ? `[signal:${signal}] ` : ''}${text}\n`)
596
+ console.log(`logged → ${LOG_FILES[type]}${signal ? ` (signal:${signal})` : ''}`)
597
+ }
598
+
599
+ // Meeting notes → structured memory. Deterministic routing, zero AI: lines that
600
+ // start with decision:/risk:/delivery:/contact: (case-insensitive) go to their
601
+ // LOG_FILES target as dated bullets; everything else lands in context.md as one
602
+ // dated debrief block. contact: lines may carry an inline [signal:x] token
603
+ // anywhere in the text - preserved verbatim so computeSignals can trust it.
604
+ // Real notes arrive as markdown: "- decision: ...", "* contact: ...",
605
+ // "**Decision:** ..." - strip bullet/bold dressing before matching, or the
606
+ // prefix silently misses and a [signal:x] token lands in context.md, which
607
+ // signal parsing never reads. Silent loss is the one failure a memory tool
608
+ // cannot have. --dry-run prints the routing without writing anything.
609
+ function cmdDebrief(args) {
610
+ args = args.slice()
611
+ const dryIdx = args.indexOf('--dry-run')
612
+ const dry = dryIdx !== -1
613
+ if (dry) args.splice(dryIdx, 1)
614
+ const eng = resolveEngagement()
615
+ if (!eng) { console.error('no engagement - run: fde resume --init <name>'); process.exit(2) }
616
+ let input = ''
617
+ if (args[0]) {
618
+ try { input = fs.readFileSync(args[0].replace(/^~/, HOME), 'utf8') }
619
+ catch (_) { console.error(`cannot read ${args[0]}`); process.exit(1) }
620
+ } else {
621
+ try { input = fs.readFileSync(0, 'utf8') } catch (_) {} // stdin until EOF
622
+ }
623
+ const d = new Date()
624
+ const date = d.toISOString().slice(0, 10)
625
+ const counts = { decision: 0, risk: 0, delivery: 0, contact: 0 }
626
+ const ctxLines = []
627
+ for (const raw of input.split('\n')) {
628
+ let line = raw.trim()
629
+ if (!line) continue
630
+ // markdown dressing: leading bullets (-, *, +) and bold around the prefix
631
+ const bare = line.replace(/^[-*+]\s+/, '').replace(/^\*\*(decision|risk|delivery|contact):?\*\*:?\s*/i, '$1: ')
632
+ const m = bare.match(/^(decision|risk|delivery|contact):\s*(.+)$/i)
633
+ if (m) {
634
+ const type = m[1].toLowerCase()
635
+ if (dry) console.log(`→ ${LOG_FILES[type]} - [${date}] ${m[2]}`)
636
+ else fs.appendFileSync(path.join(eng, LOG_FILES[type]), `\n- [${date}] ${m[2]}\n`)
637
+ counts[type]++
638
+ } else ctxLines.push(line)
639
+ }
640
+ if (ctxLines.length) {
641
+ const stamp = `${date} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`
642
+ if (dry) ctxLines.forEach(l => console.log(`→ context.md - ${l}`))
643
+ else fs.appendFileSync(path.join(eng, 'context.md'), `\n## Debrief - ${stamp}\n${ctxLines.map(l => `- ${l}`).join('\n')}\n`)
644
+ }
645
+ const plural = { decision: 'decisions', risk: 'risks', delivery: 'deliveries', contact: 'contacts' }
646
+ const parts = Object.keys(counts).filter(t => counts[t])
647
+ .map(t => `${counts[t]} ${counts[t] === 1 ? t : plural[t]}`)
648
+ if (ctxLines.length) parts.push(`${ctxLines.length} context line${ctxLines.length === 1 ? '' : 's'}`)
649
+ const verb = dry ? 'debrief would route' : 'debrief routed'
650
+ console.log(parts.length ? `${verb} → ${parts.join(', ')}` : 'debrief empty - nothing routed')
307
651
  }
308
652
 
309
653
  function cmdReceipts(args) {
@@ -320,7 +664,7 @@ function cmdReceipts(args) {
320
664
  if (rx.test(l)) { console.log(`${f}:${i + 1} ${l.trim().slice(0, 160)}`); found++ }
321
665
  })
322
666
  }
323
- if (!found) console.log(`no record of "${term}" - if it was agreed, it was never logged. That is itself the answer.`)
667
+ if (!found) console.log(`no record of "${term}" - nothing was ever logged about it. A gap in the record, not proof of absence: if it WAS agreed, log it now, dated today.`)
324
668
  }
325
669
 
326
670
  function cmdCapture() {
@@ -353,16 +697,19 @@ function cmdStatus() {
353
697
  const eng = path.join(ENGAGEMENTS_ROOT, d, '.fde')
354
698
  if (!fs.existsSync(eng)) continue
355
699
  const s = computeSignals(eng)
356
- rows.push({ name: d, phase: s.phase, trust: s.trust, updated: s.updated, topRisk: s.topRisk.slice(0, 60) })
700
+ rows.push({ name: d, phase: s.phase, trust: s.trust, signalAge: s.signalAge, stale: s.stale, updated: s.updated, topRisk: s.topRisk.slice(0, 60) })
357
701
  }
358
702
  if (!rows.length) { console.log('no engagements yet'); return }
359
703
  const order = { RED: 0, amber: 1, green: 2 }
360
704
  rows.sort((a, b) => order[a.trust] - order[b.trust])
361
705
  console.log('FDE PORTFOLIO - trust-first triage (heuristic: red > amber > green)\n')
362
706
  for (const r of rows) {
363
- console.log(` [${r.trust.padEnd(5)}] ${r.name.padEnd(24)} phase:${r.phase.padEnd(10)} updated:${r.updated.padEnd(8)} ${r.topRisk}`)
707
+ // "amber?" = structured signal went stale (>21d) - reconfirm before trusting it
708
+ const label = r.trust + (r.stale ? '?' : '')
709
+ const sig = r.signalAge != null ? `signal ${r.signalAge}d old${r.stale ? ' (STALE - reconfirm)' : ''} ` : ''
710
+ console.log(` [${label.padEnd(6)}] ${r.name.padEnd(24)} phase:${r.phase.padEnd(10)} updated:${r.updated.padEnd(8)} ${sig}${r.topRisk}`)
364
711
  }
365
- console.log('\nred/amber derive from stakeholders.md signal words - verify before acting.')
712
+ console.log('\ntrust: latest [signal:x] token in stakeholders.md wins (fde log contact --signal, fde debrief); keyword heuristic only when none exists - verify before acting.')
366
713
  }
367
714
 
368
715
  // ---------- dashboard (deterministic markdown → one local HTML) ----------
@@ -389,26 +736,14 @@ function inlineMd(s) {
389
736
  .replace(/`([^`]+)`/g, '<code>$1</code>')
390
737
  }
391
738
 
392
- function renderTable(rows) {
393
- const cells = r => r.replace(/^\s*\|/, '').replace(/\|\s*$/, '').split('|').map(c => c.trim())
394
- const isSep = r => r.includes('-') && /^\|?[\s:|-]+\|?$/.test(r.trim())
395
- let html = '<table>'; let headerDone = false
396
- for (const r of rows) {
397
- if (isSep(r)) continue
398
- const cs = cells(r)
399
- if (!headerDone) {
400
- html += '<thead><tr>' + cs.map(c => '<th>' + inlineMd(c) + '</th>').join('') + '</tr></thead><tbody>'
401
- headerDone = true
402
- } else {
403
- if (cs.every(c => !c)) continue
404
- html += '<tr>' + cs.map(c => '<td>' + inlineMd(c) + '</td>').join('') + '</tr>'
405
- }
406
- }
407
- return html + '</tbody></table>'
408
- }
409
-
410
- function mdToHtml(md) {
411
- 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')
412
747
  const out = []; let i = 0
413
748
  while (i < lines.length) {
414
749
  const t = lines[i].trim()
@@ -416,32 +751,38 @@ function mdToHtml(md) {
416
751
  if (/^\|.*\|/.test(t)) {
417
752
  const tbl = []
418
753
  while (i < lines.length && /^\s*\|.*\|/.test(lines[i])) { tbl.push(lines[i]); i++ }
419
- out.push(renderTable(tbl)); continue
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
420
760
  }
421
761
  const h = t.match(/^(#{1,6})\s+(.*)$/)
422
- if (h) { out.push('<h4>' + inlineMd(h[2]) + '</h4>'); i++; continue }
762
+ if (h) { out.push('<div class="fb-sec">' + inlineMd(h[2]) + '</div>'); i++; continue }
423
763
  if (/^[-*]\s+/.test(t)) {
424
764
  const items = []
425
765
  while (i < lines.length && /^\s*[-*]\s+/.test(lines[i])) { items.push('<li>' + inlineMd(lines[i].trim().replace(/^[-*]\s+/, '')) + '</li>'); i++ }
426
- out.push('<ul>' + items.join('') + '</ul>'); continue
766
+ out.push('<ul class="fb-plain-list">' + items.join('') + '</ul>'); continue
427
767
  }
428
768
  const para = []
429
769
  while (i < lines.length && lines[i].trim() && !/^\s*\|.*\|/.test(lines[i]) && !/^#{1,6}\s/.test(lines[i].trim()) && !/^[-*]\s+/.test(lines[i].trim())) {
430
770
  para.push(lines[i].trim()); i++
431
771
  }
432
- out.push('<p>' + inlineMd(para.join(' ')) + '</p>')
772
+ out.push('<p class="fb-plain-p">' + inlineMd(para.join(' ')) + '</p>')
433
773
  }
434
774
  return out.join('\n')
435
775
  }
436
776
 
437
- // True if a file has real content beyond headings, labels with empty values, and blank table rows.
438
- function hasContent(md) {
439
- const txt = stripPrivate(md)
440
- .replace(/^#{1,6}\s.*$/gm, '') // headings
441
- .replace(/^\s*\|[\s:|-]+\|\s*$/gm, '') // table separators
442
- .replace(/^\s*\|[\s|]*\|\s*$/gm, '') // empty table rows
443
- .replace(/\*\*[^*]+:\*\*\s*$/gm, '') // bold labels with no value
444
- .replace(/[-*]\s*$/gm, '') // empty bullets
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, '')
445
786
  .replace(/\s+/g, ' ')
446
787
  .trim()
447
788
  return txt.length > 0
@@ -459,136 +800,518 @@ function gatherEngagements() {
459
800
  return list
460
801
  }
461
802
 
462
- const DASH_SECTIONS = [
463
- ['context.md', 'Context'],
464
- ['brief.md', 'Brief - stated problem'],
465
- ['reality.md', 'Reality - actual problem'],
466
- ['success.md', 'Success & scope'],
467
- ['stakeholders.md', 'Stakeholders'],
468
- ['decisions.md', 'Plan & decisions'],
469
- ['risks.md', 'Risk register'],
470
- ['delivery.md', 'Delivery log'],
471
- ['terrain.md', 'Terrain - codebase map'],
472
- ['trust-profile.md', 'Trust profile'],
473
- ]
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
+ }`
474
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.
475
838
  function dashStyles() {
476
- return [
477
- // design system: quiet chrome, high density, daily-use second brain
478
- ':root{--bg:#f9fafb;--card:#fff;--ink:#111827;--2:#374151;--3:#4b5563;--muted:#6b7280;--line:#f3f4f6;--line2:#e5e7eb;',
479
- '--green:#10b981;--amber:#f59e0b;--red:#ef4444;--accent:#6366f1;',
480
- '--shadow-s:0 1px 2px rgba(0,0,0,.04);--shadow:0 1px 3px rgba(0,0,0,.06);--shadow-l:0 4px 12px rgba(0,0,0,.08);',
481
- '--r:8px}',
482
- '*{box-sizing:border-box;margin:0}',
483
- 'body{font:14px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;color:var(--ink);background:var(--bg);-webkit-font-smoothing:antialiased}',
484
- // header - compact, purposeful
485
- 'header{background:#111827;color:#fff;padding:20px 32px}',
486
- 'header .inner{max-width:960px;margin:0 auto;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px}',
487
- 'header .brand{display:flex;align-items:center;gap:10px}',
488
- 'header h1{font-size:16px;font-weight:600;letter-spacing:-.2px}',
489
- 'header .tagline{color:#9ca3af;font-size:12px}',
490
- '.stats{display:flex;align-items:center;gap:16px}',
491
- '.stat{font-size:12px;color:#9ca3af;display:flex;align-items:center;gap:5px}',
492
- '.stat b{color:#e5e7eb;font-weight:600}',
493
- '.stat .sdot{width:6px;height:6px;border-radius:50%;flex-shrink:0}',
494
- '.stat .sdot.green{background:#34d399}.stat .sdot.amber{background:#fbbf24}.stat .sdot.red{background:#f87171}',
495
- // layout
496
- '.wrap{max-width:960px;margin:0 auto;padding:24px 32px 64px}',
497
- // search - integrated, not floating
498
- '.search-wrap{position:relative;margin-bottom:24px}',
499
- '.search-wrap svg{position:absolute;left:12px;top:50%;transform:translateY(-50%);width:16px;height:16px;stroke:var(--muted);stroke-width:2;fill:none}',
500
- '.search{width:100%;padding:10px 14px 10px 36px;font-size:13px;border:1px solid var(--line2);border-radius:var(--r);background:var(--card);transition:border-color .15s,box-shadow .15s;outline:none}',
501
- '.search:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(99,102,241,.1)}',
502
- '.search::placeholder{color:var(--muted)}',
503
- // directive - the one line that says where to start today
504
- '.directive{display:flex;align-items:center;gap:10px;margin:0 0 20px;padding:12px 16px;background:#fef2f2;border:1px solid #fecaca;border-radius:var(--r);font-size:13.5px;line-height:1.5;color:#7f1d1d}',
505
- '.directive b{font-weight:700;color:#7f1d1d}',
506
- '.directive.amber{background:#fffbeb;border-color:#fde68a;color:#78350f}',
507
- '.directive.amber b{color:#78350f}',
508
- '.directive-dot{width:9px;height:9px;border-radius:50%;background:var(--red);flex-shrink:0;box-shadow:0 0 0 3px rgba(239,68,68,.18)}',
509
- '.directive.amber .directive-dot{background:var(--amber);box-shadow:0 0 0 3px rgba(245,158,11,.18)}',
510
- // attention rows - red engagements dominate the page, full width
511
- '.attn-stack{display:flex;flex-direction:column;gap:10px}',
512
- '.attn{background:#fef2f2;border:1px solid #fecaca;border-left:4px solid var(--red);border-radius:var(--r);padding:16px 18px;cursor:pointer;transition:box-shadow .15s,border-color .15s}',
513
- '.attn:hover{border-color:#f87171;box-shadow:var(--shadow-l)}',
514
- '.attn-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap}',
515
- '.attn-head h3{font-size:15px;font-weight:700;color:var(--ink)}',
516
- '.attn .risk{margin-top:10px}',
517
- '.attn .next{margin-top:8px;font-size:13px;line-height:1.5;color:var(--2)}.attn .next b{color:var(--3);font-weight:600;font-size:10px;text-transform:uppercase;letter-spacing:.3px;margin-right:4px}',
518
- // grid
519
- '.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px}',
520
- // cards - clean, scannable
521
- '.card{background:var(--card);border:1px solid var(--line2);border-radius:var(--r);padding:16px 18px;cursor:pointer;transition:border-color .15s,box-shadow .15s;position:relative;overflow:hidden}',
522
- '.card::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px}',
523
- '.card:hover{border-color:#d1d5db;box-shadow:var(--shadow-l)}',
524
- '.card.green::before{background:var(--green)}.card.amber::before{background:var(--amber)}.card.red::before{background:var(--red)}',
525
- '.card h3{font-size:14px;font-weight:600;margin-bottom:6px}',
526
- '.row{display:flex;align-items:center;gap:6px;flex-wrap:wrap}',
527
- '.badge{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;padding:2px 7px;border-radius:4px;background:#f3f4f6;color:#4b5563}',
528
- '.dot{width:8px;height:8px;border-radius:50%;display:inline-block;flex-shrink:0}',
529
- '.dot.green{background:var(--green)}.dot.amber{background:var(--amber)}.dot.red{background:var(--red)}',
530
- '.trust-label{font-weight:600;font-size:11px;text-transform:uppercase;letter-spacing:.3px}',
531
- '.t-green{color:var(--green)}.t-amber{color:var(--amber)}.t-red{color:var(--red)}',
532
- '.meta{color:var(--muted);font-size:11px}',
533
- '.card .next{margin-top:10px;font-size:12.5px;line-height:1.5;color:var(--2)}.card .next b{color:var(--3);font-weight:600;font-size:10px;text-transform:uppercase;letter-spacing:.3px;margin-right:2px}',
534
- '.card .risk{margin-top:8px;font-size:11.5px;color:#991b1b;padding:5px 8px;background:#fef2f2;border-radius:4px;border-left:2px solid var(--red);line-height:1.4}',
535
- '.card .risk.amber-risk{color:#92400e;background:#fffbeb;border-left-color:var(--amber)}',
536
- // demote placeholder cards (no next action) - quiet until they earn attention
537
- '.card.muted{opacity:.55}',
538
- '.card.muted:hover{opacity:1}',
539
- // section labels
540
- 'h2.section{margin:28px 0 12px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.6px;color:var(--muted)}',
541
- // detail accordion - tight, content-forward
542
- 'details.eng{background:var(--card);border:1px solid var(--line2);border-radius:var(--r);margin:8px 0;overflow:hidden}',
543
- 'details.eng>summary{list-style:none;cursor:pointer;padding:14px 18px;display:flex;align-items:center;gap:10px;font-weight:600;font-size:14px;transition:background .1s}',
544
- 'details.eng>summary:hover{background:var(--bg)}',
545
- 'details.eng>summary::-webkit-details-marker{display:none}',
546
- 'details.eng>summary::after{content:"";margin-left:auto;width:16px;height:16px;background:url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'16\' height=\'16\' viewBox=\'0 0 24 24\' fill=\'none\' stroke=\'%239ca3af\' stroke-width=\'2\'%3E%3Cpath d=\'M6 9l6 6 6-6\'/%3E%3C/svg%3E") no-repeat center;transition:transform .15s}',
547
- 'details.eng[open]>summary::after{transform:rotate(180deg)}',
548
- 'details.eng[open]>summary{border-bottom:1px solid var(--line)}',
549
- '.eng-body{padding:8px 20px 20px}',
550
- '.sub-sec{padding:14px 0;border-bottom:1px solid var(--line)}.sub-sec:last-child{border-bottom:none}',
551
- '.sub-sec h4.title{margin:0 0 8px;font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--muted)}',
552
- '.sub-sec h4{margin:10px 0 4px;font-size:13.5px;font-weight:600;color:var(--ink)}',
553
- '.sub-sec p{margin:4px 0;line-height:1.6;color:var(--2);font-size:13px}.sub-sec ul{margin:4px 0;padding-left:20px;color:var(--2);font-size:13px}',
554
- '.sub-sec li{margin:2px 0}',
555
- '.empty{color:var(--muted);font-style:italic;font-size:12px}',
556
- // tables
557
- 'table{border-collapse:collapse;width:100%;margin:8px 0;font-size:12.5px;border:1px solid var(--line2);border-radius:6px;overflow:hidden}',
558
- 'th,td{padding:7px 10px;text-align:left;vertical-align:top;border-bottom:1px solid var(--line)}',
559
- 'th{background:var(--bg);font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--3);border-bottom:1px solid var(--line2)}',
560
- 'tr:last-child td{border-bottom:none}',
561
- 'tr:hover td{background:var(--bg)}',
562
- 'code{background:#f3f4f6;padding:1px 5px;border-radius:4px;font-size:12px;color:#4b5563}',
563
- // footer
564
- 'footer{max-width:960px;margin:0 auto;padding:0 32px 48px;color:var(--muted);font-size:11.5px;line-height:1.5}',
565
- 'footer code{color:var(--3);background:#f3f4f6}',
566
- '.hide{display:none!important}',
567
- // responsive
568
- '@media(max-width:640px){header{padding:16px}.header .inner{flex-direction:column;align-items:flex-start}.wrap{padding:16px 16px 48px}.grid{grid-template-columns:1fr}.search{padding-left:32px}}',
569
- ].join('')
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
+ `
570
974
  }
571
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.
572
982
  function dashScript() {
573
983
  return [
574
- "var q=document.getElementById('q');",
575
- "function norm(s){return (s||'').toLowerCase();}",
576
- "if(q){q.addEventListener('input',function(){",
577
- " var term=norm(q.value);",
578
- " document.querySelectorAll('[data-search]').forEach(function(el){",
579
- " var hit=!term||norm(el.getAttribute('data-search')).indexOf(term)>-1;",
580
- " el.classList.toggle('hide',!hit);",
984
+ "(function(){",
985
+ "'use strict';",
986
+ "var SEL_KEY='fde-fieldbook-sel';",
987
+ "function esc(s){return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');}",
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.",
1011
+ "function snippetFor(raw,term){",
1012
+ " var i=raw.indexOf(term);",
1013
+ " if(i<0)return '';",
1014
+ " var start=Math.max(0,i-24),end=Math.min(raw.length,i+term.length+40);",
1015
+ " var pre=esc(raw.slice(start,i)),hit=esc(raw.slice(i,i+term.length)),post=esc(raw.slice(i+term.length,end));",
1016
+ " return (start>0?'\\u2026':'')+pre+'<mark>'+hit+'</mark>'+post+(end<raw.length?'\\u2026':'');",
1017
+ "}",
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();",
1023
+ " var hit=!term||raw.indexOf(term)>-1;",
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);}",
581
1029
  " });",
582
1030
  "});}",
583
- "document.querySelectorAll('.card').forEach(function(c){",
584
- " c.addEventListener('click',function(){",
585
- " var d=document.getElementById(c.getAttribute('data-target'));",
586
- " if(d){d.open=true;d.scrollIntoView({behavior:'smooth',block:'start'});}",
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
+ " }",
1049
+ "});",
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));",
587
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();}});",
588
1095
  "});",
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",
1107
+ "var themeBtn=document.getElementById('fde-theme-btn');",
1108
+ "function currentTheme(){return document.documentElement.getAttribute('data-fde-theme')==='dark'?'dark':'light';}",
1109
+ "function setThemeLabel(){if(themeBtn)themeBtn.textContent=(currentTheme()==='dark'?'light':'dark');}",
1110
+ "function toggleTheme(){",
1111
+ " var next=currentTheme()==='dark'?'light':'dark';",
1112
+ " try{localStorage.setItem('fde-fieldbook-theme',next);}catch(e){}",
1113
+ " document.documentElement.setAttribute('data-fde-theme',next);",
1114
+ " setThemeLabel();",
1115
+ "}",
1116
+ "setThemeLabel();",
1117
+ "if(themeBtn)themeBtn.addEventListener('click',toggleTheme);",
1118
+ "})();",
589
1119
  ].join('\n')
590
1120
  }
591
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)} &middot; <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 &lt;client-name&gt;</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)} &middot; ${total} engagement${total === 1 ? '' : 's'} &middot; ${attentionCount} need you &middot; ${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(' &middot; ')
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' ? '&#9679;' : sig === 'red' ? '&#9675;' : '&#9632;' // 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(' &nbsp; ')
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">&rarr;</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
+
592
1315
  function cmdDashboard(args) {
593
1316
  const outIdx = args.indexOf('--out')
594
1317
  const outPath = outIdx !== -1 && args[outIdx + 1]
@@ -597,120 +1320,117 @@ function cmdDashboard(args) {
597
1320
  const engagements = gatherEngagements()
598
1321
  const counts = { green: 0, amber: 0, RED: 0 }
599
1322
  engagements.forEach(e => { counts[e.signals.trust]++ })
600
- const now = new Date()
601
- const stamp = now.toISOString().slice(0, 16).replace('T', ' ') + ' UTC'
1323
+ const today = formatToday(new Date())
602
1324
 
603
- // enrich each engagement: next action + search index (reused in rows, cards, directive)
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.
604
1328
  engagements.forEach(e => {
605
- const ctx = readEng(e.dir, 'context.md')
1329
+ const ctx = readClean(e.dir, 'context.md')
606
1330
  e.next = (sectionBody(ctx, 'Next action').split('\n').find(l => l.trim()) || '').trim()
607
1331
  e.hasNext = !!e.next
608
- e.searchBlob = escapeHtml(stripPrivate(e.name + ' ' + ctx + ' ' + readEng(e.dir, 'risks.md') + ' ' + readEng(e.dir, 'stakeholders.md')).toLowerCase())
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())
609
1363
  })
610
1364
 
611
- // triage order: red first (most stale first), then amber, then green; real work above placeholders
1365
+ // rail + Today queue share one order: trust-first (red, amber, green)
612
1366
  const tierRank = { RED: 0, amber: 1, green: 2 }
613
- const ordered = engagements.slice().sort((a, b) =>
614
- (tierRank[a.signals.trust] - tierRank[b.signals.trust])
615
- || ((b.hasNext ? 1 : 0) - (a.hasNext ? 1 : 0))
616
- || ((b.signals.ageDays || 0) - (a.signals.ageDays || 0))
617
- || a.name.localeCompare(b.name))
618
- const reds = ordered.filter(e => e.signals.trust === 'RED')
619
- const rest = ordered.filter(e => e.signals.trust !== 'RED')
620
-
621
- // one directive line: where the FDE starts today, and why
622
- const lead = reds[0] || rest.find(e => e.signals.trust === 'amber' && e.hasNext) || rest[0]
623
- let directive = '', directiveClass = 'directive'
624
- if (lead) {
625
- const why = stripPrivate(lead.signals.topRisk || lead.next || (lead.signals.trust === 'RED' ? 'trust signal is red' : 'oldest open thread')).trim().slice(0, 90)
626
- const age = lead.signals.ageDays != null ? `${lead.signals.ageDays}d since touched` : ''
627
- directive = `Start here: <b>${inlineMd(lead.name)}</b> - ${inlineMd(why)}${age ? ' · ' + age : ''}`
628
- directiveClass = reds.length ? 'directive' : 'directive amber'
629
- }
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)
630
1370
 
631
- // red engagements: full-width attention rows that dominate the page
632
- const attention = reds.map(e => {
633
- const id = 'eng-' + slugify(e.name)
634
- return [
635
- `<div class="attn" data-target="${id}" data-search="${e.searchBlob}">`,
636
- `<div class="attn-head"><span class="dot red"></span><span class="trust-label t-red">RED</span>`,
637
- `<h3>${inlineMd(e.name)}</h3>`,
638
- `<span class="badge">${inlineMd(e.signals.phase)}</span><span class="meta">updated ${e.signals.updated}</span></div>`,
639
- e.signals.topRisk ? `<div class="risk">${inlineMd(e.signals.topRisk)}</div>` : '',
640
- e.next ? `<div class="next"><b>Next</b> ${inlineMd(e.next)}</div>` : '',
641
- `</div>`,
642
- ].join('')
643
- }).join('\n')
644
-
645
- // amber/green: quieter portfolio grid; cards without a next action sink and dim
646
- const cards = rest.map(e => {
647
- const id = 'eng-' + slugify(e.name)
648
- const trustClass = e.signals.trust
649
- const muted = e.hasNext ? '' : ' muted'
650
- return [
651
- `<div class="card ${trustClass}${muted}" data-target="${id}" data-search="${e.searchBlob}">`,
652
- `<h3>${inlineMd(e.name)}</h3>`,
653
- `<div class="row"><span class="dot ${trustClass}"></span><span class="trust-label t-${trustClass}">${trustClass}</span>`,
654
- `<span class="badge">${inlineMd(e.signals.phase)}</span><span class="meta">updated ${e.signals.updated}</span></div>`,
655
- e.next ? `<div class="next"><b>Next</b> ${inlineMd(e.next)}</div>` : '<div class="next meta">next action not set</div>',
656
- e.signals.topRisk ? `<div class="risk amber-risk">${inlineMd(e.signals.topRisk)}</div>` : '',
657
- `</div>`,
658
- ].join('')
659
- }).join('\n')
660
-
661
- const details = ordered.map(e => {
662
- const id = 'eng-' + slugify(e.name)
663
- const trustClass = e.signals.trust === 'RED' ? 'red' : e.signals.trust
664
- const subs = DASH_SECTIONS.map(([file, title]) => {
665
- const md = readEng(e.dir, file)
666
- const body = hasContent(md) ? mdToHtml(md) : '<p class="empty">- not yet filled -</p>'
667
- return `<div class="sub-sec"><h4 class="title">${title}</h4>${body}</div>`
668
- })
669
- // retrospectives (optional folder)
670
- const retroDir = path.join(e.dir, 'retrospectives')
671
- let retros = ''
672
- try {
673
- const files = fs.readdirSync(retroDir).filter(f => f.endsWith('.md')).sort()
674
- const items = files.filter(f => hasContent(readEng(retroDir, f)))
675
- .map(f => `<h4>${escapeHtml(f)}</h4>${mdToHtml(readEng(retroDir, f))}`).join('')
676
- if (items) retros = `<div class="sub-sec"><h4 class="title">Retrospectives</h4>${items}</div>`
677
- } catch (_) {}
678
- const searchBlob = escapeHtml(stripPrivate(e.name + ' ' + DASH_SECTIONS.map(([f]) => readEng(e.dir, f)).join(' ')).toLowerCase())
679
- return [
680
- `<details class="eng" id="${id}" data-search="${searchBlob}">`,
681
- `<summary><span class="dot ${trustClass}"></span>${inlineMd(e.name)}`,
682
- `<span class="badge">${inlineMd(e.signals.phase)}</span>`,
683
- `<span class="meta" style="font-weight:400">updated ${e.signals.updated}</span></summary>`,
684
- `<div class="eng-body">${subs.join('')}${retros}</div>`,
685
- `</details>`,
686
- ].join('')
687
- }).join('\n')
688
-
689
- const emptyState = '<p class="empty">No engagements yet. Start one with <code>fde resume --init &lt;client-name&gt;</code>, then re-run <code>fde dashboard</code>.</p>'
690
-
691
- const html = [
692
- '<!doctype html><html lang="en"><head><meta charset="utf-8">',
693
- '<meta name="viewport" content="width=device-width,initial-scale=1">',
694
- '<title>FDE Fieldbook</title><style>' + dashStyles() + '</style></head><body>',
695
- '<header><div class="inner"><div class="brand"><h1>FDE Fieldbook</h1>',
696
- `<span class="tagline">${engagements.length} engagement${engagements.length === 1 ? '' : 's'}</span></div>`,
697
- '<div class="stats">',
698
- `<span class="stat"><span class="sdot green"></span> <b>${counts.green}</b> green</span>`,
699
- `<span class="stat"><span class="sdot amber"></span> <b>${counts.amber}</b> amber</span>`,
700
- `<span class="stat"><span class="sdot red"></span> <b>${counts.RED}</b> red</span>`,
701
- '</div></div></header>',
702
- '<div class="wrap">',
703
- 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>' : '',
704
- directive ? `<div class="${directiveClass}"><span class="directive-dot"></span><span>${directive}</span></div>` : '',
705
- reds.length ? '<h2 class="section">Needs attention</h2><div class="attn-stack">' + attention + '</div>' : '',
706
- engagements.length ? `<h2 class="section">${reds.length ? 'Rest of portfolio' : 'Portfolio'}</h2>` : '',
707
- engagements.length ? (rest.length ? `<div class="grid">${cards}</div>` : '<p class="empty">Every active engagement needs attention - see above.</p>') : emptyState,
708
- engagements.length ? '<h2 class="section">Engagement detail</h2>' + details : '',
709
- '</div>',
710
- `<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>`,
711
- '<script>' + dashScript() + '</script>',
712
- '</body></html>',
713
- ].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)">&#8984;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">&uarr;&darr; / j k</span> client</span>
1418
+ <span><span class="t-soft">/</span> search</span>
1419
+ <span><span class="t-soft">&#8984;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>`
714
1434
 
715
1435
  fs.mkdirSync(path.dirname(outPath), { recursive: true })
716
1436
  fs.writeFileSync(outPath, html)
@@ -732,6 +1452,7 @@ switch (cmd) {
732
1452
  case 'scan': cmdScan(); break
733
1453
  case 'resume': cmdResume(args); break
734
1454
  case 'log': cmdLog(args); break
1455
+ case 'debrief': cmdDebrief(args); break
735
1456
  case 'receipts': cmdReceipts(args); break
736
1457
  case 'capture': cmdCapture(); break
737
1458
  case 'status': cmdStatus(); break
@@ -741,8 +1462,10 @@ switch (cmd) {
741
1462
  fde scan day-1 recon of this repo (facts, no AI)
742
1463
  fde resume load this workspace's engagement memory (bounded)
743
1464
  fde resume --full load the complete context.md (no bound)
744
- fde resume --init <name> create + bind engagement for this workspace
745
- fde log <type> <text> append decision|risk|delivery|contact
1465
+ fde resume --init <name> create + bind engagement for this workspace (rebind replaces)
1466
+ fde resume --bind show what this workspace is bound to, and what resolves
1467
+ fde log <type> <text> append decision|risk|delivery|contact (contact takes --signal red|amber|green)
1468
+ fde debrief [file] meeting notes → memory: decision:/risk:/delivery:/contact: lines route, rest → context.md (stdin if no file; --dry-run previews)
746
1469
  fde receipts <term> "what did we agree?" with dates
747
1470
  fde capture session-end memory snapshot (hooks use this)
748
1471
  fde status portfolio across all engagements