@unson/brainbase-mcp 0.32.0 → 0.34.0

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.
@@ -0,0 +1,6 @@
1
+ export declare const ONTOLOGY_PUBLICATION_RECEIPT_SCHEMA_VERSION = "1.0.0";
2
+ export declare function sha256(bytes: any): string;
3
+ export declare function canonicalize(value: any): any;
4
+ export declare function canonicalJson(value: any): string;
5
+ export declare function publicationReceiptContractErrors(receipt: any): string[];
6
+ export declare function verifyPublicationReceipt(receipt: any, publicKeyPem: any): boolean;
@@ -0,0 +1,44 @@
1
+ // Moved from brainbase-unson server/services/ontology-publication.js without changing behavior.
2
+ // Only type annotations were added; values stay open JSON objects as in the original.
3
+ /* eslint-disable @typescript-eslint/no-explicit-any */
4
+ import { createHash, verify } from 'node:crypto';
5
+ export const ONTOLOGY_PUBLICATION_RECEIPT_SCHEMA_VERSION = '1.0.0';
6
+ export function sha256(bytes) {
7
+ return createHash('sha256').update(bytes).digest('hex');
8
+ }
9
+ export function canonicalize(value) {
10
+ if (Array.isArray(value))
11
+ return value.map(canonicalize);
12
+ if (value && typeof value === 'object') {
13
+ return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonicalize(value[key])]));
14
+ }
15
+ return value;
16
+ }
17
+ export function canonicalJson(value) {
18
+ return JSON.stringify(canonicalize(value));
19
+ }
20
+ export function publicationReceiptContractErrors(receipt) {
21
+ const errors = [];
22
+ if (receipt?.payload?.schema_version !== ONTOLOGY_PUBLICATION_RECEIPT_SCHEMA_VERSION) {
23
+ errors.push('schema_version');
24
+ }
25
+ if (typeof receipt?.payload?.actor_entity_id !== 'string' || !receipt.payload.actor_entity_id.trim()) {
26
+ errors.push('actor_entity_id');
27
+ }
28
+ const issuedAt = receipt?.payload?.issued_at;
29
+ if (typeof issuedAt !== 'string'
30
+ || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(issuedAt)
31
+ || Number.isNaN(Date.parse(issuedAt))
32
+ || new Date(issuedAt).toISOString() !== issuedAt) {
33
+ errors.push('issued_at');
34
+ }
35
+ return errors;
36
+ }
37
+ export function verifyPublicationReceipt(receipt, publicKeyPem) {
38
+ if (receipt?.signature_algorithm !== 'ed25519' || !receipt?.payload || !receipt?.signature || !receipt?.key_id) {
39
+ return false;
40
+ }
41
+ if (publicationReceiptContractErrors(receipt).length)
42
+ return false;
43
+ return verify(null, Buffer.from(canonicalJson(receipt.payload)), publicKeyPem, Buffer.from(receipt.signature, 'base64'));
44
+ }
@@ -0,0 +1,32 @@
1
+ import { OntologyKernel } from './ontology-kernel.js';
2
+ export declare class OntologyRegistry {
3
+ [key: string]: any;
4
+ constructor({ rootDir, configDir, publicKeyPem }?: {
5
+ rootDir?: string | undefined;
6
+ configDir?: string | undefined;
7
+ publicKeyPem?: string | undefined;
8
+ });
9
+ hasCurrent(): boolean;
10
+ resolve({ version, asOf }?: any): {
11
+ kernel: OntologyKernel;
12
+ digest: string;
13
+ entry: any;
14
+ publicationVerification: {
15
+ status: string;
16
+ key_id: any;
17
+ signature_algorithm: any;
18
+ trust_source: string;
19
+ receipt_digest: any;
20
+ reason?: undefined;
21
+ } | {
22
+ status: string;
23
+ reason: any;
24
+ key_id?: undefined;
25
+ signature_algorithm?: undefined;
26
+ trust_source?: undefined;
27
+ receipt_digest?: undefined;
28
+ };
29
+ };
30
+ interpretHistory(snapshot?: any, { version, asOf }?: any): any;
31
+ unverifiedHistory(snapshot: any, asOf: any, reason: any): any;
32
+ }
@@ -0,0 +1,202 @@
1
+ // Moved from brainbase-unson server/services/ontology-registry.js without changing behavior.
2
+ // Only type annotations were added; values stay open JSON objects as in the original.
3
+ /* eslint-disable @typescript-eslint/no-explicit-any */
4
+ import { createHash } from 'node:crypto';
5
+ import { readFileSync } from 'node:fs';
6
+ import path from 'node:path';
7
+ import { OntologyError, OntologyKernel } from './ontology-kernel.js';
8
+ import { hasCompleteReceiptMetadata, hasReceiptMetadata, loadTrustedPublicKeys, verifyPublishedReceipt } from './ontology-release-trust.js';
9
+ function parseJson(bytes, label) {
10
+ try {
11
+ return JSON.parse(bytes.toString('utf8'));
12
+ }
13
+ catch (error) {
14
+ throw new OntologyError('ONTOLOGY_MANIFEST_INVALID', `Invalid JSON in ${label}`, {
15
+ cause: error.message
16
+ });
17
+ }
18
+ }
19
+ function parseTime(value, label) {
20
+ const timestamp = Date.parse(value);
21
+ if (!Number.isFinite(timestamp)) {
22
+ throw new OntologyError('ONTOLOGY_MANIFEST_INVALID', `Invalid ${label}: ${value}`);
23
+ }
24
+ return timestamp;
25
+ }
26
+ export class OntologyRegistry {
27
+ constructor({ rootDir = process.cwd(), configDir = 'config/ontology', publicKeyPem = process.env.ONTOLOGY_PUBLICATION_SIGNING_PUBLIC_KEY || '' } = {}) {
28
+ this.configDir = path.resolve(rootDir, configDir);
29
+ this.releasesDir = path.resolve(this.configDir, 'releases');
30
+ this.publicKeyPem = publicKeyPem;
31
+ try {
32
+ this.trustedPublicKeys = loadTrustedPublicKeys(this.configDir);
33
+ }
34
+ catch (error) {
35
+ throw new OntologyError('ONTOLOGY_MANIFEST_INVALID', error.message);
36
+ }
37
+ this.index = parseJson(readFileSync(path.join(this.configDir, 'index.json')), 'ontology index');
38
+ if (!Array.isArray(this.index.releases)) {
39
+ throw new OntologyError('ONTOLOGY_MANIFEST_INVALID', 'Ontology index releases must be an array');
40
+ }
41
+ }
42
+ hasCurrent() {
43
+ return typeof this.index.current === 'string' && this.index.current.length > 0;
44
+ }
45
+ resolve({ version, asOf } = {}) {
46
+ let entry;
47
+ if (version) {
48
+ entry = this.index.releases.find((release) => release.version === version);
49
+ }
50
+ else if (asOf) {
51
+ const target = parseTime(asOf, 'asOf');
52
+ entry = this.index.releases
53
+ .filter((release) => (hasCompleteReceiptMetadata(release) || release.version === this.index.current)
54
+ && parseTime(release.effective_at, 'release effective_at') <= target)
55
+ .sort((left, right) => parseTime(right.effective_at, 'release effective_at') - parseTime(left.effective_at, 'release effective_at'))[0];
56
+ }
57
+ else {
58
+ if (!this.hasCurrent()) {
59
+ throw new OntologyError('ONTOLOGY_CURRENT_UNAVAILABLE', 'No current ontology release has been published');
60
+ }
61
+ entry = this.index.releases.find((release) => release.version === this.index.current);
62
+ }
63
+ if (!entry) {
64
+ throw new OntologyError('ONTOLOGY_VERSION_UNKNOWN', `Ontology release was not found: ${version || asOf}`, {
65
+ version: version || null,
66
+ as_of: asOf || null
67
+ });
68
+ }
69
+ const releasePath = path.resolve(this.configDir, entry.path);
70
+ const relativePath = path.relative(this.releasesDir, releasePath);
71
+ if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
72
+ throw new OntologyError('ONTOLOGY_MANIFEST_INVALID', 'Ontology release path must stay inside releases/', {
73
+ path: entry.path
74
+ });
75
+ }
76
+ const bytes = readFileSync(releasePath);
77
+ const digest = createHash('sha256').update(bytes).digest('hex');
78
+ if (entry.content_digest_algorithm !== 'sha256' || digest !== entry.content_digest) {
79
+ throw new OntologyError('ONTOLOGY_DIGEST_MISMATCH', `Ontology release digest mismatch: ${entry.version}`, {
80
+ version: entry.version,
81
+ expected: entry.content_digest,
82
+ actual: digest
83
+ });
84
+ }
85
+ const manifest = parseJson(bytes, `ontology release ${entry.version}`);
86
+ if (manifest.version !== entry.version || manifest.effective_at !== entry.effective_at) {
87
+ throw new OntologyError('ONTOLOGY_MANIFEST_INVALID', 'Ontology index metadata does not match release manifest', {
88
+ index_version: entry.version,
89
+ manifest_version: manifest.version,
90
+ index_effective_at: entry.effective_at,
91
+ manifest_effective_at: manifest.effective_at
92
+ });
93
+ }
94
+ const receiptTrust = verifyPublishedReceipt({
95
+ configDir: this.configDir,
96
+ entry,
97
+ manifest,
98
+ publicKeyPem: this.publicKeyPem,
99
+ trustedPublicKeys: this.trustedPublicKeys
100
+ });
101
+ const claimsPublication = this.index.current === entry.version
102
+ || entry.status === 'retired'
103
+ || hasReceiptMetadata(entry);
104
+ if (claimsPublication && !receiptTrust.verified) {
105
+ throw new OntologyError('ONTOLOGY_PUBLICATION_UNVERIFIED', `Ontology publication receipt is not trusted: ${entry.version}`, {
106
+ http_status: 503,
107
+ version: entry.version,
108
+ reason: receiptTrust.reason,
109
+ ...receiptTrust.details
110
+ });
111
+ }
112
+ const effectiveStatus = receiptTrust.verified && this.index.current === entry.version
113
+ ? 'active'
114
+ : receiptTrust.verified && entry.status === 'retired'
115
+ ? 'retired'
116
+ : receiptTrust.verified
117
+ ? 'approved'
118
+ : 'proposed';
119
+ return {
120
+ kernel: new OntologyKernel({ manifest, status: effectiveStatus }),
121
+ digest,
122
+ entry: structuredClone(entry),
123
+ publicationVerification: receiptTrust.verified
124
+ ? {
125
+ status: 'verified',
126
+ key_id: receiptTrust.receipt.key_id,
127
+ signature_algorithm: receiptTrust.receipt.signature_algorithm,
128
+ trust_source: this.publicKeyPem ? 'environment_override' : 'git_trust_store',
129
+ receipt_digest: receiptTrust.receipt_digest
130
+ }
131
+ : { status: 'unverified', reason: receiptTrust.reason }
132
+ };
133
+ }
134
+ interpretHistory(snapshot = {}, { version, asOf } = {}) {
135
+ const recordedVersion = snapshot.ontology_version || null;
136
+ if (version && recordedVersion && version !== recordedVersion) {
137
+ throw new OntologyError('ONTOLOGY_HISTORY_VERSION_MISMATCH', 'Requested ontology version does not match the recorded fact version', {
138
+ requested_version: version,
139
+ recorded_version: recordedVersion
140
+ });
141
+ }
142
+ let release;
143
+ try {
144
+ if (version || recordedVersion) {
145
+ release = this.resolve({ version: version || recordedVersion });
146
+ }
147
+ else if (asOf) {
148
+ release = this.resolve({ asOf });
149
+ }
150
+ else {
151
+ return this.unverifiedHistory(snapshot, asOf, {
152
+ code: 'ONTOLOGY_HISTORY_VERSION_UNRESOLVED',
153
+ message: 'Historical interpretation requires a recorded ontology version or resolvable as-of time'
154
+ });
155
+ }
156
+ }
157
+ catch (error) {
158
+ if (!version && !recordedVersion && error instanceof OntologyError
159
+ && ['ONTOLOGY_VERSION_UNKNOWN', 'ONTOLOGY_CURRENT_UNAVAILABLE', 'ONTOLOGY_PUBLICATION_UNVERIFIED'].includes(error.code)) {
160
+ return this.unverifiedHistory(snapshot, asOf, {
161
+ code: error.code,
162
+ message: error.message
163
+ });
164
+ }
165
+ throw error;
166
+ }
167
+ if (release.kernel.status === 'proposed') {
168
+ return this.unverifiedHistory(snapshot, asOf, {
169
+ code: 'ONTOLOGY_PUBLICATION_UNVERIFIED',
170
+ message: `Ontology release has not been published: ${release.entry.version}`
171
+ });
172
+ }
173
+ const resolvedVersion = release.entry.version;
174
+ const mismatchedEvents = (snapshot.evolution_events || [])
175
+ .filter((event) => event.ontology_version && event.ontology_version !== resolvedVersion)
176
+ .map((event) => event.event_id);
177
+ if (mismatchedEvents.length) {
178
+ throw new OntologyError('ONTOLOGY_HISTORY_VERSION_MISMATCH', 'Evolution events must use the recorded fact ontology version', {
179
+ recorded_version: recordedVersion,
180
+ resolved_version: resolvedVersion,
181
+ event_ids: mismatchedEvents
182
+ });
183
+ }
184
+ return {
185
+ ...release.kernel.interpretHistory(snapshot, { asOf }),
186
+ recorded_ontology_version: recordedVersion,
187
+ resolved_ontology_version: resolvedVersion,
188
+ verification: 'verified'
189
+ };
190
+ }
191
+ unverifiedHistory(snapshot, asOf, reason) {
192
+ return {
193
+ ...structuredClone(snapshot),
194
+ ontology_version: null,
195
+ recorded_ontology_version: snapshot.ontology_version || null,
196
+ resolved_ontology_version: null,
197
+ interpretation_as_of: asOf || null,
198
+ verification: 'unverified',
199
+ unverified_reason: reason
200
+ };
201
+ }
202
+ }
@@ -0,0 +1,4 @@
1
+ export declare function hasReceiptMetadata(entry?: any): boolean;
2
+ export declare function hasCompleteReceiptMetadata(entry?: any): boolean;
3
+ export declare function loadTrustedPublicKeys(configDir: any): any;
4
+ export declare function verifyPublishedReceipt({ configDir, entry, manifest, publicKeyPem, trustedPublicKeys }: any): any;
@@ -0,0 +1,121 @@
1
+ // Moved from brainbase-unson server/services/ontology-release-trust.js without changing behavior.
2
+ // Only type annotations were added; values stay open JSON objects as in the original.
3
+ /* eslint-disable @typescript-eslint/no-explicit-any */
4
+ import { existsSync, readFileSync, realpathSync, statSync } from 'node:fs';
5
+ import path from 'node:path';
6
+ import { canonicalJson, publicationReceiptContractErrors, sha256, verifyPublicationReceipt } from './ontology-publication.js';
7
+ const SHA256_DIGEST = /^[a-f0-9]{64}$/;
8
+ const RECEIPT_FIELDS = ['receipt_path', 'receipt_digest_algorithm', 'receipt_digest'];
9
+ export function hasReceiptMetadata(entry = {}) {
10
+ return RECEIPT_FIELDS.some((field) => Object.prototype.hasOwnProperty.call(entry, field));
11
+ }
12
+ export function hasCompleteReceiptMetadata(entry = {}) {
13
+ return typeof entry.receipt_path === 'string'
14
+ && entry.receipt_path.trim().length > 0
15
+ && entry.receipt_digest_algorithm === 'sha256'
16
+ && typeof entry.receipt_digest === 'string'
17
+ && SHA256_DIGEST.test(entry.receipt_digest);
18
+ }
19
+ function invalid(reason, details = {}) {
20
+ return { verified: false, reason, details };
21
+ }
22
+ function isContained(parent, child) {
23
+ const relative = path.relative(parent, child);
24
+ return relative !== '' && !relative.startsWith('..') && !path.isAbsolute(relative);
25
+ }
26
+ export function loadTrustedPublicKeys(configDir) {
27
+ const trustStorePath = path.join(configDir, 'trusted-public-keys.json');
28
+ if (!existsSync(trustStorePath))
29
+ return {};
30
+ const trustStore = JSON.parse(readFileSync(trustStorePath, 'utf8'));
31
+ if (trustStore.schema_version !== '1.0.0'
32
+ || !trustStore.keys
33
+ || Array.isArray(trustStore.keys)
34
+ || typeof trustStore.keys !== 'object') {
35
+ throw new Error('Ontology trusted public keys must use the 1.0.0 key map schema');
36
+ }
37
+ for (const [keyId, key] of Object.entries(trustStore.keys)) {
38
+ if (!keyId
39
+ || key?.algorithm !== 'ed25519'
40
+ || typeof key.public_key_pem !== 'string'
41
+ || !key.public_key_pem.includes('-----BEGIN PUBLIC KEY-----')) {
42
+ throw new Error(`Invalid ontology trusted public key: ${keyId || '<empty>'}`);
43
+ }
44
+ }
45
+ return trustStore.keys;
46
+ }
47
+ export function verifyPublishedReceipt({ configDir, entry = {}, manifest, publicKeyPem = '', trustedPublicKeys = {} }) {
48
+ if (!hasCompleteReceiptMetadata(entry)) {
49
+ return invalid(hasReceiptMetadata(entry) ? 'incomplete_metadata' : 'missing_metadata');
50
+ }
51
+ const publicationsDir = path.resolve(configDir, 'publications');
52
+ const receiptPath = path.resolve(configDir, entry.receipt_path);
53
+ if (!isContained(publicationsDir, receiptPath)) {
54
+ return invalid('path_escape');
55
+ }
56
+ let realPublicationsDir;
57
+ let realReceiptPath;
58
+ let receiptBytes;
59
+ try {
60
+ realPublicationsDir = realpathSync(publicationsDir);
61
+ realReceiptPath = realpathSync(receiptPath);
62
+ if (!isContained(realPublicationsDir, realReceiptPath) || !statSync(realReceiptPath).isFile()) {
63
+ return invalid('path_escape_or_not_file');
64
+ }
65
+ receiptBytes = readFileSync(realReceiptPath);
66
+ }
67
+ catch {
68
+ return invalid('receipt_unavailable');
69
+ }
70
+ const actualDigest = sha256(receiptBytes);
71
+ if (actualDigest !== entry.receipt_digest) {
72
+ return invalid('digest_mismatch', { expected: entry.receipt_digest, actual: actualDigest });
73
+ }
74
+ let receipt;
75
+ try {
76
+ receipt = JSON.parse(receiptBytes.toString('utf8'));
77
+ }
78
+ catch {
79
+ return invalid('invalid_json');
80
+ }
81
+ const contractErrors = publicationReceiptContractErrors(receipt);
82
+ if (contractErrors.length) {
83
+ return invalid('contract_mismatch', { fields: contractErrors });
84
+ }
85
+ const trustedPublicKeyPem = publicKeyPem || trustedPublicKeys[receipt.key_id]?.public_key_pem || '';
86
+ if (!trustedPublicKeyPem) {
87
+ return invalid('public_key_unavailable');
88
+ }
89
+ try {
90
+ if (!verifyPublicationReceipt(receipt, trustedPublicKeyPem)) {
91
+ return invalid('signature_invalid');
92
+ }
93
+ }
94
+ catch {
95
+ return invalid('signature_invalid');
96
+ }
97
+ const governance = manifest?.governance || {};
98
+ const expectedBindings = {
99
+ release_version: entry.version,
100
+ release_digest: entry.content_digest,
101
+ source_commit_sha: entry.source_commit_sha,
102
+ decision_id: governance.decision_id,
103
+ scope_entity_id: governance.scope_entity_id,
104
+ proposer_entity_id: governance.proposer_entity_id,
105
+ decider_entity_id: governance.decider_entity_id,
106
+ applier_entity_id: governance.applier_entity_id,
107
+ actor_entity_id: governance.applier_entity_id
108
+ };
109
+ const mismatches = Object.entries(expectedBindings)
110
+ .filter(([key, value]) => !value || receipt.payload?.[key] !== value)
111
+ .map(([key]) => key);
112
+ const manifestImpactScope = canonicalJson(manifest?.impact_scope);
113
+ if (canonicalJson(receipt.payload?.impact_scope) !== manifestImpactScope
114
+ || (entry.impact_scope && canonicalJson(entry.impact_scope) !== manifestImpactScope)) {
115
+ mismatches.push('impact_scope');
116
+ }
117
+ if (mismatches.length) {
118
+ return invalid('binding_mismatch', { fields: mismatches });
119
+ }
120
+ return { verified: true, receipt, receipt_path: realReceiptPath, receipt_digest: actualDigest };
121
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unson/brainbase-mcp",
3
- "version": "0.32.0",
3
+ "version": "0.34.0",
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",
@@ -187,6 +187,30 @@
187
187
  "types": "./dist/judgment-resolution-contract.d.ts",
188
188
  "import": "./dist/judgment-resolution-contract.js"
189
189
  },
190
+ "./graph-maintenance-engine": {
191
+ "types": "./dist/graph-maintenance-engine.d.ts",
192
+ "import": "./dist/graph-maintenance-engine.js"
193
+ },
194
+ "./memory-scope-policy": {
195
+ "types": "./dist/memory-scope-policy.d.ts",
196
+ "import": "./dist/memory-scope-policy.js"
197
+ },
198
+ "./ontology-kernel": {
199
+ "types": "./dist/ontology-kernel.d.ts",
200
+ "import": "./dist/ontology-kernel.js"
201
+ },
202
+ "./ontology-registry": {
203
+ "types": "./dist/ontology-registry.d.ts",
204
+ "import": "./dist/ontology-registry.js"
205
+ },
206
+ "./ontology-publication": {
207
+ "types": "./dist/ontology-publication.d.ts",
208
+ "import": "./dist/ontology-publication.js"
209
+ },
210
+ "./ontology-release-trust": {
211
+ "types": "./dist/ontology-release-trust.d.ts",
212
+ "import": "./dist/ontology-release-trust.js"
213
+ },
190
214
  "./canonical-document-writer": {
191
215
  "types": "./dist/canonical-document-writer.d.ts",
192
216
  "import": "./dist/canonical-document-writer.js"
@@ -455,5 +479,5 @@
455
479
  "engines": {
456
480
  "node": ">=20"
457
481
  },
458
- "gitHead": "3f91401cb7221305fe1dfafc6126482bc8b55170"
482
+ "gitHead": "9275d1ad54f053c85229a44b1c4cba811969cd29"
459
483
  }
@@ -1514,6 +1514,27 @@ function memoryLines(answer) {
1514
1514
  return lines;
1515
1515
  }
1516
1516
 
1517
+ /** At most this many waiting judgments are listed in the world; the rest are counted, never hidden. */
1518
+ const WAITING_LIST_LIMIT = 3;
1519
+
1520
+ /**
1521
+ * The judgments waiting for the owner now, newest first, each a way down to the same judgment in
1522
+ * 判断の履歴 (ledger P17 / U2). The world stays an overview: only the exceptions become a short list.
1523
+ */
1524
+ function waitingLines(proofs, judgmentHref) {
1525
+ const waiting = [...proofs.values()]
1526
+ .filter(isWaiting)
1527
+ .sort((a, b) => String(b.proof?.recorded_at ?? '').localeCompare(String(a.proof?.recorded_at ?? '')));
1528
+ const lines = waiting.slice(0, WAITING_LIST_LIMIT).map((item) => {
1529
+ const id = item.proof.decision_attempt_id;
1530
+ const question = item.proof.interruption?.question_display_text ?? item.proof.decision?.summary ?? id;
1531
+ return { text: question, summary: question, link: { href: judgmentHref(id), label: '「判断の履歴」で開く', className: 'bb-world-waiting-link' } };
1532
+ });
1533
+ const rest = waiting.length - lines.length;
1534
+ if (rest > 0) lines.push({ text: `ほか${rest}件は「判断の履歴」で見られます。`, summary: `ほか${rest}件の待っている判断`, link: null });
1535
+ return lines;
1536
+ }
1537
+
1517
1538
  /** 判断の履歴 in the local web (it was 今日, `#today`, until 2026-10-11; the shell still opens old links). */
1518
1539
  function defaultJudgmentHref(decisionAttemptId) {
1519
1540
  return decisionAttemptId ? `#value-proofs?decision=${encodeURIComponent(decisionAttemptId)}` : '#value-proofs';
@@ -2439,6 +2460,9 @@ export function createWorldView({ root, rail, page, presentation = 'standard', d
2439
2460
  note('判断', `${home.delegation_map.judged}件。作業した場所を読めないため、事業には置かず広場の種類別だけで描いています(${placesResult.ok ? placesResult.data?.reason ?? '理由不明' : placesResult.error})。今あなたを待っている判断${waiting}件。`, 'warning', '判断の作業場所:読めない');
2440
2461
  }
2441
2462
  }
2463
+ if (judgmentsConnected) {
2464
+ for (const line of waitingLines(proofs, judgmentHref)) note('待っている判断', line.text, 'attention', line.summary, line.link);
2465
+ }
2442
2466
  const rowItems = new Map(rows.map((row) => [row.key, Array.isArray(row.items) ? row.items : []]));
2443
2467
  const memory = await memoryRead;
2444
2468
  if (disposed) return;