@unson/brainbase-mcp 0.3.1 → 0.4.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.
package/README.md CHANGED
@@ -8,6 +8,35 @@ Ontology 2.0.0は、ローカルファイルへ持ち運べる意味契約に、
8
8
 
9
9
  このリポジトリに、社内BrainbaseのUI、セッション実行基盤、xterm転送、ワークフロー管制、SNS運用、ホスト型バックエンド、Infisical設定、雲孫の社内データは含みません。それらは社内版`brainbase-unson`の範囲です。
10
10
 
11
+ ## Judgment DAG公開契約
12
+
13
+ Judgment DAGの型と副作用のない事前検証は、公開`./judgment-dag` subpath(`@unson/brainbase-mcp/judgment-dag`)から利用できます。機械可読の4つの契約ファイルは次のとおりです。
14
+
15
+ - `contracts/judgment-dag/schema.json`
16
+ - `contracts/judgment-dag/fixture.json`
17
+ - `contracts/judgment-dag/source-lock.json`
18
+ - `contracts/judgment-dag/digest.json`
19
+
20
+ 最小の検証例:
21
+
22
+ ```ts
23
+ import { readFileSync } from 'node:fs';
24
+ import { validateJudgmentDAG } from '@unson/brainbase-mcp/judgment-dag';
25
+
26
+ const fixtureUrl = import.meta.resolve(
27
+ '@unson/brainbase-mcp/contracts/judgment-dag/fixture.json'
28
+ );
29
+ const dag = JSON.parse(readFileSync(new URL(fixtureUrl), 'utf8'));
30
+ const checked = validateJudgmentDAG(dag);
31
+ console.log(checked.execution_order); // deterministic node-ID ascending tie-break
32
+ ```
33
+
34
+ `node.depends_on`と`relation: "depends_on"` edgeは完全なmirrorであり、missing・cycle・reverse-layer・scope不一致は実行前に拒否されます。
35
+
36
+ 配布済みconsumerは、installed package rootから`source-lock.sources`と`digest.files`の各package-relative pathをSHA-256で再計算し、`digest.files`をpath順に`path + NUL + sha256 + LF`で連結したaggregate digestまでreadbackします。`source-lock`はimmutableな`repository`と`accepted_base_commit`を示し、`src/`のような非同梱ファイルはhash対象にしません。
37
+
38
+ この契約はrunner、artifact、execution log、replay/evaluation、Execution/Evaluation mutation protectionを含まないJ0-2非目標のcore sliceです。
39
+
11
40
  ## マニュアル
12
41
 
13
42
  Read the public onboarding manual at [brainbase.pages.dev](https://brainbase.pages.dev/). It guides users through five phases: choose one real use case, register approved work context, prove the first value, add only necessary sources, and operationalize Skills, routines, and MCP.
@@ -0,0 +1,32 @@
1
+ {
2
+ "contract": "judgment-dag-core",
3
+ "algorithm": "sha256",
4
+ "canonicalization": "UTF-8 lines sorted by path as path + NUL + sha256 + LF",
5
+ "files": [
6
+ {
7
+ "path": "contracts/judgment-dag/fixture.json",
8
+ "sha256": "c191ea129c55c97d131998698a79f656c900150fb97abb4715aa44d2abca39c5"
9
+ },
10
+ {
11
+ "path": "contracts/judgment-dag/schema.json",
12
+ "sha256": "af783617e76dc3cdc878210311821f9b0e982b31102ab6bf46ad726d5423745d"
13
+ },
14
+ {
15
+ "path": "contracts/judgment-dag/source-lock.json",
16
+ "sha256": "c7b3020fe3952d90bd8ed991f613be66c0798983bb6cc2285a9aefff7ab2f0e9"
17
+ },
18
+ {
19
+ "path": "docs/architecture/judgment-dag-core.md",
20
+ "sha256": "24305aaa97df9c734d468c49f52784e94b77a4f506bae41d482bee05625d7e2a"
21
+ },
22
+ {
23
+ "path": "docs/management/judgment-dag-milestones.md",
24
+ "sha256": "ef51313f33de64f702fd6c86012984bd70cf99eeca5b4f4cfc27f6cb266172bd"
25
+ },
26
+ {
27
+ "path": "README.md",
28
+ "sha256": "7cd5721b9a932f5b43dd01557dfbcd8ea73563d5d23337fabdd322367d678e28"
29
+ }
30
+ ],
31
+ "digest": "fd5587b97cf343290c7d6c78f365d2d78bef668b04578e5ab55c67886ba0e827"
32
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "id": "j0-valid",
3
+ "version": "2026-08-20.1",
4
+ "nodes": [
5
+ { "id": "context.customer", "node_type": "observation", "layer": "context", "scope": { "type": "project", "id": "project-j0-fixture" }, "version": "1.0.0", "description": "customer observation", "depends_on": [], "input_contract": "fixture.input.v1", "output_contract": "fixture.output.v1", "runner_type": "deterministic", "authority": ["fixture-owner"], "confidence": 1, "valid_from": "2026-08-20T00:00:00.000Z", "valid_to": null, "provenance": [{ "source": "j0-fixture", "reference": "context.customer" }], "evaluation": { "criteria": ["context.customer is evaluated"] } },
6
+ { "id": "context.account", "node_type": "observation", "layer": "context", "scope": { "type": "project", "id": "project-j0-fixture" }, "version": "1.0.0", "description": "account observation", "depends_on": [], "input_contract": "fixture.input.v1", "output_contract": "fixture.output.v1", "runner_type": "deterministic", "authority": ["fixture-owner"], "confidence": 1, "valid_from": "2026-08-20T00:00:00.000Z", "valid_to": null, "provenance": [{ "source": "j0-fixture", "reference": "context.account" }], "evaluation": { "criteria": ["context.account is evaluated"] } },
7
+ { "id": "judgment.fit", "node_type": "judgment", "layer": "judgment", "scope": { "type": "project", "id": "project-j0-fixture" }, "version": "1.0.0", "description": "fit judgment", "depends_on": ["context.customer", "context.account"], "input_contract": "fixture.input.v1", "output_contract": "fixture.output.v1", "runner_type": "deterministic", "authority": ["fixture-owner"], "confidence": 1, "valid_from": "2026-08-20T00:00:00.000Z", "valid_to": null, "provenance": [{ "source": "j0-fixture", "reference": "judgment.fit" }], "evaluation": { "criteria": ["judgment.fit is evaluated"] } },
8
+ { "id": "resource.scope", "node_type": "resource", "layer": "resource", "scope": { "type": "project", "id": "project-j0-fixture" }, "version": "1.0.0", "description": "resource scope", "depends_on": ["judgment.fit"], "input_contract": "fixture.input.v1", "output_contract": "fixture.output.v1", "runner_type": "deterministic", "authority": ["fixture-owner"], "confidence": 1, "valid_from": "2026-08-20T00:00:00.000Z", "valid_to": null, "provenance": [{ "source": "j0-fixture", "reference": "resource.scope" }], "evaluation": { "criteria": ["resource.scope is evaluated"] } },
9
+ { "id": "execution.proposal", "node_type": "execution", "layer": "execution", "scope": { "type": "project", "id": "project-j0-fixture" }, "version": "1.0.0", "description": "execution proposal", "depends_on": ["resource.scope"], "input_contract": "fixture.input.v1", "output_contract": "fixture.output.v1", "runner_type": "deterministic", "authority": ["fixture-owner"], "confidence": 1, "valid_from": "2026-08-20T00:00:00.000Z", "valid_to": null, "provenance": [{ "source": "j0-fixture", "reference": "execution.proposal" }], "evaluation": { "criteria": ["execution.proposal is evaluated"] } },
10
+ { "id": "execution.outcome", "node_type": "outcome", "layer": "execution", "scope": { "type": "project", "id": "project-j0-fixture" }, "version": "1.0.0", "description": "execution outcome", "depends_on": ["execution.proposal"], "input_contract": "fixture.input.v1", "output_contract": "fixture.output.v1", "runner_type": "deterministic", "authority": ["fixture-owner"], "confidence": 1, "valid_from": "2026-08-20T00:00:00.000Z", "valid_to": null, "provenance": [{ "source": "j0-fixture", "reference": "execution.outcome" }], "evaluation": { "criteria": ["execution.outcome is evaluated"] } },
11
+ { "id": "evaluation.result", "node_type": "evaluation", "layer": "evaluation", "scope": { "type": "project", "id": "project-j0-fixture" }, "version": "1.0.0", "description": "evaluation result", "depends_on": ["execution.outcome"], "input_contract": "fixture.input.v1", "output_contract": "fixture.output.v1", "runner_type": "deterministic", "authority": ["fixture-owner"], "confidence": 1, "valid_from": "2026-08-20T00:00:00.000Z", "valid_to": null, "provenance": [{ "source": "j0-fixture", "reference": "evaluation.result" }], "evaluation": { "criteria": ["evaluation.result is evaluated"] } }
12
+ ],
13
+ "edges": [
14
+ { "from": "context.customer", "to": "judgment.fit", "relation": "depends_on" },
15
+ { "from": "context.account", "to": "judgment.fit", "relation": "depends_on" },
16
+ { "from": "judgment.fit", "to": "resource.scope", "relation": "depends_on" },
17
+ { "from": "resource.scope", "to": "execution.proposal", "relation": "depends_on" },
18
+ { "from": "execution.proposal", "to": "execution.outcome", "relation": "depends_on" },
19
+ { "from": "execution.outcome", "to": "evaluation.result", "relation": "depends_on" }
20
+ ]
21
+ }
@@ -0,0 +1,80 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/Unson-LLC/brainbase/blob/develop/contracts/judgment-dag/schema.json",
4
+ "title": "Brainbase Judgment DAG core contract",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["id", "version", "nodes", "edges"],
8
+ "properties": {
9
+ "id": { "$ref": "#/$defs/identifier" },
10
+ "version": { "type": "string", "minLength": 1, "pattern": "\\S" },
11
+ "nodes": { "type": "array", "items": { "$ref": "#/$defs/node" } },
12
+ "edges": { "type": "array", "items": { "$ref": "#/$defs/edge" } }
13
+ },
14
+ "$defs": {
15
+ "identifier": {
16
+ "type": "string",
17
+ "minLength": 1,
18
+ "pattern": "^(?![\\s\\S]*[\\u0000-\\u001F\\u007F])(?=[\\s\\S]*\\S)[\\s\\S]+$"
19
+ },
20
+ "metadata": {
21
+ "anyOf": [
22
+ { "type": "string" },
23
+ { "type": "number" },
24
+ { "type": "boolean" },
25
+ { "type": "null" },
26
+ { "type": "array", "items": { "$ref": "#/$defs/metadata" } },
27
+ { "type": "object", "additionalProperties": { "$ref": "#/$defs/metadata" } }
28
+ ]
29
+ },
30
+ "scope": {
31
+ "type": "object",
32
+ "additionalProperties": false,
33
+ "required": ["type", "id"],
34
+ "properties": {
35
+ "type": { "enum": ["personal", "project", "organization"] },
36
+ "id": { "$ref": "#/$defs/identifier" }
37
+ }
38
+ },
39
+ "node": {
40
+ "type": "object",
41
+ "additionalProperties": false,
42
+ "required": ["id", "node_type", "layer", "scope", "version", "description", "depends_on", "input_contract", "output_contract", "runner_type"],
43
+ "properties": {
44
+ "id": { "$ref": "#/$defs/identifier" },
45
+ "node_type": { "enum": ["observation", "judgment", "decision", "resource", "execution", "outcome", "evaluation"] },
46
+ "layer": { "enum": ["context", "judgment", "resource", "execution", "evaluation"] },
47
+ "scope": { "$ref": "#/$defs/scope" },
48
+ "version": { "type": "string", "minLength": 1, "pattern": "\\S" },
49
+ "description": { "type": "string", "minLength": 1, "pattern": "\\S" },
50
+ "depends_on": { "type": "array", "items": { "$ref": "#/$defs/identifier" }, "uniqueItems": true },
51
+ "input_contract": { "type": "string", "minLength": 1, "pattern": "\\S" },
52
+ "output_contract": { "type": "string", "minLength": 1, "pattern": "\\S" },
53
+ "runner_type": { "enum": ["deterministic", "agent", "human", "committee", "external"] },
54
+ "authority": { "$ref": "#/$defs/metadata" },
55
+ "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
56
+ "valid_from": { "type": ["string", "null"] },
57
+ "valid_to": { "type": ["string", "null"] },
58
+ "provenance": { "type": "array", "items": { "$ref": "#/$defs/metadata" } },
59
+ "evaluation": { "$ref": "#/$defs/metadata" }
60
+ },
61
+ "allOf": [
62
+ { "if": { "properties": { "node_type": { "const": "observation" } } }, "then": { "properties": { "layer": { "const": "context" } } } },
63
+ { "if": { "properties": { "node_type": { "enum": ["judgment", "decision"] } } }, "then": { "properties": { "layer": { "const": "judgment" } } } },
64
+ { "if": { "properties": { "node_type": { "const": "resource" } } }, "then": { "properties": { "layer": { "const": "resource" } } } },
65
+ { "if": { "properties": { "node_type": { "enum": ["execution", "outcome"] } } }, "then": { "properties": { "layer": { "const": "execution" } } } },
66
+ { "if": { "properties": { "node_type": { "const": "evaluation" } } }, "then": { "properties": { "layer": { "const": "evaluation" } } } }
67
+ ]
68
+ },
69
+ "edge": {
70
+ "type": "object",
71
+ "additionalProperties": false,
72
+ "required": ["from", "to", "relation"],
73
+ "properties": {
74
+ "from": { "$ref": "#/$defs/identifier" },
75
+ "to": { "$ref": "#/$defs/identifier" },
76
+ "relation": { "enum": ["depends_on", "supports", "contradicts", "gates", "supersedes", "produces", "evaluated_by", "triggers"] }
77
+ }
78
+ }
79
+ }
80
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "contract": "judgment-dag-core",
4
+ "repository": "https://github.com/Unson-LLC/brainbase",
5
+ "status": "accepted",
6
+ "accepted_base_commit": "7e5d5693f988f4ba84072c5910ef32f0e70871e1",
7
+ "sources": [
8
+ {
9
+ "kind": "architecture",
10
+ "path": "docs/architecture/judgment-dag-core.md",
11
+ "sha256": "24305aaa97df9c734d468c49f52784e94b77a4f506bae41d482bee05625d7e2a"
12
+ },
13
+ {
14
+ "kind": "milestones",
15
+ "path": "docs/management/judgment-dag-milestones.md",
16
+ "sha256": "ef51313f33de64f702fd6c86012984bd70cf99eeca5b4f4cfc27f6cb266172bd"
17
+ }
18
+ ],
19
+ "notes": [
20
+ "Outcome is produced and recorded by the Execution DAG and maps to the execution layer.",
21
+ "This J0 contract slice does not implement runner, artifact, execution-log, replay, evaluation, or mutation protection; those remain J0-2 non-goals and unverified.",
22
+ "Public DAG identifiers reject C0 and DEL control characters so dependency pair keys cannot collide.",
23
+ "J0 multi-tenancy evidence is limited to exact scope equality; cross-scope authorization, runtime, secret, database, and deployment are non-goals."
24
+ ]
25
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Shared semantic contract for the local Judgment DAG kernel.
3
+ *
4
+ * This module deliberately contains only the contract and preflight checks.
5
+ * Runners, artifact stores, replay, and public MCP/CLI adapters belong to
6
+ * later milestones and must not be coupled to this core surface.
7
+ */
8
+ export declare const JUDGMENT_DAG_NODE_TYPES: readonly ["observation", "judgment", "decision", "resource", "execution", "outcome", "evaluation"];
9
+ export type JudgmentDAGNodeType = (typeof JUDGMENT_DAG_NODE_TYPES)[number];
10
+ export declare const JUDGMENT_DAG_LAYERS: readonly ["context", "judgment", "resource", "execution", "evaluation"];
11
+ export type JudgmentDAGLayer = (typeof JUDGMENT_DAG_LAYERS)[number];
12
+ /**
13
+ * The accepted ontology has five layers. An outcome is the result produced
14
+ * by the Execution DAG; it is not a sixth layer of its own.
15
+ */
16
+ export declare const JUDGMENT_DAG_NODE_TYPE_TO_LAYER: Readonly<{
17
+ readonly observation: "context";
18
+ readonly judgment: "judgment";
19
+ readonly decision: "judgment";
20
+ readonly resource: "resource";
21
+ readonly execution: "execution";
22
+ readonly outcome: "execution";
23
+ readonly evaluation: "evaluation";
24
+ }>;
25
+ export declare const JUDGMENT_DAG_SCOPE_TYPES: readonly ["personal", "project", "organization"];
26
+ export type JudgmentDAGScopeType = (typeof JUDGMENT_DAG_SCOPE_TYPES)[number];
27
+ export declare const JUDGMENT_DAG_RUNNER_TYPES: readonly ["deterministic", "agent", "human", "committee", "external"];
28
+ export type JudgmentDAGRunnerType = (typeof JUDGMENT_DAG_RUNNER_TYPES)[number];
29
+ export declare const JUDGMENT_DAG_EDGE_RELATIONS: readonly ["depends_on", "supports", "contradicts", "gates", "supersedes", "produces", "evaluated_by", "triggers"];
30
+ export type JudgmentDAGEdgeRelation = (typeof JUDGMENT_DAG_EDGE_RELATIONS)[number];
31
+ /**
32
+ * Exact JSON object keys accepted by the runtime contract. Metadata records
33
+ * are intentionally not listed here because their nested keys are arbitrary.
34
+ */
35
+ export declare const JUDGMENT_DAG_ALLOWED_KEYS: Readonly<{
36
+ readonly root: readonly ["id", "version", "nodes", "edges"];
37
+ readonly node: readonly ["id", "node_type", "layer", "scope", "version", "description", "depends_on", "input_contract", "output_contract", "runner_type", "authority", "confidence", "valid_from", "valid_to", "provenance", "evaluation"];
38
+ readonly scope: readonly ["type", "id"];
39
+ readonly edge: readonly ["from", "to", "relation"];
40
+ }>;
41
+ export type JudgmentDAGMetadata = string | number | boolean | null | readonly JudgmentDAGMetadata[] | {
42
+ readonly [key: string]: JudgmentDAGMetadata;
43
+ };
44
+ export interface JudgmentDAGScope {
45
+ readonly type: JudgmentDAGScopeType;
46
+ readonly id: string;
47
+ }
48
+ export interface JudgmentDAGNode {
49
+ readonly id: string;
50
+ readonly node_type: JudgmentDAGNodeType;
51
+ readonly layer: JudgmentDAGLayer;
52
+ readonly scope: JudgmentDAGScope;
53
+ readonly version: string;
54
+ readonly description: string;
55
+ readonly depends_on: readonly string[];
56
+ readonly input_contract: string;
57
+ readonly output_contract: string;
58
+ readonly runner_type: JudgmentDAGRunnerType;
59
+ readonly authority?: JudgmentDAGMetadata;
60
+ readonly confidence?: number;
61
+ readonly valid_from?: string | null;
62
+ readonly valid_to?: string | null;
63
+ readonly provenance?: readonly JudgmentDAGMetadata[];
64
+ readonly evaluation?: JudgmentDAGMetadata | null;
65
+ }
66
+ /**
67
+ * For a `depends_on` relation, `from` is the dependency and `to` is the
68
+ * dependent node. This keeps the edge direction aligned with execution flow.
69
+ */
70
+ export interface JudgmentDAGEdge {
71
+ readonly from: string;
72
+ readonly to: string;
73
+ readonly relation: JudgmentDAGEdgeRelation;
74
+ }
75
+ export interface JudgmentDAG {
76
+ readonly id: string;
77
+ readonly version: string;
78
+ readonly nodes: readonly JudgmentDAGNode[];
79
+ readonly edges: readonly JudgmentDAGEdge[];
80
+ }
81
+ export type JudgmentDAGValidationCode = 'invalid_contract' | 'duplicate_node' | 'missing_dependency' | 'scope_boundary_violation' | 'reverse_layer_dependency' | 'cycle';
82
+ export interface JudgmentDAGValidationDetails {
83
+ readonly node_id?: string;
84
+ readonly dependency_id?: string;
85
+ readonly node_layer?: JudgmentDAGLayer;
86
+ readonly dependency_layer?: JudgmentDAGLayer;
87
+ readonly cycle?: readonly string[];
88
+ }
89
+ export declare class JudgmentDAGValidationError extends Error {
90
+ readonly code: JudgmentDAGValidationCode;
91
+ readonly node_id?: string;
92
+ readonly dependency_id?: string;
93
+ readonly node_layer?: JudgmentDAGLayer;
94
+ readonly dependency_layer?: JudgmentDAGLayer;
95
+ readonly cycle?: readonly string[];
96
+ constructor(code: JudgmentDAGValidationCode, message: string, details?: JudgmentDAGValidationDetails);
97
+ }
98
+ export interface JudgmentDAGValidationResult {
99
+ readonly valid: true;
100
+ readonly dag_id: string;
101
+ readonly dag_version: string;
102
+ readonly execution_order: readonly string[];
103
+ }
104
+ /**
105
+ * Validate a DAG before any runner can execute it.
106
+ *
107
+ * The input is never mutated. Dependencies declared on nodes and explicit
108
+ * `depends_on` edges are both checked. They are two required representations
109
+ * of the same dependency topology and must be exact mirrors; other edge
110
+ * relations are not part of the execution topology.
111
+ */
112
+ export declare function validateJudgmentDAG(value: unknown): JudgmentDAGValidationResult;
113
+ export declare function assertValidJudgmentDAG(value: unknown): asserts value is JudgmentDAG;
@@ -0,0 +1,439 @@
1
+ /**
2
+ * Shared semantic contract for the local Judgment DAG kernel.
3
+ *
4
+ * This module deliberately contains only the contract and preflight checks.
5
+ * Runners, artifact stores, replay, and public MCP/CLI adapters belong to
6
+ * later milestones and must not be coupled to this core surface.
7
+ */
8
+ export const JUDGMENT_DAG_NODE_TYPES = Object.freeze([
9
+ 'observation',
10
+ 'judgment',
11
+ 'decision',
12
+ 'resource',
13
+ 'execution',
14
+ 'outcome',
15
+ 'evaluation'
16
+ ]);
17
+ export const JUDGMENT_DAG_LAYERS = Object.freeze([
18
+ 'context',
19
+ 'judgment',
20
+ 'resource',
21
+ 'execution',
22
+ 'evaluation'
23
+ ]);
24
+ /**
25
+ * The accepted ontology has five layers. An outcome is the result produced
26
+ * by the Execution DAG; it is not a sixth layer of its own.
27
+ */
28
+ export const JUDGMENT_DAG_NODE_TYPE_TO_LAYER = Object.freeze({
29
+ observation: 'context',
30
+ judgment: 'judgment',
31
+ decision: 'judgment',
32
+ resource: 'resource',
33
+ execution: 'execution',
34
+ outcome: 'execution',
35
+ evaluation: 'evaluation'
36
+ });
37
+ export const JUDGMENT_DAG_SCOPE_TYPES = Object.freeze([
38
+ 'personal',
39
+ 'project',
40
+ 'organization'
41
+ ]);
42
+ export const JUDGMENT_DAG_RUNNER_TYPES = Object.freeze([
43
+ 'deterministic',
44
+ 'agent',
45
+ 'human',
46
+ 'committee',
47
+ 'external'
48
+ ]);
49
+ export const JUDGMENT_DAG_EDGE_RELATIONS = Object.freeze([
50
+ 'depends_on',
51
+ 'supports',
52
+ 'contradicts',
53
+ 'gates',
54
+ 'supersedes',
55
+ 'produces',
56
+ 'evaluated_by',
57
+ 'triggers'
58
+ ]);
59
+ /**
60
+ * Exact JSON object keys accepted by the runtime contract. Metadata records
61
+ * are intentionally not listed here because their nested keys are arbitrary.
62
+ */
63
+ export const JUDGMENT_DAG_ALLOWED_KEYS = Object.freeze({
64
+ root: Object.freeze(['id', 'version', 'nodes', 'edges']),
65
+ node: Object.freeze([
66
+ 'id',
67
+ 'node_type',
68
+ 'layer',
69
+ 'scope',
70
+ 'version',
71
+ 'description',
72
+ 'depends_on',
73
+ 'input_contract',
74
+ 'output_contract',
75
+ 'runner_type',
76
+ 'authority',
77
+ 'confidence',
78
+ 'valid_from',
79
+ 'valid_to',
80
+ 'provenance',
81
+ 'evaluation'
82
+ ]),
83
+ scope: Object.freeze(['type', 'id']),
84
+ edge: Object.freeze(['from', 'to', 'relation'])
85
+ });
86
+ export class JudgmentDAGValidationError extends Error {
87
+ code;
88
+ node_id;
89
+ dependency_id;
90
+ node_layer;
91
+ dependency_layer;
92
+ cycle;
93
+ constructor(code, message, details = {}) {
94
+ super(message);
95
+ this.name = 'JudgmentDAGValidationError';
96
+ this.code = code;
97
+ this.node_id = details.node_id;
98
+ this.dependency_id = details.dependency_id;
99
+ this.node_layer = details.node_layer;
100
+ this.dependency_layer = details.dependency_layer;
101
+ this.cycle = details.cycle;
102
+ }
103
+ }
104
+ const LAYER_INDEX = {
105
+ context: 0,
106
+ judgment: 1,
107
+ resource: 2,
108
+ execution: 3,
109
+ evaluation: 4
110
+ };
111
+ function isRecord(value) {
112
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
113
+ }
114
+ function isString(value) {
115
+ return typeof value === 'string';
116
+ }
117
+ function isNonEmptyString(value) {
118
+ return isString(value) && value.trim().length > 0;
119
+ }
120
+ function isSafeIdentifier(value) {
121
+ return isNonEmptyString(value) && !/[\u0000-\u001F\u007F]/u.test(value);
122
+ }
123
+ function isOneOf(values, value) {
124
+ return isString(value) && values.includes(value);
125
+ }
126
+ function invalidContract(message) {
127
+ throw new JudgmentDAGValidationError('invalid_contract', message);
128
+ }
129
+ function requireRecord(value, path) {
130
+ if (!isRecord(value)) {
131
+ invalidContract(`${path} must be an object`);
132
+ }
133
+ return value;
134
+ }
135
+ function requireExactKeys(value, allowedKeys, path) {
136
+ for (const key of Object.keys(value)) {
137
+ if (!allowedKeys.includes(key)) {
138
+ invalidContract(`${path}.${key} is not an allowed contract field`);
139
+ }
140
+ }
141
+ }
142
+ function requireNonEmptyString(value, path) {
143
+ if (!isNonEmptyString(value)) {
144
+ invalidContract(`${path} must be a non-empty string`);
145
+ }
146
+ return value;
147
+ }
148
+ function requireIdentifier(value, path) {
149
+ if (!isSafeIdentifier(value)) {
150
+ invalidContract(`${path} must be a non-empty string without control characters`);
151
+ }
152
+ return value;
153
+ }
154
+ function requireArray(value, path) {
155
+ if (!Array.isArray(value)) {
156
+ invalidContract(`${path} must be an array`);
157
+ }
158
+ return value;
159
+ }
160
+ function validateMetadata(value, path, active = new Set()) {
161
+ if (value === null || typeof value === 'string' || typeof value === 'boolean') {
162
+ return;
163
+ }
164
+ if (typeof value === 'number') {
165
+ if (Number.isFinite(value)) {
166
+ return;
167
+ }
168
+ invalidContract(`${path} must contain only finite JSON numbers`);
169
+ }
170
+ if (typeof value !== 'object') {
171
+ invalidContract(`${path} must contain JSON-compatible metadata`);
172
+ }
173
+ const objectValue = value;
174
+ if (active.has(objectValue)) {
175
+ invalidContract(`${path} must not contain cyclic metadata`);
176
+ }
177
+ active.add(objectValue);
178
+ if (Array.isArray(value)) {
179
+ for (let index = 0; index < value.length; index += 1) {
180
+ if (!(index in value)) {
181
+ invalidContract(`${path}[${index}] must be defined`);
182
+ }
183
+ validateMetadata(value[index], `${path}[${index}]`, active);
184
+ }
185
+ }
186
+ else {
187
+ const prototype = Object.getPrototypeOf(value);
188
+ if (prototype !== Object.prototype && prototype !== null) {
189
+ invalidContract(`${path} must contain only plain metadata objects`);
190
+ }
191
+ for (const [key, child] of Object.entries(value)) {
192
+ validateMetadata(child, `${path}.${key}`, active);
193
+ }
194
+ }
195
+ active.delete(objectValue);
196
+ }
197
+ function validateNode(value, index) {
198
+ const path = `nodes[${index}]`;
199
+ const node = requireRecord(value, path);
200
+ requireExactKeys(node, JUDGMENT_DAG_ALLOWED_KEYS.node, path);
201
+ const nodeType = node.node_type;
202
+ const layer = node.layer;
203
+ const runnerType = node.runner_type;
204
+ const scope = requireRecord(node.scope, `${path}.scope`);
205
+ requireExactKeys(scope, JUDGMENT_DAG_ALLOWED_KEYS.scope, `${path}.scope`);
206
+ if (!isOneOf(JUDGMENT_DAG_NODE_TYPES, nodeType)) {
207
+ invalidContract(`${path}.node_type is not a supported node type`);
208
+ }
209
+ if (!isOneOf(JUDGMENT_DAG_LAYERS, layer)) {
210
+ invalidContract(`${path}.layer is not a supported layer`);
211
+ }
212
+ if (!isOneOf(JUDGMENT_DAG_RUNNER_TYPES, runnerType)) {
213
+ invalidContract(`${path}.runner_type is not a supported runner type`);
214
+ }
215
+ if (!isOneOf(JUDGMENT_DAG_SCOPE_TYPES, scope.type)) {
216
+ invalidContract(`${path}.scope.type is not a supported scope type`);
217
+ }
218
+ if (JUDGMENT_DAG_NODE_TYPE_TO_LAYER[nodeType] !== layer) {
219
+ invalidContract(`${path}.layer does not match ${path}.node_type`);
220
+ }
221
+ requireIdentifier(node.id, `${path}.id`);
222
+ requireIdentifier(scope.id, `${path}.scope.id`);
223
+ requireNonEmptyString(node.version, `${path}.version`);
224
+ requireNonEmptyString(node.description, `${path}.description`);
225
+ requireNonEmptyString(node.input_contract, `${path}.input_contract`);
226
+ requireNonEmptyString(node.output_contract, `${path}.output_contract`);
227
+ const dependencies = requireArray(node.depends_on, `${path}.depends_on`);
228
+ for (let index = 0; index < dependencies.length; index += 1) {
229
+ requireIdentifier(dependencies[index], `${path}.depends_on[${index}]`);
230
+ }
231
+ if (new Set(dependencies).size !== dependencies.length) {
232
+ invalidContract(`${path}.depends_on must not contain duplicate node IDs`);
233
+ }
234
+ if (node.confidence !== undefined &&
235
+ (typeof node.confidence !== 'number' || !Number.isFinite(node.confidence) ||
236
+ node.confidence < 0 || node.confidence > 1)) {
237
+ invalidContract(`${path}.confidence must be a number between 0 and 1`);
238
+ }
239
+ for (const field of ['valid_from', 'valid_to']) {
240
+ if (node[field] !== undefined && node[field] !== null && !isString(node[field])) {
241
+ invalidContract(`${path}.${field} must be a string or null`);
242
+ }
243
+ }
244
+ if (node.provenance !== undefined && !Array.isArray(node.provenance)) {
245
+ invalidContract(`${path}.provenance must be an array`);
246
+ }
247
+ if (node.authority !== undefined) {
248
+ validateMetadata(node.authority, `${path}.authority`);
249
+ }
250
+ if (node.provenance !== undefined) {
251
+ validateMetadata(node.provenance, `${path}.provenance`);
252
+ }
253
+ if (node.evaluation !== undefined) {
254
+ validateMetadata(node.evaluation, `${path}.evaluation`);
255
+ }
256
+ return node;
257
+ }
258
+ function validateEdge(value, index, nodeById) {
259
+ const path = `edges[${index}]`;
260
+ const edge = requireRecord(value, path);
261
+ requireExactKeys(edge, JUDGMENT_DAG_ALLOWED_KEYS.edge, path);
262
+ const from = requireIdentifier(edge.from, `${path}.from`);
263
+ const to = requireIdentifier(edge.to, `${path}.to`);
264
+ if (!isOneOf(JUDGMENT_DAG_EDGE_RELATIONS, edge.relation)) {
265
+ invalidContract(`${path}.relation is not a supported edge relation`);
266
+ }
267
+ if (!nodeById.has(from) || !nodeById.has(to)) {
268
+ throw new JudgmentDAGValidationError('missing_dependency', `${path} references a node that is not in the DAG`, { node_id: to, dependency_id: from });
269
+ }
270
+ return edge;
271
+ }
272
+ function edgeKey(from, to) {
273
+ // A delimiter-based key aliases pairs such as ("a\0b", "c") and
274
+ // ("a", "b\0c"). JSON preserves the pair structure even if an unsafe
275
+ // identifier reaches this internal helper, while public identifiers are
276
+ // rejected by the schema/runtime before this point.
277
+ return JSON.stringify([from, to]);
278
+ }
279
+ function edgePairLabel(pair) {
280
+ const [from, to] = JSON.parse(pair);
281
+ return `${from} -> ${to}`;
282
+ }
283
+ function findCycle(nodes, dependenciesByNode) {
284
+ const state = new Map();
285
+ const path = [];
286
+ function visit(nodeId) {
287
+ const currentState = state.get(nodeId) ?? 0;
288
+ if (currentState === 1) {
289
+ const cycleStart = path.indexOf(nodeId);
290
+ return [...path.slice(cycleStart), nodeId];
291
+ }
292
+ if (currentState === 2) {
293
+ return undefined;
294
+ }
295
+ state.set(nodeId, 1);
296
+ path.push(nodeId);
297
+ for (const dependencyId of [...(dependenciesByNode.get(nodeId) ?? [])].sort()) {
298
+ const cycle = visit(dependencyId);
299
+ if (cycle !== undefined) {
300
+ return cycle;
301
+ }
302
+ }
303
+ path.pop();
304
+ state.set(nodeId, 2);
305
+ return undefined;
306
+ }
307
+ for (const nodeId of nodes.map((node) => node.id).sort()) {
308
+ const cycle = visit(nodeId);
309
+ if (cycle !== undefined) {
310
+ return cycle;
311
+ }
312
+ }
313
+ return undefined;
314
+ }
315
+ /**
316
+ * Validate a DAG before any runner can execute it.
317
+ *
318
+ * The input is never mutated. Dependencies declared on nodes and explicit
319
+ * `depends_on` edges are both checked. They are two required representations
320
+ * of the same dependency topology and must be exact mirrors; other edge
321
+ * relations are not part of the execution topology.
322
+ */
323
+ export function validateJudgmentDAG(value) {
324
+ const dag = requireRecord(value, 'dag');
325
+ requireExactKeys(dag, JUDGMENT_DAG_ALLOWED_KEYS.root, 'dag');
326
+ const dagId = requireIdentifier(dag.id, 'dag.id');
327
+ const dagVersion = requireNonEmptyString(dag.version, 'dag.version');
328
+ const nodeValues = requireArray(dag.nodes, 'dag.nodes');
329
+ const edgeValues = requireArray(dag.edges, 'dag.edges');
330
+ const nodes = nodeValues.map(validateNode);
331
+ const nodeById = new Map();
332
+ for (const node of nodes) {
333
+ if (nodeById.has(node.id)) {
334
+ throw new JudgmentDAGValidationError('duplicate_node', `DAG contains duplicate node ID: ${node.id}`, { node_id: node.id });
335
+ }
336
+ nodeById.set(node.id, node);
337
+ }
338
+ const dependenciesByNode = new Map(nodes.map((node) => [node.id, new Set()]));
339
+ const dependentsByNode = new Map(nodes.map((node) => [node.id, []]));
340
+ const dependencyPairs = new Set();
341
+ const nodeDependencyPairs = new Set();
342
+ function addDependency(dependencyId, dependentId) {
343
+ const dependent = nodeById.get(dependentId);
344
+ const dependency = nodeById.get(dependencyId);
345
+ if (dependent === undefined || dependency === undefined) {
346
+ throw new JudgmentDAGValidationError('missing_dependency', `Node ${dependentId} depends on missing node ${dependencyId}`, { node_id: dependentId, dependency_id: dependencyId });
347
+ }
348
+ if (dependency.scope.type !== dependent.scope.type || dependency.scope.id !== dependent.scope.id) {
349
+ throw new JudgmentDAGValidationError('scope_boundary_violation', `Dependency ${dependencyId} -> ${dependentId} crosses an exact scope boundary`, { node_id: dependentId, dependency_id: dependencyId });
350
+ }
351
+ const pair = edgeKey(dependencyId, dependentId);
352
+ if (dependencyPairs.has(pair)) {
353
+ return;
354
+ }
355
+ dependencyPairs.add(pair);
356
+ dependenciesByNode.get(dependentId)?.add(dependencyId);
357
+ dependentsByNode.get(dependencyId)?.push(dependentId);
358
+ const dependencyLayerIndex = LAYER_INDEX[dependency.layer];
359
+ const dependentLayerIndex = LAYER_INDEX[dependent.layer];
360
+ if (dependencyLayerIndex > dependentLayerIndex) {
361
+ throw new JudgmentDAGValidationError('reverse_layer_dependency', `Node ${dependentId} in layer ${dependent.layer} depends on later layer ` +
362
+ `${dependency.layer} node ${dependencyId}`, {
363
+ node_id: dependentId,
364
+ dependency_id: dependencyId,
365
+ node_layer: dependent.layer,
366
+ dependency_layer: dependency.layer
367
+ });
368
+ }
369
+ }
370
+ for (const node of nodes) {
371
+ for (const dependencyId of node.depends_on) {
372
+ nodeDependencyPairs.add(edgeKey(dependencyId, node.id));
373
+ addDependency(dependencyId, node.id);
374
+ }
375
+ }
376
+ const seenEdges = new Set();
377
+ const edgeDependencyPairs = new Set();
378
+ const edges = edgeValues.map((value, index) => validateEdge(value, index, nodeById));
379
+ for (const edge of edges) {
380
+ const key = `${edge.relation}:${edgeKey(edge.from, edge.to)}`;
381
+ if (seenEdges.has(key)) {
382
+ invalidContract(`edges contains duplicate relation ${key}`);
383
+ }
384
+ seenEdges.add(key);
385
+ if (edge.relation === 'depends_on') {
386
+ edgeDependencyPairs.add(edgeKey(edge.from, edge.to));
387
+ addDependency(edge.from, edge.to);
388
+ }
389
+ }
390
+ for (const pair of nodeDependencyPairs) {
391
+ if (!edgeDependencyPairs.has(pair)) {
392
+ invalidContract(`depends_on edge is missing for node dependency ${edgePairLabel(pair)}`);
393
+ }
394
+ }
395
+ for (const pair of edgeDependencyPairs) {
396
+ if (!nodeDependencyPairs.has(pair)) {
397
+ invalidContract(`node dependency is missing for depends_on edge ${edgePairLabel(pair)}`);
398
+ }
399
+ }
400
+ const cycle = findCycle(nodes, dependenciesByNode);
401
+ if (cycle !== undefined) {
402
+ throw new JudgmentDAGValidationError('cycle', `DAG contains a dependency cycle: ${cycle.join(' -> ')}`, { cycle });
403
+ }
404
+ const remainingDependencies = new Map([...dependenciesByNode.entries()].map(([id, dependencies]) => [id, dependencies.size]));
405
+ const ready = nodes
406
+ .filter((node) => remainingDependencies.get(node.id) === 0)
407
+ .map((node) => node.id)
408
+ .sort();
409
+ const executionOrder = [];
410
+ while (ready.length > 0) {
411
+ const completedNodeId = ready.shift();
412
+ if (completedNodeId === undefined) {
413
+ break;
414
+ }
415
+ executionOrder.push(completedNodeId);
416
+ for (const dependentId of [...(dependentsByNode.get(completedNodeId) ?? [])].sort()) {
417
+ const remaining = (remainingDependencies.get(dependentId) ?? 0) - 1;
418
+ remainingDependencies.set(dependentId, remaining);
419
+ if (remaining === 0) {
420
+ ready.push(dependentId);
421
+ ready.sort();
422
+ }
423
+ }
424
+ }
425
+ // This is defensive after findCycle, but keeps the preflight invariant
426
+ // explicit if the topology implementation changes later.
427
+ if (executionOrder.length !== nodes.length) {
428
+ throw new JudgmentDAGValidationError('cycle', 'DAG does not have a complete topological order');
429
+ }
430
+ return {
431
+ valid: true,
432
+ dag_id: dagId,
433
+ dag_version: dagVersion,
434
+ execution_order: executionOrder
435
+ };
436
+ }
437
+ export function assertValidJudgmentDAG(value) {
438
+ validateJudgmentDAG(value);
439
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Side-effect-free public entrypoint for the Judgment DAG core contract.
3
+ *
4
+ * The package root remains the MCP server entrypoint. Consumers that only
5
+ * need to validate a DAG can import this subpath without starting MCP.
6
+ */
7
+ export { JUDGMENT_DAG_EDGE_RELATIONS, JUDGMENT_DAG_ALLOWED_KEYS, JUDGMENT_DAG_LAYERS, JUDGMENT_DAG_NODE_TYPE_TO_LAYER, JUDGMENT_DAG_NODE_TYPES, JUDGMENT_DAG_RUNNER_TYPES, JUDGMENT_DAG_SCOPE_TYPES, JudgmentDAGValidationError, assertValidJudgmentDAG, validateJudgmentDAG } from './judgment-dag-core.js';
8
+ export type { JudgmentDAG, JudgmentDAGEdge, JudgmentDAGEdgeRelation, JudgmentDAGLayer, JudgmentDAGMetadata, JudgmentDAGNode, JudgmentDAGNodeType, JudgmentDAGRunnerType, JudgmentDAGScope, JudgmentDAGScopeType, JudgmentDAGValidationCode, JudgmentDAGValidationDetails, JudgmentDAGValidationResult } from './judgment-dag-core.js';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Side-effect-free public entrypoint for the Judgment DAG core contract.
3
+ *
4
+ * The package root remains the MCP server entrypoint. Consumers that only
5
+ * need to validate a DAG can import this subpath without starting MCP.
6
+ */
7
+ export { JUDGMENT_DAG_EDGE_RELATIONS, JUDGMENT_DAG_ALLOWED_KEYS, JUDGMENT_DAG_LAYERS, JUDGMENT_DAG_NODE_TYPE_TO_LAYER, JUDGMENT_DAG_NODE_TYPES, JUDGMENT_DAG_RUNNER_TYPES, JUDGMENT_DAG_SCOPE_TYPES, JudgmentDAGValidationError, assertValidJudgmentDAG, validateJudgmentDAG } from './judgment-dag-core.js';
@@ -0,0 +1,313 @@
1
+ ---
2
+ title: Brainbase Judgment DAG Core
3
+ status: accepted
4
+ date: 2026-08-20
5
+ scope: OSS Brainbase / shared core
6
+ supersedes_in_part: docs/architecture/brainbase-memory-loop-product-boundary.md
7
+ ---
8
+
9
+ # Brainbase Judgment DAG Core
10
+
11
+ ## Decision
12
+
13
+ Brainbase OSS and organization deployments share the same Judgment DAG semantic model and runtime core.
14
+
15
+ Brainbase is not only a memory/knowledge store. Its core responsibility is to externalize, preserve, replay, evaluate, and improve the structure by which a person or organization turns context into judgment and action.
16
+
17
+ The prior product boundary that limited OSS Brainbase to `Remember / Organize / Retrieve / Learn` is revised. Brainbase owns the **judgment substrate**; Mana may own autonomous operating loops, continuous follow-through, and outcome ownership on top of that substrate.
18
+
19
+ ```text
20
+ Brainbase = Remember / Organize / Retrieve / Judge / Replay / Learn
21
+ Mana = Operate / Prioritize continuously / Act autonomously / Follow-through
22
+ ```
23
+
24
+ Brainbase may represent and execute judgment nodes. It does not become an always-on autonomous operator merely because it can execute a DAG.
25
+
26
+ ## Core hypothesis
27
+
28
+ A person or organization can be modeled as a stateful system that repeatedly executes a directed judgment graph:
29
+
30
+ ```text
31
+ State(t)
32
+ ↓
33
+ Context / Observation DAG
34
+ ↓
35
+ Judgment DAG
36
+ ↓
37
+ Resource / Risk DAG
38
+ ↓
39
+ Execution DAG
40
+ ↓
41
+ Outcome
42
+ ↓
43
+ Evaluation DAG
44
+ ↓
45
+ State(t+1) + DAG update
46
+ ```
47
+
48
+ The durable asset is not the document corpus itself. It is the reusable structure connecting evidence, assumptions, judgments, decisions, commitments, actions, outcomes, and updates.
49
+
50
+ ## Shared five-layer model
51
+
52
+ ### Layer 1: Context DAG
53
+ Produces normalized observations and state required by downstream judgment.
54
+
55
+ Allowed:
56
+ - facts and observations
57
+ - metrics and snapshots
58
+ - entity resolution
59
+ - source provenance
60
+ - temporal validity
61
+
62
+ Forbidden:
63
+ - strategic choice
64
+ - resource allocation
65
+ - external action
66
+
67
+ ### Layer 2: Judgment DAG
68
+ Produces reusable interpretations and decisions from Context outputs.
69
+
70
+ Examples:
71
+ - priority judgment
72
+ - pricing judgment
73
+ - product fit judgment
74
+ - go/no-go judgment
75
+ - policy selection
76
+
77
+ Forbidden:
78
+ - direct mutation of execution state
79
+ - hidden reads from raw sources that bypass Context contracts
80
+ - direct resource commitment
81
+
82
+ ### Layer 3: Resource / Risk DAG
83
+ Converts judgments into bounded commitments.
84
+
85
+ Examples:
86
+ - budget
87
+ - time allocation
88
+ - staffing
89
+ - risk limit
90
+ - approval threshold
91
+ - scope
92
+
93
+ Forbidden:
94
+ - reimplementing upstream business judgment
95
+ - performing the external action itself
96
+
97
+ ### Layer 4: Execution DAG
98
+ Turns approved commitments into actions and records execution artifacts.
99
+
100
+ An **outcome** is the result that the Execution DAG generates and records. It is
101
+ an execution-layer node, not an independent sixth layer. The canonical node
102
+ type-to-layer mapping is `observation -> context`, `judgment/decision ->
103
+ judgment`, `resource -> resource`, `execution/outcome -> execution`, and
104
+ `evaluation -> evaluation`.
105
+
106
+ Examples:
107
+ - create task
108
+ - send proposal
109
+ - deploy software
110
+ - sign/route contract
111
+ - schedule meeting
112
+
113
+ Forbidden:
114
+ - silently changing upstream judgment or policy
115
+ - acquiring authority that was not granted by the DAG
116
+
117
+ ### Layer 5: Evaluation DAG
118
+ Compares outcomes against explicit goals and evaluation criteria.
119
+
120
+ Examples:
121
+ - forecast error
122
+ - KPI pass/fail
123
+ - decision quality
124
+ - resource efficiency
125
+ - user value confirmation
126
+
127
+ Evaluation can propose an update to a judgment/policy/DAG version; it does not silently rewrite canonical judgment without the required authority.
128
+
129
+ ## Node contract
130
+
131
+ A shared Judgment DAG node SHOULD converge on the following semantic contract:
132
+
133
+ ```text
134
+ id
135
+ node_type
136
+ layer
137
+ scope
138
+ version
139
+ description
140
+
141
+ depends_on[]
142
+ input_contract
143
+ output_contract
144
+
145
+ runner_type
146
+ deterministic
147
+ agent
148
+ human
149
+ committee
150
+ external
151
+
152
+ authority
153
+ confidence
154
+ valid_from
155
+ valid_to
156
+ provenance
157
+
158
+ evaluation
159
+ ```
160
+
161
+ Initial node types should stay intentionally small:
162
+
163
+ ```text
164
+ observation
165
+ judgment
166
+ decision
167
+ resource
168
+ execution
169
+ outcome
170
+ evaluation
171
+ ```
172
+
173
+ The `outcome` node type therefore remains in the Execution layer even though
174
+ the flow diagram shows it between Execution and Evaluation.
175
+
176
+ Ontology growth must be driven by failed real use cases, not by speculative completeness.
177
+
178
+ ## Edge contract
179
+
180
+ Knowledge/identity relations and judgment dependencies are different concepts and must not be collapsed.
181
+
182
+ Judgment DAG edges include:
183
+
184
+ ```text
185
+ depends_on
186
+ supports
187
+ contradicts
188
+ gates
189
+ supersedes
190
+ produces
191
+ evaluated_by
192
+ triggers
193
+ ```
194
+
195
+ `depends_on` defines executable DAG topology. `node.depends_on` is the
196
+ topology SSOT: every dependency pair must have exactly one matching
197
+ `relation=depends_on` edge, and every `relation=depends_on` edge must have
198
+ exactly one matching node dependency. The edge is a required complete mirror,
199
+ not an optional duplicate declaration; a one-sided or mismatched
200
+ representation is `invalid_contract`. Relations such as `member_of`,
201
+ `owned_by`, or `accountable_for` remain graph semantics and can be referenced
202
+ by DAG nodes.
203
+
204
+ ## Scope model: personal and organization use the same DAG
205
+
206
+ Do not create separate `PersonalDecision` and `CompanyDecision` schemas.
207
+
208
+ A node is scoped instead:
209
+
210
+ ```text
211
+ scope:
212
+ type: personal | project | organization
213
+ id: <scope-id>
214
+ ```
215
+
216
+ This enables promotion:
217
+
218
+ ```text
219
+ Personal Judgment
220
+ ↓ evidence / repeated success
221
+ Project Judgment
222
+ ↓ promotion / authority
223
+ Organization Policy
224
+ ```
225
+
226
+ A judgment can therefore move from an individual's learned heuristic into an organizational capability without translation into a separate schema.
227
+
228
+ J0-1 does not implement cross-scope promotion or authority evidence. Before
229
+ execution, both nodes in every dependency pair must have exactly equal
230
+ `scope.type` and `scope.id`; otherwise validation fails closed with the
231
+ machine-readable code `scope_boundary_violation`. A structurally valid DAG is
232
+ not evidence of execution authority, approval, or promotion. Those governance
233
+ boundaries remain later-scope work.
234
+
235
+ ## Runtime principles inherited from FX / keiba DAG work
236
+
237
+ Brainbase adopts the architecture lessons proven in the `sintariran/FX` and `sintariran/keiba` DAG systems:
238
+
239
+ 1. **Layer ownership is explicit.** A downstream layer must not reimplement an upstream decision.
240
+ 2. **Inputs and outputs cross typed contracts.** No hidden state side channels.
241
+ 3. **Dependencies are validated before execution.** Missing or reverse-layer dependencies are errors.
242
+ 4. **Every run produces artifacts and an execution log.** A judgment must be replayable and auditable.
243
+ 5. **DAG versions are first-class.** A changed judgment structure is a new version, not an invisible mutation.
244
+ 6. **Evaluation is separate from execution.** Metrics must not be gamed by modifying the system under evaluation.
245
+
246
+ ## OSS / organization boundary
247
+
248
+ The Judgment DAG core is OSS-level product capability.
249
+
250
+ OSS includes:
251
+ - node/edge semantic model
252
+ - dependency validation
253
+ - local execution runtime
254
+ - human and agent runners
255
+ - local artifact/execution log
256
+ - versioning
257
+ - replay/evaluation primitives
258
+ - personal/project/organization scope primitives
259
+ - basic authority metadata
260
+
261
+ Organization/Enterprise adds operational concerns rather than a different brain model:
262
+ - organization identity and directory integration
263
+ - robust RBAC / authority graph
264
+ - approval and escalation workflows
265
+ - multi-user concurrency
266
+ - managed connectors
267
+ - audit/compliance retention
268
+ - hosted runtime and HA
269
+ - cross-project governance
270
+ - enterprise security boundaries
271
+
272
+ ## Mana boundary after this decision
273
+
274
+ Mana is no longer defined as the only place where judgment can occur.
275
+
276
+ Brainbase owns **what the judgment graph is, what it depends on, who/what can run it, what it produced, and how it evaluated**.
277
+
278
+ Mana owns the higher-order operating behavior that repeatedly decides *when* to run graphs, prioritizes across goals, initiates work, monitors progress, follows through, and intervenes over time.
279
+
280
+ ```text
281
+ Brainbase: executable organizational cognition
282
+ Mana: autonomous organizational operation
283
+ ```
284
+
285
+ ## Non-goals
286
+
287
+ - Do not migrate the entire Brainbase ontology to a large Company Ontology in one release.
288
+ - Do not make all knowledge executable.
289
+ - Do not let an LLM infer authority implicitly.
290
+ - Do not create a single monolithic company DAG.
291
+ - Do not auto-promote personal judgments into organization policy without explicit evidence and authority.
292
+
293
+ ## First proving ground
294
+
295
+ `Brainbase Deployment` is the first dogfooding domain.
296
+
297
+ The initial DAG should capture:
298
+
299
+ ```text
300
+ Customer Context
301
+ ↓
302
+ Maturity / Problem Structure Judgment
303
+ ↓
304
+ Deployment Pattern Selection
305
+ ↓
306
+ Scope / Resource Decision
307
+ ↓
308
+ Proposal / Implementation
309
+ ↓
310
+ Outcome Evaluation
311
+ ```
312
+
313
+ Human judgment can initially be a runner. Each repeated decision should then be tested for delegation to an agent. The key success signal is a falling count of decisions that still require the original expert directly.
@@ -0,0 +1,143 @@
1
+ ---
2
+ title: Brainbase Judgment DAG Milestones
3
+ status: active
4
+ date: 2026-08-20
5
+ scope: OSS Brainbase
6
+ ---
7
+
8
+ # Brainbase Judgment DAG Milestones
9
+
10
+ This roadmap replaces any implicit assumption that OSS Brainbase stops at memory retrieval. The next milestones make the shared Judgment DAG core real without prematurely building a complete enterprise ontology.
11
+
12
+ ## M0 — Architecture lock
13
+
14
+ Goal: freeze semantic boundaries before implementation.
15
+
16
+ Exit criteria:
17
+ - `judgment-dag-core.md` is accepted.
18
+ - Personal and organization scopes share one node/edge model.
19
+ - Brainbase/Mana boundary is documented as cognition vs autonomous operation.
20
+ - FX/keiba lessons are explicitly adopted: layered ownership, typed boundaries, artifact logs, versioning, evaluation separation.
21
+
22
+ ## M1 — Local DAG kernel
23
+
24
+ Goal: execute a small deterministic DAG locally.
25
+
26
+ Deliverables:
27
+ - `JudgmentDAGNode` / edge types
28
+ - `depends_on` validation
29
+ - layer validation
30
+ - deterministic runner
31
+ - execution artifact store
32
+ - execution log
33
+ - DAG version identifier
34
+
35
+ Exit criteria:
36
+ - A DAG with Context → Judgment → Resource → Execution → Evaluation runs deterministically.
37
+ - Missing dependency and reverse-layer dependency fail before execution.
38
+ - Every node output is inspectable after execution.
39
+ - Existing Brainbase Graph/Decision storage remains compatible.
40
+
41
+ ## M2 — Human + Agent judgment runners
42
+
43
+ Goal: allow a judgment node to be performed by a human or an agent without changing DAG semantics.
44
+
45
+ Deliverables:
46
+ - `runner_type = human | agent | deterministic | external`
47
+ - pending human-step representation
48
+ - agent input/output contract
49
+ - explicit authority metadata
50
+ - confidence/provenance recording
51
+
52
+ Exit criteria:
53
+ - The same judgment node can be run manually and by an agent.
54
+ - Outputs can be compared without hidden context.
55
+ - Agent execution cannot silently acquire additional authority.
56
+
57
+ ## M3 — Replay and evaluation
58
+
59
+ Goal: make judgment quality testable rather than anecdotal.
60
+
61
+ Deliverables:
62
+ - immutable run snapshot / artifact reference
63
+ - replay against historical context
64
+ - explicit goal/evaluation criteria
65
+ - outcome attachment
66
+ - pass/fail or scored evaluation
67
+ - node-level comparison between versions
68
+
69
+ Exit criteria:
70
+ - A prior DAG version can be replayed against a recorded context.
71
+ - A new version can be compared with the prior version without rewriting historical artifacts.
72
+ - Evaluation cannot mutate the event set it evaluates.
73
+
74
+ ## M4 — Brainbase Deployment dogfood
75
+
76
+ Goal: externalize the first real expert judgment process.
77
+
78
+ Initial flow:
79
+
80
+ ```text
81
+ Customer Context
82
+ -> Maturity Judgment
83
+ -> Problem Structure Judgment
84
+ -> Deployment Pattern
85
+ -> Scope / Resource Decision
86
+ -> Proposal / Implementation
87
+ -> Outcome Evaluation
88
+ ```
89
+
90
+ Exit criteria:
91
+ - At least one real deployment is represented end-to-end.
92
+ - Human-only judgment nodes are explicit.
93
+ - Each expert escalation is logged as a missing/uncertain DAG capability rather than disappearing into chat.
94
+ - KPI: number of decisions requiring the original expert is measurable per deployment.
95
+
96
+ ## M5 — Scope promotion
97
+
98
+ Goal: prove Personal → Project → Organization judgment promotion using one schema.
99
+
100
+ Deliverables:
101
+ - scope metadata
102
+ - promotion candidate workflow
103
+ - evidence links
104
+ - authority/approval gate
105
+ - supersession handling
106
+
107
+ Exit criteria:
108
+ - A personal judgment can become project guidance and then organization policy without schema conversion.
109
+ - The historical personal/project records remain queryable.
110
+ - Promotion never occurs solely because an LLM repeats the same output.
111
+
112
+ ## M6 — Organization-ready primitives
113
+
114
+ Goal: keep the core reusable while allowing enterprise products to extend it.
115
+
116
+ Deliverables in OSS core:
117
+ - authority references
118
+ - approval hooks
119
+ - organization scope primitives
120
+ - audit event contract
121
+ - connector/runtime adapter interfaces
122
+
123
+ Not required in OSS M6:
124
+ - SSO/SCIM
125
+ - enterprise directory sync
126
+ - HA hosted runtime
127
+ - compliance retention policies
128
+ - full multi-user approval UI
129
+
130
+ Exit criteria:
131
+ - `brainbase-unson` can implement enterprise authority/governance without forking the DAG semantic model.
132
+
133
+ ## Product metric hierarchy
134
+
135
+ The roadmap is not complete merely because graph/node counts increase. Measure:
136
+
137
+ 1. **Replayability** — can Brainbase explain and rerun why a judgment occurred?
138
+ 2. **Delegatability** — can an agent/another human run the node using explicit contracts?
139
+ 3. **Expert escalation count** — how often is tacit expert judgment still required?
140
+ 4. **Outcome calibration** — do judgment versions improve against declared goals?
141
+ 5. **Promotion quality** — are reusable judgments correctly distinguished from case-specific decisions?
142
+
143
+ The primary dogfood KPI is **expert escalation count per deployment**, not total stored knowledge.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unson/brainbase-mcp",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Local-first Brainbase MCP server and personal onboarding kit.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -10,12 +10,31 @@
10
10
  },
11
11
  "main": "dist/index.js",
12
12
  "types": "dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ },
18
+ "./judgment-dag": {
19
+ "types": "./dist/judgment-dag.d.ts",
20
+ "import": "./dist/judgment-dag.js"
21
+ },
22
+ "./dist/*": "./dist/*",
23
+ "./contracts/judgment-dag/schema.json": "./contracts/judgment-dag/schema.json",
24
+ "./contracts/judgment-dag/fixture.json": "./contracts/judgment-dag/fixture.json",
25
+ "./contracts/judgment-dag/source-lock.json": "./contracts/judgment-dag/source-lock.json",
26
+ "./contracts/judgment-dag/digest.json": "./contracts/judgment-dag/digest.json",
27
+ "./package.json": "./package.json"
28
+ },
13
29
  "bin": {
14
30
  "brainbase-mcp": "dist/index.js",
15
31
  "brainbase": "dist/cli.js"
16
32
  },
17
33
  "files": [
18
34
  "dist",
35
+ "contracts",
36
+ "docs/architecture/judgment-dag-core.md",
37
+ "docs/management/judgment-dag-milestones.md",
19
38
  "README.md",
20
39
  "LICENSE",
21
40
  "SECURITY.md"
@@ -40,6 +59,7 @@
40
59
  "onboard:seed": "node dist/cli.js onboard:seed",
41
60
  "onboard:demo": "node dist/cli.js onboard:demo",
42
61
  "onboard:install": "node dist/cli.js onboard:install",
62
+ "contracts:generate": "node scripts/generate-judgment-dag-contract-artifacts.mjs",
43
63
  "release:plan": "node scripts/npm-release.mjs plan",
44
64
  "release:validate": "node scripts/npm-release.mjs validate",
45
65
  "release:publish": "node scripts/npm-release.mjs publish",
@@ -62,5 +82,5 @@
62
82
  "engines": {
63
83
  "node": ">=20"
64
84
  },
65
- "gitHead": "0ff2753a492aef09235be2792570000ef03dfa4b"
85
+ "gitHead": "0ee5db39ac8f91a484628cc07a2df21cdfb149b7"
66
86
  }