@quolu/lattice 0.58.2 → 0.58.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.58.2",
3
+ "version": "0.58.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",
package/src/cli-help.mjs CHANGED
@@ -113,8 +113,10 @@ Write commands:
113
113
  # 検査済みplanned sourceをcanonical refへ保存する。compile成功までは有効化しない
114
114
  structure compile --plan <key> --input <file>
115
115
  # source graph・Git provenance・ToDo DAGを結合する。consistent時だけplanへimmutableに有効化する
116
+ structure realize --plan <key> --task <id> (--planned|--realized <actual-structure.json>) [--commit <HEAD|sha>]...
117
+ # AIはplannedどおりか実体構造だけを判断する。identity・HEAD・履歴鎖・digest・actor・時刻は機械生成する
116
118
  structure realize --plan <key> --task <id> --input <file>
117
- # 実装後の構造をappend-onlyで記録してからtodo doneへ進む
119
+ # 完全なrealization envelopeを移送・再生する互換入口
118
120
  structure finalize --plan <key> --json
119
121
  # 全対象task完了後、最終HEADと全realizationを再結合する。fresh consistentだけterminal受理へ進む
120
122
  seam-proposal compile --plan <key> # 並列可否記録と実sensorからseam提案を記録する
@@ -236,7 +238,7 @@ const SUBCOMMAND_USAGE = Object.freeze({
236
238
  'todo note list': 'todo note list --plan <key> [--task <id>] --json',
237
239
  'todo bindings': 'todo bindings [--plan <key>] [--json]',
238
240
  'todo independence': 'todo independence [--plan <key>] [--json] | compile --plan <key> --input <file> | witness migrate --plan <key>',
239
- 'todo structure': 'todo structure --schema --json | [--plan <key>] --json | input --plan <key> --input <file> [--dry-run --json] | compile --plan <key> --input <file> | realize --plan <key> --task <id> --input <file> | finalize --plan <key> --json',
241
+ 'todo structure': 'todo structure --schema --json | [--plan <key>] --json | input --plan <key> --input <file> [--dry-run --json] | compile --plan <key> --input <file> | realize --plan <key> --task <id> (--planned|--realized <actual-structure.json>) [--commit <HEAD|sha>]... | realize --plan <key> --task <id> --input <full-realization.json> | finalize --plan <key> --json',
240
242
  'todo seam-profile': 'todo seam-profile --plan <key> --file <path> [--json]',
241
243
  'todo seam-proposal': 'todo seam-proposal [--plan <key>] [--json] | compile --plan <key>',
242
244
  'todo verify': 'todo verify [--plan <key>] [--json]',
package/src/todo-cli.mjs CHANGED
@@ -74,6 +74,10 @@ import {
74
74
  } from './todo-store.mjs';
75
75
  import {
76
76
  TODO_STRUCTURE_BINDING_SCHEMA,
77
+ TODO_STRUCTURE_LIMITS,
78
+ TODO_STRUCTURE_REALIZATION_SCHEMA,
79
+ digestTodoStructureTransform,
80
+ explainTodoStructureTransform,
77
81
  explainTodoStructureRealization,
78
82
  explainTodoStructureSet,
79
83
  } from './todo-structure-contracts.mjs';
@@ -646,7 +650,7 @@ function terminalAuditDoneAdvisory(plan, phases) {
646
650
 
647
651
  async function mutate({
648
652
  repoRoot, env, planKey, taskId, kind, payload, evidenceRef, advisory = null,
649
- noteContext = null,
653
+ noteContext = null, structureContext = null,
650
654
  }) {
651
655
  const actor = mutationActor(env);
652
656
  const evidence = evidenceRef === null ? null : await readEvidenceInput(repoRoot, evidenceRef);
@@ -674,7 +678,7 @@ async function mutate({
674
678
  throw new TypeError('start mutation requires note context');
675
679
  }
676
680
  const result = {
677
- schema: includesNoteContext ? 'lattice.todo_mutation_result.v4' : 'lattice.todo_mutation_result.v2',
681
+ schema: includesNoteContext ? 'lattice.todo_mutation_result.v5' : 'lattice.todo_mutation_result.v2',
678
682
  project_id: event.project_id,
679
683
  plan_key: event.plan_key,
680
684
  plan_version: event.plan_version,
@@ -689,6 +693,7 @@ async function mutate({
689
693
  ...(includesNoteContext ? {
690
694
  design_memo: designMemoProjection(authoredTask),
691
695
  note_context: noteContext,
696
+ structure_context: structureContext,
692
697
  } : {}),
693
698
  result_digest: '',
694
699
  };
@@ -696,6 +701,41 @@ async function mutate({
696
701
  return result;
697
702
  }
698
703
 
704
+ async function startStructureContext({ repoRoot, store, planKey, taskId }) {
705
+ const member = store.members.find(({ descriptor }) => descriptor.plan_key === planKey);
706
+ if (member === undefined) throw new TodoStoreError('STORE_INCONSISTENT', 'plan_not_active');
707
+ const source = await readTodoStructureSource({ repoRoot, planKey });
708
+ const binding = await readTodoStructureBinding({
709
+ repoRoot, planKey, planVersion: member.plan.plan_version,
710
+ });
711
+ if (source === null || binding === null) return {
712
+ status: 'not_enabled', enabled: false, freshness: null, stale_reasons: [],
713
+ structure_set_digest: null, task: null, next_actions: [],
714
+ };
715
+ if (source.structure_set_digest !== binding.structure_set_digest) {
716
+ throw new TodoStoreError('STRUCTURE_LIFECYCLE_GATE_FAILED',
717
+ 'enabled_structure_source_unreadable', undefined, { plan_key: planKey });
718
+ }
719
+ const task = source.tasks.find(({ task_id: id }) => id === taskId);
720
+ if (task === undefined) {
721
+ throw new TodoStoreError('STRUCTURE_LIFECYCLE_GATE_FAILED',
722
+ 'enabled_structure_task_missing', undefined, { plan_key: planKey, task_id: taskId });
723
+ }
724
+ const state = await readTodoStructureState({ repoRoot, store, planKey });
725
+ return {
726
+ status: 'available', enabled: true, freshness: state.status,
727
+ stale_reasons: state.stale_reasons,
728
+ structure_set_digest: source.structure_set_digest,
729
+ task: structuredClone(task),
730
+ next_actions: task.applicability === 'graph'
731
+ ? [
732
+ `lattice todo structure realize --plan ${planKey} --task ${taskId} --planned`,
733
+ `lattice todo structure realize --plan ${planKey} --task ${taskId} --realized <actual-structure.json>`,
734
+ ]
735
+ : [],
736
+ };
737
+ }
738
+
699
739
  function designMemoProjection(task) {
700
740
  if (typeof task.design_memo === 'string') {
701
741
  return { status: 'available', markdown: task.design_memo, prompt: TODO_DESIGN_MEMO_PROMPT };
@@ -898,8 +938,12 @@ async function startTask({
898
938
  const advisory = await startAdvisory({
899
939
  repoRoot, store, projection, planKey, taskId: resolvedTaskId,
900
940
  });
941
+ const structureContext = await startStructureContext({
942
+ repoRoot, store, planKey, taskId: resolvedTaskId,
943
+ });
901
944
  return mutate({ repoRoot, env, planKey, taskId: resolvedTaskId, kind: 'start',
902
- payload: { override_reason: overrideReason }, evidenceRef: null, advisory, noteContext });
945
+ payload: { override_reason: overrideReason }, evidenceRef: null, advisory, noteContext,
946
+ structureContext });
903
947
  }
904
948
 
905
949
  async function retractStart({ repoRoot, env, planKey, taskId, reason }) {
@@ -1961,6 +2005,31 @@ function structurePlanMember(store, requestedPlanKey) {
1961
2005
  return store.members[0];
1962
2006
  }
1963
2007
 
2008
+ function parseAutomatedStructureRealizeArgs(argv) {
2009
+ if (argv[0] !== 'structure' || argv[1] !== 'realize'
2010
+ || argv[2] !== '--plan' || !isTodoIdentifier(argv[3])
2011
+ || argv[4] !== '--task' || !isTodoIdentifier(argv[5])) return null;
2012
+ let cursor;
2013
+ let usePlanned;
2014
+ let realizedRef = null;
2015
+ if (argv[6] === '--planned') {
2016
+ cursor = 7; usePlanned = true;
2017
+ } else if (argv[6] === '--realized' && isTodoRef(argv[7])) {
2018
+ cursor = 8; usePlanned = false; realizedRef = argv[7];
2019
+ } else {
2020
+ return null;
2021
+ }
2022
+ const commitRefs = [];
2023
+ while (cursor < argv.length) {
2024
+ if (argv[cursor] !== '--commit' || typeof argv[cursor + 1] !== 'string') return null;
2025
+ commitRefs.push(argv[cursor + 1]);
2026
+ cursor += 2;
2027
+ }
2028
+ return {
2029
+ planKey: argv[3], taskId: argv[5], usePlanned, realizedRef, commitRefs,
2030
+ };
2031
+ }
2032
+
1964
2033
  function structureNextActions({ coverage, planKey, findings = [], staleReasons = [] }) {
1965
2034
  const actions = [];
1966
2035
  const add = (value) => { if (!actions.includes(value)) actions.push(value); };
@@ -1976,14 +2045,16 @@ function structureNextActions({ coverage, planKey, findings = [], staleReasons =
1976
2045
  if (staleReasons.includes('realization_head_digest')) {
1977
2046
  add(`lattice todo structure --plan ${planKey} --json`);
1978
2047
  } else {
1979
- add(`lattice todo structure realize --plan ${planKey} --task <task-id> --input <realization.json>`);
2048
+ add(`lattice todo structure realize --plan ${planKey} --task <task-id> --planned`);
2049
+ add(`lattice todo structure realize --plan ${planKey} --task <task-id> --realized <actual-structure.json>`);
1980
2050
  }
1981
2051
  add(`lattice todo structure finalize --plan ${planKey} --json`);
1982
2052
  } else if (coverage === 'superseded') {
1983
2053
  add(`lattice todo structure input --plan ${planKey} --input <migrated-structure-set.json> --dry-run --json`);
1984
2054
  } else if (coverage === 'consistent') {
1985
2055
  add(`lattice todo structure --plan ${planKey} --json`);
1986
- add(`lattice todo structure realize --plan ${planKey} --task <task-id> --input <realization.json>`);
2056
+ add(`lattice todo structure realize --plan ${planKey} --task <task-id> --planned`);
2057
+ add(`lattice todo structure realize --plan ${planKey} --task <task-id> --realized <actual-structure.json>`);
1987
2058
  add(`lattice todo structure finalize --plan ${planKey} --json`);
1988
2059
  }
1989
2060
  return actions;
@@ -2097,6 +2168,24 @@ async function readStructureRealizationInput(repoRoot, inputRef) {
2097
2168
  });
2098
2169
  }
2099
2170
 
2171
+ async function readStructureRealizedTransformInput(repoRoot, inputRef) {
2172
+ let explained = null;
2173
+ return readJsonInput(repoRoot, inputRef, {
2174
+ validate: (value) => {
2175
+ explained = explainTodoStructureTransform(value);
2176
+ return explained.valid;
2177
+ },
2178
+ invalidCode: 'INVALID_TODO_STRUCTURE_TRANSFORM',
2179
+ }).catch((error) => {
2180
+ if (error?.code === 'INVALID_TODO_STRUCTURE_TRANSFORM' && explained !== null) {
2181
+ throw new TodoStoreError(error.code, explained.reason, undefined, {
2182
+ input_ref: inputRef, path: explained.path,
2183
+ });
2184
+ }
2185
+ throw error;
2186
+ });
2187
+ }
2188
+
2100
2189
  async function readCurrentStructureEffective(repoRoot, structureSet) {
2101
2190
  const realizations = [];
2102
2191
  for (const task of structureSet.tasks.filter(({ applicability }) => applicability === 'graph')) {
@@ -2107,22 +2196,7 @@ async function readCurrentStructureEffective(repoRoot, structureSet) {
2107
2196
  return projectTodoStructureEffective({ structureSet, realizations });
2108
2197
  }
2109
2198
 
2110
- async function structureRealize({ repoRoot, env, planKey, taskId, inputRef }) {
2111
- const realization = await readStructureRealizationInput(repoRoot, inputRef);
2112
- const actor = mutationActor(env);
2113
- if (realization.plan_key !== planKey || realization.task_id !== taskId) {
2114
- throw new TodoStoreError('STRUCTURE_REALIZATION_BINDING_MISMATCH',
2115
- 'cli_target_mismatch', undefined, {
2116
- expected: { plan_key: planKey, task_id: taskId },
2117
- actual: { plan_key: realization.plan_key, task_id: realization.task_id },
2118
- });
2119
- }
2120
- if (canonicalizeTodoArtifact(realization.actor) !== canonicalizeTodoArtifact(actor)) {
2121
- throw new TodoStoreError('STRUCTURE_REALIZATION_BINDING_MISMATCH',
2122
- 'actor_environment_mismatch', undefined, {
2123
- expected_actor: actor, actual_actor: realization.actor,
2124
- });
2125
- }
2199
+ async function recordStructureRealization({ repoRoot, planKey, taskId, realization }) {
2126
2200
  const appended = await appendTodoStructureRealization({ repoRoot, realization });
2127
2201
  const structureSet = await readTodoStructureSource({ repoRoot, planKey });
2128
2202
  const effective = await readCurrentStructureEffective(repoRoot, structureSet);
@@ -2143,6 +2217,103 @@ async function structureRealize({ repoRoot, env, planKey, taskId, inputRef }) {
2143
2217
  return result;
2144
2218
  }
2145
2219
 
2220
+ async function structureRealize({ repoRoot, env, planKey, taskId, inputRef }) {
2221
+ const realization = await readStructureRealizationInput(repoRoot, inputRef);
2222
+ const actor = mutationActor(env);
2223
+ if (realization.plan_key !== planKey || realization.task_id !== taskId) {
2224
+ throw new TodoStoreError('STRUCTURE_REALIZATION_BINDING_MISMATCH',
2225
+ 'cli_target_mismatch', undefined, {
2226
+ expected: { plan_key: planKey, task_id: taskId },
2227
+ actual: { plan_key: realization.plan_key, task_id: realization.task_id },
2228
+ });
2229
+ }
2230
+ if (canonicalizeTodoArtifact(realization.actor) !== canonicalizeTodoArtifact(actor)) {
2231
+ throw new TodoStoreError('STRUCTURE_REALIZATION_BINDING_MISMATCH',
2232
+ 'actor_environment_mismatch', undefined, {
2233
+ expected_actor: actor, actual_actor: realization.actor,
2234
+ });
2235
+ }
2236
+ return recordStructureRealization({ repoRoot, planKey, taskId, realization });
2237
+ }
2238
+
2239
+ function resolveStructureRealizationCommits(repoRoot, refs) {
2240
+ const requested = refs.length === 0 ? ['HEAD'] : refs;
2241
+ if (requested.length > TODO_STRUCTURE_LIMITS.commitsPerRealization) {
2242
+ throw new TodoStoreError('STRUCTURE_REALIZATION_COMMIT_REF_INVALID',
2243
+ 'commit_ref_count_exceeds_limit', undefined, {
2244
+ actual: requested.length, limit: TODO_STRUCTURE_LIMITS.commitsPerRealization,
2245
+ });
2246
+ }
2247
+ const resolved = [];
2248
+ for (const ref of requested) {
2249
+ if (!(ref === 'HEAD' || /^[0-9a-f]{40}$/u.test(ref))) {
2250
+ throw new TodoStoreError('STRUCTURE_REALIZATION_COMMIT_REF_INVALID',
2251
+ 'commit_ref_must_be_head_or_full_sha', undefined, { commit_ref: ref });
2252
+ }
2253
+ let oid;
2254
+ try {
2255
+ oid = gitSync(['rev-parse', '--verify', `${ref}^{commit}`], {
2256
+ cwd: repoRoot, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'],
2257
+ }).trim();
2258
+ } catch {
2259
+ throw new TodoStoreError('STRUCTURE_REALIZATION_COMMIT_REF_INVALID',
2260
+ 'commit_ref_unresolved', undefined, { commit_ref: ref });
2261
+ }
2262
+ if (!/^[0-9a-f]{40}$/u.test(oid)) {
2263
+ throw new TodoStoreError('STRUCTURE_REALIZATION_COMMIT_REF_INVALID',
2264
+ 'commit_ref_resolved_invalid_oid', undefined, { commit_ref: ref });
2265
+ }
2266
+ if (resolved.includes(oid)) {
2267
+ throw new TodoStoreError('STRUCTURE_REALIZATION_COMMIT_REF_INVALID',
2268
+ 'duplicate_commit_ref', undefined, { commit_ref: ref, commit_oid: oid });
2269
+ }
2270
+ resolved.push(oid);
2271
+ }
2272
+ return resolved.sort();
2273
+ }
2274
+
2275
+ async function structureRealizeActual({
2276
+ repoRoot, env, planKey, taskId, realizedRef, usePlanned, commitRefs,
2277
+ }) {
2278
+ const structureSet = await readTodoStructureSource({ repoRoot, planKey });
2279
+ if (structureSet === null) {
2280
+ throw new TodoStoreError('STRUCTURE_REALIZATION_BINDING_MISMATCH',
2281
+ 'planned_structure_source_missing', undefined, { plan_key: planKey });
2282
+ }
2283
+ const task = structureSet.tasks.find(({ task_id: id }) => id === taskId);
2284
+ if (task?.applicability !== 'graph') {
2285
+ throw new TodoStoreError('STRUCTURE_REALIZATION_BINDING_MISMATCH',
2286
+ 'task_not_graph_applicable', undefined, { plan_key: planKey, task_id: taskId });
2287
+ }
2288
+ const realized = usePlanned
2289
+ ? structuredClone(task.planned)
2290
+ : await readStructureRealizedTransformInput(repoRoot, realizedRef);
2291
+ const chain = await readTodoStructureRealizationChain({
2292
+ repoRoot, structureSet, taskId,
2293
+ });
2294
+ const previous = chain.at(-1) ?? null;
2295
+ const realization = {
2296
+ schema: TODO_STRUCTURE_REALIZATION_SCHEMA,
2297
+ project_id: structureSet.project_id,
2298
+ plan_key: structureSet.plan_key,
2299
+ plan_version: structureSet.plan_version,
2300
+ task_id: taskId,
2301
+ sequence: (previous?.sequence ?? 0) + 1,
2302
+ previous_digest: previous?.realization_digest ?? null,
2303
+ structure_set_digest: structureSet.structure_set_digest,
2304
+ planned_digest: digestTodoStructureTransform(task.planned),
2305
+ head_sha: currentHeadSha(repoRoot),
2306
+ commit_oids: resolveStructureRealizationCommits(repoRoot, commitRefs),
2307
+ realized,
2308
+ supersedes: previous?.realization_digest ?? null,
2309
+ actor: mutationActor(env),
2310
+ recorded_at: new Date().toISOString(),
2311
+ realization_digest: '',
2312
+ };
2313
+ realization.realization_digest = todoSelfDigest(realization, 'realization_digest');
2314
+ return recordStructureRealization({ repoRoot, planKey, taskId, realization });
2315
+ }
2316
+
2146
2317
  async function structureFinalize({ repoRoot, env, planKey }) {
2147
2318
  const store = await readTodoStore({ repoRoot });
2148
2319
  const member = structurePlanMember(store, planKey);
@@ -2178,7 +2349,7 @@ async function structureFinalize({ repoRoot, env, planKey }) {
2178
2349
  throw new TodoStoreError('STRUCTURE_FINALIZATION_UNAVAILABLE',
2179
2350
  'realization_missing', undefined, {
2180
2351
  plan_key: planKey, task_id: task.task_id,
2181
- next_action: `lattice todo structure realize --plan ${planKey} --task ${task.task_id} --input <realization.json>`,
2352
+ next_action: `lattice todo structure realize --plan ${planKey} --task ${task.task_id} --realized <actual-structure.json>`,
2182
2353
  });
2183
2354
  }
2184
2355
  realizations.push(...chain);
@@ -3442,6 +3613,14 @@ export async function runTodoCli({ argv, cwd, stdout, stderr, env = process.env
3442
3613
  });
3443
3614
  }
3444
3615
 
3616
+ if (argv[0] === 'structure' && argv[1] === 'realize'
3617
+ && argv[6] === '--realized' && typeof argv[7] === 'string' && path.isAbsolute(argv[7])) {
3618
+ return typedArgumentFailure(stderr, 'INPUT_OUTSIDE_REPOSITORY', 'absolute_input_path_rejected', {
3619
+ argument: '--realized', expected: 'repo-relative path', actual: 'absolute path',
3620
+ next_action: 'place_the_input_inside_the_repository_and_pass_a_repo_relative_path',
3621
+ });
3622
+ }
3623
+
3445
3624
  // `--schema --json`はstoreを読まない決定的な出力(`plan create --schema`と同じ規律)。
3446
3625
  // 通常dispatchより前に処理し、repoRoot解決やdashboard daemon起動を経由させない。
3447
3626
  if (argv.length === 3 && argv[1] === '--schema' && argv[2] === '--json'
@@ -3476,6 +3655,7 @@ export async function runTodoCli({ argv, cwd, stdout, stderr, env = process.env
3476
3655
  }
3477
3656
  }
3478
3657
 
3658
+ const automatedStructureRealize = parseAutomatedStructureRealizeArgs(argv);
3479
3659
  let action = null;
3480
3660
  if ((argv.length === 1 && argv[0] === 'status')
3481
3661
  || (argv.length === 2 && argv[0] === 'status' && argv[1] === '--json')) {
@@ -3578,6 +3758,10 @@ export async function runTodoCli({ argv, cwd, stdout, stderr, env = process.env
3578
3758
  action = (repoRoot) => structureRealize({
3579
3759
  repoRoot, env, planKey: argv[3], taskId: argv[5], inputRef: argv[7],
3580
3760
  });
3761
+ } else if (automatedStructureRealize !== null) {
3762
+ action = (repoRoot) => structureRealizeActual({
3763
+ repoRoot, env, ...automatedStructureRealize,
3764
+ });
3581
3765
  } else if (argv.length === 5 && argv[0] === 'structure' && argv[1] === 'finalize'
3582
3766
  && argv[2] === '--plan' && isTodoIdentifier(argv[3]) && argv[4] === '--json') {
3583
3767
  action = (repoRoot) => structureFinalize({ repoRoot, env, planKey: argv[3] });
@@ -1640,7 +1640,7 @@ async function enforceTodoStructureLifecycleGate(repoRoot, member, eventInput) {
1640
1640
  if (latest === undefined) {
1641
1641
  fail('STRUCTURE_REALIZATION_REQUIRED', 'fresh_realization_missing', {
1642
1642
  plan_key: member.plan.plan_key, task_id: eventInput.task_id,
1643
- next_action: `lattice todo structure realize --plan ${member.plan.plan_key} --task ${eventInput.task_id} --input <realization.json>`,
1643
+ next_action: `lattice todo structure realize --plan ${member.plan.plan_key} --task ${eventInput.task_id} --realized <actual-structure.json>`,
1644
1644
  });
1645
1645
  }
1646
1646
  let currentHead;
@@ -1655,7 +1655,7 @@ async function enforceTodoStructureLifecycleGate(repoRoot, member, eventInput) {
1655
1655
  fail('STRUCTURE_REALIZATION_REQUIRED', 'realization_head_stale', {
1656
1656
  plan_key: member.plan.plan_key, task_id: eventInput.task_id,
1657
1657
  realization_head_sha: latest.head_sha, current_head_sha: currentHead,
1658
- next_action: `lattice todo structure realize --plan ${member.plan.plan_key} --task ${eventInput.task_id} --input <realization.json>`,
1658
+ next_action: `lattice todo structure realize --plan ${member.plan.plan_key} --task ${eventInput.task_id} --realized <actual-structure.json>`,
1659
1659
  });
1660
1660
  }
1661
1661
  }
@@ -467,6 +467,11 @@ export const digestTodoStructureTransform = (value) => todoSelfDigest(
467
467
  { schema: 'lattice.todo_structure_transform.v1', transform: value, digest: '' }, 'digest',
468
468
  );
469
469
 
470
+ /** AIが判断して渡す実体構造だけを、realization envelopeとは独立に検証する。 */
471
+ export function explainTodoStructureTransform(value) {
472
+ return transform(value, '');
473
+ }
474
+
470
475
  export function explainTodoStructureRealization(value, { structureSet = null, previous = null,
471
476
  priorDigests = null } = {}) {
472
477
  try {