@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.
Files changed (62) hide show
  1. package/LICENSE +147 -147
  2. package/README.ja.md +378 -378
  3. package/README.md +303 -303
  4. package/bin/lattice-mcp.mjs +0 -0
  5. package/bin/lattice-scripted-adapter.mjs +0 -0
  6. package/bin/lattice-scripted-worker.mjs +0 -0
  7. package/bin/lattice-work-order-adapter.mjs +0 -0
  8. package/bin/lattice.mjs +0 -0
  9. package/docs/bridge-setup.md +248 -248
  10. package/docs/schemas/lattice.executor_packet.v1.schema.json +57 -57
  11. package/docs/schemas/lattice.executor_receipt.v1.schema.json +66 -66
  12. package/docs/schemas/lattice.phase_todo_revision.v3.schema.json +360 -360
  13. package/docs/schemas/lattice.plan_create_input.v1.schema.json +56 -56
  14. package/docs/schemas/lattice.plan_create_input.v2.schema.json +72 -72
  15. package/docs/schemas/lattice.plan_create_input.v3.schema.json +81 -81
  16. package/docs/schemas/lattice.plan_create_input.v4.schema.json +357 -357
  17. package/docs/schemas/lattice.plan_scope_review.v1.schema.json +55 -55
  18. package/docs/schemas/lattice.run_request.v1.schema.json +238 -238
  19. package/docs/schemas/lattice.runtime_adapter_capabilities.v2.schema.json +55 -55
  20. package/docs/schemas/lattice.runtime_adapter_registration_input.v1.schema.json +78 -78
  21. package/docs/schemas/lattice.runtime_adapter_registration_input.v2.schema.json +86 -86
  22. package/docs/schemas/lattice.todo_extraction.v2.schema.json +298 -298
  23. package/docs/schemas/lattice.todo_extraction.v3.schema.json +150 -150
  24. package/docs/schemas/lattice.todo_extraction.v4.schema.json +161 -161
  25. package/docs/schemas/lattice.todo_revision.v2.schema.json +260 -260
  26. package/docs/schemas/lattice.todo_revision_set.v3.schema.json +363 -363
  27. package/docs/schemas/lattice.todo_structure_binding.v1.schema.json +47 -47
  28. package/docs/schemas/lattice.todo_structure_realization.v1.schema.json +55 -55
  29. package/docs/schemas/lattice.todo_structure_set.v1.schema.json +264 -264
  30. package/package.json +109 -109
  31. package/sensor/LICENSE +21 -21
  32. package/sensor/NOTICE +19 -19
  33. package/sensor/dist/bin/lattice-sensor.js +9 -9
  34. package/sensor/dist/db/index.js +24 -24
  35. package/sensor/dist/db/migrations.js +41 -41
  36. package/sensor/dist/db/queries.js +164 -164
  37. package/sensor/dist/db/schema.sql +205 -205
  38. package/sensor/dist/directory.js +5 -5
  39. package/sensor/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
  40. package/sensor/dist/extraction/wasm/tree-sitter-cfml.wasm +0 -0
  41. package/sensor/dist/extraction/wasm/tree-sitter-cfquery.wasm +0 -0
  42. package/sensor/dist/extraction/wasm/tree-sitter-cfscript.wasm +0 -0
  43. package/sensor/dist/extraction/wasm/tree-sitter-cobol.wasm +0 -0
  44. package/sensor/dist/extraction/wasm/tree-sitter-erlang.wasm +0 -0
  45. package/sensor/dist/extraction/wasm/tree-sitter-go.wasm +0 -0
  46. package/sensor/dist/extraction/wasm/tree-sitter-java.wasm +0 -0
  47. package/sensor/dist/extraction/wasm/tree-sitter-javascript.wasm +0 -0
  48. package/sensor/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
  49. package/sensor/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
  50. package/sensor/dist/extraction/wasm/tree-sitter-python.wasm +0 -0
  51. package/sensor/dist/extraction/wasm/tree-sitter-tsx.wasm +0 -0
  52. package/sensor/dist/extraction/wasm/tree-sitter-typescript.wasm +0 -0
  53. package/sensor/dist/extraction/wasm/tree-sitter-vbnet.wasm +0 -0
  54. package/sensor/dist/mcp/liveness-watchdog.js +53 -53
  55. package/sensor/dist/mcp/server-instructions.js +95 -95
  56. package/sensor/package.json +56 -56
  57. package/src/cli-help.mjs +2 -0
  58. package/src/hooks-cli.mjs +0 -1
  59. package/src/project-cli.mjs +8 -1
  60. package/src/todo-cli.mjs +20 -2
  61. package/src/todo-store-worktree-eol.mjs +191 -0
  62. package/src/todo-store.mjs +35 -17
@@ -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
- if (bytes.length === 0 || bytes.length > maxBytes) fail(code, bytes.length > maxBytes ? 'size_limit_exceeded' : reason);
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') || text.startsWith('\uFEFF')) fail(code, reason);
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, { code, reason: 'artifact_truncated_or_trailing_bytes', maxBytes, validate });
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 ? 'journal_segment_limit_exceeded' : 'journal_empty');
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 (!text.endsWith('\n') || text.includes('\r') || text.startsWith('\uFEFF')) fail('STORE_CORRUPT', 'journal_byte_contract');
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'].includes(error.detail.reason)) snapshotStale = true;
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');