@takagaki/cortex-decisions-viewer 0.12.199 → 0.12.210
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/README.md +4 -2
- package/dist/build.js +64 -83
- package/dist/canonical-evidence.js +11 -191
- package/dist/change-log.js +1 -1
- package/dist/config-flow.js +462 -0
- package/dist/config-mode.js +57 -0
- package/dist/confirmed.js +2 -2
- package/dist/engine/decision-v2-fields.js +188 -0
- package/dist/engine/ref-tokens.js +276 -0
- package/dist/engine/related-materials-field.js +148 -0
- package/dist/engine/supersedes-index.js +257 -0
- package/dist/google-confirm-page.js +54 -7
- package/dist/ledger-dir.js +1 -0
- package/dist/memory-dir.js +40 -0
- package/dist/rederivation.js +17 -8
- package/dist/render.js +905 -74
- package/dist/story.js +13 -9
- package/dist/supersedes.js +12 -110
- package/dist/view-dir.js +100 -2
- package/package.json +2 -2
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// engine-src/supersedes-index.mjs
|
|
31
|
+
var supersedes_index_exports = {};
|
|
32
|
+
__export(supersedes_index_exports, {
|
|
33
|
+
SHADOW_SAMPLE_IDS: () => SHADOW_SAMPLE_IDS,
|
|
34
|
+
compareSupersedes: () => compareSupersedes,
|
|
35
|
+
decisionDateOf: () => decisionDateOf,
|
|
36
|
+
decisionKeyOf: () => decisionKeyOf,
|
|
37
|
+
legacyRetiredTargetsOf: () => legacyRetiredTargetsOf,
|
|
38
|
+
legacySupersededBy: () => legacySupersededBy,
|
|
39
|
+
legacySupersedesIndex: () => legacySupersedesIndex,
|
|
40
|
+
retiredIdsOf: () => retiredIdsOf,
|
|
41
|
+
splitSupersededBy: () => splitSupersededBy,
|
|
42
|
+
supersedesIndex: () => supersedesIndex,
|
|
43
|
+
supersedesIndexStateOf: () => supersedesIndexStateOf,
|
|
44
|
+
supersedesOf: () => supersedesOf,
|
|
45
|
+
supersedesShadowSummaryLines: () => supersedesShadowSummaryLines
|
|
46
|
+
});
|
|
47
|
+
module.exports = __toCommonJS(supersedes_index_exports);
|
|
48
|
+
var import_node_path = __toESM(require("node:path"), 1);
|
|
49
|
+
|
|
50
|
+
// engine-src/confirmed.mjs
|
|
51
|
+
var DRAFT_STATUS_V1 = "draft";
|
|
52
|
+
var CONFIRMED_STATUSES_V1 = Object.freeze({
|
|
53
|
+
Decisions: Object.freeze(["active"]),
|
|
54
|
+
Rules: Object.freeze(["active"]),
|
|
55
|
+
Glossary: Object.freeze(["active", "superseded"]),
|
|
56
|
+
Members: Object.freeze(["active", "inactive"])
|
|
57
|
+
});
|
|
58
|
+
var CONFIRMED_STATUSES_ANY_V1 = Object.freeze(["active", "superseded", "inactive"]);
|
|
59
|
+
function sectionOfPath(p) {
|
|
60
|
+
const s = typeof p === "string" ? p.replace(/\\/g, "/") : "";
|
|
61
|
+
for (const section of Object.keys(CONFIRMED_STATUSES_V1)) {
|
|
62
|
+
if (s.startsWith(`Memory/${section}/`) || s.includes(`/Memory/${section}/`)) return section;
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
function checked(status) {
|
|
67
|
+
if (status === null || status === void 0 || typeof status === "string") return status;
|
|
68
|
+
throw new TypeError(`confirmed: status \u306F\u6587\u5B57\u5217\u3067\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u5B9F\u969B: ${typeof status}\uFF09`);
|
|
69
|
+
}
|
|
70
|
+
var HANDS = null;
|
|
71
|
+
var REPORT = null;
|
|
72
|
+
var CREATED = /* @__PURE__ */ new Set();
|
|
73
|
+
var HANDS_OPS = Object.freeze(["own", "rewrite", "append"]);
|
|
74
|
+
var HANDS_STATES = Object.freeze(["on", "shadow"]);
|
|
75
|
+
var noStatus = (s) => s === void 0 || s === null || s === "";
|
|
76
|
+
function handsPathOf(p) {
|
|
77
|
+
if (typeof p !== "string" || !p) return null;
|
|
78
|
+
const s = p.normalize("NFC").replace(/\\/g, "/");
|
|
79
|
+
if (s.startsWith("Memory/")) return s;
|
|
80
|
+
let at = -1;
|
|
81
|
+
for (const m2 of s.matchAll(/(?:^|\/)(Memory\/(?:Decisions|Rules|Glossary|Members)\/)/g)) at = m2.index + m2[0].length - m2[1].length;
|
|
82
|
+
if (at >= 0) return s.slice(at);
|
|
83
|
+
const m = /(?:^|\/)(Memory\/.+)$/.exec(s);
|
|
84
|
+
return m ? m[1] : s;
|
|
85
|
+
}
|
|
86
|
+
function lockIn(h, p) {
|
|
87
|
+
const k = handsPathOf(p);
|
|
88
|
+
if (!k) return true;
|
|
89
|
+
const rec = h.records.get(k);
|
|
90
|
+
if (rec) return h.allLock ? true : rec.lock;
|
|
91
|
+
return !CREATED.has(k);
|
|
92
|
+
}
|
|
93
|
+
function touchedIn(h, p) {
|
|
94
|
+
const k = handsPathOf(p);
|
|
95
|
+
const rec = k ? h.records.get(k) : null;
|
|
96
|
+
return Boolean(rec && rec.touched);
|
|
97
|
+
}
|
|
98
|
+
var note = (name, p) => {
|
|
99
|
+
if (REPORT) REPORT[name].add(handsPathOf(p) ?? String(p));
|
|
100
|
+
};
|
|
101
|
+
var legacyMachine = (s) => s === DRAFT_STATUS_V1;
|
|
102
|
+
function legacyHuman(p, s) {
|
|
103
|
+
if (typeof s !== "string") return false;
|
|
104
|
+
const section = sectionOfPath(p);
|
|
105
|
+
return (section ? CONFIRMED_STATUSES_V1[section] : CONFIRMED_STATUSES_ANY_V1).includes(s);
|
|
106
|
+
}
|
|
107
|
+
function machineOwned(p, status) {
|
|
108
|
+
const s = checked(status);
|
|
109
|
+
const before = legacyMachine(s);
|
|
110
|
+
if (!HANDS) return before;
|
|
111
|
+
const locked = lockIn(HANDS, p);
|
|
112
|
+
const after = (before || noStatus(s)) && !locked;
|
|
113
|
+
if (before && locked) note("draft_lock", p);
|
|
114
|
+
if (before && !after) note("own_blocked", p);
|
|
115
|
+
if (!before && after) note("own_opened", p);
|
|
116
|
+
return HANDS.state === "on" ? after : before;
|
|
117
|
+
}
|
|
118
|
+
function humanOwned(p, status) {
|
|
119
|
+
const s = checked(status);
|
|
120
|
+
const before = legacyHuman(p, s);
|
|
121
|
+
if (!HANDS || !noStatus(s)) return before;
|
|
122
|
+
const after = touchedIn(HANDS, p);
|
|
123
|
+
if (after) note("human_touched", p);
|
|
124
|
+
return HANDS.state === "on" ? after : before;
|
|
125
|
+
}
|
|
126
|
+
var STATUS_VIEW = Object.freeze({ humanOwned, machineOwned });
|
|
127
|
+
|
|
128
|
+
// engine-src/supersedes-index.mjs
|
|
129
|
+
var DECISIONS_ANCHOR = "Memory/Decisions/records/";
|
|
130
|
+
function decisionKeyOf(ref) {
|
|
131
|
+
return import_node_path.default.basename(String(ref ?? "").trim().replace(/^decision:/, ""), ".md");
|
|
132
|
+
}
|
|
133
|
+
function decisionDateOf(date, id) {
|
|
134
|
+
const raw = String(date ?? "").trim();
|
|
135
|
+
const ymd = raw.match(/^(\d{4})-?(\d{2})-?(\d{2})/) || decisionKeyOf(id).match(/^(\d{4})(\d{2})(\d{2})/);
|
|
136
|
+
return ymd ? `${ymd[1]}-${ymd[2]}-${ymd[3]}` : "";
|
|
137
|
+
}
|
|
138
|
+
var normalize = (d) => {
|
|
139
|
+
if (!d || typeof d !== "object") return null;
|
|
140
|
+
const id = String(d.id ?? "").trim();
|
|
141
|
+
if (!id) return null;
|
|
142
|
+
return {
|
|
143
|
+
id,
|
|
144
|
+
key: decisionKeyOf(id),
|
|
145
|
+
date: decisionDateOf(d.date, id),
|
|
146
|
+
status: typeof d.status === "string" ? d.status.trim() : "",
|
|
147
|
+
// 口(`confirmed.mjs`)へ渡すだけ(逆引きの出力には載せない・tools の写しの契約は変わらない)
|
|
148
|
+
path: typeof d.path === "string" && d.path.includes("Memory/Decisions/") ? d.path : DECISIONS_ANCHOR,
|
|
149
|
+
supersedes: (Array.isArray(d.supersedes) ? d.supersedes : []).map(decisionKeyOf).filter(Boolean)
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
var newestFirst = (a, b) => {
|
|
153
|
+
if (a.date !== b.date) {
|
|
154
|
+
if (!a.date) return 1;
|
|
155
|
+
if (!b.date) return -1;
|
|
156
|
+
return a.date < b.date ? 1 : -1;
|
|
157
|
+
}
|
|
158
|
+
return a.id < b.id ? 1 : a.id > b.id ? -1 : 0;
|
|
159
|
+
};
|
|
160
|
+
function supersedesIndex(decisions, { view: _view = STATUS_VIEW } = {}) {
|
|
161
|
+
const list = [...decisions instanceof Map ? decisions.values() : decisions || []].map(normalize).filter(Boolean);
|
|
162
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
163
|
+
for (const d of list) if (!byKey.has(d.key)) byKey.set(d.key, d);
|
|
164
|
+
const out = /* @__PURE__ */ new Map();
|
|
165
|
+
for (const d of list) {
|
|
166
|
+
for (const target of new Set(d.supersedes)) {
|
|
167
|
+
const old = byKey.get(target);
|
|
168
|
+
if (!old || old.key === d.key) continue;
|
|
169
|
+
if (d.date && old.date && d.date < old.date) continue;
|
|
170
|
+
const entry = out.get(old.key) || { id: old.id, by: [], retired: false };
|
|
171
|
+
if (entry.by.some((x) => decisionKeyOf(x.id) === d.key)) continue;
|
|
172
|
+
entry.by.push({ id: d.id, date: d.date, status: d.status, confirmed: true });
|
|
173
|
+
entry.retired = true;
|
|
174
|
+
out.set(old.key, entry);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
for (const entry of out.values()) entry.by.sort(newestFirst);
|
|
178
|
+
return out;
|
|
179
|
+
}
|
|
180
|
+
function supersedesOf(index, id) {
|
|
181
|
+
return index.get(decisionKeyOf(id)) || { id: String(id ?? ""), by: [], retired: false };
|
|
182
|
+
}
|
|
183
|
+
function retiredIdsOf(index) {
|
|
184
|
+
return new Set([...index.values()].filter((e) => e.retired).map((e) => e.id));
|
|
185
|
+
}
|
|
186
|
+
function splitSupersededBy(entry) {
|
|
187
|
+
const by = entry && Array.isArray(entry.by) ? entry.by : [];
|
|
188
|
+
return {
|
|
189
|
+
confirmed: by.filter((x) => x.confirmed).map((x) => x.id),
|
|
190
|
+
unconfirmed: by.filter((x) => !x.confirmed).map((x) => x.id)
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function supersedesIndexStateOf() {
|
|
194
|
+
return "on";
|
|
195
|
+
}
|
|
196
|
+
function legacySupersedesIndex(records) {
|
|
197
|
+
const out = /* @__PURE__ */ new Map();
|
|
198
|
+
for (const r of records || []) {
|
|
199
|
+
if (!r) continue;
|
|
200
|
+
for (const target of Array.isArray(r.supersedes) ? r.supersedes : []) {
|
|
201
|
+
out.set(target, [...out.get(target) || [], r.id].filter(Boolean));
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return out;
|
|
205
|
+
}
|
|
206
|
+
function legacySupersededBy(index, id) {
|
|
207
|
+
return [...new Set(id ? index.get(id) || [] : [])].sort();
|
|
208
|
+
}
|
|
209
|
+
function legacyRetiredTargetsOf(records) {
|
|
210
|
+
const out = /* @__PURE__ */ new Set();
|
|
211
|
+
for (const target of legacySupersedesIndex(records).keys()) {
|
|
212
|
+
const t = String(target ?? "").trim();
|
|
213
|
+
if (t) out.add(t);
|
|
214
|
+
}
|
|
215
|
+
return out;
|
|
216
|
+
}
|
|
217
|
+
var SHADOW_SAMPLE_IDS = 5;
|
|
218
|
+
function compareSupersedes(decisions) {
|
|
219
|
+
const list = [...decisions || []].filter((d) => d && String(d.id ?? "").trim());
|
|
220
|
+
const ids = new Set(list.map((d) => String(d.id).trim()));
|
|
221
|
+
const legacyIndex = legacySupersedesIndex(list);
|
|
222
|
+
const legacy = new Set([...ids].filter((id) => legacySupersededBy(legacyIndex, id).length));
|
|
223
|
+
const next = retiredIdsOf(supersedesIndex(list));
|
|
224
|
+
return {
|
|
225
|
+
legacyRetired: legacy.size,
|
|
226
|
+
nextRetired: next.size,
|
|
227
|
+
revived: [...legacy].filter((id) => !next.has(id)).sort(),
|
|
228
|
+
newlyRetired: [...next].filter((id) => !legacy.has(id)).sort()
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function supersedesShadowSummaryLines({ state, diff, labelChanges = 0, freshnessRows = null }) {
|
|
232
|
+
if (state !== "shadow" || !diff) return [];
|
|
233
|
+
const sample = (ids) => ids.slice(0, SHADOW_SAMPLE_IDS).map((id) => `\`${id}\``).join("\u30FB") + (ids.length > SHADOW_SAMPLE_IDS ? ` \u307B\u304B ${ids.length - SHADOW_SAMPLE_IDS} \u4EF6` : "");
|
|
234
|
+
return [
|
|
235
|
+
`- \u7F6E\u304D\u63DB\u3048\u306E\u9006\u5F15\u304D\uFF08\u6813 shadow\u30FB\u4ECA\u307E\u3067\u306E\u898F\u5247\u3067\u8AAD\u3093\u3067\u3044\u307E\u3059\uFF09: \u7F6E\u304D\u63DB\u3048\u6E08\u307F\u306E\u6C7A\u5B9A \u4ECA **${diff.legacyRetired}** \u4EF6 \u2192 \u65B0\u3057\u3044\u898F\u5247 **${diff.nextRetired}** \u4EF6`,
|
|
236
|
+
` - \u4EBA\u306E\u624B\u306E\u3042\u308B\u53E4\u3044\u6C7A\u5B9A\u3067\u3001\u7F6E\u304D\u63DB\u3048\u3092\u5019\u88DC\u306B\u7559\u3081\u305F\u6C7A\u5B9A\uFF08\u65B0\u3057\u3044\u898F\u5247\u3067\u306F\u6709\u52B9\u306B\u623B\u308B\uFF09 **${diff.revived.length}** \u4EF6${diff.revived.length ? `: ${sample(diff.revived)}` : ""}`,
|
|
237
|
+
...diff.newlyRetired.length ? [` - \u65B0\u3057\u3044\u898F\u5247\u3067\u3060\u3051\u7F6E\u304D\u63DB\u3048\u6E08\u307F\u306B\u306A\u308B\u6C7A\u5B9A ${diff.newlyRetired.length} \u4EF6: ${sample(diff.newlyRetired)}`] : [],
|
|
238
|
+
` - \u62BD\u51FA\u306B\u6E21\u3059\u65E2\u5B58\u306E\u6C7A\u5B9A\u306E\u4E00\u89A7\u3067\u672D\u304C\u5909\u308F\u308B\u884C **${labelChanges}** \u4EF6`,
|
|
239
|
+
` - \u9BAE\u5EA6\u306E\u5E33\u7C3F\u3067\u5909\u308F\u308B\u884C ${freshnessRows === null ? "\uFF08\u6570\u3048\u3066\u3044\u307E\u305B\u3093\uFF09" : `**${freshnessRows}** \u4EF6`}`
|
|
240
|
+
];
|
|
241
|
+
}
|
|
242
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
243
|
+
0 && (module.exports = {
|
|
244
|
+
SHADOW_SAMPLE_IDS,
|
|
245
|
+
compareSupersedes,
|
|
246
|
+
decisionDateOf,
|
|
247
|
+
decisionKeyOf,
|
|
248
|
+
legacyRetiredTargetsOf,
|
|
249
|
+
legacySupersededBy,
|
|
250
|
+
legacySupersedesIndex,
|
|
251
|
+
retiredIdsOf,
|
|
252
|
+
splitSupersededBy,
|
|
253
|
+
supersedesIndex,
|
|
254
|
+
supersedesIndexStateOf,
|
|
255
|
+
supersedesOf,
|
|
256
|
+
supersedesShadowSummaryLines
|
|
257
|
+
});
|
|
@@ -87,6 +87,10 @@ function googleConfirmPageJs() {
|
|
|
87
87
|
var statusEl = $("gc-status");
|
|
88
88
|
var goBtn = $("gc-go");
|
|
89
89
|
var closeBtn = $("gc-close");
|
|
90
|
+
var busyEl = $("gc-busy");
|
|
91
|
+
var busyTextEl = $("gc-busy-text");
|
|
92
|
+
var busyNoteEl = $("gc-busy-note");
|
|
93
|
+
var pageEl = $("gc-page");
|
|
90
94
|
|
|
91
95
|
var ctx = null;
|
|
92
96
|
var flow = null;
|
|
@@ -98,6 +102,20 @@ function googleConfirmPageJs() {
|
|
|
98
102
|
statusEl.textContent = text || "";
|
|
99
103
|
statusEl.className = "gc-status" + (cls ? " " + cls : "");
|
|
100
104
|
}
|
|
105
|
+
/** 窓の中全体を「読み込み中」で覆う(保存が終わるまで他の操作をしかけないため)。覆いの間は後ろの画面を操作できない */
|
|
106
|
+
function showBusy(text, note) {
|
|
107
|
+
busyTextEl.textContent = text;
|
|
108
|
+
busyNoteEl.textContent = note || "";
|
|
109
|
+
busyNoteEl.hidden = !note;
|
|
110
|
+
busyEl.hidden = false;
|
|
111
|
+
pageEl.setAttribute("inert", "");
|
|
112
|
+
pageEl.setAttribute("aria-hidden", "true");
|
|
113
|
+
}
|
|
114
|
+
function hideBusy() {
|
|
115
|
+
busyEl.hidden = true;
|
|
116
|
+
pageEl.removeAttribute("inert");
|
|
117
|
+
pageEl.removeAttribute("aria-hidden");
|
|
118
|
+
}
|
|
101
119
|
function b64urlEncode(text) {
|
|
102
120
|
return btoa(text).replace(/\\+/g, "-").replace(/\\//g, "_").replace(/=+$/, "");
|
|
103
121
|
}
|
|
@@ -121,6 +139,7 @@ function googleConfirmPageJs() {
|
|
|
121
139
|
function succeed(message, extra) {
|
|
122
140
|
finished = true;
|
|
123
141
|
busy = false;
|
|
142
|
+
hideBusy();
|
|
124
143
|
goBtn.hidden = true;
|
|
125
144
|
closeBtn.hidden = false;
|
|
126
145
|
setStatus("✓ " + message + "。このウィンドウは閉じて構いません", "is-ok");
|
|
@@ -130,6 +149,7 @@ function googleConfirmPageJs() {
|
|
|
130
149
|
/** 失敗: 理由を出し、押し直せるように戻す(別のアカウントでやり直す人のため)。本体にも理由を渡す */
|
|
131
150
|
function retryable(message, extra) {
|
|
132
151
|
busy = false;
|
|
152
|
+
hideBusy();
|
|
133
153
|
goBtn.hidden = false;
|
|
134
154
|
goBtn.disabled = false;
|
|
135
155
|
goBtn.textContent = "もう一度 Google で確認する";
|
|
@@ -140,6 +160,7 @@ function googleConfirmPageJs() {
|
|
|
140
160
|
/** 続けられない(本体が見つからない・結果が読めない): 理由と[閉じる]だけ */
|
|
141
161
|
function dead(message) {
|
|
142
162
|
busy = false;
|
|
163
|
+
hideBusy();
|
|
143
164
|
finished = true;
|
|
144
165
|
goBtn.hidden = true;
|
|
145
166
|
closeBtn.hidden = false;
|
|
@@ -161,6 +182,10 @@ function googleConfirmPageJs() {
|
|
|
161
182
|
});
|
|
162
183
|
});
|
|
163
184
|
}
|
|
185
|
+
/** 設定の表の案件の追加の意図(契約 §3。旧キー op を持たない)。保存の門(本人の Google)はトークンを添えて通る */
|
|
186
|
+
function intentBody(kind, target) {
|
|
187
|
+
return { v: 1, kind: kind, action: "add", target: target, baseRev: ctx.intent.baseRev, req: ctx.intent.req };
|
|
188
|
+
}
|
|
164
189
|
function loadInfo() {
|
|
165
190
|
var intake = ctx.intake;
|
|
166
191
|
var url = intake.url + (intake.url.indexOf("?") === -1 ? "?" : "&") + "op=google-confirm-info&t=" + encodeURIComponent(intake.token);
|
|
@@ -213,7 +238,7 @@ function googleConfirmPageJs() {
|
|
|
213
238
|
var g = window.google.picker;
|
|
214
239
|
var mine = new g.DocsView(g.ViewId.FOLDERS).setIncludeFolders(true).setSelectFolderEnabled(true).setMimeTypes("application/vnd.google-apps.folder");
|
|
215
240
|
var shared = new g.DocsView(g.ViewId.FOLDERS).setIncludeFolders(true).setSelectFolderEnabled(true).setEnableDrives(true).setMimeTypes("application/vnd.google-apps.folder");
|
|
216
|
-
new g.PickerBuilder()
|
|
241
|
+
var picker = new g.PickerBuilder()
|
|
217
242
|
.setAppId(info.projectNumber)
|
|
218
243
|
.setDeveloperKey(info.apiKey)
|
|
219
244
|
.setOAuthToken(accessToken)
|
|
@@ -224,8 +249,10 @@ function googleConfirmPageJs() {
|
|
|
224
249
|
if (data.action === g.Action.PICKED && data.docs && data.docs[0]) resolve(data.docs[0]);
|
|
225
250
|
else if (data.action === g.Action.CANCEL) resolve(null);
|
|
226
251
|
})
|
|
227
|
-
.build()
|
|
228
|
-
|
|
252
|
+
.build();
|
|
253
|
+
// Picker を操作できるように、出す前に覆いを外す(選ぶ・やめるのあとは、呼び出し側が覆いを戻すか結果を出す)
|
|
254
|
+
hideBusy();
|
|
255
|
+
picker.setVisible(true);
|
|
229
256
|
});
|
|
230
257
|
});
|
|
231
258
|
}
|
|
@@ -249,6 +276,7 @@ function googleConfirmPageJs() {
|
|
|
249
276
|
goBtn.hidden = true;
|
|
250
277
|
closeBtn.hidden = true;
|
|
251
278
|
setStatus("Google の画面へ移動しています…", "");
|
|
279
|
+
showBusy("Google の画面へ移動しています…");
|
|
252
280
|
var info = null;
|
|
253
281
|
loadInfo()
|
|
254
282
|
.then(function (i) {
|
|
@@ -275,7 +303,9 @@ function googleConfirmPageJs() {
|
|
|
275
303
|
busy = true;
|
|
276
304
|
goBtn.hidden = true;
|
|
277
305
|
closeBtn.hidden = true;
|
|
306
|
+
var isDrive = ctx.kind === "drive";
|
|
278
307
|
setStatus("確認しています…", "");
|
|
308
|
+
showBusy(isDrive ? "Google のフォルダを開いています…" : "確認しています…");
|
|
279
309
|
var tokens = null;
|
|
280
310
|
var info = null;
|
|
281
311
|
Promise.resolve()
|
|
@@ -297,13 +327,15 @@ function googleConfirmPageJs() {
|
|
|
297
327
|
var body;
|
|
298
328
|
if (ctx.kind === "drive") {
|
|
299
329
|
if (!picked) throw { message: "フォルダを選ばずに閉じられました。もう一度押してください" };
|
|
330
|
+
if (ctx.mode === "confirm") showBusy("確認しています…");
|
|
331
|
+
else showBusy("保存しています…", "終わるまでこの窓を閉じずにお待ちください");
|
|
300
332
|
body = ctx.mode === "confirm"
|
|
301
333
|
? { op: "confirm-drive-folder", id: ctx.id, folderId: picked.id }
|
|
302
|
-
: { op: "add-drive-folder", folderId: picked.id };
|
|
334
|
+
: ctx.intent ? intentBody("drive", { folderId: picked.id }) : { op: "add-drive-folder", folderId: picked.id };
|
|
303
335
|
} else {
|
|
304
336
|
body = ctx.mode === "confirm"
|
|
305
337
|
? { op: "confirm-google-chat-space", ref: ctx.id }
|
|
306
|
-
: { op: "add-google-chat-space", url: ctx.url };
|
|
338
|
+
: ctx.intent ? intentBody("google-chat", { url: ctx.url }) : { op: "add-google-chat-space", url: ctx.url };
|
|
307
339
|
}
|
|
308
340
|
return callIntake(Object.assign(body, tokens));
|
|
309
341
|
})
|
|
@@ -322,13 +354,20 @@ function googleConfirmPageJs() {
|
|
|
322
354
|
}
|
|
323
355
|
|
|
324
356
|
/** 本体からの指示(opener か BroadcastChannel)。flow が合うものだけを 1 回だけ受ける */
|
|
357
|
+
/** 設定の表の案件の追加で本体が渡す {baseRev, req}。形が合わなければ null(旧キーの要求に倒す) */
|
|
358
|
+
function intentOf(i) {
|
|
359
|
+
if (!i || typeof i !== "object") return null;
|
|
360
|
+
if (typeof i.baseRev !== "number" || !isFinite(i.baseRev) || i.baseRev < 0 || Math.floor(i.baseRev) !== i.baseRev) return null;
|
|
361
|
+
if (typeof i.req !== "string" || !/^[A-Za-z0-9_-]{8,64}$/.test(i.req)) return null;
|
|
362
|
+
return { baseRev: i.baseRev, req: i.req };
|
|
363
|
+
}
|
|
325
364
|
function acceptStart(d) {
|
|
326
365
|
if (!d || d.type !== MSG.start || ctx) return;
|
|
327
366
|
if (typeof d.flow !== "string" || !FLOW_RE.test(d.flow) || (flow && d.flow !== flow)) return;
|
|
328
367
|
if (!d.intake || typeof d.intake.url !== "string" || typeof d.intake.token !== "string") return;
|
|
329
368
|
if (d.kind !== "drive" && d.kind !== "google-chat") return;
|
|
330
369
|
flow = d.flow;
|
|
331
|
-
ctx = { intake: d.intake, ticket: typeof d.ticket === "string" ? d.ticket : null, kind: d.kind, mode: d.mode === "confirm" ? "confirm" : "add", url: typeof d.url === "string" ? d.url : "", id: typeof d.id === "string" ? d.id : "" };
|
|
370
|
+
ctx = { intake: d.intake, ticket: typeof d.ticket === "string" ? d.ticket : null, kind: d.kind, mode: d.mode === "confirm" ? "confirm" : "add", url: typeof d.url === "string" ? d.url : "", id: typeof d.id === "string" ? d.id : "", intent: intentOf(d.intent) };
|
|
332
371
|
var isDrive = ctx.kind === "drive";
|
|
333
372
|
var what = isDrive ? "Drive のフォルダ" : "Google Chat のスペース";
|
|
334
373
|
titleEl.textContent = (ctx.mode === "confirm" ? what + "を確認する" : what + "を追加する");
|
|
@@ -365,6 +404,7 @@ function googleConfirmPageJs() {
|
|
|
365
404
|
flow = returned.flow;
|
|
366
405
|
openChannel();
|
|
367
406
|
setStatus("確認の続きを準備しています…", "");
|
|
407
|
+
showBusy("確認しています…");
|
|
368
408
|
var asked = 0;
|
|
369
409
|
var timer = setInterval(function () {
|
|
370
410
|
if (ctx) { clearInterval(timer); return; }
|
|
@@ -398,7 +438,7 @@ function renderGoogleConfirmPage(assets) {
|
|
|
398
438
|
<link rel="stylesheet" href="${esc(assets.css)}" />
|
|
399
439
|
</head>
|
|
400
440
|
<body class="gc-body">
|
|
401
|
-
<main class="gc-page">
|
|
441
|
+
<main id="gc-page" class="gc-page">
|
|
402
442
|
<h1 id="gc-title" class="gc-title">Google で確認</h1>
|
|
403
443
|
<p id="gc-lead" class="gc-lead"></p>
|
|
404
444
|
<p id="gc-status" class="gc-status" role="status" aria-live="polite"></p>
|
|
@@ -407,6 +447,13 @@ function renderGoogleConfirmPage(assets) {
|
|
|
407
447
|
<button id="gc-close" class="ds-toggle-btn" type="button" hidden>閉じる</button>
|
|
408
448
|
</div>
|
|
409
449
|
</main>
|
|
450
|
+
<div id="gc-busy" class="gc-busy" role="status" aria-live="polite" hidden>
|
|
451
|
+
<div class="gc-busy-box">
|
|
452
|
+
<span class="gc-spinner" aria-hidden="true"></span>
|
|
453
|
+
<p id="gc-busy-text" class="gc-busy-text"></p>
|
|
454
|
+
<p id="gc-busy-note" class="gc-busy-note" hidden></p>
|
|
455
|
+
</div>
|
|
456
|
+
</div>
|
|
410
457
|
<script src="${esc(assets.js)}"></script>
|
|
411
458
|
</body>
|
|
412
459
|
</html>`;
|
package/dist/ledger-dir.js
CHANGED
|
@@ -10,6 +10,7 @@ exports.ledgerDirOf = ledgerDirOf;
|
|
|
10
10
|
* ビューアが読む帳簿(9 本)の置き場(cortex-engine #1094 便 3-11 の tools(T1))。根拠の台帳(便 B3)は案件リポに置くので、ここを通さず `defaultLedgerDir` から読む(`memory-evidence.ts`)。
|
|
11
11
|
*
|
|
12
12
|
* 既定は `<リポジトリルート>/.cortex`(今までと同じ)。`--ledger-dir` で別のフォルダを指せる。
|
|
13
|
+
* 組み直した案件(木に `Memory/Home.md`)は帳簿をここから読まず、記憶側の画面用ファイルだけで組む(`view-dir.ts` の `planViewsV2`・cortex-engine #1911 便 DC-2f)。
|
|
13
14
|
* ビューアは保管庫(S3)も栓も知らない(AWS SDK を足さない)。どこから持ってくるかは呼び出し側(workflow)の仕事で、
|
|
14
15
|
* ここは「そのフォルダの下の `<名前>.json` を読む」だけ。
|
|
15
16
|
*
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MEMORY_DIR_ALT = exports.NEXT_MEMORY_DIR = exports.LEGACY_MEMORY_DIR = void 0;
|
|
7
|
+
exports.memoryDirOfTree = memoryDirOfTree;
|
|
8
|
+
exports.memoryDirOfRoot = memoryDirOfRoot;
|
|
9
|
+
exports.promptInMemoryDir = promptInMemoryDir;
|
|
10
|
+
/**
|
|
11
|
+
* 記憶の置き場の名前(案件リポの直下のフォルダ)の見分け(cortex-engine #1911 便 T-12・設計 §1 T-2 の K4)。
|
|
12
|
+
*
|
|
13
|
+
* ビューアは全案件で 1 つの版しか動かせないので、置き場の名前が違う案件が混ざる間は**木の 1 つの事実**で決める:
|
|
14
|
+
* 木に `Memory/Home.md`(`REBUILT_MARKER`)があれば `Memory`(組み直した案件)、無ければ `Cortex`(今までの案件)。
|
|
15
|
+
* 🔴 今までの案件(`Cortex`)の出力は 1 バイトも変えない(`memoryDir` はキーごと出さない・文字列は元のまま)。
|
|
16
|
+
* 旧名を持つのは tools では `lambda/shared/memory-bridge.mjs` とここだけ(ビューアは lambda を import しないので 1 か所だけ写す)。
|
|
17
|
+
*/
|
|
18
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
19
|
+
const config_mode_1 = require("./config-mode");
|
|
20
|
+
exports.LEGACY_MEMORY_DIR = "Cortex";
|
|
21
|
+
exports.NEXT_MEMORY_DIR = "Memory";
|
|
22
|
+
/** 記録・Home のパスの先頭にどちらの置き場が来てもよい形(形だけを見る正規表現の部品。`Cortex` と `Memory` の 2 つだけ) */
|
|
23
|
+
exports.MEMORY_DIR_ALT = "(?:Cortex|Memory)";
|
|
24
|
+
/** リポの根(作業ディレクトリ)の木から決める。印は設定の置き場のヒントと同じ 1 つ(`config-mode.ts` の `Memory/Home.md`・通常のファイルのとき) */
|
|
25
|
+
async function memoryDirOfTree(repoRoot) {
|
|
26
|
+
return (await (0, config_mode_1.configModeHint)(repoRoot)) === "table" ? exports.NEXT_MEMORY_DIR : exports.LEGACY_MEMORY_DIR;
|
|
27
|
+
}
|
|
28
|
+
/** 知識の根(`.../Cortex` か `.../Memory`)の名前から。それ以外(旧い Decisions 単独の構成)は `Cortex` */
|
|
29
|
+
function memoryDirOfRoot(knowledgeRoot) {
|
|
30
|
+
return knowledgeRoot !== null && node_path_1.default.basename(knowledgeRoot) === exports.NEXT_MEMORY_DIR ? exports.NEXT_MEMORY_DIR : exports.LEGACY_MEMORY_DIR;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 利用者に渡す起動文の中の置き場の名前を、その案件の名前に替える。`Cortex` のときは**そのまま返す**(1 バイトも変えない)。
|
|
34
|
+
* 替えるのは置き場の中の既知のもの(区画・Home・設定 3 種)だけ——製品名の `Cortex` や `Cortex/Runner` のような別物には触らない。
|
|
35
|
+
*/
|
|
36
|
+
function promptInMemoryDir(text, dir) {
|
|
37
|
+
if (dir === exports.LEGACY_MEMORY_DIR)
|
|
38
|
+
return text;
|
|
39
|
+
return text.replace(/\bCortex\/(?=(?:Decisions|Glossary|Members|Rules|Story|Home\.md|sources\.json|notify\.json|viewer-config\.json)\b)/g, `${dir}/`);
|
|
40
|
+
}
|
package/dist/rederivation.js
CHANGED
|
@@ -24,6 +24,8 @@ exports.orderByActivity = orderByActivity;
|
|
|
24
24
|
* | `.cortex/gold-activity.json` | 「最後に見た日」と触れた日の列(+観測の到達点 `cursor`) | 夜間(追記・剪定つき) |
|
|
25
25
|
* | `.cortex/gold-term-strength.json` | 用語ごとの強さ(場面の数・使った人の数・資料の下地)と栓の状態 `state`(#790・engine #727) | 夜間(全置換) |
|
|
26
26
|
*
|
|
27
|
+
* 確認の帳簿と再導出の帳簿は**組み直していない案件(v1)だけ**読む(組み直した案件は書き手が無い・cortex-engine #1911 便 DC-2f・`opts.v2`)。
|
|
28
|
+
*
|
|
27
29
|
* 形の正本は cortex-engine `scripts/rederive/ledgers.mjs` と `docs/cortex-derived-files.md`
|
|
28
30
|
* (強さの帳簿は `scripts/gold/term-gate.mjs` の `strengthLedgerOf`)。
|
|
29
31
|
*
|
|
@@ -48,7 +50,7 @@ const ledger_dir_1 = require("./ledger-dir");
|
|
|
48
50
|
/** 帳簿の版(違ったら空として扱う・engine `LEDGER_VERSION`) */
|
|
49
51
|
exports.LEDGER_VERSION = 1;
|
|
50
52
|
/** 並びを変える区画。**用語集だけ**(関係者の並びは関与の帳簿で `engagement.ts` が決める・便 14b) */
|
|
51
|
-
const ORDER_SECTION_RE = /^Cortex\/Glossary\/records\/[^/]+\.md$/;
|
|
53
|
+
const ORDER_SECTION_RE = /^(?:Cortex|Memory)\/Glossary\/records\/[^/]+\.md$/;
|
|
52
54
|
/** ACT-R base-level の減衰(#432 裁定 5-5: d = 0.5) */
|
|
53
55
|
const ACTR_DECAY = 0.5;
|
|
54
56
|
/**
|
|
@@ -122,13 +124,8 @@ async function readOne(ledgerDir, file, then = "帯と並びは出さずに続
|
|
|
122
124
|
return parsed;
|
|
123
125
|
}
|
|
124
126
|
const asRecord = (v) => v != null && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
125
|
-
/**
|
|
126
|
-
|
|
127
|
-
* engine は単独で版を上げるので、画面が知らないキーが必ず先に入る。
|
|
128
|
-
*/
|
|
129
|
-
async function readRederivationLedgers(repoRoot, ledgerDirArg) {
|
|
130
|
-
const ledgerDir = (0, ledger_dir_1.ledgerDirOf)(repoRoot, ledgerDirArg);
|
|
131
|
-
const out = (0, exports.emptyLedgers)();
|
|
127
|
+
/** 確認の帳簿(`gold-confirmation`)と再導出の帳簿(`gold-rederivation`)を読む(v1 の案件だけ・`readRederivationLedgers`) */
|
|
128
|
+
async function readConfirmationAndRederivation(ledgerDir, out) {
|
|
132
129
|
const conf = await readOne(ledgerDir, "gold-confirmation.json");
|
|
133
130
|
const records = asRecord(conf?.records);
|
|
134
131
|
if (records) {
|
|
@@ -194,6 +191,18 @@ async function readRederivationLedgers(repoRoot, ledgerDirArg) {
|
|
|
194
191
|
}
|
|
195
192
|
}
|
|
196
193
|
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* 3 帳簿を読む。**フィールドは明示で列挙し、素通しはしない**(知らない欄を画面へ素通しにしない流儀)——
|
|
197
|
+
* engine は単独で版を上げるので、画面が知らないキーが必ず先に入る。
|
|
198
|
+
*/
|
|
199
|
+
async function readRederivationLedgers(repoRoot, ledgerDirArg, opts = {}) {
|
|
200
|
+
const ledgerDir = (0, ledger_dir_1.ledgerDirOf)(repoRoot, ledgerDirArg);
|
|
201
|
+
const out = (0, exports.emptyLedgers)();
|
|
202
|
+
// 🔴 確認の帳簿と再導出の帳簿は**組み直していない案件(v1)だけ**読む(v1 の画面の再導出の帯・確認の版に戻すが今も使う)。
|
|
203
|
+
// 組み直した案件(v2・木に `Memory/Home.md`)では書き手が無い(便 V1N)ので読まない(cortex-engine #1911 便 DC-2f・設計書 7 章 K32・消す日は全案件 v2)
|
|
204
|
+
if (opts.v2 !== true)
|
|
205
|
+
await readConfirmationAndRederivation(ledgerDir, out);
|
|
197
206
|
const act = await readOne(ledgerDir, "gold-activity.json");
|
|
198
207
|
const actSections = asRecord(act?.sections);
|
|
199
208
|
if (actSections) {
|