@unson/brainbase-mcp 0.4.0 → 0.5.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 +146 -471
- package/contracts/judgment-dag/digest.json +4 -4
- package/contracts/judgment-dag/source-lock.json +65 -1
- package/contracts/judgment-value-proof/fixture.json +54 -0
- package/contracts/judgment-value-proof/schema.json +163 -0
- package/contracts/public-message-candidate.schema.json +143 -0
- package/dist/cli.js +46 -6
- package/dist/embedding-provider.d.ts +72 -0
- package/dist/embedding-provider.js +391 -0
- package/dist/graph-retrieval.d.ts +94 -0
- package/dist/graph-retrieval.js +443 -0
- package/dist/judgment-autonomy.d.ts +62 -0
- package/dist/judgment-autonomy.js +301 -0
- package/dist/judgment-dag-artifact-store.d.ts +29 -0
- package/dist/judgment-dag-artifact-store.js +416 -0
- package/dist/judgment-dag-replay-evaluation.d.ts +108 -0
- package/dist/judgment-dag-replay-evaluation.js +424 -0
- package/dist/judgment-dag-runner.d.ts +70 -0
- package/dist/judgment-dag-runner.js +325 -0
- package/dist/judgment-dag.d.ts +6 -0
- package/dist/judgment-dag.js +3 -0
- package/dist/judgment-host.d.ts +21 -0
- package/dist/judgment-host.js +180 -0
- package/dist/judgment-value-proof.d.ts +92 -0
- package/dist/judgment-value-proof.js +229 -0
- package/dist/organization-graph.d.ts +76 -0
- package/dist/organization-graph.js +331 -0
- package/dist/portable-graph.d.ts +39 -0
- package/dist/portable-graph.js +240 -0
- package/dist/server.d.ts +42 -3
- package/dist/server.js +52 -7
- package/docs/management/judgment-dag-milestones.md +31 -1
- package/package.json +20 -4
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
const AUDIT_LINE = /^(?:🧠 |📚 Brainbase|⚠️ (?:Brainbase|判断))/u;
|
|
3
|
+
const QUESTION_END = /(?:[??]|(?:選んで|教えて|確認して|承認して)(?:ください|下さい)?[。.]?)$/u;
|
|
4
|
+
const HUMAN_QUESTION_PATTERNS = [
|
|
5
|
+
/(?:しても|して|進めても|実行しても|変更しても|修正しても|作成しても)(?:よい|いい|良い)ですか/u,
|
|
6
|
+
/(?:しますか|進めますか|実行しますか|変更しますか|修正しますか|作成しますか)/u,
|
|
7
|
+
/(?:どちら|どれ|何を|どう)(?:に|を|で)?(?:します|進めます|選びます|すべき)か/u,
|
|
8
|
+
/(?:どちら|どの|何の).+(?:ですか|ますか)/u,
|
|
9
|
+
/(?:送って|渡して|共有して)(?:も)?(?:よい|いい|良い)ですか/u,
|
|
10
|
+
/(?:選んで|教えて|確認して|承認して)(?:ください|下さい)/u,
|
|
11
|
+
/(?:送信|送付|公開|投稿|デプロイ|マージ|merge|push|publish|作成|削除|破棄|変更|共有)(?:しても|して)?(?:よい|いい|良い)ですか/iu,
|
|
12
|
+
/(?:送ります|公開します|投稿します|デプロイします|マージします|作成します|削除します|破棄します|変更します|共有します|渡します)か/iu,
|
|
13
|
+
/(?:should i|would you like|do you want|which (?:option|one)|please (?:choose|confirm|approve)|can i)\b/iu
|
|
14
|
+
];
|
|
15
|
+
const EXTERNAL_ACTION_TERMS = [
|
|
16
|
+
'外部送信', 'メール送信', '送信しますか', '公開しますか', '投稿しますか', '本番デプロイ',
|
|
17
|
+
'本番へデプロイ', 'prを作成', 'pull request', 'issueを作成', 'github issue', 'slack',
|
|
18
|
+
'メール', 'webhook', '外部api', '外部サービス', '共有しますか', '渡してよい',
|
|
19
|
+
'mergeしますか', 'pushしますか', 'publish', 'send', 'deploy', 'merge', 'push', 'post'
|
|
20
|
+
];
|
|
21
|
+
const DESTRUCTIVE_TERMS = [
|
|
22
|
+
'本番データを削除', '本番削除', '本番DB', 'drop table', 'truncate', 'production delete',
|
|
23
|
+
'データベースを削除', 'dbを削除', '削除しますか', '消去しますか', '不可逆',
|
|
24
|
+
'取り消せない', '破棄', '全削除', '上書き'
|
|
25
|
+
];
|
|
26
|
+
const PRODUCTION_ACTION_TERMS = [
|
|
27
|
+
'本番環境', '本番で', '本番へ', 'production', 'prod', '商用環境', '顧客環境'
|
|
28
|
+
];
|
|
29
|
+
const AUTHORITY_CHANGE_TERMS = [
|
|
30
|
+
'権限を変更', '権限付与', '管理者権限', 'owner権限', 'roleを変更', 'rbac',
|
|
31
|
+
'アクセス権', 'permission change', 'grant access', 'admin role'
|
|
32
|
+
];
|
|
33
|
+
const SENSITIVE_DATA_TERMS = [
|
|
34
|
+
'個人情報', '機密情報', '顧客情報', '医療情報', '認証情報を送', '秘密情報を送',
|
|
35
|
+
'personal data', 'pii', 'confidential', 'health data', 'credentialを送'
|
|
36
|
+
];
|
|
37
|
+
const AUTHORITY_TERMS = [
|
|
38
|
+
'権限がありません', '権限不足', '認証情報', '秘密情報', 'api key', 'credential', 'permission denied',
|
|
39
|
+
'access denied', 'secretが必要', 'トークンが必要'
|
|
40
|
+
];
|
|
41
|
+
const MATERIAL_COMMITMENT_TERMS = [
|
|
42
|
+
'購入', '発注', '支払い', '決済', '契約締結', '法的', '金額', '課金', 'purchase', 'payment',
|
|
43
|
+
'sign the contract', 'legal commitment'
|
|
44
|
+
];
|
|
45
|
+
const EXPLICIT_NEW_OWNER_VALUE_TERMS = [
|
|
46
|
+
'既存の判断基準では決められない', 'brainbaseに判断基準がない', '新しい価値判断を決める必要',
|
|
47
|
+
'これまで決めていない方針', 'no existing decision principle', 'new owner value choice is required'
|
|
48
|
+
];
|
|
49
|
+
const ROUTINE_TERMS = [
|
|
50
|
+
'テスト', 'lint', 'format', 'フォーマット', 'build', 'ビルド', '型チェック', 'typecheck',
|
|
51
|
+
'ファイルを読む', 'ファイルを確認', '調査', '検索', 'ログを確認', '差分を確認', 'dry-run',
|
|
52
|
+
'ローカル', '可逆', '小さな修正', '編集', '実装方法', 'リファクタ', 'read the file',
|
|
53
|
+
'run the test', 'run tests', 'inspect', 'search', 'local change'
|
|
54
|
+
];
|
|
55
|
+
const RELEASE_PIPELINE_TERMS = [
|
|
56
|
+
'prを作成', 'pull request', 'merge', 'マージ', 'push', 'publish', '公開', 'deploy',
|
|
57
|
+
'デプロイ', '本番展開', '本番反映', 'release', 'リリース'
|
|
58
|
+
];
|
|
59
|
+
function canonicalJson(value) {
|
|
60
|
+
if (value === null || typeof value === 'boolean' || typeof value === 'string')
|
|
61
|
+
return JSON.stringify(value);
|
|
62
|
+
if (typeof value === 'number') {
|
|
63
|
+
if (!Number.isFinite(value))
|
|
64
|
+
throw new TypeError('canonical JSON only supports finite numbers');
|
|
65
|
+
return JSON.stringify(value);
|
|
66
|
+
}
|
|
67
|
+
if (Array.isArray(value))
|
|
68
|
+
return `[${value.map((entry) => canonicalJson(entry)).join(',')}]`;
|
|
69
|
+
if (value && typeof value === 'object') {
|
|
70
|
+
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(',')}}`;
|
|
71
|
+
}
|
|
72
|
+
throw new TypeError('canonical JSON only supports JSON values');
|
|
73
|
+
}
|
|
74
|
+
function sha256(value) {
|
|
75
|
+
return createHash('sha256').update(value).digest('hex');
|
|
76
|
+
}
|
|
77
|
+
function containsAny(text, terms) {
|
|
78
|
+
const normalized = text.toLocaleLowerCase();
|
|
79
|
+
return terms.some((term) => normalized.includes(term.toLocaleLowerCase()));
|
|
80
|
+
}
|
|
81
|
+
function requestAuthorizesExternalAction(request, question) {
|
|
82
|
+
if (containsAny(question, RELEASE_PIPELINE_TERMS)) {
|
|
83
|
+
return containsAny(request, RELEASE_PIPELINE_TERMS);
|
|
84
|
+
}
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
export function visibleAnswerBody(answer) {
|
|
88
|
+
const lines = answer.replaceAll('\r\n', '\n').split('\n');
|
|
89
|
+
while (lines.length > 0 && (lines[0].trim() === '' || AUDIT_LINE.test(lines[0])))
|
|
90
|
+
lines.shift();
|
|
91
|
+
return lines.join('\n').trim();
|
|
92
|
+
}
|
|
93
|
+
export function extractHumanDecisionQuestion(answer) {
|
|
94
|
+
const body = visibleAnswerBody(answer);
|
|
95
|
+
if (!body)
|
|
96
|
+
return null;
|
|
97
|
+
const paragraphs = body.split(/\n\s*\n/u).map((paragraph) => paragraph.trim()).filter(Boolean);
|
|
98
|
+
const candidate = paragraphs.at(-1) ?? body;
|
|
99
|
+
const lines = candidate.split('\n').map((line) => line.trim()).filter(Boolean);
|
|
100
|
+
const question = lines.slice(-3).join(' ').slice(-1200).trim();
|
|
101
|
+
if (!question || !QUESTION_END.test(question))
|
|
102
|
+
return null;
|
|
103
|
+
return HUMAN_QUESTION_PATTERNS.some((pattern) => pattern.test(question)) ? question : null;
|
|
104
|
+
}
|
|
105
|
+
function continuationPatch(question, semantic) {
|
|
106
|
+
return {
|
|
107
|
+
cancel: [`人間への確認質問: ${question}`],
|
|
108
|
+
do_next: semantic ? [
|
|
109
|
+
'Brainbase MCPから今回の目的、適用可能な判断基準、過去Decision、委任境界を取得する',
|
|
110
|
+
'候補を比較し、既存の人間由来の基準を今回の具体的状況へ適用してOK / NG / 条件付きOKを決める',
|
|
111
|
+
'NGなら理由だけで止めず、代替行動と完了条件を作業計画へ反映する',
|
|
112
|
+
'安全かつ委任範囲内なら同じCodexターンで調査・実装・検証を続行する'
|
|
113
|
+
] : [
|
|
114
|
+
'質問対象の通常工程をそのまま実行する',
|
|
115
|
+
'結果を検証し、失敗時は安全な代替手段を試す',
|
|
116
|
+
'同じCodexターンで完了まで続行する'
|
|
117
|
+
],
|
|
118
|
+
acceptance_criteria: [
|
|
119
|
+
'人間へ同じ確認を再送しない',
|
|
120
|
+
'不可逆な外部操作、実証済みの権限不足、既存基準から決められない新しい価値判断だけを再エスカレーションする',
|
|
121
|
+
'最終回答は既存のBrainbase audit_contractも満たす'
|
|
122
|
+
]
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function resolverRequest(context, question, caseId) {
|
|
126
|
+
return {
|
|
127
|
+
schema_version: 'brainbase-autonomy-resolver-request-v1',
|
|
128
|
+
case_id: caseId,
|
|
129
|
+
turn_id: context.turn_id,
|
|
130
|
+
task_request: context.request,
|
|
131
|
+
proposed_human_question: question,
|
|
132
|
+
...(context.project_code ? { project_code: context.project_code } : {}),
|
|
133
|
+
selected_dag_ids: [...context.selected_dag_ids],
|
|
134
|
+
policy: {
|
|
135
|
+
default_behavior: 'continue',
|
|
136
|
+
complexity_behavior: 'decompose_and_continue',
|
|
137
|
+
human_only: [
|
|
138
|
+
'irreversible_external_action',
|
|
139
|
+
'missing_authority_or_secret',
|
|
140
|
+
'material_commitment',
|
|
141
|
+
'new_owner_value_choice'
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function validateResolverDecision(decision, caseId) {
|
|
147
|
+
if (decision?.schema_version !== 'brainbase-autonomy-resolver-decision-v1'
|
|
148
|
+
|| decision.case_id !== caseId
|
|
149
|
+
|| !['continue', 'human_required'].includes(decision.verdict)
|
|
150
|
+
|| typeof decision.reason_code !== 'string'
|
|
151
|
+
|| !decision.reason_code.trim()
|
|
152
|
+
|| typeof decision.reason !== 'string'
|
|
153
|
+
|| !decision.reason.trim()
|
|
154
|
+
|| !Array.isArray(decision.basis)
|
|
155
|
+
|| decision.basis.length === 0
|
|
156
|
+
|| !decision.basis.every((entry) => (entry
|
|
157
|
+
&& typeof entry.entity_id === 'string'
|
|
158
|
+
&& entry.entity_id.trim().length > 0
|
|
159
|
+
&& typeof entry.application === 'string'
|
|
160
|
+
&& entry.application.trim().length > 0))) {
|
|
161
|
+
throw new Error('judgment_autonomy_resolver_invalid');
|
|
162
|
+
}
|
|
163
|
+
if (decision.verdict === 'continue') {
|
|
164
|
+
const patch = decision.instruction_patch;
|
|
165
|
+
if (!patch
|
|
166
|
+
|| !Array.isArray(patch.cancel)
|
|
167
|
+
|| !Array.isArray(patch.do_next)
|
|
168
|
+
|| patch.do_next.length === 0
|
|
169
|
+
|| !Array.isArray(patch.acceptance_criteria)
|
|
170
|
+
|| patch.acceptance_criteria.length === 0
|
|
171
|
+
|| ![...patch.cancel, ...patch.do_next, ...patch.acceptance_criteria].every((item) => (typeof item === 'string' && item.trim().length > 0))) {
|
|
172
|
+
throw new Error('judgment_autonomy_resolver_instruction_missing');
|
|
173
|
+
}
|
|
174
|
+
const delegatedInstructions = [...patch.cancel, ...patch.do_next, ...patch.acceptance_criteria].join(' ');
|
|
175
|
+
if (containsAny(delegatedInstructions, EXTERNAL_ACTION_TERMS)
|
|
176
|
+
|| containsAny(delegatedInstructions, DESTRUCTIVE_TERMS)
|
|
177
|
+
|| containsAny(delegatedInstructions, MATERIAL_COMMITMENT_TERMS)) {
|
|
178
|
+
throw new Error('judgment_autonomy_resolver_authority_expansion');
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (decision.verdict === 'human_required'
|
|
182
|
+
&& (typeof decision.human_question !== 'string' || !decision.human_question.trim())) {
|
|
183
|
+
throw new Error('judgment_autonomy_resolver_human_question_missing');
|
|
184
|
+
}
|
|
185
|
+
return decision;
|
|
186
|
+
}
|
|
187
|
+
export async function evaluateJudgmentAutonomy(context, resolver) {
|
|
188
|
+
const question = extractHumanDecisionQuestion(context.final_answer);
|
|
189
|
+
const caseId = sha256(canonicalJson({
|
|
190
|
+
turn_id: context.turn_id,
|
|
191
|
+
request: context.request,
|
|
192
|
+
question,
|
|
193
|
+
project_code: context.project_code ?? null,
|
|
194
|
+
selected_dag_ids: [...context.selected_dag_ids]
|
|
195
|
+
}));
|
|
196
|
+
if (!question) {
|
|
197
|
+
return {
|
|
198
|
+
schema_version: 'brainbase-autonomy-evaluation-v1',
|
|
199
|
+
case_id: caseId,
|
|
200
|
+
verdict: 'not_applicable',
|
|
201
|
+
reason_code: 'not_a_human_escalation',
|
|
202
|
+
reason: 'The final answer does not request a human decision or approval.',
|
|
203
|
+
question: null,
|
|
204
|
+
source: 'deterministic',
|
|
205
|
+
instruction_patch: null,
|
|
206
|
+
resolver_decision: null
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
if (context.selected_dag_ids.includes('clarification.v1')) {
|
|
210
|
+
return {
|
|
211
|
+
schema_version: 'brainbase-autonomy-evaluation-v1', case_id: caseId,
|
|
212
|
+
verdict: 'human_required', reason_code: 'resolver_selected_clarification',
|
|
213
|
+
reason: 'The accepted Judgment Receipt explicitly selected a missing referent clarification.',
|
|
214
|
+
question, source: 'deterministic', instruction_patch: null, resolver_decision: null
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
if (containsAny(question, AUTHORITY_TERMS)) {
|
|
218
|
+
return {
|
|
219
|
+
schema_version: 'brainbase-autonomy-evaluation-v1', case_id: caseId,
|
|
220
|
+
verdict: 'human_required', reason_code: 'missing_authority_or_secret',
|
|
221
|
+
reason: 'The agent reports a missing authority or secret that the worker cannot invent.',
|
|
222
|
+
question, source: 'deterministic', instruction_patch: null, resolver_decision: null
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
if (containsAny(question, MATERIAL_COMMITMENT_TERMS)) {
|
|
226
|
+
return {
|
|
227
|
+
schema_version: 'brainbase-autonomy-evaluation-v1', case_id: caseId,
|
|
228
|
+
verdict: 'human_required', reason_code: 'material_commitment',
|
|
229
|
+
reason: 'The requested decision creates a material financial, legal, or contractual commitment.',
|
|
230
|
+
question, source: 'deterministic', instruction_patch: null, resolver_decision: null
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
const destructive = containsAny(question, DESTRUCTIVE_TERMS);
|
|
234
|
+
const production = containsAny(question, PRODUCTION_ACTION_TERMS);
|
|
235
|
+
const authorityChange = containsAny(question, AUTHORITY_CHANGE_TERMS);
|
|
236
|
+
const sensitiveData = containsAny(question, SENSITIVE_DATA_TERMS);
|
|
237
|
+
const externalAction = containsAny(question, EXTERNAL_ACTION_TERMS);
|
|
238
|
+
const authorizedReleaseAction = requestAuthorizesExternalAction(context.request, question);
|
|
239
|
+
if (destructive || authorityChange || sensitiveData
|
|
240
|
+
|| ((production || externalAction) && !authorizedReleaseAction)) {
|
|
241
|
+
return {
|
|
242
|
+
schema_version: 'brainbase-autonomy-evaluation-v1', case_id: caseId,
|
|
243
|
+
verdict: 'human_required', reason_code: 'irreversible_external_action',
|
|
244
|
+
reason: 'The requested decision crosses a production, destructive, authority, sensitive-data, or unapproved external-action boundary.',
|
|
245
|
+
question, source: 'deterministic', instruction_patch: null, resolver_decision: null
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
if (containsAny(question, EXPLICIT_NEW_OWNER_VALUE_TERMS)) {
|
|
249
|
+
return {
|
|
250
|
+
schema_version: 'brainbase-autonomy-evaluation-v1', case_id: caseId,
|
|
251
|
+
verdict: 'human_required', reason_code: 'owner_value_choice',
|
|
252
|
+
reason: 'The existing packet does not establish a reusable owner value choice.',
|
|
253
|
+
question, source: 'deterministic', instruction_patch: null, resolver_decision: null
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
if (containsAny(question, ROUTINE_TERMS)) {
|
|
257
|
+
return {
|
|
258
|
+
schema_version: 'brainbase-autonomy-evaluation-v1', case_id: caseId,
|
|
259
|
+
verdict: 'continue', reason_code: 'routine_reversible_work',
|
|
260
|
+
reason: 'The question concerns routine, reversible work already implied by the task.',
|
|
261
|
+
question, source: 'deterministic', instruction_patch: continuationPatch(question, false), resolver_decision: null
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
if (!resolver) {
|
|
265
|
+
return {
|
|
266
|
+
schema_version: 'brainbase-autonomy-evaluation-v1', case_id: caseId,
|
|
267
|
+
verdict: 'continue', reason_code: 'semantic_judgment_required',
|
|
268
|
+
reason: 'The case requires semantic application of Brainbase judgments; the current Codex worker must resolve it before escalating.',
|
|
269
|
+
question, source: 'same_codex', instruction_patch: continuationPatch(question, true), resolver_decision: null
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
const decision = validateResolverDecision(await resolver(resolverRequest(context, question, caseId)), caseId);
|
|
273
|
+
if (decision.verdict === 'human_required') {
|
|
274
|
+
return {
|
|
275
|
+
schema_version: 'brainbase-autonomy-evaluation-v1', case_id: caseId,
|
|
276
|
+
verdict: 'human_required', reason_code: 'resolver_human_required',
|
|
277
|
+
reason: decision.reason, question: decision.human_question ?? question,
|
|
278
|
+
source: 'independent_resolver', instruction_patch: null, resolver_decision: decision
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
return {
|
|
282
|
+
schema_version: 'brainbase-autonomy-evaluation-v1', case_id: caseId,
|
|
283
|
+
verdict: 'continue', reason_code: 'resolver_continue',
|
|
284
|
+
reason: decision.reason, question,
|
|
285
|
+
source: 'independent_resolver', instruction_patch: decision.instruction_patch ?? null,
|
|
286
|
+
resolver_decision: decision
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
export function renderJudgmentAutonomyContinuation(evaluation) {
|
|
290
|
+
if (evaluation.verdict !== 'continue' || !evaluation.instruction_patch) {
|
|
291
|
+
throw new TypeError('Only continue evaluations can be rendered as a continuation');
|
|
292
|
+
}
|
|
293
|
+
const patch = evaluation.instruction_patch;
|
|
294
|
+
return [
|
|
295
|
+
'この確認質問は人間へ送らず、Brainbaseの代理判断ループとして同じターンを続行してください。',
|
|
296
|
+
`判定理由: ${evaluation.reason}`,
|
|
297
|
+
`中止: ${patch.cancel.join(' / ')}`,
|
|
298
|
+
`次に行うこと:\n${patch.do_next.map((item, index) => `${index + 1}. ${item}`).join('\n')}`,
|
|
299
|
+
`完了条件:\n${patch.acceptance_criteria.map((item) => `- ${item}`).join('\n')}`
|
|
300
|
+
].join('\n');
|
|
301
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { JudgmentDAGRunRecord } from './judgment-dag-runner.js';
|
|
2
|
+
export declare const JUDGMENT_DAG_RUN_ARTIFACT_VERSION: "judgment-dag-run-artifact.v1";
|
|
3
|
+
export type JudgmentDAGRunArtifactId = `sha256:${string}`;
|
|
4
|
+
export interface SaveJudgmentDAGRunArtifactRequest {
|
|
5
|
+
readonly root: string;
|
|
6
|
+
readonly record: JudgmentDAGRunRecord;
|
|
7
|
+
}
|
|
8
|
+
export interface LoadJudgmentDAGRunArtifactRequest {
|
|
9
|
+
readonly root: string;
|
|
10
|
+
readonly artifact_id: string;
|
|
11
|
+
}
|
|
12
|
+
export interface JudgmentDAGRunArtifactReceipt {
|
|
13
|
+
readonly artifact_id: JudgmentDAGRunArtifactId;
|
|
14
|
+
readonly artifact_version: typeof JUDGMENT_DAG_RUN_ARTIFACT_VERSION;
|
|
15
|
+
readonly run_id: string;
|
|
16
|
+
readonly status: 'created' | 'existing';
|
|
17
|
+
}
|
|
18
|
+
export type JudgmentDAGArtifactErrorCode = 'invalid_request' | 'invalid_artifact_id' | 'not_found' | 'invalid_artifact' | 'integrity_mismatch' | 'storage_io_error';
|
|
19
|
+
export declare class JudgmentDAGArtifactError extends Error {
|
|
20
|
+
readonly code: JudgmentDAGArtifactErrorCode;
|
|
21
|
+
constructor(code: JudgmentDAGArtifactErrorCode, message: string);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Derive the exact J0 content address for a run record without writing it.
|
|
25
|
+
* The record is validated and normalized with the same contract used by save/load.
|
|
26
|
+
*/
|
|
27
|
+
export declare function computeJudgmentDAGRunArtifactId(value: JudgmentDAGRunRecord): JudgmentDAGRunArtifactId;
|
|
28
|
+
export declare function saveJudgmentDAGRunArtifact(request: SaveJudgmentDAGRunArtifactRequest): Promise<JudgmentDAGRunArtifactReceipt>;
|
|
29
|
+
export declare function loadJudgmentDAGRunArtifact(request: LoadJudgmentDAGRunArtifactRequest): Promise<JudgmentDAGRunRecord>;
|