nene2-python 1.8.57__tar.gz → 1.8.58__tar.gz

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 (409) hide show
  1. {nene2_python-1.8.57 → nene2_python-1.8.58}/PKG-INFO +1 -1
  2. nene2_python-1.8.58/docs/field-trials/2026-05-field-trial-187.md +261 -0
  3. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/INDEX.md +2 -1
  4. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/todo/current.md +6 -5
  5. {nene2_python-1.8.57 → nene2_python-1.8.58}/pyproject.toml +1 -1
  6. {nene2_python-1.8.57 → nene2_python-1.8.58}/.env.example +0 -0
  7. {nene2_python-1.8.57 → nene2_python-1.8.58}/.github/workflows/ci.yml +0 -0
  8. {nene2_python-1.8.57 → nene2_python-1.8.58}/.github/workflows/docs.yml +0 -0
  9. {nene2_python-1.8.57 → nene2_python-1.8.58}/.github/workflows/publish.yml +0 -0
  10. {nene2_python-1.8.57 → nene2_python-1.8.58}/.gitignore +0 -0
  11. {nene2_python-1.8.57 → nene2_python-1.8.58}/.vitepress/config.mts +0 -0
  12. {nene2_python-1.8.57 → nene2_python-1.8.58}/.vitepress/theme/custom.css +0 -0
  13. {nene2_python-1.8.57 → nene2_python-1.8.58}/.vitepress/theme/index.ts +0 -0
  14. {nene2_python-1.8.57 → nene2_python-1.8.58}/AGENTS.md +0 -0
  15. {nene2_python-1.8.57 → nene2_python-1.8.58}/CHANGELOG.md +0 -0
  16. {nene2_python-1.8.57 → nene2_python-1.8.58}/CLAUDE.md +0 -0
  17. {nene2_python-1.8.57 → nene2_python-1.8.58}/Dockerfile +0 -0
  18. {nene2_python-1.8.57 → nene2_python-1.8.58}/LICENSE +0 -0
  19. {nene2_python-1.8.57 → nene2_python-1.8.58}/README.md +0 -0
  20. {nene2_python-1.8.57 → nene2_python-1.8.58}/alembic/README +0 -0
  21. {nene2_python-1.8.57 → nene2_python-1.8.58}/alembic/env.py +0 -0
  22. {nene2_python-1.8.57 → nene2_python-1.8.58}/alembic/script.py.mako +0 -0
  23. {nene2_python-1.8.57 → nene2_python-1.8.58}/alembic/versions/001_create_notes_and_tags_tables.py +0 -0
  24. {nene2_python-1.8.57 → nene2_python-1.8.58}/alembic.ini +0 -0
  25. {nene2_python-1.8.57 → nene2_python-1.8.58}/compose.yaml +0 -0
  26. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/adr/0001-toolchain.md +0 -0
  27. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/adr/0002-clean-architecture.md +0 -0
  28. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/adr/0003-security-first.md +0 -0
  29. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/adr/0004-ai-first-design.md +0 -0
  30. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/adr/0005-logging.md +0 -0
  31. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/adr/0006-rate-limiting.md +0 -0
  32. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/adr/0009-mcp-design.md +0 -0
  33. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/adr/0010-async-use-case.md +0 -0
  34. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/adr/0011-mcp-as-core-dependency.md +0 -0
  35. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/de/index.md +0 -0
  36. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/de/tutorials/getting-started.md +0 -0
  37. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/explanation/architecture.md +0 -0
  38. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/explanation/design-philosophy.md +0 -0
  39. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-1.md +0 -0
  40. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-10.md +0 -0
  41. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-100.md +0 -0
  42. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-101.md +0 -0
  43. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-102.md +0 -0
  44. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-103.md +0 -0
  45. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-104.md +0 -0
  46. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-105.md +0 -0
  47. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-106.md +0 -0
  48. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-107.md +0 -0
  49. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-108.md +0 -0
  50. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-109.md +0 -0
  51. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-11.md +0 -0
  52. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-110.md +0 -0
  53. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-111.md +0 -0
  54. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-112.md +0 -0
  55. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-113.md +0 -0
  56. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-114.md +0 -0
  57. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-115.md +0 -0
  58. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-116.md +0 -0
  59. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-117.md +0 -0
  60. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-118.md +0 -0
  61. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-119.md +0 -0
  62. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-12.md +0 -0
  63. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-120.md +0 -0
  64. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-121.md +0 -0
  65. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-122.md +0 -0
  66. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-123.md +0 -0
  67. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-124.md +0 -0
  68. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-125.md +0 -0
  69. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-126.md +0 -0
  70. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-127.md +0 -0
  71. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-128.md +0 -0
  72. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-129.md +0 -0
  73. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-13.md +0 -0
  74. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-130.md +0 -0
  75. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-131.md +0 -0
  76. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-132.md +0 -0
  77. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-133.md +0 -0
  78. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-134.md +0 -0
  79. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-135.md +0 -0
  80. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-136.md +0 -0
  81. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-137.md +0 -0
  82. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-138.md +0 -0
  83. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-139.md +0 -0
  84. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-14.md +0 -0
  85. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-140.md +0 -0
  86. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-141.md +0 -0
  87. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-142.md +0 -0
  88. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-143.md +0 -0
  89. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-144.md +0 -0
  90. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-145.md +0 -0
  91. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-146.md +0 -0
  92. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-147.md +0 -0
  93. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-148.md +0 -0
  94. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-149.md +0 -0
  95. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-15.md +0 -0
  96. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-150.md +0 -0
  97. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-151.md +0 -0
  98. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-152.md +0 -0
  99. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-153.md +0 -0
  100. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-154.md +0 -0
  101. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-155.md +0 -0
  102. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-156.md +0 -0
  103. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-157.md +0 -0
  104. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-158.md +0 -0
  105. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-159.md +0 -0
  106. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-16.md +0 -0
  107. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-160.md +0 -0
  108. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-161.md +0 -0
  109. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-162.md +0 -0
  110. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-163.md +0 -0
  111. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-164.md +0 -0
  112. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-165.md +0 -0
  113. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-166.md +0 -0
  114. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-167.md +0 -0
  115. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-168.md +0 -0
  116. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-169.md +0 -0
  117. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-17.md +0 -0
  118. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-170.md +0 -0
  119. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-171.md +0 -0
  120. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-172.md +0 -0
  121. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-173.md +0 -0
  122. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-174.md +0 -0
  123. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-175.md +0 -0
  124. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-176.md +0 -0
  125. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-177.md +0 -0
  126. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-178.md +0 -0
  127. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-179.md +0 -0
  128. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-18.md +0 -0
  129. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-180.md +0 -0
  130. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-181.md +0 -0
  131. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-182.md +0 -0
  132. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-183.md +0 -0
  133. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-184.md +0 -0
  134. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-185.md +0 -0
  135. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-186.md +0 -0
  136. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-19.md +0 -0
  137. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-2.md +0 -0
  138. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-20.md +0 -0
  139. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-21.md +0 -0
  140. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-22.md +0 -0
  141. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-23.md +0 -0
  142. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-24.md +0 -0
  143. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-25.md +0 -0
  144. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-26.md +0 -0
  145. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-27.md +0 -0
  146. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-28.md +0 -0
  147. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-29.md +0 -0
  148. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-3.md +0 -0
  149. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-30.md +0 -0
  150. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-31.md +0 -0
  151. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-32.md +0 -0
  152. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-33.md +0 -0
  153. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-34.md +0 -0
  154. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-35.md +0 -0
  155. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-36.md +0 -0
  156. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-37.md +0 -0
  157. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-38.md +0 -0
  158. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-39.md +0 -0
  159. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-4.md +0 -0
  160. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-40.md +0 -0
  161. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-41.md +0 -0
  162. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-42.md +0 -0
  163. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-43.md +0 -0
  164. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-44.md +0 -0
  165. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-45.md +0 -0
  166. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-46.md +0 -0
  167. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-47.md +0 -0
  168. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-48.md +0 -0
  169. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-49.md +0 -0
  170. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-5.md +0 -0
  171. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-50.md +0 -0
  172. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-51.md +0 -0
  173. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-52.md +0 -0
  174. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-53.md +0 -0
  175. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-54.md +0 -0
  176. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-55.md +0 -0
  177. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-56.md +0 -0
  178. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-57.md +0 -0
  179. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-58.md +0 -0
  180. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-59.md +0 -0
  181. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-6.md +0 -0
  182. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-60.md +0 -0
  183. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-61.md +0 -0
  184. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-62.md +0 -0
  185. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-63.md +0 -0
  186. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-64.md +0 -0
  187. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-65.md +0 -0
  188. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-66.md +0 -0
  189. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-67.md +0 -0
  190. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-68.md +0 -0
  191. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-69.md +0 -0
  192. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-7.md +0 -0
  193. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-70.md +0 -0
  194. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-71.md +0 -0
  195. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-72.md +0 -0
  196. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-73.md +0 -0
  197. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-74.md +0 -0
  198. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-75.md +0 -0
  199. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-76.md +0 -0
  200. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-77.md +0 -0
  201. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-78.md +0 -0
  202. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-79.md +0 -0
  203. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-8.md +0 -0
  204. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-80.md +0 -0
  205. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-81.md +0 -0
  206. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-82.md +0 -0
  207. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-83.md +0 -0
  208. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-84.md +0 -0
  209. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-85.md +0 -0
  210. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-86.md +0 -0
  211. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-87.md +0 -0
  212. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-88.md +0 -0
  213. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-89.md +0 -0
  214. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-9.md +0 -0
  215. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-90.md +0 -0
  216. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-91.md +0 -0
  217. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-92.md +0 -0
  218. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-93.md +0 -0
  219. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-94.md +0 -0
  220. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-95.md +0 -0
  221. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-96.md +0 -0
  222. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-97.md +0 -0
  223. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-98.md +0 -0
  224. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/field-trials/2026-05-field-trial-99.md +0 -0
  225. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/fr/index.md +0 -0
  226. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/fr/tutorials/getting-started.md +0 -0
  227. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/add-new-domain.md +0 -0
  228. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/api-versioning.md +0 -0
  229. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/async-use-case.md +0 -0
  230. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/background-tasks.md +0 -0
  231. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/configure-auth.md +0 -0
  232. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/cors.md +0 -0
  233. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/custom-auth-middleware.md +0 -0
  234. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/dependency-injection.md +0 -0
  235. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/domain-events.md +0 -0
  236. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/file-upload.md +0 -0
  237. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/lifespan-and-app-state.md +0 -0
  238. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/middleware-stack.md +0 -0
  239. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/new-project.md +0 -0
  240. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/problem-details.md +0 -0
  241. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/response-patterns.md +0 -0
  242. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/run-tests.md +0 -0
  243. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/soft-delete.md +0 -0
  244. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/sqlalchemy-repository.md +0 -0
  245. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/streaming.md +0 -0
  246. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/structured-logging.md +0 -0
  247. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/validation.md +0 -0
  248. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/how-to/webhook.md +0 -0
  249. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/howto/mcp-setup.md +0 -0
  250. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/index.md +0 -0
  251. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/ja/explanation/architecture.md +0 -0
  252. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/ja/explanation/design-philosophy.md +0 -0
  253. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/ja/how-to/add-new-domain.md +0 -0
  254. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/ja/how-to/configure-auth.md +0 -0
  255. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/ja/how-to/new-project.md +0 -0
  256. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/ja/how-to/run-tests.md +0 -0
  257. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/ja/how-to/sqlalchemy-repository.md +0 -0
  258. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/ja/howto/mcp-setup.md +0 -0
  259. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/ja/index.md +0 -0
  260. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/ja/reference/api.md +0 -0
  261. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/ja/reference/configuration.md +0 -0
  262. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/ja/reference/framework-modules.md +0 -0
  263. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/ja/tutorials/first-domain.md +0 -0
  264. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/ja/tutorials/getting-started.md +0 -0
  265. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/pt-br/index.md +0 -0
  266. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/pt-br/tutorials/getting-started.md +0 -0
  267. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/reference/api.md +0 -0
  268. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/reference/configuration.md +0 -0
  269. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/reference/framework-modules.md +0 -0
  270. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/roadmap.md +0 -0
  271. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/templates/field-trial-report.md +0 -0
  272. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/tutorials/first-domain.md +0 -0
  273. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/tutorials/getting-started.md +0 -0
  274. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/zh/index.md +0 -0
  275. {nene2_python-1.8.57 → nene2_python-1.8.58}/docs/zh/tutorials/getting-started.md +0 -0
  276. {nene2_python-1.8.57 → nene2_python-1.8.58}/package-lock.json +0 -0
  277. {nene2_python-1.8.57 → nene2_python-1.8.58}/package.json +0 -0
  278. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/__init__.py +0 -0
  279. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/__main__.py +0 -0
  280. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/app.py +0 -0
  281. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/comment/__init__.py +0 -0
  282. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/comment/entity.py +0 -0
  283. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/comment/exceptions.py +0 -0
  284. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/comment/handler.py +0 -0
  285. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/comment/repository.py +0 -0
  286. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/comment/sqlalchemy_repository.py +0 -0
  287. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/comment/use_case.py +0 -0
  288. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/mcp.py +0 -0
  289. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/note/__init__.py +0 -0
  290. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/note/async_use_case.py +0 -0
  291. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/note/entity.py +0 -0
  292. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/note/exceptions.py +0 -0
  293. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/note/handler.py +0 -0
  294. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/note/repository.py +0 -0
  295. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/note/sqlalchemy_repository.py +0 -0
  296. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/note/use_case.py +0 -0
  297. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/schema.py +0 -0
  298. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/tag/__init__.py +0 -0
  299. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/tag/entity.py +0 -0
  300. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/tag/exceptions.py +0 -0
  301. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/tag/handler.py +0 -0
  302. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/tag/repository.py +0 -0
  303. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/tag/sqlalchemy_repository.py +0 -0
  304. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/example/tag/use_case.py +0 -0
  305. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/__init__.py +0 -0
  306. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/auth/__init__.py +0 -0
  307. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/auth/api_key.py +0 -0
  308. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/auth/bearer_token.py +0 -0
  309. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/auth/deps.py +0 -0
  310. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/auth/exceptions.py +0 -0
  311. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/auth/interfaces.py +0 -0
  312. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/auth/local_verifier.py +0 -0
  313. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/cache/__init__.py +0 -0
  314. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/cache/ttl.py +0 -0
  315. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/config/__init__.py +0 -0
  316. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/config/settings.py +0 -0
  317. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/database/__init__.py +0 -0
  318. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/database/exceptions.py +0 -0
  319. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/database/health.py +0 -0
  320. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/database/interfaces.py +0 -0
  321. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/database/sqlalchemy_executor.py +0 -0
  322. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/database/utils.py +0 -0
  323. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/http/__init__.py +0 -0
  324. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/http/etag.py +0 -0
  325. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/http/health.py +0 -0
  326. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/http/pagination.py +0 -0
  327. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/http/problem_details.py +0 -0
  328. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/log/__init__.py +0 -0
  329. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/log/setup.py +0 -0
  330. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/mcp/__init__.py +0 -0
  331. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/mcp/http_client.py +0 -0
  332. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/mcp/server.py +0 -0
  333. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/middleware/__init__.py +0 -0
  334. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/middleware/domain_exception.py +0 -0
  335. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/middleware/error_handler.py +0 -0
  336. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/middleware/request_id.py +0 -0
  337. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/middleware/request_logging.py +0 -0
  338. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/middleware/request_size_limit.py +0 -0
  339. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/middleware/security_headers.py +0 -0
  340. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/middleware/setup.py +0 -0
  341. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/middleware/throttle.py +0 -0
  342. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/py.typed +0 -0
  343. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/security/__init__.py +0 -0
  344. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/security/webhook.py +0 -0
  345. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/use_case/__init__.py +0 -0
  346. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/use_case/protocols.py +0 -0
  347. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/validation/__init__.py +0 -0
  348. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/nene2/validation/exceptions.py +0 -0
  349. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/scripts/__init__.py +0 -0
  350. {nene2_python-1.8.57 → nene2_python-1.8.58}/src/scripts/export_openapi.py +0 -0
  351. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/__init__.py +0 -0
  352. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/conftest.py +0 -0
  353. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/example/__init__.py +0 -0
  354. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/example/comment/__init__.py +0 -0
  355. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/example/comment/test_comment_http.py +0 -0
  356. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/example/comment/test_comment_repository.py +0 -0
  357. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/example/comment/test_comment_use_case.py +0 -0
  358. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/example/conftest.py +0 -0
  359. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/example/note/__init__.py +0 -0
  360. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/example/note/test_async_note_use_case.py +0 -0
  361. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/example/note/test_list_notes.py +0 -0
  362. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/example/note/test_note_repository.py +0 -0
  363. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/example/tag/__init__.py +0 -0
  364. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/example/tag/test_tag_repository.py +0 -0
  365. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/example/tag/test_tags.py +0 -0
  366. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/example/test_cors.py +0 -0
  367. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/example/test_mcp.py +0 -0
  368. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/__init__.py +0 -0
  369. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/auth/__init__.py +0 -0
  370. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/auth/test_api_key.py +0 -0
  371. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/auth/test_bearer_token.py +0 -0
  372. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/auth/test_make_require_auth.py +0 -0
  373. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/auth/test_token_issuer.py +0 -0
  374. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/cache/__init__.py +0 -0
  375. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/cache/test_ttl.py +0 -0
  376. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/config/__init__.py +0 -0
  377. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/config/test_settings.py +0 -0
  378. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/database/__init__.py +0 -0
  379. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/database/test_transaction.py +0 -0
  380. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/database/test_utils.py +0 -0
  381. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/http/__init__.py +0 -0
  382. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/http/test_etag.py +0 -0
  383. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/http/test_health.py +0 -0
  384. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/http/test_pagination.py +0 -0
  385. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/http/test_problem_details.py +0 -0
  386. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/log/__init__.py +0 -0
  387. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/log/test_setup.py +0 -0
  388. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/mcp/__init__.py +0 -0
  389. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/mcp/test_http_client.py +0 -0
  390. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/mcp/test_server.py +0 -0
  391. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/middleware/__init__.py +0 -0
  392. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/middleware/test_error_handler.py +0 -0
  393. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/middleware/test_request_id.py +0 -0
  394. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/middleware/test_request_logging.py +0 -0
  395. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/middleware/test_request_size_limit.py +0 -0
  396. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/middleware/test_security_headers.py +0 -0
  397. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/middleware/test_setup_middlewares.py +0 -0
  398. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/middleware/test_simple_domain_handler.py +0 -0
  399. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/middleware/test_throttle.py +0 -0
  400. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/security/__init__.py +0 -0
  401. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/security/test_webhook.py +0 -0
  402. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/use_case/__init__.py +0 -0
  403. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/use_case/test_protocols.py +0 -0
  404. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/use_case/test_run_in_threadpool.py +0 -0
  405. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/validation/__init__.py +0 -0
  406. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/nene2/validation/test_exceptions.py +0 -0
  407. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/scripts/__init__.py +0 -0
  408. {nene2_python-1.8.57 → nene2_python-1.8.58}/tests/scripts/test_export_openapi.py +0 -0
  409. {nene2_python-1.8.57 → nene2_python-1.8.58}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nene2-python
3
- Version: 1.8.57
3
+ Version: 1.8.58
4
4
  Summary: NENE2 Python — minimal API framework following NENE2's design philosophy
5
5
  Project-URL: Homepage, https://github.com/hideyukiMORI/nene2-python
6
6
  Project-URL: Repository, https://github.com/hideyukiMORI/nene2-python
@@ -0,0 +1,261 @@
1
+ # FT187: collections
2
+
3
+ **日付**: 2026-05-21
4
+ **テーマ**: collections モジュール — Counter・defaultdict・deque・ChainMap・NamedTuple・OrderedDict
5
+ **セキュリティ診断**: なし(187 % 3 = 1)
6
+ **クラッカーペンテスト**: なし(187 % 4 = 3)
7
+
8
+ ---
9
+
10
+ ## 概要
11
+
12
+ Python 標準ライブラリ `collections` は汎用コンテナ型の拡張集である。
13
+ `Counter`(頻度カウント)、`defaultdict`(デフォルト値付き辞書)、`deque`(両端キュー)、`ChainMap`(複数辞書のビュー)、`NamedTuple`(型付き名前付きタプル)、`OrderedDict`(挿入順序保持辞書)の主要 6 型を検証した。
14
+
15
+ ---
16
+
17
+ ## 実装したサンプルアプリ
18
+
19
+ **場所**: `/home/xi/docker/nene2-python-FT/ft187-collections/`
20
+
21
+ ### 主要機能
22
+
23
+ | 関数/クラス | 概要 |
24
+ |---|---|
25
+ | `word_frequency(text)` | Counter で単語頻度を集計 |
26
+ | `top_n_words(text, n)` | `most_common(n)` で上位 N 単語を取得 |
27
+ | `character_frequency(text)` | 文字頻度を集計(空白除外)|
28
+ | `merge_counters(a, b)` | Counter の `+` 演算子でマージ |
29
+ | `subtract_counters(a, b)` | Counter の `-` 演算子で差分(正の値のみ)|
30
+ | `group_by_length(words)` | defaultdict でワード長別グループ化 |
31
+ | `build_inverted_index(docs)` | defaultdict で転置インデックス構築 |
32
+ | `count_nested(items, sep)` | ネスト defaultdict でカテゴリ別集計 |
33
+ | `BoundedHistory` | `deque(maxlen=N)` でサイズ制限付き履歴 |
34
+ | `sliding_window_average(values, window)` | deque + maxlen でスライディング平均 |
35
+ | `rotate_list(items, steps)` | `deque.rotate()` でリストをローテーション |
36
+ | `resolve_config(*layers)` | ChainMap で設定レイヤーを優先順解決 |
37
+ | `get_with_override(base, override, key)` | ChainMap で override 優先の値取得 |
38
+ | `Coordinate` | `typing.NamedTuple` で型付き座標 |
39
+ | `deduplicate_preserving_order(items)` | OrderedDict で順序保持重複除去 |
40
+ | `LruDict` | OrderedDict を使った LRU キャッシュ |
41
+
42
+ ### HTTP エンドポイント
43
+
44
+ | メソッド | パス | 概要 |
45
+ |---|---|---|
46
+ | POST | `/counter/words` | 単語頻度集計 |
47
+ | POST | `/counter/top` | 上位 N 単語 |
48
+ | POST | `/counter/chars` | 文字頻度集計 |
49
+ | POST | `/counter/merge` | カウンターマージ |
50
+ | POST | `/counter/subtract` | カウンター差分 |
51
+ | POST | `/defaultdict/group` | 長さ別グループ化 |
52
+ | POST | `/defaultdict/index` | 転置インデックス |
53
+ | POST | `/defaultdict/nested` | ネストカウント |
54
+ | POST | `/deque/sliding-window` | スライディング平均 |
55
+ | POST | `/deque/rotate` | リストローテーション |
56
+ | POST | `/chainmap/resolve` | 設定レイヤー解決 |
57
+ | POST | `/ordereddict/deduplicate` | 順序保持重複除去 |
58
+ | POST | `/namedtuple/coordinates` | 座標パース |
59
+ | POST | `/ordereddict/lru` | LRU キャッシュ操作 |
60
+
61
+ ---
62
+
63
+ ## テスト結果
64
+
65
+ **56 passed**
66
+
67
+ ```
68
+ 56 passed in 0.35s
69
+ ```
70
+
71
+ mypy --strict: Success
72
+ ruff check: All checks passed
73
+ pip-audit: PYSEC-2025-183 (PyJWT via mcp transitive dep — 許容済み)
74
+
75
+ ---
76
+
77
+ ## 摩擦ポイント
78
+
79
+ ### F-1: `parse_coordinates` の引数型に `dict[str, float | str]` を使うと mypy エラー(深刻度: 低)
80
+
81
+ **事象**: `parse_coordinates(raw: list[dict[str, float | str]])` を定義し、呼び出し側で `[{"latitude": c.latitude, ...}]` を渡したところ、mypy が `Argument 1 has incompatible type "list[dict[str, object]]"` エラーを出した。辞書リテラルの型が `dict[str, object]` として推論されるため。
82
+
83
+ **原因**: Python の辞書リテラル `{"latitude": 35.0, "label": "A"}` は `dict[str, float | str]` ではなく `dict[str, object]` として推論される(値の型が異なる場合)。
84
+
85
+ **対応**: 入力専用のデータクラス `RawCoordinate(dataclass(frozen=True, slots=True))` を定義して型安全な引数にした。`dict` を渡す代わりに `RawCoordinate` オブジェクトを渡す。
86
+
87
+ ```python
88
+ @dataclass(frozen=True, slots=True)
89
+ class RawCoordinate:
90
+ latitude: float
91
+ longitude: float
92
+ label: str = ""
93
+
94
+ def parse_coordinates(raw: list[RawCoordinate]) -> list[Coordinate]:
95
+ return [Coordinate(latitude=r.latitude, ...) for r in raw]
96
+ ```
97
+
98
+ ---
99
+
100
+ ## 観察点
101
+
102
+ ### 観察1: Counter の算術演算子
103
+
104
+ ```python
105
+ a = Counter({"x": 5, "y": 2})
106
+ b = Counter({"x": 3, "y": 4})
107
+
108
+ a + b # {"x": 8, "y": 6} — 合計
109
+ a - b # {"x": 2} — 差分(正の値のみ残る)
110
+ a & b # {"x": 3, "y": 2} — 最小値(intersection)
111
+ a | b # {"x": 5, "y": 4} — 最大値(union)
112
+ ```
113
+
114
+ `Counter` は `dict` のサブクラスで算術演算子が使えるため、集合演算的な使い方ができる。`-` の結果は正の値のみ(負になったキーは除外)になる点が直感と異なる場合がある。
115
+
116
+ ### 観察2: defaultdict のネスト — `lambda` を使ったデフォルト値
117
+
118
+ ```python
119
+ # ネストした defaultdict
120
+ result: defaultdict[str, defaultdict[str, int]] = \
121
+ defaultdict(lambda: defaultdict(int))
122
+
123
+ # 使用例
124
+ result["fruit"]["apple"] += 1
125
+ ```
126
+
127
+ `lambda: defaultdict(int)` でネストした自動生成が可能。ただし `lambda` の型は mypy で推論が難しいため、明示的な型注釈が必要になる場合がある。
128
+
129
+ ### 観察3: deque の `maxlen` による自動エビクション
130
+
131
+ ```python
132
+ dq = deque(maxlen=3)
133
+ dq.append(1) # [1]
134
+ dq.append(2) # [1, 2]
135
+ dq.append(3) # [1, 2, 3]
136
+ dq.append(4) # [2, 3, 4] — 左端の 1 が自動除去
137
+ ```
138
+
139
+ `deque(maxlen=N)` は満杯時に反対側の要素を自動除去する。スライディングウィンドウ・LRU 的な「最近 N 件だけ保持」のユースケースに適している。`appendleft` を使うと最新が先頭になる(`BoundedHistory` パターン)。
140
+
141
+ ### 観察4: ChainMap の「先頭優先」セマンティクス
142
+
143
+ ```python
144
+ chain = ChainMap(override, base)
145
+ chain["key"] # override の値を優先(なければ base を参照)
146
+ chain["new"] = "value" # 先頭の override に追加(base は変更されない)
147
+ ```
148
+
149
+ `ChainMap` は辞書のコピーを作らずビューを提供する。環境変数 → 設定ファイル → デフォルト値という優先順位を持つ設定解決に適している。`new_child()` で新しいスコープを作成することも可能。
150
+
151
+ ### 観察5: `typing.NamedTuple` vs `collections.namedtuple`
152
+
153
+ ```python
154
+ # collections.namedtuple — フィールド名のみ、型なし
155
+ Point = namedtuple("Point", ["x", "y"])
156
+
157
+ # typing.NamedTuple — 型付きフィールド、デフォルト値、メソッド定義可
158
+ class Coordinate(NamedTuple):
159
+ latitude: float
160
+ longitude: float
161
+ label: str = ""
162
+ def distance_to(self, other: "Coordinate") -> float: ...
163
+ ```
164
+
165
+ `typing.NamedTuple` は型安全でデフォルト値・メソッドを持てるため、`dataclass` の代替として不変の小さな値オブジェクトに使える。ただし `frozen=True` の `dataclass` と異なり、継承で問題が生じやすいため、単純な値型に限定するのが無難。
166
+
167
+ ### 観察6: OrderedDict を使った LRU キャッシュ
168
+
169
+ ```python
170
+ cache = OrderedDict()
171
+
172
+ def get(key):
173
+ cache.move_to_end(key) # アクセスで MRU 端へ移動
174
+ return cache[key]
175
+
176
+ def put(key, value):
177
+ if len(cache) >= capacity:
178
+ cache.popitem(last=False) # LRU 端(先頭)から除去
179
+ cache[key] = value
180
+ ```
181
+
182
+ Python 3.2+ の `dict` は挿入順序保持が保証されているが、`OrderedDict` は `move_to_end()` と `popitem(last=False/True)` を持ち、LRU 実装が簡潔に書ける。
183
+
184
+ ---
185
+
186
+ ## Follow-up Issues
187
+
188
+ 今回の FT では実装上の重大な摩擦はなかった。F-1 は mypy --strict での型推論の限界によるものであり、`dataclass` を入力型として導入することで解決した。
189
+
190
+ GitHub Issues: なし
191
+
192
+ ---
193
+
194
+ ## DX Review — 6ペルソナ
195
+
196
+ ### 1. 初心者(Python 歴1年・独学中・女性・バックエンド志望)
197
+
198
+ `Counter` は「リストの頻度を数える」という非常に頻繁に必要とされる操作をワンライナーで実現できる。`most_common(n)` の使いやすさは特に印象的で、手書きのループより明快。
199
+
200
+ **ドキュメント理解**: `defaultdict` の「キーが存在しなければデフォルト値を自動生成する」という動作は、通常の辞書で `KeyError` に何度もぶつかった後に習得するパターン。デモのネスト例は実用的で理解しやすい。
201
+
202
+ **事故リスク**: 低 — ただし `Counter` の `-` が「負値を除外する」挙動を知らないと驚く。テストで明示したことで習得しやすい。
203
+
204
+ **規約の使いやすさ**: `LruDict` のパターン(`move_to_end` + `popitem`)は初心者には高度だが、「なぜ OrderedDict を使うのか」が実例で見えると理解が進む。
205
+
206
+ ### 2. ロースキル経験者(Python 歴3-4年・スクリプト系・男性・SES)
207
+
208
+ `Counter.most_common()` はログ解析・アクセス集計でそのまま使えるため実務価値が高い。`defaultdict(list)` による転置インデックスも業務で頻繁に必要になる。
209
+
210
+ **コピペ可能性**: `BoundedHistory`(deque + maxlen)・`LruDict`・`resolve_config`(ChainMap)はそのまま流用できるユーティリティ。
211
+
212
+ **拡張時の罠**: `ChainMap` の `chain["key"] = value` は先頭辞書のみ変更する。「両方の辞書を更新したい」場合は `ChainMap` は不適切。
213
+
214
+ **事故リスク**: 低
215
+
216
+ ### 3. フロントエンド寄り(React/TS 歴4年・バックエンド転向中・ノンバイナリ)
217
+
218
+ TypeScript では `Map<string, number>` や `Record<string, number>` で表現するものが Python では `Counter` / `defaultdict` に対応する。`ChainMap` は TS にない概念だが、React の Context や CSS カスケードと近いセマンティクスで理解できる。
219
+
220
+ **エラーレスポンスの質**: `/deque/sliding-window` の `window=0` に対する 422 バリデーションエラーは適切。FastAPI の `Field(ge=1)` が自動で機能している。
221
+
222
+ **Python 固有概念の学習コスト**: `NamedTuple` は TypeScript のインターフェースに近い。デフォルト値・メソッド定義できる点は TS の interface と同じ感覚で理解できる。
223
+
224
+ **事故リスク**: 低
225
+
226
+ ### 4. バックエンド経験者(Django/FastAPI 歴5-6年・男性・リードエンジニア)
227
+
228
+ `Counter` の算術演算子や `defaultdict` のネストは Django の `annotate()` / `aggregate()` では難しいデータ変換を純粋 Python で行う際に重宝する。`ChainMap` は Django の設定(`DJANGO_SETTINGS_MODULE` → デフォルト設定)と類似のパターン。
229
+
230
+ **他フレームワークとの差異**: `LruDict` は `functools.lru_cache` と比べて「任意の引数に対応する柔軟性」と「キャッシュの明示的管理」がメリット。
231
+
232
+ **nene2 の薄さへの評価**: `collections` は nene2 フレームワークと独立しているため、ドメインロジック層の実装にそのまま使えるコレクション群として評価が高い。
233
+
234
+ **事故リスク**: 低
235
+
236
+ ### 5. シニアエンジニア(設計・コードレビュー担当・女性・10-12年)
237
+
238
+ **コードレビューチェックポイント**:
239
+ - `defaultdict` が「サービス境界を超える」ケースに注意(外部に返す前に `dict(dd)` で変換しているか)
240
+ - `Counter` の `subtract()` メソッドと `-` 演算子の違い(`subtract` は負値を保持、`-` は正値のみ)
241
+ - `deque` に `maxlen` が設定されているか(無制限 deque は意図しないメモリ増大の原因)
242
+ - `ChainMap` の変更は先頭辞書のみに反映されることを把握しているか
243
+
244
+ **チームでの安全なパターン**: `BoundedHistory`(maxlen 付き deque)は監査ログ・エラー履歴の実装に、`resolve_config`(ChainMap)は設定オーバーライドに使えるチーム共有ユーティリティ。
245
+
246
+ **事故リスク**: 低
247
+
248
+ ### 6. 設計者(nene2-python 設計ポリシー目線)
249
+
250
+ **CLAUDE.md ポリシー整合性**:
251
+ - `dataclass(frozen=True, slots=True)`: `DequeSnapshot`・`RawCoordinate` で適用済み ✅
252
+ - Pydantic は HTTP 境界のみ: `app.py` の Request/Response モデルのみ ✅
253
+ - `create_app()` はファイル末尾: 適用済み ✅(FT182 の教訓)
254
+ - `max_length` 指定: 全文字列・リストフィールドに設定済み ✅
255
+ - 型安全: `dict[str, float | str]` の問題を `RawCoordinate` dataclass で解決 ✅
256
+
257
+ **初心者でも安全な API 達成度**: `BoundedHistory` が「maxlen を必ず指定して使う」パターンを示し、`LruDict` が「容量が決まっている場合のみ OrderedDict LRU を使う」ことを Pydantic の `le=100` で強制している設計は初心者でも誤用しにくい。
258
+
259
+ ---
260
+
261
+ *バージョン: v1.8.58*
@@ -220,6 +220,7 @@
220
220
  | [FT184](2026-05-field-trial-184.md) | urllib.request モジュール — URL フェッチ・Basic 認証・SSRF 防御 | 🔍 | [#516](https://github.com/hideyukiMORI/nene2-python/issues/516) [#517](https://github.com/hideyukiMORI/nene2-python/issues/517) |
221
221
  | [FT185](2026-05-field-trial-185.md) | contextlib モジュール — コンテキストマネージャー・リソース管理・エラー抑制 | | |
222
222
  | [FT186](2026-05-field-trial-186.md) | functools モジュール — キャッシュ・部分適用・デコレーター・比較・ディスパッチ | 🔒 | [#520](https://github.com/hideyukiMORI/nene2-python/issues/520) |
223
+ | [FT187](2026-05-field-trial-187.md) | collections モジュール — Counter・defaultdict・deque・ChainMap・NamedTuple・OrderedDict | | |
223
224
 
224
225
  ---
225
226
 
@@ -235,4 +236,4 @@ FT172, FT176, FT180, FT184
235
236
 
236
237
  ---
237
238
 
238
- *最終更新: 2026-05-21 (FT186 / v1.8.57)*
239
+ *最終更新: 2026-05-21 (FT187 / v1.8.58)*
@@ -1,14 +1,14 @@
1
1
  # TODO — current
2
2
 
3
3
  最終更新: 2026-05-21
4
- 現状: **v1.8.57 安定版 / フィールドトライアルループ継続中(FT186 完了)**
4
+ 現状: **v1.8.58 安定版 / フィールドトライアルループ継続中(FT187 完了)**
5
5
 
6
6
  ---
7
7
 
8
8
  ## 状態サマリー
9
9
 
10
- v1.8.57 完了済み。FT186functools / キャッシュ・部分適用・デコレーター・比較・ディスパッチ)を含む FT186 件を実施済み。セキュリティ診断実施済み。
11
- フィールドトライアルループは FT187 以降も継続中。
10
+ v1.8.58 完了済み。FT187collections / Counter・defaultdict・deque・ChainMap・NamedTuple・OrderedDict)を含む FT187 件を実施済み。
11
+ フィールドトライアルループは FT188 以降も継続中。
12
12
 
13
13
  ---
14
14
 
@@ -41,6 +41,7 @@ v1.8.57 完了済み。FT186(functools / キャッシュ・部分適用・デ
41
41
 
42
42
  | バージョン | 主な内容 |
43
43
  |---|---|
44
+ | v1.8.58 | FT187: collections — Counter・defaultdict・deque・ChainMap・NamedTuple・OrderedDict |
44
45
  | v1.8.57 | FT186: functools — キャッシュ・部分適用・デコレーター・比較・ディスパッチ(診断実施) |
45
46
  | v1.8.56 | FT185: contextlib — コンテキストマネージャー・リソース管理・エラー抑制 |
46
47
  | v1.8.55 | FT184: urllib.request — URL フェッチ・Basic 認証・SSRF 防御(クラッカーペンテスト実施) |
@@ -61,12 +62,12 @@ v1.8.57 完了済み。FT186(functools / キャッシュ・部分適用・デ
61
62
 
62
63
  ## フィールドトライアル進捗
63
64
 
64
- **実施済み**: FT1〜FT186(全 186 件)
65
+ **実施済み**: FT1〜FT187(全 187 件)
65
66
 
66
67
  索引: [`docs/field-trials/INDEX.md`](../field-trials/INDEX.md)
67
68
 
68
69
  **次のアクション**:
69
- - FT186 以降を継続(FT187187 % 4 = 3ペンテストなし、187 % 3 = 1 → 診断なし)
70
+ - FT187 以降を継続(FT188188 % 4 = 0クラッカーペンテストあり、188 % 3 = 2 → 診断なし)
70
71
 
71
72
  ---
72
73
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nene2-python"
3
- version = "1.8.57"
3
+ version = "1.8.58"
4
4
  description = "NENE2 Python — minimal API framework following NENE2's design philosophy"
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes