sdd-forge 0.1.0-alpha.32 → 0.1.0-alpha.361

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 (287) hide show
  1. package/README.md +11 -10
  2. package/package.json +7 -3
  3. package/src/AGENTS.md +420 -0
  4. package/src/docs/commands/agents.js +22 -7
  5. package/src/docs/commands/data.js +15 -13
  6. package/src/docs/commands/enrich.js +25 -9
  7. package/src/docs/commands/forge.js +2 -3
  8. package/src/docs/commands/init.js +19 -17
  9. package/src/docs/commands/readme.js +9 -6
  10. package/src/docs/commands/review.js +3 -3
  11. package/src/docs/commands/scan.js +37 -19
  12. package/src/docs/commands/text.js +105 -24
  13. package/src/docs/commands/translate.js +1 -1
  14. package/src/docs/data/agents.js +5 -4
  15. package/src/docs/data/docs.js +76 -8
  16. package/src/docs/data/lang.js +2 -2
  17. package/src/docs/data/text.js +32 -0
  18. package/src/docs/lib/command-context.js +3 -3
  19. package/src/docs/lib/directive-parser.js +335 -137
  20. package/src/docs/lib/forge-prompts.js +6 -6
  21. package/src/docs/lib/resolver-factory.js +73 -34
  22. package/src/docs/lib/scanner.js +1 -1
  23. package/src/docs/lib/template-merger.js +299 -89
  24. package/src/docs/lib/text-prompts.js +26 -18
  25. package/src/docs/lib/toml-parser.js +135 -0
  26. package/src/docs.js +23 -9
  27. package/src/flow/commands/cleanup.js +41 -22
  28. package/src/flow/commands/merge.js +104 -6
  29. package/src/flow/commands/resume.js +55 -5
  30. package/src/flow/commands/review.js +16 -6
  31. package/src/flow/commands/start.js +6 -14
  32. package/src/flow/commands/status.js +85 -38
  33. package/src/lib/flow-state.js +388 -28
  34. package/src/lib/i18n.js +4 -3
  35. package/src/lib/json-parse.js +31 -0
  36. package/src/lib/multi-select.js +265 -0
  37. package/src/lib/presets.js +95 -23
  38. package/src/lib/skills.js +96 -0
  39. package/src/lib/types.js +48 -22
  40. package/src/locale/en/prompts.json +4 -6
  41. package/src/locale/en/ui.json +19 -33
  42. package/src/locale/ja/prompts.json +4 -6
  43. package/src/locale/ja/ui.json +19 -33
  44. package/src/presets/api/preset.json +13 -0
  45. package/src/presets/api/templates/en/api_overview.md +22 -0
  46. package/src/presets/api/templates/en/authentication.md +22 -0
  47. package/src/presets/api/templates/ja/api_overview.md +22 -0
  48. package/src/presets/api/templates/ja/authentication.md +22 -0
  49. package/src/presets/architecture/preset.json +6 -0
  50. package/src/presets/base/data/structure.js +87 -0
  51. package/src/presets/base/preset.json +0 -1
  52. package/src/presets/base/templates/en/AGENTS.sdd.md +5 -1
  53. package/src/presets/base/templates/en/development.md +21 -19
  54. package/src/presets/base/templates/en/guardrail.md +20 -0
  55. package/src/presets/base/templates/en/layout.md +10 -0
  56. package/src/presets/base/templates/en/overview.md +22 -18
  57. package/src/presets/base/templates/en/project_structure.md +21 -19
  58. package/src/presets/base/templates/en/stack_and_ops.md +22 -18
  59. package/src/presets/base/templates/ja/AGENTS.sdd.md +5 -1
  60. package/src/presets/base/templates/ja/development.md +21 -19
  61. package/src/presets/base/templates/ja/guardrail.md +20 -0
  62. package/src/presets/base/templates/ja/layout.md +10 -0
  63. package/src/presets/base/templates/ja/overview.md +22 -18
  64. package/src/presets/base/templates/ja/project_structure.md +21 -19
  65. package/src/presets/base/templates/ja/stack_and_ops.md +22 -18
  66. package/src/presets/cakephp2/data/{shells.js → commands.js} +12 -12
  67. package/src/presets/cakephp2/data/config.js +2 -2
  68. package/src/presets/cakephp2/preset.json +1 -1
  69. package/src/presets/cakephp2/scan/{shells-detail.js → commands-detail.js} +9 -8
  70. package/src/presets/cakephp2/templates/en/auth_and_session.md +42 -0
  71. package/src/presets/cakephp2/templates/en/business_logic.md +16 -0
  72. package/src/presets/cakephp2/templates/en/commands.md +16 -0
  73. package/src/presets/cakephp2/templates/en/controller_routes.md +19 -0
  74. package/src/presets/cakephp2/templates/en/database_architecture.md +11 -0
  75. package/src/presets/cakephp2/templates/en/db_tables.md +16 -0
  76. package/src/presets/cakephp2/templates/en/development.md +46 -0
  77. package/src/presets/cakephp2/templates/en/guardrail.md +8 -0
  78. package/src/presets/cakephp2/templates/en/project_structure.md +31 -0
  79. package/src/presets/cakephp2/templates/en/stack_and_ops.md +43 -0
  80. package/src/presets/cakephp2/templates/ja/auth_and_session.md +23 -3
  81. package/src/presets/cakephp2/templates/ja/business_logic.md +16 -0
  82. package/src/presets/cakephp2/templates/ja/commands.md +16 -0
  83. package/src/presets/cakephp2/templates/ja/controller_routes.md +13 -7
  84. package/src/presets/cakephp2/templates/ja/database_architecture.md +11 -0
  85. package/src/presets/cakephp2/templates/ja/db_tables.md +6 -12
  86. package/src/presets/cakephp2/templates/ja/development.md +13 -17
  87. package/src/presets/cakephp2/templates/ja/guardrail.md +8 -0
  88. package/src/presets/cakephp2/templates/ja/project_structure.md +13 -21
  89. package/src/presets/cakephp2/templates/ja/stack_and_ops.md +18 -23
  90. package/src/presets/ci/data/pipelines.js +89 -0
  91. package/src/presets/ci/preset.json +15 -0
  92. package/src/presets/ci/scan/workflows.js +289 -0
  93. package/src/presets/ci/templates/en/ci_cd.md +27 -0
  94. package/src/presets/ci/templates/ja/ci_cd.md +27 -0
  95. package/src/presets/cli/data/commands.js +52 -0
  96. package/src/presets/cli/preset.json +1 -1
  97. package/src/presets/cli/templates/en/README.md +12 -14
  98. package/src/presets/cli/templates/en/commands.md +22 -27
  99. package/src/presets/cli/templates/en/config.md +19 -18
  100. package/src/presets/cli/templates/en/guardrail.md +6 -0
  101. package/src/presets/cli/templates/ja/README.md +12 -14
  102. package/src/presets/cli/templates/ja/commands.md +22 -27
  103. package/src/presets/cli/templates/ja/config.md +19 -18
  104. package/src/presets/cli/templates/ja/guardrail.md +6 -0
  105. package/src/presets/database/data/schema.js +36 -0
  106. package/src/presets/database/preset.json +8 -0
  107. package/src/presets/database/templates/en/database.md +16 -0
  108. package/src/presets/database/templates/ja/database.md +16 -0
  109. package/src/presets/drizzle/data/schema.js +128 -0
  110. package/src/presets/drizzle/preset.json +21 -0
  111. package/src/presets/drizzle/scan/schema.js +114 -0
  112. package/src/presets/drizzle/templates/en/database.md +11 -0
  113. package/src/presets/drizzle/templates/en/schema.md +20 -0
  114. package/src/presets/drizzle/templates/ja/database.md +11 -0
  115. package/src/presets/drizzle/templates/ja/schema.md +20 -0
  116. package/src/presets/edge/data/runtime.js +93 -0
  117. package/src/presets/edge/preset.json +8 -0
  118. package/src/presets/edge/templates/en/edge_runtime.md +20 -0
  119. package/src/presets/edge/templates/ja/edge_runtime.md +20 -0
  120. package/src/presets/graphql/data/schema.js +119 -0
  121. package/src/presets/graphql/preset.json +18 -0
  122. package/src/presets/graphql/scan/schema.js +108 -0
  123. package/src/presets/graphql/templates/en/api_overview.md +8 -0
  124. package/src/presets/graphql/templates/en/authentication.md +15 -0
  125. package/src/presets/graphql/templates/en/schema.md +27 -0
  126. package/src/presets/graphql/templates/ja/api_overview.md +8 -0
  127. package/src/presets/graphql/templates/ja/authentication.md +15 -0
  128. package/src/presets/graphql/templates/ja/schema.md +27 -0
  129. package/src/presets/hono/data/middleware.js +37 -0
  130. package/src/presets/hono/preset.json +19 -0
  131. package/src/presets/hono/scan/middleware.js +68 -0
  132. package/src/presets/hono/templates/en/middleware.md +13 -0
  133. package/src/presets/hono/templates/ja/middleware.md +13 -0
  134. package/src/presets/js-webapp/preset.json +24 -0
  135. package/src/presets/laravel/data/commands.js +8 -14
  136. package/src/presets/laravel/preset.json +1 -1
  137. package/src/presets/laravel/scan/config.js +108 -0
  138. package/src/presets/laravel/scan/routes.js +62 -5
  139. package/src/presets/laravel/templates/en/auth_and_session.md +29 -0
  140. package/src/presets/laravel/templates/en/controller_routes.md +34 -0
  141. package/src/presets/laravel/templates/en/db_tables.md +16 -0
  142. package/src/presets/laravel/templates/en/guardrail.md +8 -0
  143. package/src/presets/laravel/templates/en/project_structure.md +13 -0
  144. package/src/presets/laravel/templates/en/stack_and_ops.md +34 -0
  145. package/src/presets/laravel/templates/ja/auth_and_session.md +13 -13
  146. package/src/presets/laravel/templates/ja/controller_routes.md +18 -28
  147. package/src/presets/laravel/templates/ja/db_tables.md +10 -16
  148. package/src/presets/laravel/templates/ja/guardrail.md +8 -0
  149. package/src/presets/laravel/templates/ja/project_structure.md +7 -7
  150. package/src/presets/laravel/templates/ja/stack_and_ops.md +15 -23
  151. package/src/presets/library/preset.json +1 -1
  152. package/src/presets/library/templates/en/README.md +16 -0
  153. package/src/presets/library/templates/en/guardrail.md +4 -0
  154. package/src/presets/library/templates/en/public_api.md +34 -0
  155. package/src/presets/library/templates/en/usage.md +41 -0
  156. package/src/presets/library/templates/ja/README.md +5 -7
  157. package/src/presets/library/templates/ja/guardrail.md +4 -0
  158. package/src/presets/library/templates/ja/public_api.md +16 -15
  159. package/src/presets/library/templates/ja/usage.md +19 -18
  160. package/src/presets/monorepo/data/monorepo.js +80 -0
  161. package/src/presets/monorepo/preset.json +6 -0
  162. package/src/presets/nextjs/data/components.js +103 -0
  163. package/src/presets/nextjs/data/routes.js +187 -0
  164. package/src/presets/nextjs/preset.json +35 -0
  165. package/src/presets/nextjs/scan/components.js +53 -0
  166. package/src/presets/nextjs/scan/routes.js +175 -0
  167. package/src/presets/nextjs/templates/en/components.md +27 -0
  168. package/src/presets/nextjs/templates/en/middleware.md +13 -0
  169. package/src/presets/nextjs/templates/en/pages_routing.md +27 -0
  170. package/src/presets/nextjs/templates/en/route_handlers.md +13 -0
  171. package/src/presets/nextjs/templates/ja/components.md +27 -0
  172. package/src/presets/nextjs/templates/ja/middleware.md +13 -0
  173. package/src/presets/nextjs/templates/ja/pages_routing.md +27 -0
  174. package/src/presets/nextjs/templates/ja/route_handlers.md +13 -0
  175. package/src/presets/node-cli/preset.json +3 -1
  176. package/src/presets/node-cli/templates/en/README.md +9 -9
  177. package/src/presets/node-cli/templates/en/cli_commands.md +9 -8
  178. package/src/presets/node-cli/templates/en/configuration.md +9 -8
  179. package/src/presets/node-cli/templates/en/development_testing.md +10 -9
  180. package/src/presets/node-cli/templates/en/guardrail.md +4 -0
  181. package/src/presets/node-cli/templates/en/internal_design.md +10 -9
  182. package/src/presets/node-cli/templates/en/overview.md +9 -8
  183. package/src/presets/node-cli/templates/ja/README.md +9 -9
  184. package/src/presets/node-cli/templates/ja/cli_commands.md +9 -8
  185. package/src/presets/node-cli/templates/ja/configuration.md +9 -8
  186. package/src/presets/node-cli/templates/ja/development_testing.md +10 -9
  187. package/src/presets/node-cli/templates/ja/guardrail.md +4 -0
  188. package/src/presets/node-cli/templates/ja/internal_design.md +10 -9
  189. package/src/presets/node-cli/templates/ja/overview.md +9 -8
  190. package/src/presets/php-webapp/preset.json +10 -0
  191. package/src/presets/postgres/data/database.js +19 -0
  192. package/src/presets/postgres/preset.json +6 -0
  193. package/src/presets/postgres/templates/en/database.md +9 -0
  194. package/src/presets/postgres/templates/ja/database.md +9 -0
  195. package/src/presets/principle/preset.json +5 -0
  196. package/src/presets/r2/data/storage.js +69 -0
  197. package/src/presets/r2/preset.json +8 -0
  198. package/src/presets/r2/templates/en/storage.md +11 -0
  199. package/src/presets/r2/templates/ja/storage.md +11 -0
  200. package/src/presets/rest/preset.json +14 -0
  201. package/src/presets/rest/templates/en/api_overview.md +8 -0
  202. package/src/presets/rest/templates/en/authentication.md +15 -0
  203. package/src/presets/rest/templates/en/endpoints.md +20 -0
  204. package/src/presets/rest/templates/ja/api_overview.md +8 -0
  205. package/src/presets/rest/templates/ja/authentication.md +15 -0
  206. package/src/presets/rest/templates/ja/endpoints.md +20 -0
  207. package/src/presets/storage/data/buckets.js +22 -0
  208. package/src/presets/storage/preset.json +8 -0
  209. package/src/presets/storage/templates/en/storage.md +20 -0
  210. package/src/presets/storage/templates/ja/storage.md +20 -0
  211. package/src/presets/symfony/data/commands.js +8 -14
  212. package/src/presets/symfony/preset.json +1 -1
  213. package/src/presets/symfony/scan/controllers.js +4 -6
  214. package/src/presets/symfony/scan/php-attributes.js +72 -0
  215. package/src/presets/symfony/scan/routes.js +4 -6
  216. package/src/presets/symfony/templates/en/auth_and_session.md +29 -0
  217. package/src/presets/symfony/templates/en/business_logic.md +10 -0
  218. package/src/presets/symfony/templates/en/controller_routes.md +32 -0
  219. package/src/presets/symfony/templates/en/db_tables.md +21 -0
  220. package/src/presets/symfony/templates/en/guardrail.md +8 -0
  221. package/src/presets/symfony/templates/en/project_structure.md +13 -0
  222. package/src/presets/symfony/templates/en/stack_and_ops.md +34 -0
  223. package/src/presets/symfony/templates/ja/auth_and_session.md +13 -13
  224. package/src/presets/symfony/templates/ja/business_logic.md +10 -0
  225. package/src/presets/symfony/templates/ja/controller_routes.md +16 -26
  226. package/src/presets/symfony/templates/ja/db_tables.md +13 -21
  227. package/src/presets/symfony/templates/ja/guardrail.md +8 -0
  228. package/src/presets/symfony/templates/ja/project_structure.md +7 -7
  229. package/src/presets/symfony/templates/ja/stack_and_ops.md +15 -23
  230. package/src/presets/web-design/NOTICE +10 -0
  231. package/src/presets/web-design/preset.json +5 -0
  232. package/src/presets/web-design/templates/en/guardrail.md +34 -0
  233. package/src/presets/web-design/templates/ja/guardrail.md +34 -0
  234. package/src/presets/webapp/data/{shells.js → commands.js} +9 -12
  235. package/src/presets/webapp/preset.json +2 -2
  236. package/src/presets/webapp/templates/en/README.md +22 -0
  237. package/src/presets/webapp/templates/en/auth_and_session.md +47 -0
  238. package/src/presets/webapp/templates/en/business_logic.md +45 -0
  239. package/src/presets/webapp/templates/en/commands.md +42 -0
  240. package/src/presets/webapp/templates/en/controller_routes.md +49 -0
  241. package/src/presets/webapp/templates/en/database_architecture.md +41 -0
  242. package/src/presets/webapp/templates/en/db_tables.md +29 -0
  243. package/src/presets/webapp/templates/en/guardrail.md +10 -0
  244. package/src/presets/webapp/templates/ja/README.md +7 -9
  245. package/src/presets/webapp/templates/ja/auth_and_session.md +23 -22
  246. package/src/presets/webapp/templates/ja/business_logic.md +23 -24
  247. package/src/presets/webapp/templates/ja/commands.md +42 -0
  248. package/src/presets/webapp/templates/ja/controller_routes.md +25 -26
  249. package/src/presets/webapp/templates/ja/database_architecture.md +21 -20
  250. package/src/presets/webapp/templates/ja/db_tables.md +15 -18
  251. package/src/presets/webapp/templates/ja/guardrail.md +10 -0
  252. package/src/presets/workers/data/bindings.js +84 -0
  253. package/src/presets/workers/preset.json +23 -0
  254. package/src/presets/workers/scan/bindings.js +129 -0
  255. package/src/presets/workers/templates/en/bindings.md +20 -0
  256. package/src/presets/workers/templates/en/edge_runtime.md +11 -0
  257. package/src/presets/workers/templates/ja/bindings.md +20 -0
  258. package/src/presets/workers/templates/ja/edge_runtime.md +11 -0
  259. package/src/presets-cmd.js +48 -33
  260. package/src/setup.js +352 -352
  261. package/src/spec/commands/gate.js +9 -12
  262. package/src/spec/commands/guardrail.js +276 -63
  263. package/src/spec/commands/init.js +9 -3
  264. package/src/spec/commands/lint.js +164 -0
  265. package/src/spec.js +1 -0
  266. package/src/templates/skills/sdd-forge.flow-finalize/SKILL.en.md +248 -0
  267. package/src/templates/skills/sdd-forge.flow-finalize/SKILL.ja.md +248 -0
  268. package/src/templates/skills/sdd-forge.flow-impl/SKILL.en.md +166 -0
  269. package/src/templates/skills/sdd-forge.flow-impl/SKILL.ja.md +166 -0
  270. package/src/templates/skills/sdd-forge.flow-plan/SKILL.en.md +273 -0
  271. package/src/templates/skills/sdd-forge.flow-plan/{SKILL.md → SKILL.ja.md} +70 -51
  272. package/src/templates/skills/sdd-forge.flow-resume/{SKILL.md → SKILL.en.md} +2 -1
  273. package/src/templates/skills/sdd-forge.flow-resume/SKILL.ja.md +34 -0
  274. package/src/templates/skills/sdd-forge.flow-status/{SKILL.md → SKILL.en.md} +4 -4
  275. package/src/templates/skills/sdd-forge.flow-status/SKILL.ja.md +94 -0
  276. package/src/templates/skills/sdd-forge.flow-sync/SKILL.en.md +42 -0
  277. package/src/templates/skills/sdd-forge.flow-sync/SKILL.ja.md +42 -0
  278. package/src/upgrade.js +3 -98
  279. package/src/README.md +0 -201
  280. package/src/presets/node-cli/templates/ja/commands.md +0 -2
  281. package/src/presets/node-cli/templates/ja/config.md +0 -2
  282. package/src/presets/node-cli/templates/ja/development.md +0 -2
  283. package/src/presets/node-cli/templates/ja/project_structure.md +0 -2
  284. package/src/presets/node-cli/templates/ja/stack_and_ops.md +0 -2
  285. package/src/presets/webapp/templates/ja/batch_and_shell.md +0 -43
  286. package/src/templates/skills/sdd-forge.flow-impl/SKILL.md +0 -148
  287. package/src/templates/skills/sdd-forge.flow-merge/SKILL.md +0 -178
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # <!-- {{data: project.name("")}} -->sdd-forge<!-- {{/data}} -->
1
+ # <!-- {{data("cli.project.name")}} -->sdd-forge<!-- {{/data}} -->
2
2
 
3
- <!-- {{data: docs.langSwitcher("absolute")}} -->
3
+ <!-- {{data("cli.docs.langSwitcher", {labels: "absolute"})}} -->
4
4
  **English** | [日本語](https://github.com/SpreadWorks/sdd-forge/blob/main/docs/ja/README.md)
5
5
  <!-- {{/data}} -->
6
6
 
@@ -54,13 +54,13 @@ Documentation is automatically refreshed during the merge phase, so docs and cod
54
54
  ### Install
55
55
 
56
56
  <pre>
57
- npm install -g <!-- {{data: project.name("")}} -->sdd-forge<!-- {{/data}} -->
57
+ npm install -g <!-- {{data("cli.project.name")}} -->sdd-forge<!-- {{/data}} -->
58
58
  </pre>
59
59
 
60
60
  ### Setup
61
61
 
62
62
  <pre>
63
- <!-- {{data: project.name("")}} -->sdd-forge<!-- {{/data}} --> setup
63
+ <!-- {{data("cli.project.name")}} -->sdd-forge<!-- {{/data}} --> setup
64
64
  </pre>
65
65
 
66
66
  An interactive wizard configures your project type (preset) and AI agent.
@@ -70,7 +70,7 @@ An interactive wizard configures your project type (preset) and AI agent.
70
70
  If you already have source code, generate documentation to get a complete picture of the system. Especially useful for onboarding onto legacy codebases.
71
71
 
72
72
  <pre>
73
- <!-- {{data: project.name("")}} -->sdd-forge<!-- {{/data}} --> docs build
73
+ <!-- {{data("cli.project.name")}} -->sdd-forge<!-- {{/data}} --> docs build
74
74
  </pre>
75
75
 
76
76
  ### Develop with the SDD flow
@@ -123,13 +123,14 @@ See the [configuration reference](docs/configuration.md) for details.
123
123
 
124
124
  ## Documentation
125
125
 
126
- <!-- {{data: docs.chapters("Chapter|Summary")}} -->
126
+ <!-- {{data("cli.docs.chapters", {header: "", labels: "Chapter|Summary", ignoreError: true})}} -->
127
127
  | Chapter | Summary |
128
128
  | --- | --- |
129
- | [01. Tool Overview and Architecture](https://github.com/SpreadWorks/sdd-forge/blob/main/docs/overview.md) | This chapter introduces sdd-forge, a CLI tool for Spec-Driven Development that automates technical documentation gene… |
130
- | [02. CLI Command Reference](https://github.com/SpreadWorks/sdd-forge/blob/main/docs/cli_commands.md) | sdd-forge provides over 20 CLI commands organized into four namespaces (`docs`, `spec`, `flow`, and standalone comman… |
131
- | [03. Configuration and Customization](https://github.com/SpreadWorks/sdd-forge/blob/main/docs/configuration.md) | sdd-forge uses a layered configuration system centered on `.sdd-forge/config.json`, supplemented by preset manifests … |
132
- | [04. Internal Design](https://github.com/SpreadWorks/sdd-forge/blob/main/docs/internal_design.md) | This chapter describes sdd-forge's internal architecture: the three-layer directory structure under `src/`, the depen… |
129
+ | [Tool Overview and Architecture](https://github.com/SpreadWorks/sdd-forge/blob/main/docs/overview.md) | sdd-forge is a CLI tool that automates technical documentation generation through source code analysis and provides a… |
130
+ | [Technology Stack and Operations](https://github.com/SpreadWorks/sdd-forge/blob/main/docs/stack_and_ops.md) | sdd-forge is a CLI tool built entirely in JavaScript on Node.js, using ES modules with zero external dependencies. |
131
+ | [Project Structure](https://github.com/SpreadWorks/sdd-forge/blob/main/docs/project_structure.md) | The project consists of 1 top-level source directory (src/) containing 157 files across 5 major areas: CLI entry poin… |
132
+ | [CLI Command Reference](https://github.com/SpreadWorks/sdd-forge/blob/main/docs/cli_commands.md) | sdd-forge provides over 25 CLI commands organized into four namespaces docs (12 subcommands), spec (4 subcommands),… |
133
+ | [Configuration and Customization](https://github.com/SpreadWorks/sdd-forge/blob/main/docs/configuration.md) | sdd-forge uses two primary configuration files — .sdd-forge/config.json for project-specific settings and preset.json… |
133
134
  <!-- {{/data}} -->
134
135
 
135
136
  ## License
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdd-forge",
3
- "version": "0.1.0-alpha.32",
3
+ "version": "0.1.0-alpha.361",
4
4
  "description": "Spec-Driven Development tooling for automated documentation generation",
5
5
  "repository": {
6
6
  "type": "git",
@@ -11,7 +11,8 @@
11
11
  "sdd-forge": "./src/sdd-forge.js"
12
12
  },
13
13
  "files": [
14
- "src/"
14
+ "src/",
15
+ "!src/presets/*/tests/"
15
16
  ],
16
17
  "engines": {
17
18
  "node": ">=18.0.0"
@@ -24,7 +25,10 @@
24
25
  "technical-docs"
25
26
  ],
26
27
  "scripts": {
27
- "test": "find tests -name '*.test.js' | xargs node --test"
28
+ "test": "node tests/run.js",
29
+ "test:unit": "node tests/run.js --scope unit",
30
+ "test:e2e": "node tests/run.js --scope e2e",
31
+ "test:acceptance": "node tests/acceptance/run.js"
28
32
  },
29
33
  "license": "MIT"
30
34
  }
package/src/AGENTS.md ADDED
@@ -0,0 +1,420 @@
1
+ # sdd-forge — 内部アーキテクチャとルール
2
+
3
+ このドキュメントは `src/` 配下のコード(npm パッケージとして配布される)の開発ルールを定義する。
4
+
5
+ ## プロジェクト概要
6
+
7
+ - **パッケージ:** `sdd-forge`
8
+ - **説明:** ソースコード解析に基づくドキュメント自動生成と SDD ワークフローを提供する CLI ツール
9
+ - **モジュール形式:** ES Modules (`"type": "module"`)
10
+ - **ランタイム:** Node.js >= 18.0.0
11
+ - **外部依存:** なし(Node.js 組み込みモジュールのみ)
12
+ - **エントリポイント:** `./src/sdd-forge.js`
13
+
14
+ ## ディレクトリ構造
15
+
16
+ ```
17
+ src/
18
+ ├── sdd-forge.js CLI エントリポイント(トップレベルディスパッチャ)
19
+ ├── docs.js docs ディスパッチャ
20
+ ├── spec.js spec ディスパッチャ
21
+ ├── flow.js flow ディスパッチャ
22
+ ├── setup.js / upgrade.js / presets-cmd.js / help.js 独立コマンド
23
+ ├── lib/ 全レイヤー共有ユーティリティ
24
+ │ ├── cli.js repoRoot, sourceRoot, parseArgs, PKG_DIR
25
+ │ ├── config.js .sdd-forge/config.json ローダー
26
+ │ ├── agent.js AI エージェント呼び出し
27
+ │ ├── presets.js プリセット自動探索・親チェーン解決
28
+ │ ├── flow-state.js SDD フロー状態永続化
29
+ │ ├── i18n.js 3層 i18n(ドメイン名前空間付き)
30
+ │ └── types.js 型エイリアス解決・バリデーション
31
+ ├── docs/
32
+ │ ├── commands/ scan, enrich, init, data, text, readme,
33
+ │ │ forge, review, changelog, agents, translate
34
+ │ ├── data/ 共通 DataSource(project, docs, lang, agents)
35
+ │ └── lib/ ドキュメント生成エンジン
36
+ ├── flow/commands/ start, status, review, merge, resume, cleanup
37
+ ├── spec/commands/ init, gate, guardrail
38
+ ├── presets/ プリセット群(後述)
39
+ ├── locale/ en/, ja/
40
+ └── templates/ スキャフォールドテンプレート
41
+ ```
42
+
43
+ ## コマンドルーティング
44
+
45
+ 3段階ディスパッチ: `sdd-forge.js` → `docs.js`/`spec.js`/`flow.js` → `commands/*.js`
46
+
47
+ ```
48
+ sdd-forge <cmd> [args]
49
+
50
+ ├─ sdd-forge.js # 1. プロジェクトコンテキスト解決 + ディスパッチ
51
+ │ ├─ docs.js # 2. docs サブコマンドのルーティング
52
+ │ │ └─ docs/commands/*.js # 3. 実際のコマンド実装
53
+ │ ├─ spec.js # 2. spec サブコマンドのルーティング
54
+ │ │ └─ spec/commands/*.js
55
+ │ ├─ flow.js # 2+3. 直接実行(ディスパッチャなし)
56
+ │ └─ help.js # 2+3. 直接実行
57
+ ```
58
+
59
+ ### プロジェクトコンテキスト
60
+
61
+ `sdd-forge.js` は実行時に以下の環境変数を設定する:
62
+
63
+ | 環境変数 | 意味 | 設定元 |
64
+ |---|---|---|
65
+ | `SDD_SOURCE_ROOT` | 対象プロジェクトのソースコードルート | `cli.js` で解決 |
66
+ | `SDD_WORK_ROOT` | 作業ディレクトリ(`.sdd-forge/`, `docs/` の親) | `cli.js` で解決 |
67
+
68
+ ### ドキュメント生成パイプライン
69
+
70
+ `sdd-forge docs build` は以下のパイプラインを順に実行する:
71
+
72
+ ```
73
+ scan → enrich → init → data → text → readme → agents → [translate]
74
+ ```
75
+
76
+ | ステップ | 役割 |
77
+ |---|---|
78
+ | **scan** | ソースコードをスキャンし analysis.json を生成 |
79
+ | **enrich** | AI で analysis エントリーに summary/chapter/role を付与 |
80
+ | **init** | テンプレートを継承チェーンでマージし docs/ に出力 |
81
+ | **data** | `{{data}}` ディレクティブを analysis データで置換 |
82
+ | **text** | `{{text}}` ディレクティブを AI 生成テキストで埋める |
83
+ | **readme** | README.md を生成 |
84
+ | **agents** | AGENTS.md を生成 |
85
+
86
+ ---
87
+
88
+ ## プリセットシステム
89
+
90
+ ### 概要
91
+
92
+ プリセットはフレームワーク固有のスキャン設定・DataSource・テンプレートをパッケージ化する。
93
+ `parent` フィールドによる単一継承チェーンで構成される。
94
+
95
+ ```
96
+ base → webapp → js-webapp → hono
97
+ base → webapp → js-webapp → nextjs
98
+ base → webapp → php-webapp → cakephp2
99
+ base → webapp → php-webapp → laravel
100
+ base → webapp → php-webapp → symfony
101
+ base → cli → node-cli
102
+ base → library
103
+ base → database → drizzle
104
+ base → edge → workers
105
+ base → storage → r2
106
+ base → api → rest
107
+ base → api → graphql
108
+ ```
109
+
110
+ ### preset.json の構造
111
+
112
+ ```json
113
+ {
114
+ "parent": "webapp",
115
+ "label": "CakePHP 2.x",
116
+ "aliases": [],
117
+ "chapters": ["overview.md", "stack_and_ops.md", ...],
118
+ "scan": {
119
+ "include": ["app/**/*.php"],
120
+ "exclude": ["vendor/**"]
121
+ }
122
+ }
123
+ ```
124
+
125
+ | フィールド | 説明 |
126
+ |---|---|
127
+ | `parent` | 親プリセットの key(継承チェーン) |
128
+ | `label` | 表示名 |
129
+ | `chapters` | このプリセットの章順序(子は親の chapters を上書き) |
130
+ | `scan.include` | スキャン対象の glob パターン |
131
+ | `scan.exclude` | 除外パターン |
132
+
133
+ ### プリセットディレクトリ構成
134
+
135
+ ```
136
+ presets/<key>/
137
+ ├── preset.json プリセット定義
138
+ ├── data/ DataSource クラス群
139
+ │ ├── config.js 設定解析
140
+ │ ├── controllers.js コントローラ解析
141
+ │ └── ...
142
+ ├── scan/ scan パーサー群
143
+ │ ├── routes.js ルート解析
144
+ │ ├── config.js 設定解析
145
+ │ └── ...
146
+ ├── tests/ プリセット固有テスト
147
+ │ ├── unit/ ユニットテスト(scan パーサー I/O テスト等)
148
+ │ └── e2e/ E2E テスト(統合スキャンテスト等)
149
+ └── templates/ 章テンプレート
150
+ ├── ja/
151
+ │ ├── overview.md
152
+ │ ├── stack_and_ops.md
153
+ │ └── ...
154
+ └── en/
155
+ └── ...
156
+ ```
157
+
158
+ ---
159
+
160
+ ## プリセット作成ルール
161
+
162
+ ### MUST: プリセット作成手順(トップダウン設計)
163
+
164
+ プリセットの構成要素は以下の順序で作成すること:
165
+
166
+ 1. **テンプレート** (`templates/`) — どんなドキュメントを出力するか定義する
167
+ 2. **DataSource** (`data/`) — テンプレートが必要とするデータを定義する
168
+ 3. **scan パーサー** (`scan/`) — DataSource にデータを供給するパーサーを実装する
169
+
170
+ 消費者(テンプレート)→ 仲介者(DataSource)→ 生産者(scan)の順に作ることで、不要なパーサーを書かず、必要なデータの漏れがなくなる。
171
+
172
+ ### MUST: プリセットテストの作成
173
+
174
+ プリセットは `tests/` ディレクトリを含むこと。
175
+
176
+ - `tests/unit/` — scan パーサーの I/O テスト。最小限のフィクスチャを `createTmpDir()` で作成し、パーサー関数の入出力を検証する
177
+ - `tests/e2e/` — preset.json の scan 設定検証、フルスキャンパイプラインテスト
178
+ - `npm test -- --preset <name>` でプリセット毎のテストを実行できること
179
+ - テストファイルは npm パッケージには含まれない(package.json の `files` で除外済み)
180
+
181
+ ### MUST: scan DataSource と data DataSource の対応
182
+
183
+ **data DataSource が `analysis.X` を読むなら、チェーン内に `X` を書く scan DataSource が必要。**
184
+
185
+ - scan DataSource は `match(file)` + `scan(files)` メソッドを持ち、ファイルを解析して `analysis[name]` に書き込む
186
+ - data DataSource は `analysis[key]` を読んでマークダウンテーブルを生成する
187
+ - この2つは対であるべき
188
+ - scan DataSource を実装できるなら実装する(フレームワーク固有の scan は子プリセットで実装する)
189
+ - scan DataSource を実装できない場合は、data DataSource も作ってはならない。テンプレートは `{{text}}` にする
190
+ - **data DataSource だけが存在し、対応する scan DataSource がない状態はルール違反**
191
+
192
+ ```
193
+ ✅ 正しい例:
194
+ scan DataSource "modules" → analysis.modules に書き込む
195
+ data DataSource modules.list() → analysis.modules を読む
196
+
197
+ ❌ 間違い:
198
+ data DataSource schema.tables() → analysis.schemas を読む
199
+ → analysis.schemas を書く scan DataSource がどこにもない
200
+ ```
201
+
202
+ ### MUST: `{{data}}` と `{{text}}` の使い分け
203
+
204
+ | 条件 | ディレクティブ |
205
+ |---|---|
206
+ | scan で構造的に収集できるデータ | `{{data("preset.source.method")}}` |
207
+ | scan で収集不可(フレームワーク固有すぎる) | `{{text({prompt: "..."})}}` |
208
+
209
+ **判断基準**: そのデータを正規表現やパーサーで機械的に抽出できるか?
210
+ - YES → `{{data}}`(テーブル形式で正確なデータを提供)
211
+ - NO → `{{text}}`(AI がソースコードと analysis コンテキストから文章を生成)
212
+
213
+ ### MUST: 親テンプレートは `{{text}}`、子が `{{data}}` で override
214
+
215
+ フレームワーク固有のデータを表示する箇所は、親(webapp 等)テンプレートでは `{{text}}` + `{%block%}` で定義し、子プリセットが block override で `{{data}}` に差し替える。
216
+
217
+ ```markdown
218
+ <!-- webapp/templates/ja/auth_and_session.md -->
219
+ <!-- {%block "auth_config"%} -->
220
+ <!-- {{text({prompt: "認証設定を説明してください。"})}} -->
221
+ <!-- {{/text}} -->
222
+ <!-- {%/block%} -->
223
+ ```
224
+
225
+ ```markdown
226
+ <!-- cakephp2/templates/ja/auth_and_session.md -->
227
+ <!-- {%extends%} -->
228
+ <!-- {%block "auth_config"%} -->
229
+ <!-- {{data("cakephp2.config.auth", {labels: "項目|内容"})}} -->
230
+ <!-- {{/data}} -->
231
+ <!-- {%/block%} -->
232
+ ```
233
+
234
+ これにより:
235
+ - webapp 単体: AI が文章を生成(scan データがなくても動く)
236
+ - cakephp2: scan データから正確なテーブルを出力
237
+ - 将来のプリセット: override テンプレートを追加するだけ
238
+
239
+ ### MUST: enrich は静的収集データの加工に留める
240
+
241
+ enrich フェーズは scan が収集したエントリーへのメタデータ付与(summary, chapter, role)のみを行う。
242
+ 新しい analysis カテゴリの生成や、scan が見つけていないデータの創出は行わない。
243
+
244
+ ### DataSource の2種類
245
+
246
+ **1. Scannable DataSource(scan + data 兼用)**
247
+
248
+ ```javascript
249
+ import { Scannable } from "../../../docs/lib/scan-source.js";
250
+ import { DataSource } from "../../../docs/lib/data-source.js";
251
+
252
+ export default class ModulesSource extends Scannable(DataSource) {
253
+ match(file) { return file.ext === ".js"; }
254
+ scan(files) { return { modules: [...], summary: { total: files.length } }; }
255
+ list(analysis, labels) { /* analysis.modules を読んでテーブル生成 */ }
256
+ }
257
+ ```
258
+
259
+ - `match(file)`: このソースが処理すべきファイルか判定
260
+ - `scan(files)`: マッチしたファイルを解析し、analysis に書き込むデータを返す
261
+ - その他メソッド: data コマンドで呼ばれ、analysis を読んでマークダウンを返す
262
+
263
+ **2. Data-only DataSource(data 専用)**
264
+
265
+ ```javascript
266
+ import { DataSource } from "../../../docs/lib/data-source.js";
267
+
268
+ export default class SchemaSource extends DataSource {
269
+ tables(analysis, labels) { /* analysis.schemas.tables を読んでテーブル生成 */ }
270
+ }
271
+ ```
272
+
273
+ - `scan()` / `match()` を持たない
274
+ - analysis にデータがあれば動作する(なければ null を返す)
275
+ - **MUST**: このパターンを使う場合、読む analysis キーを書く scan DataSource がチェーン内に存在する必要がある。対応する scan がないなら data DataSource を作ってはならない
276
+
277
+ ---
278
+
279
+ ## テンプレート構文
280
+
281
+ ### ディレクティブ
282
+
283
+ **出力ディレクティブ** (`{{ }}`):
284
+
285
+ ```html
286
+ <!-- {{data("preset.source.method", {labels: "ヘッダ1|ヘッダ2"})}} -->
287
+ <!-- {{/data}} -->
288
+
289
+ <!-- {{text({prompt: "説明を書いてください。", mode: "deep"})}} -->
290
+ <!-- {{/text}} -->
291
+ ```
292
+
293
+ **制御ディレクティブ** (`{% %}`):
294
+
295
+ ```html
296
+ <!-- {%extends "layout"%} -->
297
+
298
+ <!-- {%block "content"%} -->
299
+ ...
300
+ <!-- {%/block%} -->
301
+ ```
302
+
303
+ ### テンプレート継承
304
+
305
+ `{%extends%}` で親テンプレートのブロックを継承・上書きする。
306
+
307
+ ```
308
+ layout.md(レイアウト)
309
+ └─ overview.md({%extends "layout"%} で継承)
310
+ └─ cakephp2/overview.md({%extends%} で override)
311
+ ```
312
+
313
+ **layout.md のナビゲーション**: layout を extends するテンプレートは自動的にナビゲーション(前後章リンク)が付与される。extends しないテンプレートにはナビが付かない。
314
+
315
+ ### block のネスト
316
+
317
+ block は入れ子にできる。親ブロック内にネストされたブロックは、子テンプレートで個別に override 可能。
318
+
319
+ ```markdown
320
+ <!-- {%block "content"%} -->
321
+ ## 見出し
322
+ <!-- {%block "section_a"%} -->
323
+ セクション A の内容
324
+ <!-- {%/block%} -->
325
+ <!-- {%block "section_b"%} -->
326
+ セクション B の内容
327
+ <!-- {%/block%} -->
328
+ <!-- {%/block%} -->
329
+ ```
330
+
331
+ ---
332
+
333
+ ## コーディングルール
334
+
335
+ ### プロジェクト固有情報の埋め込み禁止
336
+
337
+ `src/` 配下のコードおよびテンプレートに、特定プロジェクトの情報を直接書いてはならない。
338
+
339
+ - **禁止**: プロジェクト名、ホスト名、ポート番号、コンテナ名、固有 DB 名
340
+ - **許可**: `presets/` 配下のフレームワーク固有ロジック(汎用的な解析パターン)
341
+ - **設定**: プロジェクト固有の値は `.sdd-forge/config.json` で外部化する
342
+
343
+ ### 外部依存の禁止
344
+
345
+ Node.js 組み込み API (`fs`, `path`, `child_process`, `url` 等) のみを使用する。
346
+ npm パッケージへの依存を追加しないこと。
347
+
348
+ ### フォールバック値の抑制
349
+
350
+ 必須の設定値・環境変数が不足している場合は、黙ってデフォルト値で動作させず、エラーメッセージを出力して停止すること。
351
+
352
+ ### コマンドファイルの構造
353
+
354
+ `commands/` 配下のファイルは以下のパターンに従う:
355
+
356
+ ```javascript
357
+ import { runIfDirect } from "../../lib/entrypoint.js";
358
+ import { parseArgs } from "../../lib/cli.js";
359
+ import { resolveCommandContext } from "../lib/command-context.js";
360
+
361
+ async function main(ctx) {
362
+ if (!ctx) {
363
+ const cli = parseArgs(process.argv.slice(2), { ... });
364
+ if (cli.help) { printHelp(); return; }
365
+ ctx = resolveCommandContext(cli);
366
+ }
367
+ // 実装
368
+ }
369
+
370
+ export { main };
371
+ runIfDirect(import.meta.url, main);
372
+ ```
373
+
374
+ ### AI エージェント呼び出し (`lib/agent.js`)
375
+
376
+ **非同期呼び出しで `execFile` を使ってはならない。**
377
+
378
+ `child_process.spawn` を使い、`stdio: ["ignore", "pipe", "pipe"]` を明示する。
379
+ `execFile` は stdin を pipe モードで開くが、Claude CLI は stdin が pipe だと EOF を待ち続けてハングする。
380
+
381
+ ```javascript
382
+ // NG: execFile — stdin が pipe のままでハングする
383
+ execFile("claude", args, opts, callback);
384
+
385
+ // OK: spawn — stdin を ignore で閉じる
386
+ const child = spawn("claude", args, {
387
+ stdio: ["ignore", "pipe", "pipe"],
388
+ ...opts,
389
+ });
390
+ ```
391
+
392
+ ---
393
+
394
+ ## テスト
395
+
396
+ ### プリセット整合性テスト
397
+
398
+ `tests/unit/presets/preset-scan-integrity.test.js` が以下を自動検証する:
399
+
400
+ 1. **scan パターンと scan DataSource の整合性** — preset.json に scan.include を定義しているプリセットは、チェーン内に scan DataSource を持つ
401
+ 2. **テンプレートの data ディレクティブと DataSource メソッドの整合性** — `{{data("preset.source.method")}}` が参照するメソッドが DataSource に存在する
402
+ 3. **analysis キーのカバレッジ** — data DataSource が `analysis.X` を読むなら、`X` を書く scan DataSource がプリセットエコシステム内に存在する
403
+
404
+ **新しいプリセットを追加・変更したら `npm test` を実行し、整合性テストがパスすることを確認すること。**
405
+
406
+ ### プリセット固有テスト
407
+
408
+ プリセット固有テストの配置ルールとテスト内容は「プリセット作成ルール > MUST: プリセットテストの作成」を参照。
409
+
410
+ **プリセット毎のテスト実行:**
411
+
412
+ ```bash
413
+ npm test -- --preset laravel # tests/unit + tests/e2e + src/presets/laravel/tests/
414
+ npm test -- --preset symfony # tests/unit + tests/e2e + src/presets/symfony/tests/
415
+ ```
416
+
417
+ ### テストルール
418
+
419
+ - テストを通すためにテストコードを修正してはならない
420
+ - テスト失敗時はまずシナリオの妥当性を確認し、妥当であればプロダクトコードを修正する
@@ -3,7 +3,7 @@
3
3
  * src/docs/commands/agents.js
4
4
  *
5
5
  * AGENTS.md を更新する。
6
- * AGENTS.md 内の {{data: agents.sdd}} / {{data: agents.project}} ディレクティブを解決し、
6
+ * AGENTS.md 内の {{data("agents.sdd")}} / {{data("agents.project")}} ディレクティブを解決し、
7
7
  * PROJECT セクションは AI で精査する。
8
8
  */
9
9
 
@@ -14,11 +14,11 @@ import { parseArgs } from "../../lib/cli.js";
14
14
  import { sddOutputDir } from "../../lib/config.js";
15
15
  import { callAgent, loadAgentConfig, DEFAULT_AGENT_TIMEOUT } from "../../lib/agent.js";
16
16
  import { translate } from "../../lib/i18n.js";
17
- import { resolveType } from "../../lib/types.js";
18
17
  import { createResolver } from "../lib/resolver-factory.js";
19
18
  import { createLogger } from "../../lib/progress.js";
20
19
  import { parseDirectives, replaceBlockDirective, resolveDataDirectives } from "../lib/directive-parser.js";
21
20
  import { resolveCommandContext, loadFullAnalysis, getChapterFiles, readText } from "../lib/command-context.js";
21
+ import { loadSddTemplate } from "../../lib/agents-md.js";
22
22
 
23
23
  const logger = createLogger("agents");
24
24
 
@@ -52,7 +52,8 @@ function buildRefinePrompt(projectContent, docsContent, config, srcRoot, sddCont
52
52
 
53
53
  if (config.type) {
54
54
  parts.push("## Project Config");
55
- parts.push(`- type: ${config.type}`);
55
+ const typeStr = Array.isArray(config.type) ? config.type.join(", ") : config.type;
56
+ parts.push(`- type: ${typeStr}`);
56
57
  parts.push("");
57
58
  }
58
59
 
@@ -90,7 +91,7 @@ function resolveAgentsDirectives(text, resolveFn) {
90
91
 
91
92
  const result = resolveDataDirectives(
92
93
  text,
93
- (source, method, labels) => resolveFn(source, method, {}, labels),
94
+ (preset, source, method, labels) => resolveFn(preset, source, method, {}, labels),
94
95
  {
95
96
  onResolve(d, rendered) {
96
97
  if (d.source === "agents" && d.method === "sdd") sddContent = rendered;
@@ -152,7 +153,21 @@ async function main(ctx) {
152
153
 
153
154
  const agentsPath = path.join(srcRoot, "AGENTS.md");
154
155
  if (!fs.existsSync(agentsPath)) {
155
- throw new Error(t("messages:agents.notFound", { path: agentsPath }));
156
+ // Generate from template
157
+ const sddSection = loadSddTemplate(lang || config?.lang || "en");
158
+ const template = [
159
+ `# ${path.basename(srcRoot)}`,
160
+ "",
161
+ '<!-- {{data("agents.sdd")}} -->',
162
+ sddSection,
163
+ "<!-- {{/data}} -->",
164
+ "",
165
+ '<!-- {{data("agents.project")}} -->',
166
+ "<!-- {{/data}} -->",
167
+ "",
168
+ ].join("\n");
169
+ fs.writeFileSync(agentsPath, template, "utf8");
170
+ logger.log(`created ${agentsPath}`);
156
171
  }
157
172
 
158
173
  // Load analysis
@@ -169,9 +184,9 @@ async function main(ctx) {
169
184
  const combinedDocs = [docsContent, readmeContent].filter(Boolean).join("\n\n---\n\n");
170
185
 
171
186
  // Create resolver and resolve {{data}} directives
172
- const resolvedType = resolveType(config.type || "base");
187
+ const resolvedType = config.type || "base";
173
188
  const resolver = await createResolver(resolvedType, root, { configChapters: config.chapters });
174
- const resolveFn = (source, method, a, labels) => resolver.resolve(source, method, analysis, labels);
189
+ const resolveFn = (preset, source, method, a, labels) => resolver.resolve(preset, source, method, analysis, labels);
175
190
 
176
191
  let content = fs.readFileSync(agentsPath, "utf8");
177
192
  const { text: resolved, sddContent, projectContent } = resolveAgentsDirectives(content, resolveFn);
@@ -33,7 +33,7 @@ const logger = createLogger("data");
33
33
  * @param {string} text - テンプレート全文
34
34
  * @param {Object} analysis - analysis.json
35
35
  * @param {string} fileName - ログ出力用ファイル名
36
- * @param {function} [resolveFn] - (source, method, analysis, labels) => rendered string
36
+ * @param {function} [resolveFn] - (preset, source, method, analysis, labels) => rendered string
37
37
  * @returns {{ text: string, replaced: number, skipped: number }}
38
38
  */
39
39
  function processTemplate(text, analysis, fileName, resolveFn) {
@@ -45,7 +45,7 @@ function processTemplate(text, analysis, fileName, resolveFn) {
45
45
 
46
46
  const result = resolveDataDirectives(
47
47
  text,
48
- (source, method, labels) => resolveFn(source, method, analysis, labels),
48
+ (preset, source, method, labels) => resolveFn(preset, source, method, analysis, labels),
49
49
  {
50
50
  onSkip(d) {
51
51
  if (d.type === "text") {
@@ -55,7 +55,7 @@ function processTemplate(text, analysis, fileName, resolveFn) {
55
55
  },
56
56
  onUnresolved(d) {
57
57
  unresolved++;
58
- logger.log(`UNRESOLVED {{data}} in ${fileName}:${d.line + 1}: ${d.source}.${d.method} → null`);
58
+ logger.log(`UNRESOLVED {{data}} in ${fileName}:${d.line + 1}: ${d.preset}.${d.source}.${d.method} → null`);
59
59
  },
60
60
  },
61
61
  );
@@ -128,7 +128,7 @@ async function main(ctx) {
128
128
  let resolveFn;
129
129
  try {
130
130
  const resolver = await createResolver(type, root, { docsDir, configChapters: ctx.config?.chapters });
131
- resolveFn = (source, method, a, labels) => resolver.resolve(source, method, a, labels);
131
+ resolveFn = (preset, source, method, a, labels) => resolver.resolve(preset, source, method, a, labels);
132
132
  logger.verbose(`resolver: ${type}`);
133
133
  } catch (err) {
134
134
  throw new Error(t("messages:data.resolverFailed", { message: err.message }));
@@ -146,15 +146,17 @@ async function main(ctx) {
146
146
  for (const file of docsFiles) {
147
147
  const filePath = path.join(docsDir, file);
148
148
  const original = fs.readFileSync(filePath, "utf8");
149
- // Inject file path context for lang.links resolver
150
- const wrappedResolveFn = (source, method, a, labels) => {
151
- if (source === "lang" && method === "links") {
152
- return resolveFn(source, method, a, [`${docsDirRel}/${file}`]);
153
- }
154
- if (source === "docs" && method === "langSwitcher") {
155
- return resolveFn(source, method, a, [labels[0] || "relative", `${docsDirRel}/${file}`]);
156
- }
157
- return resolveFn(source, method, a, labels);
149
+ // Inject file path context for file-aware resolvers
150
+ const fileRelPath = `${docsDirRel}/${file}`;
151
+ const FILE_CONTEXT_RULES = {
152
+ "lang.links": (_labels) => [fileRelPath],
153
+ "docs.langSwitcher": (labels) => [labels[0] || "relative", fileRelPath],
154
+ "docs.nav": (_labels) => [fileRelPath],
155
+ };
156
+ const wrappedResolveFn = (preset, source, method, a, labels) => {
157
+ const rule = FILE_CONTEXT_RULES[`${source}.${method}`];
158
+ if (rule) return resolveFn(preset, source, method, a, rule(labels));
159
+ return resolveFn(preset, source, method, a, labels);
158
160
  };
159
161
  const result = processTemplate(original, analysis, file, wrappedResolveFn);
160
162