fdeops 3.9.6 → 3.9.8

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
@@ -29,6 +29,8 @@ const fs = require('fs')
29
29
  const path = require('path')
30
30
  const os = require('os')
31
31
  const { execSync, execFileSync } = require('child_process')
32
+ const { createMemoryApi } = require('./lib/memory')
33
+ const { createTrustApi } = require('./lib/trust')
32
34
 
33
35
  const HOME = os.homedir()
34
36
  // FDEOPS_ENGAGEMENTS_ROOT isolates init/status/dashboard (and the registry) for
@@ -168,6 +170,14 @@ function readEng(eng, f) {
168
170
  try { return fs.readFileSync(path.join(eng, f), 'utf8') } catch (_) { return '' }
169
171
  }
170
172
 
173
+ // Redact private notes and template hints from every model-facing read.
174
+ function stripPrivate(md) {
175
+ return md
176
+ .replace(/<private>[\s\S]*?<\/private>/gi, '(private - redacted)')
177
+ .replace(/<private>[\s\S]*$/i, '(private - redacted)')
178
+ .replace(/<!--[\s\S]*?-->/g, '')
179
+ }
180
+
171
181
  // Read + redact in one step - the default way dashboard code should ever touch
172
182
  // a markdown file, so a forgotten stripPrivate() call can't leak a <private> block.
173
183
  function readClean(eng, f) { return stripPrivate(readEng(eng, f)) }
@@ -201,7 +211,7 @@ function refuseSecret(kind, hit) {
201
211
  console.error(
202
212
  `refused: ${kind} looks like a ${hit}.\n` +
203
213
  `Do not log credentials into engagement memory. Redact first, or pass --force if this is intentional.\n` +
204
- `If you already wrote one: fde log --undo`
214
+ `If you already wrote one: fde log --undo (last write) or fde redact <term> --apply (buried)`
205
215
  )
206
216
  }
207
217
 
@@ -335,7 +345,6 @@ function rmTreeQuiet(dir) {
335
345
 
336
346
  const OWNER_FILE = '.owner'
337
347
  const DEBRIEF_PROPOSE = '.debrief-propose'
338
- let _gitWarned = false
339
348
 
340
349
  function gitBinOk() {
341
350
  try {
@@ -386,72 +395,12 @@ function datedEntry(eng, date, text, signal) {
386
395
  return bits.join(' ')
387
396
  }
388
397
 
389
- function ensureMemoryGit(eng) {
390
- if (!eng || !fs.existsSync(eng)) return false
391
- if (fs.existsSync(path.join(eng, '.git'))) {
392
- writeOwnerIfMissing(eng)
393
- return true
394
- }
395
- if (!gitBinOk()) {
396
- if (!_gitWarned) {
397
- process.stderr.write('⚠ git not found - engagement memory will not be versioned (receipts stay dated, but not tamper-evident)\n')
398
- _gitWarned = true
399
- }
400
- writeOwnerIfMissing(eng)
401
- return false
402
- }
403
- try {
404
- execFileSync('git', ['init'], { cwd: eng, stdio: 'ignore', timeout: 10000 })
405
- atomicWriteFile(
406
- path.join(eng, '.gitignore'),
407
- ['*.lock', '*.tmp', '.last-write', '.debrief-propose', ''].join('\n')
408
- )
409
- writeOwnerIfMissing(eng)
410
- commitMemory(eng, 'init engagement memory')
411
- return true
412
- } catch (_) {
413
- return false
414
- }
415
- }
416
-
417
- function commitMemory(eng, message) {
418
- if (!eng || !fs.existsSync(path.join(eng, '.git'))) {
419
- if (!ensureMemoryGit(eng)) return null
420
- }
421
- if (!gitBinOk()) return null
422
- const owner = writeOwnerIfMissing(eng)
423
- try {
424
- execFileSync('git', ['add', '-A'], { cwd: eng, stdio: 'ignore', timeout: 10000 })
425
- const porcelain = execFileSync('git', ['status', '--porcelain'], {
426
- cwd: eng, encoding: 'utf8', timeout: 10000, stdio: ['ignore', 'pipe', 'ignore'],
427
- })
428
- if (!String(porcelain || '').trim()) return null
429
- const env = {
430
- ...process.env,
431
- GIT_AUTHOR_NAME: owner.name,
432
- GIT_AUTHOR_EMAIL: owner.email,
433
- GIT_COMMITTER_NAME: owner.name,
434
- GIT_COMMITTER_EMAIL: owner.email,
435
- }
436
- execFileSync('git', ['-c', 'commit.gpgsign=false', 'commit', '-m', String(message || 'memory write').slice(0, 72)], {
437
- cwd: eng, stdio: 'ignore', timeout: 15000, env,
438
- })
439
- return execFileSync('git', ['rev-parse', '--short', 'HEAD'], {
440
- cwd: eng, encoding: 'utf8', timeout: 5000, stdio: ['ignore', 'pipe', 'ignore'],
441
- }).toString().trim()
442
- } catch (_) {
443
- return null
444
- }
445
- }
446
-
447
- function memoryHead(eng) {
448
- if (!eng || !fs.existsSync(path.join(eng, '.git'))) return ''
449
- try {
450
- return execFileSync('git', ['rev-parse', '--short', 'HEAD'], {
451
- cwd: eng, encoding: 'utf8', timeout: 5000, stdio: ['ignore', 'pipe', 'ignore'],
452
- }).toString().trim()
453
- } catch (_) { return '' }
454
- }
398
+ const {
399
+ ensureMemoryGit,
400
+ memoryDirtyManual,
401
+ commitMemory,
402
+ memoryHead,
403
+ } = createMemoryApi({ fs, path, gitBinOk, writeOwnerIfMissing, atomicWriteFile })
455
404
 
456
405
  // Pull the body under a "## Heading" up to the next "##" (or EOF).
457
406
  function sectionBody(md, heading) {
@@ -509,169 +458,13 @@ function appendLogEntry(eng, type, entry, opts = {}) {
509
458
  lockedAppendFile(p, `\n${entry}\n`)
510
459
  }
511
460
  recordLastWrite(eng, LOG_FILES[type], entry)
512
- if (!opts.skipCommit) commitMemory(eng, opts.commitMsg || `log ${type}`)
513
- }
514
-
515
- // phase / trust / top risk / freshness - identical heuristic for status + dashboard.
516
- // Trust resolution: structured [signal:red|amber|green] tokens in stakeholders.md
517
- // (written by `fde log contact --signal` and `fde debrief`) win - the latest dated
518
- // one. Older than 21 days → stale: shown with a "?" marker + age so a forgotten
519
- // signal never silently drives triage. The keyword grep survives only as the
520
- // zero-effort floor when NO token exists anywhere - prose like "escalated to CTO,
521
- // resolved amicably" must not flip a client amber forever.
522
- function stakeholdersMemoryHealth(eng) {
523
- // Hostile handoff: binary / unparseable stakeholders must not read as healthy green.
524
- let buf
525
- try { buf = fs.readFileSync(path.join(eng, 'stakeholders.md')) } catch (_) {
526
- return { ok: true, warn: '' }
527
- }
528
- if (buf.includes(0)) {
529
- return { ok: false, warn: 'memory unreadable - verify (binary data in stakeholders.md)' }
530
- }
531
- const md = buf.toString('utf8')
532
- const ledger = readEng(eng, SIGNAL_LEDGER)
533
- if (/\[signal:(red|amber|green)\]/i.test(md + '\n' + ledger)) {
534
- return { ok: true, warn: '' }
535
- }
536
- const trustLine = md.match(/\*\*Trust:\*\*\s*([A-Za-z?]+)/i)
537
- if (trustLine && !/^(red|amber|green)$/i.test(trustLine[1])) {
538
- return { ok: false, warn: 'memory unreadable - verify (invalid trust value)' }
539
- }
540
- const table = parseMdTable(md)
541
- const meaningful = md.split('\n').filter(l => {
542
- const t = l.trim()
543
- return t && !t.startsWith('#') && !t.startsWith('<!--') && !/^\|?\s*:?-{3,}/.test(t)
544
- }).length
545
- // Content present but no table and no structured signal → do not invent "green"
546
- if (meaningful >= 3 && !table) {
547
- return { ok: false, warn: 'memory unreadable - verify (stakeholders.md unparseable)' }
461
+ if (!opts.skipCommit) {
462
+ const files = [LOG_FILES[type]]
463
+ if (type === 'contact' && /\[signal:(red|amber|green)\]/i.test(entry)) files.push(SIGNAL_LEDGER)
464
+ commitMemory(eng, opts.commitMsg || `log ${type}`, { files })
548
465
  }
549
- return { ok: true, warn: '' }
550
- }
551
-
552
- // Subject key for a signal-history line - first real name word (same spirit as
553
- // extractStakeholders). A green about Randy must not clear an amber about Denise.
554
- // Strip author tags [@email-local] so attribution never becomes the subject key.
555
- function signalSubjectKey(text) {
556
- const cleaned = String(text).replace(/\[@[^\]]+\]/g, '').replace(/\([^)]*\)/g, '')
557
- const words = cleaned.split(/\s+/).filter(w => w && !/^(dr|mr|mrs|ms)\.?$/i.test(w))
558
- const frag = (words[0] || '').replace(/[^a-z0-9]/gi, '').toLowerCase()
559
- return frag.length >= 3 ? frag : ('anon:' + cleaned.slice(0, 48).toLowerCase())
560
- }
561
-
562
- function parsePhase(ctx) {
563
- // Template ships "**Phase:** land | discover | ..." - that is UNSET, not land.
564
- const m = ctx.match(/\*\*Phase:\*\*\s*(.+)/i) || ctx.match(/^phase[:\s*]+(.+)$/im)
565
- if (!m) return '?'
566
- const raw = m[1].replace(/\*/g, '').trim()
567
- if (!raw || /\|/.test(raw) || /^unset$/i.test(raw) || /^[\[(]/.test(raw)) return '?'
568
- const one = raw.toLowerCase().match(/^(land|discover|plan|build|ship|close)\b/)
569
- return one ? one[1] : '?'
570
466
  }
571
467
 
572
- function countOpenRisks(eng) {
573
- const md = readClean(eng, 'risks.md')
574
- const body = md.split(/^#{1,6}\s+Retired\b/im)[0] || md
575
- let n = 0
576
- for (const raw of body.split('\n')) {
577
- const t = raw.trim()
578
- if (!t || t.startsWith('<!--') || /^#{1,6}\s/.test(t)) continue
579
- if (/risk\s*\|\s*status|mitigation/i.test(t) || /^\|?[\s|:-]+$/.test(t)) continue
580
- if (/^[-*]/.test(t) || (/^\|/.test(t) && t.length > 12)) n++
581
- }
582
- return n
583
- }
584
-
585
- function nextActionLine(ctx) {
586
- const body = sectionBody(ctx, 'Next action')
587
- for (const raw of body.split('\n')) {
588
- const t = raw.trim().replace(/^[-*]\s+/, '')
589
- if (t) return t.slice(0, 120)
590
- }
591
- return ''
592
- }
593
-
594
- function computeSignals(eng) {
595
- // readClean, not readEng: status/dashboard echo topRisk and stakeholder lines
596
- // to the terminal and the rendered HTML - a <private> risk must never surface.
597
- const ctx = readClean(eng, 'context.md'); const stake = readClean(eng, 'stakeholders.md'); const risks = readClean(eng, 'risks.md')
598
- // Prefer structured tokens from stakeholders + CLI ledger (ledger survives wipes)
599
- const signalText = stake + '\n' + readClean(eng, SIGNAL_LEDGER)
600
- const phase = parsePhase(ctx)
601
- // Latest signal PER stakeholder, then worst-of those actives.
602
- // Global "latest wins" let a green from person B hide a sponsor crisis on A.
603
- const byPerson = new Map()
604
- for (const l of signalText.split('\n')) {
605
- const sm = l.match(/\[signal:(red|amber|green)\]/i)
606
- if (!sm) continue
607
- const date = (l.match(/\[(\d{4}-\d{2}-\d{2})\]/) || [])[1] || ''
608
- const text = l.replace(/^\s*-\s*/, '')
609
- .replace(/\[signal:(red|amber|green)\]/i, '')
610
- .replace(/\[\d{4}-\d{2}-\d{2}\]/, '')
611
- .replace(/\[@[^\]]+\]/g, '')
612
- .trim()
613
- const key = signalSubjectKey(text)
614
- const prev = byPerson.get(key)
615
- if (!prev || date >= prev.date) byPerson.set(key, { date, sig: sm[1].toLowerCase(), text })
616
- }
617
- const RANK = { red: 0, amber: 1, green: 2 }
618
- let worst = null
619
- for (const s of byPerson.values()) {
620
- if (!worst || RANK[s.sig] < RANK[worst.sig] || (RANK[s.sig] === RANK[worst.sig] && s.date >= worst.date)) {
621
- worst = s
622
- }
623
- }
624
- const mem = stakeholdersMemoryHealth(eng)
625
- let trust, signalAge = null, stale = false, trustReason = ''
626
- if (!mem.ok && !worst) {
627
- trust = 'amber'
628
- trustReason = mem.warn
629
- } else if (worst) {
630
- trust = worst.sig === 'red' ? 'RED' : worst.sig
631
- trustReason = (worst.text || '').slice(0, 80)
632
- if (worst.date) {
633
- signalAge = Math.max(0, Math.floor((Date.now() - Date.parse(worst.date)) / 86400000))
634
- stale = signalAge > 21
635
- }
636
- } else {
637
- const sLines = stake.split('\n').filter(l => !(/green/i.test(l) && /red|amber/i.test(l)))
638
- trust = sLines.some(l => /\bred\b/i.test(l)) ? 'RED'
639
- : sLines.some(l => /amber|gone quiet|routing around|escalat/i.test(l)) ? 'amber' : 'green'
640
- }
641
- const topRisk = (risks.split('\n').find(l => {
642
- const t = l.trim()
643
- return /^[-|]/.test(t) && t.length > 20 && !/^\|?[-\s|]+$/.test(t) &&
644
- !/risk\s*\|\s*status|mitigation/i.test(t) && !t.startsWith('<!--')
645
- }) || '').replace(/\|/g, ' ').replace(/\s+/g, ' ').trim().slice(0, 80)
646
- // Prefer the trust trigger (signal / memory warn) over a random risk line when triage is not green
647
- const reason = (trust !== 'green' && (trustReason || mem.warn)) ? (trustReason || mem.warn) : topRisk
648
- const openRisks = countOpenRisks(eng)
649
- const nextAction = nextActionLine(ctx)
650
- let updated = 'never', ageDays = Infinity
651
- try {
652
- ageDays = Math.floor((Date.now() - fs.statSync(path.join(eng, 'context.md')).mtimeMs) / 86400000)
653
- updated = ageDays === 0 ? 'today' : `${ageDays}d ago`
654
- } catch (_) {}
655
- return { phase, trust, signalAge, stale, topRisk, reason, memoryWarn: mem.warn, openRisks, nextAction, updated, ageDays }
656
- }
657
-
658
- function resumeTriage(eng) {
659
- const s = computeSignals(eng)
660
- const label = s.trust + (s.stale ? '?' : '')
661
- const phase = s.phase === '?' ? 'unset' : s.phase
662
- const lines = [
663
- `TRIAGE [${label.padEnd(6)}] phase:${phase} updated:${s.updated} open risks:${s.openRisks}`,
664
- ]
665
- if (s.reason) {
666
- const age = s.signalAge != null ? ` (${s.signalAge}d old${s.stale ? ', STALE - reconfirm' : ''})` : ''
667
- lines.push(` trust: ${s.reason}${age}`)
668
- }
669
- if (s.nextAction) lines.push(` next: ${s.nextAction}`)
670
- else lines.push(' next: (none set - add under ## Next action in context.md)')
671
- return lines.join('\n')
672
- }
673
-
674
-
675
468
  // ---------- dashboard content extractors (best-effort, read-only) ----------
676
469
  // The fieldbook's structured widgets (stakeholders, risks, log, stats) want
677
470
  // data shapes that .fde/ markdown does not literally carry - it is written by
@@ -743,6 +536,15 @@ function parseMdTable(md) {
743
536
  }
744
537
  function colIndex(headers, rx) { return headers.findIndex(h => rx.test(h)) }
745
538
 
539
+ const {
540
+ signalSubjectKey,
541
+ nextActionLine,
542
+ computeSignals,
543
+ resumeTriage,
544
+ } = createTrustApi({
545
+ fs, path, readClean, readEng, parseMdTable, sectionBody, SIGNAL_LEDGER, memoryDirtyManual,
546
+ })
547
+
746
548
  // Stakeholders: columns are matched by header wording, not position - real
747
549
  // files use "Name" or "Name / role", "Stance" or "Signal", with or without a
748
550
  // separate Role column (see examples/garvey-payments vs examples/kesterman-
@@ -1181,7 +983,9 @@ function cmdLogUndo() {
1181
983
  if (led != null) withFileLock(ledgerPath, () => { atomicWriteFile(ledgerPath, led.endsWith('\n') ? led : led + '\n') })
1182
984
  }
1183
985
  try { fs.unlinkSync(metaPath) } catch (_) {}
1184
- const hash = commitMemory(eng, `undo ${meta.file}`)
986
+ const undoFiles = [meta.file]
987
+ if (/\[signal:(red|amber|green)\]/i.test(meta.entry)) undoFiles.push(SIGNAL_LEDGER)
988
+ const hash = commitMemory(eng, `undo ${meta.file}`, { files: undoFiles })
1185
989
  console.log(`undid last write → ${meta.file}${hash ? ` @${hash}` : ''}`)
1186
990
  }
1187
991
 
@@ -1242,7 +1046,7 @@ function setContextPhase(eng, phase) {
1242
1046
  md = md.replace(/\*\*Last updated:\*\*\s*.*/i, `**Last updated:** ${today}`)
1243
1047
  }
1244
1048
  withFileLock(p, () => { atomicWriteFile(p, md.endsWith('\n') ? md : md + '\n') })
1245
- return commitMemory(eng, `phase ${phase}`)
1049
+ return commitMemory(eng, `phase ${phase}`, { files: ['context.md'] })
1246
1050
  }
1247
1051
 
1248
1052
 
@@ -1444,7 +1248,9 @@ function cmdDebrief(args) {
1444
1248
 
1445
1249
  const { counts, ctxLines } = routeDebriefInput(eng, input, { dry, force })
1446
1250
  if (!dry) {
1447
- const hash = commitMemory(eng, 'debrief')
1251
+ const hash = commitMemory(eng, 'debrief', {
1252
+ files: ['decisions.md', 'risks.md', 'delivery.md', 'stakeholders.md', 'context.md', SIGNAL_LEDGER],
1253
+ })
1448
1254
  try { fs.unlinkSync(path.join(eng, DEBRIEF_PROPOSE)) } catch (_) {}
1449
1255
  if (hash) console.log(`memory @${hash}`)
1450
1256
  }
@@ -1487,7 +1293,7 @@ function cmdReceipts(args) {
1487
1293
  const agreed = collect(AGREEMENTS)
1488
1294
  const claimed = collect(CLAIMS)
1489
1295
  if (agreed.length) {
1490
- console.log('AGREED (dated record - defensible):')
1296
+ console.log('ON RECORD (dated - defensible):')
1491
1297
  agreed.forEach(h => console.log(h))
1492
1298
  }
1493
1299
  if (claimed.length) {
@@ -1525,7 +1331,7 @@ function cmdCapture() {
1525
1331
  try {
1526
1332
  ensureMemoryGit(eng)
1527
1333
  lockedAppendFile(path.join(eng, 'context.md'), block, { soft: true })
1528
- commitMemory(eng, 'session capture')
1334
+ commitMemory(eng, 'session capture', { files: ['context.md'] })
1529
1335
  } catch (_) {}
1530
1336
  }
1531
1337
 
@@ -1557,7 +1363,7 @@ function cmdOwner(args) {
1557
1363
  withFileLock(path.join(eng, OWNER_FILE), () => {
1558
1364
  atomicWriteFile(path.join(eng, OWNER_FILE), `name: ${name}\nemail: ${email}\n`)
1559
1365
  })
1560
- const hash = commitMemory(eng, 'owner set')
1366
+ const hash = commitMemory(eng, 'owner set', { files: [OWNER_FILE] })
1561
1367
  console.log(`owner → ${name} <${email}>${hash ? ` @${hash}` : ''}`)
1562
1368
  return
1563
1369
  }
@@ -1568,6 +1374,49 @@ function cmdOwner(args) {
1568
1374
  else console.log('memory HEAD: (unversioned - git init on next write)')
1569
1375
  }
1570
1376
 
1377
+ function riskFingerprint(text) {
1378
+ return String(text || '')
1379
+ .toLowerCase()
1380
+ .replace(/\[\d{4}-\d{2}-\d{2}\]/g, '')
1381
+ .replace(/\[@[^\]]+\]/g, '')
1382
+ .replace(/^\s*[-*|]\s*/, '')
1383
+ .replace(/[^a-z0-9]+/g, ' ')
1384
+ .trim()
1385
+ .split(/\s+/)
1386
+ .slice(0, 5)
1387
+ .join(' ')
1388
+ }
1389
+
1390
+ function findDuplicateOpenRisks(eng) {
1391
+ // Scan raw open risks (not extractRisks - that dedupes exact text).
1392
+ const md = readClean(eng, 'risks.md')
1393
+ const body = md.split(/^#{1,6}\s+Retired\b/im)[0] || md
1394
+ const items = []
1395
+ const table = parseMdTable(body)
1396
+ if (table) {
1397
+ const riskIdx = colIndex(table.headers, /^risk$/i)
1398
+ if (riskIdx !== -1) {
1399
+ for (const cs of table.rows) {
1400
+ const t = (cs[riskIdx] || '').trim()
1401
+ if (t) items.push(t)
1402
+ }
1403
+ }
1404
+ }
1405
+ for (const raw of body.split('\n')) {
1406
+ const t = raw.trim()
1407
+ const m = t.match(/^-\s*\[\d{4}-\d{2}-\d{2}\]\s*(?:\[@[^\]]+\]\s*)?(.*)$/)
1408
+ if (m && m[1].trim()) items.push(m[1].trim())
1409
+ }
1410
+ const byKey = new Map()
1411
+ for (const text of items) {
1412
+ const key = riskFingerprint(text)
1413
+ if (key.length < 12) continue
1414
+ if (!byKey.has(key)) byKey.set(key, [])
1415
+ byKey.get(key).push(text)
1416
+ }
1417
+ return [...byKey.values()].filter(g => g.length >= 2)
1418
+ }
1419
+
1571
1420
  function cmdDoctor() {
1572
1421
  const eng = resolveEngagement()
1573
1422
  if (!eng) { console.error('no engagement - run: fde resume --init <name>'); process.exit(2) }
@@ -1587,6 +1436,18 @@ function cmdDoctor() {
1587
1436
  if (!sectionBody(readClean(eng, 'context.md'), 'Next action')) {
1588
1437
  issues.push('no ## Next action in context.md - Monday morning has nothing to drive')
1589
1438
  }
1439
+ if ((s.phase === 'close' || s.phase === 'ship') && s.openRisks > 0) {
1440
+ issues.push(
1441
+ `phase is ${s.phase} with ${s.openRisks} open risk(s) - retire, hand off, or move still-live ones before calling the embed done`
1442
+ )
1443
+ }
1444
+ const dupes = findDuplicateOpenRisks(eng)
1445
+ if (dupes.length) {
1446
+ const sample = (dupes[0][0] || '').replace(/\s+/g, ' ').trim().slice(0, 60)
1447
+ issues.push(
1448
+ `${dupes.length} duplicate open-risk cluster(s) (e.g. "${sample}${sample.length >= 60 ? '…' : ''}") - consolidate or retire echoes in risks.md`
1449
+ )
1450
+ }
1590
1451
  console.log(`FDE DOCTOR - ${engagementSlugFromPath(eng)}`)
1591
1452
  console.log(resumeTriage(eng))
1592
1453
  if (!issues.length) {
@@ -1598,6 +1459,73 @@ function cmdDoctor() {
1598
1459
  process.exit(1)
1599
1460
  }
1600
1461
 
1462
+ // Remove buried lines that contain a search term (secrets noticed hours later).
1463
+ // Preview by default; --apply commits the scrub to the memory ledger.
1464
+ const REDACT_FILES = [
1465
+ 'decisions.md', 'risks.md', 'delivery.md', 'stakeholders.md', 'context.md',
1466
+ 'brief.md', 'reality.md', 'assumptions.md', SIGNAL_LEDGER,
1467
+ ]
1468
+
1469
+ function cmdRedact(args) {
1470
+ const apply = args.includes('--apply')
1471
+ const term = args.filter(a => a !== '--apply').join(' ').trim()
1472
+ if (!term || term.length < 4) {
1473
+ console.error('usage: fde redact <term> [--apply]\n preview lines containing <term>; --apply removes them and commits the ledger')
1474
+ process.exit(1)
1475
+ }
1476
+ const eng = resolveEngagement({ forWrite: apply })
1477
+ if (!eng) { console.error('no engagement - run: fde resume --init <name>'); process.exit(2) }
1478
+ const needle = term.toLowerCase()
1479
+ const hits = []
1480
+ for (const file of REDACT_FILES) {
1481
+ const abs = path.join(eng, file)
1482
+ if (!fs.existsSync(abs)) continue
1483
+ const md = readEng(eng, file)
1484
+ const lines = md.split('\n')
1485
+ lines.forEach((line, i) => {
1486
+ if (line.toLowerCase().includes(needle)) hits.push({ file, lineNo: i + 1, line })
1487
+ })
1488
+ }
1489
+ if (!hits.length) {
1490
+ console.log(`redact: no lines contain ${JSON.stringify(term)}`)
1491
+ return
1492
+ }
1493
+ console.log(`REDACT - ${hits.length} matching line(s) for ${JSON.stringify(term)}`)
1494
+ hits.slice(0, 20).forEach(h => {
1495
+ const preview = h.line.length > 100 ? h.line.slice(0, 97) + '…' : h.line
1496
+ console.log(` ${h.file}:${h.lineNo} ${preview}`)
1497
+ })
1498
+ if (hits.length > 20) console.log(` … +${hits.length - 20} more`)
1499
+ if (!apply) {
1500
+ console.log('\nPreview only. Remove and commit: fde redact <term> --apply')
1501
+ console.log('Note: git history still holds prior commits - rotate the real secret.')
1502
+ return
1503
+ }
1504
+ ensureMemoryGit(eng)
1505
+ const touched = []
1506
+ const byFile = new Map()
1507
+ for (const h of hits) {
1508
+ if (!byFile.has(h.file)) byFile.set(h.file, new Set())
1509
+ byFile.get(h.file).add(h.lineNo)
1510
+ }
1511
+ for (const [file, lineNos] of byFile) {
1512
+ const abs = path.join(eng, file)
1513
+ const before = readEng(eng, file)
1514
+ const kept = before.split('\n').filter((_, i) => !lineNos.has(i + 1))
1515
+ const after = kept.join('\n')
1516
+ if (after === before) continue
1517
+ withFileLock(abs, () => { atomicWriteFile(abs, after.endsWith('\n') || after === '' ? after : after + '\n') })
1518
+ touched.push(file)
1519
+ }
1520
+ if (!touched.length) {
1521
+ console.log('nothing changed')
1522
+ return
1523
+ }
1524
+ const hash = commitMemory(eng, `redact ${term.slice(0, 40)}`, { files: touched })
1525
+ console.log(`redacted ${hits.length} line(s) in ${touched.join(', ')}${hash ? ` @${hash}` : ''}`)
1526
+ console.log('rotate the real credential if this was a secret - history may still contain it')
1527
+ }
1528
+
1601
1529
  function cmdPrep(args) {
1602
1530
  const eng = resolveEngagement()
1603
1531
  if (!eng) { console.error('no engagement - run: fde resume --init <name>'); process.exit(2) }
@@ -1719,7 +1647,7 @@ function cmdGarden(args) {
1719
1647
  applied++
1720
1648
  console.log(`applied: archived ${p.sessionBlocks.length} old session-end blocks → context-archive.md`)
1721
1649
  }
1722
- const hash = commitMemory(eng, 'garden')
1650
+ const hash = commitMemory(eng, 'garden', { files: ['context.md', 'context-archive.md'] })
1723
1651
  if (!applied) console.log('no mechanical proposals applied (manual items remain)')
1724
1652
  else console.log(`garden done${hash ? ` @${hash}` : ''}`)
1725
1653
  }
@@ -1738,7 +1666,8 @@ function cmdStatus(args) {
1738
1666
  const eng = path.join(ENGAGEMENTS_ROOT, d, '.fde')
1739
1667
  if (!fs.existsSync(eng)) continue
1740
1668
  const s = computeSignals(eng)
1741
- rows.push({ name: d, phase: s.phase, trust: s.trust, signalAge: s.signalAge, stale: s.stale, updated: s.updated, reason: (s.reason || s.topRisk).slice(0, 60) })
1669
+ const note = [s.memoryWarn, (s.dirtyFiles && s.dirtyFiles.length) ? `dirty:${s.dirtyFiles.length}` : '', s.reason || s.topRisk].filter(Boolean).join(' · ').slice(0, 70)
1670
+ rows.push({ name: d, phase: s.phase, trust: s.trust, signalAge: s.signalAge, stale: s.stale, updated: s.updated, reason: note, memoryWarn: s.memoryWarn, dirtyFiles: s.dirtyFiles })
1742
1671
  }
1743
1672
  } else {
1744
1673
  const eng = resolveEngagement()
@@ -1747,7 +1676,8 @@ function cmdStatus(args) {
1747
1676
  process.exit(2)
1748
1677
  }
1749
1678
  const s = computeSignals(eng)
1750
- rows.push({ name: engagementSlugFromPath(eng), phase: s.phase, trust: s.trust, signalAge: s.signalAge, stale: s.stale, updated: s.updated, reason: (s.reason || s.topRisk).slice(0, 60) })
1679
+ const note = [s.memoryWarn, (s.dirtyFiles && s.dirtyFiles.length) ? `dirty:${s.dirtyFiles.length}` : '', s.reason || s.topRisk].filter(Boolean).join(' · ').slice(0, 70)
1680
+ rows.push({ name: engagementSlugFromPath(eng), phase: s.phase, trust: s.trust, signalAge: s.signalAge, stale: s.stale, updated: s.updated, reason: note, memoryWarn: s.memoryWarn, dirtyFiles: s.dirtyFiles })
1751
1681
  }
1752
1682
  if (!rows.length) { console.log('no engagements yet'); return }
1753
1683
  const order = { RED: 0, amber: 1, green: 2 }
@@ -1758,91 +1688,19 @@ function cmdStatus(args) {
1758
1688
  const label = r.trust + (r.stale ? '?' : '')
1759
1689
  const sig = r.signalAge != null ? `signal ${r.signalAge}d old${r.stale ? ' (STALE - reconfirm)' : ''} ` : ''
1760
1690
  console.log(` [${label.padEnd(6)}] ${r.name.padEnd(24)} phase:${(r.phase === '?' ? 'unset' : r.phase).padEnd(10)} updated:${r.updated.padEnd(8)} ${sig}${r.reason}`)
1691
+ if (r.memoryWarn) console.log(` memory: ${r.memoryWarn}`)
1692
+ if (r.dirtyFiles && r.dirtyFiles.length) {
1693
+ console.log(` ⚠ dirty (uncommitted manual edits): ${r.dirtyFiles.slice(0, 5).join(', ')}`)
1694
+ }
1761
1695
  }
1762
1696
  if (!all) console.log('\n(current engagement only - pass --all for the full portfolio)')
1763
1697
  console.log('\ntrust: worst active [signal:x] across stakeholders (latest per person) - a green from B cannot clear an amber/red on A; keyword heuristic only when none exists.')
1764
1698
  }
1765
1699
 
1766
- // ---------- dashboard (deterministic markdown → one local HTML) ----------
1767
-
1768
- function escapeHtml(s) {
1769
- return String(s)
1770
- .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
1771
- .replace(/"/g, '&quot;').replace(/'/g, '&#39;')
1772
- }
1773
-
1774
- // Never leak <private> notes or template hint comments into the rendered page.
1775
- // Closed pairs are redacted; an unclosed <private> redacts to end-of-text so a
1776
- // forgotten closing tag can never leak the rest of the file.
1777
- function stripPrivate(md) {
1778
- // Redact <private> before <!-- --> so a private block that itself contains a
1779
- // comment can't survive. Closed pairs first; then any unclosed <private> to
1780
- // end-of-text so a forgotten close tag never leaks the rest of the file.
1781
- // Case-insensitive (<PRIVATE> too). This is the ONE redactor every read path
1782
- // that can reach the model or a shared artifact must go through - see readClean.
1783
- return md
1784
- .replace(/<private>[\s\S]*?<\/private>/gi, '(private - redacted)')
1785
- .replace(/<private>[\s\S]*$/i, '(private - redacted)')
1786
- .replace(/<!--[\s\S]*?-->/g, '')
1787
- }
1788
-
1789
- function inlineMd(s) {
1790
- return escapeHtml(s)
1791
- .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
1792
- .replace(/`([^`]+)`/g, '<code>$1</code>')
1793
- }
1794
1700
 
1795
- // Generic markdown -> HTML for the three .fde files that are reference
1796
- // documents, not logs (success.md, terrain.md, trust-profile.md): they don't
1797
- // fit the structured stakeholder/risk/log widgets, but they're real content
1798
- // (trust-profile.md especially - sacred data and AI policy) and must stay
1799
- // visible in the fieldbook, not silently dropped. Headings, tables, bullet
1800
- // lists, and paragraphs only - matches what these files actually contain.
1801
- function mdBlockHtml(md) {
1802
- const lines = md.split('\n')
1803
- const out = []; let i = 0
1804
- while (i < lines.length) {
1805
- const t = lines[i].trim()
1806
- if (!t) { i++; continue }
1807
- if (/^\|.*\|/.test(t)) {
1808
- const tbl = []
1809
- while (i < lines.length && /^\s*\|.*\|/.test(lines[i])) { tbl.push(lines[i]); i++ }
1810
- const parsed = parseMdTable(tbl.join('\n'))
1811
- if (parsed) {
1812
- out.push('<table class="fb-table"><thead><tr>' + parsed.headers.map(h => '<th>' + inlineMd(h) + '</th>').join('') + '</tr></thead><tbody>' +
1813
- parsed.rows.map(r => '<tr>' + r.map(c => '<td>' + inlineMd(c) + '</td>').join('') + '</tr>').join('') + '</tbody></table>')
1814
- }
1815
- continue
1816
- }
1817
- const h = t.match(/^(#{1,6})\s+(.*)$/)
1818
- if (h) { out.push('<div class="fb-sec">' + inlineMd(h[2]) + '</div>'); i++; continue }
1819
- if (/^[-*]\s+/.test(t)) {
1820
- const items = []
1821
- while (i < lines.length && /^\s*[-*]\s+/.test(lines[i])) { items.push('<li>' + inlineMd(lines[i].trim().replace(/^[-*]\s+/, '')) + '</li>'); i++ }
1822
- out.push('<ul class="fb-plain-list">' + items.join('') + '</ul>'); continue
1823
- }
1824
- const para = []
1825
- while (i < lines.length && lines[i].trim() && !/^\s*\|.*\|/.test(lines[i]) && !/^#{1,6}\s/.test(lines[i].trim()) && !/^[-*]\s+/.test(lines[i].trim())) {
1826
- para.push(lines[i].trim()); i++
1827
- }
1828
- out.push('<p class="fb-plain-p">' + inlineMd(para.join(' ')) + '</p>')
1829
- }
1830
- return out.join('\n')
1831
- }
1701
+ // ---------- dashboard (deterministic markdown one local HTML) ----------
1832
1702
 
1833
- // True if a file has real content beyond headings, empty table cells, and
1834
- // blank bullets - same heuristic the old dashboard used to skip empty files.
1835
- function hasRealContent(md) {
1836
- const txt = md
1837
- .replace(/^#{1,6}\s.*$/gm, '')
1838
- .replace(/^\s*\|[\s:|-]+\|\s*$/gm, '')
1839
- .replace(/^\s*\|[\s|]*\|\s*$/gm, '')
1840
- .replace(/\*\*[^*]+:\*\*\s*$/gm, '')
1841
- .replace(/[-*]\s*$/gm, '')
1842
- .replace(/\s+/g, ' ')
1843
- .trim()
1844
- return txt.length > 0
1845
- }
1703
+ const render = require("./lib/render")
1846
1704
 
1847
1705
  function gatherEngagements(opts = {}) {
1848
1706
  const list = []
@@ -1860,518 +1718,6 @@ function gatherEngagements(opts = {}) {
1860
1718
  return list
1861
1719
  }
1862
1720
 
1863
- // Geist (400-700 variable weight) + Geist Mono (400-600 variable weight),
1864
- // latin subset only, base64-embedded woff2 - zero network calls, still opens
1865
- // fully offline. Spliced in verbatim by the build step below; never fetched.
1866
- const FONT_FACE_CSS = `@font-face {
1867
- font-family: 'Geist';
1868
- font-style: normal;
1869
- font-weight: 400 700;
1870
- font-display: swap;
1871
- src: url(data:font/woff2;base64,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) format('woff2');
1872
- 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;
1873
- }
1874
- @font-face {
1875
- font-family: 'Geist Mono';
1876
- font-style: normal;
1877
- font-weight: 400 600;
1878
- font-display: swap;
1879
- src: url(data:font/woff2;base64,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) format('woff2');
1880
- 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;
1881
- }`
1882
-
1883
- const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
1884
- const WEEKDAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
1885
- function formatToday(d) { return `${WEEKDAYS[d.getDay()]}, ${MONTHS[d.getMonth()]} ${d.getDate()}` }
1886
- function formatLogDate(iso) {
1887
- const m = String(iso).match(/^(\d{4})-(\d{2})-(\d{2})$/)
1888
- return m ? `${MONTHS[parseInt(m[2], 10) - 1]} ${parseInt(m[3], 10)}` : iso
1889
- }
1890
- function trustWord(t) { return t === 'green' ? 'steady' : t === 'amber' ? 'watch' : 'at risk' }
1891
- function dotClassFor(trust) { return trust === 'RED' ? 'red' : trust }
1892
-
1893
- // Two-pane fieldbook: left rail (search + today + per-client nav), right main
1894
- // panel with a Today queue view and a per-client detail view, plus a command
1895
- // palette overlay. Light + dark are both full, real token sets (not one
1896
- // derived from the other) - translated 1:1 from the design's THEMES object
1897
- // into the file's existing :root / html[data-fde-theme="dark"] mechanism.
1898
- function dashStyles() {
1899
- return `
1900
- :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)}
1901
- 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)}
1902
- ${FONT_FACE_CSS}
1903
- *,*::before,*::after{box-sizing:border-box}
1904
- html,body{margin:0;padding:0;height:100%}
1905
- 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}
1906
- ::selection{background:var(--accent-bg)}
1907
- button,input{font-family:inherit}
1908
- code{background:var(--panel);padding:1px 5px;border-radius:4px;font-size:12px;color:var(--ink-soft);font-family:'Geist Mono',monospace}
1909
- strong{font-weight:600}
1910
- .empty{color:var(--ink-faint);font-style:italic;font-size:13px}
1911
- .fb-app{height:100vh;display:flex;flex-direction:column;overflow:hidden}
1912
- .fb-scroll::-webkit-scrollbar{width:7px;height:7px}
1913
- .fb-scroll::-webkit-scrollbar-thumb{background:var(--line);border-radius:7px}
1914
- .fb-scroll::-webkit-scrollbar-track{background:transparent}
1915
- .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)}
1916
- .fb-brand{display:flex;align-items:baseline;gap:9px}
1917
- .fb-wordmark{font-family:'Geist Mono',monospace;font-size:14px;font-weight:700;letter-spacing:.01em}
1918
- .fb-tagline{font-family:'Geist Mono',monospace;font-size:12px;color:var(--ink-faint)}
1919
- .fb-need{font-family:'Geist Mono',monospace;font-size:11.5px;color:var(--accent);margin-left:8px}
1920
- .fb-spacer{flex:1 1 auto}
1921
- .fb-today{font-family:'Geist Mono',monospace;font-size:11.5px;color:var(--ink-faint)}
1922
- .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}
1923
- .fb-btn:hover{color:var(--ink);border-color:var(--accent)}
1924
- .fb-body{flex:1 1 auto;display:flex;min-height:0}
1925
- .fb-rail{flex:0 0 288px;display:flex;flex-direction:column;background:var(--bg);border-right:1px solid var(--line)}
1926
- .fb-rail-search{flex:0 0 auto;padding:12px 14px}
1927
- .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}
1928
- .fb-search:focus{border-color:var(--accent)}
1929
- .fb-search::placeholder{color:var(--ink-faint)}
1930
- .fb-rail-list{flex:1 1 auto;overflow-y:auto;padding:0 8px 16px}
1931
- .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}
1932
- .fb-nav:hover{background:var(--panel)}
1933
- .fb-nav.active{background:var(--panel);border-left-color:var(--accent)}
1934
- .fb-nav.hide{display:none}
1935
- .fb-nav-row{display:flex;align-items:center;gap:8px}
1936
- .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}
1937
- .fb-nav.active .fb-nav-name{font-weight:600}
1938
- .fb-nav-today{color:var(--accent);font-weight:600}
1939
- .fb-nav-count{margin-left:auto;font-family:'Geist Mono',monospace;font-size:10.5px;color:var(--ink-faint)}
1940
- .fb-nav-meta{margin-top:3px;padding-left:14px;font-family:'Geist Mono',monospace;font-size:10.5px;color:var(--ink-faint)}
1941
- .fb-nav-reason{margin-top:3px;padding-left:14px;font-size:12px;line-height:1.35;color:var(--ink-soft)}
1942
- .fb-nav-reason.hide{display:none}
1943
- .fb-nav-reason mark{background:var(--accent-bg);color:inherit;border-radius:2px;padding:0 1px}
1944
- .fb-main{flex:1 1 auto;overflow-y:auto;background:var(--bg)}
1945
- .fb-main-inner{max-width:1440px;margin:0 auto;padding:28px 48px 64px}
1946
- .fb-grid-wrap{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:22px 40px;margin-top:22px}
1947
- .fb-grid-wrap .fb-block{margin-top:0}
1948
- .fb-top-grid{display:grid;grid-template-columns:1fr 280px;gap:0 32px;align-items:stretch}
1949
- .fb-vitals{display:flex;flex-direction:column;margin-top:22px;padding:16px 18px;background:var(--panel);border:1px solid var(--line);border-radius:8px}
1950
- .fb-vital-row{display:flex;justify-content:space-between;gap:10px;padding:5px 0;font-size:12.5px}
1951
- .fb-vital-row+.fb-vital-row{border-top:1px solid var(--line)}
1952
- .fb-vital-label{font-family:'Geist Mono',monospace;font-size:10.5px;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-faint)}
1953
- .fb-vital-val{color:var(--ink);font-weight:600;text-align:right}
1954
- .fb-vital-div{margin:4px 0;border-top:1px solid var(--line)}
1955
- @media(max-width:920px){.fb-top-grid{grid-template-columns:1fr}.fb-vitals{max-width:400px}}
1956
- .fb-view[hidden]{display:none}
1957
- .fb-eyebrow{font-family:'Geist Mono',monospace;font-size:11px;color:var(--ink-faint)}
1958
- .fb-h1{font-family:'Geist Mono',monospace;font-size:26px;font-weight:600;letter-spacing:-.01em;margin:6px 0 0}
1959
- .fb-title-row{display:flex;align-items:baseline;gap:10px;margin-top:6px}
1960
- .fb-title-row .fb-h1{margin-top:0}
1961
- .fb-trust{display:flex;align-items:center;gap:6px;font-family:'Geist Mono',monospace;font-size:12px}
1962
- .fb-meta-line{margin-top:5px;font-family:'Geist Mono',monospace;font-size:12px;color:var(--ink-faint)}
1963
- .fb-block{margin-top:22px;padding-top:18px;border-top:1px solid var(--line)}
1964
- .fb-sec{font-family:'Geist Mono',monospace;font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--accent);margin:0 0 8px}
1965
- .fb-sec-row{display:flex;align-items:baseline;gap:8px}
1966
- .fb-sec-row .fb-sec{margin:0}
1967
- .fb-count{font-family:'Geist Mono',monospace;font-size:10.5px;color:var(--ink-faint)}
1968
- .fb-now-action{font-size:16.5px;font-weight:600;line-height:1.5;color:var(--ink)}
1969
- .fb-now-session{margin-top:10px;font-size:14.5px;line-height:1.6;color:var(--ink-soft)}
1970
- .fb-why{margin:0;font-size:14.5px;line-height:1.6;color:var(--ink)}
1971
- .fb-why-reality{margin-top:8px}
1972
- .fb-accent-label{color:var(--accent);font-weight:600}
1973
- .fb-stats{display:flex;gap:22px;flex-wrap:wrap;font-family:'Geist Mono',monospace;font-size:13.5px}
1974
- .fb-stat{display:inline-flex;align-items:baseline;gap:6px;padding:2px 0}
1975
- .fb-arrow{color:var(--ink-faint)}
1976
- .fb-stat-to{color:var(--ink);font-weight:600}
1977
- .fb-list{margin-top:2px}
1978
- .fb-row{display:flex;align-items:baseline;gap:10px;padding:7px 8px;margin:0 -8px;border-radius:5px}
1979
- .fb-list .fb-row:nth-child(even){background:var(--panel)}
1980
- .fb-row:hover{background:var(--rowhover)!important}
1981
- .fb-person-name{font-size:14px;font-weight:600;color:var(--ink);flex:0 0 150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1982
- .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}
1983
- .fb-person-note{font-size:13px;color:var(--ink-soft);flex:1 1 auto}
1984
- .fb-risk-sev{font-family:'Geist Mono',monospace;font-size:10.5px;letter-spacing:.04em;text-transform:uppercase;flex:0 0 38px}
1985
- .fb-risk-text{font-size:14px;line-height:1.4;color:var(--ink);flex:1 1 auto}
1986
- .fb-log-date{font-family:'Geist Mono',monospace;font-size:11.5px;color:var(--ink-faint);flex:0 0 48px}
1987
- .fb-log-kind{font-family:'Geist Mono',monospace;font-size:10px;letter-spacing:.03em;text-transform:uppercase;flex:0 0 62px}
1988
- .fb-log-text{flex:1 1 auto;font-size:14px;line-height:1.5;color:var(--ink)}
1989
- .fb-more{border-top:1px solid var(--line);padding:12px 0}
1990
- .fb-more:first-child{border-top:none;padding-top:0}
1991
- .fb-more-sum{cursor:pointer;list-style:none;display:flex;align-items:center;gap:6px}
1992
- .fb-more-sum::-webkit-details-marker{display:none}
1993
- .fb-more-sum::before{content:'\\2023';color:var(--ink-faint);transition:transform .12s}
1994
- .fb-more[open] .fb-more-sum::before{transform:rotate(90deg)}
1995
- .fb-more-body{margin-top:10px}
1996
- .fb-plain-p{font-size:14px;line-height:1.55;color:var(--ink-soft);margin:0 0 10px}
1997
- .fb-plain-list{margin:0 0 10px;padding-left:18px}
1998
- .fb-plain-list li{font-size:14px;line-height:1.55;color:var(--ink-soft);margin:2px 0}
1999
- .fb-table{border-collapse:collapse;width:100%;margin:0 0 12px;font-size:13px}
2000
- .fb-table th,.fb-table td{padding:6px 9px;text-align:left;vertical-align:top;border-bottom:1px solid var(--line)}
2001
- .fb-table th{font-family:'Geist Mono',monospace;font-size:10px;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-faint)}
2002
- .fb-table tr:last-child td{border-bottom:none}
2003
- .fb-queue-row,.fb-flag-row{cursor:pointer}
2004
- .fb-queue-row:nth-child(even),.fb-flag-row:nth-child(even){background:var(--panel)}
2005
- .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}
2006
- .fb-queue-action{font-size:14px;line-height:1.45;color:var(--ink);flex:1 1 auto}
2007
- .fb-queue-touched{font-family:'Geist Mono',monospace;font-size:10.5px;color:var(--ink-faint);flex:0 0 auto}
2008
- .fb-flag-slug{font-family:'Geist Mono',monospace;font-size:12px;color:var(--ink-faint);flex:0 0 130px}
2009
- .fb-flag-text{font-family:'Geist Mono',monospace;font-size:12.5px}
2010
- .dot{display:inline-block;flex:0 0 auto;border-radius:50%;box-sizing:border-box}
2011
- .dot.green{background:var(--green)}
2012
- .dot.amber{background:var(--amber);border-radius:2px}
2013
- .dot.red{background:transparent;border:1.5px solid var(--red)}
2014
- .dot-sm{width:7px;height:7px}
2015
- .dot-md{width:8px;height:8px}
2016
- .dot-lg{width:9px;height:9px}
2017
- .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)}
2018
- .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}
2019
- .fb-hints-spacer{margin-left:auto}
2020
- .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}
2021
- .fb-palette-backdrop.open{display:flex}
2022
- .fb-palette{width:480px;max-width:90vw;background:var(--bg);border:1px solid var(--line);border-radius:10px;overflow:hidden;box-shadow:var(--shadow)}
2023
- .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}
2024
- .fb-palette-list{max-height:300px;overflow-y:auto}
2025
- .fb-palette-item{display:flex;gap:10px;align-items:baseline;padding:9px 14px;cursor:pointer}
2026
- .fb-palette-item.active{background:var(--panel)}
2027
- .fb-palette-item.hide{display:none}
2028
- .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}
2029
- .fb-palette-label{font-family:'Geist Mono',monospace;font-size:13px;color:var(--ink)}
2030
- .fb-palette-hint{margin-left:auto;font-family:'Geist Mono',monospace;font-size:11px;color:var(--ink-faint)}
2031
- @media(max-width:760px){.fb-rail{flex:0 0 220px}.fb-main-inner{padding:20px}}
2032
- @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}}
2033
- `
2034
- }
2035
-
2036
- // Vanilla DOM only - no framework. Read-only: view selection (today vs a
2037
- // client) is a plain show/hide over pre-rendered panels, not a re-render.
2038
- // Search filters the rail (hide + match-snippet, same mechanic the old
2039
- // dashboard used); keyboard nav (j/k/arrows, /, Escape, cmd/ctrl+K) and the
2040
- // command palette are wired the same way the theme toggle already was here -
2041
- // addEventListener, guarded null checks, no inline handlers.
2042
- function dashScript() {
2043
- return [
2044
- "(function(){",
2045
- "'use strict';",
2046
- "var SEL_KEY='fde-fieldbook-sel';",
2047
- "function esc(s){return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');}",
2048
- "function all(sel){return Array.prototype.slice.call(document.querySelectorAll(sel));}",
2049
- "",
2050
- "var views=all('.fb-view');",
2051
- "var navItems=all('.fb-nav');",
2052
- "var searchInput=document.getElementById('fb-search');",
2053
- "",
2054
- "function selectView(id){",
2055
- " if(!document.getElementById('view-'+id))return;",
2056
- " views.forEach(function(v){v.hidden=(v.id!=='view-'+id);});",
2057
- " navItems.forEach(function(n){n.classList.toggle('active',n.getAttribute('data-target')===id);});",
2058
- " try{localStorage.setItem(SEL_KEY,id);}catch(e){}",
2059
- "}",
2060
- "navItems.forEach(function(n){n.addEventListener('click',function(){selectView(n.getAttribute('data-target'));});});",
2061
- "all('[data-nav]').forEach(function(n){n.addEventListener('click',function(){selectView(n.getAttribute('data-nav'));});});",
2062
- "",
2063
- "var startSel='today';",
2064
- "try{var s=localStorage.getItem(SEL_KEY);if(s&&document.getElementById('view-'+s))startSel=s;}catch(e){}",
2065
- "selectView(startSel);",
2066
- "",
2067
- "// search: filters the rail, shows a match snippet in place of the default reason line",
2068
- "// NOTE: snippetFor() below returns a string built ONLY from esc()-escaped",
2069
- "// fragments plus hardcoded '<mark>' literals - never raw untrusted markup -",
2070
- "// so assigning it via innerHTML cannot inject a tag from engagement content.",
2071
- "function snippetFor(raw,term){",
2072
- " var i=raw.indexOf(term);",
2073
- " if(i<0)return '';",
2074
- " var start=Math.max(0,i-24),end=Math.min(raw.length,i+term.length+40);",
2075
- " var pre=esc(raw.slice(start,i)),hit=esc(raw.slice(i,i+term.length)),post=esc(raw.slice(i+term.length,end));",
2076
- " return (start>0?'\\u2026':'')+pre+'<mark>'+hit+'</mark>'+post+(end<raw.length?'\\u2026':'');",
2077
- "}",
2078
- "if(searchInput){searchInput.addEventListener('input',function(){",
2079
- " var term=searchInput.value.trim().toLowerCase();",
2080
- " navItems.forEach(function(n){",
2081
- " if(n.getAttribute('data-target')==='today')return;",
2082
- " var raw=(n.getAttribute('data-search')||'').toLowerCase();",
2083
- " var hit=!term||raw.indexOf(term)>-1;",
2084
- " n.classList.toggle('hide',!hit);",
2085
- " var reason=n.querySelector('.fb-nav-reason');",
2086
- " if(!reason)return;",
2087
- " if(term&&hit){var snip=snippetFor(raw,term);reason.innerHTML=snip;reason.classList.toggle('hide',!snip);}",
2088
- " else{reason.innerHTML=n.getAttribute('data-default-reason')||'';reason.classList.toggle('hide',!reason.innerHTML);}",
2089
- " });",
2090
- "});}",
2091
- "",
2092
- "// keyboard: j/k/arrows move rail selection, / focuses search, Esc blurs/closes",
2093
- "function visibleIds(){return navItems.filter(function(n){return !n.classList.contains('hide');}).map(function(n){return n.getAttribute('data-target');});}",
2094
- "function currentId(){var v=document.querySelector('.fb-view:not([hidden])');return v?v.id.replace('view-',''):'today';}",
2095
- "document.addEventListener('keydown',function(ev){",
2096
- " if((ev.metaKey||ev.ctrlKey)&&(ev.key==='k'||ev.key==='K')){ev.preventDefault();openPalette();return;}",
2097
- " if(paletteIsOpen()){if(ev.key==='Escape'){ev.preventDefault();closePalette();}return;}",
2098
- " var t=ev.target,typing=t&&(t.tagName==='INPUT'||t.tagName==='TEXTAREA'||t.isContentEditable);",
2099
- " if(typing){if(ev.key==='Escape')t.blur();return;}",
2100
- " if(ev.key==='/'){ev.preventDefault();if(searchInput)searchInput.focus();return;}",
2101
- " var down=ev.key==='ArrowDown'||ev.key==='j',up=ev.key==='ArrowUp'||ev.key==='k';",
2102
- " if(down||up){",
2103
- " ev.preventDefault();",
2104
- " var ids=visibleIds();",
2105
- " var idx=ids.indexOf(currentId());",
2106
- " var next=ids[Math.min(ids.length-1,Math.max(0,idx+(down?1:-1)))];",
2107
- " if(next)selectView(next);",
2108
- " }",
2109
- "});",
2110
- "",
2111
- "// command palette: search-filterable nav (today + each client + theme toggle)",
2112
- "var paletteBackdrop=document.getElementById('fb-palette-backdrop');",
2113
- "var paletteInput=document.getElementById('fb-palette-input');",
2114
- "var paletteInner=document.querySelector('.fb-palette');",
2115
- "var paletteItems=all('.fb-palette-item');",
2116
- "var pActive=0;",
2117
- "function paletteIsOpen(){return !!(paletteBackdrop&&paletteBackdrop.classList.contains('open'));}",
2118
- "function visiblePaletteItems(){return paletteItems.filter(function(it){return !it.classList.contains('hide');});}",
2119
- "function highlightPalette(){",
2120
- " var visible=visiblePaletteItems();",
2121
- " paletteItems.forEach(function(it){it.classList.remove('active');});",
2122
- " if(visible[pActive]){visible[pActive].classList.add('active');visible[pActive].scrollIntoView({block:'nearest'});}",
2123
- "}",
2124
- "function filterPalette(q){",
2125
- " q=q.toLowerCase();",
2126
- " paletteItems.forEach(function(it){",
2127
- " var label=(it.getAttribute('data-label')||'').toLowerCase();",
2128
- " var kind=(it.getAttribute('data-kind')||'').toLowerCase();",
2129
- " it.classList.toggle('hide',!(!q||label.indexOf(q)>-1||kind.indexOf(q)>-1));",
2130
- " });",
2131
- " pActive=0;highlightPalette();",
2132
- "}",
2133
- "function openPalette(){",
2134
- " if(!paletteBackdrop)return;",
2135
- " paletteBackdrop.classList.add('open');",
2136
- " if(paletteInput){paletteInput.value='';paletteInput.focus();}",
2137
- " filterPalette('');",
2138
- "}",
2139
- "function closePalette(){if(paletteBackdrop)paletteBackdrop.classList.remove('open');}",
2140
- "function runActive(){",
2141
- " var it=visiblePaletteItems()[pActive];",
2142
- " if(!it)return;",
2143
- " var target=it.getAttribute('data-target');",
2144
- " if(target==='__theme__')toggleTheme();",
2145
- " else if(target)selectView(target);",
2146
- " closePalette();",
2147
- "}",
2148
- "if(paletteBackdrop)paletteBackdrop.addEventListener('click',function(ev){if(ev.target===paletteBackdrop)closePalette();});",
2149
- "if(paletteInner)paletteInner.addEventListener('click',function(ev){ev.stopPropagation();});",
2150
- "var paletteBtn=document.getElementById('fb-palette-btn');",
2151
- "if(paletteBtn)paletteBtn.addEventListener('click',openPalette);",
2152
- "paletteItems.forEach(function(it){",
2153
- " it.addEventListener('click',function(){pActive=visiblePaletteItems().indexOf(it);runActive();});",
2154
- " it.addEventListener('mouseenter',function(){var v=visiblePaletteItems();var i=v.indexOf(it);if(i>-1){pActive=i;highlightPalette();}});",
2155
- "});",
2156
- "if(paletteInput){",
2157
- " paletteInput.addEventListener('input',function(){filterPalette(paletteInput.value);});",
2158
- " paletteInput.addEventListener('keydown',function(ev){",
2159
- " if(ev.key==='Escape'){closePalette();return;}",
2160
- " if(ev.key==='ArrowDown'){ev.preventDefault();pActive=Math.min(visiblePaletteItems().length-1,pActive+1);highlightPalette();return;}",
2161
- " if(ev.key==='ArrowUp'){ev.preventDefault();pActive=Math.max(0,pActive-1);highlightPalette();return;}",
2162
- " if(ev.key==='Enter'){ev.preventDefault();runActive();}",
2163
- " });",
2164
- "}",
2165
- "",
2166
- "// theme toggle - local only, no network; pre-paint script in <head> avoids a flash",
2167
- "var themeBtn=document.getElementById('fde-theme-btn');",
2168
- "function currentTheme(){return document.documentElement.getAttribute('data-fde-theme')==='dark'?'dark':'light';}",
2169
- "function setThemeLabel(){if(themeBtn)themeBtn.textContent=(currentTheme()==='dark'?'light':'dark');}",
2170
- "function toggleTheme(){",
2171
- " var next=currentTheme()==='dark'?'light':'dark';",
2172
- " try{localStorage.setItem('fde-fieldbook-theme',next);}catch(e){}",
2173
- " document.documentElement.setAttribute('data-fde-theme',next);",
2174
- " setThemeLabel();",
2175
- "}",
2176
- "setThemeLabel();",
2177
- "if(themeBtn)themeBtn.addEventListener('click',toggleTheme);",
2178
- "})();",
2179
- ].join('\n')
2180
- }
2181
-
2182
- // ---- HTML builders (one per fieldbook widget) - kept small and named so the
2183
- // structured extractors above and the markup below stay easy to trace. ----
2184
-
2185
- function railItemHtml(e) {
2186
- const dotClass = dotClassFor(e.signals.trust)
2187
- const touchedClass = e.quiet ? 't-amber' : 't-faint'
2188
- const preview = e.next.length > 58 ? e.next.slice(0, 56) + '…' : e.next
2189
- const defaultReason = e.signals.trust !== 'green' && preview ? escapeHtml(preview) : ''
2190
- return `<button class="fb-nav" data-target="eng-${e.slug}" data-search="${e.searchBlob}" data-default-reason="${defaultReason}">
2191
- <div class="fb-nav-row"><span class="dot dot-sm ${dotClass}"></span><span class="fb-nav-name">${inlineMd(e.name)}</span></div>
2192
- <div class="fb-nav-meta">${escapeHtml(e.phaseLabel)} &middot; <span class="${touchedClass}">${escapeHtml(e.signals.updated)}</span></div>
2193
- <div class="fb-nav-reason${defaultReason ? '' : ' hide'}">${defaultReason}</div>
2194
- </button>`
2195
- }
2196
-
2197
- function queueRowHtml(e) {
2198
- const dotClass = dotClassFor(e.signals.trust)
2199
- const noAction = !e.hasNext
2200
- const actionText = noAction ? 'no next action set - open and add one' : e.next
2201
- const touchedClass = e.quiet ? 't-amber' : 't-faint'
2202
- return `<div class="fb-row fb-queue-row" data-nav="eng-${e.slug}">
2203
- <span class="dot dot-md ${dotClass}"></span>
2204
- <span class="fb-queue-slug">${inlineMd(e.name)}</span>
2205
- <span class="fb-queue-action${noAction ? ' t-amber' : ''}">${inlineMd(actionText)}</span>
2206
- <span class="fb-queue-touched ${touchedClass}">${escapeHtml(e.signals.updated)}</span>
2207
- </div>`
2208
- }
2209
-
2210
- function flagRowHtml(e, text, colorClass) {
2211
- return `<div class="fb-row fb-flag-row" data-nav="eng-${e.slug}">
2212
- <span class="fb-flag-slug">${inlineMd(e.name)}</span>
2213
- <span class="fb-flag-text t-${colorClass}">${escapeHtml(text)}</span>
2214
- </div>`
2215
- }
2216
-
2217
- function todayViewHtml({ today, total, attentionCount, highRiskTotal, todayQueue, flagsHtml, hasEngagements }) {
2218
- if (!hasEngagements) {
2219
- return `<div id="view-today" class="fb-view">
2220
- <div class="fb-eyebrow">portfolio</div>
2221
- <h1 class="fb-h1">Today</h1>
2222
- <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>
2223
- </div>`
2224
- }
2225
- return `<div id="view-today" class="fb-view">
2226
- <div class="fb-eyebrow">portfolio</div>
2227
- <h1 class="fb-h1">Today</h1>
2228
- <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>
2229
- <div class="fb-block">
2230
- <div class="fb-sec">Queue — next action per client, worst first</div>
2231
- ${todayQueue}
2232
- </div>
2233
- ${flagsHtml ? `<div class="fb-block">
2234
- <div class="fb-sec">Flags</div>
2235
- ${flagsHtml}
2236
- </div>` : ''}
2237
- </div>`
2238
- }
2239
-
2240
- function clientViewHtml(e) {
2241
- const dotClass = dotClassFor(e.signals.trust)
2242
- const sectorLine = [
2243
- e.overlay ? escapeHtml(e.overlay) : '',
2244
- escapeHtml(e.phaseLabel),
2245
- e.days != null ? `day ${e.days}` : '',
2246
- `touched ${escapeHtml(e.signals.updated)}`,
2247
- ].filter(Boolean).join(' &middot; ')
2248
-
2249
- const nowBlock = `<div class="fb-block">
2250
- <div class="fb-sec">Now</div>
2251
- <div class="fb-now-action${e.hasNext ? '' : ' t-amber'}">${e.hasNext ? inlineMd(e.next) : 'next action not set'}</div>
2252
- ${e.lastSession ? `<div class="fb-now-session">${inlineMd(e.lastSession)}</div>` : ''}
2253
- </div>`
2254
-
2255
- // Brief vs reality is the whole point of "discover" - what they said they
2256
- // needed vs what's actually true. Squeezed onto one truncated line, that
2257
- // contrast disappears. Each gets its own line, its own room to finish a
2258
- // thought, not a race to fit before an ellipsis.
2259
- const whyBlock = (e.brief || e.reality) ? `<div class="fb-block">
2260
- <div class="fb-sec">Why</div>
2261
- ${e.brief ? `<p class="fb-why"><span class="t-faint">What they asked for:</span> ${inlineMd(e.brief)}</p>` : ''}
2262
- ${e.reality ? `<p class="fb-why fb-why-reality"><span class="fb-accent-label">What's actually true:</span> ${inlineMd(e.reality)}</p>` : ''}
2263
- </div>` : ''
2264
-
2265
- // Vitals: a fixed field-facing gut-check panel, not a Movement block that
2266
- // only exists when text mining finds numbers. Every row here is already
2267
- // computed elsewhere in this file for other purposes (status/dashboard
2268
- // triage, receipts, signals) - never a new fabricated field, just the
2269
- // existing facts surfaced where an FDE's eye lands first. Sits beside
2270
- // Now/Why so that column's natural reading width doesn't leave the top of
2271
- // the page empty on a wide screen, and carries enough real rows to earn
2272
- // roughly the same height instead of floating short beside a tall column.
2273
- // Plain English, not fdeops shorthand - a junior FDE reading this for the
2274
- // first time gets the same clear meaning as someone who wrote the CLI.
2275
- // "signal" (the --signal flag's own word) becomes "trust"; a bare day
2276
- // count becomes "started: 3 days ago" in the same relative-time phrasing
2277
- // as everything else here, so there's one pattern to learn, not several.
2278
- const dotGlyph = sig => sig === 'green' ? '&#9679;' : sig === 'red' ? '&#9675;' : '&#9632;' // filled circle / hollow ring / filled square - same shapes as the People list below
2279
- const signalColor = sig => sig === 'green' ? '#12885c' : sig === 'red' ? '#b23e2b' : '#a56a19'
2280
- const teamStatus = e.stakeholders.length
2281
- ? ['green', 'amber', 'red'].map(sig => e.stakeholders.filter(p => p.signal === sig).length)
2282
- .map((n, i) => n ? `<span style="color:${signalColor(['green', 'amber', 'red'][i])}">${dotGlyph(['green', 'amber', 'red'][i])} ${n}</span>` : null)
2283
- .filter(Boolean).join(' &nbsp; ')
2284
- : ''
2285
- const vitalsRows = [
2286
- ['trust', trustWord(e.signals.trust), dotClass],
2287
- 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,
2288
- ['phase', e.phaseLabel, ''],
2289
- e.days != null ? ['started', e.days === 0 ? 'today' : `${e.days} days ago`, ''] : null,
2290
- ['last updated', e.signals.updated, e.quiet ? 'amber' : ''],
2291
- e.log.length ? ['last note', formatLogDate(e.log[0].date), ''] : null,
2292
- e.risks.length ? ['open risks', `${e.risks.length}${e.highRisks ? ` (${e.highRisks} urgent)` : ''}`, e.highRisks ? 'red' : ''] : null,
2293
- e.stakeholders.length ? ['people', `${e.stakeholders.length}`, ''] : null,
2294
- ].filter(Boolean)
2295
- const vitalsBlock = `<div class="fb-vitals">
2296
- ${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')}
2297
- ${teamStatus ? `<div class="fb-vital-row"><span class="fb-vital-label">team status</span><span class="fb-vital-val">${teamStatus}</span></div>` : ''}
2298
- ${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')}` : ''}
2299
- </div>`
2300
-
2301
- const peopleBlock = e.stakeholders.length ? `<div class="fb-block">
2302
- <div class="fb-sec">People</div>
2303
- <div class="fb-list">
2304
- ${e.stakeholders.map(p => `<div class="fb-row fb-person">
2305
- <span class="dot dot-sm ${p.signal}" title="${trustWord(p.signal)}"></span>
2306
- <span class="fb-person-name">${inlineMd(p.name)}</span>
2307
- <span class="fb-person-role">${inlineMd(p.role)}</span>
2308
- <span class="fb-person-note">${inlineMd(p.note)}</span>
2309
- </div>`).join('\n')}
2310
- </div>
2311
- </div>` : ''
2312
-
2313
- const riskBlock = e.risks.length ? `<div class="fb-block">
2314
- <div class="fb-sec-row"><div class="fb-sec">Risk</div><span class="fb-count">${e.risks.length} open</span></div>
2315
- <div class="fb-list">
2316
- ${e.risks.map(r => `<div class="fb-row fb-risk">
2317
- <span class="fb-risk-sev t-${r.severity === 'high' ? 'red' : 'amber'}">${escapeHtml(r.severity)}</span>
2318
- <span class="fb-risk-text">${inlineMd(r.text)}</span>
2319
- </div>`).join('\n')}
2320
- </div>
2321
- </div>` : ''
2322
-
2323
- const logBlock = e.log.length ? `<div class="fb-block">
2324
- <div class="fb-sec">Log</div>
2325
- <div class="fb-list">
2326
- ${e.log.map(g => `<div class="fb-row fb-log">
2327
- <span class="fb-log-date">${escapeHtml(formatLogDate(g.date))}</span>
2328
- <span class="fb-log-kind t-${g.kind === 'receipt' ? 'green' : g.kind === 'decision' ? 'accent' : 'faint'}">${escapeHtml(g.kind)}</span>
2329
- <span class="fb-log-text">${inlineMd(g.text)}</span>
2330
- </div>`).join('\n')}
2331
- </div>
2332
- </div>` : ''
2333
-
2334
- // reference docs (success/terrain/trust-profile) - collapsed by default,
2335
- // never hidden entirely: trust-profile.md carries the data boundary
2336
- const moreBlock = e.moreSections.length ? `<div class="fb-block">
2337
- ${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')}
2338
- </div>` : ''
2339
-
2340
- // People + Risk pair naturally (who's involved / what's at stake) and read
2341
- // well side by side on a wide screen - a single 760px column left half the
2342
- // window empty. Stats stays full width (it's already a wrapping strip of
2343
- // small tiles that benefits from horizontal room); Log stays full width
2344
- // (a chronological list reads better long than squeezed into a column).
2345
- const pairedBlock = (peopleBlock || riskBlock) ? `<div class="fb-grid-wrap">${peopleBlock}${riskBlock}</div>` : ''
2346
-
2347
- return `<div id="view-eng-${e.slug}" class="fb-view" hidden>
2348
- <div class="fb-eyebrow">.fde/${escapeHtml(e.slug)}</div>
2349
- <div class="fb-title-row">
2350
- <h1 class="fb-h1">${inlineMd(e.name)}</h1>
2351
- <span class="fb-trust"><span class="dot dot-lg ${dotClass}"></span><span class="t-${dotClass}">${trustWord(e.signals.trust)}</span></span>
2352
- </div>
2353
- <div class="fb-meta-line">${sectorLine}</div>
2354
- <div class="fb-top-grid">
2355
- <div>${nowBlock}${whyBlock}</div>
2356
- ${vitalsBlock}
2357
- </div>
2358
- ${pairedBlock}${logBlock}${moreBlock}
2359
- </div>`
2360
- }
2361
-
2362
- function paletteItemsHtml(ordered) {
2363
- const items = [
2364
- { kind: 'view', label: 'today', hint: 'portfolio queue', target: 'today' },
2365
- ...ordered.map(e => ({ kind: 'open', label: e.slug, hint: trustWord(e.signals.trust), target: 'eng-' + e.slug })),
2366
- { kind: 'action', label: 'toggle theme', hint: 'light / dark', target: '__theme__' },
2367
- ]
2368
- return items.map(it => `<div class="fb-palette-item" data-target="${escapeHtml(it.target)}" data-label="${escapeHtml(it.label)}" data-kind="${escapeHtml(it.kind)}">
2369
- <span class="fb-palette-kind">${escapeHtml(it.kind)}</span>
2370
- <span class="fb-palette-label">${escapeHtml(it.label)}</span>
2371
- <span class="fb-palette-hint">${escapeHtml(it.hint)}</span>
2372
- </div>`).join('\n')
2373
- }
2374
-
2375
1721
  function cmdDashboard(args) {
2376
1722
  const all = args.includes('--all')
2377
1723
  const outIdx = args.indexOf('--out')
@@ -2391,7 +1737,7 @@ function cmdDashboard(args) {
2391
1737
  }
2392
1738
  const counts = { green: 0, amber: 0, RED: 0 }
2393
1739
  engagements.forEach(e => { counts[e.signals.trust]++ })
2394
- const today = formatToday(new Date())
1740
+ const today = render.formatToday(new Date())
2395
1741
 
2396
1742
  // enrich each engagement with everything the read-only fieldbook renders -
2397
1743
  // next action + last-session excerpt (reused from context.md), brief/reality
@@ -2423,9 +1769,9 @@ function cmdDashboard(args) {
2423
1769
  ['terrain.md', 'Terrain'],
2424
1770
  ['trust-profile.md', 'Trust profile'],
2425
1771
  ].map(([f, title]) => [title, readClean(e.dir, f)])
2426
- .filter(([, md]) => hasRealContent(md))
2427
- .map(([title, md]) => ({ title, html: mdBlockHtml(md) }))
2428
- e.searchBlob = escapeHtml([
1772
+ .filter(([, md]) => render.hasRealContent(md))
1773
+ .map(([title, md]) => ({ title, html: render.mdBlockHtml(md, parseMdTable) }))
1774
+ e.searchBlob = render.escapeHtml([
2429
1775
  e.name, e.next, e.lastSession, e.reality, e.brief,
2430
1776
  ...e.log.map(g => g.text), ...e.risks.map(r => r.text),
2431
1777
  ...e.stakeholders.map(p => `${p.name} ${p.role} ${p.note}`),
@@ -2433,75 +1779,7 @@ function cmdDashboard(args) {
2433
1779
  ].join(' ').toLowerCase())
2434
1780
  })
2435
1781
 
2436
- // rail + Today queue share one order: trust-first (red, amber, green)
2437
- const tierRank = { RED: 0, amber: 1, green: 2 }
2438
- const ordered = engagements.slice().sort((a, b) => tierRank[a.signals.trust] - tierRank[b.signals.trust])
2439
- const attentionCount = engagements.filter(e => e.signals.trust !== 'green').length
2440
- const highRiskTotal = engagements.reduce((n, e) => n + e.highRisks, 0)
2441
-
2442
- const railItems = ordered.map(railItemHtml).join('\n')
2443
- const todayQueue = ordered.map(queueRowHtml).join('\n') || '<p class="empty">No engagements yet.</p>'
2444
- const flagRows = []
2445
- ordered.forEach(e => {
2446
- if (e.quiet) flagRows.push(flagRowHtml(e, `quiet - last touched ${e.signals.updated}`, 'amber'))
2447
- if (e.highRisks) flagRows.push(flagRowHtml(e, `${e.highRisks} high risk${e.highRisks > 1 ? 's' : ''} open`, 'red'))
2448
- })
2449
-
2450
- const todayView = todayViewHtml({
2451
- today, total: engagements.length, attentionCount, highRiskTotal,
2452
- todayQueue, flagsHtml: flagRows.join('\n'), hasEngagements: engagements.length > 0,
2453
- })
2454
- const clientViews = ordered.map(clientViewHtml).join('\n')
2455
- const paletteItems = paletteItemsHtml(ordered)
2456
-
2457
- const html = `<!doctype html><html lang="en"><head><meta charset="utf-8">
2458
- <meta name="viewport" content="width=device-width,initial-scale=1">
2459
- <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>
2460
- <title>FDE Fieldbook</title><style>${dashStyles()}</style></head><body>
2461
- <div class="fb-app">
2462
- <header class="fb-header">
2463
- <div class="fb-brand">
2464
- <span class="fb-wordmark">FDEOPS</span>
2465
- <span class="fb-tagline">fieldbook</span>
2466
- ${engagements.length ? `<span class="fb-need">${attentionCount}/${engagements.length} need you</span>` : ''}
2467
- </div>
2468
- <div class="fb-spacer"></div>
2469
- <span class="fb-today">${escapeHtml(today)}</span>
2470
- <button id="fb-palette-btn" class="fb-btn" type="button" title="Command palette (Ctrl/Cmd+K)">&#8984;K</button>
2471
- <button id="fde-theme-btn" class="fb-btn" type="button">dark</button>
2472
- </header>
2473
- <div class="fb-body">
2474
- <aside class="fb-rail">
2475
- <div class="fb-rail-search"><input id="fb-search" class="fb-search" placeholder="search clients, notes, risks…" spellcheck="false"></div>
2476
- <div class="fb-rail-list fb-scroll">
2477
- <button class="fb-nav" data-target="today">
2478
- <div class="fb-nav-row"><span class="fb-nav-today">today</span>${engagements.length ? `<span class="fb-nav-count">${attentionCount} need you</span>` : ''}</div>
2479
- </button>
2480
- ${railItems}
2481
- </div>
2482
- </aside>
2483
- <main class="fb-main fb-scroll">
2484
- <div class="fb-main-inner">
2485
- ${todayView}
2486
- ${clientViews}
2487
- <div class="fb-hints">
2488
- <span><span class="t-soft">&uarr;&darr; / j k</span> client</span>
2489
- <span><span class="t-soft">/</span> search</span>
2490
- <span><span class="t-soft">&#8984;K</span> palette</span>
2491
- <span class="fb-hints-spacer">deterministic render of .fde/ - edit the markdown, re-run fde dashboard</span>
2492
- </div>
2493
- </div>
2494
- </main>
2495
- </div>
2496
- <div id="fb-palette-backdrop" class="fb-palette-backdrop">
2497
- <div class="fb-palette">
2498
- <input id="fb-palette-input" class="fb-palette-input" placeholder="jump to client or action…" spellcheck="false">
2499
- <div class="fb-palette-list fb-scroll">${paletteItems}</div>
2500
- </div>
2501
- </div>
2502
- </div>
2503
- <script>${dashScript()}</script>
2504
- </body></html>`
1782
+ const html = render.buildFieldbookHtml({ engagements, today })
2505
1783
 
2506
1784
  try {
2507
1785
  fs.mkdirSync(path.dirname(outPath), { recursive: true })
@@ -2538,6 +1816,7 @@ function printUsage() {
2538
1816
  fde debrief --smart propose routing from messy notes → review → fde debrief --apply
2539
1817
  fde prep [label] grounded walk-in brief from existing .fde/ only
2540
1818
  fde doctor lint engagement memory (stale signals, gaps)
1819
+ fde redact <term> preview/remove lines containing a buried term (pass --apply to commit)
2541
1820
  fde garden [--apply] propose safe consolidations (contract: no new facts; git-reversible)
2542
1821
  fde owner [set email] who keeps this engagement record
2543
1822
  fde receipts <term> "what did we agree?" with dates
@@ -2558,6 +1837,7 @@ switch (cmd) {
2558
1837
  case 'debrief': cmdDebrief(args); break
2559
1838
  case 'prep': cmdPrep(args); break
2560
1839
  case 'doctor': cmdDoctor(); break
1840
+ case 'redact': cmdRedact(args); break
2561
1841
  case 'garden': cmdGarden(args); break
2562
1842
  case 'owner': cmdOwner(args); break
2563
1843
  case 'receipts': cmdReceipts(args); break