@quolu/lattice 0.62.1 → 0.62.3
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/package.json +1 -1
- package/src/runtime-pull-intake.mjs +54 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quolu/lattice",
|
|
3
|
-
"version": "0.62.
|
|
3
|
+
"version": "0.62.3",
|
|
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",
|
|
@@ -990,9 +990,24 @@ export async function attachPullWorker({ runDir, taskId, input, environment = pr
|
|
|
990
990
|
const occupied = state.intakes.find((entry) => (
|
|
991
991
|
entry.task_id !== taskId && entry.accepted === null && entry.worker?.pid === input.pid
|
|
992
992
|
));
|
|
993
|
-
if (occupied) {
|
|
993
|
+
if (occupied && occupied.intervention.state !== 'hold') {
|
|
994
994
|
fail('WORKER_ALREADY_ATTACHED', `同じworkerは複数active intakeへattachできない: ${occupied.task_id}`);
|
|
995
995
|
}
|
|
996
|
+
if (occupied && occupied.intervention.state === 'hold') {
|
|
997
|
+
if (occupied.worker.stopped) {
|
|
998
|
+
await signalAttachedWorker(occupied, 'SIGCONT');
|
|
999
|
+
current = await appendEvent(runDir, current, buildEvent({
|
|
1000
|
+
events: current.events, meta: current.meta, kind: 'worker_resumed',
|
|
1001
|
+
taskId: occupied.task_id, payload: { released_by: 'stale_hold_reattach' },
|
|
1002
|
+
}));
|
|
1003
|
+
}
|
|
1004
|
+
current = await appendEvent(runDir, current, buildEvent({
|
|
1005
|
+
events: current.events, meta: current.meta, kind: 'worker_detached',
|
|
1006
|
+
taskId: occupied.task_id,
|
|
1007
|
+
payload: { detached_by: actor, pid: occupied.worker.pid, resumed: occupied.worker.stopped },
|
|
1008
|
+
}));
|
|
1009
|
+
state = project(current.events, current.meta);
|
|
1010
|
+
}
|
|
996
1011
|
if (intake.worker !== null) {
|
|
997
1012
|
if (digestArtifact(binding) !== digestArtifact({
|
|
998
1013
|
pid: intake.worker.pid, process_group_id: intake.worker.process_group_id,
|
|
@@ -1082,6 +1097,16 @@ export async function detachPullWorker({ runDir, taskId, environment = process.e
|
|
|
1082
1097
|
} finally { await lock.release(); }
|
|
1083
1098
|
}
|
|
1084
1099
|
|
|
1100
|
+
export function concurrentAttachBlocked(occupied) {
|
|
1101
|
+
if (!occupied) return false;
|
|
1102
|
+
return occupied.intervention?.state !== 'hold';
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
export function remainingRuntimeConflictFindings(findings, acceptedTaskId) {
|
|
1106
|
+
if (!Array.isArray(findings)) return [];
|
|
1107
|
+
return findings.filter((finding) => !(finding.todo_ids ?? []).includes(acceptedTaskId));
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1085
1110
|
export function observationIntakes(state, includeTaskId = null) {
|
|
1086
1111
|
return state.intakes.filter((entry) => {
|
|
1087
1112
|
if (entry.accepted !== null) return false;
|
|
@@ -1247,6 +1272,34 @@ export async function acceptPullTask({ repoRoot, runDir, taskId, environment = p
|
|
|
1247
1272
|
}));
|
|
1248
1273
|
}
|
|
1249
1274
|
}
|
|
1275
|
+
state = project(current.events, current.meta);
|
|
1276
|
+
for (const waiting of state.intakes.filter((entry) => (
|
|
1277
|
+
entry.accepted === null && entry.intervention.reason === 'runtime_conflict'
|
|
1278
|
+
))) {
|
|
1279
|
+
const remaining = remainingRuntimeConflictFindings(
|
|
1280
|
+
waiting.intervention.detail?.findings, taskId,
|
|
1281
|
+
);
|
|
1282
|
+
if (remaining.length > 0) {
|
|
1283
|
+
if (remaining.length === (waiting.intervention.detail?.findings ?? []).length) continue;
|
|
1284
|
+
current = await changeIntervention(runDir, current, waiting.task_id, {
|
|
1285
|
+
...waiting.intervention,
|
|
1286
|
+
detail: { ...waiting.intervention.detail, findings: remaining },
|
|
1287
|
+
});
|
|
1288
|
+
continue;
|
|
1289
|
+
}
|
|
1290
|
+
const intervention = { state: 'none', reason: null, next_action: null,
|
|
1291
|
+
lease_state: 'granted', detail: { released_by_accepted_task: taskId } };
|
|
1292
|
+
current = await changeIntervention(runDir, current, waiting.task_id, intervention);
|
|
1293
|
+
const resumed = project(current.events, current.meta).intakes
|
|
1294
|
+
.find((entry) => entry.task_id === waiting.task_id);
|
|
1295
|
+
if (resumed.worker?.stopped) {
|
|
1296
|
+
await signalAttachedWorker(resumed, 'SIGCONT');
|
|
1297
|
+
current = await appendEvent(runDir, current, buildEvent({
|
|
1298
|
+
events: current.events, meta: current.meta, kind: 'worker_resumed', taskId: waiting.task_id,
|
|
1299
|
+
payload: { released_by_accepted_task: taskId },
|
|
1300
|
+
}));
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1250
1303
|
const result = { schema: 'lattice.pull_accept_result.v1', outcome: 'accepted',
|
|
1251
1304
|
already_accepted: false, task_id: taskId, head_sha: checkpoint.diff.head_sha,
|
|
1252
1305
|
done_event_digest: done.event_digest, checkpoint_digest: checkpoint.checkpoint_digest };
|