@quolu/lattice 0.62.3 → 0.63.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.ja.md +4 -0
- package/README.md +3 -0
- package/package.json +1 -1
- package/src/cli-help.mjs +3 -1
- package/src/todo-cli.mjs +46 -3
- package/src/todo-independence-guidance.mjs +28 -3
package/README.ja.md
CHANGED
|
@@ -228,6 +228,10 @@ lattice todo start --plan <key> --task <id> --parallel-frontier
|
|
|
228
228
|
lattice todo start --plan <key> --task <id> --override-reason <reason>
|
|
229
229
|
```
|
|
230
230
|
|
|
231
|
+
記録があるのに対象工程が未宣言・失効なら`todo start`は`INDEPENDENCE_UNVERIFIED`で拒否します。
|
|
232
|
+
`independence compile`は`next_ready`がwitnessに無いとき`INDEPENDENCE_READY_UNDECLARED`で拒否します。
|
|
233
|
+
remainingのA工程は同じwitnessへ含めます。競合の同時起動は助言のままです。
|
|
234
|
+
|
|
231
235
|
`--serial-confirmed`と`--serialization-reviewed`は古い手順の互換として受理しますが、
|
|
232
236
|
再実行の条件ではありません。直列理由の文言を審査して拒否することもありません。
|
|
233
237
|
|
package/README.md
CHANGED
|
@@ -193,6 +193,9 @@ lattice todo seam-proposal land --plan <key> --names names.json
|
|
|
193
193
|
parallel set. Starting one of them does not require `--parallel-frontier` or
|
|
194
194
|
`--override-reason`. Those flags record intent; they are not gates.
|
|
195
195
|
`--serial-confirmed` and `--serialization-reviewed` are accepted only for compatibility.
|
|
196
|
+
If an independence record exists but the task is undeclared or stale, `todo start`
|
|
197
|
+
fails with `INDEPENDENCE_UNVERIFIED`. `independence compile` fails with
|
|
198
|
+
`INDEPENDENCE_READY_UNDECLARED` when `next_ready` is missing from the witness.
|
|
196
199
|
|
|
197
200
|
```bash
|
|
198
201
|
lattice todo start --plan <key> --task <id>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quolu/lattice",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.63.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",
|
package/src/cli-help.mjs
CHANGED
|
@@ -156,7 +156,9 @@ ${TODO_INDEPENDENCE_WORKFLOW.join('\n')}
|
|
|
156
156
|
|
|
157
157
|
判定していない工程は「競合が無い」ではなく「未検査」として扱われ、
|
|
158
158
|
todo startのadvisoryとtodo independenceの投影が、その状況と次の一歩を返す。
|
|
159
|
-
|
|
159
|
+
記録があるのに対象工程が未宣言・失効なら todo start は拒否する。
|
|
160
|
+
next_ready が witness に無い independence compile も拒否する。
|
|
161
|
+
競合の同時起動は助言のまま。並列既定はstatusのdispatch_frontierとnext_actionが案内する。
|
|
160
162
|
`,
|
|
161
163
|
sensor: `Usage: lattice sensor <init|sync> [path] --json
|
|
162
164
|
lattice sensor diff <rootA> <rootB> [options] --json
|
package/src/todo-cli.mjs
CHANGED
|
@@ -133,8 +133,10 @@ import {
|
|
|
133
133
|
compileTodoIndependence,
|
|
134
134
|
migrateWitnessSetTaskIds,
|
|
135
135
|
projectIndependenceFrontier,
|
|
136
|
+
TodoIndependenceError,
|
|
136
137
|
} from './todo-independence.mjs';
|
|
137
138
|
import {
|
|
139
|
+
independenceStartRefusal,
|
|
138
140
|
selectIndependenceGuidance,
|
|
139
141
|
selectWitnessScaffoldGuidance,
|
|
140
142
|
selectSeamProposalGuidance,
|
|
@@ -728,8 +730,9 @@ function designMemoProjection(task) {
|
|
|
728
730
|
/**
|
|
729
731
|
* 着手しようとしているtaskについて、記録済みの独立性から助言を組む(ADR 0128 Decision 5)。
|
|
730
732
|
*
|
|
731
|
-
*
|
|
732
|
-
*
|
|
733
|
+
* どの ready を取るかは助言のまま。記録があるのに対象工程が未検証なら呼び出し側が
|
|
734
|
+
* start を拒否する(ADR 0182)。助言を計算できない状況——git HEADが読めない等——は
|
|
735
|
+
* silent degradeせず、呼び出し側でstart自体を止める。
|
|
733
736
|
*/
|
|
734
737
|
async function startAdvisory({ repoRoot, store, projection, planKey, taskId }) {
|
|
735
738
|
const artifact = await readTodoIndependenceArtifact({ repoRoot, store, planKey });
|
|
@@ -861,6 +864,14 @@ async function startTask({
|
|
|
861
864
|
const advisory = await startAdvisory({
|
|
862
865
|
repoRoot, store, projection, planKey, taskId: resolvedTaskId,
|
|
863
866
|
});
|
|
867
|
+
const refusal = independenceStartRefusal(advisory.guidance);
|
|
868
|
+
if (refusal !== null) {
|
|
869
|
+
throw new TodoStoreError('INDEPENDENCE_UNVERIFIED', refusal.code, refusal.message, {
|
|
870
|
+
plan_key: planKey,
|
|
871
|
+
task_id: resolvedTaskId,
|
|
872
|
+
next_action: refusal.next_action,
|
|
873
|
+
});
|
|
874
|
+
}
|
|
864
875
|
const structureContext = await startStructureContext({
|
|
865
876
|
repoRoot, store, planKey, taskId: resolvedTaskId,
|
|
866
877
|
});
|
|
@@ -2388,9 +2399,41 @@ async function structure({ repoRoot, requestedPlanKey }) {
|
|
|
2388
2399
|
|
|
2389
2400
|
async function independenceCompile({ repoRoot, planKey, inputRef }) {
|
|
2390
2401
|
const witnessSet = await readWitnessSetInput(repoRoot, inputRef);
|
|
2402
|
+
const storeForReady = await readTodoStore({ repoRoot });
|
|
2403
|
+
const memberForReady = storeForReady.members.find(({ descriptor }) => descriptor.plan_key === planKey);
|
|
2404
|
+
if (!memberForReady) {
|
|
2405
|
+
throw new TodoStoreError('STORE_INCONSISTENT', 'plan_not_active', undefined, { plan_key: planKey });
|
|
2406
|
+
}
|
|
2407
|
+
const planTaskIds = new Set(memberForReady.plan.tasks.map(({ task_id: taskId }) => taskId));
|
|
2408
|
+
const declaredIds = Object.keys(witnessSet.manual_witness ?? {});
|
|
2409
|
+
const absentFromPlan = declaredIds.filter((taskId) => !planTaskIds.has(taskId)).sort();
|
|
2410
|
+
if (absentFromPlan.length > 0) {
|
|
2411
|
+
throw new TodoIndependenceError(
|
|
2412
|
+
'INDEPENDENCE_TASK_ABSENT',
|
|
2413
|
+
'witness_task_absent_from_plan',
|
|
2414
|
+
{ task_ids: absentFromPlan },
|
|
2415
|
+
);
|
|
2416
|
+
}
|
|
2417
|
+
const readyIds = projectTodoStatus(storeForReady, TODO_STATUS_DISPATCH_ONLY).next_ready
|
|
2418
|
+
.filter((task) => task.plan_key === planKey)
|
|
2419
|
+
.map((task) => task.task_id);
|
|
2420
|
+
const declared = new Set(declaredIds);
|
|
2421
|
+
const missingReady = readyIds.filter((taskId) => !declared.has(taskId)).sort();
|
|
2422
|
+
if (missingReady.length > 0) {
|
|
2423
|
+
throw new TodoStoreError(
|
|
2424
|
+
'INDEPENDENCE_READY_UNDECLARED',
|
|
2425
|
+
'ready_tasks_missing_from_witness',
|
|
2426
|
+
undefined,
|
|
2427
|
+
{
|
|
2428
|
+
plan_key: planKey,
|
|
2429
|
+
missing_task_ids: missingReady,
|
|
2430
|
+
next_action: 'add_task_to_witness_set_then_compile',
|
|
2431
|
+
},
|
|
2432
|
+
);
|
|
2433
|
+
}
|
|
2391
2434
|
const observation = await collectTodoIndependenceAuthoritativeObservation({ repoRoot, witnessSet });
|
|
2392
2435
|
const baseSha = observation.head_sha;
|
|
2393
|
-
const store =
|
|
2436
|
+
const store = storeForReady;
|
|
2394
2437
|
const member = store.members.find(({ descriptor }) => descriptor.plan_key === planKey);
|
|
2395
2438
|
if (!member) throw new TodoStoreError('STORE_INCONSISTENT', 'plan_not_active', undefined, { plan_key: planKey });
|
|
2396
2439
|
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
* 状況から`{code, message, next_action}`を引く単一正本。advisory・投影・typed error・helpは
|
|
5
5
|
* すべてここから引く。面ごとに文言を書けば必ずずれ、同じ状況に別の説明が付く。
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* 文は事実と次の一歩だけを述べ、指示しない。どのreadyを取るかはhostが所有する
|
|
8
8
|
* (ADR 0063 Decision 5)。命令形にするとLatticeがagentを統制する面へ滑る。
|
|
9
|
+
* ただし記録があるのに対象工程が未検証なら start は拒否する(ADR 0182)。
|
|
10
|
+
* それは配車ではなく、intakeが hold する着手を journal へ書かない。
|
|
9
11
|
*/
|
|
10
12
|
|
|
11
13
|
export const TODO_INDEPENDENCE_GUIDANCE_CODES = Object.freeze([
|
|
@@ -81,7 +83,7 @@ const CATALOG = Object.freeze({
|
|
|
81
83
|
next_action: 'declare_witness_set_then_compile',
|
|
82
84
|
}),
|
|
83
85
|
independence_task_undeclared: Object.freeze({
|
|
84
|
-
message: 'この工程はwitness setで宣言されていないため、記録には含まれていない。',
|
|
86
|
+
message: 'この工程はwitness setで宣言されていないため、記録には含まれていない。startは拒否する。',
|
|
85
87
|
next_action: 'add_task_to_witness_set_then_compile',
|
|
86
88
|
}),
|
|
87
89
|
independence_contract_superseded: Object.freeze({
|
|
@@ -173,6 +175,27 @@ const SEVERABILITY_HINT = Object.freeze({
|
|
|
173
175
|
serial: '共有stateまたはeffectの衝突なので、分割では切り離せない。',
|
|
174
176
|
});
|
|
175
177
|
|
|
178
|
+
/**
|
|
179
|
+
* 記録があるのに対象工程が未検証なら start を拒否する code。
|
|
180
|
+
* 記録が無い(independence_unrecorded)は従来どおり助言だけで通す。
|
|
181
|
+
* 競合(conflict_*)はどの ready を取るかの dispatch なので拒否しない。
|
|
182
|
+
*/
|
|
183
|
+
export const INDEPENDENCE_START_REFUSAL_CODES = Object.freeze([
|
|
184
|
+
'independence_task_undeclared',
|
|
185
|
+
'independence_stale_for_task',
|
|
186
|
+
'independence_superseded',
|
|
187
|
+
'independence_contract_superseded',
|
|
188
|
+
'independence_verdicts_absent',
|
|
189
|
+
]);
|
|
190
|
+
|
|
191
|
+
export function independenceStartRefusal(guidance) {
|
|
192
|
+
if (guidance === null || typeof guidance !== 'object' || Array.isArray(guidance)) {
|
|
193
|
+
throw new TypeError('independence start refusal guidance is invalid');
|
|
194
|
+
}
|
|
195
|
+
if (!INDEPENDENCE_START_REFUSAL_CODES.includes(guidance.code)) return null;
|
|
196
|
+
return guidance;
|
|
197
|
+
}
|
|
198
|
+
|
|
176
199
|
export function todoIndependenceGuidance(code, { severability = null } = {}) {
|
|
177
200
|
const entry = CATALOG[code];
|
|
178
201
|
if (entry === undefined) {
|
|
@@ -305,9 +328,11 @@ export function selectSeamProposalGuidance({ coverage, unknownKinds = [] }) {
|
|
|
305
328
|
export const TODO_INDEPENDENCE_WORKFLOW = Object.freeze([
|
|
306
329
|
'1. 宣言する: .lattice/todo/witness/<plan_key>.json へ、ToDoごとのowns/reads/writes/affected_testsを書く',
|
|
307
330
|
' 係争資源しか所有していないToDoは、ownsまたはwritesの内側で自分が触るsymbolをconcern_anchorsへ宣言できる(witness set v2)。並列可否の判定には写らず、切断候補の束縛だけに効く',
|
|
308
|
-
'
|
|
331
|
+
' remaining の A 工程(まだ done でない ready / blocked)も同じ witness に含める。現在の ready だけを compile すると、次の frontier の start が INDEPENDENCE_UNVERIFIED になる',
|
|
332
|
+
'2. 判定する: lattice todo independence compile --plan <key> --input <ref>(実sensorを引く。pretty-printやdigest未計算の下書きは機械が直す)。next_ready が witness に無い compile は拒否する',
|
|
309
333
|
'3. 読む: lattice todo independence --plan <key> --json(sensorを引かず、記録とHEAD照合だけで返る)',
|
|
310
334
|
'4. 追従する: plan改訂後は lattice todo independence witness migrate --plan <key> で宣言を写してから再compileする',
|
|
335
|
+
'5. 記録があるのに対象工程が未宣言・失効なら todo start は拒否する。競合の同時起動は助言のまま',
|
|
311
336
|
]);
|
|
312
337
|
|
|
313
338
|
/**
|