@unson/brainbase-mcp 0.41.10 → 0.41.11

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.
@@ -793,6 +793,79 @@ function groupFor(groups, sessionRef, key) {
793
793
  groups.set(groupKey, group);
794
794
  return group;
795
795
  }
796
+ const FRAME_USE_ROLES = new Set(['constraint', 'criterion', 'prediction']);
797
+ const FRAME_USE_VERDICTS = new Set(['satisfied', 'violated', 'tension']);
798
+ const FRAME_PREDICTION_CHECKS = new Set(['held', 'failed', 'unchecked']);
799
+ /**
800
+ * The usage value shared by every writer of judgment history references
801
+ * (docs/specs/judgment-history-frame-basis.md): the role in the chosen option,
802
+ * then the constraint verdict or the prediction check.
803
+ */
804
+ function frameUseUsage(use) {
805
+ const role = text(use.role);
806
+ if (!role || !FRAME_USE_ROLES.has(role))
807
+ return null;
808
+ if (role === 'prediction') {
809
+ const check = isObject(use.check) ? text(use.check.status) : null;
810
+ return `prediction:${check && FRAME_PREDICTION_CHECKS.has(check) ? check : 'unchecked'}`;
811
+ }
812
+ const verdict = text(use.verdict);
813
+ if (role === 'constraint')
814
+ return verdict && FRAME_USE_VERDICTS.has(verdict) ? `constraint:${verdict}` : null;
815
+ return verdict && FRAME_USE_VERDICTS.has(verdict) ? `criterion:${verdict}` : 'criterion';
816
+ }
817
+ /** Carry how the chosen option used each selected reference; rejected options never leak in. */
818
+ function frameReferencesWithUsage(frame) {
819
+ const references = frame.selected_references;
820
+ if (!Array.isArray(references))
821
+ return references;
822
+ const chosenLabel = text(frame.chosen_option);
823
+ const chosen = Array.isArray(frame.alternatives)
824
+ ? frame.alternatives.find((option) => isObject(option) && chosenLabel !== null && option.label === chosenLabel)
825
+ : null;
826
+ const uses = isObject(chosen) && Array.isArray(chosen.uses) ? chosen.uses.filter(isObject) : [];
827
+ return references.map((reference) => {
828
+ if (!isObject(reference))
829
+ return reference;
830
+ const ref = text(reference.ref);
831
+ const use = ref ? uses.find((candidate) => text(candidate.ref) === ref) : undefined;
832
+ const usage = use ? frameUseUsage(use) : null;
833
+ return usage && reference.usage === undefined ? { ...reference, usage } : reference;
834
+ });
835
+ }
836
+ /**
837
+ * Personal KG records the owner's answer applied in this turn. Only resolved
838
+ * answers count; their content never enters the history record.
839
+ */
840
+ function personalKnowledgeReferences(events) {
841
+ const references = [];
842
+ const seen = new Set();
843
+ for (const event of events) {
844
+ if (event.success !== true || text(event.event_kind) !== 'personal_answer')
845
+ continue;
846
+ const metadata = isObject(event.safe_metadata) ? event.safe_metadata : null;
847
+ const answer = metadata && isObject(metadata.personal_answer) ? metadata.personal_answer : null;
848
+ if (!answer || text(answer.status) !== 'resolved' || !Array.isArray(answer.reference_ids))
849
+ continue;
850
+ for (const value of answer.reference_ids) {
851
+ const ref = safeId(value);
852
+ if (!ref || seen.has(ref))
853
+ continue;
854
+ seen.add(ref);
855
+ references.push({ ref, kind: 'personal_knowledge', version: null, digest: null, why: null, usage: 'applied', availability: 'unknown' });
856
+ }
857
+ }
858
+ return references;
859
+ }
860
+ function withPersonalKnowledge(judgment, events) {
861
+ const personal = personalKnowledgeReferences(events);
862
+ if (personal.length === 0)
863
+ return judgment;
864
+ const existing = judgment.selected_references ?? [];
865
+ const known = new Set(existing.map((reference) => `${reference.kind ?? ''}\u0000${reference.ref}`));
866
+ const added = personal.filter((reference) => !known.has(`${reference.kind}\u0000${reference.ref}`));
867
+ return added.length === 0 ? judgment : { ...judgment, selected_references: [...existing, ...added] };
868
+ }
796
869
  function sourceBlocks(value) {
797
870
  if (!value)
798
871
  return [];
@@ -808,7 +881,7 @@ function sourceBlocks(value) {
808
881
  const frame = isObject(metadata.judgment_frame) ? metadata.judgment_frame : null;
809
882
  if (frame)
810
883
  blocks.push({
811
- selected_references: frame.selected_references,
884
+ selected_references: frameReferencesWithUsage(frame),
812
885
  alternatives: Array.isArray(frame.alternatives) ? frame.alternatives.map((option) => isObject(option) ? {
813
886
  label: option.label,
814
887
  evaluation: null,
@@ -1018,7 +1091,7 @@ function normalizeFinalRecord(final, sessionRef, key, configuredEntrypoint, turn
1018
1091
  recorded_at: recordedAt,
1019
1092
  project_code: projectCode,
1020
1093
  turn_ref: `${sessionRef}/${sha256(turnId)}`,
1021
- judgment: mergeJudgment(judgment, blocks, field(blocks[0] ?? null, 'missing_fields')),
1094
+ judgment: withPersonalKnowledge(mergeJudgment(judgment, blocks, field(blocks[0] ?? null, 'missing_fields')), events),
1022
1095
  execution: mergeExecution({ ...execution, status: finalExecutionStatus }, [...executionBlocks(final), ...events.flatMap((event) => executionBlocks(event)).reverse()], completed)
1023
1096
  };
1024
1097
  return { ...baseRecord, missing_fields: missingFields(baseRecord, firstPresent(blocks, 'missing_fields')) };
@@ -1034,7 +1107,7 @@ function mergeRecordWithFinal(adoptionRecord, final, sessionRef, key, turnInput,
1034
1107
  recorded_at: projected.recorded_at,
1035
1108
  project_code: adoptionRecord.project_code ?? projected.project_code,
1036
1109
  entrypoint: adoptionRecord.entrypoint === 'unknown' ? projected.entrypoint : adoptionRecord.entrypoint,
1037
- judgment: mergeJudgment(adoptionRecord.judgment, blocks, undefined),
1110
+ judgment: withPersonalKnowledge(mergeJudgment(adoptionRecord.judgment, blocks, undefined), events),
1038
1111
  execution
1039
1112
  };
1040
1113
  return { ...baseRecord, missing_fields: missingFields(baseRecord, firstPresent(blocks, 'missing_fields')) };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unson/brainbase-mcp",
3
- "version": "0.41.10",
3
+ "version": "0.41.11",
4
4
  "description": "Local-first Brainbase judgment OS that lets supported AI agents reuse a user's approved goals, priorities, decisions, and judgment criteria.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -483,5 +483,5 @@
483
483
  "engines": {
484
484
  "node": ">=20"
485
485
  },
486
- "gitHead": "9ea5345d8da4b0cf825daf73610474dd8903a8f5"
486
+ "gitHead": "3849d107c129672e91d6c28cfa3b8b5053d7f53a"
487
487
  }
@@ -292,7 +292,7 @@
292
292
  }
293
293
 
294
294
  .bb-jh-ledger .bb-ws-ledger-row {
295
- grid-template-columns: 92px minmax(0, 1fr) 250px 105px;
295
+ grid-template-columns: 92px minmax(0, 1fr) 250px 120px;
296
296
  align-items: center;
297
297
  min-height: 52px;
298
298
  }
@@ -581,7 +581,7 @@
581
581
  .bb-jh-ledger .bb-ws-ledger-row > span:nth-child(1)::before { content: '日時'; }
582
582
  .bb-jh-ledger .bb-ws-ledger-row > span:nth-child(2)::before { content: '行った判断'; }
583
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: '入口・状態'; }
584
+ .bb-jh-ledger .bb-ws-ledger-row > span:nth-child(4)::before { content: '判断したAI'; }
585
585
  }
586
586
 
587
587
  /* Compact workspace header, search controls and shared floating notifications. */
@@ -617,3 +617,156 @@
617
617
  }
618
618
  .bb-jh-notifications .bb-jh-banner.is-danger { border-left-color: var(--bb-color-notice-danger); }
619
619
  .bb-jh-notifications .bb-jh-banner-sources > span { white-space: normal; }
620
+
621
+ /* Loading stays in the page, like the other workspace screens. */
622
+ .bb-jh-loading { color: var(--bb-color-muted); }
623
+ .bb-jh-summary-note { font-size: 11.5px; }
624
+ .bb-jh-entrypoint { display: grid; gap: 2px; }
625
+ .bb-jh-entrypoint small.bb-jh-waiting { color: var(--bb-color-warning-strong, var(--bb-color-accent-strong)); font-size: 11px; font-weight: 600; }
626
+ .bb-jh-filter-fields .bb-jh-filter .bb-ws-combobox { width: 100%; }
627
+
628
+ /* Detail: references that only have an id, the one question, and the record details. */
629
+ .bb-jh-references { display: grid; gap: 8px; }
630
+ .bb-jh-reference-list small { color: var(--bb-color-quiet); font-size: 11px; }
631
+ .bb-jh-reference-kinds { margin: 0; color: var(--bb-color-ink); font-size: 13px; font-weight: 600; }
632
+ .bb-jh-references .bb-jh-reference-note,
633
+ .bb-jh-handoff .bb-jh-reference-note { margin: 0; }
634
+ .bb-jh-feedback { display: grid; gap: 12px; }
635
+ .bb-jh-feedback-events { display: grid; gap: 0; margin: 0; padding: 0; list-style: none; }
636
+ .bb-jh-feedback-answers { display: flex; flex-wrap: wrap; gap: 6px; }
637
+ .bb-jh-feedback-composer > .bb-ws-button { justify-self: start; }
638
+ .bb-jh-record-details { margin-top: 10px; }
639
+ .bb-jh-record-details > summary { color: var(--bb-color-muted); font-size: 12px; cursor: pointer; }
640
+ .bb-jh-record-details[open] > summary { margin-bottom: 8px; }
641
+ .bb-jh-record-details .bb-ws-definition dd { overflow-wrap: anywhere; }
642
+ .bb-jh-id-list { display: grid; gap: 2px; margin: 0; padding: 0; list-style: none; font-family: var(--bb-font-mono); font-size: 10.5px; color: var(--bb-color-quiet); overflow-wrap: anywhere; }
643
+ .bb-jh-handoff { display: grid; gap: 6px; margin-top: 14px; }
644
+ .bb-jh-handoff h4 { margin: 0; font-size: 12.5px; color: var(--bb-color-ink); }
645
+ .bb-jh-feedback-answers .bb-ws-button[aria-pressed="true"] { border-color: var(--bb-color-accent); background: var(--bb-color-accent-soft, #eeebfd); color: var(--bb-color-accent-strong, var(--bb-color-accent)); }
646
+ .bb-jh-feedback-composer [data-action="submit-judgment-feedback"] { border-color: var(--bb-color-accent); background: var(--bb-color-accent); color: #fff; }
647
+ .bb-jh-feedback-composer [data-action="submit-judgment-feedback"]:disabled { opacity: .55; cursor: default; }
648
+ .bb-jh-feedback-composer textarea,
649
+ .bb-jh-reference-export textarea { box-sizing: border-box; }
650
+
651
+ /* 判断の根拠と本人の考え (story-judgment-history-frame-basis-v1) */
652
+ .bb-jh-basis {
653
+ display: grid;
654
+ gap: 14px;
655
+ }
656
+
657
+ .bb-jh-basis-group {
658
+ display: grid;
659
+ gap: 6px;
660
+ min-width: 0;
661
+ }
662
+
663
+ .bb-jh-basis-group h4 {
664
+ margin: 0;
665
+ color: var(--bb-color-muted);
666
+ font-size: 11px;
667
+ font-weight: 680;
668
+ letter-spacing: 0.04em;
669
+ }
670
+
671
+ .bb-jh-basis-list {
672
+ display: grid;
673
+ gap: 10px;
674
+ margin: 0;
675
+ padding: 0;
676
+ list-style: none;
677
+ }
678
+
679
+ .bb-jh-basis-list li {
680
+ display: grid;
681
+ gap: 3px;
682
+ min-width: 0;
683
+ padding-left: 10px;
684
+ border-left: 2px solid var(--bb-color-border);
685
+ }
686
+
687
+ .bb-jh-basis-list strong {
688
+ color: var(--bb-color-ink);
689
+ font-size: 13px;
690
+ line-height: 1.45;
691
+ overflow-wrap: anywhere;
692
+ }
693
+
694
+ .bb-jh-basis-list strong.bb-jh-unrecorded {
695
+ color: var(--bb-color-quiet);
696
+ font-weight: 500;
697
+ }
698
+
699
+ .bb-jh-basis-usage {
700
+ color: var(--bb-color-muted);
701
+ font-size: 12px;
702
+ line-height: 1.5;
703
+ }
704
+
705
+ .bb-jh-basis-usage.is-violated,
706
+ .bb-jh-basis-usage.is-failed {
707
+ color: var(--bb-color-danger);
708
+ }
709
+
710
+ .bb-jh-basis-usage.is-tension {
711
+ color: var(--bb-color-warning);
712
+ }
713
+
714
+ .bb-jh-basis-usage.is-unrecorded {
715
+ color: var(--bb-color-quiet);
716
+ }
717
+
718
+ .bb-jh-basis-why {
719
+ color: var(--bb-color-muted);
720
+ font-size: 12px;
721
+ line-height: 1.5;
722
+ }
723
+
724
+ .bb-jh-basis-list small {
725
+ color: var(--bb-color-quiet);
726
+ font-size: 11px;
727
+ }
728
+
729
+ .bb-jh-owner {
730
+ display: grid;
731
+ gap: 4px;
732
+ padding: 10px 12px;
733
+ border: 1px solid var(--bb-color-border);
734
+ border-radius: var(--bb-radius-sm);
735
+ background: var(--bb-color-panel);
736
+ }
737
+
738
+ .bb-jh-owner.is-applied {
739
+ border-color: var(--bb-color-accent);
740
+ background: var(--bb-color-accent-soft);
741
+ }
742
+
743
+ .bb-jh-owner strong {
744
+ color: var(--bb-color-ink);
745
+ font-size: 13px;
746
+ line-height: 1.5;
747
+ }
748
+
749
+ .bb-jh-owner p {
750
+ margin: 0;
751
+ color: var(--bb-color-muted);
752
+ font-size: 12px;
753
+ line-height: 1.5;
754
+ }
755
+
756
+ .bb-jh-owner-badge {
757
+ width: fit-content;
758
+ padding: 1px 7px;
759
+ border: 1px solid var(--bb-color-border);
760
+ border-radius: 999px;
761
+ color: var(--bb-color-quiet);
762
+ font-size: 11px;
763
+ line-height: 1.6;
764
+ white-space: nowrap;
765
+ }
766
+
767
+ .bb-jh-owner-badge.is-applied {
768
+ border-color: var(--bb-color-accent);
769
+ background: var(--bb-color-accent-soft);
770
+ color: var(--bb-color-accent-strong);
771
+ font-weight: 680;
772
+ }