@quolu/lattice 0.64.0 → 0.64.2
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/LICENSE +147 -147
- package/README.ja.md +378 -378
- package/README.md +303 -303
- package/bin/lattice-mcp.mjs +0 -0
- package/bin/lattice-scripted-adapter.mjs +0 -0
- package/bin/lattice-scripted-worker.mjs +0 -0
- package/bin/lattice-work-order-adapter.mjs +0 -0
- package/bin/lattice.mjs +0 -0
- package/docs/bridge-setup.md +248 -248
- package/docs/schemas/lattice.executor_packet.v1.schema.json +57 -57
- package/docs/schemas/lattice.executor_receipt.v1.schema.json +66 -66
- package/docs/schemas/lattice.phase_todo_revision.v3.schema.json +360 -360
- package/docs/schemas/lattice.plan_create_input.v1.schema.json +56 -56
- package/docs/schemas/lattice.plan_create_input.v2.schema.json +72 -72
- package/docs/schemas/lattice.plan_create_input.v3.schema.json +81 -81
- package/docs/schemas/lattice.plan_create_input.v4.schema.json +357 -357
- package/docs/schemas/lattice.plan_scope_review.v1.schema.json +55 -55
- package/docs/schemas/lattice.run_request.v1.schema.json +238 -238
- package/docs/schemas/lattice.runtime_adapter_capabilities.v2.schema.json +55 -55
- package/docs/schemas/lattice.runtime_adapter_registration_input.v1.schema.json +78 -78
- package/docs/schemas/lattice.runtime_adapter_registration_input.v2.schema.json +86 -86
- package/docs/schemas/lattice.todo_extraction.v2.schema.json +298 -298
- package/docs/schemas/lattice.todo_extraction.v3.schema.json +150 -150
- package/docs/schemas/lattice.todo_extraction.v4.schema.json +161 -161
- package/docs/schemas/lattice.todo_revision.v2.schema.json +260 -260
- package/docs/schemas/lattice.todo_revision_set.v3.schema.json +363 -363
- package/docs/schemas/lattice.todo_structure_binding.v1.schema.json +47 -47
- package/docs/schemas/lattice.todo_structure_realization.v1.schema.json +55 -55
- package/docs/schemas/lattice.todo_structure_set.v1.schema.json +264 -264
- package/package.json +109 -109
- package/sensor/LICENSE +21 -21
- package/sensor/NOTICE +19 -19
- package/sensor/dist/bin/lattice-sensor.js +9 -9
- package/sensor/dist/db/index.js +24 -24
- package/sensor/dist/db/migrations.js +41 -41
- package/sensor/dist/db/queries.js +164 -164
- package/sensor/dist/db/schema.sql +205 -205
- package/sensor/dist/directory.js +5 -5
- package/sensor/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
- package/sensor/dist/extraction/wasm/tree-sitter-cfml.wasm +0 -0
- package/sensor/dist/extraction/wasm/tree-sitter-cfquery.wasm +0 -0
- package/sensor/dist/extraction/wasm/tree-sitter-cfscript.wasm +0 -0
- package/sensor/dist/extraction/wasm/tree-sitter-cobol.wasm +0 -0
- package/sensor/dist/extraction/wasm/tree-sitter-erlang.wasm +0 -0
- package/sensor/dist/extraction/wasm/tree-sitter-go.wasm +0 -0
- package/sensor/dist/extraction/wasm/tree-sitter-java.wasm +0 -0
- package/sensor/dist/extraction/wasm/tree-sitter-javascript.wasm +0 -0
- package/sensor/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
- package/sensor/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
- package/sensor/dist/extraction/wasm/tree-sitter-python.wasm +0 -0
- package/sensor/dist/extraction/wasm/tree-sitter-tsx.wasm +0 -0
- package/sensor/dist/extraction/wasm/tree-sitter-typescript.wasm +0 -0
- package/sensor/dist/extraction/wasm/tree-sitter-vbnet.wasm +0 -0
- package/sensor/dist/mcp/liveness-watchdog.js +53 -53
- package/sensor/dist/mcp/server-instructions.js +95 -95
- package/sensor/package.json +56 -56
- package/src/cli-help.mjs +2 -0
- package/src/hooks-cli.mjs +0 -1
- package/src/project-cli.mjs +8 -1
- package/src/todo-cli.mjs +20 -2
- package/src/todo-store-worktree-eol.mjs +191 -0
- package/src/todo-store.mjs +35 -17
package/src/todo-store.mjs
CHANGED
|
@@ -135,18 +135,26 @@ function decodeUtf8(bytes, code, reason) {
|
|
|
135
135
|
catch { fail(code, reason); }
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
function parseCanonicalJsonLine(bytes, { code, reason, maxBytes, validate }) {
|
|
139
|
-
|
|
138
|
+
function parseCanonicalJsonLine(bytes, { code, reason, maxBytes, validate, ref = null }) {
|
|
139
|
+
const detail = ref === null ? undefined : { ref };
|
|
140
|
+
if (bytes.length === 0 || bytes.length > maxBytes) {
|
|
141
|
+
fail(code, bytes.length > maxBytes ? 'size_limit_exceeded' : reason, detail);
|
|
142
|
+
}
|
|
140
143
|
const text = decodeUtf8(bytes, code, 'invalid_utf8');
|
|
141
|
-
if (text.includes('\r')
|
|
144
|
+
if (text.includes('\r')) {
|
|
145
|
+
fail(code, 'artifact_eol_converted', {
|
|
146
|
+
...detail, next_action: 'lattice todo repair-eol --json',
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
if (text.startsWith('\uFEFF')) fail(code, reason, detail);
|
|
142
150
|
const body = text.endsWith('\n') ? text.slice(0, -1) : text;
|
|
143
151
|
let value;
|
|
144
|
-
try { value = JSON.parse(body); } catch { fail(code, reason); }
|
|
145
|
-
if (!text.endsWith('\n')) fail(code, reason);
|
|
152
|
+
try { value = JSON.parse(body); } catch { fail(code, reason, detail); }
|
|
153
|
+
if (!text.endsWith('\n')) fail(code, reason, detail);
|
|
146
154
|
let expected;
|
|
147
|
-
try { expected = `${canonicalizeTodoArtifact(value)}\n`; } catch { fail(code, reason); }
|
|
148
|
-
if (text !== expected) fail(code, 'non_canonical_or_duplicate_key');
|
|
149
|
-
if (!validate(value)) fail(code, 'schema_invalid');
|
|
155
|
+
try { expected = `${canonicalizeTodoArtifact(value)}\n`; } catch { fail(code, reason, detail); }
|
|
156
|
+
if (text !== expected) fail(code, 'non_canonical_or_duplicate_key', detail);
|
|
157
|
+
if (!validate(value)) fail(code, 'schema_invalid', detail);
|
|
150
158
|
return value;
|
|
151
159
|
}
|
|
152
160
|
|
|
@@ -154,7 +162,9 @@ async function readArtifact(repoRoot, ref, { code, maxBytes, validate, missing =
|
|
|
154
162
|
const state = await pathState(repoRoot, ref, code, { missing });
|
|
155
163
|
if (state === null) return null;
|
|
156
164
|
const bytes = await readFile(state.absolute);
|
|
157
|
-
return parseCanonicalJsonLine(bytes, {
|
|
165
|
+
return parseCanonicalJsonLine(bytes, {
|
|
166
|
+
code, reason: 'artifact_truncated_or_trailing_bytes', maxBytes, validate, ref,
|
|
167
|
+
});
|
|
158
168
|
}
|
|
159
169
|
|
|
160
170
|
async function readSnapshotArtifact(repoRoot, ref) {
|
|
@@ -163,16 +173,23 @@ async function readSnapshotArtifact(repoRoot, ref) {
|
|
|
163
173
|
const bytes = await readFile(state.absolute);
|
|
164
174
|
return parseCanonicalJsonLine(bytes, {
|
|
165
175
|
code: 'SNAPSHOT_INVALID', reason: 'snapshot_truncated_or_trailing_bytes',
|
|
166
|
-
maxBytes: TODO_LIMITS.snapshotBytes, validate: validateTodoSnapshot,
|
|
176
|
+
maxBytes: TODO_LIMITS.snapshotBytes, validate: validateTodoSnapshot, ref,
|
|
167
177
|
});
|
|
168
178
|
}
|
|
169
179
|
|
|
170
|
-
function parseJournalSegment(bytes) {
|
|
180
|
+
function parseJournalSegment(bytes, ref = null) {
|
|
181
|
+
const detail = ref === null ? undefined : { ref };
|
|
171
182
|
if (bytes.length === 0 || bytes.length > TODO_LIMITS.journalSegmentBytes) {
|
|
172
|
-
fail('STORE_CORRUPT', bytes.length > TODO_LIMITS.journalSegmentBytes
|
|
183
|
+
fail('STORE_CORRUPT', bytes.length > TODO_LIMITS.journalSegmentBytes
|
|
184
|
+
? 'journal_segment_limit_exceeded' : 'journal_empty', detail);
|
|
173
185
|
}
|
|
174
186
|
const text = decodeUtf8(bytes, 'STORE_CORRUPT', 'journal_invalid_utf8');
|
|
175
|
-
if (
|
|
187
|
+
if (text.includes('\r')) {
|
|
188
|
+
fail('STORE_CORRUPT', 'artifact_eol_converted', {
|
|
189
|
+
...detail, next_action: 'lattice todo repair-eol --json',
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
if (!text.endsWith('\n') || text.startsWith('\uFEFF')) fail('STORE_CORRUPT', 'journal_byte_contract', detail);
|
|
176
193
|
const lines = text.slice(0, -1).split('\n');
|
|
177
194
|
if (lines.some((line) => line.length === 0)) fail('STORE_CORRUPT', 'journal_truncated_or_empty_line');
|
|
178
195
|
return lines.map((line) => {
|
|
@@ -205,8 +222,8 @@ async function readJournal(repoRoot, journalRef) {
|
|
|
205
222
|
const [, startText, endText, previousDigest, segmentDigest] = name.match(
|
|
206
223
|
/^(\d{12})-(\d{12})-([0-9a-f]{64})-([0-9a-f]{64})\.jsonl$/u,
|
|
207
224
|
);
|
|
225
|
+
const events = parseJournalSegment(bytes, ref);
|
|
208
226
|
if (sha256Bytes(bytes) !== segmentDigest) fail('STORE_CORRUPT', 'sealed_segment_digest_mismatch');
|
|
209
|
-
const events = parseJournalSegment(bytes);
|
|
210
227
|
if (events[0].sequence !== Number(startText) || events.at(-1).sequence !== Number(endText)) {
|
|
211
228
|
fail('STORE_CORRUPT', 'sealed_segment_range_mismatch');
|
|
212
229
|
}
|
|
@@ -220,7 +237,7 @@ async function readJournal(repoRoot, journalRef) {
|
|
|
220
237
|
if (error?.code !== 'ENOENT') fail('STORE_CORRUPT', 'sealed_segment_read_failed');
|
|
221
238
|
}
|
|
222
239
|
const activeBytes = await readFile(state.absolute);
|
|
223
|
-
segments.push({ ref: journalRef, bytes: activeBytes, events: parseJournalSegment(activeBytes) });
|
|
240
|
+
segments.push({ ref: journalRef, bytes: activeBytes, events: parseJournalSegment(activeBytes, journalRef) });
|
|
224
241
|
const events = segments.flatMap(({ events: entries }) => entries);
|
|
225
242
|
const failures = verifyLinearHashChain({
|
|
226
243
|
entries: events,
|
|
@@ -291,7 +308,7 @@ async function readPlanScopedJournal(repoRoot, journalRef) {
|
|
|
291
308
|
if (error?.code === 'ENOENT') return { ref, events: [], activeBytes: Buffer.alloc(0) };
|
|
292
309
|
fail('STORE_CORRUPT', 'plan_scoped_journal_read_failed');
|
|
293
310
|
}
|
|
294
|
-
const events = parseJournalSegment(bytes);
|
|
311
|
+
const events = parseJournalSegment(bytes, ref);
|
|
295
312
|
if (!events.every(({ kind }) => TODO_PLAN_SCOPED_EVENT_KINDS.includes(kind))) {
|
|
296
313
|
fail('STORE_CORRUPT', 'plan_scoped_journal_kind_invalid');
|
|
297
314
|
}
|
|
@@ -1571,7 +1588,8 @@ export async function readTodoStore(options = {}) {
|
|
|
1571
1588
|
snapshotStale = snapshot === null || canonicalizeTodoArtifact(snapshot) !== canonicalizeTodoArtifact(expectedSnapshot);
|
|
1572
1589
|
} catch (error) {
|
|
1573
1590
|
if (error instanceof TodoStoreError && error.code === 'SNAPSHOT_INVALID'
|
|
1574
|
-
&& !['unsafe_artifact_path', 'path_alias_or_escape', 'path_outside_store'
|
|
1591
|
+
&& !['unsafe_artifact_path', 'path_alias_or_escape', 'path_outside_store',
|
|
1592
|
+
'artifact_eol_converted'].includes(error.detail.reason)) snapshotStale = true;
|
|
1575
1593
|
else throw error;
|
|
1576
1594
|
}
|
|
1577
1595
|
if (options.forWrite === true && snapshotStale) fail('STORE_WRITE_REFUSED', 'snapshot_stale');
|