@evomap/evolver-core 2.0.0-beta.0

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 (373) hide show
  1. package/dist/algo/antiDistill.d.ts +35 -0
  2. package/dist/algo/antiDistill.js +167 -0
  3. package/dist/algo/bans.d.ts +6 -0
  4. package/dist/algo/bans.js +33 -0
  5. package/dist/algo/candidateAssembly.d.ts +65 -0
  6. package/dist/algo/candidateAssembly.js +196 -0
  7. package/dist/algo/capabilityCandidates.d.ts +38 -0
  8. package/dist/algo/capabilityCandidates.js +131 -0
  9. package/dist/algo/confidence.d.ts +106 -0
  10. package/dist/algo/confidence.js +196 -0
  11. package/dist/algo/cycleEngine.d.ts +143 -0
  12. package/dist/algo/cycleEngine.js +417 -0
  13. package/dist/algo/cycleFailureClassifier.d.ts +52 -0
  14. package/dist/algo/cycleFailureClassifier.js +104 -0
  15. package/dist/algo/epigenetics.d.ts +14 -0
  16. package/dist/algo/epigenetics.js +41 -0
  17. package/dist/algo/evolutionEvent.d.ts +23 -0
  18. package/dist/algo/evolutionEvent.js +24 -0
  19. package/dist/algo/exploration.d.ts +34 -0
  20. package/dist/algo/exploration.js +55 -0
  21. package/dist/algo/geneHealth.d.ts +24 -0
  22. package/dist/algo/geneHealth.js +16 -0
  23. package/dist/algo/geneIntake.d.ts +37 -0
  24. package/dist/algo/geneIntake.js +100 -0
  25. package/dist/algo/genePromotion.d.ts +48 -0
  26. package/dist/algo/genePromotion.js +53 -0
  27. package/dist/algo/geneSelection.d.ts +128 -0
  28. package/dist/algo/geneSelection.js +222 -0
  29. package/dist/algo/index.d.ts +18 -0
  30. package/dist/algo/index.js +18 -0
  31. package/dist/algo/mutation.d.ts +12 -0
  32. package/dist/algo/mutation.js +22 -0
  33. package/dist/algo/orchestrator.d.ts +65 -0
  34. package/dist/algo/orchestrator.js +63 -0
  35. package/dist/algo/solidify.d.ts +43 -0
  36. package/dist/algo/solidify.js +63 -0
  37. package/dist/algo/strategyPresets.d.ts +32 -0
  38. package/dist/algo/strategyPresets.js +61 -0
  39. package/dist/assetstore/index.d.ts +8 -0
  40. package/dist/assetstore/index.js +8 -0
  41. package/dist/assetstore/learningHistory.d.ts +25 -0
  42. package/dist/assetstore/learningHistory.js +38 -0
  43. package/dist/assetstore/localJsonl.d.ts +34 -0
  44. package/dist/assetstore/localJsonl.js +182 -0
  45. package/dist/assetstore/pendingSignals.d.ts +22 -0
  46. package/dist/assetstore/pendingSignals.js +171 -0
  47. package/dist/assetstore/provenance.d.ts +39 -0
  48. package/dist/assetstore/provenance.js +109 -0
  49. package/dist/assetstore/provider.d.ts +48 -0
  50. package/dist/assetstore/provider.js +36 -0
  51. package/dist/assetstore/remoteStub.d.ts +32 -0
  52. package/dist/assetstore/remoteStub.js +36 -0
  53. package/dist/assetstore/reviewFilter.d.ts +20 -0
  54. package/dist/assetstore/reviewFilter.js +44 -0
  55. package/dist/assetstore/reviewLedger.d.ts +55 -0
  56. package/dist/assetstore/reviewLedger.js +121 -0
  57. package/dist/benchmark/antiGeneBenchmark.d.ts +79 -0
  58. package/dist/benchmark/antiGeneBenchmark.js +241 -0
  59. package/dist/benchmark/antiGeneRollout.d.ts +80 -0
  60. package/dist/benchmark/antiGeneRollout.js +256 -0
  61. package/dist/benchmark/benchmark.d.ts +32 -0
  62. package/dist/benchmark/benchmark.js +26 -0
  63. package/dist/benchmark/evolutionThesisSolver.d.ts +25 -0
  64. package/dist/benchmark/evolutionThesisSolver.js +41 -0
  65. package/dist/benchmark/index.d.ts +5 -0
  66. package/dist/benchmark/index.js +5 -0
  67. package/dist/benchmark/thesis.d.ts +85 -0
  68. package/dist/benchmark/thesis.js +150 -0
  69. package/dist/bootstrap/envFingerprint.d.ts +45 -0
  70. package/dist/bootstrap/envFingerprint.js +72 -0
  71. package/dist/bootstrap/index.d.ts +2 -0
  72. package/dist/bootstrap/index.js +2 -0
  73. package/dist/bootstrap/selfEvolve.d.ts +36 -0
  74. package/dist/bootstrap/selfEvolve.js +26 -0
  75. package/dist/cycle/cycleTimeline.d.ts +35 -0
  76. package/dist/cycle/cycleTimeline.js +74 -0
  77. package/dist/cycle/index.d.ts +2 -0
  78. package/dist/cycle/index.js +2 -0
  79. package/dist/cycle/stateMachine.d.ts +6 -0
  80. package/dist/cycle/stateMachine.js +25 -0
  81. package/dist/daemon/cycleContext.d.ts +12 -0
  82. package/dist/daemon/cycleContext.js +13 -0
  83. package/dist/daemon/drain.d.ts +11 -0
  84. package/dist/daemon/drain.js +16 -0
  85. package/dist/daemon/guards.d.ts +87 -0
  86. package/dist/daemon/guards.js +142 -0
  87. package/dist/daemon/idempotency.d.ts +11 -0
  88. package/dist/daemon/idempotency.js +36 -0
  89. package/dist/daemon/idleScheduler.d.ts +55 -0
  90. package/dist/daemon/idleScheduler.js +181 -0
  91. package/dist/daemon/index.d.ts +8 -0
  92. package/dist/daemon/index.js +8 -0
  93. package/dist/daemon/stepRunner.d.ts +12 -0
  94. package/dist/daemon/stepRunner.js +31 -0
  95. package/dist/daemon/unhandledRejectionWindow.d.ts +21 -0
  96. package/dist/daemon/unhandledRejectionWindow.js +52 -0
  97. package/dist/daemon/watchdog.d.ts +11 -0
  98. package/dist/daemon/watchdog.js +14 -0
  99. package/dist/events/eventSchema.d.ts +132 -0
  100. package/dist/events/eventSchema.js +30 -0
  101. package/dist/events/eventStore.d.ts +32 -0
  102. package/dist/events/eventStore.js +137 -0
  103. package/dist/events/ingest.d.ts +34 -0
  104. package/dist/events/ingest.js +61 -0
  105. package/dist/events/paths.d.ts +22 -0
  106. package/dist/events/paths.js +44 -0
  107. package/dist/events/projectors.d.ts +9 -0
  108. package/dist/events/projectors.js +11 -0
  109. package/dist/events/public.d.ts +14 -0
  110. package/dist/events/public.js +8 -0
  111. package/dist/events/replayer.d.ts +26 -0
  112. package/dist/events/replayer.js +67 -0
  113. package/dist/events/reports.d.ts +90 -0
  114. package/dist/events/reports.js +244 -0
  115. package/dist/events/retention.d.ts +70 -0
  116. package/dist/events/retention.js +177 -0
  117. package/dist/events/sink.d.ts +5 -0
  118. package/dist/events/sink.js +1 -0
  119. package/dist/exec/autoExec.d.ts +137 -0
  120. package/dist/exec/autoExec.js +221 -0
  121. package/dist/exec/autonomousCycle.d.ts +48 -0
  122. package/dist/exec/autonomousCycle.js +78 -0
  123. package/dist/exec/claudeBridge.d.ts +112 -0
  124. package/dist/exec/claudeBridge.js +219 -0
  125. package/dist/exec/index.d.ts +9 -0
  126. package/dist/exec/index.js +11 -0
  127. package/dist/exec/openPrRegistry.d.ts +60 -0
  128. package/dist/exec/openPrRegistry.js +130 -0
  129. package/dist/exec/policy/blastRadius.d.ts +31 -0
  130. package/dist/exec/policy/blastRadius.js +67 -0
  131. package/dist/exec/policy/constraints.d.ts +26 -0
  132. package/dist/exec/policy/constraints.js +62 -0
  133. package/dist/exec/policy/destructive.d.ts +45 -0
  134. package/dist/exec/policy/destructive.js +108 -0
  135. package/dist/exec/policy/failureMode.d.ts +33 -0
  136. package/dist/exec/policy/failureMode.js +49 -0
  137. package/dist/exec/policy/index.d.ts +24 -0
  138. package/dist/exec/policy/index.js +30 -0
  139. package/dist/exec/policy/protectedPaths.d.ts +17 -0
  140. package/dist/exec/policy/protectedPaths.js +65 -0
  141. package/dist/exec/policyCheck.d.ts +2 -0
  142. package/dist/exec/policyCheck.js +7 -0
  143. package/dist/exec/prompt.d.ts +34 -0
  144. package/dist/exec/prompt.js +108 -0
  145. package/dist/exec/proofOfWork.d.ts +9 -0
  146. package/dist/exec/proofOfWork.js +11 -0
  147. package/dist/exec/runnerRegistry.d.ts +123 -0
  148. package/dist/exec/runnerRegistry.js +237 -0
  149. package/dist/exec/selfPr.d.ts +83 -0
  150. package/dist/exec/selfPr.js +104 -0
  151. package/dist/exec/selfPrObfuscation.d.ts +21 -0
  152. package/dist/exec/selfPrObfuscation.js +85 -0
  153. package/dist/hooks/hooks.d.ts +117 -0
  154. package/dist/hooks/hooks.js +89 -0
  155. package/dist/hooks/index.d.ts +1 -0
  156. package/dist/hooks/index.js +1 -0
  157. package/dist/hub/assetCallLog.d.ts +43 -0
  158. package/dist/hub/assetCallLog.js +72 -0
  159. package/dist/hub/bindings.d.ts +28 -0
  160. package/dist/hub/bindings.js +90 -0
  161. package/dist/hub/capability.d.ts +278 -0
  162. package/dist/hub/capability.js +1 -0
  163. package/dist/hub/conversationDistiller.d.ts +88 -0
  164. package/dist/hub/conversationDistiller.js +264 -0
  165. package/dist/hub/fake.d.ts +45 -0
  166. package/dist/hub/fake.js +69 -0
  167. package/dist/hub/hubReview.d.ts +91 -0
  168. package/dist/hub/hubReview.js +106 -0
  169. package/dist/hub/index.d.ts +10 -0
  170. package/dist/hub/index.js +10 -0
  171. package/dist/hub/ingest.d.ts +15 -0
  172. package/dist/hub/ingest.js +15 -0
  173. package/dist/hub/questionGenerator.d.ts +59 -0
  174. package/dist/hub/questionGenerator.js +406 -0
  175. package/dist/hub/reuseDecision.d.ts +87 -0
  176. package/dist/hub/reuseDecision.js +127 -0
  177. package/dist/hub/sanitize.d.ts +52 -0
  178. package/dist/hub/sanitize.js +321 -0
  179. package/dist/index.d.ts +27 -0
  180. package/dist/index.js +27 -0
  181. package/dist/mailbox/catalog.d.ts +17 -0
  182. package/dist/mailbox/catalog.js +53 -0
  183. package/dist/mailbox/daemon.d.ts +48 -0
  184. package/dist/mailbox/daemon.js +61 -0
  185. package/dist/mailbox/dispatch.d.ts +46 -0
  186. package/dist/mailbox/dispatch.js +62 -0
  187. package/dist/mailbox/envelope.d.ts +43 -0
  188. package/dist/mailbox/envelope.js +52 -0
  189. package/dist/mailbox/index.d.ts +8 -0
  190. package/dist/mailbox/index.js +8 -0
  191. package/dist/mailbox/ipcServer.d.ts +46 -0
  192. package/dist/mailbox/ipcServer.js +168 -0
  193. package/dist/mailbox/requestReply.d.ts +40 -0
  194. package/dist/mailbox/requestReply.js +77 -0
  195. package/dist/mailbox/store.d.ts +74 -0
  196. package/dist/mailbox/store.js +308 -0
  197. package/dist/mailbox/wake.d.ts +45 -0
  198. package/dist/mailbox/wake.js +60 -0
  199. package/dist/material/boundary.d.ts +7 -0
  200. package/dist/material/boundary.js +14 -0
  201. package/dist/material/consumer.d.ts +21 -0
  202. package/dist/material/consumer.js +52 -0
  203. package/dist/material/emit.d.ts +55 -0
  204. package/dist/material/emit.js +52 -0
  205. package/dist/material/factory.d.ts +27 -0
  206. package/dist/material/factory.js +25 -0
  207. package/dist/material/index.d.ts +8 -0
  208. package/dist/material/index.js +8 -0
  209. package/dist/material/materialStore.d.ts +24 -0
  210. package/dist/material/materialStore.js +76 -0
  211. package/dist/material/sampling.d.ts +21 -0
  212. package/dist/material/sampling.js +39 -0
  213. package/dist/material/sources.d.ts +25 -0
  214. package/dist/material/sources.js +33 -0
  215. package/dist/material/watermark.d.ts +21 -0
  216. package/dist/material/watermark.js +76 -0
  217. package/dist/observers/cursorRewriteObserver.d.ts +46 -0
  218. package/dist/observers/cursorRewriteObserver.js +103 -0
  219. package/dist/observers/distillObserver.d.ts +31 -0
  220. package/dist/observers/distillObserver.js +93 -0
  221. package/dist/observers/index.d.ts +5 -0
  222. package/dist/observers/index.js +5 -0
  223. package/dist/observers/observerBus.d.ts +44 -0
  224. package/dist/observers/observerBus.js +73 -0
  225. package/dist/observers/reflectionObserver.d.ts +31 -0
  226. package/dist/observers/reflectionObserver.js +124 -0
  227. package/dist/observers/valueDigestObserver.d.ts +50 -0
  228. package/dist/observers/valueDigestObserver.js +70 -0
  229. package/dist/ops/cleanup.d.ts +23 -0
  230. package/dist/ops/cleanup.js +68 -0
  231. package/dist/ops/health.d.ts +37 -0
  232. package/dist/ops/health.js +96 -0
  233. package/dist/ops/index.d.ts +7 -0
  234. package/dist/ops/index.js +7 -0
  235. package/dist/ops/recall.d.ts +65 -0
  236. package/dist/ops/recall.js +152 -0
  237. package/dist/ops/reuseOutcomes.d.ts +68 -0
  238. package/dist/ops/reuseOutcomes.js +126 -0
  239. package/dist/ops/savingsCore.d.ts +47 -0
  240. package/dist/ops/savingsCore.js +112 -0
  241. package/dist/ops/selfUpdate.d.ts +106 -0
  242. package/dist/ops/selfUpdate.js +294 -0
  243. package/dist/ops/valueLedger.d.ts +205 -0
  244. package/dist/ops/valueLedger.js +238 -0
  245. package/dist/ops/valueOutreach.d.ts +70 -0
  246. package/dist/ops/valueOutreach.js +244 -0
  247. package/dist/personality/drift.d.ts +45 -0
  248. package/dist/personality/drift.js +106 -0
  249. package/dist/personality/events.d.ts +25 -0
  250. package/dist/personality/events.js +37 -0
  251. package/dist/personality/evolveOps.d.ts +20 -0
  252. package/dist/personality/evolveOps.js +93 -0
  253. package/dist/personality/index.d.ts +11 -0
  254. package/dist/personality/index.js +11 -0
  255. package/dist/personality/mutate.d.ts +21 -0
  256. package/dist/personality/mutate.js +39 -0
  257. package/dist/personality/pivot.d.ts +23 -0
  258. package/dist/personality/pivot.js +22 -0
  259. package/dist/personality/prompt.d.ts +6 -0
  260. package/dist/personality/prompt.js +62 -0
  261. package/dist/personality/riskGate.d.ts +42 -0
  262. package/dist/personality/riskGate.js +80 -0
  263. package/dist/personality/schema.d.ts +255 -0
  264. package/dist/personality/schema.js +119 -0
  265. package/dist/personality/select.d.ts +46 -0
  266. package/dist/personality/select.js +71 -0
  267. package/dist/personality/stats.d.ts +46 -0
  268. package/dist/personality/stats.js +82 -0
  269. package/dist/personality/store.d.ts +35 -0
  270. package/dist/personality/store.js +92 -0
  271. package/dist/schema/common.d.ts +28 -0
  272. package/dist/schema/common.js +17 -0
  273. package/dist/schema/index.d.ts +5 -0
  274. package/dist/schema/index.js +5 -0
  275. package/dist/schema/material.d.ts +201 -0
  276. package/dist/schema/material.js +50 -0
  277. package/dist/schema/problem.d.ts +160 -0
  278. package/dist/schema/problem.js +45 -0
  279. package/dist/schema/proofOfWork.d.ts +97 -0
  280. package/dist/schema/proofOfWork.js +9 -0
  281. package/dist/schema/signal.d.ts +41 -0
  282. package/dist/schema/signal.js +19 -0
  283. package/dist/shadow/index.d.ts +6 -0
  284. package/dist/shadow/index.js +6 -0
  285. package/dist/shadow/jsonlSink.d.ts +17 -0
  286. package/dist/shadow/jsonlSink.js +27 -0
  287. package/dist/shadow/redact.d.ts +11 -0
  288. package/dist/shadow/redact.js +18 -0
  289. package/dist/shadow/shadowHub.d.ts +12 -0
  290. package/dist/shadow/shadowHub.js +42 -0
  291. package/dist/shadow/shadowMailbox.d.ts +17 -0
  292. package/dist/shadow/shadowMailbox.js +25 -0
  293. package/dist/shadow/shadowStore.d.ts +18 -0
  294. package/dist/shadow/shadowStore.js +55 -0
  295. package/dist/shadow/sink.d.ts +37 -0
  296. package/dist/shadow/sink.js +18 -0
  297. package/dist/signals/cycleHistoryFromEvents.d.ts +11 -0
  298. package/dist/signals/cycleHistoryFromEvents.js +96 -0
  299. package/dist/signals/expand.d.ts +34 -0
  300. package/dist/signals/expand.js +125 -0
  301. package/dist/signals/extractor.d.ts +25 -0
  302. package/dist/signals/extractor.js +57 -0
  303. package/dist/signals/index.d.ts +6 -0
  304. package/dist/signals/index.js +6 -0
  305. package/dist/signals/metaSignals.d.ts +57 -0
  306. package/dist/signals/metaSignals.js +158 -0
  307. package/dist/signals/signalGate.d.ts +15 -0
  308. package/dist/signals/signalGate.js +40 -0
  309. package/dist/signals/traceSignals.d.ts +44 -0
  310. package/dist/signals/traceSignals.js +123 -0
  311. package/dist/signatures/classifier.d.ts +16 -0
  312. package/dist/signatures/classifier.js +29 -0
  313. package/dist/signatures/index.d.ts +2 -0
  314. package/dist/signatures/index.js +2 -0
  315. package/dist/signatures/signatures.d.ts +22 -0
  316. package/dist/signatures/signatures.js +42 -0
  317. package/dist/strategy/experiment.d.ts +48 -0
  318. package/dist/strategy/experiment.js +63 -0
  319. package/dist/strategy/index.d.ts +2 -0
  320. package/dist/strategy/index.js +2 -0
  321. package/dist/strategy/strategyPoint.d.ts +30 -0
  322. package/dist/strategy/strategyPoint.js +23 -0
  323. package/dist/trace/index.d.ts +2 -0
  324. package/dist/trace/index.js +2 -0
  325. package/dist/trace/trajectory.d.ts +82 -0
  326. package/dist/trace/trajectory.js +117 -0
  327. package/dist/trace/trajectoryExport.d.ts +237 -0
  328. package/dist/trace/trajectoryExport.js +1818 -0
  329. package/dist/trigger/budget.d.ts +16 -0
  330. package/dist/trigger/budget.js +20 -0
  331. package/dist/trigger/engine.d.ts +12 -0
  332. package/dist/trigger/engine.js +23 -0
  333. package/dist/trigger/index.d.ts +6 -0
  334. package/dist/trigger/index.js +6 -0
  335. package/dist/trigger/problemBuilder.d.ts +24 -0
  336. package/dist/trigger/problemBuilder.js +32 -0
  337. package/dist/trigger/trigger.d.ts +22 -0
  338. package/dist/trigger/trigger.js +27 -0
  339. package/dist/trigger/valueModel.d.ts +26 -0
  340. package/dist/trigger/valueModel.js +25 -0
  341. package/dist/trigger/wfq.d.ts +13 -0
  342. package/dist/trigger/wfq.js +25 -0
  343. package/dist/util/fileLock.d.ts +24 -0
  344. package/dist/util/fileLock.js +227 -0
  345. package/dist/util/index.d.ts +2 -0
  346. package/dist/util/index.js +2 -0
  347. package/dist/util/version.d.ts +12 -0
  348. package/dist/util/version.js +51 -0
  349. package/dist/verify/index.d.ts +4 -0
  350. package/dist/verify/index.js +4 -0
  351. package/dist/verify/rollback.d.ts +22 -0
  352. package/dist/verify/rollback.js +33 -0
  353. package/dist/verify/sandboxRunner.d.ts +39 -0
  354. package/dist/verify/sandboxRunner.js +116 -0
  355. package/dist/verify/sandboxedValidation.d.ts +35 -0
  356. package/dist/verify/sandboxedValidation.js +56 -0
  357. package/dist/verify/validation.d.ts +41 -0
  358. package/dist/verify/validation.js +85 -0
  359. package/dist/wire/canonicalize.golden.d.ts +23 -0
  360. package/dist/wire/canonicalize.golden.js +46 -0
  361. package/dist/wire/geneHints.d.ts +64 -0
  362. package/dist/wire/geneHints.js +100 -0
  363. package/dist/wire/index.d.ts +91 -0
  364. package/dist/wire/index.js +3 -0
  365. package/dist/wire/schemaGate.d.ts +11 -0
  366. package/dist/wire/schemaGate.js +49 -0
  367. package/dist/workflow/dsl.d.ts +54 -0
  368. package/dist/workflow/dsl.js +15 -0
  369. package/dist/workflow/engine.d.ts +30 -0
  370. package/dist/workflow/engine.js +94 -0
  371. package/dist/workflow/index.d.ts +2 -0
  372. package/dist/workflow/index.js +2 -0
  373. package/package.json +29 -0
@@ -0,0 +1,16 @@
1
+ /** 进化预算 (军杰§5.4): 日 cycle/token 上限 + per-pattern 上限. */
2
+ export interface BudgetConfig {
3
+ maxCyclesPerDay: number;
4
+ maxTokensPerDay: number;
5
+ perPatternCap: number;
6
+ }
7
+ export declare class Budget {
8
+ private readonly cfg;
9
+ private cycles;
10
+ private tokens;
11
+ private readonly perPattern;
12
+ constructor(cfg: BudgetConfig);
13
+ available(patternId: string): boolean;
14
+ consume(patternId: string, tokens?: number): void;
15
+ reset(): void;
16
+ }
@@ -0,0 +1,20 @@
1
+ export class Budget {
2
+ cfg;
3
+ cycles = 0;
4
+ tokens = 0;
5
+ perPattern = new Map();
6
+ constructor(cfg) {
7
+ this.cfg = cfg;
8
+ }
9
+ available(patternId) {
10
+ return this.cycles < this.cfg.maxCyclesPerDay
11
+ && this.tokens < this.cfg.maxTokensPerDay
12
+ && (this.perPattern.get(patternId) ?? 0) < this.cfg.perPatternCap;
13
+ }
14
+ consume(patternId, tokens = 0) {
15
+ this.cycles += 1;
16
+ this.tokens += tokens;
17
+ this.perPattern.set(patternId, (this.perPattern.get(patternId) ?? 0) + 1);
18
+ }
19
+ reset() { this.cycles = 0; this.tokens = 0; this.perPattern.clear(); }
20
+ }
@@ -0,0 +1,12 @@
1
+ import type { Ingestor } from '../events/ingest.js';
2
+ import type { ProblemPattern } from '../schema/problem.js';
3
+ import { type TriggerConfig, type TriggerDecision } from './trigger.js';
4
+ import type { Budget } from './budget.js';
5
+ /** 触发引擎: 评估 → 经 ingest 落 decision.* 事件(human.why 必填) → 消费 budget. */
6
+ export declare class TriggerEngine {
7
+ private readonly ingestor;
8
+ private readonly cfg;
9
+ private readonly budget;
10
+ constructor(ingestor: Ingestor, cfg: TriggerConfig, budget: Budget);
11
+ evaluate(p: ProblemPattern, now: number): Promise<TriggerDecision>;
12
+ }
@@ -0,0 +1,23 @@
1
+ import { evaluateTrigger } from './trigger.js';
2
+ /** 触发引擎: 评估 → 经 ingest 落 decision.* 事件(human.why 必填) → 消费 budget. */
3
+ export class TriggerEngine {
4
+ ingestor;
5
+ cfg;
6
+ budget;
7
+ constructor(ingestor, cfg, budget) {
8
+ this.ingestor = ingestor;
9
+ this.cfg = cfg;
10
+ this.budget = budget;
11
+ }
12
+ async evaluate(p, now) {
13
+ const d = evaluateTrigger(p, this.cfg, this.budget, now);
14
+ await this.ingestor.ingest({
15
+ type: d.trigger ? 'decision.triggered' : 'decision.suppressed',
16
+ human: { title: `${d.trigger ? '触发' : '抑制'} ${p.id}`, why: d.reasons.join('; ') },
17
+ payload: { patternId: p.id, value: d.value.score, factors: d.value.factors, threshold: d.thresholdUsed, reasons: d.reasons },
18
+ });
19
+ if (d.trigger)
20
+ this.budget.consume(p.id);
21
+ return d;
22
+ }
23
+ }
@@ -0,0 +1,6 @@
1
+ export * from './valueModel.js';
2
+ export * from './budget.js';
3
+ export * from './trigger.js';
4
+ export * from './wfq.js';
5
+ export * from './engine.js';
6
+ export * from './problemBuilder.js';
@@ -0,0 +1,6 @@
1
+ export * from './valueModel.js';
2
+ export * from './budget.js';
3
+ export * from './trigger.js';
4
+ export * from './wfq.js';
5
+ export * from './engine.js';
6
+ export * from './problemBuilder.js';
@@ -0,0 +1,24 @@
1
+ import type { ProblemPattern } from '../schema/problem.js';
2
+ export interface ProblemPatternInput {
3
+ problemKind: string;
4
+ failureMode?: string;
5
+ domainTags?: readonly string[];
6
+ affectedSurface?: string;
7
+ occurrences: number;
8
+ firstSeenAt: string;
9
+ lastSeenAt: string;
10
+ linkedSignals?: readonly string[];
11
+ /** 0..1 severity hint (caller maps its failure-mode taxonomy → a number). Default 0.5. */
12
+ severity?: number;
13
+ /** Override the classified heuristic; default: true unless kind is 'general' or failureMode is 'unknown'. */
14
+ classified?: boolean;
15
+ /** Override the derived id/signature. */
16
+ id?: string;
17
+ signature?: string;
18
+ }
19
+ /**
20
+ * Assemble a triggerable ProblemPattern. The value factors come from {@link deriveValueFactors} so a vague
21
+ * high-volume catch-all cannot out-trigger a specific, actionable problem by sheer volume (observation tuning,
22
+ * #53). `classified` is auto-detected from the kind/failureMode being specific.
23
+ */
24
+ export declare function buildProblemPattern(input: ProblemPatternInput): ProblemPattern;
@@ -0,0 +1,32 @@
1
+ import { problemSignature, SIGNATURE_V } from '../signatures/signatures.js';
2
+ import { deriveValueFactors } from './valueModel.js';
3
+ /**
4
+ * Assemble a triggerable ProblemPattern. The value factors come from {@link deriveValueFactors} so a vague
5
+ * high-volume catch-all cannot out-trigger a specific, actionable problem by sheer volume (observation tuning,
6
+ * #53). `classified` is auto-detected from the kind/failureMode being specific.
7
+ */
8
+ export function buildProblemPattern(input) {
9
+ const sigInput = {
10
+ problemKind: input.problemKind,
11
+ ...(input.domainTags ? { domainTags: input.domainTags } : {}),
12
+ ...(input.affectedSurface ? { affectedSurface: input.affectedSurface } : {}),
13
+ ...(input.failureMode ? { failureMode: input.failureMode } : {}),
14
+ };
15
+ const signature = input.signature ?? problemSignature(sigInput);
16
+ const classified = input.classified ?? (input.problemKind !== 'general' && (input.failureMode ?? 'unknown') !== 'unknown');
17
+ return {
18
+ id: input.id ?? signature,
19
+ signature,
20
+ signatureV: SIGNATURE_V,
21
+ firstSeenAt: input.firstSeenAt,
22
+ lastSeenAt: input.lastSeenAt,
23
+ occurrences: input.occurrences,
24
+ linkedSignals: [...(input.linkedSignals ?? [])],
25
+ resolvedBy: null,
26
+ status: 'open',
27
+ value: deriveValueFactors({ occurrences: input.occurrences, classified, ...(input.severity !== undefined ? { severity: input.severity } : {}) }),
28
+ consecutiveFailures: 0,
29
+ cooldownUntil: null,
30
+ extensions: {},
31
+ };
32
+ }
@@ -0,0 +1,22 @@
1
+ import type { ProblemPattern } from '../schema/problem.js';
2
+ import { type ValueResult } from './valueModel.js';
3
+ import type { Budget } from './budget.js';
4
+ export interface PersistenceConfig {
5
+ minOccurrences: number;
6
+ minOpenDurationMs: number;
7
+ }
8
+ export interface TriggerConfig {
9
+ persistence: PersistenceConfig;
10
+ valueThreshold: number;
11
+ dynamicThreshold?: () => number;
12
+ }
13
+ export interface TriggerDecision {
14
+ trigger: boolean;
15
+ patternId: string;
16
+ value: ValueResult;
17
+ thresholdUsed: number;
18
+ reasons: string[];
19
+ }
20
+ export declare function persistenceOk(p: ProblemPattern, cfg: PersistenceConfig, now: number): boolean;
21
+ /** 触发判定 = persistence ∧ value ∧ budget (军杰§5.5). */
22
+ export declare function evaluateTrigger(p: ProblemPattern, cfg: TriggerConfig, budget: Budget, now: number): TriggerDecision;
@@ -0,0 +1,27 @@
1
+ import { computeValue } from './valueModel.js';
2
+ export function persistenceOk(p, cfg, now) {
3
+ const openDuration = now - Date.parse(p.firstSeenAt);
4
+ return p.status === 'open'
5
+ && p.occurrences >= cfg.minOccurrences
6
+ && openDuration >= cfg.minOpenDurationMs
7
+ && (p.cooldownUntil === null || Date.parse(p.cooldownUntil) < now);
8
+ }
9
+ /** 触发判定 = persistence ∧ value ∧ budget (军杰§5.5). */
10
+ export function evaluateTrigger(p, cfg, budget, now) {
11
+ const value = computeValue(p.value);
12
+ const threshold = cfg.dynamicThreshold ? cfg.dynamicThreshold() : cfg.valueThreshold;
13
+ const reasons = [];
14
+ const persist = persistenceOk(p, cfg.persistence, now);
15
+ if (!persist)
16
+ reasons.push(`persistence 未达(occ=${p.occurrences}/${cfg.persistence.minOccurrences}, status=${p.status})`);
17
+ const valueOk = value.score >= threshold;
18
+ if (!valueOk)
19
+ reasons.push(`value ${value.score.toFixed(3)} < 阈值 ${threshold}`);
20
+ const budgetOk = budget.available(p.id);
21
+ if (!budgetOk)
22
+ reasons.push('budget 耗尽');
23
+ const trigger = persist && valueOk && budgetOk;
24
+ if (trigger)
25
+ reasons.push(`触发: value=${value.score.toFixed(3)}≥${threshold}, persistence ok, budget ok`);
26
+ return { trigger, patternId: p.id, value, thresholdUsed: threshold, reasons };
27
+ }
@@ -0,0 +1,26 @@
1
+ import type { ValueFactors } from '../schema/problem.js';
2
+ export interface ValueResult {
3
+ score: number;
4
+ factors: ValueFactors;
5
+ }
6
+ /** value = severity × reach × strategicFit × (1+novelty)/(1+costEst). 命名因子, 禁黑盒 (军杰§5.3). */
7
+ export declare function computeValue(f: ValueFactors): ValueResult;
8
+ /** Observation stats for one problem pattern, used to derive its value factors. */
9
+ export interface ProblemValueStats {
10
+ occurrences: number;
11
+ /** false for vague catch-all buckets (e.g. 'general'/'unknown') — they should NOT out-rank specific problems by sheer volume. */
12
+ classified?: boolean;
13
+ /** 0..1 hint from the failure-mode severity (caller maps its taxonomy → a number); default 0.5. */
14
+ severity?: number;
15
+ novelty?: number;
16
+ costEst?: number;
17
+ }
18
+ /** occurrences that earn full reach — a FIXED scale, deliberately NOT normalized to the biggest bucket. */
19
+ export declare const REACH_FULL_AT = 30;
20
+ /**
21
+ * Derive value factors from a problem's observation stats — the tuning learned from observing real agent logs
22
+ * (evolver-v2-observation): a vague high-volume catch-all should not out-trigger specific, actionable problems.
23
+ * So `reach` is on a FIXED occurrence scale (not normalized to the largest bucket, which crushes everything
24
+ * specific), and `strategicFit` is reduced for unclassified problems. Feed the result to {@link computeValue}.
25
+ */
26
+ export declare function deriveValueFactors(stats: ProblemValueStats): ValueFactors;
@@ -0,0 +1,25 @@
1
+ /** value = severity × reach × strategicFit × (1+novelty)/(1+costEst). 命名因子, 禁黑盒 (军杰§5.3). */
2
+ export function computeValue(f) {
3
+ const score = (f.severity * f.reach * f.strategicFit * (1 + f.novelty)) / (1 + f.costEst);
4
+ return { score, factors: { ...f } };
5
+ }
6
+ /** occurrences that earn full reach — a FIXED scale, deliberately NOT normalized to the biggest bucket. */
7
+ export const REACH_FULL_AT = 30;
8
+ const UNCLASSIFIED_FIT = 0.35;
9
+ const CLASSIFIED_FIT = 0.9;
10
+ const clamp01 = (n) => Math.max(0, Math.min(1, n));
11
+ /**
12
+ * Derive value factors from a problem's observation stats — the tuning learned from observing real agent logs
13
+ * (evolver-v2-observation): a vague high-volume catch-all should not out-trigger specific, actionable problems.
14
+ * So `reach` is on a FIXED occurrence scale (not normalized to the largest bucket, which crushes everything
15
+ * specific), and `strategicFit` is reduced for unclassified problems. Feed the result to {@link computeValue}.
16
+ */
17
+ export function deriveValueFactors(stats) {
18
+ return {
19
+ severity: clamp01(stats.severity ?? 0.5),
20
+ reach: clamp01(Math.max(0, stats.occurrences) / REACH_FULL_AT),
21
+ strategicFit: stats.classified === false ? UNCLASSIFIED_FIT : CLASSIFIED_FIT,
22
+ novelty: stats.novelty ?? 0,
23
+ costEst: stats.costEst ?? 0.2,
24
+ };
25
+ }
@@ -0,0 +1,13 @@
1
+ export interface WfqItem {
2
+ id: string;
3
+ weight: number;
4
+ enqueuedAt: number;
5
+ }
6
+ /** 加权公平队列骨架 (军杰§7): 防单一高频霸占, age_boost 防饿死. */
7
+ export declare class WeightedFairQueue {
8
+ private items;
9
+ enqueue(item: WfqItem): void;
10
+ size(): number;
11
+ /** pick = argmax(weight + age_boost); age_boost = min(log2(1+waitMin), 4). */
12
+ pick(now: number): WfqItem | undefined;
13
+ }
@@ -0,0 +1,25 @@
1
+ /** 加权公平队列骨架 (军杰§7): 防单一高频霸占, age_boost 防饿死. */
2
+ export class WeightedFairQueue {
3
+ items = [];
4
+ enqueue(item) { if (!this.items.some((i) => i.id === item.id))
5
+ this.items.push(item); }
6
+ size() { return this.items.length; }
7
+ /** pick = argmax(weight + age_boost); age_boost = min(log2(1+waitMin), 4). */
8
+ pick(now) {
9
+ let best;
10
+ let bestScore = -Infinity;
11
+ for (const it of this.items) {
12
+ const waitMin = (now - it.enqueuedAt) / 60000;
13
+ const score = it.weight + Math.min(Math.log2(1 + Math.max(0, waitMin)), 4);
14
+ if (score > bestScore) {
15
+ bestScore = score;
16
+ best = it;
17
+ }
18
+ }
19
+ if (best) {
20
+ const id = best.id;
21
+ this.items = this.items.filter((i) => i.id !== id);
22
+ }
23
+ return best;
24
+ }
25
+ }
@@ -0,0 +1,24 @@
1
+ export declare function syncSleep(ms: number): void;
2
+ export declare class LockTimeoutError extends Error {
3
+ readonly code = "LOCK_TIMEOUT";
4
+ constructor(lockPath: string);
5
+ }
6
+ export interface AcquireLockOptions {
7
+ maxTries?: number;
8
+ waitMs?: number;
9
+ }
10
+ /**
11
+ * Cross-process O_EXCL file lock with crashed-owner recovery.
12
+ *
13
+ * The lock file records the owner pid and token. If a waiter finds the lock held by a pid that is no longer
14
+ * alive (the owner crashed without releaseLock), it reclaims the stale lock instead of spinning
15
+ * until timeout — otherwise one crashed process would deadlock every future writer until the file
16
+ * is removed by hand. Acquisition stays atomic (O_EXCL), and stale reclaim moves the old lock aside
17
+ * under a mutation guard before deletion so waiters cannot delete each other's newly-created locks.
18
+ * A live owner's lock (including this process's own) is never stolen.
19
+ *
20
+ * NOTE: still synchronous (blocks the event loop while waiting) by design — it guards short
21
+ * synchronous critical sections (append-only writes).
22
+ */
23
+ export declare function acquireLock(lockPath: string, opts?: AcquireLockOptions): void;
24
+ export declare function releaseLock(lockPath: string): void;
@@ -0,0 +1,227 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
3
+ import { basename, dirname, join, resolve } from 'node:path';
4
+ export function syncSleep(ms) {
5
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
6
+ }
7
+ const ownedLocks = new Map();
8
+ export class LockTimeoutError extends Error {
9
+ code = 'LOCK_TIMEOUT';
10
+ constructor(lockPath) {
11
+ super(`获取文件锁超时: ${lockPath}`);
12
+ this.name = 'LockTimeoutError';
13
+ }
14
+ }
15
+ function lockKey(lockPath) {
16
+ return resolve(lockPath);
17
+ }
18
+ function newOwner() {
19
+ return { pid: process.pid, token: randomUUID() };
20
+ }
21
+ function serializeOwner(owner) {
22
+ return `${JSON.stringify({ v: 1, pid: owner.pid, token: owner.token })}\n`;
23
+ }
24
+ function isErrno(error, code) {
25
+ return typeof error === 'object' && error !== null && error.code === code;
26
+ }
27
+ /** True if pid is a live process (cross-platform via signal 0; EPERM = exists but owned by another user). */
28
+ function pidAlive(pid) {
29
+ if (!Number.isInteger(pid) || pid <= 0)
30
+ return false;
31
+ try {
32
+ process.kill(pid, 0);
33
+ return true;
34
+ }
35
+ catch (e) {
36
+ return e.code === 'EPERM';
37
+ }
38
+ }
39
+ function parseJsonOwner(raw) {
40
+ try {
41
+ const value = JSON.parse(raw);
42
+ if (typeof value !== 'object' || value === null)
43
+ return null;
44
+ const record = value;
45
+ if (typeof record.pid !== 'number'
46
+ || !Number.isInteger(record.pid)
47
+ || record.pid <= 0
48
+ || typeof record.token !== 'string'
49
+ || record.token.length === 0) {
50
+ return null;
51
+ }
52
+ return { pid: record.pid, token: record.token };
53
+ }
54
+ catch (error) {
55
+ if (error instanceof SyntaxError)
56
+ return null;
57
+ throw error;
58
+ }
59
+ }
60
+ function parseLegacyOwner(raw) {
61
+ const first = raw.trim().split(/\s+/, 1)[0];
62
+ if (first === undefined)
63
+ return null;
64
+ const pid = Number(first);
65
+ return Number.isInteger(pid) && pid > 0 ? { pid, token: null } : null;
66
+ }
67
+ function parseOwner(raw) {
68
+ const trimmed = raw.trim();
69
+ if (trimmed.length === 0)
70
+ return null;
71
+ return parseJsonOwner(trimmed) ?? parseLegacyOwner(trimmed);
72
+ }
73
+ /** Owner recorded in the lock file; null if missing/unparseable. */
74
+ function lockOwner(lockPath) {
75
+ try {
76
+ return parseOwner(readFileSync(lockPath, 'utf8'));
77
+ }
78
+ catch (error) {
79
+ if (isErrno(error, 'ENOENT'))
80
+ return null;
81
+ throw error;
82
+ }
83
+ }
84
+ function sameOwner(parsed, owner) {
85
+ return parsed?.pid === owner.pid && parsed.token === owner.token;
86
+ }
87
+ function sidecarPath(lockPath, kind) {
88
+ return join(dirname(lockPath), `.${basename(lockPath)}.${kind}.${process.pid}.${randomUUID()}`);
89
+ }
90
+ function mutationGuardPath(lockPath) {
91
+ return join(dirname(lockPath), `.${basename(lockPath)}.mutation`);
92
+ }
93
+ function removeFileIfExists(path) {
94
+ try {
95
+ unlinkSync(path);
96
+ }
97
+ catch (error) {
98
+ if (!isErrno(error, 'ENOENT'))
99
+ throw error;
100
+ }
101
+ }
102
+ function createLockFile(lockPath, owner, trackOwnership) {
103
+ try {
104
+ writeFileSync(lockPath, serializeOwner(owner), { flag: 'wx', mode: 0o600 });
105
+ if (trackOwnership)
106
+ ownedLocks.set(lockKey(lockPath), owner);
107
+ return true;
108
+ }
109
+ catch (error) {
110
+ if (isErrno(error, 'EEXIST'))
111
+ return false;
112
+ throw error;
113
+ }
114
+ }
115
+ function tryAcquireMutationGuard(lockPath) {
116
+ const guardPath = mutationGuardPath(lockPath);
117
+ const guard = newOwner();
118
+ if (createLockFile(guardPath, guard, false))
119
+ return guard;
120
+ const owner = lockOwner(guardPath);
121
+ if (owner === null || owner.pid === process.pid || pidAlive(owner.pid))
122
+ return null;
123
+ const stalePath = sidecarPath(guardPath, 'stale');
124
+ try {
125
+ renameSync(guardPath, stalePath);
126
+ }
127
+ catch (error) {
128
+ if (isErrno(error, 'ENOENT'))
129
+ return null;
130
+ throw error;
131
+ }
132
+ removeFileIfExists(stalePath);
133
+ return createLockFile(guardPath, guard, false) ? guard : null;
134
+ }
135
+ function releaseMutationGuard(lockPath, guard) {
136
+ const guardPath = mutationGuardPath(lockPath);
137
+ if (!sameOwner(lockOwner(guardPath), guard))
138
+ return;
139
+ const releasedPath = sidecarPath(guardPath, 'released');
140
+ try {
141
+ renameSync(guardPath, releasedPath);
142
+ }
143
+ catch (error) {
144
+ if (isErrno(error, 'ENOENT'))
145
+ return;
146
+ throw error;
147
+ }
148
+ removeFileIfExists(releasedPath);
149
+ }
150
+ function reclaimStaleLock(lockPath) {
151
+ const guard = tryAcquireMutationGuard(lockPath);
152
+ if (guard === null)
153
+ return false;
154
+ try {
155
+ const owner = lockOwner(lockPath);
156
+ if (owner === null || owner.pid === process.pid || pidAlive(owner.pid))
157
+ return false;
158
+ const stalePath = sidecarPath(lockPath, 'stale');
159
+ try {
160
+ renameSync(lockPath, stalePath);
161
+ }
162
+ catch (error) {
163
+ if (isErrno(error, 'ENOENT'))
164
+ return false;
165
+ throw error;
166
+ }
167
+ removeFileIfExists(stalePath);
168
+ return true;
169
+ }
170
+ finally {
171
+ releaseMutationGuard(lockPath, guard);
172
+ }
173
+ }
174
+ /**
175
+ * Cross-process O_EXCL file lock with crashed-owner recovery.
176
+ *
177
+ * The lock file records the owner pid and token. If a waiter finds the lock held by a pid that is no longer
178
+ * alive (the owner crashed without releaseLock), it reclaims the stale lock instead of spinning
179
+ * until timeout — otherwise one crashed process would deadlock every future writer until the file
180
+ * is removed by hand. Acquisition stays atomic (O_EXCL), and stale reclaim moves the old lock aside
181
+ * under a mutation guard before deletion so waiters cannot delete each other's newly-created locks.
182
+ * A live owner's lock (including this process's own) is never stolen.
183
+ *
184
+ * NOTE: still synchronous (blocks the event loop while waiting) by design — it guards short
185
+ * synchronous critical sections (append-only writes).
186
+ */
187
+ export function acquireLock(lockPath, opts = {}) {
188
+ const maxTries = opts.maxTries ?? 300;
189
+ const waitMs = opts.waitMs ?? 10;
190
+ for (let i = 0; i < maxTries; i++) {
191
+ const owner = newOwner();
192
+ if (createLockFile(lockPath, owner, true)) {
193
+ return;
194
+ }
195
+ const current = lockOwner(lockPath);
196
+ if (current !== null && current.pid !== process.pid && !pidAlive(current.pid)) {
197
+ if (!reclaimStaleLock(lockPath))
198
+ syncSleep(waitMs);
199
+ continue;
200
+ }
201
+ syncSleep(waitMs);
202
+ }
203
+ throw new LockTimeoutError(lockPath);
204
+ }
205
+ export function releaseLock(lockPath) {
206
+ const key = lockKey(lockPath);
207
+ const owner = ownedLocks.get(key);
208
+ if (owner === undefined)
209
+ return;
210
+ try {
211
+ if (!sameOwner(lockOwner(lockPath), owner))
212
+ return;
213
+ const releasedPath = sidecarPath(lockPath, 'released');
214
+ try {
215
+ renameSync(lockPath, releasedPath);
216
+ }
217
+ catch (error) {
218
+ if (isErrno(error, 'ENOENT'))
219
+ return;
220
+ throw error;
221
+ }
222
+ removeFileIfExists(releasedPath);
223
+ }
224
+ finally {
225
+ ownedLocks.delete(key);
226
+ }
227
+ }
@@ -0,0 +1,2 @@
1
+ export * from './fileLock.js';
2
+ export * from './version.js';
@@ -0,0 +1,2 @@
1
+ export * from './fileLock.js';
2
+ export * from './version.js';
@@ -0,0 +1,12 @@
1
+ export interface PackageMetadata {
2
+ readonly name?: string;
3
+ readonly version?: string;
4
+ readonly bin?: string | Record<string, string>;
5
+ }
6
+ export interface ResolveRuntimeVersionOptions {
7
+ readonly startDir: string;
8
+ readonly isPackage: (pkg: PackageMetadata) => boolean;
9
+ readonly fallback?: string;
10
+ readonly execGit?: (args: readonly string[], cwd: string) => string;
11
+ }
12
+ export declare function resolveRuntimeVersion(opts: ResolveRuntimeVersionOptions): string;
@@ -0,0 +1,51 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { readFileSync } from 'node:fs';
3
+ import { dirname, join } from 'node:path';
4
+ const PLACEHOLDER_VERSIONS = new Set(['', '0.0.0']);
5
+ const GIT_SHA_RE = /^[0-9a-f]{7,40}$/i;
6
+ export function resolveRuntimeVersion(opts) {
7
+ const fallback = opts.fallback ?? '0.0.0';
8
+ const found = findRuntimePackage(opts.startDir, opts.isPackage);
9
+ const packageVersion = found?.pkg.version?.trim() ?? '';
10
+ if (!PLACEHOLDER_VERSIONS.has(packageVersion))
11
+ return packageVersion;
12
+ const gitVersion = resolveGitVersion(found?.dir ?? opts.startDir, opts.execGit);
13
+ return gitVersion ?? fallback;
14
+ }
15
+ function findRuntimePackage(startDir, isPackage) {
16
+ let dir = startDir;
17
+ for (let i = 0; i < 8; i += 1) {
18
+ try {
19
+ const pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'));
20
+ if (isPackage(pkg))
21
+ return { dir, pkg };
22
+ }
23
+ catch {
24
+ // Source and built layouts put package.json at different depths.
25
+ }
26
+ const parent = dirname(dir);
27
+ if (parent === dir)
28
+ break;
29
+ dir = parent;
30
+ }
31
+ return null;
32
+ }
33
+ function resolveGitVersion(startDir, execGit = defaultExecGit) {
34
+ const sha = safeGit(['rev-parse', '--short=12', 'HEAD'], startDir, execGit);
35
+ if (!sha || !GIT_SHA_RE.test(sha))
36
+ return null;
37
+ const dirty = safeGit(['status', '--porcelain'], startDir, execGit);
38
+ return `0.0.0+git.${sha.toLowerCase()}${dirty ? '.dirty' : ''}`;
39
+ }
40
+ function safeGit(args, cwd, execGit) {
41
+ try {
42
+ const out = execGit(args, cwd).trim();
43
+ return out.length > 0 ? out : null;
44
+ }
45
+ catch {
46
+ return null;
47
+ }
48
+ }
49
+ function defaultExecGit(args, cwd) {
50
+ return execFileSync('git', [...args], { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
51
+ }
@@ -0,0 +1,4 @@
1
+ export * from './validation.js';
2
+ export * from './rollback.js';
3
+ export * from './sandboxRunner.js';
4
+ export * from './sandboxedValidation.js';
@@ -0,0 +1,4 @@
1
+ export * from './validation.js';
2
+ export * from './rollback.js';
3
+ export * from './sandboxRunner.js';
4
+ export * from './sandboxedValidation.js';
@@ -0,0 +1,22 @@
1
+ export interface RollbackConfig {
2
+ ownedRoots: readonly string[];
3
+ optIn: boolean;
4
+ }
5
+ export interface RollbackTarget {
6
+ path: string;
7
+ tracked: boolean;
8
+ }
9
+ export interface RollbackPlan {
10
+ willRollback: RollbackTarget[];
11
+ skipped: Array<{
12
+ target: RollbackTarget;
13
+ reason: string;
14
+ }>;
15
+ }
16
+ /**
17
+ * 规划回滚(M4A-4, 批注#20). 三条铁律, 全部满足才回滚:
18
+ * - opt-in: optIn=false 时一律不回滚.
19
+ * - 只动 evolver-owned: 路径必须在 ownedRoots 之内(绝不 reset 主仓 working tree / 仓外文件).
20
+ * - 不删 untracked: 未跟踪文件不回滚(避免破坏用户未提交工作).
21
+ */
22
+ export declare function planRollback(targets: readonly RollbackTarget[], cfg: RollbackConfig): RollbackPlan;