@khoavu882/doflow 2.0.0-beta.3 → 2.0.0-beta.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.
Files changed (167) hide show
  1. package/bin/doflow.js +2 -2
  2. package/core/.claude-plugin/plugin.json +1 -1
  3. package/core/.codex-plugin/plugin.json +1 -1
  4. package/core/.plugin/plugin.json +1 -1
  5. package/core/registry/storage.json +87 -83
  6. package/core/registry/verification.json +1 -1
  7. package/core/shared/scripts/doflow/bash/render-puml.sh +2 -2
  8. package/core/shared/skills/do-execute-plan/references/scaffold.md +2 -2
  9. package/package.json +4 -2
  10. package/src/adapters/antigravity/{index.ts → index.js} +60 -60
  11. package/src/adapters/claude/{index.ts → index.js} +48 -48
  12. package/src/adapters/claude/{mcp.ts → mcp.js} +16 -16
  13. package/src/adapters/codex/{agents.ts → agents.js} +24 -24
  14. package/src/adapters/codex/{config.ts → config.js} +49 -49
  15. package/src/adapters/codex/{hooks.ts → hooks.js} +23 -23
  16. package/src/adapters/codex/{index.ts → index.js} +98 -98
  17. package/src/adapters/codex/{mcp.ts → mcp.js} +38 -38
  18. package/src/adapters/codex/{native-projection.ts → native-projection.js} +5 -5
  19. package/src/adapters/copilot/{index.ts → index.js} +42 -42
  20. package/src/adapters/{copy-tree.ts → copy-tree.js} +70 -70
  21. package/src/adapters/gemini/{hooks.ts → hooks.js} +24 -24
  22. package/src/adapters/gemini/{index.ts → index.js} +41 -41
  23. package/src/adapters/{hook-commands.ts → hook-commands.js} +8 -8
  24. package/src/adapters/{index.ts → index.js} +13 -13
  25. package/src/adapters/kiro/{index.ts → index.js} +34 -34
  26. package/src/adapters/{mcp-entries.ts → mcp-entries.js} +55 -55
  27. package/src/adapters/opencode/{index.ts → index.js} +52 -52
  28. package/src/adapters/pi/{index.ts → index.js} +30 -30
  29. package/src/adapters/pi/{json-members.ts → json-members.js} +23 -23
  30. package/src/adapters/pi/{mcp.ts → mcp.js} +70 -70
  31. package/src/adapters/{resolve-source.ts → resolve-source.js} +1 -1
  32. package/src/cli/commands/{install.ts → install.js} +24 -24
  33. package/src/cli/commands/{list-backups.ts → list-backups.js} +4 -4
  34. package/src/cli/commands/{reconcile.ts → reconcile.js} +19 -19
  35. package/src/cli/commands/{remove.ts → remove.js} +10 -10
  36. package/src/cli/commands/{rollback.ts → rollback.js} +17 -17
  37. package/src/cli/commands/{self-update.ts → self-update.js} +3 -3
  38. package/src/cli/commands/{status.ts → status.js} +24 -24
  39. package/src/cli/commands/{tools.ts → tools.js} +16 -16
  40. package/src/cli/commands/{update.ts → update.js} +19 -19
  41. package/src/cli/{index.ts → index.js} +26 -26
  42. package/src/cli/{runtime-commands.ts → runtime-commands.js} +48 -48
  43. package/src/cli/{shared.ts → shared.js} +40 -40
  44. package/src/helper/{bash-helper.ts → bash-helper.js} +7 -7
  45. package/src/helper/{git.ts → git.js} +2 -2
  46. package/src/helper/{guardrails.ts → guardrails.js} +10 -10
  47. package/src/helper/{harness-paths.ts → harness-paths.js} +24 -24
  48. package/src/helper/{marker-merge.ts → marker-merge.js} +4 -4
  49. package/src/helper/{prompt.ts → prompt.js} +5 -5
  50. package/src/helper/{repo-root.ts → repo-root.js} +2 -2
  51. package/src/helper/{settings-merge.ts → settings-merge.js} +27 -27
  52. package/src/helper/{settings-scope.ts → settings-scope.js} +3 -3
  53. package/src/helper/{toml.ts → toml.js} +48 -48
  54. package/src/install/{backup-set.ts → backup-set.js} +16 -16
  55. package/src/install/{backup.ts → backup.js} +65 -65
  56. package/src/install/{context.ts → context.js} +15 -15
  57. package/src/install/{manifest.ts → manifest.js} +27 -27
  58. package/src/install/{mcp.ts → mcp.js} +30 -30
  59. package/src/install/{paths.ts → paths.js} +15 -15
  60. package/src/install/{targets.ts → targets.js} +10 -10
  61. package/src/install/{tool-lifecycle.ts → tool-lifecycle.js} +20 -20
  62. package/src/lifecycle/{bash-availability.ts → bash-availability.js} +1 -1
  63. package/src/lifecycle/{index.ts → index.js} +140 -140
  64. package/src/lifecycle/{mcp-index.ts → mcp-index.js} +1 -1
  65. package/src/lifecycle/{policies.ts → policies.js} +11 -11
  66. package/src/lifecycle/{view.ts → view.js} +28 -28
  67. package/src/registry/{index.ts → index.js} +60 -60
  68. package/src/release/build-package.js +91 -0
  69. package/src/release/changelog-section.js +70 -0
  70. package/src/release/{sync-plugin-versions.ts → sync-plugin-versions.js} +4 -4
  71. package/src/runtime/advice/{cli.ts → cli.js} +31 -31
  72. package/src/runtime/advice/{client.ts → client.js} +44 -44
  73. package/src/runtime/advice/{config.ts → config.js} +16 -16
  74. package/src/runtime/advice/{doctor.ts → doctor.js} +32 -32
  75. package/src/runtime/advice/{endpoint-guard.ts → endpoint-guard.js} +20 -20
  76. package/src/runtime/advice/{kinds.ts → kinds.js} +16 -16
  77. package/src/runtime/advice/providers/{ollama-systemone.ts → ollama-systemone.js} +21 -21
  78. package/src/runtime/advice/{record.ts → record.js} +19 -19
  79. package/src/runtime/advice/{registry.ts → registry.js} +16 -16
  80. package/src/runtime/advice/{strength.ts → strength.js} +7 -7
  81. package/src/runtime/{brief-tools.ts → brief-tools.js} +50 -50
  82. package/src/runtime/{c4-project.ts → c4-project.js} +27 -27
  83. package/src/runtime/{capability-router.ts → capability-router.js} +39 -39
  84. package/src/runtime/{checkouts.ts → checkouts.js} +21 -21
  85. package/src/runtime/{claims.ts → claims.js} +30 -30
  86. package/src/runtime/{cli-result.ts → cli-result.js} +4 -4
  87. package/src/runtime/{cli.ts → cli.js} +37 -37
  88. package/src/runtime/{command-detect.ts → command-detect.js} +47 -47
  89. package/src/runtime/{context-pack.ts → context-pack.js} +20 -20
  90. package/src/runtime/{decision-register.ts → decision-register.js} +67 -67
  91. package/src/runtime/{evidence-ledger.ts → evidence-ledger.js} +25 -25
  92. package/src/runtime/failure/{capture.ts → capture.js} +29 -29
  93. package/src/runtime/failure/{classifier.ts → classifier.js} +4 -4
  94. package/src/runtime/failure/{cli.ts → cli.js} +30 -30
  95. package/src/runtime/failure/{home.ts → home.js} +6 -6
  96. package/src/runtime/failure/{store.ts → store.js} +32 -32
  97. package/src/runtime/{feature-resolve.ts → feature-resolve.js} +6 -6
  98. package/src/runtime/{freshness.ts → freshness.js} +15 -15
  99. package/src/runtime/{health.ts → health.js} +72 -72
  100. package/src/runtime/{history-compactor.ts → history-compactor.js} +25 -25
  101. package/src/runtime/{implementation-gate.ts → implementation-gate.js} +30 -30
  102. package/src/runtime/inventory/{coverage.ts → coverage.js} +10 -10
  103. package/src/runtime/inventory/{identity.ts → identity.js} +2 -2
  104. package/src/runtime/inventory/{index.ts → index.js} +36 -36
  105. package/src/runtime/inventory/{precedence.ts → precedence.js} +2 -2
  106. package/src/runtime/inventory/{read-scopes.ts → read-scopes.js} +9 -9
  107. package/src/runtime/inventory/{siblings.ts → siblings.js} +15 -15
  108. package/src/runtime/knowledge/{chunker.ts → chunker.js} +12 -12
  109. package/src/runtime/knowledge/{hybrid.ts → hybrid.js} +17 -17
  110. package/src/runtime/knowledge/{index-store.ts → index-store.js} +23 -23
  111. package/src/runtime/knowledge/{retrieval.ts → retrieval.js} +27 -27
  112. package/src/runtime/{leak-scan.ts → leak-scan.js} +12 -12
  113. package/src/runtime/lifecycle/{cli.ts → cli.js} +32 -32
  114. package/src/runtime/lifecycle/{event-store.ts → event-store.js} +48 -48
  115. package/src/runtime/lifecycle/{fold.ts → fold.js} +41 -41
  116. package/src/runtime/lifecycle/{followup.ts → followup.js} +54 -54
  117. package/src/runtime/lifecycle/{goal.ts → goal.js} +50 -50
  118. package/src/runtime/lifecycle/{intent-writer.ts → intent-writer.js} +5 -5
  119. package/src/runtime/lifecycle/{overview.ts → overview.js} +47 -47
  120. package/src/runtime/lifecycle/{release.ts → release.js} +29 -29
  121. package/src/runtime/lifecycle/{report-store.ts → report-store.js} +25 -25
  122. package/src/runtime/lifecycle/{retention.ts → retention.js} +37 -37
  123. package/src/runtime/lifecycle/{root.ts → root.js} +9 -9
  124. package/src/runtime/lifecycle/{status.ts → status.js} +64 -64
  125. package/src/runtime/lifecycle/{store-upkeep.ts → store-upkeep.js} +46 -46
  126. package/src/runtime/{locator-resolve.ts → locator-resolve.js} +7 -7
  127. package/src/runtime/{mask.ts → mask.js} +22 -22
  128. package/src/runtime/{mcp-consultations.ts → mcp-consultations.js} +54 -54
  129. package/src/runtime/{mcp-reach.ts → mcp-reach.js} +24 -24
  130. package/src/runtime/{model-router.ts → model-router.js} +20 -20
  131. package/src/runtime/{outcome.ts → outcome.js} +27 -27
  132. package/src/runtime/{reach.ts → reach.js} +21 -21
  133. package/src/runtime/{readiness-record.ts → readiness-record.js} +12 -12
  134. package/src/runtime/{readiness.ts → readiness.js} +35 -35
  135. package/src/runtime/{recovery.ts → recovery.js} +15 -15
  136. package/src/runtime/{research-request.ts → research-request.js} +34 -34
  137. package/src/runtime/{retrieval-plan.ts → retrieval-plan.js} +40 -40
  138. package/src/runtime/scaffold/{artifacts.ts → artifacts.js} +19 -19
  139. package/src/runtime/scaffold/{fingerprint.ts → fingerprint.js} +3 -3
  140. package/src/runtime/scaffold/{generate.ts → generate.js} +109 -109
  141. package/src/runtime/scaffold/{languages.ts → languages.js} +34 -34
  142. package/src/runtime/storage/{cli.ts → cli.js} +9 -9
  143. package/src/runtime/storage/{engine.ts → engine.js} +37 -37
  144. package/src/runtime/storage/{registry.ts → registry.js} +19 -19
  145. package/src/runtime/storage/{roots.ts → roots.js} +8 -8
  146. package/src/runtime/storage/{rules.ts → rules.js} +26 -26
  147. package/src/runtime/storage/{upkeep.ts → upkeep.js} +35 -35
  148. package/src/runtime/storage/{work-status.ts → work-status.js} +39 -39
  149. package/src/runtime/{task-attempts.ts → task-attempts.js} +61 -61
  150. package/src/runtime/{task-classifier.ts → task-classifier.js} +34 -34
  151. package/src/runtime/{task-scope.ts → task-scope.js} +13 -13
  152. package/src/runtime/{task-state.ts → task-state.js} +15 -15
  153. package/src/runtime/trace/{indicators.ts → indicators.js} +22 -22
  154. package/src/runtime/trace/{ledger.ts → ledger.js} +42 -42
  155. package/src/runtime/trace/{render.ts → render.js} +7 -7
  156. package/src/runtime/trace/{views.ts → views.js} +40 -40
  157. package/src/runtime/verification/{contract-runner.ts → contract-runner.js} +23 -23
  158. package/src/runtime/verification/{engine.ts → engine.js} +143 -143
  159. package/src/runtime/verification/{registry.ts → registry.js} +6 -6
  160. package/src/runtime/verification/{scope-bound.ts → scope-bound.js} +50 -50
  161. package/src/runtime/verification/{test-selection.ts → test-selection.js} +28 -28
  162. package/src/runtime/{workflow-engine.ts → workflow-engine.js} +50 -50
  163. package/src/runtime/{workflow-orchestrator.ts → workflow-orchestrator.js} +91 -91
  164. package/src/runtime/{worktree.ts → worktree.js} +31 -31
  165. package/src/state/{index.ts → index.js} +26 -26
  166. package/src/state/{lockfile.ts → lockfile.js} +20 -20
  167. package/src/state/{run-lock.ts → run-lock.js} +44 -44
@@ -29,17 +29,17 @@
29
29
  const fs = require('node:fs');
30
30
  const path = require('node:path');
31
31
  const { execFileSync } = require('node:child_process');
32
- const { REPO_ROOT } = require('../../helper/repo-root.ts');
33
- const { resolveBashHelper } = require('../../helper/bash-helper.ts');
32
+ const { REPO_ROOT } = require('../../helper/repo-root.js');
33
+ const { resolveBashHelper } = require('../../helper/bash-helper.js');
34
34
 
35
35
  const MAX_BUFFER = 256 * 1024 * 1024;
36
36
 
37
37
  /** Where `do-git-state.sh` is: the shared resolver (package copy first, else the one projected beside the runtime). */
38
- function resolveGitStateHelper(repoRoot: string = REPO_ROOT, existsImpl: (file: string) => boolean = fs.existsSync): string | null {
38
+ function resolveGitStateHelper(repoRoot = REPO_ROOT, existsImpl = fs.existsSync) {
39
39
  return resolveBashHelper('do-git-state.sh', repoRoot, existsImpl);
40
40
  }
41
41
 
42
- function git(root: string, args: string[]): string {
42
+ function git(root , args ) {
43
43
  return execFileSync('git', args, { cwd: root, encoding: 'utf8', maxBuffer: MAX_BUFFER, stdio: ['ignore', 'pipe', 'ignore'] });
44
44
  }
45
45
 
@@ -49,7 +49,7 @@ function git(root: string, args: string[]): string {
49
49
  * @returns {{integration_ref:string|null, feature_prefixes:string[], release_tags:string[], base_tag:string|null}
50
50
  * |{error:string}}
51
51
  */
52
- function readGitFacts(root: string, runtimeRoot: string = REPO_ROOT): any {
52
+ function readGitFacts(root , runtimeRoot = REPO_ROOT) {
53
53
  const helper = resolveGitStateHelper(runtimeRoot);
54
54
  if (!helper) return { error: 'git-state-helper-missing' };
55
55
  try {
@@ -57,20 +57,20 @@ function readGitFacts(root: string, runtimeRoot: string = REPO_ROOT): any {
57
57
  const facts = JSON.parse(out);
58
58
  if (facts.error) return { error: facts.error };
59
59
  return facts;
60
- } catch (error: any) {
60
+ } catch (error ) {
61
61
  return { error: error.code === 'ENOENT' ? 'bash-not-found' : 'git-state-failed' };
62
62
  }
63
63
  }
64
64
 
65
- function escapeRegExp(text: string): string { return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }
65
+ function escapeRegExp(text ) { return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }
66
66
 
67
67
  /** The slug appears in the subject bounded by its ends or by characters outside `[a-z0-9-]`. */
68
- function subjectNames(subject: string, slug: string): boolean {
68
+ function subjectNames(subject , slug ) {
69
69
  return new RegExp(`(?:^|[^a-z0-9-])${escapeRegExp(slug)}(?:$|[^a-z0-9-])`).test(subject);
70
70
  }
71
71
 
72
72
  /** First-parent merges of `ref`, oldest first. */
73
- function readMerges(root: string, ref: string): Array<{ sha: string; parents: string[]; ct: number; subject: string }> {
73
+ function readMerges(root , ref ) {
74
74
  const out = git(root, ['log', '--first-parent', '--merges', '--format=%H%x09%P%x09%ct%x09%s', ref]);
75
75
  return out.split('\n').filter(Boolean).map((line) => {
76
76
  const [sha, parents, ct, ...subject] = line.split('\t');
@@ -79,9 +79,9 @@ function readMerges(root: string, ref: string): Array<{ sha: string; parents: st
79
79
  }
80
80
 
81
81
  /** Branch refs by short name (`feat/x`, `origin/feat/x`) with their tips; local branches first. */
82
- function readBranchTips(root: string): Array<{ short: string; local: string; sha: string }> {
82
+ function readBranchTips(root ) {
83
83
  const out = git(root, ['for-each-ref', '--format=%(refname)%09%(objectname)', 'refs/heads', 'refs/remotes']);
84
- const tips: Array<{ short: string; local: string; sha: string }> = [];
84
+ const tips = [];
85
85
  for (const line of out.split('\n').filter(Boolean)) {
86
86
  const [refname, sha] = line.split('\t');
87
87
  if (refname.startsWith('refs/heads/')) tips.push({ short: refname.slice('refs/heads/'.length), local: refname.slice('refs/heads/'.length), sha });
@@ -94,7 +94,7 @@ function readBranchTips(root: string): Array<{ short: string; local: string; sha
94
94
  }
95
95
 
96
96
  /** The commit a tag names, peeled through any number of tag objects, or null when it is no commit. */
97
- function peelTag(root: string, refname: string): string | null {
97
+ function peelTag(root , refname ) {
98
98
  try { return git(root, ['rev-parse', '--verify', '--quiet', `${refname}^{commit}`]).trim() || null; } catch { return null; }
99
99
  }
100
100
 
@@ -103,14 +103,14 @@ function peelTag(root: string, refname: string): string | null {
103
103
  * `tag.sort`, as `git tag --contains` did), so the first containing tag is the one it would name.
104
104
  * @returns {Array<{name:string, commit:string|null}>}
105
105
  */
106
- function readTagCommits(root: string, wanted: Set<string>): Array<{ name: string; commit: string | null }> {
106
+ function readTagCommits(root , wanted ) {
107
107
  const out = git(root, ['tag', '--list', 'v*', '--format=%(refname)%09%(objecttype)%09%(objectname)%09%(*objecttype)%09%(*objectname)']);
108
- const tags: Array<{ name: string; commit: string | null }> = [];
108
+ const tags = [];
109
109
  for (const line of out.split('\n').filter(Boolean)) {
110
110
  const [refname, type, object, peeledType, peeled] = line.split('\t');
111
111
  const name = refname.slice('refs/tags/'.length);
112
112
  if (!wanted.has(name)) continue;
113
- let commit: string | null = null;
113
+ let commit = null;
114
114
  if (type === 'commit') commit = object;
115
115
  else if (type === 'tag' && peeledType === 'commit') commit = peeled;
116
116
  else if (type === 'tag') commit = peelTag(root, refname); // a tag of a tag: rare, one call each
@@ -134,53 +134,53 @@ function readTagCommits(root: string, wanted: Set<string>): Array<{ name: string
134
134
  * @param {string} pinned a full commit sha
135
135
  * @param {string[]} [revs] further full commit shas whose history is read too
136
136
  */
137
- function readHistory(root: string, pinned: string, revs: string[] = []): { introducer: (sha: string) => string | undefined; isAncestor: (a: string, b: string) => boolean } {
137
+ function readHistory(root , pinned , revs = []) {
138
138
  const input = `${[pinned, ...revs].join('\n')}\n`;
139
139
  const out = execFileSync('git', ['rev-list', '--parents', '--topo-order', '--stdin'], { cwd: root, input, encoding: 'utf8', maxBuffer: MAX_BUFFER, stdio: ['pipe', 'pipe', 'ignore'] });
140
- const parents = new Map<string, string[]>();
141
- const order: string[] = [];
140
+ const parents = new Map ();
141
+ const order = [];
142
142
  for (const line of out.split('\n')) {
143
143
  if (!line) continue;
144
144
  const [sha, ...rest] = line.split(' ');
145
145
  parents.set(sha, rest);
146
146
  order.push(sha);
147
147
  }
148
- const chain: string[] = [];
149
- for (let sha = pinned; parents.has(sha); sha = (parents.get(sha) as string[])[0]) chain.push(sha);
148
+ const chain = [];
149
+ for (let sha = pinned; parents.has(sha); sha = (parents.get(sha) )[0]) chain.push(sha);
150
150
  chain.reverse();
151
- const chainIndex = new Map<string, number>(chain.map((sha, i): [string, number] => [sha, i]));
151
+ const chainIndex = new Map (chain.map((sha, i) => [sha, i]));
152
152
 
153
- const introducer = new Map<string, string>();
153
+ const introducer = new Map ();
154
154
  for (const head of chain) {
155
- const stack: string[] = [head];
155
+ const stack = [head];
156
156
  while (stack.length) {
157
- const sha = stack.pop() as string;
157
+ const sha = stack.pop() ;
158
158
  if (introducer.has(sha) || !parents.has(sha)) continue;
159
159
  introducer.set(sha, head);
160
- stack.push(...(parents.get(sha) as string[]));
160
+ stack.push(...(parents.get(sha) ));
161
161
  }
162
162
  }
163
163
 
164
164
  // --topo-order lists no parent before its children, so walking it backwards meets parents first.
165
- const chainMax = new Map<string, number>();
165
+ const chainMax = new Map ();
166
166
  for (let i = order.length - 1; i >= 0; i -= 1) {
167
167
  const sha = order[i];
168
- let max: number = chainIndex.has(sha) ? (chainIndex.get(sha) as number) : -1;
169
- if (max === -1) for (const parent of parents.get(sha) as string[]) max = Math.max(max, chainMax.get(parent) ?? -1);
168
+ let max = chainIndex.has(sha) ? (chainIndex.get(sha) ) : -1;
169
+ if (max === -1) for (const parent of parents.get(sha) ) max = Math.max(max, chainMax.get(parent) ?? -1);
170
170
  chainMax.set(sha, max);
171
171
  }
172
172
 
173
- const reached = new Map<string, Set<string>>();
174
- function ancestorsOf(sha: string): Set<string> {
173
+ const reached = new Map ();
174
+ function ancestorsOf(sha ) {
175
175
  let seen = reached.get(sha);
176
176
  if (seen) return seen;
177
- seen = new Set<string>();
178
- const stack: string[] = [sha];
177
+ seen = new Set ();
178
+ const stack = [sha];
179
179
  while (stack.length) {
180
- const next = stack.pop() as string;
180
+ const next = stack.pop() ;
181
181
  if (seen.has(next) || !parents.has(next)) continue;
182
182
  seen.add(next);
183
- stack.push(...(parents.get(next) as string[]));
183
+ stack.push(...(parents.get(next) ));
184
184
  }
185
185
  reached.set(sha, seen);
186
186
  return seen;
@@ -188,9 +188,9 @@ function readHistory(root: string, pinned: string, revs: string[] = []): { intro
188
188
 
189
189
  return {
190
190
  /** The chain commit that brought `sha` into `pinned`'s history, or undefined when it is not in it. */
191
- introducer: (sha: string) => introducer.get(sha),
191
+ introducer: (sha ) => introducer.get(sha),
192
192
  /** `a` is `b` or an ancestor of it; `a` must be in the read. */
193
- isAncestor(a: string, b: string): boolean {
193
+ isAncestor(a , b ) {
194
194
  const index = chainIndex.get(a);
195
195
  if (index !== undefined) return index <= (chainMax.get(b) ?? -1);
196
196
  return ancestorsOf(b).has(a);
@@ -205,17 +205,17 @@ function readHistory(root: string, pinned: string, revs: string[] = []): { intro
205
205
  * (a fast-forward, or a branch with no commits of its own) is its own introducer, so it never counts;
206
206
  * a tip the merge holds but its first parent does not came in on a non-first parent.
207
207
  */
208
- function introducingMerge(history: () => any, mergeBySha: Map<string, any>, tip: string, lowerBound: number): any {
208
+ function introducingMerge(history , mergeBySha , tip , lowerBound ) {
209
209
  const merge = mergeBySha.get(history().introducer(tip));
210
210
  if (!merge || merge.sha === tip || merge.ct < lowerBound) return null;
211
211
  return merge;
212
212
  }
213
213
 
214
214
  /** Evidence of a merge of `slug` into the pinned ref, tried in IC-021's order, or null. */
215
- function findEvidence({ slug, lowerBound, merges, mergeBySha, newestCt, history, tips, prefixes, confirmed }: any): { kind: string; ref: string | null; commit: string | null } | null {
216
- const branchNames = new Set(prefixes.map((prefix: string) => `${prefix}/${slug}`));
215
+ function findEvidence({ slug, lowerBound, merges, mergeBySha, newestCt, history, tips, prefixes, confirmed } ) {
216
+ const branchNames = new Set(prefixes.map((prefix ) => `${prefix}/${slug}`));
217
217
  // No merge is recent enough for this feature: no branch can have one, so the graph need not be read for it.
218
- const branchTips = newestCt < lowerBound ? [] : tips.filter((t: any) => branchNames.has(t.local));
218
+ const branchTips = newestCt < lowerBound ? [] : tips.filter((t ) => branchNames.has(t.local));
219
219
  for (const tip of branchTips) {
220
220
  const merge = introducingMerge(history, mergeBySha, tip.sha, lowerBound);
221
221
  if (merge) return { kind: 'branch', ref: tip.short, commit: merge.sha };
@@ -228,8 +228,8 @@ function findEvidence({ slug, lowerBound, merges, mergeBySha, newestCt, history,
228
228
  }
229
229
 
230
230
  /** A value computed on first use, so a call that needs no graph never reads one. */
231
- function lazy<T>(make: () => T): () => T {
232
- let value: T;
231
+ function lazy (make ) {
232
+ let value ;
233
233
  let made = false;
234
234
  return () => {
235
235
  if (!made) { value = make(); made = true; }
@@ -237,12 +237,12 @@ function lazy<T>(make: () => T): () => T {
237
237
  };
238
238
  }
239
239
 
240
- const BUCKET: Record<string, string> = { finished: 'finished', 'awaiting-release': 'awaitingRelease', 'in-progress': 'inProgress', unknown: 'unknown' };
240
+ const BUCKET = { finished: 'finished', 'awaiting-release': 'awaitingRelease', 'in-progress': 'inProgress', unknown: 'unknown' };
241
241
 
242
- function emptyBuckets(): Record<string, string[]> { return { finished: [], awaitingRelease: [], inProgress: [], unknown: [] }; }
242
+ function emptyBuckets() { return { finished: [], awaitingRelease: [], inProgress: [], unknown: [] }; }
243
243
 
244
244
  /** Slugs grouped in the four buckets IC-007 and IC-022 show. */
245
- function bucketize(statuses: any, slugs: string[] = Object.keys(statuses)): Record<string, string[]> {
245
+ function bucketize(statuses , slugs = Object.keys(statuses)) {
246
246
  const buckets = emptyBuckets();
247
247
  for (const slug of slugs) {
248
248
  const entry = statuses[slug];
@@ -251,12 +251,12 @@ function bucketize(statuses: any, slugs: string[] = Object.keys(statuses)): Reco
251
251
  return buckets;
252
252
  }
253
253
 
254
- function result(releaseMode: string, integrationRef: string | null, reason: string | null, statuses: any, notDetected: string[] = [], behind: number = 0): any {
254
+ function result(releaseMode , integrationRef , reason , statuses , notDetected = [], behind = 0) {
255
255
  return { releaseMode, integrationRef, integrationBehind: behind, reason, statuses, features: bucketize(statuses), notDetected };
256
256
  }
257
257
 
258
258
  /** The one-line note a stale local integration branch earns (DEC-044), or null. */
259
- function behindNote(ref: string, behind: number): string | null {
259
+ function behindNote(ref , behind ) {
260
260
  return behind > 0
261
261
  ? `local ${ref} is ${behind} commit${behind === 1 ? '' : 's'} behind origin/${ref}; a merge that exists only on origin is not seen until you pull`
262
262
  : null;
@@ -277,10 +277,10 @@ function behindNote(ref: string, behind: number): string | null {
277
277
  * failure?:string (git, or the git-facts helper, failed while deriving: `git-state-failed`, `bash-not-found`,
278
278
  * `git-state-helper-missing`; an environment fault, so every status is `unknown`)}}
279
279
  */
280
- function deriveStatuses({ root, fold, facts = readGitFacts(root) }: { root: string; fold: any; facts?: any }): any {
280
+ function deriveStatuses({ root, fold, facts = readGitFacts(root) } ) {
281
281
  const tracked = fold.features;
282
- const unknown = (reason: string) => result('unknown', facts.integration_ref ?? null, reason,
283
- Object.fromEntries(tracked.map((f: any) => [f.slug, { status: 'unknown', evidence: null, release: null }])));
282
+ const unknown = (reason ) => result('unknown', facts.integration_ref ?? null, reason,
283
+ Object.fromEntries(tracked.map((f ) => [f.slug, { status: 'unknown', evidence: null, release: null }])));
284
284
  if (facts.error) return { ...unknown(`git facts unavailable: ${facts.error}`), failure: facts.error };
285
285
  if (!facts.integration_ref) return unknown('no integration ref resolves (develop, main, master, origin/HEAD)');
286
286
 
@@ -297,21 +297,21 @@ function deriveStatuses({ root, fold, facts = readGitFacts(root) }: { root: stri
297
297
  // Pin the ref once: every query below names the same commit.
298
298
  const pinned = git(root, ['rev-parse', '--verify', `${ref}^{commit}`]).trim();
299
299
  const merges = readMerges(root, pinned);
300
- const mergeBySha = new Map(merges.map((m): [string, any] => [m.sha, m]));
300
+ const mergeBySha = new Map(merges.map((m) => [m.sha, m]));
301
301
  const newestCt = merges.reduce((max, m) => Math.max(max, m.ct), -Infinity);
302
302
  const tips = readBranchTips(root);
303
- const mergedSlugs = new Set<string>(fold.merged.map((m: any) => m.slug));
304
- const recorded = new Map<string, string>();
303
+ const mergedSlugs = new Set (fold.merged.map((m ) => m.slug));
304
+ const recorded = new Map ();
305
305
  for (const release of fold.releases) for (const f of release.features) if (!recorded.has(f.slug)) recorded.set(f.slug, release.tag);
306
- const recordedTags = new Set(fold.releases.map((r: any) => r.tag));
307
- const unrecordedTags = new Set<string>(facts.release_tags.filter((tag: string) => !recordedTags.has(tag)));
306
+ const recordedTags = new Set(fold.releases.map((r ) => r.tag));
307
+ const unrecordedTags = new Set (facts.release_tags.filter((tag ) => !recordedTags.has(tag)));
308
308
  // Only a tag with no release record can finish a feature by containment (DEC-030), so only those are read.
309
309
  const tags = lazy(() => (releaseMode === 'tagged' && unrecordedTags.size > 0 ? readTagCommits(root, unrecordedTags) : []));
310
- const history = lazy(() => readHistory(root, pinned, tags().map((t) => t.commit).filter(Boolean) as string[]));
310
+ const history = lazy(() => readHistory(root, pinned, tags().map((t) => t.commit).filter(Boolean) ));
311
311
 
312
- const statuses: Record<string, any> = {};
313
- const evidenceCommits: Record<string, string | null> = {};
314
- const notDetected: string[] = [];
312
+ const statuses = {};
313
+ const evidenceCommits = {};
314
+ const notDetected = [];
315
315
  for (const feature of tracked) {
316
316
  const lowerBound = Math.floor(Date.parse(feature.trackedAt) / 1000);
317
317
  const evidence = findEvidence({
@@ -319,20 +319,20 @@ function deriveStatuses({ root, fold, facts = readGitFacts(root) }: { root: stri
319
319
  });
320
320
  const shown = evidence && { kind: evidence.kind, ref: evidence.ref };
321
321
  evidenceCommits[feature.slug] = evidence ? evidence.commit : null;
322
- let status: string;
323
- let release: string | null = null;
322
+ let status ;
323
+ let release = null;
324
324
  if (releaseMode === 'untagged') {
325
325
  status = evidence ? 'finished' : 'in-progress';
326
326
  } else if (recorded.has(feature.slug)) {
327
327
  // A record finishes the feature by itself: no containment is looked for.
328
328
  status = 'finished';
329
- release = recorded.get(feature.slug) as string;
329
+ release = recorded.get(feature.slug) ;
330
330
  } else {
331
331
  // DEC-030: a merge inside a `v*` tag that has no release record also finishes the feature. A
332
332
  // tag with a record uses only that record, and a feature excluded from it is already outside it.
333
333
  // The evidence commit is a first-parent merge of the pinned ref, so it is in the graph read.
334
334
  const containing = evidence && evidence.commit && unrecordedTags.size > 0
335
- ? tags().filter((t) => t.commit && history().isAncestor(evidence.commit as string, t.commit as string)).map((t) => t.name)
335
+ ? tags().filter((t) => t.commit && history().isAncestor(evidence.commit , t.commit )).map((t) => t.name)
336
336
  : [];
337
337
  if (containing.length > 0) { status = 'finished'; release = containing[0]; }
338
338
  else status = evidence ? 'awaiting-release' : 'in-progress';
@@ -343,7 +343,7 @@ function deriveStatuses({ root, fold, facts = readGitFacts(root) }: { root: stri
343
343
  // `integrationSha` and `evidenceCommits` are for the release preview, which must use the very commit
344
344
  // pinned here (DEC-044) and the full merge commit an evidence names, not its 7-character `ref`.
345
345
  return { ...result(releaseMode, ref, null, statuses, notDetected, behind), integrationSha: pinned, evidenceCommits };
346
- } catch (error: any) {
346
+ } catch (error ) {
347
347
  // A git failure is an environment fault, not a DoFlow defect: it is reported, never thrown.
348
348
  // `failure` tells a caller git itself failed, which it reports (overview) or refuses on (release, merged).
349
349
  return { ...unknown(`git could not answer (git-state-failed): ${String(error.message).split('\n')[0]}`), failure: 'git-state-failed' };
@@ -24,11 +24,11 @@
24
24
 
25
25
  const nodeFs = require('node:fs');
26
26
  const path = require('node:path');
27
- const { acquireLock, tryAcquireLock } = require('../task-state.ts');
27
+ const { acquireLock, tryAcquireLock } = require('../task-state.js');
28
28
  const {
29
29
  EVENTS_REL, LIFECYCLE_REL, JOURNAL_REL, lockTarget, isEventName, randomChars, readEvents, readJournal, StoreUnsafeError,
30
- } = require('./event-store.ts');
31
- const { retentionWindow, selectExpired } = require('./retention.ts');
30
+ } = require('./event-store.js');
31
+ const { retentionWindow, selectExpired } = require('./retention.js');
32
32
 
33
33
  const LEGACY_LIFECYCLE_REL = path.join('agent-docs', 'lifecycle');
34
34
  const LEGACY_EVENTS_REL = path.join(LEGACY_LIFECYCLE_REL, 'events');
@@ -36,30 +36,30 @@ const LEGACY_EVENTS_REL = path.join(LEGACY_LIFECYCLE_REL, 'events');
36
36
  const MARKER_REL = path.join(LIFECYCLE_REL, 'migrated.json');
37
37
  const MIGRATING_PREFIX = 'events.migrating-';
38
38
  const NOTICE = 'note: the lifecycle store is now .doflow/state/lifecycle/events; agent-docs/lifecycle/ is no longer read and can be deleted';
39
- const removedLine = (count: any, hours: any) => `retention: removed ${count} event files older than ${hours} h`;
40
- const invalidLine = (raw: any) => `warning: DOFLOW_RETENTION_HOURS='${raw}' is not a positive whole number of hours; ignored, nothing removed`;
39
+ const removedLine = (count , hours ) => `retention: removed ${count} event files older than ${hours} h`;
40
+ const invalidLine = (raw ) => `warning: DOFLOW_RETENTION_HOURS='${raw}' is not a positive whole number of hours; ignored, nothing removed`;
41
41
  /** Bounds one pass, so its journal stays far below the reader's cap and its lock is held briefly. */
42
42
  const MAX_PASS_FILES = 20000;
43
43
  /** Unlinks between two refreshes of the lock's age. */
44
44
  const REFRESH_EVERY = 500;
45
- const unwritableLine = (code: any) => `warning: retention skipped: .doflow/state/lifecycle cannot be written (${code}); nothing was hidden or removed`;
46
- const unlinkLine = (code: any) => `warning: retention could not remove every file (${code}); they stay hidden and the next lifecycle command finishes the removal`;
45
+ const unwritableLine = (code ) => `warning: retention skipped: .doflow/state/lifecycle cannot be written (${code}); nothing was hidden or removed`;
46
+ const unlinkLine = (code ) => `warning: retention could not remove every file (${code}); they stay hidden and the next lifecycle command finishes the removal`;
47
47
 
48
- function lstatOrNull(fsImpl: any, file: any) {
48
+ function lstatOrNull(fsImpl , file ) {
49
49
  try { return fsImpl.lstatSync(file); } catch { return null; }
50
50
  }
51
51
 
52
52
  /** The names in a folder, or none when it is absent or not a folder. */
53
- function namesIn(fsImpl: any, dir: any) {
53
+ function namesIn(fsImpl , dir ) {
54
54
  try {
55
55
  return fsImpl.readdirSync(dir).sort();
56
- } catch (error: any) {
56
+ } catch (error ) {
57
57
  if (error.code === 'ENOENT' || error.code === 'ENOTDIR') return [];
58
58
  throw error;
59
59
  }
60
60
  }
61
61
 
62
- function refuseLinks(fsImpl: any, root: any, rels: any) {
62
+ function refuseLinks(fsImpl , root , rels ) {
63
63
  for (const rel of rels) {
64
64
  const folder = path.join(root, rel);
65
65
  const st = lstatOrNull(fsImpl, folder);
@@ -68,21 +68,21 @@ function refuseLinks(fsImpl: any, root: any, rels: any) {
68
68
  }
69
69
 
70
70
  /** The event files of the old folder that a copy takes: event-named regular files, nothing else. */
71
- function legacyEventFiles(fsImpl: any, root: any) {
71
+ function legacyEventFiles(fsImpl , root ) {
72
72
  const dir = path.join(root, LEGACY_EVENTS_REL);
73
73
  const st = lstatOrNull(fsImpl, dir);
74
74
  if (!st || !st.isDirectory()) return [];
75
- return namesIn(fsImpl, dir).filter((name: any) => {
75
+ return namesIn(fsImpl, dir).filter((name ) => {
76
76
  if (!isEventName(name)) return false;
77
77
  const entry = lstatOrNull(fsImpl, path.join(dir, name));
78
78
  return Boolean(entry && entry.isFile());
79
79
  });
80
80
  }
81
81
 
82
- const hasMarker = (fsImpl: any, root: any) => lstatOrNull(fsImpl, path.join(root, MARKER_REL)) !== null;
83
- const storeHasEvents = (fsImpl: any, root: any) => namesIn(fsImpl, path.join(root, EVENTS_REL)).some(isEventName);
82
+ const hasMarker = (fsImpl , root ) => lstatOrNull(fsImpl, path.join(root, MARKER_REL)) !== null;
83
+ const storeHasEvents = (fsImpl , root ) => namesIn(fsImpl, path.join(root, EVENTS_REL)).some(isEventName);
84
84
 
85
- function removeQuietly(fsImpl: any, target: any) {
85
+ function removeQuietly(fsImpl , target ) {
86
86
  try { fsImpl.rmSync(target, { recursive: true, force: true }); } catch { /* best effort */ }
87
87
  }
88
88
 
@@ -90,26 +90,26 @@ function removeQuietly(fsImpl: any, target: any) {
90
90
  * Flushes one copied file. The copy takes the source's mode, so it is made writable by its owner
91
91
  * first, like any file the store writes: Windows refuses to flush a read-only handle.
92
92
  */
93
- function fsyncCopy(fsImpl: any, file: any) {
93
+ function fsyncCopy(fsImpl , file ) {
94
94
  fsImpl.chmodSync(file, 0o644);
95
95
  const fd = fsImpl.openSync(file, 'r+');
96
96
  try { fsImpl.fsyncSync(fd); } finally { fsImpl.closeSync(fd); }
97
97
  }
98
98
 
99
99
  /** Flushes a folder's entries where the platform lets a folder be opened. */
100
- function fsyncFolder(fsImpl: any, dir: any) {
100
+ function fsyncFolder(fsImpl , dir ) {
101
101
  let fd;
102
102
  try { fd = fsImpl.openSync(dir, 'r'); } catch { return; }
103
103
  try { fsImpl.fsyncSync(fd); } finally { fsImpl.closeSync(fd); }
104
104
  }
105
105
 
106
- const migrationFailed = (code: any) => ({
106
+ const migrationFailed = (code ) => ({
107
107
  ok: false,
108
108
  finding: 'store-migration-failed',
109
109
  message: `could not copy agent-docs/lifecycle/events to .doflow/state/lifecycle/events (${code}); the old folder is unchanged and the next lifecycle command retries. Nothing was written.`,
110
110
  lines: [],
111
111
  });
112
- const legacyUnreadable = (code: any) => ({
112
+ const legacyUnreadable = (code ) => ({
113
113
  ok: false,
114
114
  finding: 'store-migration-failed',
115
115
  message: `could not list agent-docs/lifecycle/events (${code}), so the old store cannot be copied to .doflow/state/lifecycle/events; make the folder readable, or delete it if its events are not needed, and the next lifecycle command retries. Nothing was written.`,
@@ -117,7 +117,7 @@ const legacyUnreadable = (code: any) => ({
117
117
  });
118
118
 
119
119
  /** Writes `text` to `file` by a flushed temp file in the same folder and a rename. */
120
- function writeAtomic(fsImpl: any, file: any, text: any) {
120
+ function writeAtomic(fsImpl , file , text ) {
121
121
  const dir = path.dirname(file);
122
122
  const tmp = path.join(dir, `.${path.basename(file, '.json')}-${process.pid}-${randomChars(6)}.tmp`);
123
123
  try {
@@ -129,7 +129,7 @@ function writeAtomic(fsImpl: any, file: any, text: any) {
129
129
  fsImpl.closeSync(fd);
130
130
  }
131
131
  fsImpl.renameSync(tmp, file);
132
- } catch (error: any) {
132
+ } catch (error ) {
133
133
  try { fsImpl.unlinkSync(tmp); } catch { /* never written */ }
134
134
  throw error;
135
135
  }
@@ -137,7 +137,7 @@ function writeAtomic(fsImpl: any, file: any, text: any) {
137
137
  }
138
138
 
139
139
  /** Records that the store is in place; false when it cannot be written, so a later verb tries again. */
140
- function writeMarker(fsImpl: any, root: any, copied: any, now: any) {
140
+ function writeMarker(fsImpl , root , copied , now ) {
141
141
  try {
142
142
  writeAtomic(fsImpl, path.join(root, MARKER_REL), `${JSON.stringify({ v: 1, from: 'agent-docs/lifecycle/events', copied, at: now.toISOString() })}\n`);
143
143
  return true;
@@ -150,7 +150,7 @@ function writeMarker(fsImpl: any, root: any, copied: any, now: any) {
150
150
  * The copy itself, under the store lock, of the event files the caller listed. Returns the number
151
151
  * copied, or the `store-migration-failed` refusal.
152
152
  */
153
- function copyLegacyStore(fsImpl: any, root: any, files: any) {
153
+ function copyLegacyStore(fsImpl , root , files ) {
154
154
  const lifecycleDir = path.join(root, LIFECYCLE_REL);
155
155
  const eventsDir = path.join(root, EVENTS_REL);
156
156
  const legacyDir = path.join(root, LEGACY_EVENTS_REL);
@@ -176,26 +176,26 @@ function copyLegacyStore(fsImpl: any, root: any, files: any) {
176
176
  }
177
177
  try {
178
178
  fsImpl.renameSync(tmp, eventsDir);
179
- } catch (error: any) {
179
+ } catch (error ) {
180
180
  if (error.code !== 'EEXIST' && error.code !== 'ENOTEMPTY') throw error;
181
181
  removeQuietly(fsImpl, tmp); // another copier committed first
182
182
  }
183
183
  fsyncFolder(fsImpl, lifecycleDir);
184
184
  return files.length;
185
- } catch (error: any) {
185
+ } catch (error ) {
186
186
  if (tmp) removeQuietly(fsImpl, tmp);
187
187
  return migrationFailed(error.code || error.message);
188
188
  }
189
189
  }
190
190
 
191
191
  /** The UTC time an event file name's id starts with. */
192
- function idTime(name: any) {
192
+ function idTime(name ) {
193
193
  const m = /^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(\d{3})Z-/.exec(name);
194
194
  return m ? Date.UTC(+m[1], +m[2] - 1, +m[3], +m[4], +m[5], +m[6], +m[7]) : NaN;
195
195
  }
196
196
 
197
197
  /** Writes the retention journal, flushed to disk, with a new generation. */
198
- function writeJournal(fsImpl: any, root: any, pending: any) {
198
+ function writeJournal(fsImpl , root , pending ) {
199
199
  writeAtomic(fsImpl, path.join(root, JOURNAL_REL), `${JSON.stringify({ v: 1, generation: randomChars(16), pending })}\n`);
200
200
  }
201
201
 
@@ -203,13 +203,13 @@ function writeJournal(fsImpl: any, root: any, pending: any) {
203
203
  * Keeps the held store lock from looking stale: another verb breaks a lock whose folder is older
204
204
  * than the lock's stale timeout, so a long pass renews its folder's time as it goes.
205
205
  */
206
- function refreshLock(fsImpl: any, root: any) {
206
+ function refreshLock(fsImpl , root ) {
207
207
  const now = new Date();
208
208
  try { fsImpl.utimesSync(`${lockTarget(root)}.lock`, now, now); } catch { /* the lock folder is ours; a failed touch only shortens its life */ }
209
209
  }
210
210
 
211
211
  /** Unlinks pending event files without clearing the journal until every hidden name is finished. */
212
- function removePending(fsImpl: any, root: any, names: any, onRemoved = () => {}, { maxFiles = Infinity, shouldStop }: any = {}) {
212
+ function removePending(fsImpl , root , names , onRemoved = () => {}, { maxFiles = Infinity, shouldStop } = {}) {
213
213
  const dir = path.join(root, EVENTS_REL);
214
214
  let removed = 0;
215
215
  for (let index = 0; index < names.length; index += 1) {
@@ -217,14 +217,14 @@ function removePending(fsImpl: any, root: any, names: any, onRemoved = () => {},
217
217
  const file = path.join(dir, names[index]);
218
218
  if (removed >= maxFiles) {
219
219
  try { fsImpl.lstatSync(file); return { complete: false, removed }; }
220
- catch (error: any) { if (error.code !== 'ENOENT' && error.code !== 'ENOTDIR') throw error; continue; }
220
+ catch (error ) { if (error.code !== 'ENOENT' && error.code !== 'ENOTDIR') throw error; continue; }
221
221
  }
222
222
  if (index % REFRESH_EVERY === 0) refreshLock(fsImpl, root);
223
223
  try {
224
224
  fsImpl.unlinkSync(file);
225
225
  removed += 1;
226
226
  onRemoved();
227
- } catch (error: any) {
227
+ } catch (error ) {
228
228
  if (error.code !== 'ENOENT') throw error;
229
229
  }
230
230
  }
@@ -233,7 +233,7 @@ function removePending(fsImpl: any, root: any, names: any, onRemoved = () => {},
233
233
  }
234
234
 
235
235
  /** Selects whole units only; a unit that does not fit waits for the next pass. */
236
- function passFiles(units: any, { maxFiles = MAX_PASS_FILES, shouldStop }: any = {}) {
236
+ function passFiles(units , { maxFiles = MAX_PASS_FILES, shouldStop } = {}) {
237
237
  const files = [], limit = Math.max(0, Math.min(MAX_PASS_FILES, Number.isFinite(maxFiles) ? maxFiles : MAX_PASS_FILES));
238
238
  let partial = false;
239
239
  for (const unit of units) {
@@ -248,9 +248,9 @@ function passFiles(units: any, { maxFiles = MAX_PASS_FILES, shouldStop }: any =
248
248
  * The retention pass, under the store lock: finish a pending journal within the caller's remaining
249
249
  * limits, then remove whole eligible units. A stopped deletion keeps the complete name set hidden.
250
250
  */
251
- function retain(fsImpl: any, root: any, window: any, now: any, { maxFiles = MAX_PASS_FILES, shouldStop }: any = {}) {
251
+ function retain(fsImpl , root , window , now , { maxFiles = MAX_PASS_FILES, shouldStop } = {}) {
252
252
  let removedCount = 0;
253
- const selected: any[] = [];
253
+ const selected = [];
254
254
  try {
255
255
  if (shouldStop?.()) return { removed: [], removedCount, warning: [], partial: true, selected };
256
256
  const pending = readJournal(root, fsImpl).pending;
@@ -274,7 +274,7 @@ function retain(fsImpl: any, root: any, window: any, now: any, { maxFiles = MAX_
274
274
  if (shouldStop?.()) return { removed: [], removedCount, warning: [], partial: true, selected };
275
275
  const file = path.join(root, EVENTS_REL, name);
276
276
  let info;
277
- try { info = fsImpl.lstatSync(file); } catch (error: any) { if (error.code !== 'ENOENT') throw error; }
277
+ try { info = fsImpl.lstatSync(file); } catch (error ) { if (error.code !== 'ENOENT') throw error; }
278
278
  selected.push({ name, bytes: info?.isFile() ? info.size : 0 });
279
279
  }
280
280
  refreshLock(fsImpl, root);
@@ -285,7 +285,7 @@ function retain(fsImpl: any, root: any, window: any, now: any, { maxFiles = MAX_
285
285
  removed: window.source === 'default' ? [] : [removedLine(bounded.files.length, window.hours)],
286
286
  removedCount, warning: [], partial: bounded.partial || !result.complete, selected,
287
287
  };
288
- } catch (error: any) {
288
+ } catch (error ) {
289
289
  // A failure is not a stopped pass: `partial` means only a stop, a held lock or the removal cap,
290
290
  // so throttled upkeep advances its due time instead of retrying a failing pass on every verb.
291
291
  return { removed: [], removedCount, warning: [unlinkLine(error.code || error.message)], partial: false, selected, code: error.code || 'EIO' };
@@ -293,10 +293,10 @@ function retain(fsImpl: any, root: any, window: any, now: any, { maxFiles = MAX_
293
293
  }
294
294
 
295
295
  /** Runs a bounded lifecycle retention pass under a non-waiting store lock for the storage engine. */
296
- function retainLocked(root: any, options: any = {}) {
296
+ function retainLocked(root , options = {}) {
297
297
  const { window, now = new Date(), fsImpl = nodeFs, maxFiles = MAX_PASS_FILES, shouldStop } = options;
298
298
  const bounded = Object.hasOwn(options, 'maxFiles') || Object.hasOwn(options, 'shouldStop');
299
- const outcome = (removed: any, warning: any, partial = false, selected: any = [], code?: any) => bounded
299
+ const outcome = (removed , warning , partial = false, selected = [], code ) => bounded
300
300
  ? { removed, warning, partial, selected, ...(code ? { code } : {}) }
301
301
  : { removed, warning };
302
302
  const eventsDir = path.join(root, EVENTS_REL);
@@ -314,10 +314,10 @@ function retainLocked(root: any, options: any = {}) {
314
314
  }
315
315
 
316
316
  /** Whether a lock-free look finds anything for the retention pass to remove. */
317
- function needsPrune(fsImpl: any, root: any, window: any, now: any) {
317
+ function needsPrune(fsImpl , root , window , now ) {
318
318
  if (window.state !== 'on') return false;
319
319
  const cutoff = now.getTime() - window.ms;
320
- if (!namesIn(fsImpl, path.join(root, EVENTS_REL)).some((name: any) => isEventName(name) && idTime(name) < cutoff)) return false;
320
+ if (!namesIn(fsImpl, path.join(root, EVENTS_REL)).some((name ) => isEventName(name) && idTime(name) < cutoff)) return false;
321
321
  return selectExpired(readEvents(root, { fsImpl }).events, { now, windowMs: window.ms }).files.length > 0;
322
322
  }
323
323
 
@@ -330,7 +330,7 @@ function needsPrune(fsImpl: any, root: any, window: any, now: any) {
330
330
  * `lines` are for stderr, without the verb prefix.
331
331
  * @throws {StoreUnsafeError} a symlinked new store folder, or a symlinked old folder when a copy must read it
332
332
  */
333
- function prepareStore(root: string, { env = process.env, now = new Date(), fsImpl = nodeFs, registry }: any = {}) {
333
+ function prepareStore(root , { env = process.env, now = new Date(), fsImpl = nodeFs, registry } = {}) {
334
334
  refuseLinks(fsImpl, root, [LIFECYCLE_REL, EVENTS_REL]);
335
335
  const legacyDir = lstatOrNull(fsImpl, path.join(root, LEGACY_EVENTS_REL));
336
336
  const notice = legacyDir && legacyDir.isDirectory() ? [NOTICE] : [];
@@ -342,7 +342,7 @@ function prepareStore(root: string, { env = process.env, now = new Date(), fsImp
342
342
  if (storeHasEvents(fsImpl, root)) {
343
343
  markerDue = true;
344
344
  } else {
345
- try { migrate = legacyEventFiles(fsImpl, root).length > 0; } catch (error: any) { return legacyUnreadable(error.code || error.message); }
345
+ try { migrate = legacyEventFiles(fsImpl, root).length > 0; } catch (error ) { return legacyUnreadable(error.code || error.message); }
346
346
  }
347
347
  }
348
348
  const retentionDue = readJournal(root, fsImpl).pending.length > 0 || needsPrune(fsImpl, root, window, now);
@@ -354,7 +354,7 @@ function prepareStore(root: string, { env = process.env, now = new Date(), fsImp
354
354
  fsImpl.mkdirSync(lifecycleDir, { recursive: true });
355
355
  // An unwritable folder would only show as a lock that never comes; name it for what it is.
356
356
  fsImpl.accessSync(lifecycleDir, nodeFs.constants.W_OK);
357
- } catch (error: any) {
357
+ } catch (error ) {
358
358
  // Without a copy to make, an unwritable store only stops the retention pass, not the verb.
359
359
  if (!migrate) return { ok: true, lines: [...notice, ...invalid, ...(retentionDue ? [unwritableLine(error.code || error.message)] : [])] };
360
360
  return migrationFailed(error.code || error.message);
@@ -362,7 +362,7 @@ function prepareStore(root: string, { env = process.env, now = new Date(), fsImp
362
362
  let release;
363
363
  try {
364
364
  release = acquireLock(fsImpl, lockTarget(root));
365
- } catch (error: any) {
365
+ } catch (error ) {
366
366
  if (/^Could not lock/.test(error.message || '')) return { ok: false, finding: 'store-locked', message: `${error.message} Nothing was written.`, lines: [] };
367
367
  throw error;
368
368
  }
@@ -373,7 +373,7 @@ function prepareStore(root: string, { env = process.env, now = new Date(), fsImp
373
373
  marked = writeMarker(fsImpl, root, 0, now);
374
374
  } else if (!marked) {
375
375
  let files;
376
- try { files = legacyEventFiles(fsImpl, root); } catch (error: any) { return legacyUnreadable(error.code || error.message); }
376
+ try { files = legacyEventFiles(fsImpl, root); } catch (error ) { return legacyUnreadable(error.code || error.message); }
377
377
  if (files.length) {
378
378
  refuseLinks(fsImpl, root, [LEGACY_LIFECYCLE_REL, LEGACY_EVENTS_REL]);
379
379
  const copied = copyLegacyStore(fsImpl, root, files);