@jakkrichm/create-nexus-devflow 2.0.24 → 2.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +1 -1
  2. package/dist/bin/create-nexus-devflow.d.ts +18 -1
  3. package/dist/bin/create-nexus-devflow.js +439 -11
  4. package/dist/bin/create-nexus-devflow.js.map +1 -1
  5. package/dist/lib/command-catalog.d.ts +11 -0
  6. package/dist/lib/command-catalog.js +63 -0
  7. package/dist/lib/command-catalog.js.map +1 -0
  8. package/dist/lib/current-work.js +94 -48
  9. package/dist/lib/current-work.js.map +1 -1
  10. package/dist/lib/dashboard-page.d.ts +2 -0
  11. package/dist/lib/dashboard-page.js +201 -0
  12. package/dist/lib/dashboard-page.js.map +1 -0
  13. package/dist/lib/dashboard-snapshot.d.ts +49 -0
  14. package/dist/lib/dashboard-snapshot.js +96 -0
  15. package/dist/lib/dashboard-snapshot.js.map +1 -0
  16. package/dist/lib/dashboard.d.ts +2 -0
  17. package/dist/lib/dashboard.js +360 -8
  18. package/dist/lib/dashboard.js.map +1 -1
  19. package/dist/lib/discoveries.d.ts +19 -0
  20. package/dist/lib/discoveries.js +81 -0
  21. package/dist/lib/discoveries.js.map +1 -0
  22. package/dist/lib/doctor.d.ts +26 -0
  23. package/dist/lib/doctor.js +474 -0
  24. package/dist/lib/doctor.js.map +1 -0
  25. package/dist/lib/findings.d.ts +26 -2
  26. package/dist/lib/findings.js +165 -1
  27. package/dist/lib/findings.js.map +1 -1
  28. package/dist/lib/gatekeeper.d.ts +19 -0
  29. package/dist/lib/gatekeeper.js +77 -0
  30. package/dist/lib/gatekeeper.js.map +1 -0
  31. package/dist/lib/git-hooks.d.ts +16 -0
  32. package/dist/lib/git-hooks.js +78 -0
  33. package/dist/lib/git-hooks.js.map +1 -0
  34. package/dist/lib/history.d.ts +6 -1
  35. package/dist/lib/history.js +98 -11
  36. package/dist/lib/history.js.map +1 -1
  37. package/dist/lib/ideas.d.ts +26 -0
  38. package/dist/lib/ideas.js +179 -0
  39. package/dist/lib/ideas.js.map +1 -0
  40. package/dist/lib/status.d.ts +2 -0
  41. package/dist/lib/status.js +60 -6
  42. package/dist/lib/status.js.map +1 -1
  43. package/dist/lib/update.d.ts +9 -3
  44. package/dist/lib/update.js +129 -22
  45. package/dist/lib/update.js.map +1 -1
  46. package/dist/lib/version-check.d.ts +22 -0
  47. package/dist/lib/version-check.js +59 -0
  48. package/dist/lib/version-check.js.map +1 -0
  49. package/dist/lib/workflow-state.d.ts +23 -0
  50. package/dist/lib/workflow-state.js +112 -0
  51. package/dist/lib/workflow-state.js.map +1 -0
  52. package/dist/scripts/prepare-template.js +3 -3
  53. package/package.json +1 -1
  54. package/template/{.claude/skills/00-discover → .agents/skills/00-explore}/SKILL.md +10 -10
  55. package/template/.agents/skills/10-define/SKILL.md +4 -4
  56. package/template/.agents/skills/20-spec/SKILL.md +2 -3
  57. package/template/.agents/skills/30-plan/SKILL.md +2 -3
  58. package/template/.agents/skills/40-execute/SKILL.md +2 -2
  59. package/template/.agents/skills/50-verify/SKILL.md +2 -2
  60. package/template/.agents/skills/60-report/SKILL.md +3 -3
  61. package/template/{.claude/skills/70-release → .agents/skills/70-deliver}/SKILL.md +7 -13
  62. package/template/.agents/skills/adopt/SKILL.md +136 -73
  63. package/template/.agents/skills/audit/SKILL.md +275 -0
  64. package/template/.agents/skills/autopilot/SKILL.md +228 -147
  65. package/template/.agents/skills/brainstorm/SKILL.md +3 -3
  66. package/template/.agents/skills/brief/SKILL.md +74 -51
  67. package/template/.agents/skills/check/SKILL.md +96 -76
  68. package/template/.agents/skills/ci/SKILL.md +140 -61
  69. package/template/.agents/skills/complete/SKILL.md +156 -101
  70. package/template/.agents/skills/convert-any-to-md/SKILL.md +2 -2
  71. package/template/.agents/skills/debug/SKILL.md +124 -49
  72. package/template/.agents/skills/devflow/SKILL.md +16 -10
  73. package/template/.agents/skills/discovery/SKILL.md +166 -0
  74. package/template/.agents/skills/doctor/SKILL.md +188 -72
  75. package/template/.agents/skills/feature/SKILL.md +195 -102
  76. package/template/.agents/skills/fix/SKILL.md +41 -90
  77. package/template/.agents/skills/idea/SKILL.md +3 -3
  78. package/template/.agents/skills/implement/SKILL.md +189 -46
  79. package/template/.agents/skills/onboard/SKILL.md +215 -85
  80. package/template/.agents/skills/overview/SKILL.md +51 -85
  81. package/template/.agents/skills/prototype/SKILL.md +82 -27
  82. package/template/.agents/skills/release/SKILL.md +160 -0
  83. package/template/.agents/skills/report-html/SKILL.md +2 -2
  84. package/template/.agents/skills/rollback/SKILL.md +123 -77
  85. package/template/.agents/skills/status/SKILL.md +109 -0
  86. package/template/.agents/skills/test/SKILL.md +2 -2
  87. package/template/.agents/skills/tests/SKILL.md +126 -0
  88. package/template/.agents/skills/try/SKILL.md +77 -65
  89. package/template/{.agents/skills/00-discover → .claude/skills/00-explore}/SKILL.md +9 -9
  90. package/template/.claude/skills/10-define/SKILL.md +2 -2
  91. package/template/.claude/skills/20-spec/SKILL.md +1 -1
  92. package/template/.claude/skills/30-plan/SKILL.md +1 -1
  93. package/template/.claude/skills/60-report/SKILL.md +1 -1
  94. package/template/{.agents/skills/70-release → .claude/skills/70-deliver}/SKILL.md +6 -12
  95. package/template/.claude/skills/adopt/SKILL.md +2 -2
  96. package/template/.claude/skills/audit/SKILL.md +141 -0
  97. package/template/.claude/skills/autopilot/SKILL.md +74 -52
  98. package/template/.claude/skills/brief/SKILL.md +67 -45
  99. package/template/.claude/skills/ci/SKILL.md +1 -1
  100. package/template/.claude/skills/complete/SKILL.md +1 -1
  101. package/template/.claude/skills/debug/SKILL.md +1 -1
  102. package/template/.claude/skills/devflow/SKILL.md +7 -7
  103. package/template/.claude/skills/discovery/SKILL.md +145 -0
  104. package/template/.claude/skills/doctor/SKILL.md +1 -1
  105. package/template/.claude/skills/feature/SKILL.md +67 -18
  106. package/template/.claude/skills/fix/SKILL.md +1 -1
  107. package/template/.claude/skills/idea/SKILL.md +2 -2
  108. package/template/.claude/skills/onboard/SKILL.md +3 -3
  109. package/template/.claude/skills/overview/SKILL.md +39 -88
  110. package/template/.claude/skills/prototype/SKILL.md +1 -1
  111. package/template/.claude/skills/release/SKILL.md +171 -0
  112. package/template/.claude/skills/rollback/SKILL.md +2 -2
  113. package/template/AGENTS.md +5 -5
  114. package/template/devflow/build-plan.md +40 -0
  115. package/template/devflow/context/ai-interaction.md +4 -4
  116. package/template/devflow/context/coding-standards.md +3 -3
  117. package/template/devflow/context/current-stage.md +1 -1
  118. package/template/devflow/context/findings.md +1 -1
  119. package/template/devflow/history/HISTORY.md +2 -2
  120. package/template/devflow/project-plan.md +27 -0
  121. package/template/devflow/reference/mockup.html +476 -0
  122. package/template/devflow/reference/project-overview-template.md +39 -0
  123. package/template/devflow/reference/running-id-contract.md +24 -2
@@ -1,5 +1,7 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import http from "node:http";
3
+ import { DASHBOARD_PAGE_HTML } from "./dashboard-page.js";
4
+ import { readDashboardSnapshot } from "./dashboard-snapshot.js";
3
5
  import { readHistory } from "./history.js";
4
6
  import { readProjectStatus } from "./status.js";
5
7
  const DASHBOARD_HOST = "127.0.0.1";
@@ -7,7 +9,7 @@ async function startDashboardServer(startPath = process.cwd(), options = {}) {
7
9
  const initialStatus = await readProjectStatus(startPath);
8
10
  const projectRoot = initialStatus.project.root;
9
11
  const server = http.createServer((request, response) => {
10
- void handleRequest(projectRoot, request, response);
12
+ void handleRequest(projectRoot, request, response, options.snapshotOptions);
11
13
  });
12
14
  await new Promise((resolve, reject) => {
13
15
  const onError = (error) => {
@@ -32,7 +34,7 @@ async function startDashboardServer(startPath = process.cwd(), options = {}) {
32
34
  close: () => closeServer(server)
33
35
  };
34
36
  }
35
- async function handleRequest(projectRoot, request, response) {
37
+ async function handleRequest(projectRoot, request, response, snapshotOptions) {
36
38
  const method = request.method || "GET";
37
39
  if (method !== "GET" && method !== "HEAD") {
38
40
  response.setHeader("Allow", "GET, HEAD");
@@ -41,8 +43,8 @@ async function handleRequest(projectRoot, request, response) {
41
43
  }
42
44
  const pathname = new URL(request.url || "/", `http://${DASHBOARD_HOST}`).pathname;
43
45
  if (pathname === "/") {
44
- response.setHeader("Content-Security-Policy", "default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; connect-src * 'self'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'");
45
- sendResponse(response, method, 200, "text/html; charset=utf-8", DASHBOARD_HTML);
46
+ response.setHeader("Content-Security-Policy", "default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; connect-src 'self'; img-src 'self' data:; base-uri 'none'; form-action 'none'; frame-ancestors 'none'");
47
+ sendResponse(response, method, 200, "text/html; charset=utf-8", DASHBOARD_PAGE_HTML);
46
48
  return;
47
49
  }
48
50
  if (pathname === "/api/status") {
@@ -57,6 +59,18 @@ async function handleRequest(projectRoot, request, response) {
57
59
  }
58
60
  return;
59
61
  }
62
+ if (pathname === "/api/dashboard") {
63
+ try {
64
+ const snapshot = await readDashboardSnapshot(projectRoot, snapshotOptions);
65
+ sendResponse(response, method, 200, "application/json; charset=utf-8", `${JSON.stringify(snapshot)}\n`);
66
+ }
67
+ catch (error) {
68
+ sendResponse(response, method, 500, "application/json; charset=utf-8", `${JSON.stringify({
69
+ error: error instanceof Error ? error.message : "Unable to read dashboard snapshot."
70
+ })}\n`);
71
+ }
72
+ return;
73
+ }
60
74
  if (pathname === "/api/history") {
61
75
  try {
62
76
  const history = await readHistory(projectRoot);
@@ -432,11 +446,55 @@ const DASHBOARD_HTML = `<!doctype html>
432
446
 
433
447
  .next-action { padding: 24px; }
434
448
 
449
+ .next-action-header {
450
+ display: flex;
451
+ align-items: center;
452
+ justify-content: space-between;
453
+ gap: 12px;
454
+ }
455
+
456
+ .next-copy-btn {
457
+ display: inline-flex;
458
+ align-items: center;
459
+ gap: 6px;
460
+ padding: 5px 12px;
461
+ border-radius: 6px;
462
+ background: rgba(118, 168, 255, 0.12);
463
+ color: var(--code-blue);
464
+ border: 1px solid rgba(118, 168, 255, 0.3);
465
+ font: 600 11px/1.3 var(--font-mono);
466
+ cursor: pointer;
467
+ transition: background-color 0.2s ease, border-color 0.2s ease, transform 0.15s ease, color 0.2s ease;
468
+ user-select: none;
469
+ }
470
+ .next-copy-btn:hover {
471
+ background: var(--blue);
472
+ color: #ffffff;
473
+ border-color: var(--blue);
474
+ transform: translateY(-1px);
475
+ }
476
+ .next-copy-btn:active {
477
+ transform: translateY(0);
478
+ }
479
+ .next-copy-btn.copied {
480
+ background: var(--green);
481
+ color: #ffffff;
482
+ border-color: var(--green);
483
+ }
484
+
435
485
  .command {
436
486
  margin: 13px 0 8px;
437
487
  color: var(--code-blue);
438
488
  font: 600 clamp(20px, 3vw, 29px)/1.3 var(--font-mono);
439
489
  overflow-wrap: anywhere;
490
+ cursor: pointer;
491
+ border-radius: 6px;
492
+ padding: 4px 6px;
493
+ margin-left: -6px;
494
+ transition: background-color 0.2s ease;
495
+ }
496
+ .command:hover {
497
+ background: rgba(118, 168, 255, 0.08);
440
498
  }
441
499
 
442
500
  .command-flip { animation: commandFlip 300ms ease-out; }
@@ -465,7 +523,135 @@ const DASHBOARD_HTML = `<!doctype html>
465
523
  li:last-child { border-bottom: 0; }
466
524
  li.empty { color: var(--ink-muted); }
467
525
  li.empty:hover { background-color: transparent; transform: none; }
468
- li.fade-slide-in { animation: fadeSlideIn 250ms ease-out both; }
526
+ /* Markdown Inline Formatting */
527
+ .inline-code, code.inline-code {
528
+ display: inline-block;
529
+ padding: 1.5px 6px;
530
+ margin: 0 2px;
531
+ border-radius: 5px;
532
+ background: var(--surface-muted);
533
+ color: var(--blue-dark);
534
+ font-family: var(--font-mono);
535
+ font-size: 0.88em;
536
+ font-weight: 600;
537
+ border: 1px solid var(--line);
538
+ line-height: 1.35;
539
+ vertical-align: baseline;
540
+ word-break: break-word;
541
+ }
542
+ strong {
543
+ color: var(--ink);
544
+ font-weight: 700;
545
+ }
546
+ em {
547
+ font-style: italic;
548
+ color: var(--ink-soft);
549
+ }
550
+ del {
551
+ text-decoration: line-through;
552
+ color: var(--ink-muted);
553
+ }
554
+ .inline-link {
555
+ color: var(--blue);
556
+ text-decoration: none;
557
+ font-weight: 600;
558
+ }
559
+ .inline-link:hover {
560
+ text-decoration: underline;
561
+ }
562
+
563
+ /* Idea Inbox Item Styling */
564
+ .idea-item {
565
+ display: flex;
566
+ flex-direction: column;
567
+ gap: 8px;
568
+ padding: 14px 16px;
569
+ border: 1px solid var(--line);
570
+ border-radius: 10px;
571
+ background: var(--surface-solid);
572
+ margin-bottom: 12px;
573
+ transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease;
574
+ }
575
+ .idea-item:hover {
576
+ border-color: var(--blue);
577
+ box-shadow: 0 4px 16px rgba(21, 94, 239, 0.09);
578
+ transform: translateY(-1px);
579
+ }
580
+ .idea-header {
581
+ display: flex;
582
+ align-items: center;
583
+ justify-content: space-between;
584
+ gap: 12px;
585
+ }
586
+ .idea-id-badge {
587
+ display: inline-flex;
588
+ align-items: center;
589
+ padding: 4px 9px;
590
+ border-radius: 6px;
591
+ background: rgba(21, 94, 239, 0.08);
592
+ color: var(--blue-dark);
593
+ font: 700 11px/1 var(--font-mono);
594
+ letter-spacing: .04em;
595
+ }
596
+ .idea-title-text {
597
+ color: var(--ink);
598
+ font-size: 14px;
599
+ font-weight: 700;
600
+ letter-spacing: -.01em;
601
+ line-height: 1.45;
602
+ }
603
+ .idea-title-text .inline-code {
604
+ font-size: 0.85em;
605
+ background: rgba(21, 94, 239, 0.06);
606
+ border-color: rgba(21, 94, 239, 0.2);
607
+ }
608
+ .idea-desc-text {
609
+ color: var(--ink-soft);
610
+ font-size: 13px;
611
+ line-height: 1.55;
612
+ }
613
+ .idea-meta-row {
614
+ display: flex;
615
+ align-items: center;
616
+ justify-content: space-between;
617
+ flex-wrap: wrap;
618
+ gap: 10px;
619
+ margin-top: 2px;
620
+ padding-top: 8px;
621
+ border-top: 1px dashed var(--line);
622
+ }
623
+ .idea-feasibility-tag {
624
+ color: var(--ink-soft);
625
+ font-size: 12px;
626
+ background: var(--surface-muted);
627
+ padding: 4px 9px;
628
+ border-radius: 6px;
629
+ line-height: 1.4;
630
+ }
631
+ .idea-feasibility-tag strong {
632
+ color: var(--ink);
633
+ }
634
+ .idea-feasibility-tag .inline-code {
635
+ font-size: 0.85em;
636
+ background: rgba(0, 0, 0, 0.04);
637
+ }
638
+ .idea-cmd-code {
639
+ display: inline-block;
640
+ padding: 4px 10px;
641
+ border-radius: 6px;
642
+ background: var(--surface-muted);
643
+ color: var(--blue-dark);
644
+ font: 600 11px/1.3 var(--font-mono);
645
+ cursor: pointer;
646
+ border: 1px solid var(--line);
647
+ transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
648
+ user-select: none;
649
+ }
650
+ .idea-cmd-code:hover {
651
+ background: var(--blue);
652
+ color: #ffffff;
653
+ border-color: var(--blue);
654
+ }
469
655
 
470
656
  footer { margin-top: 24px; color: var(--ink-muted); font: 11px/1.6 var(--font-mono); }
471
657
 
@@ -551,6 +737,12 @@ const DASHBOARD_HTML = `<!doctype html>
551
737
  <ul id="warnings-list" aria-live="polite"><li class="empty">Loading warnings...</li></ul>
552
738
  </article>
553
739
 
740
+ <article class="card full card-enter" style="animation-delay: 0.26s;">
741
+ <div class="card-head"><span class="label">Idea Inbox & Backlog</span><span class="value" id="ideas-count">-</span></div>
742
+ <div class="muted">Pending ideas from devflow/ideas.md. Start any idea with /feature IDEA-xxx or /00-explore IDEA-xxx.</div>
743
+ <ul id="ideas-list" tabindex="0" aria-label="Idea Inbox"><li class="empty">Loading ideas...</li></ul>
744
+ </article>
745
+
554
746
  <article class="card full card-enter" style="animation-delay: 0.28s;">
555
747
  <div class="card-head"><span class="label">Completed Work Archive</span><span class="value" id="history-count">-</span></div>
556
748
  <div class="muted">Categorized history of features, fixes, and rollbacks.</div>
@@ -558,8 +750,17 @@ const DASHBOARD_HTML = `<!doctype html>
558
750
  </article>
559
751
 
560
752
  <article class="card full code-panel next-action card-enter" style="animation-delay: 0.32s;" id="next-panel">
561
- <span class="label">Next Action</span>
562
- <div class="command" id="next-command" aria-live="polite">Loading...</div>
753
+ <div class="next-action-header">
754
+ <span class="label">Next Action</span>
755
+ <button class="next-copy-btn" id="next-copy-btn" type="button" aria-label="Copy next command" title="Click to copy next action command">
756
+ <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
757
+ <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
758
+ <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
759
+ </svg>
760
+ <span id="next-copy-text">Copy Command</span>
761
+ </button>
762
+ </div>
763
+ <div class="command" id="next-command" aria-live="polite" title="Click to copy command">Loading...</div>
563
764
  <div class="muted" id="next-reason"></div>
564
765
  </article>
565
766
  </section>
@@ -619,6 +820,40 @@ const DASHBOARD_HTML = `<!doctype html>
619
820
  setTimeout(() => node.classList.remove(className), 600);
620
821
  }
621
822
 
823
+ function escapeHtml(str) {
824
+ if (typeof str !== 'string') return '';
825
+ return str
826
+ .replace(/&/g, '&amp;')
827
+ .replace(/</g, '&lt;')
828
+ .replace(/>/g, '&gt;')
829
+ .replace(/"/g, '&quot;')
830
+ .replace(/'/g, '&#039;');
831
+ }
832
+
833
+ function renderMarkdownInline(text) {
834
+ if (!text) return '';
835
+ var str = escapeHtml(text);
836
+
837
+ // Inline code
838
+ str = str.replace(new RegExp('\\x60([^\\x60]+)\\x60', 'g'), '<code class="inline-code">$1</code>');
839
+
840
+ // Bold
841
+ str = str.replace(new RegExp('\\\\*\\\\*(.+?)\\\\*\\\\*', 'g'), '<strong>$1</strong>');
842
+ str = str.replace(new RegExp('__(.+?)__', 'g'), '<strong>$1</strong>');
843
+
844
+ // Strikethrough
845
+ str = str.replace(new RegExp('~~(.+?)~~', 'g'), '<del>$1</del>');
846
+
847
+ // Italic
848
+ str = str.replace(new RegExp('(^|[^*])\\\\*([^*\\\\r\\\\n]+)\\\\*([^*]|$)', 'g'), '$1<em>$2</em>$3');
849
+ str = str.replace(new RegExp('(^|[^_])_([^_\\\\r\\\\n]+)_([^_]|$)', 'g'), '$1<em>$2</em>$3');
850
+
851
+ // Links
852
+ str = str.replace(new RegExp('\\\\[([^\\\\]]+)\\\\]\\\\((https?:\\\\/\\\\/[^\\\\s\\\\)]+|#[^\\\\s\\\\)]+)\\\\)', 'g'), '<a href="$2" target="_blank" rel="noopener noreferrer" class="inline-link">$1</a>');
853
+
854
+ return str;
855
+ }
856
+
622
857
  function setList(id, values, emptyMessage) {
623
858
  const list = byId(id);
624
859
  if (!list) return;
@@ -628,7 +863,7 @@ const DASHBOARD_HTML = `<!doctype html>
628
863
 
629
864
  items.forEach((value, idx) => {
630
865
  const item = document.createElement("li");
631
- item.textContent = value;
866
+ item.innerHTML = renderMarkdownInline(value);
632
867
  if (values.length === 0) {
633
868
  item.className = "empty";
634
869
  } else if (!isFirstLoad && !prevItemsText.includes(value)) {
@@ -639,6 +874,86 @@ const DASHBOARD_HTML = `<!doctype html>
639
874
  });
640
875
  }
641
876
 
877
+ function setIdeas(ideas) {
878
+ const list = byId('ideas-list');
879
+ if (!list) return;
880
+ list.replaceChildren();
881
+
882
+ const items = ideas && ideas.pending && ideas.pending.length > 0 ? ideas.pending : [];
883
+ if (items.length === 0) {
884
+ const emptyItem = document.createElement('li');
885
+ emptyItem.className = 'empty';
886
+ emptyItem.textContent = 'No pending ideas in devflow/ideas.md';
887
+ list.append(emptyItem);
888
+ return;
889
+ }
890
+
891
+ items.forEach((idea, idx) => {
892
+ const li = document.createElement('li');
893
+ li.className = 'idea-item';
894
+ if (!isFirstLoad) {
895
+ li.classList.add('fade-slide-in');
896
+ li.style.animationDelay = (idx * 40) + 'ms';
897
+ }
898
+
899
+ const headerDiv = document.createElement('div');
900
+ headerDiv.className = 'idea-header';
901
+
902
+ const badgeSpan = document.createElement('span');
903
+ badgeSpan.className = 'idea-id-badge';
904
+ badgeSpan.textContent = idea.id;
905
+
906
+ const cmdCode = document.createElement('code');
907
+ cmdCode.className = 'idea-cmd-code';
908
+ cmdCode.textContent = '/feature ' + idea.id;
909
+ cmdCode.title = 'Click to copy command';
910
+ cmdCode.onclick = () => {
911
+ if (navigator.clipboard) {
912
+ navigator.clipboard.writeText('/feature ' + idea.id);
913
+ const orig = cmdCode.textContent;
914
+ cmdCode.textContent = 'Copied!';
915
+ setTimeout(() => { cmdCode.textContent = orig; }, 1200);
916
+ }
917
+ };
918
+
919
+ headerDiv.append(badgeSpan, cmdCode);
920
+
921
+ const titleDiv = document.createElement('div');
922
+ titleDiv.className = 'idea-title-text';
923
+ titleDiv.innerHTML = renderMarkdownInline(idea.title);
924
+
925
+ li.append(headerDiv, titleDiv);
926
+
927
+ if (idea.rawInput) {
928
+ const descDiv = document.createElement('div');
929
+ descDiv.className = 'idea-desc-text';
930
+ descDiv.innerHTML = renderMarkdownInline(idea.rawInput);
931
+ li.append(descDiv);
932
+ }
933
+
934
+ if (idea.feasibility || idea.value || idea.date) {
935
+ const metaDiv = document.createElement('div');
936
+ metaDiv.className = 'idea-meta-row';
937
+ if (idea.feasibility) {
938
+ const feasSpan = document.createElement('span');
939
+ feasSpan.className = 'idea-feasibility-tag';
940
+ feasSpan.innerHTML = '⚡ ' + renderMarkdownInline(idea.feasibility);
941
+ metaDiv.append(feasSpan);
942
+ }
943
+ if (idea.date) {
944
+ const dateSpan = document.createElement('span');
945
+ dateSpan.className = 'muted';
946
+ dateSpan.style.fontSize = '11px';
947
+ dateSpan.textContent = idea.date;
948
+ metaDiv.append(dateSpan);
949
+ }
950
+ li.append(metaDiv);
951
+ }
952
+
953
+ list.append(li);
954
+ });
955
+ }
956
+
642
957
  async function refreshStatus() {
643
958
  if (refreshing) return;
644
959
  refreshing = true;
@@ -732,6 +1047,17 @@ const DASHBOARD_HTML = `<!doctype html>
732
1047
  }
733
1048
  setList('warnings-list', warnings.map(w => w.message), 'No active warnings or drift');
734
1049
 
1050
+ const ideas = data.ideas || { totalPending: 0, pending: [] };
1051
+ const prevIdeasCount = prevData?.ideas?.totalPending ?? 0;
1052
+ const ideasNode = byId('ideas-count');
1053
+ if (!isFirstLoad && ideas.totalPending !== prevIdeasCount) {
1054
+ animateCount(ideasNode, prevIdeasCount, ideas.totalPending);
1055
+ triggerFlash(ideasNode, 'green');
1056
+ } else {
1057
+ ideasNode.textContent = ideas.totalPending + ' pending';
1058
+ }
1059
+ setIdeas(ideas);
1060
+
735
1061
  const historyItems = historyData.items || [];
736
1062
  const prevHistoryCount = prevData?.historyCount ?? 0;
737
1063
  const historyNode = byId('history-count');
@@ -778,6 +1104,32 @@ const DASHBOARD_HTML = `<!doctype html>
778
1104
  }
779
1105
  }
780
1106
 
1107
+ function setupNextActionCopy() {
1108
+ const copyBtn = byId('next-copy-btn');
1109
+ const cmdNode = byId('next-command');
1110
+ const copyText = byId('next-copy-text');
1111
+
1112
+ const performCopy = () => {
1113
+ const textToCopy = cmdNode ? cmdNode.textContent.trim() : '';
1114
+ if (!textToCopy || textToCopy === 'Loading...') return;
1115
+ if (navigator.clipboard) {
1116
+ navigator.clipboard.writeText(textToCopy);
1117
+ if (copyBtn && copyText) {
1118
+ copyBtn.classList.add('copied');
1119
+ copyText.textContent = '✓ Copied!';
1120
+ setTimeout(() => {
1121
+ copyBtn.classList.remove('copied');
1122
+ copyText.textContent = 'Copy Command';
1123
+ }, 1400);
1124
+ }
1125
+ }
1126
+ };
1127
+
1128
+ if (copyBtn) copyBtn.onclick = performCopy;
1129
+ if (cmdNode) cmdNode.onclick = performCopy;
1130
+ }
1131
+
1132
+ setupNextActionCopy();
781
1133
  refreshStatus();
782
1134
  setInterval(refreshStatus, 2000);
783
1135
  </script>
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../lib/dashboard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../lib/dashboard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ interface DiscoveryItem {
2
+ id: string;
3
+ title: string;
4
+ date: string | null;
5
+ decision: "Proceed" | "Defer" | "Reject" | "Unknown";
6
+ approvalStatus: string | null;
7
+ status: string | null;
8
+ file: string;
9
+ }
10
+ interface DiscoverySummary {
11
+ total: number;
12
+ activeId: string | null;
13
+ active: DiscoveryItem | null;
14
+ recent: DiscoveryItem[];
15
+ }
16
+ declare function readDiscoveries(projectRoot: string, activeId?: string | null): Promise<DiscoverySummary>;
17
+ declare function parseDiscovery(markdown: string, file: string, fallbackId: string): DiscoveryItem;
18
+ export { parseDiscovery, readDiscoveries };
19
+ export type { DiscoveryItem, DiscoverySummary };
@@ -0,0 +1,81 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ async function readDiscoveries(projectRoot, activeId = null) {
4
+ const root = path.join(projectRoot, "devflow", "discoveries");
5
+ let entries;
6
+ try {
7
+ entries = await fs.readdir(root, { withFileTypes: true });
8
+ }
9
+ catch (error) {
10
+ if (getErrorCode(error) === "ENOENT")
11
+ return emptySummary(activeId);
12
+ throw error;
13
+ }
14
+ const items = await Promise.all(entries
15
+ .filter((entry) => entry.isDirectory() && !entry.isSymbolicLink())
16
+ .map(async (entry) => {
17
+ const file = path.join(entry.name, "00-explore.md");
18
+ try {
19
+ const markdown = await fs.readFile(path.join(root, file), "utf8");
20
+ return parseDiscovery(markdown, file, entry.name);
21
+ }
22
+ catch (error) {
23
+ if (getErrorCode(error) === "ENOENT")
24
+ return null;
25
+ throw error;
26
+ }
27
+ }));
28
+ const valid = items.filter((item) => item !== null)
29
+ .sort((left, right) => right.id.localeCompare(left.id));
30
+ return {
31
+ total: valid.length,
32
+ activeId,
33
+ active: valid.find((item) => item.id === activeId) || null,
34
+ recent: valid.slice(0, 6)
35
+ };
36
+ }
37
+ function parseDiscovery(markdown, file, fallbackId) {
38
+ const id = field(markdown, "Discovery ID") || fallbackId.match(/DISC-\d{8}-\d{3}/)?.[0] || fallbackId;
39
+ const heading = markdown.match(/^#\s+(.+)$/m)?.[1]?.trim() || fallbackId;
40
+ const title = heading
41
+ .replace(/^.*?\]\s*/, "")
42
+ .replace(/^Discovery Document:\s*/i, "")
43
+ .trim();
44
+ const finalDecision = markdown.match(/Final Decision:\s*`?(Proceed|Defer|Reject)`?/i)?.[1];
45
+ const status = field(markdown, "Status");
46
+ const statusDecision = status?.match(/\b(Proceed|Defer|Reject)\b/i)?.[1];
47
+ const normalizedDecision = finalDecision || statusDecision;
48
+ return {
49
+ id,
50
+ title,
51
+ date: field(markdown, "Date"),
52
+ decision: normalizeDecision(normalizedDecision),
53
+ approvalStatus: field(markdown, "Approval Status"),
54
+ status,
55
+ file: file.replaceAll("\\", "/")
56
+ };
57
+ }
58
+ function field(markdown, label) {
59
+ const escaped = label.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
60
+ return markdown.match(new RegExp(`\\*\\*${escaped}\\*\\*:\\s*\\x60?([^\\r\\n\\x60]+)`, "i"))?.[1]?.trim() || null;
61
+ }
62
+ function normalizeDecision(value) {
63
+ const normalized = value?.toLowerCase();
64
+ if (normalized === "proceed")
65
+ return "Proceed";
66
+ if (normalized === "defer")
67
+ return "Defer";
68
+ if (normalized === "reject")
69
+ return "Reject";
70
+ return "Unknown";
71
+ }
72
+ function emptySummary(activeId) {
73
+ return { total: 0, activeId, active: null, recent: [] };
74
+ }
75
+ function getErrorCode(error) {
76
+ return typeof error === "object" && error !== null && "code" in error && typeof error.code === "string"
77
+ ? error.code
78
+ : undefined;
79
+ }
80
+ export { parseDiscovery, readDiscoveries };
81
+ //# sourceMappingURL=discoveries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discoveries.js","sourceRoot":"","sources":["../../lib/discoveries.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export interface DoctorCheck {
2
+ id: string;
3
+ name: string;
4
+ status: "pass" | "warn" | "fail";
5
+ message: string;
6
+ fixable: boolean;
7
+ fixed?: boolean;
8
+ }
9
+ export interface DoctorReport {
10
+ projectRoot: string;
11
+ isDevFlowProject: boolean;
12
+ checks: DoctorCheck[];
13
+ totalChecks: number;
14
+ passCount: number;
15
+ warnCount: number;
16
+ failCount: number;
17
+ fixedCount: number;
18
+ }
19
+ export interface DoctorOptions {
20
+ fix?: boolean;
21
+ color?: boolean;
22
+ }
23
+ export declare function runDoctor(projectRoot: string, options?: DoctorOptions): Promise<DoctorReport>;
24
+ export declare function formatDoctorHuman(report: DoctorReport, options?: {
25
+ color?: boolean;
26
+ }): string;