@unson/brainbase-mcp 0.43.0 → 0.44.1
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/meeting-minutes.css +122 -0
- package/ui/meeting-minutes.js +316 -0
- package/ui/objective-editor.js +47 -11
- 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
|
@@ -391,6 +391,7 @@ export class CanonicalTaskService {
|
|
|
391
391
|
auditRepository;
|
|
392
392
|
policy;
|
|
393
393
|
operationRepository;
|
|
394
|
+
readiness;
|
|
394
395
|
clock;
|
|
395
396
|
baseUrl;
|
|
396
397
|
constructor(options) {
|
|
@@ -400,6 +401,14 @@ export class CanonicalTaskService {
|
|
|
400
401
|
this.auditRepository = options.auditRepository;
|
|
401
402
|
this.policy = options.policy ?? { authorize: () => undefined };
|
|
402
403
|
this.operationRepository = options.operationRepository;
|
|
404
|
+
if (options.readiness != null && typeof options.readiness.assertMutationReady !== 'function') {
|
|
405
|
+
throw new Error('Canonical Task readiness must provide assertMutationReady()');
|
|
406
|
+
}
|
|
407
|
+
this.readiness = options.readiness ?? undefined;
|
|
408
|
+
if ((this.repository.requiresReadiness === true || this.operationRepository?.requiresReadiness === true)
|
|
409
|
+
&& !this.readiness) {
|
|
410
|
+
throw new Error('Canonical Task readiness is required for durable persistence or operation coordination');
|
|
411
|
+
}
|
|
403
412
|
this.clock = options.clock ?? (() => new Date());
|
|
404
413
|
this.baseUrl = options.baseUrl;
|
|
405
414
|
if (typeof options.baseUrl === 'string' && options.baseUrl && !validHttpUrl(options.baseUrl)) {
|
|
@@ -447,10 +456,12 @@ export class CanonicalTaskService {
|
|
|
447
456
|
const normalizedContext = await this.normalizeContext(context);
|
|
448
457
|
const clientKey = this.requireIdempotencyKey(normalizedContext);
|
|
449
458
|
const payload = this.normalizeCreateInput(input);
|
|
459
|
+
await this.assertMutationReady();
|
|
450
460
|
await this.authorize('create', normalizedContext, undefined, payload);
|
|
451
461
|
const operation = operationKey(normalizedContext, clientKey, 'api:');
|
|
452
462
|
const inputFingerprint = fingerprint(payload);
|
|
453
463
|
const recover = async () => {
|
|
464
|
+
await this.assertMutationReady();
|
|
454
465
|
const existing = await this.read(() => this.repository.findByIdempotencyKey(operation, ...this.scopeArgs(normalizedContext)));
|
|
455
466
|
if (!existing)
|
|
456
467
|
return { recovered: false };
|
|
@@ -469,6 +480,7 @@ export class CanonicalTaskService {
|
|
|
469
480
|
const recovered = await recover();
|
|
470
481
|
if (recovered.recovered && recovered.result)
|
|
471
482
|
return recovered.result;
|
|
483
|
+
await this.assertMutationReady();
|
|
472
484
|
const created = await this.read(() => this.repository.create({
|
|
473
485
|
...payload,
|
|
474
486
|
status: 'pending',
|
|
@@ -554,15 +566,24 @@ export class CanonicalTaskService {
|
|
|
554
566
|
? expectedVersionOrInput
|
|
555
567
|
: expectedVersionOrInput.expected_version);
|
|
556
568
|
const clientKey = this.requireIdempotencyKey(normalizedContext);
|
|
569
|
+
await this.assertMutationReady();
|
|
557
570
|
// A prepared-delete coordinator owns the durable operation lookup. Do not
|
|
558
571
|
// require the row to remain visible before entering it: a completed
|
|
559
572
|
// operation may legitimately recover after the delete removed the row.
|
|
560
573
|
// The fallback path still performs the ordinary read and authorization
|
|
561
574
|
// checks before invoking the local operation runner.
|
|
562
|
-
if (normalizedContext.storageScope !== undefined)
|
|
563
|
-
await this.authorize('delete', normalizedContext);
|
|
564
575
|
let task = null;
|
|
565
|
-
if (
|
|
576
|
+
if (this.operationRepository?.executePreparedDelete) {
|
|
577
|
+
// Read and authorize a visible task before entering the coordinator. A
|
|
578
|
+
// completed replay can legitimately have no row, so absence is left to
|
|
579
|
+
// the durable snapshot reauthorization below.
|
|
580
|
+
task = await this.read(() => this.repository.get(normalizedId, ...this.scopeArgs(normalizedContext)));
|
|
581
|
+
if (task) {
|
|
582
|
+
await this.authorize('delete', normalizedContext, task);
|
|
583
|
+
this.assertVersion(task, version);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
else {
|
|
566
587
|
task = await this.read(() => this.repository.get(normalizedId, ...this.scopeArgs(normalizedContext)));
|
|
567
588
|
if (!task)
|
|
568
589
|
throw new CanonicalTaskError('task_not_found', 'Task was not found', 404, { task_id: normalizedId });
|
|
@@ -595,6 +616,7 @@ export class CanonicalTaskService {
|
|
|
595
616
|
version: version + 1,
|
|
596
617
|
};
|
|
597
618
|
const prepare = async () => {
|
|
619
|
+
await this.assertMutationReady();
|
|
598
620
|
const current = await this.read(() => this.repository.get(normalizedId, ...this.scopeArgs(normalizedContext)));
|
|
599
621
|
if (!current)
|
|
600
622
|
throw new CanonicalTaskError('task_not_found', 'Task was not found', 404, { task_id: normalizedId });
|
|
@@ -614,6 +636,7 @@ export class CanonicalTaskService {
|
|
|
614
636
|
...(normalizedContext.storageScope === undefined ? {} : { storage_scope: normalizedContext.storageScope }),
|
|
615
637
|
actor: normalizedContext.principal,
|
|
616
638
|
auth_source: normalizedContext.authSource ?? null,
|
|
639
|
+
task: current,
|
|
617
640
|
},
|
|
618
641
|
};
|
|
619
642
|
};
|
|
@@ -623,6 +646,7 @@ export class CanonicalTaskService {
|
|
|
623
646
|
return current;
|
|
624
647
|
});
|
|
625
648
|
const removeTask = async (current) => {
|
|
649
|
+
await this.assertMutationReady();
|
|
626
650
|
const taskToRemove = current ?? await this.read(() => this.repository.get(normalizedId, ...this.scopeArgs(normalizedContext)));
|
|
627
651
|
if (!taskToRemove)
|
|
628
652
|
throw new CanonicalTaskError('task_not_found', 'Task was not found', 404, { task_id: normalizedId });
|
|
@@ -634,6 +658,26 @@ export class CanonicalTaskService {
|
|
|
634
658
|
this.assertVersion(taskToRemove, version);
|
|
635
659
|
await this.read(() => this.repository.delete(normalizedId, version, ...this.scopeArgs(normalizedContext)));
|
|
636
660
|
};
|
|
661
|
+
const authorizeReplay = async (authorizationSnapshot) => {
|
|
662
|
+
await this.assertMutationReady();
|
|
663
|
+
const snapshotTask = authorizationSnapshot?.task;
|
|
664
|
+
if (!snapshotTask || typeof snapshotTask !== 'object' || Array.isArray(snapshotTask)) {
|
|
665
|
+
throw new CanonicalTaskError('canonical_task_authorization_snapshot_unavailable', 'Completed Canonical Task delete operation has no authorization snapshot', 503);
|
|
666
|
+
}
|
|
667
|
+
const taskSnapshot = snapshotTask;
|
|
668
|
+
if (authorizationSnapshot.task_id !== normalizedId
|
|
669
|
+
|| authorizationSnapshot.task_version !== version
|
|
670
|
+
|| taskSnapshot.id !== normalizedId
|
|
671
|
+
|| taskSnapshot.version !== version) {
|
|
672
|
+
throw new CanonicalTaskError('canonical_task_authorization_snapshot_unavailable', 'Completed Canonical Task delete operation has an invalid authorization snapshot', 503);
|
|
673
|
+
}
|
|
674
|
+
const snapshotScope = authorizationSnapshot.storage_scope;
|
|
675
|
+
if (snapshotScope !== normalizedContext.storageScope
|
|
676
|
+
&& (snapshotScope !== undefined || normalizedContext.storageScope !== undefined)) {
|
|
677
|
+
throw new CanonicalTaskError('task_not_found', 'Task was not found', 404);
|
|
678
|
+
}
|
|
679
|
+
await this.authorize('delete', normalizedContext, taskSnapshot);
|
|
680
|
+
};
|
|
637
681
|
let deleted;
|
|
638
682
|
if (this.operationRepository?.executePreparedDelete) {
|
|
639
683
|
deleted = await this.operationRepository.executePreparedDelete({
|
|
@@ -647,6 +691,7 @@ export class CanonicalTaskService {
|
|
|
647
691
|
prepare,
|
|
648
692
|
findTask,
|
|
649
693
|
removeTask,
|
|
694
|
+
authorizeReplay,
|
|
650
695
|
projectResult: projectTaskResult,
|
|
651
696
|
});
|
|
652
697
|
}
|
|
@@ -697,6 +742,7 @@ export class CanonicalTaskService {
|
|
|
697
742
|
async versionedMutation(input) {
|
|
698
743
|
const taskId = normalizeString(input.taskId, 'task_id', { required: true, max: 200 });
|
|
699
744
|
const expectedVersion = this.requireExpectedVersion(input.expectedVersion);
|
|
745
|
+
await this.assertMutationReady();
|
|
700
746
|
const current = await this.read(() => this.repository.get(taskId, ...this.scopeArgs(input.context)));
|
|
701
747
|
if (!current)
|
|
702
748
|
throw new CanonicalTaskError('task_not_found', 'Task was not found', 404, { task_id: taskId });
|
|
@@ -740,6 +786,7 @@ export class CanonicalTaskService {
|
|
|
740
786
|
}
|
|
741
787
|
}
|
|
742
788
|
const recover = async () => {
|
|
789
|
+
await this.assertMutationReady();
|
|
743
790
|
const latest = await this.read(() => this.repository.get(taskId, ...this.scopeArgs(input.context)));
|
|
744
791
|
if (!latest)
|
|
745
792
|
throw new CanonicalTaskError('task_not_found', 'Task was not found', 404, { task_id: taskId });
|
|
@@ -756,6 +803,7 @@ export class CanonicalTaskService {
|
|
|
756
803
|
return { recovered: false };
|
|
757
804
|
};
|
|
758
805
|
const run = async () => {
|
|
806
|
+
await this.assertMutationReady();
|
|
759
807
|
const latest = await this.read(() => this.repository.get(taskId, ...this.scopeArgs(input.context)));
|
|
760
808
|
if (!latest)
|
|
761
809
|
throw new CanonicalTaskError('task_not_found', 'Task was not found', 404, { task_id: taskId });
|
|
@@ -970,6 +1018,10 @@ export class CanonicalTaskService {
|
|
|
970
1018
|
async authorize(action, context, task, input) {
|
|
971
1019
|
await this.policy.authorize({ action, context, task, input });
|
|
972
1020
|
}
|
|
1021
|
+
async assertMutationReady() {
|
|
1022
|
+
if (this.readiness)
|
|
1023
|
+
await this.readiness.assertMutationReady();
|
|
1024
|
+
}
|
|
973
1025
|
async scopeFilters(operation, context, filters) {
|
|
974
1026
|
if (!this.policy.scopeFilters)
|
|
975
1027
|
return filters;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
type Manifest = Record<string, string>;
|
|
2
|
+
export interface CanonicalTaskStoreConfig {
|
|
3
|
+
schemaVersion: string;
|
|
4
|
+
/** The committed manifest, frozen. Tenant-specific keys stay as the tenant named them. */
|
|
5
|
+
manifest: Readonly<Manifest>;
|
|
6
|
+
identityHash: string;
|
|
7
|
+
manifestPath: string;
|
|
8
|
+
}
|
|
9
|
+
export interface CanonicalTaskStoreConfigOptions {
|
|
10
|
+
/** The tenant's committed store manifest (JSON object of non-empty strings). */
|
|
11
|
+
manifestPath: string;
|
|
12
|
+
/** Keys the tenant requires. `schema_version` is always required. */
|
|
13
|
+
requiredKeys?: string[];
|
|
14
|
+
/** Values the manifest must keep. A tenant pins its store identity here. */
|
|
15
|
+
expectedIdentity?: Record<string, string>;
|
|
16
|
+
/** Environment variables that must not be set, so the identity cannot be overridden at runtime. */
|
|
17
|
+
forbiddenEnvOverrides?: string[];
|
|
18
|
+
env?: Record<string, string | undefined>;
|
|
19
|
+
}
|
|
20
|
+
export declare function canonicalTaskStoreManifestJson(manifest: Record<string, unknown>): string;
|
|
21
|
+
/**
|
|
22
|
+
* Loads the store manifest that names one Canonical Task store. Its hash
|
|
23
|
+
* binds persisted readiness to this exact store identity.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createCanonicalTaskStoreConfig({ manifestPath, requiredKeys, expectedIdentity, forbiddenEnvOverrides, env, }: CanonicalTaskStoreConfigOptions): CanonicalTaskStoreConfig;
|
|
26
|
+
export type CanonicalTaskBackend = 'disabled' | 'postgres';
|
|
27
|
+
export declare function resolveCanonicalTaskBackend(value?: unknown): CanonicalTaskBackend;
|
|
28
|
+
export declare function canonicalTaskBackendIdentityHash(storeConfig: {
|
|
29
|
+
identityHash: string;
|
|
30
|
+
}, backend?: unknown): string;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
export function canonicalTaskStoreManifestJson(manifest) {
|
|
5
|
+
return JSON.stringify(Object.fromEntries(Object.keys(manifest).sort().map((key) => [key, manifest[key]])));
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Loads the store manifest that names one Canonical Task store. Its hash
|
|
9
|
+
* binds persisted readiness to this exact store identity.
|
|
10
|
+
*/
|
|
11
|
+
export function createCanonicalTaskStoreConfig({ manifestPath, requiredKeys = [], expectedIdentity = {}, forbiddenEnvOverrides = [], env = process.env, }) {
|
|
12
|
+
if (typeof manifestPath !== 'string' || !manifestPath)
|
|
13
|
+
throw new Error('Canonical Task store manifest path is required');
|
|
14
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
15
|
+
if (!manifest || typeof manifest !== 'object' || Array.isArray(manifest)) {
|
|
16
|
+
throw new Error('Canonical Task store manifest must be a JSON object');
|
|
17
|
+
}
|
|
18
|
+
for (const [key, value] of Object.entries(manifest)) {
|
|
19
|
+
if (typeof value !== 'string' || !value.trim()) {
|
|
20
|
+
throw new Error(`Canonical Task store manifest value ${key} must be a non-empty string`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
for (const key of new Set(['schema_version', ...requiredKeys])) {
|
|
24
|
+
if (typeof manifest[key] !== 'string' || !manifest[key].trim()) {
|
|
25
|
+
throw new Error(`Canonical Task store manifest requires ${key}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
for (const [key, expected] of Object.entries(expectedIdentity)) {
|
|
29
|
+
if (manifest[key] !== expected) {
|
|
30
|
+
throw new Error(`Canonical Task manifest ${key} does not match the fixed canonical identity`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (forbiddenEnvOverrides.some((key) => env[key] !== undefined)) {
|
|
34
|
+
throw new Error('Canonical Task identity overrides are forbidden; use the committed manifest');
|
|
35
|
+
}
|
|
36
|
+
return Object.freeze({
|
|
37
|
+
schemaVersion: manifest.schema_version,
|
|
38
|
+
manifest: Object.freeze({ ...manifest }),
|
|
39
|
+
identityHash: createHash('sha256').update(canonicalTaskStoreManifestJson(manifest)).digest('hex'),
|
|
40
|
+
manifestPath: resolve(manifestPath),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
export function resolveCanonicalTaskBackend(value = process.env.CANONICAL_TASK_BACKEND) {
|
|
44
|
+
const backend = typeof value === 'string' && value.trim() ? value.trim() : 'disabled';
|
|
45
|
+
if (backend !== 'disabled' && backend !== 'postgres') {
|
|
46
|
+
throw new Error('CANONICAL_TASK_BACKEND must be disabled or postgres');
|
|
47
|
+
}
|
|
48
|
+
return backend;
|
|
49
|
+
}
|
|
50
|
+
export function canonicalTaskBackendIdentityHash(storeConfig, backend = resolveCanonicalTaskBackend()) {
|
|
51
|
+
const resolved = resolveCanonicalTaskBackend(backend);
|
|
52
|
+
return createHash('sha256').update(`${storeConfig.identityHash}:backend:${resolved}`).digest('hex');
|
|
53
|
+
}
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Parser - brainbaseの設定ファイル(YAML)を読み取り、統合ビューを提供
|
|
3
|
+
*/
|
|
4
|
+
export type CatalogMode = 'required' | 'disabled';
|
|
5
|
+
export interface ConfigParserLogger {
|
|
6
|
+
debug(message: string, data?: Record<string, unknown>): void;
|
|
7
|
+
error(message: string, data?: Error | (Record<string, unknown> & {
|
|
8
|
+
error?: unknown;
|
|
9
|
+
})): void;
|
|
10
|
+
}
|
|
11
|
+
export interface ConfigParserOptions {
|
|
12
|
+
configPath: string;
|
|
13
|
+
slackDir: string;
|
|
14
|
+
brainbaseRoot: string;
|
|
15
|
+
projectsRoot: string;
|
|
16
|
+
catalogMode?: CatalogMode;
|
|
17
|
+
logger?: ConfigParserLogger;
|
|
18
|
+
}
|
|
19
|
+
export interface ProjectLocalConfig {
|
|
20
|
+
path?: string;
|
|
21
|
+
glob_include?: string[];
|
|
22
|
+
[key: string]: unknown;
|
|
23
|
+
}
|
|
24
|
+
export interface ProjectGitHubConfig {
|
|
25
|
+
owner?: string;
|
|
26
|
+
repo?: string;
|
|
27
|
+
branch?: string;
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
export interface ProjectAirtableConfig {
|
|
31
|
+
base_id?: string;
|
|
32
|
+
base_name?: string;
|
|
33
|
+
[key: string]: unknown;
|
|
34
|
+
}
|
|
35
|
+
export interface ProjectConfig {
|
|
36
|
+
id?: string;
|
|
37
|
+
name?: string;
|
|
38
|
+
catalog_version?: number;
|
|
39
|
+
emoji?: string;
|
|
40
|
+
archived?: boolean;
|
|
41
|
+
local?: ProjectLocalConfig;
|
|
42
|
+
github?: ProjectGitHubConfig;
|
|
43
|
+
airtable?: ProjectAirtableConfig;
|
|
44
|
+
capabilities?: unknown;
|
|
45
|
+
people?: unknown;
|
|
46
|
+
organization?: unknown;
|
|
47
|
+
created_by?: unknown;
|
|
48
|
+
success_criteria?: unknown;
|
|
49
|
+
project_code?: unknown;
|
|
50
|
+
[key: string]: unknown;
|
|
51
|
+
}
|
|
52
|
+
export interface SlackWorkspace {
|
|
53
|
+
name?: string;
|
|
54
|
+
id?: string;
|
|
55
|
+
projects?: string[];
|
|
56
|
+
[key: string]: unknown;
|
|
57
|
+
}
|
|
58
|
+
export type SlackWorkspaces = Record<string, SlackWorkspace>;
|
|
59
|
+
export interface SlackChannel {
|
|
60
|
+
project_id?: string;
|
|
61
|
+
channel_id?: string;
|
|
62
|
+
channel_name?: string;
|
|
63
|
+
type?: string;
|
|
64
|
+
workspace?: string;
|
|
65
|
+
[key: string]: unknown;
|
|
66
|
+
}
|
|
67
|
+
export interface SlackMember {
|
|
68
|
+
slack_id?: string;
|
|
69
|
+
brainbase_name?: string;
|
|
70
|
+
[key: string]: unknown;
|
|
71
|
+
}
|
|
72
|
+
export interface ProjectCatalog {
|
|
73
|
+
root: string;
|
|
74
|
+
projects: ProjectConfig[];
|
|
75
|
+
}
|
|
76
|
+
export interface GitHubMapping {
|
|
77
|
+
project_id?: string;
|
|
78
|
+
owner?: string;
|
|
79
|
+
repo?: string;
|
|
80
|
+
branch: string;
|
|
81
|
+
url: string;
|
|
82
|
+
}
|
|
83
|
+
export interface AirtableMapping {
|
|
84
|
+
project_id?: string;
|
|
85
|
+
base_id?: string;
|
|
86
|
+
base_name?: string;
|
|
87
|
+
url: string;
|
|
88
|
+
}
|
|
89
|
+
export interface PluginSettings {
|
|
90
|
+
enabled: string[];
|
|
91
|
+
disabled: string[];
|
|
92
|
+
}
|
|
93
|
+
export interface OrganizationConfig {
|
|
94
|
+
[key: string]: unknown;
|
|
95
|
+
}
|
|
96
|
+
export interface DependencyConfig {
|
|
97
|
+
[key: string]: unknown;
|
|
98
|
+
}
|
|
99
|
+
export interface NotificationsConfig {
|
|
100
|
+
channels?: Record<string, unknown>;
|
|
101
|
+
dnd?: Record<string, unknown>;
|
|
102
|
+
[key: string]: unknown;
|
|
103
|
+
}
|
|
104
|
+
export interface ConfigSnapshot {
|
|
105
|
+
slack: {
|
|
106
|
+
workspaces: SlackWorkspaces;
|
|
107
|
+
channels: SlackChannel[];
|
|
108
|
+
members: SlackMember[];
|
|
109
|
+
};
|
|
110
|
+
projects: ProjectCatalog;
|
|
111
|
+
github: GitHubMapping[];
|
|
112
|
+
airtable: AirtableMapping[];
|
|
113
|
+
plugins: PluginSettings;
|
|
114
|
+
}
|
|
115
|
+
export interface UnifiedChannel {
|
|
116
|
+
id?: string;
|
|
117
|
+
name?: string;
|
|
118
|
+
type: string;
|
|
119
|
+
workspace?: string;
|
|
120
|
+
}
|
|
121
|
+
export interface UnifiedGitHubMapping {
|
|
122
|
+
owner?: string;
|
|
123
|
+
repo?: string;
|
|
124
|
+
branch: string;
|
|
125
|
+
url: string;
|
|
126
|
+
paths: string[] | null;
|
|
127
|
+
}
|
|
128
|
+
export interface UnifiedProject {
|
|
129
|
+
id: string;
|
|
130
|
+
emoji: string | null;
|
|
131
|
+
archived: boolean;
|
|
132
|
+
channels: UnifiedChannel[];
|
|
133
|
+
github: UnifiedGitHubMapping | null;
|
|
134
|
+
}
|
|
135
|
+
export interface UnifiedWorkspace {
|
|
136
|
+
key: string;
|
|
137
|
+
name?: string;
|
|
138
|
+
id?: string;
|
|
139
|
+
projects: UnifiedProject[];
|
|
140
|
+
}
|
|
141
|
+
export interface UnifiedView {
|
|
142
|
+
workspaces: UnifiedWorkspace[];
|
|
143
|
+
orphanedChannels: Array<{
|
|
144
|
+
id?: string;
|
|
145
|
+
name?: string;
|
|
146
|
+
workspace?: string;
|
|
147
|
+
project_id?: string;
|
|
148
|
+
}>;
|
|
149
|
+
orphanedProjects: Array<{
|
|
150
|
+
id?: string;
|
|
151
|
+
hasGithub: boolean;
|
|
152
|
+
channelCount: number;
|
|
153
|
+
}>;
|
|
154
|
+
}
|
|
155
|
+
export type ConfigSourceStatus = 'not_applicable' | 'not_loaded' | 'loaded' | 'missing' | 'invalid';
|
|
156
|
+
export interface IntegrityIssue {
|
|
157
|
+
type: string;
|
|
158
|
+
severity: 'error' | 'warning' | 'info';
|
|
159
|
+
message: string;
|
|
160
|
+
source: string;
|
|
161
|
+
}
|
|
162
|
+
export interface IntegrityReport {
|
|
163
|
+
applicability: 'applicable' | 'not_applicable';
|
|
164
|
+
source: {
|
|
165
|
+
status: ConfigSourceStatus;
|
|
166
|
+
path: string;
|
|
167
|
+
mode: CatalogMode;
|
|
168
|
+
};
|
|
169
|
+
issues: IntegrityIssue[];
|
|
170
|
+
summary: {
|
|
171
|
+
total: number;
|
|
172
|
+
errors: number;
|
|
173
|
+
warnings: number;
|
|
174
|
+
info: number;
|
|
175
|
+
};
|
|
176
|
+
stats: {
|
|
177
|
+
workspaces: number;
|
|
178
|
+
channels: number;
|
|
179
|
+
members: number;
|
|
180
|
+
projects: number;
|
|
181
|
+
github: number;
|
|
182
|
+
airtable: number;
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
interface RootConfig {
|
|
186
|
+
projects?: ProjectConfig[];
|
|
187
|
+
plugins?: Partial<PluginSettings>;
|
|
188
|
+
organizations?: OrganizationConfig[];
|
|
189
|
+
dependencies?: DependencyConfig;
|
|
190
|
+
notifications?: NotificationsConfig;
|
|
191
|
+
}
|
|
192
|
+
export declare class ConfigParser {
|
|
193
|
+
/**
|
|
194
|
+
* Construct a parser with every filesystem boundary supplied by the host.
|
|
195
|
+
*
|
|
196
|
+
* The OSS package deliberately has no workspace or repository defaults. A
|
|
197
|
+
* host that needs compatibility defaults must provide them in its adapter.
|
|
198
|
+
*
|
|
199
|
+
* @param paths filesystem boundaries and optional catalog mode supplied by the host
|
|
200
|
+
*/
|
|
201
|
+
configPath: string;
|
|
202
|
+
slackDir: string;
|
|
203
|
+
brainbaseRoot: string;
|
|
204
|
+
projectsRoot: string;
|
|
205
|
+
workspaceRoot: string;
|
|
206
|
+
catalogMode: CatalogMode;
|
|
207
|
+
logger: ConfigParserLogger;
|
|
208
|
+
private _configSourceStatus;
|
|
209
|
+
private _configCache;
|
|
210
|
+
private _configPromise;
|
|
211
|
+
constructor(paths: ConfigParserOptions);
|
|
212
|
+
/**
|
|
213
|
+
* @template T
|
|
214
|
+
* @param {string} filePath
|
|
215
|
+
* @param {T} defaultValue
|
|
216
|
+
* @param {string} [label]
|
|
217
|
+
* @returns {Promise<T>}
|
|
218
|
+
*/
|
|
219
|
+
_loadYamlFile<T>(filePath: string, defaultValue: T, label?: string): Promise<T>;
|
|
220
|
+
/**
|
|
221
|
+
* @template T
|
|
222
|
+
* @param {string} filename
|
|
223
|
+
* @param {T} defaultValue
|
|
224
|
+
* @returns {Promise<T>}
|
|
225
|
+
*/
|
|
226
|
+
_loadSlackYaml<T>(filename: string, defaultValue: T): Promise<T>;
|
|
227
|
+
_loadConfig(): Promise<RootConfig>;
|
|
228
|
+
/**
|
|
229
|
+
* SPEC-settings-phase0-guards INV-4: ConfigService.write 後に呼ぶことで stale cache を回避
|
|
230
|
+
*/
|
|
231
|
+
invalidateCache(): void;
|
|
232
|
+
/**
|
|
233
|
+
* @param {ProjectConfig[]} [projects]
|
|
234
|
+
* @returns {ProjectConfig[]}
|
|
235
|
+
*/
|
|
236
|
+
_expandProjectPaths(projects?: ProjectConfig[]): ProjectConfig[];
|
|
237
|
+
/**
|
|
238
|
+
* Slackワークスペース一覧を取得
|
|
239
|
+
*/
|
|
240
|
+
getWorkspaces(): Promise<SlackWorkspaces>;
|
|
241
|
+
/**
|
|
242
|
+
* Slackチャンネル一覧を取得
|
|
243
|
+
*/
|
|
244
|
+
getChannels(): Promise<SlackChannel[]>;
|
|
245
|
+
/**
|
|
246
|
+
* Slackメンバー一覧を取得
|
|
247
|
+
*/
|
|
248
|
+
getMembers(): Promise<SlackMember[]>;
|
|
249
|
+
/**
|
|
250
|
+
* プロジェクト設定(config.yml)を取得
|
|
251
|
+
*/
|
|
252
|
+
getProjects(): Promise<ProjectCatalog>;
|
|
253
|
+
/**
|
|
254
|
+
* GitHubマッピングを取得(config.ymlから抽出)
|
|
255
|
+
*/
|
|
256
|
+
getGitHubMappings(): Promise<GitHubMapping[]>;
|
|
257
|
+
/**
|
|
258
|
+
* Airtableマッピングを取得(config.ymlから抽出)
|
|
259
|
+
*/
|
|
260
|
+
getAirtableMappings(): Promise<AirtableMapping[]>;
|
|
261
|
+
/**
|
|
262
|
+
* UI Plugins設定を取得(config.ymlから抽出)
|
|
263
|
+
* @returns {Promise<any>} { enabled: string[] } - 有効なプラグインID一覧
|
|
264
|
+
*/
|
|
265
|
+
getPlugins(): Promise<PluginSettings>;
|
|
266
|
+
/**
|
|
267
|
+
* 統合ビュー: Workspace → Project → Slack/GitHub/Airtable の関係を一覧
|
|
268
|
+
*/
|
|
269
|
+
getUnifiedView(): Promise<UnifiedView>;
|
|
270
|
+
/**
|
|
271
|
+
* Organizations(法人)設定を取得
|
|
272
|
+
* @returns {Promise<any[]>} 法人一覧
|
|
273
|
+
*/
|
|
274
|
+
getOrganizations(): Promise<OrganizationConfig[]>;
|
|
275
|
+
/**
|
|
276
|
+
* Dependencies(依存関係)設定を取得
|
|
277
|
+
* @returns {Promise<any>} 依存関係マッピング
|
|
278
|
+
*/
|
|
279
|
+
getDependencies(): Promise<DependencyConfig>;
|
|
280
|
+
/**
|
|
281
|
+
* Notifications(通知)設定を取得
|
|
282
|
+
* @returns {Promise<any>} 通知設定
|
|
283
|
+
*/
|
|
284
|
+
getNotifications(): Promise<NotificationsConfig>;
|
|
285
|
+
/**
|
|
286
|
+
* 全設定を統合して取得
|
|
287
|
+
*/
|
|
288
|
+
getAll(): Promise<ConfigSnapshot>;
|
|
289
|
+
/**
|
|
290
|
+
* 整合性チェック
|
|
291
|
+
* - チャンネルに定義されているが、プロジェクトに存在しないproject_id
|
|
292
|
+
* - ワークスペースに定義されているが、チャンネルがないワークスペース
|
|
293
|
+
* - 重複したSlack ID
|
|
294
|
+
* - GitHubマッピングの検証
|
|
295
|
+
*/
|
|
296
|
+
checkIntegrity(): Promise<IntegrityReport>;
|
|
297
|
+
}
|
|
298
|
+
export {};
|