@quolu/lattice 0.69.2 → 0.69.4

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quolu/lattice",
3
- "version": "0.69.2",
3
+ "version": "0.69.4",
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",
@@ -219,7 +219,7 @@ function snapshot(options = {}) {
219
219
  version: options.version ?? 'unknown',
220
220
  state_schema_version: STATE_VERSION,
221
221
  cursor: { high_watermark: store.next_sequence - 1, acknowledged_through: store.acknowledged_through, next: rows.at(-1)?.sequence ?? afterCursor },
222
- runtime_errors: rows.filter((record) => record.status === 'open').map(({ error_code, component, status, severity, fingerprint, message_template, count, first_seen, last_seen, state_schema_version }) => ({ error_code, component, status, severity, fingerprint, message_template, occurrence_count: count, first_seen, last_seen, state_schema_version })),
222
+ runtime_errors: rows.filter((record) => record.status === 'open').map(({ product_version, error_code, component, status, severity, fingerprint, message_template, count, first_seen, last_seen, state_schema_version }) => ({ product_version, error_code, component, status, severity, fingerprint, message_template, occurrence_count: count, first_seen, last_seen, state_schema_version })),
223
223
  resolutions: rows.filter((record) => record.status === 'resolved').map(({ fingerprint, resolved_at, reason_code }) => ({ fingerprint, resolved_at, reason_code })),
224
224
  diagnostics: {
225
225
  collection: enabled ? 'enabled' : 'disabled',
@@ -25,6 +25,25 @@ import {
25
25
  readTodoIndependenceArtifact, readTodoStore, readTodoWitnessSet,
26
26
  } from './todo-store.mjs';
27
27
 
28
+ export function ownScopeGrowth(taskId, finding) {
29
+ return finding?.kind === 'undeclared_write'
30
+ && Array.isArray(finding.todo_ids)
31
+ && finding.todo_ids.length === 1
32
+ && finding.todo_ids[0] === taskId
33
+ && typeof finding.path === 'string'
34
+ && finding.path.length > 0;
35
+ }
36
+
37
+ export function acceptFindings(taskId, findings) {
38
+ const blocking = [];
39
+ const added = [];
40
+ for (const finding of findings) {
41
+ if (ownScopeGrowth(taskId, finding)) added.push(finding.path);
42
+ else blocking.push(finding);
43
+ }
44
+ return { blocking, added_paths: [...new Set(added)].sort() };
45
+ }
46
+
28
47
  export const PULL_RUN_META_SCHEMA = 'lattice.pull_run_meta.v1';
29
48
  const PULL_EVENT_SCHEMA = 'lattice.pull_run_event.v1';
30
49
  const PULL_EVENTS_FILE = 'pull-events.json';
@@ -1219,15 +1238,16 @@ export async function acceptPullTask({ repoRoot, runDir, taskId, environment = p
1219
1238
  const findings = [...direct, ...independent].filter((finding, index, all) => (
1220
1239
  index === all.findIndex((candidate) => digestArtifact(candidate) === digestArtifact(finding))
1221
1240
  ));
1222
- if (findings.length > 0) {
1223
- const affected = new Set(findings.flatMap((finding) => finding.todo_ids));
1241
+ const { blocking, added_paths: addedPaths } = acceptFindings(taskId, findings);
1242
+ if (blocking.length > 0) {
1243
+ const affected = new Set(blocking.flatMap((finding) => finding.todo_ids));
1224
1244
  for (const affectedTaskId of [...affected].sort()) {
1225
1245
  const affectedIntake = project(current.events, current.meta).intakes
1226
1246
  .find((entry) => entry.task_id === affectedTaskId);
1227
1247
  if (!affectedIntake || affectedIntake.accepted !== null) continue;
1228
1248
  const intervention = { state: 'hold', reason: 'runtime_conflict',
1229
1249
  next_action: 'inspect_findings_and_resolve_or_split', lease_state: 'revoked',
1230
- detail: { findings: findings.filter((finding) => finding.todo_ids.includes(affectedTaskId)) } };
1250
+ detail: { findings: blocking.filter((finding) => finding.todo_ids.includes(affectedTaskId)) } };
1231
1251
  current = await changeIntervention(runDir, current, affectedTaskId, intervention);
1232
1252
  const stoppedIntake = project(current.events, current.meta).intakes
1233
1253
  .find((entry) => entry.task_id === affectedTaskId);
@@ -1240,7 +1260,7 @@ export async function acceptPullTask({ repoRoot, runDir, taskId, environment = p
1240
1260
  }
1241
1261
  }
1242
1262
  }
1243
- fail('RUNTIME_CONFLICT_HOLD', 'observed diffがruntime conflictを生成した', { findings });
1263
+ fail('RUNTIME_CONFLICT_HOLD', 'observed diffがruntime conflictを生成した', { findings: blocking });
1244
1264
  }
1245
1265
  if (intake.intervention.state === 'hold' && intake.intervention.reason === 'runtime_conflict') {
1246
1266
  const released = { state: 'none', reason: null, next_action: null,
@@ -1261,7 +1281,8 @@ export async function acceptPullTask({ repoRoot, runDir, taskId, environment = p
1261
1281
  events: current.events, meta: current.meta, kind: 'task_accepted', taskId,
1262
1282
  payload: { done_event_digest: done.event_digest,
1263
1283
  checkpoint_digest: checkpoint.checkpoint_digest, checkpoint,
1264
- head_sha: checkpoint.diff.head_sha },
1284
+ head_sha: checkpoint.diff.head_sha,
1285
+ ...(addedPaths.length > 0 ? { added_paths: addedPaths } : {}) },
1265
1286
  }));
1266
1287
 
1267
1288
  // 先着taskがacceptedになった後、planning conflictだけで待っていた後着を再投影する。