@takagaki/cortex-decisions-viewer 0.12.122 → 0.12.123

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.
@@ -7,7 +7,7 @@ exports.PERMISSIONS_DATA = void 0;
7
7
  * 操作タブの[権限]がこの値を CLIENT_JS に注入して読む(公開ページと同じ中身)。
8
8
  */
9
9
  exports.PERMISSIONS_DATA = {
10
- "revisedOn": "2026年9月30日",
10
+ "revisedOn": "2026年10月8日",
11
11
  "enactedOn": "2026年9月25日",
12
12
  "tools": [
13
13
  {
@@ -292,6 +292,12 @@ exports.PERMISSIONS_DATA = {
292
292
  "accessText": "読む",
293
293
  "purpose": "会議のメモを探して読む"
294
294
  },
295
+ {
296
+ "spell": "https://www.googleapis.com/auth/drive.file",
297
+ "access": "write",
298
+ "accessText": "書く",
299
+ "purpose": "投入フォームから入った材料の根拠として、Cortex 自身が作ったフォルダに Google ドキュメントを置き、そのプロジェクトのメンバーだけに閲覧を許す(Cortex が作ったもの以外は開けません)"
300
+ },
295
301
  {
296
302
  "spell": "https://www.googleapis.com/auth/calendar",
297
303
  "access": "write",
package/dist/render.js CHANGED
@@ -6079,6 +6079,12 @@ button.ops-card-btn:disabled { opacity: .6; cursor: default; }
6079
6079
  color: var(--text); background: var(--surface); font-family: inherit;
6080
6080
  }
6081
6081
  .file-chip.is-unguessed { background: #fffbeb; border-color: #fcd34d; color: #92400e; }
6082
+ /* 記録の種類(cortex-engine #1094 V2a)。選ぶまで赤い枠(選ばないと送れない) */
6083
+ .file-chip-kind {
6084
+ border: 1px solid var(--border); border-radius: 6px; padding: 1px 4px; font-size: 11.5px;
6085
+ color: var(--text); background: var(--surface); font-family: inherit;
6086
+ }
6087
+ .file-chip-kind.is-unset { border-color: #dc2626; color: #b91c1c; }
6082
6088
  .file-chip-guess { font-size: 11px; font-weight: 700; color: #92400e; white-space: nowrap; }
6083
6089
  /* 会議名の欄(選択肢+新規入力+入力エラー) */
6084
6090
  .meeting-field { display: flex; flex-direction: column; gap: 6px; }
@@ -18860,6 +18866,15 @@ ${calendarAddUrl.toString()}
18860
18866
  ? { txt: 1, md: 1, docx: 1, doc: 1, rtf: 1, pdf: 1, vtt: 1, srt: 1 }
18861
18867
  : { pdf: 1, docx: 1, doc: 1, pptx: 1, ppt: 1, xlsx: 1, xls: 1, csv: 1, txt: 1, md: 1, rtf: 1, png: 1, jpg: 1, jpeg: 1, gif: 1, webp: 1, svg: 1, bmp: 1, heic: 1, tiff: 1 };
18862
18868
  var allowedLabel = "テキスト・Word・PDF・字幕(.vtt/.srt)";
18869
+ // 記録の種類(cortex-engine #1094 V2a)。値は取り込みの台帳の語彙(受け口の LEDGER_RECORD_KINDS)と同じ
18870
+ // 種類を尋ねるのは、取り込みの台帳に本文が載る文字のファイルだけ(Word・PDF は本文が台帳に載らないので、選んでも残らない)
18871
+ var RECORD_KIND_EXT = { txt: 1, md: 1, csv: 1, vtt: 1, srt: 1 };
18872
+ function asksKind(entry) { return isT && !!RECORD_KIND_EXT[extOf(entry.file.name)]; }
18873
+ var RECORD_KIND_OPTIONS = [
18874
+ { value: "transcript", label: "文字起こし" },
18875
+ { value: "human_minutes", label: "人の議事録" },
18876
+ { value: "tool_ai_summary", label: "AI の要約" },
18877
+ ];
18863
18878
  function extOf(name) { var m = String(name).toLowerCase().match(/\.([a-z0-9]+)$/); return m ? m[1] : ""; }
18864
18879
  var fileInput = el("input", { type: "file", multiple: "multiple", class: "modal-file-hidden" });
18865
18880
  var fileListEl = el("div", { class: "dropzone-files" });
@@ -18889,7 +18904,7 @@ ${calendarAddUrl.toString()}
18889
18904
  var meetingBox = el("div", { class: "meeting-field" });
18890
18905
  if (meetingList.length) {
18891
18906
  meetingSelect = el("select", { class: "modal-name meeting-select" });
18892
- meetingSelect.appendChild(el("option", { value: "", text: "会議を選択してください" }));
18907
+ meetingSelect.appendChild(el("option", { value: "", text: "既にある会議を選ぶ" }));
18893
18908
  meetingList.forEach(function (m) {
18894
18909
  meetingSelect.appendChild(el("option", { value: m.path, text: m.path }));
18895
18910
  });
@@ -19046,10 +19061,13 @@ ${calendarAddUrl.toString()}
19046
19061
  refreshMeetingError();
19047
19062
  refreshDupWarn();
19048
19063
  var ok = !!(nameInput.value.trim() && selectedFiles.length);
19049
- // 文字起こしは会議名が確定し、各ファイルの日付が入っているときだけ送れる
19064
+ // 文字起こしは会議名が確定し、各ファイルの日付と記録の種類が入っているときだけ送れる
19065
+ var kindMissing = selectedFiles.filter(function (e) { return asksKind(e) && !e.recordKind; }).length;
19050
19066
  if (isT) {
19051
- ok = ok && !meetingProblem() && selectedFiles.every(function (e) { return !!e.date; });
19067
+ ok = ok && !meetingProblem() && kindMissing === 0 && selectedFiles.every(function (e) { return !!e.date; });
19052
19068
  }
19069
+ // 種類の選び忘れは件数をボタンに出す(どこを直せば押せるかが分かる)
19070
+ submitBtn.textContent = kindMissing ? "記録の種類を選んでください(あと " + kindMissing + " 件)" : "送信";
19053
19071
  submitBtn.disabled = !ok;
19054
19072
  }
19055
19073
  function renderFiles() {
@@ -19076,6 +19094,21 @@ ${calendarAddUrl.toString()}
19076
19094
  });
19077
19095
  chip.appendChild(dateInput);
19078
19096
  if (note) chip.appendChild(note);
19097
+ // 記録の種類(cortex-engine #1094 V2a)。**既定値は置かない**——間違った種類が黙って入ると、
19098
+ // 会議ごとの一次の記録の選び方(文字起こし → 人の議事録 → AI の要約)を取り違える
19099
+ if (asksKind(entry)) {
19100
+ var kindSelect = el("select", { class: "file-chip-kind" + (entry.recordKind ? "" : " is-unset"), "aria-label": entry.file.name + " の記録の種類" });
19101
+ kindSelect.appendChild(el("option", { value: "", text: "記録の種類を選ぶ" }));
19102
+ RECORD_KIND_OPTIONS.forEach(function (o) { kindSelect.appendChild(el("option", { value: o.value, text: o.label })); });
19103
+ kindSelect.value = entry.recordKind || "";
19104
+ kindSelect.addEventListener("click", function (e) { e.stopPropagation(); });
19105
+ kindSelect.addEventListener("change", function () {
19106
+ entry.recordKind = kindSelect.value;
19107
+ kindSelect.className = "file-chip-kind" + (entry.recordKind ? "" : " is-unset");
19108
+ update();
19109
+ });
19110
+ chip.appendChild(kindSelect);
19111
+ }
19079
19112
  }
19080
19113
  var x = el("button", { class: "file-chip-x", type: "button", text: "×" });
19081
19114
  x.addEventListener("click", function (e) { e.stopPropagation(); selectedFiles.splice(idx, 1); renderFiles(); update(); });
@@ -19098,7 +19131,7 @@ ${calendarAddUrl.toString()}
19098
19131
  var guess = isT ? guessMeetingDate(f.name) : null;
19099
19132
  // 推せなければ当日を仮置きする。**空のままにしない**——日付が空の入力欄は
19100
19133
  // 「入れなくてよい」に見えるが、実際は送れない(送信ボタンが無効なだけ)
19101
- selectedFiles.push({ file: f, date: isT ? (guess || todayIso()) : "", guessed: !!guess });
19134
+ selectedFiles.push({ file: f, date: isT ? (guess || todayIso()) : "", guessed: !!guess, recordKind: "" });
19102
19135
  addedNames.push(f.name || "");
19103
19136
  });
19104
19137
  if (isT && addedNames.length) autoPickMeeting(addedNames);
@@ -19189,6 +19222,7 @@ ${calendarAddUrl.toString()}
19189
19222
  var up = { key: pres.j.key, filename: f.name };
19190
19223
  // 会議日は YYYYMMDD で送る(そのまま日付ディレクトリの名前になる)
19191
19224
  if (isT) up.date = String(entries[i].date || "").split("-").join("");
19225
+ if (isT && entries[i].recordKind) up.recordKind = entries[i].recordKind;
19192
19226
  uploaded.push(up);
19193
19227
  }
19194
19228
  setStatus("取り込み中…", false);
package/dist/story.js CHANGED
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.STORY_DIGEST_EMPTY_LINE = exports.STORY_MAX_MONTHS = exports.STORY_MAX_WEEKS = exports.STORY_MONTHS_DIR = exports.STORY_WEEKS_DIR = exports.STORY_MAX_FILE_BYTES = exports.STORY_COLLAPSE_QUIET_DAYS = exports.STORY_EMPTY_LINE = exports.STORY_MAX_DAYS = exports.STORY_DAYS_DIR = exports.STORY_LEDGER_FILE = void 0;
7
7
  exports.parseStoryLedger = parseStoryLedger;
8
+ exports.partialDaysOf = partialDaysOf;
8
9
  exports.onDaysOf = onDaysOf;
9
10
  exports.storyDayMarkdown = storyDayMarkdown;
10
11
  exports.isEngineQuietDay = isEngineQuietDay;
@@ -109,6 +110,18 @@ function parseStoryLedger(text) {
109
110
  return "broken";
110
111
  }
111
112
  }
113
+ /** 帳簿で途中まで書いた日(`v2.partial_at` が空でない文字列の行・engine の `partialAtOf` と同じ判じ。engine #1094)。この日は「書けている最後の日」に数えない */
114
+ function partialDaysOf(ledger) {
115
+ const out = new Set();
116
+ for (const [day, row] of Object.entries(ledger.days)) {
117
+ if (!DAY_RE.test(day) || !row || typeof row !== "object")
118
+ continue;
119
+ const v2 = row.v2;
120
+ if (v2 && typeof v2 === "object" && typeof v2.partial_at === "string" && v2.partial_at.trim() !== "")
121
+ out.add(day);
122
+ }
123
+ return out;
124
+ }
112
125
  /** 帳簿で `mode: "on"` の日 */
113
126
  function onDaysOf(ledger) {
114
127
  const out = new Set();
@@ -385,7 +398,9 @@ ledgerDir) {
385
398
  }
386
399
  // 一番古い「動きのある日」から今日まで、日付の抜けを動きのない日の行で埋める。動きのある日が 1 つも無ければ出さない
387
400
  // 最後の日=帳簿で on の最後の日(日のファイルの日付ではない。末尾に静かな日が続いても、帳簿には処理した印が残る)
388
- const lastDay = [...on].reduce((a, d) => (a === null || d > a ? d : a), null);
401
+ // 途中まで書いた日(partial_at つき)は数えない。その日のファイルがあれば本文は出る
402
+ const partial = partialDaysOf(ledger);
403
+ const lastDay = [...on].filter((d) => !partial.has(d)).reduce((a, d) => (a === null || d > a ? d : a), null);
389
404
  return out.length ? withQuietDays(out, today, lastDay) : null;
390
405
  }
391
406
  // ---------------------------------------------------------------------------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takagaki/cortex-decisions-viewer",
3
- "version": "0.12.122",
3
+ "version": "0.12.123",
4
4
  "description": "Cortexの意思決定記録(Decisions/*.md)を静的サイトにビルドして閲覧する。各レコードに「Edit on GitHub」リンクを付与する。",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,