@quolu/lattice 0.58.1 → 0.58.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/todo-cli.mjs +42 -8
- package/src/todo-structure-overlay.mjs +8 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quolu/lattice",
|
|
3
|
-
"version": "0.58.
|
|
3
|
+
"version": "0.58.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",
|
package/src/todo-cli.mjs
CHANGED
|
@@ -646,7 +646,7 @@ function terminalAuditDoneAdvisory(plan, phases) {
|
|
|
646
646
|
|
|
647
647
|
async function mutate({
|
|
648
648
|
repoRoot, env, planKey, taskId, kind, payload, evidenceRef, advisory = null,
|
|
649
|
-
noteContext = null,
|
|
649
|
+
noteContext = null, structureContext = null,
|
|
650
650
|
}) {
|
|
651
651
|
const actor = mutationActor(env);
|
|
652
652
|
const evidence = evidenceRef === null ? null : await readEvidenceInput(repoRoot, evidenceRef);
|
|
@@ -674,7 +674,7 @@ async function mutate({
|
|
|
674
674
|
throw new TypeError('start mutation requires note context');
|
|
675
675
|
}
|
|
676
676
|
const result = {
|
|
677
|
-
schema: includesNoteContext ? 'lattice.todo_mutation_result.
|
|
677
|
+
schema: includesNoteContext ? 'lattice.todo_mutation_result.v5' : 'lattice.todo_mutation_result.v2',
|
|
678
678
|
project_id: event.project_id,
|
|
679
679
|
plan_key: event.plan_key,
|
|
680
680
|
plan_version: event.plan_version,
|
|
@@ -689,6 +689,7 @@ async function mutate({
|
|
|
689
689
|
...(includesNoteContext ? {
|
|
690
690
|
design_memo: designMemoProjection(authoredTask),
|
|
691
691
|
note_context: noteContext,
|
|
692
|
+
structure_context: structureContext,
|
|
692
693
|
} : {}),
|
|
693
694
|
result_digest: '',
|
|
694
695
|
};
|
|
@@ -696,6 +697,38 @@ async function mutate({
|
|
|
696
697
|
return result;
|
|
697
698
|
}
|
|
698
699
|
|
|
700
|
+
async function startStructureContext({ repoRoot, store, planKey, taskId }) {
|
|
701
|
+
const member = store.members.find(({ descriptor }) => descriptor.plan_key === planKey);
|
|
702
|
+
if (member === undefined) throw new TodoStoreError('STORE_INCONSISTENT', 'plan_not_active');
|
|
703
|
+
const source = await readTodoStructureSource({ repoRoot, planKey });
|
|
704
|
+
const binding = await readTodoStructureBinding({
|
|
705
|
+
repoRoot, planKey, planVersion: member.plan.plan_version,
|
|
706
|
+
});
|
|
707
|
+
if (source === null || binding === null) return {
|
|
708
|
+
status: 'not_enabled', enabled: false, freshness: null, stale_reasons: [],
|
|
709
|
+
structure_set_digest: null, task: null, next_actions: [],
|
|
710
|
+
};
|
|
711
|
+
if (source.structure_set_digest !== binding.structure_set_digest) {
|
|
712
|
+
throw new TodoStoreError('STRUCTURE_LIFECYCLE_GATE_FAILED',
|
|
713
|
+
'enabled_structure_source_unreadable', undefined, { plan_key: planKey });
|
|
714
|
+
}
|
|
715
|
+
const task = source.tasks.find(({ task_id: id }) => id === taskId);
|
|
716
|
+
if (task === undefined) {
|
|
717
|
+
throw new TodoStoreError('STRUCTURE_LIFECYCLE_GATE_FAILED',
|
|
718
|
+
'enabled_structure_task_missing', undefined, { plan_key: planKey, task_id: taskId });
|
|
719
|
+
}
|
|
720
|
+
const state = await readTodoStructureState({ repoRoot, store, planKey });
|
|
721
|
+
return {
|
|
722
|
+
status: 'available', enabled: true, freshness: state.status,
|
|
723
|
+
stale_reasons: state.stale_reasons,
|
|
724
|
+
structure_set_digest: source.structure_set_digest,
|
|
725
|
+
task: structuredClone(task),
|
|
726
|
+
next_actions: task.applicability === 'graph'
|
|
727
|
+
? [`lattice todo structure realize --plan ${planKey} --task ${taskId} --input <realization.json>`]
|
|
728
|
+
: [],
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
|
|
699
732
|
function designMemoProjection(task) {
|
|
700
733
|
if (typeof task.design_memo === 'string') {
|
|
701
734
|
return { status: 'available', markdown: task.design_memo, prompt: TODO_DESIGN_MEMO_PROMPT };
|
|
@@ -898,8 +931,12 @@ async function startTask({
|
|
|
898
931
|
const advisory = await startAdvisory({
|
|
899
932
|
repoRoot, store, projection, planKey, taskId: resolvedTaskId,
|
|
900
933
|
});
|
|
934
|
+
const structureContext = await startStructureContext({
|
|
935
|
+
repoRoot, store, planKey, taskId: resolvedTaskId,
|
|
936
|
+
});
|
|
901
937
|
return mutate({ repoRoot, env, planKey, taskId: resolvedTaskId, kind: 'start',
|
|
902
|
-
payload: { override_reason: overrideReason }, evidenceRef: null, advisory, noteContext
|
|
938
|
+
payload: { override_reason: overrideReason }, evidenceRef: null, advisory, noteContext,
|
|
939
|
+
structureContext });
|
|
903
940
|
}
|
|
904
941
|
|
|
905
942
|
async function retractStart({ repoRoot, env, planKey, taskId, reason }) {
|
|
@@ -2035,10 +2072,7 @@ async function structureCompile({ repoRoot, env, planKey, inputRef }) {
|
|
|
2035
2072
|
const overlay = compileTodoStructureOverlay({
|
|
2036
2073
|
structureSet,
|
|
2037
2074
|
topology: mergedTopology(store),
|
|
2038
|
-
taskStates:
|
|
2039
|
-
task_id: taskId,
|
|
2040
|
-
status: member.tasks.find(({ task_id: id }) => id === taskId)?.status ?? 'pending',
|
|
2041
|
-
})),
|
|
2075
|
+
taskStates: member.tasks.map(({ task_id: taskId, status }) => ({ task_id: taskId, status })),
|
|
2042
2076
|
sourceProjection: sourceEvidence.projection,
|
|
2043
2077
|
gitProvenance,
|
|
2044
2078
|
realizations,
|
|
@@ -2196,7 +2230,7 @@ async function structureFinalize({ repoRoot, env, planKey }) {
|
|
|
2196
2230
|
const overlay = compileTodoStructureOverlay({
|
|
2197
2231
|
structureSet: source,
|
|
2198
2232
|
topology: mergedTopology(store),
|
|
2199
|
-
taskStates:
|
|
2233
|
+
taskStates: member.tasks.map(({ task_id: taskId, status }) => ({ task_id: taskId, status })),
|
|
2200
2234
|
sourceProjection: sourceEvidence.projection,
|
|
2201
2235
|
gitProvenance,
|
|
2202
2236
|
realizations,
|
|
@@ -62,12 +62,14 @@ function normalizeTaskStates(structureSet, taskStates) {
|
|
|
62
62
|
if (!isPlain(entry) || Object.keys(entry).length !== 2
|
|
63
63
|
|| typeof entry.task_id !== 'string'
|
|
64
64
|
|| !['pending', 'in-progress', 'blocked', 'done'].includes(entry.status)
|
|
65
|
-
||
|
|
65
|
+
|| states.has(entry.task_id)) {
|
|
66
66
|
fail('STRUCTURE_OVERLAY_INPUT_INVALID', 'task_state_entry_invalid');
|
|
67
67
|
}
|
|
68
68
|
states.set(entry.task_id, entry.status);
|
|
69
69
|
}
|
|
70
|
-
if (
|
|
70
|
+
if ([...expected].some((taskId) => !states.has(taskId))) {
|
|
71
|
+
fail('STRUCTURE_OVERLAY_INPUT_INVALID', 'task_state_coverage_invalid');
|
|
72
|
+
}
|
|
71
73
|
return states;
|
|
72
74
|
}
|
|
73
75
|
|
|
@@ -302,7 +304,7 @@ function buildOverlayGraph(structureSet, states, latestRealizations, sourceProje
|
|
|
302
304
|
return { nodes: uniqueNodes, edges, effective };
|
|
303
305
|
}
|
|
304
306
|
|
|
305
|
-
function connectionFindings(structureSet, effective, topologyDag) {
|
|
307
|
+
function connectionFindings(structureSet, effective, topologyDag, states) {
|
|
306
308
|
const findings = [];
|
|
307
309
|
const externalById = new Map(structureSet.external_contracts
|
|
308
310
|
.map((external) => [external.contract_id, external]));
|
|
@@ -322,7 +324,8 @@ function connectionFindings(structureSet, effective, topologyDag) {
|
|
|
322
324
|
const structureTaskIds = new Set(structureSet.tasks.map(({ task_id: id }) => id));
|
|
323
325
|
const extraTopologyTasks = topologyDag.nodes
|
|
324
326
|
.filter(({ ref }) => ref.project_id === structureSet.project_id
|
|
325
|
-
&& ref.plan_key === structureSet.plan_key && !structureTaskIds.has(ref.task_id)
|
|
327
|
+
&& ref.plan_key === structureSet.plan_key && !structureTaskIds.has(ref.task_id)
|
|
328
|
+
&& states.get(ref.task_id) !== 'done')
|
|
326
329
|
.map(({ ref }) => ref.task_id).sort(compareText);
|
|
327
330
|
if (extraTopologyTasks.length > 0) findings.push(finding({
|
|
328
331
|
code: 'STRUCTURE_COVERAGE_MISSING', severity: 'error', taskIds: extraTopologyTasks,
|
|
@@ -557,7 +560,7 @@ export function compileTodoStructureOverlay({
|
|
|
557
560
|
const rawFindings = [
|
|
558
561
|
...anchorFindings(structureSet, sourceProjection),
|
|
559
562
|
...missingEffectiveAnchors,
|
|
560
|
-
...connectionFindings(structureSet, graph.effective, topologyDag),
|
|
563
|
+
...connectionFindings(structureSet, graph.effective, topologyDag, states),
|
|
561
564
|
...realizationFindings(
|
|
562
565
|
structureSet, states, normalizedRealizations, gitProvenance, graph.effective,
|
|
563
566
|
),
|