@quolu/lattice 0.50.0 → 0.51.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/bin/lattice-work-order-adapter.mjs +20 -0
- package/docs/schemas/lattice.runtime_adapter_capabilities.v2.schema.json +55 -0
- package/docs/schemas/lattice.runtime_adapter_registration_input.v2.schema.json +86 -0
- package/package.json +5 -2
- package/src/boundary-observation-compiler-v2.mjs +1 -1
- package/src/cli-help.mjs +29 -2
- package/src/rc3-actual-dogfood.mjs +6 -2
- package/src/rc3-scripted-campaign.mjs +37 -10
- package/src/rc4-stage1-dogfood.mjs +6 -2
- package/src/runtime-adapter-registry.mjs +21 -7
- package/src/runtime-cli.mjs +476 -34
- package/src/runtime-contracts.mjs +59 -13
- package/src/runtime-controller-protocol.mjs +48 -3
- package/src/runtime-decision-verifier.mjs +70 -0
- package/src/runtime-diff-observer.mjs +66 -4
- package/src/runtime-direct-os-observer.mjs +25 -8
- package/src/runtime-driver-state.mjs +162 -0
- package/src/runtime-engine.mjs +37 -6
- package/src/runtime-front-end.mjs +39 -1
- package/src/runtime-managed-supervisor.mjs +80 -14
- package/src/runtime-multi-epoch-store.mjs +87 -14
- package/src/runtime-pull-intake.mjs +1188 -0
- package/src/runtime-work-order-contracts.mjs +91 -0
- package/src/runtime-work-order-controller.mjs +1167 -0
- package/src/seam-proposal-queries.mjs +1 -1
- package/src/todo-cli.mjs +199 -5
- package/src/todo-contracts.mjs +4 -1
- package/src/todo-gantt-html-independence.mjs +3 -2
- package/src/todo-gantt-html-shared.mjs +1 -2
- package/src/todo-gantt-html-style.mjs +13 -0
- package/src/todo-gantt-html.mjs +15 -2
- package/src/todo-gantt-layout.mjs +71 -1
- package/src/todo-gantt-live.mjs +12 -1
- package/src/todo-gantt-nested.mjs +243 -0
- package/src/todo-gantt-svg.mjs +80 -5
- package/src/todo-independence-contracts.mjs +73 -7
- package/src/todo-independence-guidance.mjs +30 -1
- package/src/todo-independence.mjs +89 -7
- package/src/todo-revision.mjs +1 -1
- package/src/todo-split.mjs +472 -0
- package/src/todo-store-git-transaction.mjs +418 -0
- package/src/todo-store.mjs +54 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
runWorkOrderAdapterController,
|
|
5
|
+
WorkOrderAdapterControllerError,
|
|
6
|
+
} from '../src/runtime-work-order-controller.mjs';
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
await runWorkOrderAdapterController();
|
|
10
|
+
} catch (error) {
|
|
11
|
+
const payload = {
|
|
12
|
+
schema: 'lattice.work_order_adapter_error.v1',
|
|
13
|
+
code: error instanceof WorkOrderAdapterControllerError
|
|
14
|
+
? error.code
|
|
15
|
+
: 'WORK_ORDER_CONTROLLER_FAILED',
|
|
16
|
+
message: String(error?.message ?? error),
|
|
17
|
+
};
|
|
18
|
+
process.stderr.write(`${JSON.stringify(payload)}\n`);
|
|
19
|
+
process.exitCode = 1;
|
|
20
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/kitepon-rgb/Lattice/blob/main/docs/schemas/lattice.runtime_adapter_capabilities.v2.schema.json",
|
|
4
|
+
"title": "lattice.runtime_adapter_capabilities.v2",
|
|
5
|
+
"description": "controller handshakeとlaunch descriptorを束縛するruntime adapter能力契約。host_driven_epochはhostによるmanaged epoch駆動の受入宣言である。",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"schema",
|
|
10
|
+
"operations",
|
|
11
|
+
"process_observation",
|
|
12
|
+
"worktree_fingerprint",
|
|
13
|
+
"staged_write_lease",
|
|
14
|
+
"durable_dispatch",
|
|
15
|
+
"host_driven_epoch",
|
|
16
|
+
"capabilities_digest"
|
|
17
|
+
],
|
|
18
|
+
"properties": {
|
|
19
|
+
"schema": {
|
|
20
|
+
"const": "lattice.runtime_adapter_capabilities.v2"
|
|
21
|
+
},
|
|
22
|
+
"operations": {
|
|
23
|
+
"const": [
|
|
24
|
+
"dispatch",
|
|
25
|
+
"observe",
|
|
26
|
+
"inventory",
|
|
27
|
+
"barrier",
|
|
28
|
+
"rebind",
|
|
29
|
+
"prepare",
|
|
30
|
+
"activate",
|
|
31
|
+
"release",
|
|
32
|
+
"revoke"
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"process_observation": {
|
|
36
|
+
"const": true
|
|
37
|
+
},
|
|
38
|
+
"worktree_fingerprint": {
|
|
39
|
+
"const": true
|
|
40
|
+
},
|
|
41
|
+
"staged_write_lease": {
|
|
42
|
+
"const": true
|
|
43
|
+
},
|
|
44
|
+
"durable_dispatch": {
|
|
45
|
+
"const": true
|
|
46
|
+
},
|
|
47
|
+
"host_driven_epoch": {
|
|
48
|
+
"type": "boolean"
|
|
49
|
+
},
|
|
50
|
+
"capabilities_digest": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"pattern": "^[0-9a-f]{64}$"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/kitepon-rgb/Lattice/blob/main/docs/schemas/lattice.runtime_adapter_registration_input.v2.schema.json",
|
|
4
|
+
"title": "lattice.runtime_adapter_registration_input.v2",
|
|
5
|
+
"description": "lattice run adapter register の入力契約。host_driven_epochでhostによるmanaged epoch駆動への同意を宣言し、digestと固定capabilitiesはCLIが導出する。",
|
|
6
|
+
"oneOf": [
|
|
7
|
+
{
|
|
8
|
+
"type": "object",
|
|
9
|
+
"additionalProperties": false,
|
|
10
|
+
"required": [
|
|
11
|
+
"schema",
|
|
12
|
+
"adapter_kind",
|
|
13
|
+
"launch_kind",
|
|
14
|
+
"binary_path",
|
|
15
|
+
"argv",
|
|
16
|
+
"config_ref",
|
|
17
|
+
"host_driven_epoch"
|
|
18
|
+
],
|
|
19
|
+
"properties": {
|
|
20
|
+
"schema": {
|
|
21
|
+
"const": "lattice.runtime_adapter_registration_input.v2"
|
|
22
|
+
},
|
|
23
|
+
"adapter_kind": {
|
|
24
|
+
"$ref": "#/$defs/identifier"
|
|
25
|
+
},
|
|
26
|
+
"launch_kind": {
|
|
27
|
+
"const": "host_binary"
|
|
28
|
+
},
|
|
29
|
+
"binary_path": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"pattern": "^/"
|
|
32
|
+
},
|
|
33
|
+
"argv": {
|
|
34
|
+
"type": "array",
|
|
35
|
+
"maxItems": 64,
|
|
36
|
+
"items": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"pattern": "^[^\\u0000]*$"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"config_ref": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"minLength": 1
|
|
44
|
+
},
|
|
45
|
+
"host_driven_epoch": {
|
|
46
|
+
"type": "boolean"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"type": "object",
|
|
52
|
+
"additionalProperties": false,
|
|
53
|
+
"required": [
|
|
54
|
+
"schema",
|
|
55
|
+
"adapter_kind",
|
|
56
|
+
"launch_kind",
|
|
57
|
+
"endpoint",
|
|
58
|
+
"host_driven_epoch"
|
|
59
|
+
],
|
|
60
|
+
"properties": {
|
|
61
|
+
"schema": {
|
|
62
|
+
"const": "lattice.runtime_adapter_registration_input.v2"
|
|
63
|
+
},
|
|
64
|
+
"adapter_kind": {
|
|
65
|
+
"$ref": "#/$defs/identifier"
|
|
66
|
+
},
|
|
67
|
+
"launch_kind": {
|
|
68
|
+
"const": "existing_endpoint"
|
|
69
|
+
},
|
|
70
|
+
"endpoint": {
|
|
71
|
+
"type": "string",
|
|
72
|
+
"minLength": 1
|
|
73
|
+
},
|
|
74
|
+
"host_driven_epoch": {
|
|
75
|
+
"type": "boolean"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
"$defs": {
|
|
81
|
+
"identifier": {
|
|
82
|
+
"type": "string",
|
|
83
|
+
"pattern": "^[0-9A-Za-z](?:[0-9A-Za-z._-]{0,127})$"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quolu/lattice",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.51.0",
|
|
4
4
|
"description": "Schedulability compiler for multi-agent development: observe real code boundaries, refactor the conflicting seam, recompile the plan for parallel execution",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Quo / クオ at kitepon.dev",
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"bin": {
|
|
19
19
|
"lattice": "bin/lattice.mjs",
|
|
20
20
|
"lattice-mcp": "bin/lattice-mcp.mjs",
|
|
21
|
-
"lattice-scripted-adapter": "bin/lattice-scripted-adapter.mjs"
|
|
21
|
+
"lattice-scripted-adapter": "bin/lattice-scripted-adapter.mjs",
|
|
22
|
+
"lattice-work-order-adapter": "bin/lattice-work-order-adapter.mjs"
|
|
22
23
|
},
|
|
23
24
|
"files": [
|
|
24
25
|
"bin",
|
|
@@ -37,6 +38,8 @@
|
|
|
37
38
|
"docs/schemas/lattice.executor_packet.v1.schema.json",
|
|
38
39
|
"docs/schemas/lattice.executor_receipt.v1.schema.json",
|
|
39
40
|
"docs/schemas/lattice.runtime_adapter_registration_input.v1.schema.json",
|
|
41
|
+
"docs/schemas/lattice.runtime_adapter_registration_input.v2.schema.json",
|
|
42
|
+
"docs/schemas/lattice.runtime_adapter_capabilities.v2.schema.json",
|
|
40
43
|
"docs/bridge-setup.md",
|
|
41
44
|
"sensor/dist",
|
|
42
45
|
"!sensor/dist/bin/lattice-sensor.*",
|
|
@@ -6,7 +6,7 @@ const GRAPH_SCHEMA = 'lattice.normalized_boundary_graph.v2';
|
|
|
6
6
|
const MAX_TODOS = 256;
|
|
7
7
|
const IDENTIFIER = /^[0-9A-Za-z](?:[0-9A-Za-z._-]{0,127})$/;
|
|
8
8
|
const DIGEST = /^[0-9a-f]{64}$/;
|
|
9
|
-
const RESOURCE_KINDS = new Set(['symbol', 'path', 'state', 'effect', 'dynamic']);
|
|
9
|
+
const RESOURCE_KINDS = new Set(['symbol', 'path', 'state', 'effect', 'line', 'dynamic']);
|
|
10
10
|
const PROVENANCE_SOURCES = new Set([
|
|
11
11
|
'sensor',
|
|
12
12
|
'manual_candidate_spec',
|
package/src/cli-help.mjs
CHANGED
|
@@ -38,12 +38,22 @@ Commands:
|
|
|
38
38
|
|
|
39
39
|
Commands:
|
|
40
40
|
start --request <request.json> --executor <adapter>
|
|
41
|
+
start --selection pull --id <id> --plan <key> --equipment detached-worktree
|
|
41
42
|
start --schema --json # lattice.run_request.v1 の JSON Schema を出す
|
|
43
|
+
intake --run .lattice/runs/<id> --task <task_id>
|
|
44
|
+
intake release --run .lattice/runs/<id> --task <task_id>
|
|
45
|
+
intake attach --run .lattice/runs/<id> --task <task_id> --input <worker.json>
|
|
46
|
+
intake intervention --run .lattice/runs/<id> --task <task_id>
|
|
47
|
+
intake accept --run .lattice/runs/<id> --task <task_id>
|
|
42
48
|
adapter register --input <descriptor.json>
|
|
43
49
|
adapter register --schema --json # 登録入力の JSON Schema を出す
|
|
44
50
|
adapter list --json
|
|
51
|
+
activate --run .lattice/runs/<id>
|
|
52
|
+
# 全waveが完了するまで戻らないforeground driver。別processのobserve/statusは
|
|
53
|
+
# driver_stateとwaiting_onで、駆動中か・何を待っているかを投影する。
|
|
45
54
|
observe --run .lattice/runs/<id>
|
|
46
55
|
status --run .lattice/runs/<id>
|
|
56
|
+
landing --run .lattice/runs/<id>
|
|
47
57
|
resume --run .lattice/runs/<id>
|
|
48
58
|
close --run .lattice/runs/<id>
|
|
49
59
|
abandon --run .lattice/runs/<id> --reason <reason>
|
|
@@ -95,6 +105,7 @@ Write commands:
|
|
|
95
105
|
seam-proposal compile --plan <key> # 並列可否記録と実sensorからseam提案を記録する
|
|
96
106
|
seam-proposal apply --plan <key> # 記録済み提案を隔離worktreeで適用し五条件で採否を決める
|
|
97
107
|
seam-proposal land --plan <key> --names <file> # 採用された変換を本ツリーへ着地させる
|
|
108
|
+
split --plan <key> --input <file> # in-progress ToDoを抽出群とpending残差へrevisionする
|
|
98
109
|
revise --plan <key> --input <file>
|
|
99
110
|
revise-phase --plan <key> --input <file>
|
|
100
111
|
revise-set --input <file>
|
|
@@ -114,6 +125,11 @@ Write commands:
|
|
|
114
125
|
Write commands require LATTICE_TODO_ACTOR_HOST, LATTICE_TODO_ACTOR_SESSION,
|
|
115
126
|
and LATTICE_TODO_ACTOR_AGENT.
|
|
116
127
|
|
|
128
|
+
storeだけを書き換えるcommandの末尾へ--commit-storeを付けると、共有Git lockを取得し、
|
|
129
|
+
生じた.lattice/todoの変更だけをcommitしてreceiptを返す。
|
|
130
|
+
dirtyなsourceとstore外の既存stageは保持し、store自身がdirtyなら拒否する。
|
|
131
|
+
ignoredな再生成artifactだけを作るindependence/seam-proposal compileは対象外。
|
|
132
|
+
|
|
117
133
|
並列可否(依存線の不在は、書き込み境界が干渉しないことを意味しない):
|
|
118
134
|
${TODO_INDEPENDENCE_WORKFLOW.join('\n')}
|
|
119
135
|
|
|
@@ -171,16 +187,25 @@ const SUBCOMMAND_USAGE = Object.freeze({
|
|
|
171
187
|
'plan show': 'plan show <plan_key> --json',
|
|
172
188
|
'plan compile': 'plan compile --request <request.json> | --schema --json',
|
|
173
189
|
'plan verify': 'plan verify --request <request.json> --plan <plan.json>',
|
|
174
|
-
'run start': 'run start --request <request.json> --executor <adapter>
|
|
190
|
+
'run start': 'run start --request <request.json> --executor <adapter>'
|
|
191
|
+
+ ' | --selection pull --id <id> --plan <key> --equipment detached-worktree | --schema --json',
|
|
192
|
+
'run intake': 'run intake --run .lattice/runs/<id> --task <task_id>',
|
|
193
|
+
'run intake release': 'run intake release --run .lattice/runs/<id> --task <task_id>',
|
|
194
|
+
'run intake attach': 'run intake attach --run .lattice/runs/<id> --task <task_id> --input <worker.json>',
|
|
195
|
+
'run intake intervention': 'run intake intervention --run .lattice/runs/<id> --task <task_id>',
|
|
196
|
+
'run intake accept': 'run intake accept --run .lattice/runs/<id> --task <task_id>',
|
|
175
197
|
'run adapter register': 'run adapter register --input <descriptor.json> | --schema --json',
|
|
176
198
|
'run adapter list': 'run adapter list --json',
|
|
177
199
|
'run observe': 'run observe --run .lattice/runs/<id>',
|
|
178
200
|
'run status': 'run status --run .lattice/runs/<id>',
|
|
179
201
|
'run resume': 'run resume --run .lattice/runs/<id>',
|
|
202
|
+
'run landing': 'run landing --run .lattice/runs/<id>',
|
|
180
203
|
'run close': 'run close --run .lattice/runs/<id>',
|
|
181
204
|
'run abandon': 'run abandon --run .lattice/runs/<id> --reason <reason>',
|
|
182
205
|
'run list': 'run list --json',
|
|
183
|
-
'run activate': 'run activate --run .lattice/runs/<id
|
|
206
|
+
'run activate': 'run activate --run .lattice/runs/<id>\n\n'
|
|
207
|
+
+ '全waveが完了するまで戻らないforeground driver。別processのrun observe/statusは\n'
|
|
208
|
+
+ 'driver_stateとwaiting_onで、駆動中か・何を待っているかを投影する。',
|
|
184
209
|
'run conflict': 'run conflict --run .lattice/runs/<id> --finding <digest>',
|
|
185
210
|
'run hold': 'run hold --run .lattice/runs/<id> --finding <digest>',
|
|
186
211
|
'run recompile': 'run recompile --run .lattice/runs/<id> --input <recompile-request.json>',
|
|
@@ -215,12 +240,14 @@ const SUBCOMMAND_USAGE = Object.freeze({
|
|
|
215
240
|
'todo phase close-unaudited': 'todo phase close-unaudited --plan <key> --phase <id> --reason <text>',
|
|
216
241
|
'todo phase baseline': 'todo phase baseline --reason <text> [--except <plan_key>]...',
|
|
217
242
|
'todo start': 'todo start --plan <key> --task <id> [--parallel-frontier|--override-reason <text>]',
|
|
243
|
+
'todo retract': 'todo retract --plan <key> --task <id> --reason <text>',
|
|
218
244
|
'todo block': 'todo block --plan <key> --task <id> --reason <text>',
|
|
219
245
|
'todo unblock': 'todo unblock --plan <key> --task <id>',
|
|
220
246
|
'todo done': 'todo done --plan <key> --task <id> --evidence <file>',
|
|
221
247
|
'todo reopen': 'todo reopen --plan <key> --task <id> --reason <text> [--override-reason <text>]',
|
|
222
248
|
'todo evidence': 'todo evidence promote --plan <key> --task <id> --evidence <file>',
|
|
223
249
|
'todo evidence promote': 'todo evidence promote --plan <key> --task <id> --evidence <file>',
|
|
250
|
+
'todo split': 'todo split --plan <key> --input <file>',
|
|
224
251
|
'todo revise': 'todo revise --plan <key> --input <file> | --schema --json',
|
|
225
252
|
'todo revise-phase': 'todo revise-phase --plan <key> --input <file> | --schema --json',
|
|
226
253
|
'todo revise-set': 'todo revise-set --input <file> | --schema --json',
|
|
@@ -263,12 +263,16 @@ export async function observeActualCheckpoint({ stateDir, todoId, planKey = 'pla
|
|
|
263
263
|
const classifyPackets = { ...state.packets, ...(state.redispatchPackets ?? {}) };
|
|
264
264
|
void packets;
|
|
265
265
|
const classified = classifyCheckpointObservation({
|
|
266
|
-
runId: RUN_ID, plan, events, packets: classifyPackets, todoId,
|
|
266
|
+
runId: RUN_ID, plan, events, packets: classifyPackets, manifests: state.manifests, todoId,
|
|
267
267
|
detect: detectCheckpointFindings, recordedAt: RUN_TIMESTAMP,
|
|
268
268
|
});
|
|
269
269
|
state.events = classified.events;
|
|
270
270
|
await saveState(stateDir, state);
|
|
271
|
-
return {
|
|
271
|
+
return {
|
|
272
|
+
findings: classified.findings,
|
|
273
|
+
scope_expanded: classified.scope_expanded,
|
|
274
|
+
checkpoint_digest: checkpoint.checkpoint_digest,
|
|
275
|
+
};
|
|
272
276
|
}
|
|
273
277
|
|
|
274
278
|
/** hold裁定→recompile→(carried TODOの)rebind packet発行までを一括で行う。 */
|
|
@@ -149,8 +149,9 @@ function docWriter(docPath, body) {
|
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
/** 全running executorを1回ずつ観測し、checkpointがあれば分類する共通driver。 */
|
|
152
|
-
async function observeAndClassifyAll({ runId, plan, events, packets, adapter }) {
|
|
152
|
+
async function observeAndClassifyAll({ runId, plan, events, packets, manifests, adapter }) {
|
|
153
153
|
let next = events;
|
|
154
|
+
const scopeExpanded = [];
|
|
154
155
|
const state = projectRuntimeState({ events: next });
|
|
155
156
|
for (const todoId of state.running) {
|
|
156
157
|
const observed = await observeExecutor({
|
|
@@ -159,33 +160,40 @@ async function observeAndClassifyAll({ runId, plan, events, packets, adapter })
|
|
|
159
160
|
next = observed.events;
|
|
160
161
|
if (observed.observation.state === 'checkpoint_ready') {
|
|
161
162
|
const classified = classifyCheckpointObservation({
|
|
162
|
-
runId, plan, events: next, packets, todoId,
|
|
163
|
+
runId, plan, events: next, packets, manifests, todoId,
|
|
163
164
|
detect: detectCheckpointFindings, recordedAt: RUN_TIMESTAMP,
|
|
164
165
|
});
|
|
165
166
|
next = classified.events;
|
|
166
|
-
|
|
167
|
+
scopeExpanded.push(...classified.scope_expanded);
|
|
168
|
+
if (classified.findings.length > 0) {
|
|
169
|
+
return { events: next, frozen: true, scope_expanded: scopeExpanded };
|
|
170
|
+
}
|
|
167
171
|
}
|
|
168
172
|
}
|
|
169
|
-
return { events: next, frozen: false };
|
|
173
|
+
return { events: next, frozen: false, scope_expanded: scopeExpanded };
|
|
170
174
|
}
|
|
171
175
|
|
|
172
176
|
/** 競合なし前提でclosed loopまで回す(clean/irreducible串行の完走用)。 */
|
|
173
177
|
async function driveToClose({ runId, plan, events, packets, manifests, adapter, maxRounds = 16 }) {
|
|
174
178
|
let next = events;
|
|
179
|
+
const scopeExpanded = [];
|
|
175
180
|
for (let round = 0; round < maxRounds; round += 1) {
|
|
176
181
|
const dispatched = await dispatchReadyFrontier({
|
|
177
182
|
runId, plan, events: next, packets, manifests, adapter, recordedAt: RUN_TIMESTAMP,
|
|
178
183
|
});
|
|
179
184
|
if (dispatched.failure) fail(`dispatch失敗: ${dispatched.failure.message}`);
|
|
180
185
|
next = dispatched.events;
|
|
181
|
-
const observed = await observeAndClassifyAll({
|
|
186
|
+
const observed = await observeAndClassifyAll({
|
|
187
|
+
runId, plan, events: next, packets, manifests, adapter,
|
|
188
|
+
});
|
|
182
189
|
if (observed.frozen) fail('競合なし条件でfreezeが発生した');
|
|
183
190
|
next = observed.events;
|
|
191
|
+
scopeExpanded.push(...observed.scope_expanded);
|
|
184
192
|
const adjudicated = adjudicatePendingReceipts({ runId, plan, events: next, recordedAt: RUN_TIMESTAMP });
|
|
185
193
|
next = adjudicated.events;
|
|
186
194
|
const closed = closeRunIfComplete({ runId, plan, events: next, recordedAt: RUN_TIMESTAMP });
|
|
187
195
|
next = closed.events;
|
|
188
|
-
if (closed.closed) return next;
|
|
196
|
+
if (closed.closed) return { events: next, scope_expanded: scopeExpanded };
|
|
189
197
|
}
|
|
190
198
|
fail('closed loopがmaxRounds内に完走しない');
|
|
191
199
|
return null;
|
|
@@ -292,12 +300,14 @@ async function runCleanParallel({ scaffold }) {
|
|
|
292
300
|
},
|
|
293
301
|
});
|
|
294
302
|
let events = initializeRunEvents({ runId, request, plan, manifests, recordedAt: RUN_TIMESTAMP });
|
|
295
|
-
|
|
303
|
+
const driven = await driveToClose({ runId, plan, events, packets, manifests, adapter });
|
|
304
|
+
events = driven.events;
|
|
296
305
|
const state = projectRuntimeState({ events });
|
|
297
306
|
return {
|
|
298
307
|
request,
|
|
299
308
|
plan,
|
|
300
309
|
events,
|
|
310
|
+
scope_expanded: driven.scope_expanded,
|
|
301
311
|
record: conditionRecord({
|
|
302
312
|
condition: 'clean_parallel',
|
|
303
313
|
expected: { hold: [], continue: ['TA', 'TB', 'TC'], accepted: ['TA', 'TB', 'TC'], closed: true },
|
|
@@ -352,7 +362,8 @@ async function runLateConflict({ scaffold }) {
|
|
|
352
362
|
const observed = await observeExecutor({ runId, plan, events, adapter, todoId, recordedAt: RUN_TIMESTAMP });
|
|
353
363
|
events = observed.events;
|
|
354
364
|
const classified = classifyCheckpointObservation({
|
|
355
|
-
runId, plan, events, packets,
|
|
365
|
+
runId, plan, events, packets, manifests, todoId,
|
|
366
|
+
detect: detectCheckpointFindings, recordedAt: RUN_TIMESTAMP,
|
|
356
367
|
});
|
|
357
368
|
events = classified.events;
|
|
358
369
|
}
|
|
@@ -464,22 +475,36 @@ async function runScopeViolation({ scaffold }) {
|
|
|
464
475
|
const observed = await observeExecutor({ runId, plan, events, adapter, todoId: 'TA', recordedAt: RUN_TIMESTAMP });
|
|
465
476
|
events = observed.events;
|
|
466
477
|
const classified = classifyCheckpointObservation({
|
|
467
|
-
runId, plan, events, packets, todoId: 'TA',
|
|
478
|
+
runId, plan, events, packets, manifests, todoId: 'TA',
|
|
479
|
+
detect: detectCheckpointFindings, recordedAt: RUN_TIMESTAMP,
|
|
468
480
|
});
|
|
469
481
|
events = classified.events;
|
|
470
|
-
|
|
482
|
+
const driven = await driveToClose({ runId, plan, events, packets, manifests, adapter });
|
|
483
|
+
events = driven.events;
|
|
484
|
+
const scopeExpanded = [...classified.scope_expanded, ...driven.scope_expanded];
|
|
471
485
|
const state = projectRuntimeState({ events });
|
|
472
486
|
return {
|
|
473
487
|
request,
|
|
474
488
|
plan,
|
|
475
489
|
manifests,
|
|
476
490
|
events,
|
|
491
|
+
scope_expanded: scopeExpanded,
|
|
477
492
|
record: conditionRecord({
|
|
478
493
|
condition: 'scope_violation',
|
|
479
494
|
// directory名はRC3 artifact互換のため維持する。現契約では単独の予測超過は
|
|
480
495
|
// conflictではなく、観測を残したまま有効なreceiptを受理する。
|
|
481
496
|
expected: {
|
|
482
497
|
observation_kinds: ['prediction_excess'],
|
|
498
|
+
scope_expanded: [{
|
|
499
|
+
task_id: 'TA',
|
|
500
|
+
compared_witness_digest: null,
|
|
501
|
+
first_seen_path_count: 1,
|
|
502
|
+
path_count: 2,
|
|
503
|
+
added_paths: ['docs/rogue.md'],
|
|
504
|
+
removed_paths: [],
|
|
505
|
+
growth_events: 1,
|
|
506
|
+
gate_shape: false,
|
|
507
|
+
}],
|
|
483
508
|
conflict_finding_kinds: [],
|
|
484
509
|
frozen: false,
|
|
485
510
|
accepted: ['TA', 'TB'],
|
|
@@ -487,6 +512,7 @@ async function runScopeViolation({ scaffold }) {
|
|
|
487
512
|
},
|
|
488
513
|
actual: {
|
|
489
514
|
observation_kinds: [...new Set(classified.observations.map(({ kind }) => kind))],
|
|
515
|
+
scope_expanded: scopeExpanded,
|
|
490
516
|
conflict_finding_kinds: [...new Set(classified.findings.map(({ kind }) => kind))],
|
|
491
517
|
frozen: state.freeze !== null,
|
|
492
518
|
accepted: state.accepted,
|
|
@@ -1352,5 +1378,6 @@ export async function runRc3ScriptedCampaign(options = {}) {
|
|
|
1352
1378
|
campaignManifest,
|
|
1353
1379
|
verification,
|
|
1354
1380
|
conditions: results.map(({ record }) => record.condition),
|
|
1381
|
+
scope_expanded: results.flatMap((result) => result.scope_expanded ?? []),
|
|
1355
1382
|
};
|
|
1356
1383
|
}
|
|
@@ -264,12 +264,16 @@ export async function observeStage1Checkpoint({ stateDir, todoId, planKey = 'pla
|
|
|
264
264
|
}));
|
|
265
265
|
const classifyPackets = { ...state.packets, ...(state.redispatchPackets ?? {}) };
|
|
266
266
|
const classified = classifyCheckpointObservation({
|
|
267
|
-
runId: RUN_ID, plan, events, packets: classifyPackets, todoId,
|
|
267
|
+
runId: RUN_ID, plan, events, packets: classifyPackets, manifests: state.manifests, todoId,
|
|
268
268
|
detect: detectCheckpointFindings, recordedAt: RUN_TIMESTAMP,
|
|
269
269
|
});
|
|
270
270
|
state.events = classified.events;
|
|
271
271
|
await saveState(stateDir, state);
|
|
272
|
-
return {
|
|
272
|
+
return {
|
|
273
|
+
findings: classified.findings,
|
|
274
|
+
scope_expanded: classified.scope_expanded,
|
|
275
|
+
checkpoint_digest: checkpoint.checkpoint_digest,
|
|
276
|
+
};
|
|
273
277
|
}
|
|
274
278
|
|
|
275
279
|
/** hold裁定→recompile→(carried TODOの)rebind packet発行までを一括で行う受け皿。 */
|
|
@@ -21,7 +21,8 @@ import {
|
|
|
21
21
|
import { selfDigest } from './runtime-contracts.mjs';
|
|
22
22
|
import { observeMacosBinaryIdentity } from './runtime-managed-supervisor.mjs';
|
|
23
23
|
|
|
24
|
-
const INPUT_SCHEMA = 'lattice.runtime_adapter_registration_input.
|
|
24
|
+
const INPUT_SCHEMA = 'lattice.runtime_adapter_registration_input.v2';
|
|
25
|
+
const LEGACY_INPUT_SCHEMA = 'lattice.runtime_adapter_registration_input.v1';
|
|
25
26
|
const REGISTRY_SCHEMA = 'lattice.runtime_adapter_registry.v1';
|
|
26
27
|
const DESCRIPTOR_SCHEMA = 'lattice.runtime_adapter_launch_descriptor.v1';
|
|
27
28
|
const REGISTRY_REF = '.lattice/runtime/adapter-registry/registry.json';
|
|
@@ -68,10 +69,17 @@ function inputFailure(reason, inputPath = '') {
|
|
|
68
69
|
|
|
69
70
|
function validateRegistrationInput(value) {
|
|
70
71
|
if (!plain(value)) inputFailure('input_must_be_object');
|
|
71
|
-
if (value.schema
|
|
72
|
+
if (![LEGACY_INPUT_SCHEMA, INPUT_SCHEMA].includes(value.schema)) {
|
|
73
|
+
inputFailure('unsupported_schema', '/schema');
|
|
74
|
+
}
|
|
72
75
|
if (!ID.test(value.adapter_kind ?? '')) inputFailure('invalid_adapter_kind', '/adapter_kind');
|
|
76
|
+
const hostDrivenFields = value.schema === INPUT_SCHEMA ? ['host_driven_epoch'] : [];
|
|
77
|
+
if (value.schema === INPUT_SCHEMA && typeof value.host_driven_epoch !== 'boolean') {
|
|
78
|
+
inputFailure('host_driven_epoch_must_be_boolean', '/host_driven_epoch');
|
|
79
|
+
}
|
|
73
80
|
if (value.launch_kind === 'host_binary') {
|
|
74
|
-
if (!exact(value, ['schema', 'adapter_kind', 'launch_kind', 'binary_path', 'argv',
|
|
81
|
+
if (!exact(value, ['schema', 'adapter_kind', 'launch_kind', 'binary_path', 'argv',
|
|
82
|
+
'config_ref', ...hostDrivenFields])) {
|
|
75
83
|
inputFailure('unexpected_or_missing_keys');
|
|
76
84
|
}
|
|
77
85
|
if (typeof value.binary_path !== 'string' || !path.isAbsolute(value.binary_path)) {
|
|
@@ -87,7 +95,8 @@ function validateRegistrationInput(value) {
|
|
|
87
95
|
return;
|
|
88
96
|
}
|
|
89
97
|
if (value.launch_kind === 'existing_endpoint') {
|
|
90
|
-
if (!exact(value, ['schema', 'adapter_kind', 'launch_kind', 'endpoint'
|
|
98
|
+
if (!exact(value, ['schema', 'adapter_kind', 'launch_kind', 'endpoint',
|
|
99
|
+
...hostDrivenFields])) {
|
|
91
100
|
inputFailure('unexpected_or_missing_keys');
|
|
92
101
|
}
|
|
93
102
|
if (typeof value.endpoint !== 'string' || value.endpoint.length === 0) {
|
|
@@ -104,9 +113,11 @@ function validateRegistrationInput(value) {
|
|
|
104
113
|
inputFailure('unsupported_launch_kind', '/launch_kind');
|
|
105
114
|
}
|
|
106
115
|
|
|
107
|
-
function createCapabilities() {
|
|
116
|
+
function createCapabilities(input = { schema: LEGACY_INPUT_SCHEMA }) {
|
|
108
117
|
const capabilities = {
|
|
109
|
-
schema:
|
|
118
|
+
schema: input.schema === INPUT_SCHEMA
|
|
119
|
+
? 'lattice.runtime_adapter_capabilities.v2'
|
|
120
|
+
: 'lattice.runtime_adapter_capabilities.v1',
|
|
110
121
|
operations: [...CONTROLLER_OPERATIONS],
|
|
111
122
|
process_observation: true,
|
|
112
123
|
worktree_fingerprint: true,
|
|
@@ -114,6 +125,9 @@ function createCapabilities() {
|
|
|
114
125
|
durable_dispatch: true,
|
|
115
126
|
capabilities_digest: '',
|
|
116
127
|
};
|
|
128
|
+
if (input.schema === INPUT_SCHEMA) {
|
|
129
|
+
capabilities.host_driven_epoch = input.host_driven_epoch;
|
|
130
|
+
}
|
|
117
131
|
capabilities.capabilities_digest = selfDigest(capabilities, 'capabilities_digest');
|
|
118
132
|
if (!validateRuntimeAdapterCapabilities(capabilities)) {
|
|
119
133
|
throw new TypeError('runtime adapter capabilities生成不正');
|
|
@@ -326,7 +340,7 @@ async function resolveHostBinary(repoRoot, input, binaryIdentityObserver) {
|
|
|
326
340
|
}
|
|
327
341
|
|
|
328
342
|
async function buildLaunchDescriptor(repoRoot, input, binaryIdentityObserver) {
|
|
329
|
-
const capabilities = createCapabilities();
|
|
343
|
+
const capabilities = createCapabilities(input);
|
|
330
344
|
let observation = { status: 'not_applicable', reason: null, message: null };
|
|
331
345
|
let descriptor;
|
|
332
346
|
if (input.launch_kind === 'host_binary') {
|