@unson/brainbase-mcp 0.41.3 → 0.41.6

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.
@@ -14,7 +14,7 @@ import {
14
14
  workspaceNotice,
15
15
  workspacePageHeader,
16
16
  workspaceSectionTitle,
17
- workspaceHelp, workspaceDialog, workspaceDisclosure, workspaceErrorCard,
17
+ workspaceHelp, workspaceDialog, workspaceDisclosure, workspaceErrorCard, workspaceLoadingCard, workspaceDismissNotification,
18
18
  } from './workspace-kit.js';
19
19
 
20
20
  export const FOUNDATION_OVERVIEW_CONTRACT_VERSION = 'foundation-overview.v1';
@@ -660,10 +660,25 @@ function renderModels(doc, catalog, viewState, callbacks, recordContexts) {
660
660
  return section;
661
661
  }
662
662
 
663
- function renderLoading(doc, state, callbacks) {
664
- const notice = workspaceNotice(doc, { label: '読み込み', text: '目的・哲学・世界モデルを読み込んでいます。' });
665
- notice.append(workspaceButton(doc, { text: '再試行', variant: 'quiet', onClick: callbacks.load }));
666
- return notice;
663
+ /** Keep one loading card across redraws so completion can leave visibly. */
664
+ function renderLoadingState(doc, root, viewState, loading, onLoading) {
665
+ if (onLoading) { onLoading(loading); return; }
666
+ if (loading) {
667
+ viewState.cancelLoadingDismiss?.();
668
+ viewState.cancelLoadingDismiss = null;
669
+ viewState.loadingCard ??= workspaceLoadingCard(doc);
670
+ }
671
+ const card = viewState.loadingCard;
672
+ if (!card) return;
673
+ const stack = viewState.loadingStack ??= makeElement(doc, 'aside', { className: 'bb-ws-error-stack', attrs: { 'aria-label': '読み込み状況' } });
674
+ stack.append(card); root.append(stack);
675
+ if (!loading && !viewState.cancelLoadingDismiss) {
676
+ const cancel = workspaceDismissNotification(card, () => {
677
+ if (viewState.loadingCard !== card) return;
678
+ viewState.loadingCard = null; viewState.cancelLoadingDismiss = null; viewState.loadingStack = null; stack.remove();
679
+ });
680
+ if (viewState.loadingCard === card) viewState.cancelLoadingDismiss = cancel;
681
+ }
667
682
  }
668
683
 
669
684
  function renderFailure(doc, state, callbacks) {
@@ -684,6 +699,7 @@ export function renderFoundationOverview(root, state, {
684
699
  recordContexts,
685
700
  partial = false,
686
701
  onNotice,
702
+ onLoading,
687
703
  } = {}) {
688
704
  if (!root) throw new TypeError('root is required');
689
705
  const doc = getDocument(explicitDocument);
@@ -705,14 +721,13 @@ export function renderFoundationOverview(root, state, {
705
721
  else surface.append(workspaceErrorCard(doc, notice));
706
722
  };
707
723
  if (state.status === 'loading') {
708
- surface.append(renderLoading(doc, state, callbacks)); root.append(surface); return surface;
724
+ root.append(surface); renderLoadingState(doc, root, viewState, true, onLoading); return surface;
709
725
  }
710
726
  if (state.status !== 'ready') {
711
727
  notify({ title: '取得失敗', message: `${state.error?.message ?? '目的・哲学・世界モデルを確認できません。'} 登録なし・0件として表示していません。`, onRetry: callbacks.load });
712
- root.append(surface); return surface;
728
+ root.append(surface); renderLoadingState(doc, root, viewState, false, onLoading); return surface;
713
729
  }
714
730
  const catalog = state.catalog;
715
- if (partial) notify({ title: '取得済みの範囲', tone: 'warning', message: '以下の登録なし・検索結果は取得できた記録だけが対象です。全体は未確認です。' });
716
731
  surface.append(renderObjectives(doc, catalog, viewState, callbacks, recordContexts));
717
732
  const fold = (title, help, content, initialOpen) => {
718
733
  const key = title === '哲学' ? 'philosophyOpen' : 'modelsOpen';
@@ -721,6 +736,7 @@ export function renderFoundationOverview(root, state, {
721
736
  surface.append(fold('哲学', '判断の前提となる考え方です。登録された本文と、判断への適用範囲を分けて表示します。', renderPhilosophies(doc, catalog, recordContexts), true));
722
737
  surface.append(fold('世界モデル', '何をすると結果が変わるか、という仮説。未検証・許可用途を分けて確認します。', renderModels(doc, catalog, viewState, callbacks, recordContexts), false));
723
738
  root.append(surface);
739
+ renderLoadingState(doc, root, viewState, false, onLoading);
724
740
  return surface;
725
741
  }
726
742
 
@@ -731,7 +747,7 @@ function appendRecordSource(doc, card, record, contexts) {
731
747
 
732
748
  /** Compose independently validated catalogs by topic, preserving each reference's source context. */
733
749
  export function renderFoundationCollectionOverview(root, sources, {
734
- document: explicitDocument, viewState = { query: '', page: 0 }, callbacks = {}, scopeLabel = '全体', onNotice,
750
+ document: explicitDocument, viewState = { query: '', page: 0 }, callbacks = {}, scopeLabel = '全体', onNotice, onLoading,
735
751
  } = {}) {
736
752
  const doc = getDocument(explicitDocument);
737
753
  root.replaceChildren();
@@ -742,7 +758,7 @@ export function renderFoundationCollectionOverview(root, sources, {
742
758
  for (const source of sources) {
743
759
  if (source.state.status !== 'ready') {
744
760
  if (source.state.status === 'loading') {
745
- root.append(workspaceNotice(doc, { label: source.label, text: '目的・哲学・世界モデルを読み込んでいます。' }));
761
+ // A single shared loading card is rendered after the available catalogs.
746
762
  } else {
747
763
  const notice = { title: source.label, message: `取得失敗: ${source.state.error?.message ?? 'この対象は未確認です。0件ではありません。'}`, onRetry: callbacks.load };
748
764
  if (onNotice) onNotice(notice); else root.append(workspaceErrorCard(doc, notice));
@@ -778,10 +794,11 @@ export function renderFoundationCollectionOverview(root, sources, {
778
794
  const mount = makeElement(doc, 'div');
779
795
  renderFoundationOverview(mount, { status: 'ready', catalog }, {
780
796
  document: doc, scopeId: scopeLabel, showHeader: false, viewState, callbacks,
781
- recordContexts: contexts, partial: ready !== sources.length, onNotice,
797
+ recordContexts: contexts, partial: ready !== sources.length, onNotice, onLoading: () => {},
782
798
  });
783
799
  root.append(mount);
784
800
  }
801
+ renderLoadingState(doc, root, viewState, sources.some(source => source.state.status === 'loading'), onLoading);
785
802
  return root;
786
803
  }
787
804
 
@@ -841,6 +858,8 @@ export function createFoundationOverview({ root, port, scopeId, document: explic
841
858
  destroyed = true;
842
859
  generation += 1;
843
860
  viewState.dialog?.close();
861
+ viewState.cancelLoadingDismiss?.();
862
+ viewState.loadingCard = null;
844
863
  root.replaceChildren();
845
864
  },
846
865
  };
@@ -4,13 +4,190 @@
4
4
  min-width: 0;
5
5
  }
6
6
 
7
+ .bb-jh .bb-ws-breadcrumb {
8
+ margin-bottom: 4px;
9
+ font-size: 12px;
10
+ }
11
+
12
+ .bb-jh .bb-ws-page-head {
13
+ align-items: flex-end;
14
+ gap: 8px 16px;
15
+ }
16
+
17
+ .bb-jh .bb-ws-page-head h1 {
18
+ font-size: 20px;
19
+ font-weight: 800;
20
+ line-height: 1.25;
21
+ letter-spacing: 0;
22
+ }
23
+
24
+ .bb-jh .bb-ws-lead {
25
+ margin: 0;
26
+ font-size: 12.5px;
27
+ line-height: 1.4;
28
+ }
29
+
30
+ .bb-jh-banner {
31
+ display: flex;
32
+ align-items: center;
33
+ gap: 10px;
34
+ margin: 10px 0 8px;
35
+ padding: 6px 10px;
36
+ border: 1px solid #f0d98c;
37
+ border-radius: 6px;
38
+ background: #fff8e6;
39
+ font-size: 12.5px;
40
+ line-height: 1.4;
41
+ }
42
+
43
+ .bb-jh-banner.is-info {
44
+ border-color: #cddcf2;
45
+ background: #f2f6fc;
46
+ }
47
+
48
+ .bb-jh-banner.is-danger {
49
+ border-color: #f0b4b4;
50
+ background: #fdecec;
51
+ }
52
+
53
+ .bb-jh-banner > strong,
54
+ .bb-jh-banner-note,
55
+ .bb-jh-source-detail summary {
56
+ white-space: nowrap;
57
+ }
58
+
59
+ .bb-jh-banner-sources {
60
+ display: flex;
61
+ flex: 1 1 auto;
62
+ flex-wrap: nowrap;
63
+ gap: 12px;
64
+ min-width: 0;
65
+ overflow: hidden;
66
+ }
67
+
68
+ .bb-jh-banner-sources > span {
69
+ white-space: nowrap;
70
+ }
71
+
72
+ .bb-jh-banner-note {
73
+ color: var(--bb-color-muted);
74
+ }
75
+
76
+ .bb-jh-source-detail {
77
+ margin-left: auto;
78
+ flex: none;
79
+ }
80
+
81
+ .bb-jh-source-detail summary {
82
+ color: #1a56b8;
83
+ cursor: pointer;
84
+ }
85
+
86
+ .bb-jh-source-detail-body {
87
+ position: absolute;
88
+ z-index: 2;
89
+ display: grid;
90
+ gap: 4px;
91
+ max-width: 360px;
92
+ margin-top: 6px;
93
+ padding: 8px 10px;
94
+ border: 1px solid var(--bb-color-border);
95
+ border-radius: 6px;
96
+ background: var(--bb-color-panel, #fff);
97
+ color: var(--bb-color-muted);
98
+ font-size: 12px;
99
+ }
100
+
101
+ .bb-jh-source-detail-body p {
102
+ margin: 0;
103
+ }
104
+
105
+ .bb-jh-banner > .bb-ws-button {
106
+ align-self: center;
107
+ flex: none;
108
+ }
109
+
7
110
  .bb-jh-controls {
8
111
  display: flex;
9
- flex-wrap: wrap;
112
+ flex-wrap: nowrap;
10
113
  align-items: center;
11
- justify-content: space-between;
12
- gap: 14px 20px;
13
- margin: 28px 0 20px;
114
+ gap: 8px;
115
+ margin: 0 0 6px;
116
+ }
117
+
118
+ .bb-jh-toolbar-status {
119
+ display: flex;
120
+ flex: none;
121
+ align-items: center;
122
+ gap: 8px;
123
+ margin-left: auto;
124
+ }
125
+
126
+ .bb-jh-checked {
127
+ color: var(--bb-color-muted);
128
+ font-size: 12.5px;
129
+ white-space: nowrap;
130
+ }
131
+
132
+ .bb-jh-controls .bb-ws-button:disabled {
133
+ color: #9aa0a6;
134
+ opacity: 0.55;
135
+ }
136
+
137
+ .bb-jh-summary {
138
+ margin: 4px 0 6px;
139
+ color: #3b4148;
140
+ font-size: 12.5px;
141
+ }
142
+
143
+ .bb-jh-summary strong {
144
+ color: #111;
145
+ font-size: 14px;
146
+ }
147
+
148
+ .bb-jh-summary-note {
149
+ color: #6b7280;
150
+ }
151
+
152
+ .bb-jh-skeleton {
153
+ display: block;
154
+ height: 10px;
155
+ border-radius: 4px;
156
+ background: linear-gradient(90deg, #eef0f2, #f6f7f8, #eef0f2);
157
+ background-size: 200% 100%;
158
+ animation: bb-jh-shimmer 1.6s linear infinite;
159
+ }
160
+
161
+ .bb-jh-skeleton.is-inline {
162
+ display: inline-block;
163
+ width: 36px;
164
+ vertical-align: middle;
165
+ }
166
+
167
+ .bb-jh-skeleton.is-date { width: 60px; }
168
+ .bb-jh-skeleton.is-decision { width: 85%; }
169
+ .bb-jh-skeleton.is-reference { width: 75%; }
170
+ .bb-jh-skeleton.is-status { width: 60px; }
171
+
172
+ .bb-jh-skeleton-row {
173
+ pointer-events: none;
174
+ }
175
+
176
+ @keyframes bb-jh-shimmer {
177
+ from { background-position: 100% 0; }
178
+ to { background-position: -100% 0; }
179
+ }
180
+
181
+ .bb-jh.is-reduced-motion .bb-jh-skeleton {
182
+ animation: none;
183
+ background: #eef0f2;
184
+ }
185
+
186
+ @media (prefers-reduced-motion: reduce) {
187
+ .bb-jh-skeleton {
188
+ animation: none;
189
+ background: #eef0f2;
190
+ }
14
191
  }
15
192
 
16
193
  .bb-jh-reference-note {
@@ -22,8 +199,14 @@
22
199
 
23
200
  .bb-jh-periods {
24
201
  display: flex;
25
- flex-wrap: wrap;
26
- gap: 6px;
202
+ flex: none;
203
+ flex-wrap: nowrap;
204
+ gap: 0;
205
+ }
206
+
207
+ .bb-jh-periods .bb-ws-button {
208
+ min-height: 30px;
209
+ padding: 3px 10px;
27
210
  }
28
211
 
29
212
  .bb-jh-normal-filters {
@@ -34,11 +217,14 @@
34
217
  }
35
218
 
36
219
  .bb-jh-filter {
37
- display: grid;
38
- min-width: 130px;
220
+ display: flex;
221
+ flex: none;
222
+ align-items: center;
39
223
  gap: 4px;
224
+ min-width: 0;
40
225
  color: var(--bb-color-muted);
41
- font-size: 11px;
226
+ font-size: 12.5px;
227
+ white-space: nowrap;
42
228
  }
43
229
 
44
230
  .bb-jh-filter span {
@@ -46,10 +232,10 @@
46
232
  }
47
233
 
48
234
  .bb-jh-filter select {
49
- min-height: 38px;
235
+ min-height: 30px;
50
236
  border: 1px solid var(--bb-color-border-strong);
51
237
  border-radius: var(--bb-radius-sm);
52
- padding: 7px 28px 7px 10px;
238
+ padding: 3px 8px;
53
239
  background: var(--bb-color-panel);
54
240
  color: var(--bb-color-ink);
55
241
  font: inherit;
@@ -57,12 +243,13 @@
57
243
 
58
244
  .bb-jh-search {
59
245
  display: flex;
60
- flex: 1 1 230px;
246
+ flex: 1 1 110px;
61
247
  align-items: center;
62
248
  gap: 9px;
63
- max-width: 330px;
249
+ min-width: 110px;
250
+ max-width: none;
64
251
  color: var(--bb-color-muted);
65
- font-size: 12px;
252
+ font-size: 12.5px;
66
253
  }
67
254
 
68
255
  .bb-jh-search span {
@@ -77,10 +264,10 @@
77
264
 
78
265
  .bb-jh-search input {
79
266
  width: 100%;
80
- min-height: 38px;
267
+ min-height: 30px;
81
268
  border: 1px solid var(--bb-color-border-strong);
82
269
  border-radius: var(--bb-radius-sm);
83
- padding: 8px 12px;
270
+ padding: 3px 10px;
84
271
  background: var(--bb-color-panel);
85
272
  color: var(--bb-color-ink);
86
273
  font: inherit;
@@ -105,14 +292,14 @@
105
292
  }
106
293
 
107
294
  .bb-jh-ledger .bb-ws-ledger-row {
108
- grid-template-columns: 124px minmax(190px, 1.05fr) minmax(260px, 1.8fr);
109
- align-items: stretch;
110
- min-height: 76px;
295
+ grid-template-columns: 92px minmax(0, 1fr) 250px 105px;
296
+ align-items: center;
297
+ min-height: 52px;
111
298
  }
112
299
 
113
300
  .bb-jh-ledger .bb-ws-ledger-head {
114
301
  align-items: center;
115
- min-height: 38px;
302
+ min-height: 32px;
116
303
  }
117
304
 
118
305
  .bb-jh-ledger .bb-ws-ledger-row > span {
@@ -386,7 +573,47 @@
386
573
  text-transform: uppercase;
387
574
  }
388
575
 
576
+ .bb-jh-controls,
577
+ .bb-jh-banner-sources {
578
+ flex-wrap: wrap;
579
+ }
580
+
389
581
  .bb-jh-ledger .bb-ws-ledger-row > span:nth-child(1)::before { content: '日時'; }
390
- .bb-jh-ledger .bb-ws-ledger-row > span:nth-child(2)::before { content: '使った参照'; }
391
- .bb-jh-ledger .bb-ws-ledger-row > span:nth-child(3)::before { content: '行った判断'; }
392
- }
582
+ .bb-jh-ledger .bb-ws-ledger-row > span:nth-child(2)::before { content: '行った判断'; }
583
+ .bb-jh-ledger .bb-ws-ledger-row > span:nth-child(3)::before { content: '使った参照'; }
584
+ .bb-jh-ledger .bb-ws-ledger-row > span:nth-child(4)::before { content: '入口・状態'; }
585
+ }
586
+
587
+ /* Compact workspace header, search controls and shared floating notifications. */
588
+ .bb-jh { position: relative; }
589
+ .bb-jh > .bb-ws-page { margin-bottom: var(--bb-space-6, 32px); }
590
+ .bb-jh .bb-ws-page-head h1 { font-size: 24px; line-height: 1.4; font-weight: 600; letter-spacing: .02em; }
591
+ .bb-jh-controls { margin-bottom: var(--bb-space-4, 16px); }
592
+ .bb-jh-checked { font-size: 11px; font-variant-numeric: tabular-nums; }
593
+ .bb-jh-filter-fields { display: grid; gap: 16px; }
594
+ .bb-jh-filter-fields .bb-jh-periods { flex-wrap: wrap; gap: 6px; }
595
+ .bb-jh-filter-fields .bb-jh-normal-filters { display: grid; flex: none; gap: 16px; }
596
+ .bb-jh-filter-fields .bb-jh-filter { display: grid; gap: 6px; }
597
+ .bb-jh-filter-fields select { width: 100%; }
598
+ .bb-jh-refresh { display: grid; place-items: center; flex: none; width: 32px; height: 32px; padding: 6px; }
599
+ .bb-jh-refresh-mark { display: block; width: 16px; height: 16px; }
600
+ .bb-jh-notifications { display: grid; gap: 8px; }
601
+ .bb-jh-notifications .bb-jh-banner { margin: 0; }
602
+ .bb-jh-notifications .bb-jh-banner-sources { display: grid; gap: 4px; margin-top: 8px; }
603
+ .bb-jh-notifications .bb-jh-source-detail { margin: 8px 0 0; }
604
+ .bb-jh-notifications .bb-jh-source-detail summary { color: inherit; }
605
+ .bb-jh-notifications .bb-jh-source-detail-body { position: static; max-width: none; background: transparent; border-color: var(--bb-color-notice-border); color: inherit; }
606
+ .bb-jh-detail .bb-ws-rail-head { margin-top: 0; }
607
+ @media (max-width: 760px) {
608
+ .bb-jh-controls { flex-direction: row; flex-wrap: wrap; align-items: center; }
609
+ .bb-jh-search { flex: 1 1 150px; }
610
+ .bb-jh-toolbar-status { margin-left: auto; }
611
+ }
612
+ .bb-jh-notifications .bb-jh-banner {
613
+ border-color: var(--bb-color-notice-border);
614
+ background: var(--bb-color-notice-background);
615
+ color: var(--bb-color-notice-text);
616
+ border-left-color: var(--bb-color-notice-warning);
617
+ }
618
+ .bb-jh-notifications .bb-jh-banner.is-danger { border-left-color: var(--bb-color-notice-danger); }
619
+ .bb-jh-notifications .bb-jh-banner-sources > span { white-space: normal; }