@unson/brainbase-mcp 0.44.0 → 0.44.2
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/contracts/canonical-task/operation-schema.sql +58 -0
- package/contracts/canonical-task/search-indexes.sql +10 -0
- package/contracts/canonical-task/store-schema.sql +77 -0
- package/dist/automation-run.d.ts +213 -0
- package/dist/automation-run.js +479 -0
- package/dist/canonical-task-operations.d.ts +205 -0
- package/dist/canonical-task-operations.js +700 -0
- package/dist/canonical-task-postgres.d.ts +139 -0
- package/dist/canonical-task-postgres.js +554 -0
- package/dist/canonical-task-service.d.ts +13 -0
- package/dist/canonical-task-service.js +55 -3
- package/dist/canonical-task-store-config.d.ts +31 -0
- package/dist/canonical-task-store-config.js +53 -0
- package/dist/config-parser.d.ts +298 -0
- package/dist/config-parser.js +593 -0
- package/dist/connected-onboarding.d.ts +57 -0
- package/dist/connected-onboarding.js +37 -0
- package/dist/durable-wait-http.d.ts +3 -1
- package/dist/durable-wait-http.js +73 -6
- package/dist/durable-waits.d.ts +93 -3
- package/dist/durable-waits.js +320 -8
- package/dist/honcho.d.ts +25 -0
- package/dist/honcho.js +81 -0
- package/dist/judgment-event-adapter.d.ts +72 -0
- package/dist/judgment-event-adapter.js +114 -0
- package/dist/judgment-event-outbox.d.ts +182 -0
- package/dist/judgment-event-outbox.js +568 -0
- package/dist/judgment-execution-outcome.d.ts +46 -0
- package/dist/judgment-execution-outcome.js +149 -0
- package/dist/judgment-host.d.ts +18 -7
- package/dist/judgment-host.js +82 -34
- package/dist/judgment-lifecycle-core.d.ts +198 -0
- package/dist/judgment-lifecycle-core.js +464 -0
- package/dist/judgment-node-evidence.d.ts +57 -0
- package/dist/judgment-node-evidence.js +297 -0
- package/dist/judgment-runtime-resolution.d.ts +264 -0
- package/dist/judgment-runtime-resolution.js +1248 -0
- package/dist/judgment-runtime-resolution.public.d.ts +255 -0
- package/dist/knowledge-event.d.ts +28 -0
- package/dist/knowledge-event.js +114 -0
- package/dist/mcp-runtime.d.ts +75 -0
- package/dist/mcp-runtime.js +188 -0
- package/dist/meeting-automation-runtime.d.ts +102 -0
- package/dist/meeting-automation-runtime.js +249 -0
- package/dist/meeting-automation.d.ts +155 -0
- package/dist/meeting-automation.js +341 -0
- package/dist/meeting-minutes-context-receipt.d.ts +91 -0
- package/dist/meeting-minutes-context-receipt.js +280 -0
- package/dist/meeting-source-sync.d.ts +89 -0
- package/dist/meeting-source-sync.js +230 -0
- package/dist/mesh.d.ts +58 -0
- package/dist/mesh.js +134 -0
- package/dist/onboarding-runtime.d.ts +47 -0
- package/dist/onboarding-runtime.js +4719 -0
- package/dist/routine-cycle.d.ts +51 -0
- package/dist/routine-cycle.js +153 -0
- package/dist/routine-liveness.d.ts +49 -0
- package/dist/routine-liveness.js +227 -0
- package/dist/routine-runtime.d.ts +101 -0
- package/dist/routine-runtime.js +237 -0
- package/dist/routines.d.ts +3 -0
- package/dist/routines.js +3 -0
- package/dist/run-receipt.d.ts +40 -0
- package/dist/run-receipt.js +635 -0
- package/dist/runtime-host.d.ts +64 -0
- package/dist/runtime-host.js +70 -0
- package/dist/world-work.d.ts +16 -0
- package/package.json +115 -3
- package/ui/objective-editor.js +47 -11
- package/ui/workspace-kit.css +33 -1
- package/ui/workspace-kit.js +13 -2
- package/ui/world/world-canvas-ui.css +4 -49
- package/ui/world/world-canvas-ui.js +26 -71
- package/ui/world/world-district.js +18 -3
- package/ui/world/world-placement.js +13 -0
- package/ui/world/world-work-rail.js +7 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-owned dependencies shared by the routine and automation run cores.
|
|
3
|
+
*
|
|
4
|
+
* The OSS package deliberately does not resolve a tenant, user, credential,
|
|
5
|
+
* storage directory, or Graph connection by itself. A consumer supplies those
|
|
6
|
+
* values through these ports for every operation.
|
|
7
|
+
*/
|
|
8
|
+
export type Awaitable<T> = T | PromiseLike<T>;
|
|
9
|
+
export interface RuntimePortInput {
|
|
10
|
+
operation: string;
|
|
11
|
+
routine?: string;
|
|
12
|
+
automationId?: string;
|
|
13
|
+
runId?: string;
|
|
14
|
+
request?: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface RuntimeHostContext {
|
|
17
|
+
storageRoot: string;
|
|
18
|
+
now: Date;
|
|
19
|
+
tenantId: string;
|
|
20
|
+
identity: unknown;
|
|
21
|
+
auth: unknown;
|
|
22
|
+
graph: unknown;
|
|
23
|
+
input: RuntimePortInput;
|
|
24
|
+
}
|
|
25
|
+
export interface RuntimeStorageRootPort {
|
|
26
|
+
resolve(input: RuntimePortInput): Awaitable<string>;
|
|
27
|
+
}
|
|
28
|
+
export interface RuntimeClockPort {
|
|
29
|
+
now(): Date;
|
|
30
|
+
}
|
|
31
|
+
export interface RuntimeIdentityPort {
|
|
32
|
+
resolve(input: RuntimePortInput & {
|
|
33
|
+
tenantId: string;
|
|
34
|
+
}): Awaitable<unknown>;
|
|
35
|
+
}
|
|
36
|
+
export interface RuntimeTenantPort {
|
|
37
|
+
resolve(input: RuntimePortInput): Awaitable<string>;
|
|
38
|
+
}
|
|
39
|
+
export type RuntimeAuthorization = true | false | {
|
|
40
|
+
allowed: boolean;
|
|
41
|
+
context?: unknown;
|
|
42
|
+
};
|
|
43
|
+
export interface RuntimeAuthPort {
|
|
44
|
+
authorize(input: RuntimePortInput & {
|
|
45
|
+
tenantId: string;
|
|
46
|
+
identity: unknown;
|
|
47
|
+
}): Awaitable<RuntimeAuthorization>;
|
|
48
|
+
}
|
|
49
|
+
export interface RuntimeGraphPort {
|
|
50
|
+
resolve(input: RuntimePortInput & {
|
|
51
|
+
tenantId: string;
|
|
52
|
+
identity: unknown;
|
|
53
|
+
}): Awaitable<unknown>;
|
|
54
|
+
}
|
|
55
|
+
export interface RuntimeHostPorts {
|
|
56
|
+
storageRoot: RuntimeStorageRootPort;
|
|
57
|
+
clock: RuntimeClockPort;
|
|
58
|
+
identity: RuntimeIdentityPort;
|
|
59
|
+
tenant: RuntimeTenantPort;
|
|
60
|
+
auth: RuntimeAuthPort;
|
|
61
|
+
graph: RuntimeGraphPort;
|
|
62
|
+
}
|
|
63
|
+
export declare function assertRuntimeHostPorts(ports: RuntimeHostPorts): void;
|
|
64
|
+
export declare function resolveRuntimeHostContext(ports: RuntimeHostPorts, input: RuntimePortInput): Promise<RuntimeHostContext>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-owned dependencies shared by the routine and automation run cores.
|
|
3
|
+
*
|
|
4
|
+
* The OSS package deliberately does not resolve a tenant, user, credential,
|
|
5
|
+
* storage directory, or Graph connection by itself. A consumer supplies those
|
|
6
|
+
* values through these ports for every operation.
|
|
7
|
+
*/
|
|
8
|
+
export function assertRuntimeHostPorts(ports) {
|
|
9
|
+
if (!ports || typeof ports !== 'object') {
|
|
10
|
+
throw new Error('runtime host ports are required');
|
|
11
|
+
}
|
|
12
|
+
const required = ['storageRoot', 'clock', 'identity', 'tenant', 'auth', 'graph'];
|
|
13
|
+
for (const name of required) {
|
|
14
|
+
if (!ports[name] || typeof ports[name] !== 'object') {
|
|
15
|
+
throw new Error(`runtime host port ${name} is required`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
for (const [name, value] of [
|
|
19
|
+
['storageRoot.resolve', ports.storageRoot.resolve],
|
|
20
|
+
['clock.now', ports.clock.now],
|
|
21
|
+
['identity.resolve', ports.identity.resolve],
|
|
22
|
+
['tenant.resolve', ports.tenant.resolve],
|
|
23
|
+
['auth.authorize', ports.auth.authorize],
|
|
24
|
+
['graph.resolve', ports.graph.resolve]
|
|
25
|
+
]) {
|
|
26
|
+
if (typeof value !== 'function') {
|
|
27
|
+
throw new Error(`runtime host port ${name} must be a function`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export async function resolveRuntimeHostContext(ports, input) {
|
|
32
|
+
assertRuntimeHostPorts(ports);
|
|
33
|
+
const storageRoot = await ports.storageRoot.resolve(input);
|
|
34
|
+
if (typeof storageRoot !== 'string' || storageRoot.trim() === '') {
|
|
35
|
+
throw new Error('runtime storage root must be a non-empty string');
|
|
36
|
+
}
|
|
37
|
+
const tenantId = await ports.tenant.resolve(input);
|
|
38
|
+
if (typeof tenantId !== 'string' || tenantId.trim() === '') {
|
|
39
|
+
throw new Error('runtime tenant port must resolve a non-empty string');
|
|
40
|
+
}
|
|
41
|
+
const identity = await ports.identity.resolve({ ...input, tenantId });
|
|
42
|
+
if (identity === null || identity === undefined) {
|
|
43
|
+
throw new Error('runtime identity port must resolve an identity');
|
|
44
|
+
}
|
|
45
|
+
const authorization = await ports.auth.authorize({ ...input, tenantId, identity });
|
|
46
|
+
const allowed = authorization === true
|
|
47
|
+
|| (typeof authorization === 'object'
|
|
48
|
+
&& authorization !== null
|
|
49
|
+
&& authorization.allowed === true);
|
|
50
|
+
if (!allowed) {
|
|
51
|
+
throw new Error(`runtime authorization denied for ${input.operation}`);
|
|
52
|
+
}
|
|
53
|
+
const graph = await ports.graph.resolve({ ...input, tenantId, identity });
|
|
54
|
+
if (graph === null || graph === undefined) {
|
|
55
|
+
throw new Error('runtime Graph port must resolve a context');
|
|
56
|
+
}
|
|
57
|
+
const now = ports.clock.now();
|
|
58
|
+
if (!(now instanceof Date) || Number.isNaN(now.getTime())) {
|
|
59
|
+
throw new Error('runtime clock must return a valid Date');
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
storageRoot,
|
|
63
|
+
now,
|
|
64
|
+
tenantId,
|
|
65
|
+
identity,
|
|
66
|
+
auth: authorization,
|
|
67
|
+
graph,
|
|
68
|
+
input
|
|
69
|
+
};
|
|
70
|
+
}
|
package/dist/world-work.d.ts
CHANGED
|
@@ -63,7 +63,23 @@ export interface WorldWorkAmbiguousMention {
|
|
|
63
63
|
readonly text: string;
|
|
64
64
|
readonly candidates: readonly WorldWorkPersonRef[];
|
|
65
65
|
}
|
|
66
|
+
/** Optional current actors supplied by an authoritative host; the common UI owns no membership store. */
|
|
67
|
+
export interface WorldWorkActor {
|
|
68
|
+
readonly id: string;
|
|
69
|
+
readonly name: string;
|
|
70
|
+
readonly task_id: string;
|
|
71
|
+
readonly kind?: string;
|
|
72
|
+
readonly state: WorldWorkStatus | null;
|
|
73
|
+
readonly activity?: {
|
|
74
|
+
readonly state: string;
|
|
75
|
+
readonly moving: boolean;
|
|
76
|
+
readonly heartbeat_at?: string | null;
|
|
77
|
+
readonly checked_at?: string;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
66
80
|
export interface WorldWorkSite {
|
|
81
|
+
readonly actors_state?: 'confirmed' | 'unconfirmed';
|
|
82
|
+
readonly actors?: readonly WorldWorkActor[];
|
|
67
83
|
readonly task_id: string;
|
|
68
84
|
readonly title: string;
|
|
69
85
|
/** What the work is for, as the task record states it (`purpose_label`); null when it states none. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unson/brainbase-mcp",
|
|
3
|
-
"version": "0.44.
|
|
3
|
+
"version": "0.44.2",
|
|
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",
|
|
@@ -43,6 +43,30 @@
|
|
|
43
43
|
"types": "./dist/judgment-value-proof.d.ts",
|
|
44
44
|
"import": "./dist/judgment-value-proof.js"
|
|
45
45
|
},
|
|
46
|
+
"./judgment-host": {
|
|
47
|
+
"types": "./dist/judgment-host.d.ts",
|
|
48
|
+
"import": "./dist/judgment-host.js"
|
|
49
|
+
},
|
|
50
|
+
"./judgment-lifecycle-core": {
|
|
51
|
+
"types": "./dist/judgment-lifecycle-core.d.ts",
|
|
52
|
+
"import": "./dist/judgment-lifecycle-core.js"
|
|
53
|
+
},
|
|
54
|
+
"./judgment-execution-outcome": {
|
|
55
|
+
"types": "./dist/judgment-execution-outcome.d.ts",
|
|
56
|
+
"import": "./dist/judgment-execution-outcome.js"
|
|
57
|
+
},
|
|
58
|
+
"./judgment-node-evidence": {
|
|
59
|
+
"types": "./dist/judgment-node-evidence.d.ts",
|
|
60
|
+
"import": "./dist/judgment-node-evidence.js"
|
|
61
|
+
},
|
|
62
|
+
"./judgment-event-adapter": {
|
|
63
|
+
"types": "./dist/judgment-event-adapter.d.ts",
|
|
64
|
+
"import": "./dist/judgment-event-adapter.js"
|
|
65
|
+
},
|
|
66
|
+
"./judgment-event-outbox": {
|
|
67
|
+
"types": "./dist/judgment-event-outbox.d.ts",
|
|
68
|
+
"import": "./dist/judgment-event-outbox.js"
|
|
69
|
+
},
|
|
46
70
|
"./judgment-value-proof-review": {
|
|
47
71
|
"types": "./dist/judgment-value-proof-review.d.ts",
|
|
48
72
|
"import": "./dist/judgment-value-proof-review.js"
|
|
@@ -99,6 +123,18 @@
|
|
|
99
123
|
"types": "./dist/canonical-task-service.d.ts",
|
|
100
124
|
"import": "./dist/canonical-task-service.js"
|
|
101
125
|
},
|
|
126
|
+
"./canonical-task-postgres": {
|
|
127
|
+
"types": "./dist/canonical-task-postgres.d.ts",
|
|
128
|
+
"import": "./dist/canonical-task-postgres.js"
|
|
129
|
+
},
|
|
130
|
+
"./canonical-task-operations": {
|
|
131
|
+
"types": "./dist/canonical-task-operations.d.ts",
|
|
132
|
+
"import": "./dist/canonical-task-operations.js"
|
|
133
|
+
},
|
|
134
|
+
"./canonical-task-store-config": {
|
|
135
|
+
"types": "./dist/canonical-task-store-config.d.ts",
|
|
136
|
+
"import": "./dist/canonical-task-store-config.js"
|
|
137
|
+
},
|
|
102
138
|
"./foundation-catalog": {
|
|
103
139
|
"types": "./dist/foundation-catalog.d.ts",
|
|
104
140
|
"import": "./dist/foundation-catalog.js"
|
|
@@ -123,6 +159,18 @@
|
|
|
123
159
|
"types": "./dist/company-os-receipt-adapter.d.ts",
|
|
124
160
|
"import": "./dist/company-os-receipt-adapter.js"
|
|
125
161
|
},
|
|
162
|
+
"./run-receipt": {
|
|
163
|
+
"types": "./dist/run-receipt.d.ts",
|
|
164
|
+
"import": "./dist/run-receipt.js"
|
|
165
|
+
},
|
|
166
|
+
"./routines": {
|
|
167
|
+
"types": "./dist/routines.d.ts",
|
|
168
|
+
"import": "./dist/routines.js"
|
|
169
|
+
},
|
|
170
|
+
"./automation-run": {
|
|
171
|
+
"types": "./dist/automation-run.d.ts",
|
|
172
|
+
"import": "./dist/automation-run.js"
|
|
173
|
+
},
|
|
126
174
|
"./company-os-learning-adoption": {
|
|
127
175
|
"types": "./dist/company-os-learning-adoption.d.ts",
|
|
128
176
|
"import": "./dist/company-os-learning-adoption.js"
|
|
@@ -187,6 +235,10 @@
|
|
|
187
235
|
"types": "./dist/judgment-resolution-contract.d.ts",
|
|
188
236
|
"import": "./dist/judgment-resolution-contract.js"
|
|
189
237
|
},
|
|
238
|
+
"./judgment-runtime-resolution": {
|
|
239
|
+
"types": "./dist/judgment-runtime-resolution.public.d.ts",
|
|
240
|
+
"import": "./dist/judgment-runtime-resolution.js"
|
|
241
|
+
},
|
|
190
242
|
"./graph-maintenance-engine": {
|
|
191
243
|
"types": "./dist/graph-maintenance-engine.d.ts",
|
|
192
244
|
"import": "./dist/graph-maintenance-engine.js"
|
|
@@ -255,10 +307,34 @@
|
|
|
255
307
|
"types": "./dist/knowledge-promotion.d.ts",
|
|
256
308
|
"import": "./dist/knowledge-promotion.js"
|
|
257
309
|
},
|
|
310
|
+
"./knowledge-event": {
|
|
311
|
+
"types": "./dist/knowledge-event.d.ts",
|
|
312
|
+
"import": "./dist/knowledge-event.js"
|
|
313
|
+
},
|
|
258
314
|
"./organization-connection": {
|
|
259
315
|
"types": "./dist/organization-connection.d.ts",
|
|
260
316
|
"import": "./dist/organization-connection.js"
|
|
261
317
|
},
|
|
318
|
+
"./mesh": {
|
|
319
|
+
"types": "./dist/mesh.d.ts",
|
|
320
|
+
"import": "./dist/mesh.js"
|
|
321
|
+
},
|
|
322
|
+
"./honcho": {
|
|
323
|
+
"types": "./dist/honcho.d.ts",
|
|
324
|
+
"import": "./dist/honcho.js"
|
|
325
|
+
},
|
|
326
|
+
"./onboarding-runtime": {
|
|
327
|
+
"types": "./dist/onboarding-runtime.d.ts",
|
|
328
|
+
"import": "./dist/onboarding-runtime.js"
|
|
329
|
+
},
|
|
330
|
+
"./connected-onboarding": {
|
|
331
|
+
"types": "./dist/connected-onboarding.d.ts",
|
|
332
|
+
"import": "./dist/connected-onboarding.js"
|
|
333
|
+
},
|
|
334
|
+
"./mcp-runtime": {
|
|
335
|
+
"types": "./dist/mcp-runtime.d.ts",
|
|
336
|
+
"import": "./dist/mcp-runtime.js"
|
|
337
|
+
},
|
|
262
338
|
"./resource-reservations": {
|
|
263
339
|
"types": "./dist/resource-reservations.d.ts",
|
|
264
340
|
"import": "./dist/resource-reservations.js"
|
|
@@ -287,6 +363,10 @@
|
|
|
287
363
|
"types": "./dist/server-support.d.ts",
|
|
288
364
|
"import": "./dist/server-support.js"
|
|
289
365
|
},
|
|
366
|
+
"./config-parser": {
|
|
367
|
+
"types": "./dist/config-parser.d.ts",
|
|
368
|
+
"import": "./dist/config-parser.js"
|
|
369
|
+
},
|
|
290
370
|
"./company-os-impact-review": {
|
|
291
371
|
"types": "./dist/company-os-impact-review.d.ts",
|
|
292
372
|
"import": "./dist/company-os-impact-review.js"
|
|
@@ -303,6 +383,22 @@
|
|
|
303
383
|
"types": "./dist/meeting-minutes.d.ts",
|
|
304
384
|
"import": "./dist/meeting-minutes.js"
|
|
305
385
|
},
|
|
386
|
+
"./meeting-automation": {
|
|
387
|
+
"types": "./dist/meeting-automation.d.ts",
|
|
388
|
+
"import": "./dist/meeting-automation.js"
|
|
389
|
+
},
|
|
390
|
+
"./meeting-automation-runtime": {
|
|
391
|
+
"types": "./dist/meeting-automation-runtime.d.ts",
|
|
392
|
+
"import": "./dist/meeting-automation-runtime.js"
|
|
393
|
+
},
|
|
394
|
+
"./meeting-minutes-context-receipt": {
|
|
395
|
+
"types": "./dist/meeting-minutes-context-receipt.d.ts",
|
|
396
|
+
"import": "./dist/meeting-minutes-context-receipt.js"
|
|
397
|
+
},
|
|
398
|
+
"./meeting-source-sync": {
|
|
399
|
+
"types": "./dist/meeting-source-sync.d.ts",
|
|
400
|
+
"import": "./dist/meeting-source-sync.js"
|
|
401
|
+
},
|
|
306
402
|
"./meeting-minutes-http": {
|
|
307
403
|
"types": "./dist/meeting-minutes-http.d.ts",
|
|
308
404
|
"import": "./dist/meeting-minutes-http.js"
|
|
@@ -444,9 +540,12 @@
|
|
|
444
540
|
"access": "public"
|
|
445
541
|
},
|
|
446
542
|
"scripts": {
|
|
447
|
-
"build": "tsc -p tsconfig.json",
|
|
543
|
+
"build": "tsc -p tsconfig.json && node scripts/copy-judgment-runtime-resolution-public-types.mjs && tsc -p tsconfig.judgment-runtime-resolution-types.json --pretty false && node scripts/build-stage3b-candidate-bundle.mjs",
|
|
544
|
+
"typecheck:config-parser": "tsc -p tsconfig.config-parser-types.json --pretty false",
|
|
545
|
+
"typecheck:judgment-runtime-resolution": "tsc -p tsconfig.judgment-runtime-resolution-types.json --pretty false",
|
|
448
546
|
"test": "vitest run --exclude tests/npm-prepublication-evidence.integration.test.ts",
|
|
449
547
|
"test:integration": "vitest run tests/mcp-contract.test.ts tests/ontology-cli.test.ts tests/npm-release-validation.integration.test.ts tests/npm-consumer-smoke.integration.test.ts",
|
|
548
|
+
"test:canonical-task-postgres": "vitest run tests/canonical-task-postgres-service.integration.test.ts",
|
|
450
549
|
"test:consumer-smoke": "vitest run tests/npm-consumer-smoke.integration.test.ts",
|
|
451
550
|
"test:integration:release-evidence": "vitest run tests/npm-release-validation.integration.test.ts tests/npm-prepublication-evidence.integration.test.ts",
|
|
452
551
|
"test:e2e": "vitest run tests/e2e/brainbase-mcp-only-acceptance.spec.ts tests/e2e/story-brainbase-portable-ontology-kernel-acceptance.spec.ts",
|
|
@@ -477,6 +576,7 @@
|
|
|
477
576
|
"dependencies": {
|
|
478
577
|
"@modelcontextprotocol/sdk": "^1.31.0",
|
|
479
578
|
"graphology": "0.26.0",
|
|
579
|
+
"js-yaml": "^4.1.1",
|
|
480
580
|
"sigma": "3.0.3",
|
|
481
581
|
"zod": "^3.25.56"
|
|
482
582
|
},
|
|
@@ -486,7 +586,9 @@
|
|
|
486
586
|
"devDependencies": {
|
|
487
587
|
"@electric-sql/pglite": "^0.5.8",
|
|
488
588
|
"@types/node": "^22.15.29",
|
|
589
|
+
"@types/pg": "^8.23.1",
|
|
489
590
|
"esbuild": "0.28.2",
|
|
591
|
+
"pg": "^8.23.1",
|
|
490
592
|
"three": "0.186.1",
|
|
491
593
|
"tsx": "^4.19.4",
|
|
492
594
|
"typescript": "^5.8.3",
|
|
@@ -496,5 +598,15 @@
|
|
|
496
598
|
"engines": {
|
|
497
599
|
"node": ">=20"
|
|
498
600
|
},
|
|
499
|
-
"
|
|
601
|
+
"directories": {
|
|
602
|
+
"doc": "docs",
|
|
603
|
+
"test": "tests"
|
|
604
|
+
},
|
|
605
|
+
"keywords": [],
|
|
606
|
+
"author": "",
|
|
607
|
+
"bugs": {
|
|
608
|
+
"url": "https://github.com/Unson-LLC/brainbase/issues"
|
|
609
|
+
},
|
|
610
|
+
"homepage": "https://github.com/Unson-LLC/brainbase#readme",
|
|
611
|
+
"gitHead": "108ed1e1c5066b088e6c61b9d6ff87149a9f2ce6"
|
|
500
612
|
}
|
package/ui/objective-editor.js
CHANGED
|
@@ -260,6 +260,18 @@ function definitionForSave(definition) {
|
|
|
260
260
|
|
|
261
261
|
function normalizeReadiness(value) {
|
|
262
262
|
const object = objectValue(value);
|
|
263
|
+
const explicitState = normalizeState(firstValue(object, 'state'));
|
|
264
|
+
if (['permission_denied', 'api_unavailable', 'missing', 'conflict', 'error_retryable'].includes(explicitState)) {
|
|
265
|
+
return {
|
|
266
|
+
state: explicitState,
|
|
267
|
+
ready: null,
|
|
268
|
+
issues: null,
|
|
269
|
+
code: nonEmptyText(firstValue(object, 'code')) ?? explicitState,
|
|
270
|
+
currentRevision: nonEmptyText(firstValue(object, 'currentRevision', 'current_revision')),
|
|
271
|
+
message: nonEmptyText(firstValue(object, 'message')) ?? STATUS_LABELS[explicitState],
|
|
272
|
+
error: firstValue(object, 'error'),
|
|
273
|
+
};
|
|
274
|
+
}
|
|
263
275
|
if (!object || typeof object.ready !== 'boolean') return { state: 'unknown', ready: null, issues: null };
|
|
264
276
|
const issues = asArray(object.issues);
|
|
265
277
|
const messageValue = firstValue(object, 'message', 'reason');
|
|
@@ -708,11 +720,17 @@ function renderCorrectionGuidance(guidance) {
|
|
|
708
720
|
return section;
|
|
709
721
|
}
|
|
710
722
|
|
|
711
|
-
function renderReadiness(root, readiness) {
|
|
723
|
+
function renderReadiness(root, readiness, callbacks = {}) {
|
|
712
724
|
const section = makeElement('section', { className: 'objective-editor-readiness', attrs: { 'aria-label': '判断利用可能性' } });
|
|
713
725
|
const normalized = normalizeReadiness(readiness);
|
|
714
726
|
section.append(makeElement('div', { className: 'objective-editor-subheading', text: '判断への利用' }));
|
|
715
727
|
if (normalized.state !== 'ready') {
|
|
728
|
+
if (normalized.state !== 'unknown') {
|
|
729
|
+
section.append(statusNotice(normalized, {
|
|
730
|
+
onRetry: ['error_retryable', 'api_unavailable'].includes(normalized.state) ? callbacks.onRetryReadiness : null,
|
|
731
|
+
}));
|
|
732
|
+
return section;
|
|
733
|
+
}
|
|
716
734
|
section.append(statusBadge('judgment_unknown'), makeElement('p', { className: 'objective-editor-muted', text: '判断に使える状態かどうかを、保存先から確認できていません。' }));
|
|
717
735
|
return section;
|
|
718
736
|
}
|
|
@@ -897,7 +915,7 @@ function buildObjectiveForm(state, callbacks, { workspace = false } = {}) {
|
|
|
897
915
|
onAddCriterion: () => { captureDraft(); callbacks.onAddCriterion?.(); },
|
|
898
916
|
onRemoveCriterion: (index) => { captureDraft(); callbacks.onRemoveCriterion?.(index); },
|
|
899
917
|
}));
|
|
900
|
-
form.append(renderReadiness(form, state.readiness));
|
|
918
|
+
form.append(renderReadiness(form, state.readiness, callbacks));
|
|
901
919
|
form.append(renderConstraintRefs(form, state, callbacks));
|
|
902
920
|
const actions = makeElement('div', { className: 'objective-editor-actions' });
|
|
903
921
|
actions.append(makeElement('span', { className: 'objective-editor-muted', text: callbacks.canEdit ? '保存後に同じID・新版を再取得して確認します。' : '読み取り専用です。書込み権限はホストから提供してください。' }));
|
|
@@ -1199,9 +1217,16 @@ function constraintContent(doc, state, callbacks) {
|
|
|
1199
1217
|
return content;
|
|
1200
1218
|
}
|
|
1201
1219
|
|
|
1202
|
-
function readinessContent(doc, readiness) {
|
|
1220
|
+
function readinessContent(doc, readiness, callbacks = {}) {
|
|
1203
1221
|
const normalized = normalizeReadiness(readiness);
|
|
1204
1222
|
if (normalized.state !== 'ready') {
|
|
1223
|
+
if (normalized.state !== 'unknown') {
|
|
1224
|
+
return [workspaceStatusNotice(doc, normalized, {
|
|
1225
|
+
label: '判断',
|
|
1226
|
+
onRetry: ['error_retryable', 'api_unavailable'].includes(normalized.state) ? callbacks.onRetryReadiness : null,
|
|
1227
|
+
retryLabel: '再読込',
|
|
1228
|
+
})];
|
|
1229
|
+
}
|
|
1205
1230
|
return [statusBadge('judgment_unknown'), makeElement('p', { text: '判断に使える状態かどうかを、保存先から確認できていません。' })];
|
|
1206
1231
|
}
|
|
1207
1232
|
if (normalized.ready) {
|
|
@@ -1242,7 +1267,7 @@ function renderObjectiveDetail(doc, state, callbacks) {
|
|
|
1242
1267
|
}));
|
|
1243
1268
|
parts.push(workspaceRailBlock(doc, { title: `評価基準${objective.criteria ? ` ${objective.criteria.length}件` : ''}`, className: 'bb-objective-criteria-block', content: criteriaContent(doc, objective.criteria) }));
|
|
1244
1269
|
parts.push(workspaceRailBlock(doc, { title: '制約の参照', className: 'bb-objective-constraints-block', content: constraintContent(doc, state, callbacks) }));
|
|
1245
|
-
parts.push(workspaceRailBlock(doc, { title: '判断に使えるか', className: 'bb-objective-readiness-block', content: readinessContent(doc, state.readiness) }));
|
|
1270
|
+
parts.push(workspaceRailBlock(doc, { title: '判断に使えるか', className: 'bb-objective-readiness-block', content: readinessContent(doc, state.readiness, callbacks) }));
|
|
1246
1271
|
if (callbacks.canEdit) {
|
|
1247
1272
|
parts.push(makeElement('p', { className: 'objective-editor-muted bb-objective-revision-note', text: '直して保存すると同じ目的の新しい版を作ります。保存結果を読み戻して確認し、確認できない場合はその状態を表示します。' }));
|
|
1248
1273
|
parts.push(workspaceActions(doc, [{ text: '目的を直す', variant: 'primary', onClick: callbacks.onEdit }]));
|
|
@@ -1416,6 +1441,7 @@ export function createObjectiveEditorController(options = {}) {
|
|
|
1416
1441
|
onAddConstraintRef: addConstraintRef,
|
|
1417
1442
|
onRemoveConstraintRef: removeConstraintRef,
|
|
1418
1443
|
onReloadConstraints: () => loadConstraintRefs(state.selected),
|
|
1444
|
+
onRetryReadiness: () => loadReadiness(state.selected),
|
|
1419
1445
|
onLoadStoryLinks: loadStoryLinks,
|
|
1420
1446
|
onRetryStory: () => loadStoryLinks(state.story.storyId),
|
|
1421
1447
|
onEdit: beginEdit,
|
|
@@ -1513,24 +1539,34 @@ export function createObjectiveEditorController(options = {}) {
|
|
|
1513
1539
|
const request = ++readinessRequest;
|
|
1514
1540
|
const current = () => version === selectionVersion && request === readinessRequest
|
|
1515
1541
|
&& state.selected?.id === objective.id && state.selected?.revision === objective.revision;
|
|
1542
|
+
const apply = (readiness) => {
|
|
1543
|
+
if (!current()) return false;
|
|
1544
|
+
state.readiness = readiness;
|
|
1545
|
+
if (state.selected) state.selected.readiness = readiness;
|
|
1546
|
+
if (Array.isArray(state.objectives.records)) {
|
|
1547
|
+
state.objectives.records = state.objectives.records.map((record) => (
|
|
1548
|
+
record?.id === objective.id && record?.revision === objective.revision
|
|
1549
|
+
? { ...record, readiness }
|
|
1550
|
+
: record
|
|
1551
|
+
));
|
|
1552
|
+
}
|
|
1553
|
+
render();
|
|
1554
|
+
return true;
|
|
1555
|
+
};
|
|
1516
1556
|
const method = portMethod(port, 'checkObjectiveReadiness');
|
|
1517
1557
|
if (!method) {
|
|
1518
|
-
|
|
1519
|
-
render();
|
|
1558
|
+
apply({ state: 'unknown', ready: null, issues: null, message: '判断に使える状態を確かめる経路がありません。' });
|
|
1520
1559
|
return state.readiness;
|
|
1521
1560
|
}
|
|
1522
1561
|
try {
|
|
1523
1562
|
const payload = await method(objective.id, context, objective.revision);
|
|
1524
|
-
if (!
|
|
1525
|
-
state.readiness = normalizeReadiness(payload);
|
|
1563
|
+
if (!apply(normalizeReadiness(payload))) return state.readiness;
|
|
1526
1564
|
} catch (error) {
|
|
1527
1565
|
if (!current()) return state.readiness;
|
|
1528
1566
|
const normalized = normalizeObjectiveError(error);
|
|
1529
1567
|
state.permissionDenied ||= normalized.state === 'permission_denied';
|
|
1530
|
-
|
|
1568
|
+
if (!apply({ state: normalized.state, ready: null, issues: null, ...normalized })) return state.readiness;
|
|
1531
1569
|
}
|
|
1532
|
-
if (state.selected) state.selected.readiness = state.readiness;
|
|
1533
|
-
render();
|
|
1534
1570
|
return state.readiness;
|
|
1535
1571
|
}
|
|
1536
1572
|
|
package/ui/workspace-kit.css
CHANGED
|
@@ -517,7 +517,39 @@
|
|
|
517
517
|
.bb-ws-error-stack { position: absolute; z-index: 55; top: 0; right: 0; width: min(300px,100%); max-height: none; padding-bottom: 64px; pointer-events: none; box-sizing: border-box; overflow: visible; }
|
|
518
518
|
.bb-ws-error-list { display: grid; gap: 6px; }
|
|
519
519
|
.bb-ws-error-count { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
|
|
520
|
-
.bb-ws-
|
|
520
|
+
.bb-ws-notification-card {
|
|
521
|
+
--bb-notification-accent: var(--bb-color-notice-control-border);
|
|
522
|
+
--bb-notification-symbol-border: var(--bb-color-notice-control-border);
|
|
523
|
+
--bb-notification-symbol-text: var(--bb-color-notice-text);
|
|
524
|
+
box-sizing: border-box;
|
|
525
|
+
padding: 8px 10px;
|
|
526
|
+
border: 1px solid var(--bb-color-notice-border);
|
|
527
|
+
border-left: 3px solid var(--bb-notification-accent);
|
|
528
|
+
border-radius: 4px;
|
|
529
|
+
background: var(--bb-color-notice-background);
|
|
530
|
+
backdrop-filter: blur(5px);
|
|
531
|
+
color: var(--bb-color-notice-text);
|
|
532
|
+
font-size: 12px;
|
|
533
|
+
line-height: 1.5;
|
|
534
|
+
}
|
|
535
|
+
.bb-ws-notification-card.is-warning {
|
|
536
|
+
--bb-notification-accent: var(--bb-color-notice-warning);
|
|
537
|
+
--bb-notification-symbol-border: var(--bb-color-notice-warning-symbol-border);
|
|
538
|
+
--bb-notification-symbol-text: var(--bb-color-notice-warning-text);
|
|
539
|
+
}
|
|
540
|
+
.bb-ws-notification-card.is-danger {
|
|
541
|
+
--bb-notification-accent: var(--bb-color-notice-danger);
|
|
542
|
+
--bb-notification-symbol-border: var(--bb-color-notice-danger-symbol-border);
|
|
543
|
+
--bb-notification-symbol-text: var(--bb-color-notice-danger-text);
|
|
544
|
+
}
|
|
545
|
+
.bb-ws-notification-symbol {
|
|
546
|
+
display: grid; place-items: center; flex: none;
|
|
547
|
+
width: 18px; height: 18px; border-radius: 3px;
|
|
548
|
+
border: 1px solid var(--bb-notification-symbol-border);
|
|
549
|
+
color: var(--bb-notification-symbol-text);
|
|
550
|
+
font-size: 11px; font-weight: 700;
|
|
551
|
+
}
|
|
552
|
+
.bb-ws-error-card { display: flex; align-items: start; gap: 8px; width: 100%; pointer-events: auto; }
|
|
521
553
|
.bb-ws-error-card.is-warning { border-left-color: var(--bb-color-notice-warning); }
|
|
522
554
|
.bb-ws-error-card > details { flex: 1; min-width: 0; }
|
|
523
555
|
.bb-ws-error-card summary { display: flex; align-items: center; gap: 6px; list-style: none; cursor: pointer; }
|
package/ui/workspace-kit.js
CHANGED
|
@@ -371,9 +371,20 @@ export function workspaceFilterPopover(doc, { content, open = false, onToggle, t
|
|
|
371
371
|
} };
|
|
372
372
|
}
|
|
373
373
|
|
|
374
|
+
/** Reusable notification surface. Hosts own content, placement and lifecycle.
|
|
375
|
+
* Tones use shared semantic tokens; unknown values stay informational.
|
|
376
|
+
*/
|
|
377
|
+
export function workspaceNotificationCard(doc, { tone = 'info', content, tag = 'section', className = '', role } = {}) {
|
|
378
|
+
const severity = tone === 'attention' ? 'warning' : ['info', 'warning', 'danger'].includes(tone) ? tone : 'info';
|
|
379
|
+
const card = el(doc, tag, { className: `bb-ws-notification-card is-${severity} ${className}`.trim(), attrs: { role } });
|
|
380
|
+
appendContent(card, doc, content);
|
|
381
|
+
return card;
|
|
382
|
+
}
|
|
383
|
+
|
|
374
384
|
/** Compact notification with a fixed-center, purely visual spinner. */
|
|
375
385
|
export function workspaceLoadingCard(doc, { title = 'ロード中' } = {}) {
|
|
376
|
-
const card =
|
|
386
|
+
const card = workspaceNotificationCard(doc, { className: 'bb-ws-error-card bb-ws-loading-card', role: 'status' });
|
|
387
|
+
card.setAttribute('aria-live', 'polite');
|
|
377
388
|
card.append(el(doc, 'span', { className: 'bb-ws-loading-spinner', attrs: { 'aria-hidden': 'true' } }), el(doc, 'span', { text: title }));
|
|
378
389
|
return card;
|
|
379
390
|
}
|
|
@@ -404,7 +415,7 @@ export function workspaceDismissNotification(card, onDismiss) {
|
|
|
404
415
|
|
|
405
416
|
/** Persistent, initially closed notification. The caller owns its lifecycle. */
|
|
406
417
|
export function workspaceErrorCard(doc, { title, message, tone = 'danger', onRetry } = {}) {
|
|
407
|
-
const card =
|
|
418
|
+
const card = workspaceNotificationCard(doc, { tone, className: 'bb-ws-error-card', role: 'listitem' });
|
|
408
419
|
const details = el(doc, 'details');
|
|
409
420
|
const summary = el(doc, 'summary', { attrs: { 'aria-label': `${title}の通知` } });
|
|
410
421
|
summary.append(el(doc, 'span', { className: 'bb-ws-error-symbol', text: '!', attrs: { 'aria-hidden': 'true' } }), el(doc, 'span', { text: title }));
|
|
@@ -103,31 +103,7 @@
|
|
|
103
103
|
.bb-world-canvas-ui .bb-world-canvas-city:disabled { cursor: default; opacity: .65; }
|
|
104
104
|
.bb-world-canvas-ui .bb-world-canvas-sky { display: grid; place-items: center; padding: 0; }
|
|
105
105
|
.bb-world-canvas-ui .bb-world-canvas-sky-icon { font-size: 22px; line-height: 1; }
|
|
106
|
-
.bb-world-canvas-ui .bb-world-canvas-sky-
|
|
107
|
-
position: absolute;
|
|
108
|
-
top: calc(var(--bb-world-toolbar-top) + 48px);
|
|
109
|
-
right: var(--bb-world-right-inset);
|
|
110
|
-
min-width: 150px;
|
|
111
|
-
padding: 5px;
|
|
112
|
-
border: 1px solid rgb(13 25 46 / 18%);
|
|
113
|
-
border-radius: 9px;
|
|
114
|
-
background: #fff;
|
|
115
|
-
box-shadow: 0 8px 25px #0d192e22;
|
|
116
|
-
pointer-events: auto;
|
|
117
|
-
}
|
|
118
|
-
.bb-world-canvas-ui .bb-world-canvas-sky-option {
|
|
119
|
-
display: block;
|
|
120
|
-
width: 100%;
|
|
121
|
-
padding: 8px 10px;
|
|
122
|
-
border: 0;
|
|
123
|
-
border-radius: 5px;
|
|
124
|
-
background: transparent;
|
|
125
|
-
color: inherit;
|
|
126
|
-
font-size: 12px;
|
|
127
|
-
text-align: left;
|
|
128
|
-
}
|
|
129
|
-
.bb-world-canvas-ui .bb-world-canvas-sky-option:hover,
|
|
130
|
-
.bb-world-canvas-ui .bb-world-canvas-sky-option[aria-checked="true"] { background: #e5f8e1; }
|
|
106
|
+
.bb-world-canvas-ui .bb-world-canvas-sky-icon svg { display: block; width: 23px; height: 23px; }
|
|
131
107
|
|
|
132
108
|
.bb-world-canvas-ui .bb-world-canvas-quests {
|
|
133
109
|
position: absolute;
|
|
@@ -147,28 +123,7 @@
|
|
|
147
123
|
min-width: 0;
|
|
148
124
|
margin: 0;
|
|
149
125
|
padding: 7px 10px 7px 8px;
|
|
150
|
-
border: 1px solid rgb(255 255 255 / 18%);
|
|
151
|
-
border-left: 3px solid #9be891;
|
|
152
|
-
border-radius: 4px;
|
|
153
|
-
background: linear-gradient(110deg, rgb(13 25 46 / 88%), rgb(13 25 46 / 72%));
|
|
154
|
-
color: #fff;
|
|
155
|
-
font-size: 12px;
|
|
156
|
-
line-height: 18px;
|
|
157
126
|
box-shadow: 0 3px 12px #0d192e18;
|
|
158
|
-
backdrop-filter: blur(5px);
|
|
159
|
-
}
|
|
160
|
-
.bb-world-canvas-ui .bb-world-canvas-quest-symbol {
|
|
161
|
-
display: grid;
|
|
162
|
-
place-items: center;
|
|
163
|
-
flex: none;
|
|
164
|
-
width: 18px;
|
|
165
|
-
height: 18px;
|
|
166
|
-
border: 1px solid #9be89170;
|
|
167
|
-
border-radius: 3px;
|
|
168
|
-
background: #9be89112;
|
|
169
|
-
color: #b5f2ab;
|
|
170
|
-
font-size: 11px;
|
|
171
|
-
font-weight: 700;
|
|
172
127
|
}
|
|
173
128
|
.bb-world-canvas-ui .bb-world-canvas-quest-text { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
|
|
174
129
|
/* A quest with a way down (候補の確認, 区画の入口) is pressable as a whole row even though the quest list lets
|
|
@@ -181,7 +136,7 @@
|
|
|
181
136
|
}
|
|
182
137
|
.bb-world-canvas-ui .bb-world-canvas-quest.has-way:hover,
|
|
183
138
|
.bb-world-canvas-ui .bb-world-canvas-quest.has-way:focus-within {
|
|
184
|
-
border-color:
|
|
139
|
+
border-color: var(--bb-notification-accent);
|
|
185
140
|
background: linear-gradient(110deg, rgb(20 44 62 / 94%), rgb(20 44 62 / 84%));
|
|
186
141
|
}
|
|
187
142
|
.bb-world-canvas-ui .bb-world-canvas-quest a,
|
|
@@ -191,7 +146,7 @@
|
|
|
191
146
|
padding: 0;
|
|
192
147
|
border: 0;
|
|
193
148
|
background: none;
|
|
194
|
-
color:
|
|
149
|
+
color: var(--bb-notification-symbol-text);
|
|
195
150
|
font: inherit;
|
|
196
151
|
text-decoration: underline;
|
|
197
152
|
text-underline-offset: 2px;
|
|
@@ -205,7 +160,7 @@
|
|
|
205
160
|
.bb-world-canvas-ui .bb-world-canvas-quest a:focus-visible,
|
|
206
161
|
.bb-world-canvas-ui .bb-world-canvas-quest-action:focus-visible { outline: none; }
|
|
207
162
|
.bb-world-canvas-ui .bb-world-canvas-quest a:focus-visible::before,
|
|
208
|
-
.bb-world-canvas-ui .bb-world-canvas-quest-action:focus-visible::before { outline: 2px solid
|
|
163
|
+
.bb-world-canvas-ui .bb-world-canvas-quest-action:focus-visible::before { outline: 2px solid var(--bb-notification-symbol-text); outline-offset: 1px; }
|
|
209
164
|
/* A quest with nowhere to go: flat and dashed, so it reads as a sign, not a button, with its reason. */
|
|
210
165
|
.bb-world-canvas-ui .bb-world-canvas-quest.is-static {
|
|
211
166
|
border-style: dashed;
|