@khoavu882/doflow 2.0.0-beta.3 → 2.0.0-beta.5

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 (236) hide show
  1. package/bin/doflow.js +2 -2
  2. package/core/.antigravity-plugin/plugin.json +0 -1
  3. package/core/.claude-plugin/plugin.json +1 -1
  4. package/core/.codex-plugin/plugin.json +1 -1
  5. package/core/.plugin/plugin.json +1 -1
  6. package/core/harnesses/claude/hooks/mcp-tool-guard.sh +7 -17
  7. package/core/harnesses/claude/hooks/pre-bash-guard.sh +7 -17
  8. package/core/harnesses/claude/hooks/pre-implement-gate.sh +7 -18
  9. package/core/harnesses/claude/hooks/session-start.sh +5 -3
  10. package/core/harnesses/claude/hooks/stop-check.sh +5 -3
  11. package/core/harnesses/claude/hooks/subagent-audit.sh +5 -5
  12. package/core/harnesses/claude/hooks/user-prompt-submit.sh +5 -3
  13. package/core/harnesses/codex/hooks/mcp-tool-guard.sh +7 -15
  14. package/core/harnesses/codex/hooks/pre-bash-guard.sh +7 -15
  15. package/core/harnesses/codex/hooks/pre-implement-gate.sh +7 -16
  16. package/core/harnesses/codex/hooks/session-start.sh +5 -3
  17. package/core/harnesses/codex/hooks/stop-check.sh +6 -5
  18. package/core/harnesses/codex/hooks/subagent-audit.sh +17 -6
  19. package/core/harnesses/codex/hooks/user-prompt-submit.sh +5 -4
  20. package/core/harnesses/gemini/hooks/mcp-tool-guard.sh +7 -18
  21. package/core/harnesses/gemini/hooks/pre-bash-guard.sh +7 -18
  22. package/core/harnesses/gemini/hooks/pre-implement-gate.sh +7 -19
  23. package/core/harnesses/gemini/hooks/session-start.sh +5 -3
  24. package/core/harnesses/kiro/hooks/mcp-tool-guard.sh +20 -5
  25. package/core/harnesses/kiro/hooks/pre-bash-guard.sh +20 -5
  26. package/core/harnesses/kiro/hooks/pre-implement-gate.sh +20 -5
  27. package/core/harnesses/kiro/hooks/session-start.sh +11 -5
  28. package/core/harnesses/kiro/hooks/stop-check.sh +21 -30
  29. package/core/harnesses/pi/extensions/doflow-guard.js +159 -0
  30. package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +27 -11
  31. package/core/harnesses/shared/hooks/adapters/antigravity.js +14 -57
  32. package/core/harnesses/shared/hooks/bridge/bridge.sh +184 -0
  33. package/core/harnesses/shared/hooks/bridge/envelope.jq +60 -0
  34. package/core/harnesses/shared/hooks/bridge/respond.sh +62 -0
  35. package/core/harnesses/shared/hooks/policies/capture-failure.sh +4 -2
  36. package/core/harnesses/shared/hooks/policies/contract.sh +75 -0
  37. package/core/harnesses/shared/hooks/policies/deny-json.sh +39 -4
  38. package/core/harnesses/shared/hooks/policies/lib.sh +4 -2
  39. package/core/harnesses/shared/hooks/policies/mcp-tool-guard.sh +46 -34
  40. package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +75 -25
  41. package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +67 -73
  42. package/core/harnesses/shared/hooks/policies/session-context.sh +37 -7
  43. package/core/harnesses/shared/hooks/policies/stop-check.sh +42 -15
  44. package/core/harnesses/shared/hooks/policies/subagent-audit.sh +35 -5
  45. package/core/harnesses/shared/hooks/policies/user-prompt-submit.sh +40 -7
  46. package/core/harnesses/shared/hooks/stream-hook-runner.js +69 -181
  47. package/core/registry/assets.json +19 -0
  48. package/core/registry/contracts.json +2 -2
  49. package/core/registry/harnesses.json +196 -10
  50. package/core/registry/lifecycle.json +2626 -7
  51. package/core/registry/storage.json +110 -83
  52. package/core/registry/verification.json +1 -1
  53. package/core/shared/scripts/doflow/bash/render-puml.sh +2 -2
  54. package/core/shared/scripts/doflow/bin/doflow-run +10 -6
  55. package/core/shared/skills/do-design/SKILL.md +6 -6
  56. package/core/shared/skills/do-execute-plan/SKILL.md +11 -10
  57. package/core/shared/skills/do-execute-plan/references/readiness_gate.md +2 -0
  58. package/core/shared/skills/do-execute-plan/references/scaffold.md +2 -2
  59. package/core/shared/skills/do-implement/SKILL.md +3 -2
  60. package/core/shared/skills/do-plan/SKILL.md +7 -8
  61. package/package.json +4 -2
  62. package/src/adapters/antigravity/{index.ts → index.js} +141 -105
  63. package/src/adapters/claude/{index.ts → index.js} +63 -49
  64. package/src/adapters/claude/{mcp.ts → mcp.js} +16 -16
  65. package/src/adapters/codex/{agents.ts → agents.js} +24 -24
  66. package/src/adapters/codex/{config.ts → config.js} +49 -49
  67. package/src/adapters/codex/{hooks.ts → hooks.js} +62 -27
  68. package/src/adapters/codex/{index.ts → index.js} +148 -105
  69. package/src/adapters/codex/{mcp.ts → mcp.js} +38 -38
  70. package/src/adapters/codex/{native-projection.ts → native-projection.js} +5 -5
  71. package/src/adapters/copilot/{index.ts → index.js} +42 -42
  72. package/src/adapters/{copy-tree.ts → copy-tree.js} +74 -74
  73. package/src/adapters/gemini/{hooks.ts → hooks.js} +78 -37
  74. package/src/adapters/gemini/{index.ts → index.js} +96 -57
  75. package/src/adapters/{hook-commands.ts → hook-commands.js} +8 -8
  76. package/src/adapters/{index.ts → index.js} +13 -13
  77. package/src/adapters/kiro/{index.ts → index.js} +49 -35
  78. package/src/adapters/{mcp-entries.ts → mcp-entries.js} +55 -55
  79. package/src/adapters/opencode/{index.ts → index.js} +52 -52
  80. package/src/adapters/pi/hooks.js +119 -0
  81. package/src/adapters/pi/{index.ts → index.js} +64 -39
  82. package/src/adapters/pi/{json-members.ts → json-members.js} +23 -23
  83. package/src/adapters/pi/{mcp.ts → mcp.js} +70 -70
  84. package/src/adapters/{resolve-source.ts → resolve-source.js} +1 -1
  85. package/src/cli/commands/{install.ts → install.js} +25 -25
  86. package/src/cli/commands/{list-backups.ts → list-backups.js} +4 -4
  87. package/src/cli/commands/{reconcile.ts → reconcile.js} +19 -19
  88. package/src/cli/commands/{remove.ts → remove.js} +10 -10
  89. package/src/cli/commands/{rollback.ts → rollback.js} +17 -17
  90. package/src/cli/commands/{self-update.ts → self-update.js} +3 -3
  91. package/src/cli/commands/{status.ts → status.js} +24 -24
  92. package/src/cli/commands/{tools.ts → tools.js} +16 -16
  93. package/src/cli/commands/{update.ts → update.js} +20 -20
  94. package/src/cli/{index.ts → index.js} +43 -31
  95. package/src/cli/{runtime-commands.ts → runtime-commands.js} +97 -58
  96. package/src/cli/{shared.ts → shared.js} +40 -40
  97. package/src/helper/{bash-helper.ts → bash-helper.js} +7 -7
  98. package/src/helper/{git.ts → git.js} +2 -2
  99. package/src/helper/{guardrails.ts → guardrails.js} +10 -10
  100. package/src/helper/{harness-paths.ts → harness-paths.js} +24 -24
  101. package/src/helper/{marker-merge.ts → marker-merge.js} +4 -4
  102. package/src/helper/{prompt.ts → prompt.js} +5 -5
  103. package/src/helper/{repo-root.ts → repo-root.js} +2 -2
  104. package/src/helper/{settings-merge.ts → settings-merge.js} +27 -27
  105. package/src/helper/{settings-scope.ts → settings-scope.js} +3 -3
  106. package/src/helper/{toml.ts → toml.js} +48 -48
  107. package/src/install/{backup-set.ts → backup-set.js} +16 -16
  108. package/src/install/{backup.ts → backup.js} +65 -65
  109. package/src/install/{context.ts → context.js} +15 -15
  110. package/src/install/{manifest.ts → manifest.js} +27 -27
  111. package/src/install/{mcp.ts → mcp.js} +30 -30
  112. package/src/install/{paths.ts → paths.js} +15 -15
  113. package/src/install/{targets.ts → targets.js} +10 -10
  114. package/src/install/{tool-lifecycle.ts → tool-lifecycle.js} +20 -20
  115. package/src/lifecycle/{bash-availability.ts → bash-availability.js} +1 -1
  116. package/src/lifecycle/coverage.js +57 -0
  117. package/src/lifecycle/hook-step.js +61 -0
  118. package/src/lifecycle/{index.ts → index.js} +160 -146
  119. package/src/lifecycle/{mcp-index.ts → mcp-index.js} +1 -1
  120. package/src/lifecycle/{policies.ts → policies.js} +11 -11
  121. package/src/lifecycle/{view.ts → view.js} +28 -28
  122. package/src/registry/{index.ts → index.js} +195 -66
  123. package/src/release/build-package.js +91 -0
  124. package/src/release/changelog-section.js +70 -0
  125. package/src/release/{sync-plugin-versions.ts → sync-plugin-versions.js} +4 -4
  126. package/src/runtime/advice/{cli.ts → cli.js} +31 -31
  127. package/src/runtime/advice/{client.ts → client.js} +44 -44
  128. package/src/runtime/advice/{config.ts → config.js} +16 -16
  129. package/src/runtime/advice/{doctor.ts → doctor.js} +32 -32
  130. package/src/runtime/advice/{endpoint-guard.ts → endpoint-guard.js} +20 -20
  131. package/src/runtime/advice/{kinds.ts → kinds.js} +16 -16
  132. package/src/runtime/advice/providers/{ollama-systemone.ts → ollama-systemone.js} +21 -21
  133. package/src/runtime/advice/{record.ts → record.js} +19 -19
  134. package/src/runtime/advice/{registry.ts → registry.js} +16 -16
  135. package/src/runtime/advice/{strength.ts → strength.js} +7 -7
  136. package/src/runtime/{brief-tools.ts → brief-tools.js} +50 -50
  137. package/src/runtime/{c4-project.ts → c4-project.js} +27 -27
  138. package/src/runtime/candidate.js +505 -0
  139. package/src/runtime/{capability-router.ts → capability-router.js} +39 -39
  140. package/src/runtime/{checkouts.ts → checkouts.js} +21 -21
  141. package/src/runtime/{claims.ts → claims.js} +44 -35
  142. package/src/runtime/{cli-result.ts → cli-result.js} +15 -8
  143. package/src/runtime/{cli.ts → cli.js} +59 -292
  144. package/src/runtime/{command-detect.ts → command-detect.js} +47 -47
  145. package/src/runtime/context/budget.js +203 -0
  146. package/src/runtime/context/compose.js +1367 -0
  147. package/src/runtime/context/delivery-store.js +102 -0
  148. package/src/runtime/context/mandatory.js +594 -0
  149. package/src/runtime/context/pointer.js +142 -0
  150. package/src/runtime/context-pack.js +1277 -0
  151. package/src/runtime/{decision-register.ts → decision-register.js} +67 -67
  152. package/src/runtime/evidence-fields.js +39 -0
  153. package/src/runtime/{evidence-ledger.ts → evidence-ledger.js} +32 -25
  154. package/src/runtime/failure/{capture.ts → capture.js} +29 -29
  155. package/src/runtime/failure/{classifier.ts → classifier.js} +4 -4
  156. package/src/runtime/failure/{cli.ts → cli.js} +30 -30
  157. package/src/runtime/failure/{home.ts → home.js} +6 -6
  158. package/src/runtime/failure/{store.ts → store.js} +32 -32
  159. package/src/runtime/{feature-resolve.ts → feature-resolve.js} +6 -6
  160. package/src/runtime/{freshness.ts → freshness.js} +59 -22
  161. package/src/runtime/{health.ts → health.js} +72 -72
  162. package/src/runtime/{history-compactor.ts → history-compactor.js} +25 -25
  163. package/src/runtime/{implementation-gate.ts → implementation-gate.js} +30 -30
  164. package/src/runtime/inventory/{coverage.ts → coverage.js} +10 -10
  165. package/src/runtime/inventory/{identity.ts → identity.js} +2 -2
  166. package/src/runtime/inventory/{index.ts → index.js} +36 -36
  167. package/src/runtime/inventory/{precedence.ts → precedence.js} +2 -2
  168. package/src/runtime/inventory/{read-scopes.ts → read-scopes.js} +9 -9
  169. package/src/runtime/inventory/{siblings.ts → siblings.js} +15 -15
  170. package/src/runtime/knowledge/{chunker.ts → chunker.js} +12 -12
  171. package/src/runtime/knowledge/{hybrid.ts → hybrid.js} +17 -17
  172. package/src/runtime/knowledge/{index-store.ts → index-store.js} +23 -23
  173. package/src/runtime/knowledge/{retrieval.ts → retrieval.js} +27 -27
  174. package/src/runtime/{leak-scan.ts → leak-scan.js} +12 -12
  175. package/src/runtime/lifecycle/{cli.ts → cli.js} +32 -32
  176. package/src/runtime/lifecycle/{event-store.ts → event-store.js} +48 -48
  177. package/src/runtime/lifecycle/{fold.ts → fold.js} +41 -41
  178. package/src/runtime/lifecycle/{followup.ts → followup.js} +54 -54
  179. package/src/runtime/lifecycle/{goal.ts → goal.js} +50 -50
  180. package/src/runtime/lifecycle/{intent-writer.ts → intent-writer.js} +5 -5
  181. package/src/runtime/lifecycle/{overview.ts → overview.js} +47 -47
  182. package/src/runtime/lifecycle/{release.ts → release.js} +29 -29
  183. package/src/runtime/lifecycle/{report-store.ts → report-store.js} +25 -25
  184. package/src/runtime/lifecycle/{retention.ts → retention.js} +37 -37
  185. package/src/runtime/lifecycle/{root.ts → root.js} +9 -9
  186. package/src/runtime/lifecycle/{status.ts → status.js} +64 -64
  187. package/src/runtime/lifecycle/{store-upkeep.ts → store-upkeep.js} +46 -46
  188. package/src/runtime/{locator-resolve.ts → locator-resolve.js} +7 -7
  189. package/src/runtime/{mask.ts → mask.js} +22 -22
  190. package/src/runtime/{mcp-consultations.ts → mcp-consultations.js} +54 -54
  191. package/src/runtime/{mcp-reach.ts → mcp-reach.js} +24 -24
  192. package/src/runtime/{model-router.ts → model-router.js} +20 -20
  193. package/src/runtime/{outcome.ts → outcome.js} +27 -27
  194. package/src/runtime/{reach.ts → reach.js} +21 -21
  195. package/src/runtime/{readiness-record.ts → readiness-record.js} +12 -12
  196. package/src/runtime/{readiness.ts → readiness.js} +113 -43
  197. package/src/runtime/{recovery.ts → recovery.js} +15 -15
  198. package/src/runtime/{research-request.ts → research-request.js} +34 -34
  199. package/src/runtime/{retrieval-plan.ts → retrieval-plan.js} +453 -104
  200. package/src/runtime/retrieval-record.js +223 -0
  201. package/src/runtime/scaffold/{artifacts.ts → artifacts.js} +22 -19
  202. package/src/runtime/scaffold/{fingerprint.ts → fingerprint.js} +3 -3
  203. package/src/runtime/scaffold/{generate.ts → generate.js} +109 -109
  204. package/src/runtime/scaffold/{languages.ts → languages.js} +34 -34
  205. package/src/runtime/source-version.js +289 -0
  206. package/src/runtime/storage/{cli.ts → cli.js} +9 -9
  207. package/src/runtime/storage/{engine.ts → engine.js} +37 -37
  208. package/src/runtime/storage/{registry.ts → registry.js} +19 -19
  209. package/src/runtime/storage/{roots.ts → roots.js} +8 -8
  210. package/src/runtime/storage/{rules.ts → rules.js} +26 -26
  211. package/src/runtime/storage/{upkeep.ts → upkeep.js} +35 -35
  212. package/src/runtime/storage/{work-status.ts → work-status.js} +39 -39
  213. package/src/runtime/{task-attempts.ts → task-attempts.js} +62 -62
  214. package/src/runtime/{task-classifier.ts → task-classifier.js} +34 -34
  215. package/src/runtime/{task-scope.ts → task-scope.js} +40 -15
  216. package/src/runtime/{task-state.ts → task-state.js} +86 -21
  217. package/src/runtime/trace/{indicators.ts → indicators.js} +22 -22
  218. package/src/runtime/trace/{ledger.ts → ledger.js} +42 -42
  219. package/src/runtime/trace/{render.ts → render.js} +7 -7
  220. package/src/runtime/trace/{views.ts → views.js} +40 -40
  221. package/src/runtime/verification/{contract-runner.ts → contract-runner.js} +23 -23
  222. package/src/runtime/verification/{engine.ts → engine.js} +143 -143
  223. package/src/runtime/verification/{registry.ts → registry.js} +6 -6
  224. package/src/runtime/verification/{scope-bound.ts → scope-bound.js} +50 -50
  225. package/src/runtime/verification/{test-selection.ts → test-selection.js} +28 -28
  226. package/src/runtime/{workflow-engine.ts → workflow-engine.js} +50 -50
  227. package/src/runtime/{workflow-orchestrator.ts → workflow-orchestrator.js} +91 -91
  228. package/src/runtime/{worktree.ts → worktree.js} +31 -31
  229. package/src/state/{index.ts → index.js} +26 -26
  230. package/src/state/{lockfile.ts → lockfile.js} +20 -20
  231. package/src/state/{run-lock.ts → run-lock.js} +44 -44
  232. package/core/.antigravity-plugin/hooks.json +0 -39
  233. package/core/harnesses/shared/hooks/adapters/arg-fields.js +0 -19
  234. package/core/harnesses/shared/hooks/adapters/gemini.js +0 -114
  235. package/core/harnesses/shared/hooks/hooks.json +0 -47
  236. package/src/runtime/context-pack.ts +0 -492
@@ -9,30 +9,30 @@
9
9
  * by the service and printed here, never thrown, so it cannot reach failure capture (NFR-005).
10
10
  */
11
11
 
12
- const { finishRuntime, usageError } = require('../cli-result.ts');
13
- const { projectRoot } = require('./root.ts');
14
- const followup = require('./followup.ts');
15
- const { StoreUnsafeError, StoreLockedError } = require('./event-store.ts');
16
- const { prepareStore } = require('./store-upkeep.ts');
17
- const { printSafe } = require('../mask.ts');
18
- const { buildOverview, initFeature, featureStatus } = require('./overview.ts');
19
- const { releaseFeatures, recordMerged } = require('./release.ts');
20
- const goal = require('./goal.ts');
12
+ const { finishRuntime, usageError } = require('../cli-result.js');
13
+ const { projectRoot } = require('./root.js');
14
+ const followup = require('./followup.js');
15
+ const { StoreUnsafeError, StoreLockedError } = require('./event-store.js');
16
+ const { prepareStore } = require('./store-upkeep.js');
17
+ const { printSafe } = require('../mask.js');
18
+ const { buildOverview, initFeature, featureStatus } = require('./overview.js');
19
+ const { releaseFeatures, recordMerged } = require('./release.js');
20
+ const goal = require('./goal.js');
21
21
 
22
22
  const FOLLOWUP_ACTIONS = ['add', 'list', 'take', 'settle', 'promote', 'report'];
23
23
  const LIFECYCLE_ACTIONS = ['overview', 'init', 'release', 'status', 'merged'];
24
24
  const GOAL_ACTIONS = ['add', 'item', 'check', 'link', 'list', 'done'];
25
25
  /** The flags each goal action takes, besides --goal, --channel and --json; any other one given is a usage error. */
26
- const GOAL_FLAGS: Record<string, any> = {
26
+ const GOAL_FLAGS = {
27
27
  add: ['statement', 'item'], item: ['text'], check: ['item', 'evidence', 'unmet'],
28
28
  link: ['slug', 'replace'], list: [], done: ['reason'],
29
29
  };
30
30
 
31
- function sourceText(source: any) {
31
+ function sourceText(source ) {
32
32
  return [source.kind, source.feature, source.taskClass, source.taskId, source.release, source.stage, source.ref].filter(Boolean).join(' ');
33
33
  }
34
34
 
35
- function followupLines(result: any) {
35
+ function followupLines(result ) {
36
36
  const lines = [];
37
37
  switch (result.action) {
38
38
  case 'add': for (const c of result.created) lines.push(`added ${c.id} (${sourceText(c.source)}): ${c.statement}`); break;
@@ -52,17 +52,17 @@ function followupLines(result: any) {
52
52
  return lines;
53
53
  }
54
54
 
55
- function overviewLines(r: any) {
55
+ function overviewLines(r ) {
56
56
  const lines = [`${r.mode} overview: ${r.followups.open} open follow-up${r.followups.open === 1 ? '' : 's'}, ${r.followups.shown} shown (release mode ${r.releaseMode}${r.integrationRef ? `, integration ref ${r.integrationRef}` : ''})`];
57
57
  for (const i of r.followups.items) lines.push(` ${i.id} (${sourceText(i.source)}, ${i.added})${i.promoted ? ` promoted to ${i.intent}` : ''}${i.pending === false ? ' settled this run' : ''} ${i.statement}`);
58
58
  if (Array.isArray(r.failures)) {
59
59
  lines.push(`failures: ${r.failures.length} new or regressed`);
60
60
  for (const f of r.failures) lines.push(` ${f.fp} ${f.status} x${f.count} ${f.command} ${f.kind}${f.message ? `: ${f.message}` : ''} (last seen ${f.lastSeen}, ${f.lastVersion})`);
61
61
  }
62
- for (const g of r.goals) lines.push(`goal ${g.goal}: ${g.items.met}/${g.items.total} items met${g.proposeDone ? ' (propose done)' : ''}`, ...g.nudges.map((n: any) => ` ${n}`), ...(g.conflicts || []).map((c: any) => ` conflict: ${c.reason}${c.text ? ` (dropped text: ${JSON.stringify(c.text)})` : ''}`));
62
+ for (const g of r.goals) lines.push(`goal ${g.goal}: ${g.items.met}/${g.items.total} items met${g.proposeDone ? ' (propose done)' : ''}`, ...g.nudges.map((n ) => ` ${n}`), ...(g.conflicts || []).map((c ) => ` conflict: ${c.reason}${c.text ? ` (dropped text: ${JSON.stringify(c.text)})` : ''}`));
63
63
  const f = r.features;
64
64
  // The finished and awaiting-release lists only grow, so the text shows their bounded form.
65
- const bounded = (key: any) => (r.featuresShown && r.featuresShown[key]) || { count: f[key].length, shown: f[key], more: 0 };
65
+ const bounded = (key ) => (r.featuresShown && r.featuresShown[key]) || { count: f[key].length, shown: f[key], more: 0 };
66
66
  const names = [['finished', bounded('finished')], ['awaiting release', bounded('awaitingRelease')],
67
67
  ['in progress', { count: f.inProgress.length, shown: f.inProgress, more: 0 }], ['unknown', { count: f.unknown.length, shown: f.unknown, more: 0 }]].filter(([, b]) => b.count);
68
68
  for (const [label, b] of names) {
@@ -72,12 +72,12 @@ function overviewLines(r: any) {
72
72
  if (r.mode === 'maintain') lines.push(`pending: ${r.pending}`);
73
73
  if (r.note) lines.push(`note: ${r.note}`);
74
74
  if (r.conflicts.length) lines.push(`${r.conflicts.length} event conflict${r.conflicts.length === 1 ? '' : 's'} (see --json)`);
75
- if (r.unreadable.length) lines.push(`unreadable event files: ${r.unreadable.map((n: any) => (r.unreadableReasons && r.unreadableReasons[n] ? `${n} (${r.unreadableReasons[n]})` : n)).join(', ')}`);
75
+ if (r.unreadable.length) lines.push(`unreadable event files: ${r.unreadable.map((n ) => (r.unreadableReasons && r.unreadableReasons[n] ? `${n} (${r.unreadableReasons[n]})` : n)).join(', ')}`);
76
76
  for (const line of r.next) lines.push(`next: ${line}`);
77
77
  return lines;
78
78
  }
79
79
 
80
- function releaseLines(r: any) {
80
+ function releaseLines(r ) {
81
81
  const lines = [`${r.recorded ? 'recorded' : 'preview of'} release ${r.tag} (previous ${r.previousTag || 'none'}, bound ${r.bound})`];
82
82
  for (const c of r.candidates) if (!r.excluded.includes(c.slug)) lines.push(` ships ${c.slug} (${c.evidence}${c.ref ? ` ${c.ref}` : ''})`);
83
83
  if (r.added.length) lines.push(`added: ${r.added.join(', ')}`);
@@ -89,7 +89,7 @@ function releaseLines(r: any) {
89
89
  return lines;
90
90
  }
91
91
 
92
- function lifecycleLines(result: any) {
92
+ function lifecycleLines(result ) {
93
93
  switch (result.action) {
94
94
  case 'init': return [`${result.slug}: tracked ${result.tracked}${result.taken.length ? `, took ${result.taken.join(', ')}` : ''}${result.goal ? `, serves ${result.goal}` : ''}`, ...result.next];
95
95
  case 'status': return [`${result.slug}: ${result.status}${result.evidence ? ` (${result.evidence.kind}${result.evidence.ref ? ` ${result.evidence.ref}` : ''})` : ''}${result.release ? `, release ${result.release}` : ''}`, ...(result.note ? [`note: ${result.note}`] : [])];
@@ -99,12 +99,12 @@ function lifecycleLines(result: any) {
99
99
  }
100
100
  }
101
101
 
102
- function goalLines(r: any) {
103
- const met = (g: any) => `${g.progress.met}/${g.progress.total} items met`;
102
+ function goalLines(r ) {
103
+ const met = (g ) => `${g.progress.met}/${g.progress.total} items met`;
104
104
  switch (r.action) {
105
- case 'add': return [`added goal ${r.goal}: ${r.outcome}`, ...r.items.map((i: any) => ` ${i.id} ${i.text}`), ...r.next.map((n: any) => `next: ${n}`)];
106
- case 'item': return [`added ${r.item.id} to ${r.goal}: ${r.item.text}`, ...r.next.map((n: any) => `next: ${n}`)];
107
- case 'check': return [`${r.goal} ${r.item}: ${r.met ? 'met' : 'unmet'} (${r.evidence}); ${r.progress.met}/${r.progress.total} items met${r.proposeDone ? ' (propose done)' : ''}`, ...r.next.map((n: any) => `next: ${n}`)];
105
+ case 'add': return [`added goal ${r.goal}: ${r.outcome}`, ...r.items.map((i ) => ` ${i.id} ${i.text}`), ...r.next.map((n ) => `next: ${n}`)];
106
+ case 'item': return [`added ${r.item.id} to ${r.goal}: ${r.item.text}`, ...r.next.map((n ) => `next: ${n}`)];
107
+ case 'check': return [`${r.goal} ${r.item}: ${r.met ? 'met' : 'unmet'} (${r.evidence}); ${r.progress.met}/${r.progress.total} items met${r.proposeDone ? ' (propose done)' : ''}`, ...r.next.map((n ) => `next: ${n}`)];
108
108
  case 'link': return [r.linked === 'already' ? `${r.slug} already serves ${r.goal}` : `${r.slug} now serves ${r.goal}${r.replaced ? ` (was ${r.replaced})` : ''}`];
109
109
  case 'done': return [`${r.goal} is done${r.unmet.length ? ` with ${r.unmet.join(', ')} unmet: ${r.reason}` : ''}`];
110
110
  default: {
@@ -119,13 +119,13 @@ function goalLines(r: any) {
119
119
  for (const c of g.conflicts || []) lines.push(` conflict: ${c.reason}${c.text ? ` (dropped text: ${JSON.stringify(c.text)})` : ''}`);
120
120
  }
121
121
  if (r.reason) lines.push(`note: ${r.reason}`);
122
- return [...lines, ...r.next.map((n: any) => `next: ${n}`)];
122
+ return [...lines, ...r.next.map((n ) => `next: ${n}`)];
123
123
  }
124
124
  }
125
125
  }
126
126
 
127
127
  /** Prints a result and sets the exit status; shared by the verbs. */
128
- function emit(result: any, json: any, lines: any) {
128
+ function emit(result , json , lines ) {
129
129
  if (json) console.log(JSON.stringify(result, null, 2));
130
130
  else if (result.ok === false) console.log(printSafe(`${result.finding}: ${result.message}`));
131
131
  else for (const line of lines(result)) console.log(printSafe(line));
@@ -133,10 +133,10 @@ function emit(result: any, json: any, lines: any) {
133
133
  }
134
134
 
135
135
  /** Runs `fn`, turning a caller mistake into the exit-2 usage result and a lock that never came into the `store-locked` refusal. */
136
- function guarded(verb: any, action: any, json: any, fn: any) {
136
+ function guarded(verb , action , json , fn ) {
137
137
  try {
138
138
  return fn();
139
- } catch (error: any) {
139
+ } catch (error ) {
140
140
  if (error instanceof followup.FollowupUsageError || error instanceof StoreUnsafeError) return usageError(verb, error.message, json);
141
141
  if (error instanceof StoreLockedError) return emit({ ok: false, action, finding: 'store-locked', message: error.message }, json, () => []);
142
142
  throw error;
@@ -144,13 +144,13 @@ function guarded(verb: any, action: any, json: any, fn: any) {
144
144
  }
145
145
 
146
146
  /** Runs the store upkeep for one invocation and prints its lines to stderr; returns its refusal, or null. */
147
- function upkeep(verb: any, action: any, root: any) {
147
+ function upkeep(verb , action , root ) {
148
148
  const prepared = prepareStore(root);
149
149
  for (const line of prepared.lines) console.error(printSafe(`doflow ${verb}: ${line}`));
150
150
  return prepared.ok ? null : { ok: false, action, finding: prepared.finding, message: prepared.message };
151
151
  }
152
152
 
153
- function refuseGlobal(verb: any, global: any, json: any) {
153
+ function refuseGlobal(verb , global , json ) {
154
154
  return global ? usageError(verb, `${verb} works on the project store at the repository root and refuses -g`, json) : null;
155
155
  }
156
156
 
@@ -162,7 +162,7 @@ function refuseGlobal(verb: any, global: any, json: any) {
162
162
  * @param {Object} options.flags parsed flag values: statement, stage, source, taskClass, taskId, release,
163
163
  * batch, channel, state, ids, as, reason, evidence, title; for report also file, stdin, text, feature
164
164
  */
165
- function handleFollowupCommand({ action, cwd, global = false, slug = null, json = false, flags = {} }: any = {}) {
165
+ function handleFollowupCommand({ action, cwd, global = false, slug = null, json = false, flags = {} } = {}) {
166
166
  const refused = refuseGlobal('followup', global, json);
167
167
  if (refused !== null) return refused;
168
168
  return guarded('followup', action, json, () => {
@@ -213,7 +213,7 @@ function handleFollowupCommand({ action, cwd, global = false, slug = null, json
213
213
  * @param {Object} options.flags parsed flag values: take, intent, goal, maintain, since, tag, confirm,
214
214
  * feature, exclude, reason, channel
215
215
  */
216
- function handleLifecycleCommand({ action, cwd, global = false, slug = null, json = false, flags = {} }: any = {}) {
216
+ function handleLifecycleCommand({ action, cwd, global = false, slug = null, json = false, flags = {} } = {}) {
217
217
  const refused = refuseGlobal('lifecycle', global, json);
218
218
  if (refused !== null) return refused;
219
219
  return guarded('lifecycle', action === undefined ? 'overview' : action, json, () => {
@@ -246,7 +246,7 @@ function handleLifecycleCommand({ action, cwd, global = false, slug = null, json
246
246
  * @param {Object} options.flags parsed flag values: goal, statement, item (a list), text, evidence, unmet,
247
247
  * replace, reason, channel; `--slug` arrives as `slug`
248
248
  */
249
- function handleGoalCommand({ action, cwd, global = false, slug = null, json = false, flags = {} }: any = {}) {
249
+ function handleGoalCommand({ action, cwd, global = false, slug = null, json = false, flags = {} } = {}) {
250
250
  const refused = refuseGlobal('goal', global, json);
251
251
  if (refused !== null) return refused;
252
252
  return guarded('goal', action, json, () => {
@@ -17,9 +17,9 @@
17
17
  const nodeFs = require('node:fs');
18
18
  const path = require('node:path');
19
19
  const crypto = require('node:crypto');
20
- const { acquireLock } = require('../task-state.ts');
21
- const { printSafe } = require('../mask.ts');
22
- const { foldInto, finalize, applyEvent } = require('./fold.ts');
20
+ const { acquireLock } = require('../task-state.js');
21
+ const { printSafe } = require('../mask.js');
22
+ const { foldInto, finalize, applyEvent } = require('./fold.js');
23
23
 
24
24
  const LIFECYCLE_REL = path.join('.doflow', 'state', 'lifecycle');
25
25
  const EVENTS_REL = path.join(LIFECYCLE_REL, 'events');
@@ -39,39 +39,39 @@ const MAX_EVENT_BYTES = 256 * 1024;
39
39
  const MAX_JOURNAL_BYTES = 16 * 1024 * 1024;
40
40
  const READ_CHUNK = 64 * 1024;
41
41
  /** The decision register's channel vocabulary: who the caller says is acting. */
42
- const CHANNEL_BY: Record<string, string> = { question: 'user', gate: 'user', prompt: 'user', default: 'agent' };
42
+ const CHANNEL_BY = { question: 'user', gate: 'user', prompt: 'user', default: 'agent' };
43
43
 
44
- function eventsDir(root: string): string { return path.join(root, EVENTS_REL); }
45
- function lockTarget(root: string): string { return path.join(root, EVENTS_REL); }
44
+ function eventsDir(root ) { return path.join(root, EVENTS_REL); }
45
+ function lockTarget(root ) { return path.join(root, EVENTS_REL); }
46
46
 
47
47
  /** @param {string} [channel] defaults to `default` @returns {'user'|'agent'|null} null for an unknown channel */
48
- function byFromChannel(channel: string = 'default'): string | null { return CHANNEL_BY[channel] ?? null; }
48
+ function byFromChannel(channel = 'default') { return CHANNEL_BY[channel] ?? null; }
49
49
 
50
50
  /** `length` random characters of the lowercase Crockford base32 alphabet. */
51
- function randomChars(length: number): string {
51
+ function randomChars(length ) {
52
52
  const bytes = crypto.randomBytes(length);
53
53
  let out = '';
54
54
  for (const b of bytes) out += ALPHABET[b % 32];
55
55
  return out;
56
56
  }
57
57
 
58
- function idFor(at: string, random: (n: number) => string): string { return `${at.replace(/[-:.]/g, '')}-${random(6)}`; }
58
+ function idFor(at , random ) { return `${at.replace(/[-:.]/g, '')}-${random(6)}`; }
59
59
 
60
60
  /** Synchronous sleep without spinning, as the store lock waits. */
61
- function sleep(ms: number): void {
61
+ function sleep(ms ) {
62
62
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
63
63
  }
64
64
 
65
65
  /** DEC-045: `at` is a strict UTC timestamp that is a real instant, so year 10000 and "+275760-..." never parse. */
66
66
  const STRICT_AT = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
67
- function isStrictAt(at: any): boolean {
67
+ function isStrictAt(at ) {
68
68
  if (typeof at !== 'string' || !STRICT_AT.test(at)) return false;
69
69
  const ms = Date.parse(at);
70
70
  return Number.isFinite(ms) && new Date(ms).toISOString() === at;
71
71
  }
72
72
 
73
73
  /** An IC-002 envelope whose `at` is strict and equals the time prefix of its file id. */
74
- function isEnvelope(event: any, idFromName: string): boolean {
74
+ function isEnvelope(event , idFromName ) {
75
75
  return event && typeof event === 'object' && event.v === 1 && event.id === idFromName
76
76
  && typeof event.type === 'string' && typeof event.by === 'string'
77
77
  && isStrictAt(event.at) && idFromName.startsWith(`${event.at.replace(/[-:.]/g, '')}-`)
@@ -84,7 +84,7 @@ class StoreUnsafeError extends Error {}
84
84
  /** The store lock could not be taken in time; the verb refuses with `store-locked` and writes nothing. */
85
85
  class StoreLockedError extends Error {}
86
86
 
87
- function assertStoreFolders(root: string, fsImpl: any): void {
87
+ function assertStoreFolders(root , fsImpl ) {
88
88
  for (const rel of [path.join('.doflow'), path.join('.doflow', 'state'), LIFECYCLE_REL, EVENTS_REL]) {
89
89
  const folder = path.join(root, rel);
90
90
  let link = false;
@@ -99,9 +99,9 @@ function assertStoreFolders(root: string, fsImpl: any): void {
99
99
  * and again by `O_NOFOLLOW` where the platform has it; `O_NONBLOCK` keeps a FIFO swapped in after
100
100
  * the `lstat` from blocking the open, and the descriptor is checked again before any read.
101
101
  */
102
- function readEventFile(fsImpl: any, file: string, maxBytes: number = MAX_EVENT_BYTES): { reason?: string; text?: string } {
102
+ function readEventFile(fsImpl , file , maxBytes = MAX_EVENT_BYTES) {
103
103
  const flags = nodeFs.constants;
104
- let fd: number | undefined;
104
+ let fd ;
105
105
  try {
106
106
  if (!fsImpl.lstatSync(file).isFile()) return { reason: 'not a regular file' };
107
107
  fd = fsImpl.openSync(file, flags.O_RDONLY | (flags.O_NOFOLLOW || 0) | (flags.O_NONBLOCK || 0));
@@ -110,7 +110,7 @@ function readEventFile(fsImpl: any, file: string, maxBytes: number = MAX_EVENT_B
110
110
  const tooLarge = { reason: `larger than ${maxBytes / 1024} KiB` };
111
111
  if (st.size > maxBytes) return tooLarge;
112
112
  // Read in chunks up to one byte past the cap, so a file that grew after the fstat is still caught.
113
- const chunks: Buffer[] = [];
113
+ const chunks = [];
114
114
  let length = 0;
115
115
  while (length <= maxBytes) {
116
116
  const chunk = Buffer.allocUnsafe(Math.min(READ_CHUNK, maxBytes + 1 - length));
@@ -120,7 +120,7 @@ function readEventFile(fsImpl: any, file: string, maxBytes: number = MAX_EVENT_B
120
120
  length += n;
121
121
  }
122
122
  return length > maxBytes ? tooLarge : { text: Buffer.concat(chunks, length).toString('utf8') };
123
- } catch (error: any) {
123
+ } catch (error ) {
124
124
  return { reason: error.code || 'unreadable' };
125
125
  } finally {
126
126
  if (fd !== undefined) { try { fsImpl.closeSync(fd); } catch { /* read already done */ } }
@@ -128,16 +128,16 @@ function readEventFile(fsImpl: any, file: string, maxBytes: number = MAX_EVENT_B
128
128
  }
129
129
 
130
130
  /** The event with every string print-safe; a report excerpt is multi-line by design, so it keeps its line breaks (cli.js removes them when printing). */
131
- function cleanEvent(event: any): any {
131
+ function cleanEvent(event ) {
132
132
  const clean = printSafe(event);
133
133
  if (typeof event.data.excerpt === 'string') clean.data.excerpt = printSafe(event.data.excerpt, { keepLineBreaks: true });
134
134
  return clean;
135
135
  }
136
136
 
137
137
  /** Whether `name` is `<EVENT_ID>.json`. */
138
- function isEventName(name: string): boolean {
138
+ function isEventName(name ) {
139
139
  const match = /^(.+)\.json$/.exec(name);
140
- return Boolean(match) && EVENT_ID.test((match as RegExpExecArray)[1]);
140
+ return Boolean(match) && EVENT_ID.test((match )[1]);
141
141
  }
142
142
 
143
143
  /**
@@ -146,39 +146,39 @@ function isEventName(name: string): boolean {
146
146
  * pending; a pending name that is not an event file name is ignored.
147
147
  * @returns {{generation: string|null, pending: string[]}}
148
148
  */
149
- function readJournal(root: string, fsImpl: any = nodeFs): { generation: string | null; pending: string[] } {
149
+ function readJournal(root , fsImpl = nodeFs) {
150
150
  const read = readEventFile(fsImpl, path.join(root, JOURNAL_REL), MAX_JOURNAL_BYTES);
151
- let journal: any;
152
- try { journal = read.reason ? null : JSON.parse(read.text as string); } catch { journal = null; }
151
+ let journal ;
152
+ try { journal = read.reason ? null : JSON.parse(read.text ); } catch { journal = null; }
153
153
  if (!journal || typeof journal !== 'object' || journal.v !== 1) return { generation: null, pending: [] };
154
154
  return {
155
155
  generation: typeof journal.generation === 'string' ? journal.generation : null,
156
- pending: Array.isArray(journal.pending) ? journal.pending.filter((name: any) => typeof name === 'string' && isEventName(name)) : [],
156
+ pending: Array.isArray(journal.pending) ? journal.pending.filter((name ) => typeof name === 'string' && isEventName(name)) : [],
157
157
  };
158
158
  }
159
159
 
160
160
  /** One pass over the event files, leaving out the names in `hidden`. */
161
- function readEventFiles(root: string, fsImpl: any, hidden: Set<string>, shouldStop?: () => boolean): any {
161
+ function readEventFiles(root , fsImpl , hidden , shouldStop ) {
162
162
  const dir = eventsDir(root);
163
- let names: string[];
163
+ let names ;
164
164
  try {
165
165
  names = fsImpl.readdirSync(dir);
166
- } catch (error: any) {
166
+ } catch (error ) {
167
167
  if (error.code === 'ENOENT' || error.code === 'ENOTDIR') return { events: [], unreadable: [], reasons: {} };
168
168
  throw error;
169
169
  }
170
170
  const orderedNames = names.sort();
171
171
  if (shouldStop?.()) return { events: [], unreadable: [], reasons: {}, incomplete: true };
172
- const events: any[] = [];
173
- const unreadable: string[] = [];
174
- const reasons: Record<string, string> = {};
172
+ const events = [];
173
+ const unreadable = [];
174
+ const reasons = {};
175
175
  for (const name of orderedNames) {
176
176
  if (shouldStop?.()) return { events: [], unreadable: [], reasons: {}, incomplete: true };
177
177
  if (!isEventName(name) || hidden.has(name)) continue;
178
178
  const read = readEventFile(fsImpl, path.join(dir, name));
179
179
  if (read.reason) { unreadable.push(name); reasons[name] = read.reason; continue; }
180
180
  try {
181
- const event = JSON.parse(read.text as string);
181
+ const event = JSON.parse(read.text );
182
182
  // Someone else's file is shown as it is read, so its text is made print-safe here (stored bytes are not changed).
183
183
  if (isEnvelope(event, name.slice(0, -'.json'.length))) events.push(cleanEvent(event)); else unreadable.push(name);
184
184
  } catch {
@@ -204,7 +204,7 @@ function readEventFiles(root: string, fsImpl: any, hidden: Set<string>, shouldSt
204
204
  * StoreLockedError.
205
205
  * @returns {{events: Object[], unreadable: string[], reasons: Object<string,string>, incomplete?: true}}
206
206
  */
207
- function readEvents(root: string, { fsImpl = nodeFs, lockFallback = true, shouldStop }: any = {}): any {
207
+ function readEvents(root , { fsImpl = nodeFs, lockFallback = true, shouldStop } = {}) {
208
208
  assertStoreFolders(root, fsImpl);
209
209
  if (shouldStop?.()) return { events: [], unreadable: [], reasons: {}, incomplete: true };
210
210
  for (let attempt = 1; attempt <= STABLE_READS; attempt += 1) {
@@ -220,10 +220,10 @@ function readEvents(root: string, { fsImpl = nodeFs, lockFallback = true, should
220
220
  }
221
221
  if (shouldStop?.()) return { events: [], unreadable: [], reasons: {}, incomplete: true };
222
222
  if (!lockFallback) throw new StoreLockedError('Lifecycle event store changed during a read; a stable snapshot was unavailable.');
223
- let release: () => void;
223
+ let release ;
224
224
  try {
225
225
  release = acquireLock(fsImpl, lockTarget(root));
226
- } catch (error: any) {
226
+ } catch (error ) {
227
227
  if (/^Could not lock/.test(error.message || '')) throw new StoreLockedError(`${error.message} Nothing was written.`);
228
228
  throw error;
229
229
  }
@@ -240,20 +240,20 @@ function readEvents(root: string, { fsImpl = nodeFs, lockFallback = true, should
240
240
  * @param {{hasBody?: Function, fsImpl?: Object}} [options]
241
241
  * @returns {Object} the fold result (see fold.js) plus `unreadable`
242
242
  */
243
- function readFold(root: string, { fsImpl = nodeFs, hasBody, now = new Date() }: any = {}): any {
243
+ function readFold(root , { fsImpl = nodeFs, hasBody, now = new Date() } = {}) {
244
244
  const { events, unreadable, reasons } = readEvents(root, { fsImpl });
245
245
  return { ...finalize(foldInto(events, { now }), { hasBody }), unreadable, unreadableReasons: reasons };
246
246
  }
247
247
 
248
248
  /** Picks a free, valid id for each draft before any file is created, so a batch is all or nothing. */
249
- function allocateIds(fsImpl: any, dir: string, stamped: any[], random: (n: number) => string): string[] | null {
250
- const chosen = new Set<string>();
251
- const ids: string[] = [];
249
+ function allocateIds(fsImpl , dir , stamped , random ) {
250
+ const chosen = new Set ();
251
+ const ids = [];
252
252
  for (const { at, id } of stamped) {
253
- let candidate: string | null = id;
253
+ let candidate = id;
254
254
  for (let attempt = 0; attempt <= COLLISION_RETRIES; attempt += 1) {
255
255
  if (attempt > 0) candidate = idFor(at, random);
256
- if (EVENT_ID.test(candidate as string) && !chosen.has(candidate as string) && !fsImpl.existsSync(path.join(dir, `${candidate}.json`))) break;
256
+ if (EVENT_ID.test(candidate ) && !chosen.has(candidate ) && !fsImpl.existsSync(path.join(dir, `${candidate}.json`))) break;
257
257
  candidate = null;
258
258
  }
259
259
  if (!candidate) return null;
@@ -276,17 +276,17 @@ function allocateIds(fsImpl: any, dir: string, stamped: any[], random: (n: numbe
276
276
  * conflict, with its own `code` in `conflict.code`), `id-collision`, `invalid-id` (the clock or
277
277
  * the random source cannot produce an id of the IC-001 shape) and `store-locked`.
278
278
  */
279
- function appendEvents(root: string, drafts: any[], { now = new Date(), fsImpl = nodeFs, random = randomChars }: any = {}): any {
279
+ function appendEvents(root , drafts , { now = new Date(), fsImpl = nodeFs, random = randomChars } = {}) {
280
280
  const dir = eventsDir(root);
281
281
  // A write that would be refused leaves nothing behind, not even the store folder (IC-001: created
282
282
  // on the first write), so the check runs once before the folder and the lock and again under the lock.
283
283
  const early = planEvents(root, drafts, { now, fsImpl, random });
284
284
  if (early.refused) return early.refused;
285
285
  fsImpl.mkdirSync(dir, { recursive: true });
286
- let release: () => void;
286
+ let release ;
287
287
  try {
288
288
  release = acquireLock(fsImpl, lockTarget(root));
289
- } catch (error: any) {
289
+ } catch (error ) {
290
290
  if (/^Could not lock/.test(error.message || '')) return { ok: false, finding: 'store-locked', message: `${error.message} Nothing was written.` };
291
291
  throw error;
292
292
  }
@@ -295,8 +295,8 @@ function appendEvents(root: string, drafts: any[], { now = new Date(), fsImpl =
295
295
  if (refused) return refused;
296
296
  const ids = allocateIds(fsImpl, dir, stamped, random);
297
297
  if (!ids) return { ok: false, finding: 'id-collision', written: [], message: `could not find a free event id after ${COLLISION_RETRIES} tries. Nothing was written.` };
298
- const written: any[] = [];
299
- stamped.forEach(({ draft, at }: any, index: number) => {
298
+ const written = [];
299
+ stamped.forEach(({ draft, at } , index ) => {
300
300
  const event = { v: 1, id: ids[index], type: draft.type, at, by: draft.by, data: draft.data };
301
301
  const file = path.join(dir, `${event.id}.json`);
302
302
  // The ids are free under the lock; the exclusive create only guards against a writer outside it.
@@ -310,15 +310,15 @@ function appendEvents(root: string, drafts: any[], { now = new Date(), fsImpl =
310
310
  }
311
311
 
312
312
  /** Folds the store, stamps each draft and applies it; `refused` is the whole call's refusal when any is illegal. */
313
- function planEvents(root: string, drafts: any[], { now, fsImpl, random }: any): any {
313
+ function planEvents(root , drafts , { now, fsImpl, random } ) {
314
314
  const state = foldInto(readEvents(root, { fsImpl }).events, { now });
315
315
  // An event dated far ahead is not in the fold (DEC-045), so it cannot push this stamp forward.
316
316
  let floor = state.newestAt === null ? -Infinity : state.newestAt + 1;
317
- const stamped: any[] = [];
317
+ const stamped = [];
318
318
  for (const draft of drafts) {
319
319
  const atMs = Math.max(now.getTime(), floor);
320
320
  floor = atMs + 1;
321
- let at: string | null;
321
+ let at ;
322
322
  try { at = new Date(atMs).toISOString(); } catch { at = null; }
323
323
  // The dry run draws the id the write will try first, so a conflict names the event it refuses.
324
324
  const id = at && isStrictAt(at) ? idFor(at, random) : null;