@pennyfarthing/core 10.1.0 → 10.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (407) hide show
  1. package/README.md +13 -18
  2. package/package.json +3 -1
  3. package/packages/core/dist/cli/commands/doctor-file-layout.test.js.map +1 -1
  4. package/packages/core/dist/cli/commands/doctor-legacy.test.js +24 -0
  5. package/packages/core/dist/cli/commands/doctor-legacy.test.js.map +1 -1
  6. package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
  7. package/packages/core/dist/cli/commands/doctor.js +101 -15
  8. package/packages/core/dist/cli/commands/doctor.js.map +1 -1
  9. package/packages/core/dist/cli/commands/e2e-fresh-install.test.js +1 -1
  10. package/packages/core/dist/cli/commands/e2e-fresh-install.test.js.map +1 -1
  11. package/packages/core/dist/cli/commands/e2e-upgrade.test.js +1 -1
  12. package/packages/core/dist/cli/commands/e2e-upgrade.test.js.map +1 -1
  13. package/packages/core/dist/cli/commands/hooks-consolidation.test.js +2 -2
  14. package/packages/core/dist/cli/commands/hooks-consolidation.test.js.map +1 -1
  15. package/packages/core/dist/cli/commands/init-consolidation.test.js.map +1 -1
  16. package/packages/core/dist/cli/commands/uninstall.d.ts.map +1 -1
  17. package/packages/core/dist/cli/commands/uninstall.js +24 -13
  18. package/packages/core/dist/cli/commands/uninstall.js.map +1 -1
  19. package/packages/core/dist/cli/commands/update-consolidation.test.js +0 -10
  20. package/packages/core/dist/cli/commands/update-consolidation.test.js.map +1 -1
  21. package/packages/core/dist/cli/commands/update.js.map +1 -1
  22. package/packages/core/dist/cli/ocean-profiles.test.js.map +1 -1
  23. package/packages/core/dist/cli/theme-maker.test.js +64 -115
  24. package/packages/core/dist/cli/theme-maker.test.js.map +1 -1
  25. package/packages/core/dist/index.d.ts +1 -1
  26. package/packages/core/dist/index.d.ts.map +1 -1
  27. package/packages/core/dist/index.js +2 -2
  28. package/packages/core/dist/index.js.map +1 -1
  29. package/packages/core/dist/plugins/plugin-discovery.d.ts +116 -0
  30. package/packages/core/dist/plugins/plugin-discovery.d.ts.map +1 -0
  31. package/packages/core/dist/plugins/plugin-discovery.js +165 -0
  32. package/packages/core/dist/plugins/plugin-discovery.js.map +1 -0
  33. package/packages/core/dist/plugins/plugin-discovery.test.d.ts +22 -0
  34. package/packages/core/dist/plugins/plugin-discovery.test.d.ts.map +1 -0
  35. package/packages/core/dist/plugins/plugin-discovery.test.js +498 -0
  36. package/packages/core/dist/plugins/plugin-discovery.test.js.map +1 -0
  37. package/packages/core/dist/scripts/generate-spider-report.js.map +1 -1
  38. package/packages/core/dist/workflow/context-watch.d.ts +80 -0
  39. package/packages/core/dist/workflow/context-watch.d.ts.map +1 -0
  40. package/packages/core/dist/workflow/context-watch.js +235 -0
  41. package/packages/core/dist/workflow/context-watch.js.map +1 -0
  42. package/packages/core/dist/workflow/context-watch.test.d.ts +1 -0
  43. package/packages/core/dist/workflow/context-watch.test.d.ts.map +1 -0
  44. package/packages/core/dist/workflow/context-watch.test.js +746 -0
  45. package/packages/core/dist/workflow/context-watch.test.js.map +1 -0
  46. package/packages/core/dist/workflow/file-watch.d.ts +82 -0
  47. package/packages/core/dist/workflow/file-watch.d.ts.map +1 -0
  48. package/packages/core/dist/workflow/file-watch.js +198 -0
  49. package/packages/core/dist/workflow/file-watch.js.map +1 -0
  50. package/packages/core/dist/workflow/file-watch.test.d.ts +21 -0
  51. package/packages/core/dist/workflow/file-watch.test.d.ts.map +1 -0
  52. package/packages/core/dist/workflow/file-watch.test.js +469 -0
  53. package/packages/core/dist/workflow/file-watch.test.js.map +1 -0
  54. package/packages/core/dist/workflow/observation-writer.d.ts +79 -0
  55. package/packages/core/dist/workflow/observation-writer.d.ts.map +1 -0
  56. package/packages/core/dist/workflow/observation-writer.js +97 -0
  57. package/packages/core/dist/workflow/observation-writer.js.map +1 -0
  58. package/packages/core/dist/workflow/observation-writer.test.d.ts +18 -0
  59. package/packages/core/dist/workflow/observation-writer.test.d.ts.map +1 -0
  60. package/packages/core/dist/workflow/observation-writer.test.js +424 -0
  61. package/packages/core/dist/workflow/observation-writer.test.js.map +1 -0
  62. package/packages/core/dist/workflow/story-workflow-routing.test.js +4 -2
  63. package/packages/core/dist/workflow/story-workflow-routing.test.js.map +1 -1
  64. package/packages/core/dist/workflow/tandem-lifecycle.d.ts +117 -0
  65. package/packages/core/dist/workflow/tandem-lifecycle.d.ts.map +1 -0
  66. package/packages/core/dist/workflow/tandem-lifecycle.js +186 -0
  67. package/packages/core/dist/workflow/tandem-lifecycle.js.map +1 -0
  68. package/packages/core/dist/workflow/tandem-lifecycle.test.d.ts +16 -0
  69. package/packages/core/dist/workflow/tandem-lifecycle.test.d.ts.map +1 -0
  70. package/packages/core/dist/workflow/tandem-lifecycle.test.js +531 -0
  71. package/packages/core/dist/workflow/tandem-lifecycle.test.js.map +1 -0
  72. package/packages/core/dist/workflow/tool-watch.d.ts +68 -0
  73. package/packages/core/dist/workflow/tool-watch.d.ts.map +1 -0
  74. package/packages/core/dist/workflow/tool-watch.js +166 -0
  75. package/packages/core/dist/workflow/tool-watch.js.map +1 -0
  76. package/packages/core/dist/workflow/tool-watch.test.d.ts +18 -0
  77. package/packages/core/dist/workflow/tool-watch.test.d.ts.map +1 -0
  78. package/packages/core/dist/workflow/tool-watch.test.js +718 -0
  79. package/packages/core/dist/workflow/tool-watch.test.js.map +1 -0
  80. package/packages/core/dist/workflow/workflow-migration.test.js +8 -4
  81. package/packages/core/dist/workflow/workflow-migration.test.js.map +1 -1
  82. package/packages/core/dist/workflow/workflow-schema.d.ts +7 -0
  83. package/packages/core/dist/workflow/workflow-schema.d.ts.map +1 -1
  84. package/packages/core/dist/workflow/workflow-schema.js +44 -0
  85. package/packages/core/dist/workflow/workflow-schema.js.map +1 -1
  86. package/packages/core/dist/workflow/workflow-schema.test.d.ts.map +1 -1
  87. package/packages/core/dist/workflow/workflow-schema.test.js +192 -0
  88. package/packages/core/dist/workflow/workflow-schema.test.js.map +1 -1
  89. package/pennyfarthing-dist/agents/handoff.md +18 -3
  90. package/pennyfarthing-dist/agents/sm-finish.md +1 -1
  91. package/pennyfarthing-dist/agents/sm-handoff.md +27 -4
  92. package/pennyfarthing-dist/agents/sm.md +11 -5
  93. package/pennyfarthing-dist/agents/tandem-backseat.md +119 -0
  94. package/pennyfarthing-dist/commands/setup.md +4 -0
  95. package/pennyfarthing-dist/guides/agent-behavior.md +62 -6
  96. package/pennyfarthing-dist/guides/bikelane.md +3 -2
  97. package/pennyfarthing-dist/guides/scale-levels.md +4 -6
  98. package/pennyfarthing-dist/guides/tandem-protocol.md +158 -0
  99. package/pennyfarthing-dist/personas/themes/discworld.yaml +1 -1
  100. package/pennyfarthing-dist/personas/themes/fifth-element.yaml +295 -0
  101. package/pennyfarthing-dist/scripts/README.md +1 -1
  102. package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +131 -54
  103. package/pennyfarthing-dist/scripts/hooks/post-merge.sh +20 -10
  104. package/pennyfarthing-dist/scripts/misc/statusline.sh +50 -8
  105. package/pennyfarthing-dist/scripts/workflow/README.md +2 -2
  106. package/pennyfarthing-dist/scripts/workflow/finish-story.sh +10 -189
  107. package/pennyfarthing-dist/skills/skill-registry.schema.json +8 -0
  108. package/pennyfarthing-dist/skills/skill-registry.yaml +1 -1
  109. package/pennyfarthing-dist/skills/sprint/skill.md +25 -2
  110. package/pennyfarthing-dist/skills/workflow/skill.md +24 -1
  111. package/pennyfarthing-dist/workflows/architecture/workflow.yaml +65 -0
  112. package/pennyfarthing-dist/workflows/bdd-tandem.yaml +70 -0
  113. package/pennyfarthing-dist/workflows/tdd-tandem.yaml +61 -0
  114. package/pennyfarthing_scripts/__pycache__/__init__.cpython-314.pyc +0 -0
  115. package/pennyfarthing_scripts/__pycache__/bellmode_hook.cpython-314.pyc +0 -0
  116. package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
  117. package/pennyfarthing_scripts/__pycache__/config.cpython-314.pyc +0 -0
  118. package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
  119. package/pennyfarthing_scripts/__pycache__/jira_bidirectional_sync.cpython-314.pyc +0 -0
  120. package/pennyfarthing_scripts/__pycache__/jira_epic_creation.cpython-314.pyc +0 -0
  121. package/pennyfarthing_scripts/__pycache__/jira_sync.cpython-314.pyc +0 -0
  122. package/pennyfarthing_scripts/__pycache__/jira_sync_story.cpython-314.pyc +0 -0
  123. package/pennyfarthing_scripts/__pycache__/output.cpython-314.pyc +0 -0
  124. package/pennyfarthing_scripts/__pycache__/patch_mode.cpython-314.pyc +0 -0
  125. package/pennyfarthing_scripts/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
  126. package/pennyfarthing_scripts/__pycache__/workflow.cpython-314.pyc +0 -0
  127. package/pennyfarthing_scripts/bellmode_hook.py +202 -47
  128. package/pennyfarthing_scripts/brownfield/__init__.py +6 -6
  129. package/pennyfarthing_scripts/brownfield/__main__.py +1 -0
  130. package/pennyfarthing_scripts/brownfield/__pycache__/__init__.cpython-314.pyc +0 -0
  131. package/pennyfarthing_scripts/brownfield/__pycache__/__main__.cpython-314.pyc +0 -0
  132. package/pennyfarthing_scripts/brownfield/__pycache__/cli.cpython-314.pyc +0 -0
  133. package/pennyfarthing_scripts/brownfield/__pycache__/discover.cpython-314.pyc +0 -0
  134. package/pennyfarthing_scripts/brownfield/cli.py +0 -1
  135. package/pennyfarthing_scripts/brownfield/discover.py +1 -2
  136. package/pennyfarthing_scripts/cli.py +11 -6
  137. package/pennyfarthing_scripts/codemarkers/__init__.py +5 -1
  138. package/pennyfarthing_scripts/codemarkers/__pycache__/__init__.cpython-314.pyc +0 -0
  139. package/pennyfarthing_scripts/codemarkers/__pycache__/__main__.cpython-314.pyc +0 -0
  140. package/pennyfarthing_scripts/codemarkers/__pycache__/analyze.cpython-314.pyc +0 -0
  141. package/pennyfarthing_scripts/codemarkers/__pycache__/cli.cpython-314.pyc +0 -0
  142. package/pennyfarthing_scripts/codemarkers/__pycache__/formatters.cpython-314.pyc +0 -0
  143. package/pennyfarthing_scripts/codemarkers/__pycache__/models.cpython-314.pyc +0 -0
  144. package/pennyfarthing_scripts/codemarkers/analyze.py +177 -2
  145. package/pennyfarthing_scripts/codemarkers/cli.py +50 -0
  146. package/pennyfarthing_scripts/codemarkers/formatters.py +0 -1
  147. package/pennyfarthing_scripts/codemarkers/models.py +15 -0
  148. package/pennyfarthing_scripts/common/__init__.py +8 -9
  149. package/pennyfarthing_scripts/common/__pycache__/__init__.cpython-314.pyc +0 -0
  150. package/pennyfarthing_scripts/common/__pycache__/config.cpython-314.pyc +0 -0
  151. package/pennyfarthing_scripts/common/__pycache__/output.cpython-314.pyc +0 -0
  152. package/pennyfarthing_scripts/common/__pycache__/themes.cpython-314.pyc +0 -0
  153. package/pennyfarthing_scripts/common/config.py +1 -1
  154. package/pennyfarthing_scripts/complexity/__init__.py +1 -1
  155. package/pennyfarthing_scripts/complexity/__pycache__/__init__.cpython-314.pyc +0 -0
  156. package/pennyfarthing_scripts/complexity/__pycache__/__main__.cpython-314.pyc +0 -0
  157. package/pennyfarthing_scripts/complexity/__pycache__/analyze.cpython-314.pyc +0 -0
  158. package/pennyfarthing_scripts/complexity/__pycache__/cli.cpython-314.pyc +0 -0
  159. package/pennyfarthing_scripts/complexity/__pycache__/formatters.cpython-314.pyc +0 -0
  160. package/pennyfarthing_scripts/complexity/__pycache__/models.cpython-314.pyc +0 -0
  161. package/pennyfarthing_scripts/complexity/analyze.py +1 -1
  162. package/pennyfarthing_scripts/complexity/cli.py +5 -1
  163. package/pennyfarthing_scripts/complexity/formatters.py +1 -1
  164. package/pennyfarthing_scripts/context.py +14 -15
  165. package/pennyfarthing_scripts/deadcode/__pycache__/__init__.cpython-314.pyc +0 -0
  166. package/pennyfarthing_scripts/deadcode/__pycache__/__main__.cpython-314.pyc +0 -0
  167. package/pennyfarthing_scripts/deadcode/__pycache__/analyze.cpython-314.pyc +0 -0
  168. package/pennyfarthing_scripts/deadcode/__pycache__/cli.cpython-314.pyc +0 -0
  169. package/pennyfarthing_scripts/deadcode/__pycache__/formatters.cpython-314.pyc +0 -0
  170. package/pennyfarthing_scripts/deadcode/__pycache__/models.cpython-314.pyc +0 -0
  171. package/pennyfarthing_scripts/deadcode/analyze.py +3 -4
  172. package/pennyfarthing_scripts/deadcode/cli.py +2 -2
  173. package/pennyfarthing_scripts/dependencies/__init__.py +2 -2
  174. package/pennyfarthing_scripts/dependencies/__pycache__/__init__.cpython-314.pyc +0 -0
  175. package/pennyfarthing_scripts/dependencies/__pycache__/__main__.cpython-314.pyc +0 -0
  176. package/pennyfarthing_scripts/dependencies/__pycache__/analyze.cpython-314.pyc +0 -0
  177. package/pennyfarthing_scripts/dependencies/__pycache__/cli.cpython-314.pyc +0 -0
  178. package/pennyfarthing_scripts/dependencies/__pycache__/formatters.cpython-314.pyc +0 -0
  179. package/pennyfarthing_scripts/dependencies/__pycache__/models.cpython-314.pyc +0 -0
  180. package/pennyfarthing_scripts/dependencies/analyze.py +1 -1
  181. package/pennyfarthing_scripts/dependencies/cli.py +8 -4
  182. package/pennyfarthing_scripts/dependencies/formatters.py +1 -1
  183. package/pennyfarthing_scripts/git/__init__.py +5 -5
  184. package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
  185. package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
  186. package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
  187. package/pennyfarthing_scripts/git/create_branches.py +3 -2
  188. package/pennyfarthing_scripts/git/status_all.py +1 -1
  189. package/pennyfarthing_scripts/healthscore/__init__.py +2 -2
  190. package/pennyfarthing_scripts/healthscore/__main__.py +8 -0
  191. package/pennyfarthing_scripts/healthscore/__pycache__/__init__.cpython-314.pyc +0 -0
  192. package/pennyfarthing_scripts/healthscore/__pycache__/__main__.cpython-314.pyc +0 -0
  193. package/pennyfarthing_scripts/healthscore/__pycache__/analyze.cpython-314.pyc +0 -0
  194. package/pennyfarthing_scripts/healthscore/__pycache__/cli.cpython-314.pyc +0 -0
  195. package/pennyfarthing_scripts/healthscore/__pycache__/formatters.cpython-314.pyc +0 -0
  196. package/pennyfarthing_scripts/healthscore/__pycache__/models.cpython-314.pyc +0 -0
  197. package/pennyfarthing_scripts/healthscore/analyze.py +451 -21
  198. package/pennyfarthing_scripts/healthscore/cli.py +5 -1
  199. package/pennyfarthing_scripts/healthscore/models.py +0 -1
  200. package/pennyfarthing_scripts/hooks.py +8 -11
  201. package/pennyfarthing_scripts/hotspots/__init__.py +6 -6
  202. package/pennyfarthing_scripts/hotspots/__pycache__/__init__.cpython-314.pyc +0 -0
  203. package/pennyfarthing_scripts/hotspots/__pycache__/__main__.cpython-314.pyc +0 -0
  204. package/pennyfarthing_scripts/hotspots/__pycache__/analyze.cpython-314.pyc +0 -0
  205. package/pennyfarthing_scripts/hotspots/__pycache__/cli.cpython-314.pyc +0 -0
  206. package/pennyfarthing_scripts/hotspots/__pycache__/formatters.cpython-314.pyc +0 -0
  207. package/pennyfarthing_scripts/hotspots/__pycache__/models.cpython-314.pyc +0 -0
  208. package/pennyfarthing_scripts/hotspots/analyze.py +128 -14
  209. package/pennyfarthing_scripts/hotspots/cli.py +2 -2
  210. package/pennyfarthing_scripts/hotspots/models.py +0 -1
  211. package/pennyfarthing_scripts/jira/__init__.py +15 -17
  212. package/pennyfarthing_scripts/jira/__pycache__/__init__.cpython-314.pyc +0 -0
  213. package/pennyfarthing_scripts/jira/__pycache__/__main__.cpython-314.pyc +0 -0
  214. package/pennyfarthing_scripts/jira/__pycache__/bidirectional.cpython-314.pyc +0 -0
  215. package/pennyfarthing_scripts/jira/__pycache__/claim.cpython-314.pyc +0 -0
  216. package/pennyfarthing_scripts/jira/__pycache__/cli.cpython-314.pyc +0 -0
  217. package/pennyfarthing_scripts/jira/__pycache__/client.cpython-314.pyc +0 -0
  218. package/pennyfarthing_scripts/jira/__pycache__/create.cpython-314.pyc +0 -0
  219. package/pennyfarthing_scripts/jira/__pycache__/epic.cpython-314.pyc +0 -0
  220. package/pennyfarthing_scripts/jira/__pycache__/operations.cpython-314.pyc +0 -0
  221. package/pennyfarthing_scripts/jira/__pycache__/reconcile.cpython-314.pyc +0 -0
  222. package/pennyfarthing_scripts/jira/__pycache__/story.cpython-314.pyc +0 -0
  223. package/pennyfarthing_scripts/jira/__pycache__/sync.cpython-314.pyc +0 -0
  224. package/pennyfarthing_scripts/jira/bidirectional.py +2 -3
  225. package/pennyfarthing_scripts/jira/claim.py +21 -0
  226. package/pennyfarthing_scripts/jira/cli.py +2 -2
  227. package/pennyfarthing_scripts/jira/client.py +4 -4
  228. package/pennyfarthing_scripts/jira/create.py +45 -1
  229. package/pennyfarthing_scripts/jira/epic.py +3 -2
  230. package/pennyfarthing_scripts/jira/reconcile.py +0 -1
  231. package/pennyfarthing_scripts/jira/story.py +2 -0
  232. package/pennyfarthing_scripts/jira/sync.py +1 -1
  233. package/pennyfarthing_scripts/migration/__pycache__/__init__.cpython-314.pyc +0 -0
  234. package/pennyfarthing_scripts/migration/__pycache__/session.cpython-314.pyc +0 -0
  235. package/pennyfarthing_scripts/migration/__pycache__/skill.cpython-314.pyc +0 -0
  236. package/pennyfarthing_scripts/migration/__pycache__/step.cpython-314.pyc +0 -0
  237. package/pennyfarthing_scripts/migration/__pycache__/validate.cpython-314.pyc +0 -0
  238. package/pennyfarthing_scripts/migration/skill.py +0 -1
  239. package/pennyfarthing_scripts/migration/step.py +0 -1
  240. package/pennyfarthing_scripts/migration/validate.py +8 -5
  241. package/pennyfarthing_scripts/patch_mode.py +2 -2
  242. package/pennyfarthing_scripts/preflight/__init__.py +1 -1
  243. package/pennyfarthing_scripts/preflight/__pycache__/__init__.cpython-314.pyc +0 -0
  244. package/pennyfarthing_scripts/preflight/__pycache__/__main__.cpython-314.pyc +0 -0
  245. package/pennyfarthing_scripts/preflight/__pycache__/cli.cpython-314.pyc +0 -0
  246. package/pennyfarthing_scripts/preflight/__pycache__/finish.cpython-314.pyc +0 -0
  247. package/pennyfarthing_scripts/preflight/finish.py +0 -1
  248. package/pennyfarthing_scripts/pretooluse_hook.py +6 -7
  249. package/pennyfarthing_scripts/prime/__pycache__/__init__.cpython-314.pyc +0 -0
  250. package/pennyfarthing_scripts/prime/__pycache__/cli.cpython-314.pyc +0 -0
  251. package/pennyfarthing_scripts/prime/__pycache__/loader.cpython-314.pyc +0 -0
  252. package/pennyfarthing_scripts/prime/__pycache__/models.cpython-314.pyc +0 -0
  253. package/pennyfarthing_scripts/prime/__pycache__/persona.cpython-314.pyc +0 -0
  254. package/pennyfarthing_scripts/prime/__pycache__/session.cpython-314.pyc +0 -0
  255. package/pennyfarthing_scripts/prime/__pycache__/tiers.cpython-314.pyc +0 -0
  256. package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
  257. package/pennyfarthing_scripts/prime/cli.py +5 -1
  258. package/pennyfarthing_scripts/prime/loader.py +2 -3
  259. package/pennyfarthing_scripts/prime/persona.py +2 -1
  260. package/pennyfarthing_scripts/prime/tiers.py +4 -4
  261. package/pennyfarthing_scripts/schema_validation_hook.py +2 -3
  262. package/pennyfarthing_scripts/sprint/__init__.py +10 -12
  263. package/pennyfarthing_scripts/sprint/__main__.py +2 -2
  264. package/pennyfarthing_scripts/sprint/__pycache__/__init__.cpython-314.pyc +0 -0
  265. package/pennyfarthing_scripts/sprint/__pycache__/__main__.cpython-314.pyc +0 -0
  266. package/pennyfarthing_scripts/sprint/__pycache__/archive.cpython-314.pyc +0 -0
  267. package/pennyfarthing_scripts/sprint/__pycache__/archive_epic.cpython-314.pyc +0 -0
  268. package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
  269. package/pennyfarthing_scripts/sprint/__pycache__/epic_add.cpython-314.pyc +0 -0
  270. package/pennyfarthing_scripts/sprint/__pycache__/import_epic.cpython-314.pyc +0 -0
  271. package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
  272. package/pennyfarthing_scripts/sprint/__pycache__/status.cpython-314.pyc +0 -0
  273. package/pennyfarthing_scripts/sprint/__pycache__/story_add.cpython-314.pyc +0 -0
  274. package/pennyfarthing_scripts/sprint/__pycache__/story_finish.cpython-314.pyc +0 -0
  275. package/pennyfarthing_scripts/sprint/__pycache__/story_update.cpython-314.pyc +0 -0
  276. package/pennyfarthing_scripts/sprint/__pycache__/validate_cmd.cpython-314.pyc +0 -0
  277. package/pennyfarthing_scripts/sprint/__pycache__/validator.cpython-314.pyc +0 -0
  278. package/pennyfarthing_scripts/sprint/__pycache__/work.cpython-314.pyc +0 -0
  279. package/pennyfarthing_scripts/sprint/__pycache__/yaml_io.cpython-314.pyc +0 -0
  280. package/pennyfarthing_scripts/sprint/archive.py +0 -1
  281. package/pennyfarthing_scripts/sprint/archive_epic.py +1 -4
  282. package/pennyfarthing_scripts/sprint/cli.py +34 -28
  283. package/pennyfarthing_scripts/sprint/epic_add.py +8 -1
  284. package/pennyfarthing_scripts/sprint/import_epic.py +42 -18
  285. package/pennyfarthing_scripts/sprint/loader.py +6 -0
  286. package/pennyfarthing_scripts/sprint/status.py +1 -2
  287. package/pennyfarthing_scripts/sprint/story_add.py +2 -2
  288. package/pennyfarthing_scripts/sprint/story_finish.py +3 -5
  289. package/pennyfarthing_scripts/sprint/story_update.py +11 -3
  290. package/pennyfarthing_scripts/sprint/validate_cmd.py +0 -1
  291. package/pennyfarthing_scripts/sprint/validator.py +120 -6
  292. package/pennyfarthing_scripts/sprint/work.py +1 -4
  293. package/pennyfarthing_scripts/sprint/yaml_io.py +10 -2
  294. package/pennyfarthing_scripts/story/__init__.py +14 -16
  295. package/pennyfarthing_scripts/story/__pycache__/__init__.cpython-314.pyc +0 -0
  296. package/pennyfarthing_scripts/story/__pycache__/__main__.cpython-314.pyc +0 -0
  297. package/pennyfarthing_scripts/story/__pycache__/cli.cpython-314.pyc +0 -0
  298. package/pennyfarthing_scripts/story/__pycache__/create.cpython-314.pyc +0 -0
  299. package/pennyfarthing_scripts/story/__pycache__/size.cpython-314.pyc +0 -0
  300. package/pennyfarthing_scripts/story/__pycache__/template.cpython-314.pyc +0 -0
  301. package/pennyfarthing_scripts/story/size.py +0 -1
  302. package/pennyfarthing_scripts/story/template.py +0 -1
  303. package/pennyfarthing_scripts/swebench.py +1 -2
  304. package/pennyfarthing_scripts/tests/__pycache__/__init__.cpython-314.pyc +0 -0
  305. package/pennyfarthing_scripts/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc +0 -0
  306. package/pennyfarthing_scripts/tests/__pycache__/test_brownfield.cpython-314-pytest-9.0.2.pyc +0 -0
  307. package/pennyfarthing_scripts/tests/__pycache__/test_cli_modules.cpython-314-pytest-9.0.2.pyc +0 -0
  308. package/pennyfarthing_scripts/tests/__pycache__/test_codemarkers.cpython-314-pytest-9.0.2.pyc +0 -0
  309. package/pennyfarthing_scripts/tests/__pycache__/test_common.cpython-314-pytest-9.0.2.pyc +0 -0
  310. package/pennyfarthing_scripts/tests/__pycache__/test_git_utils.cpython-314-pytest-9.0.2.pyc +0 -0
  311. package/pennyfarthing_scripts/tests/__pycache__/test_healthscore.cpython-314-pytest-9.0.2.pyc +0 -0
  312. package/pennyfarthing_scripts/tests/__pycache__/test_jira_package.cpython-314-pytest-9.0.2.pyc +0 -0
  313. package/pennyfarthing_scripts/tests/__pycache__/test_package_structure.cpython-314-pytest-9.0.2.pyc +0 -0
  314. package/pennyfarthing_scripts/tests/__pycache__/test_patch_mode.cpython-314-pytest-9.0.2.pyc +0 -0
  315. package/pennyfarthing_scripts/tests/__pycache__/test_prime.cpython-314-pytest-9.0.2.pyc +0 -0
  316. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_package.cpython-314-pytest-9.0.2.pyc +0 -0
  317. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_validator.cpython-314-pytest-9.0.2.pyc +0 -0
  318. package/pennyfarthing_scripts/tests/__pycache__/test_story_add.cpython-314-pytest-9.0.2.pyc +0 -0
  319. package/pennyfarthing_scripts/tests/__pycache__/test_story_package.cpython-314-pytest-9.0.2.pyc +0 -0
  320. package/pennyfarthing_scripts/tests/__pycache__/test_story_update.cpython-314-pytest-9.0.2.pyc +0 -0
  321. package/pennyfarthing_scripts/tests/__pycache__/test_tiers.cpython-314-pytest-9.0.2.pyc +0 -0
  322. package/pennyfarthing_scripts/tests/__pycache__/test_token_counting.cpython-314-pytest-9.0.2.pyc +0 -0
  323. package/pennyfarthing_scripts/tests/__pycache__/test_validate_cmd.cpython-314-pytest-9.0.2.pyc +0 -0
  324. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_check.cpython-314-pytest-9.0.2.pyc +0 -0
  325. package/pennyfarthing_scripts/tests/__pycache__/test_yaml_io.cpython-314-pytest-9.0.2.pyc +0 -0
  326. package/pennyfarthing_scripts/tests/conftest.py +1 -2
  327. package/pennyfarthing_scripts/tests/test_brownfield.py +10 -13
  328. package/pennyfarthing_scripts/tests/test_cli_modules.py +0 -4
  329. package/pennyfarthing_scripts/tests/test_codemarkers.py +13 -8
  330. package/pennyfarthing_scripts/tests/test_common.py +9 -4
  331. package/pennyfarthing_scripts/tests/test_epic_shard_validation.py +699 -0
  332. package/pennyfarthing_scripts/tests/test_git_utils.py +10 -13
  333. package/pennyfarthing_scripts/tests/test_healthscore.py +17 -25
  334. package/pennyfarthing_scripts/tests/test_jira_package.py +0 -3
  335. package/pennyfarthing_scripts/tests/test_package_structure.py +3 -16
  336. package/pennyfarthing_scripts/tests/test_patch_mode.py +7 -11
  337. package/pennyfarthing_scripts/tests/test_prime.py +39 -21
  338. package/pennyfarthing_scripts/tests/test_sprint_package.py +3 -8
  339. package/pennyfarthing_scripts/tests/test_sprint_validator.py +53 -5
  340. package/pennyfarthing_scripts/tests/test_story_add.py +3 -7
  341. package/pennyfarthing_scripts/tests/test_story_package.py +0 -3
  342. package/pennyfarthing_scripts/tests/test_story_update.py +5 -10
  343. package/pennyfarthing_scripts/tests/test_tiers.py +18 -17
  344. package/pennyfarthing_scripts/tests/test_token_counting.py +19 -13
  345. package/pennyfarthing_scripts/tests/test_validate_cmd.py +2 -7
  346. package/pennyfarthing_scripts/tests/test_workflow_check.py +0 -2
  347. package/pennyfarthing_scripts/tests/test_yaml_io.py +0 -3
  348. package/pennyfarthing_scripts/theme/__pycache__/__init__.cpython-314.pyc +0 -0
  349. package/pennyfarthing_scripts/theme/__pycache__/cli.cpython-314.pyc +0 -0
  350. package/pennyfarthing_scripts/theme/cli.py +3 -2
  351. package/pennyfarthing_scripts/validate/__init__.py +21 -0
  352. package/pennyfarthing_scripts/validate/__pycache__/__init__.cpython-314.pyc +0 -0
  353. package/pennyfarthing_scripts/validate/__pycache__/cli.cpython-314.pyc +0 -0
  354. package/pennyfarthing_scripts/validate/adapters/__init__.py +0 -0
  355. package/pennyfarthing_scripts/validate/adapters/__pycache__/__init__.cpython-314.pyc +0 -0
  356. package/pennyfarthing_scripts/validate/adapters/__pycache__/agent.cpython-314.pyc +0 -0
  357. package/pennyfarthing_scripts/validate/adapters/__pycache__/schema.cpython-314.pyc +0 -0
  358. package/pennyfarthing_scripts/validate/adapters/__pycache__/skill_command.cpython-314.pyc +0 -0
  359. package/pennyfarthing_scripts/validate/adapters/__pycache__/sprint.cpython-314.pyc +0 -0
  360. package/pennyfarthing_scripts/validate/adapters/__pycache__/workflow.cpython-314.pyc +0 -0
  361. package/pennyfarthing_scripts/validate/adapters/agent.py +239 -0
  362. package/pennyfarthing_scripts/validate/adapters/schema.py +30 -0
  363. package/pennyfarthing_scripts/validate/adapters/skill_command.py +292 -0
  364. package/pennyfarthing_scripts/validate/adapters/sprint.py +69 -0
  365. package/pennyfarthing_scripts/validate/adapters/workflow.py +320 -0
  366. package/pennyfarthing_scripts/validate/cli.py +141 -0
  367. package/pennyfarthing_scripts/welcome_hook.py +2 -3
  368. package/pennyfarthing_scripts/workflow.py +3 -3
  369. package/scripts/README.md +3 -15
  370. package/pennyfarthing-dist/commands/benchmark-control.md +0 -69
  371. package/pennyfarthing-dist/commands/benchmark.md +0 -485
  372. package/pennyfarthing-dist/commands/job-fair.md +0 -102
  373. package/pennyfarthing-dist/commands/solo.md +0 -447
  374. package/pennyfarthing-dist/guides/benchmarks.md +0 -62
  375. package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
  376. package/pennyfarthing-dist/scripts/test/ensure-swebench-data.sh +0 -59
  377. package/pennyfarthing-dist/scripts/test/ground-truth-judge.py +0 -220
  378. package/pennyfarthing-dist/scripts/test/swebench-judge.py +0 -374
  379. package/pennyfarthing-dist/scripts/test/test-cache.sh +0 -165
  380. package/pennyfarthing-dist/scripts/test/test-setup.sh +0 -337
  381. package/pennyfarthing-dist/scripts/theme/compute-theme-tiers.sh +0 -13
  382. package/pennyfarthing-dist/scripts/theme/compute_theme_tiers.py +0 -402
  383. package/pennyfarthing-dist/scripts/theme/update-theme-tiers.sh +0 -97
  384. package/pennyfarthing-dist/skills/finalize-run/SKILL.md +0 -261
  385. package/pennyfarthing-dist/skills/judge/SKILL.md +0 -644
  386. package/pennyfarthing-dist/skills/persona-benchmark/SKILL.md +0 -187
  387. package/pennyfarthing-dist/workflows/dev-story/checklist.md +0 -80
  388. package/pennyfarthing-dist/workflows/dev-story/instructions.xml +0 -410
  389. package/pennyfarthing-dist/workflows/dev-story/workflow.yaml +0 -50
  390. package/pennyfarthing-dist/workflows/quick-spec/steps/step-01-understand.md +0 -201
  391. package/pennyfarthing-dist/workflows/quick-spec/steps/step-02-investigate.md +0 -156
  392. package/pennyfarthing-dist/workflows/quick-spec/steps/step-03-generate.md +0 -140
  393. package/pennyfarthing-dist/workflows/quick-spec/steps/step-04-review.md +0 -203
  394. package/pennyfarthing-dist/workflows/quick-spec/tech-spec-template.md +0 -74
  395. package/pennyfarthing-dist/workflows/quick-spec/workflow.yaml +0 -27
  396. package/pennyfarthing_scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  397. package/pennyfarthing_scripts/__pycache__/jira.cpython-314.pyc +0 -0
  398. package/pennyfarthing_scripts/__pycache__/pretooluse_hook.cpython-314.pyc +0 -0
  399. package/pennyfarthing_scripts/__pycache__/sprint.cpython-314.pyc +0 -0
  400. package/pennyfarthing_scripts/__pycache__/workflow.cpython-311.pyc +0 -0
  401. package/pennyfarthing_scripts/jira/__pycache__/compat.cpython-314.pyc +0 -0
  402. package/pennyfarthing_scripts/jira/__pycache__/mappings.cpython-314.pyc +0 -0
  403. package/pennyfarthing_scripts/jira/__pycache__/models.cpython-314.pyc +0 -0
  404. package/pennyfarthing_scripts/migration/__pycache__/__main__.cpython-314.pyc +0 -0
  405. package/pennyfarthing_scripts/migration/__pycache__/cli.cpython-314.pyc +0 -0
  406. package/pennyfarthing_scripts/prime/__pycache__/__main__.cpython-314.pyc +0 -0
  407. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_cli.cpython-314-pytest-9.0.2.pyc +0 -0
@@ -0,0 +1,469 @@
1
+ /**
2
+ * Tests for Story 95-4: File-watch Observation Scope
3
+ *
4
+ * RED state tests for file change detection in the backseat agent.
5
+ * These tests cover all acceptance criteria:
6
+ *
7
+ * AC1: Detect file create events in working tree
8
+ * AC2: Detect file modify events in working tree
9
+ * AC3: Detect file delete events in working tree
10
+ * AC4: Detection within 5 seconds (poll interval ≤ 2s)
11
+ * AC5: Non-blocking — functions return promptly, polling is async
12
+ * AC6: Writes observations with file-watch trigger type via ObservationWriter
13
+ * AC7: Context accumulation — tracks seen files, avoids redundant observations
14
+ * AC8: Ignores non-source directories (.pennyfarthing/, .session/, node_modules/)
15
+ * AC9: Error resilience — continues observing if a single write fails
16
+ * AC10: Returns result objects ({success, error?}) per framework pattern
17
+ *
18
+ * Run with: npm test
19
+ */
20
+ import { describe, it, beforeEach, afterEach } from 'node:test';
21
+ import assert from 'node:assert';
22
+ import { mkdirSync, rmSync, existsSync, writeFileSync, unlinkSync } from 'node:fs';
23
+ import { join, dirname } from 'node:path';
24
+ import { fileURLToPath } from 'node:url';
25
+ // Import the module under test (does not exist yet — will cause import failure)
26
+ import { detectFileChanges, startFileWatcher, stopFileWatcher, createFileWatchScope, } from './file-watch.js';
27
+ // Import observation writer for integration tests
28
+ import { initObservationFile, parseObservationFile, } from './observation-writer.js';
29
+ // Get directory for test fixtures
30
+ const __dirname = dirname(fileURLToPath(import.meta.url));
31
+ const TEST_DIR = join(__dirname, '__test_file_watch__');
32
+ const SESSION_DIR = join(TEST_DIR, '.session');
33
+ const WORK_DIR = join(TEST_DIR, 'workdir');
34
+ // =============================================================================
35
+ // Test Fixtures
36
+ // =============================================================================
37
+ const DEFAULT_POLL_MS = 100; // Fast for testing
38
+ const DEFAULT_CONFIG = {
39
+ workDir: WORK_DIR,
40
+ sessionDir: SESSION_DIR,
41
+ storyId: '95-4',
42
+ agent: 'architect',
43
+ persona: 'Will Bailey',
44
+ phase: 'implement',
45
+ pollIntervalMs: DEFAULT_POLL_MS,
46
+ ignorePaths: ['.pennyfarthing/', '.session/', 'node_modules/'],
47
+ };
48
+ const OBS_CONFIG = {
49
+ storyId: '95-4',
50
+ agent: 'architect',
51
+ persona: 'Will Bailey',
52
+ phase: 'implement',
53
+ sessionDir: SESSION_DIR,
54
+ };
55
+ // =============================================================================
56
+ // Setup / Teardown
57
+ // =============================================================================
58
+ describe('95-4: File-watch Observation Scope', () => {
59
+ beforeEach(() => {
60
+ if (existsSync(TEST_DIR)) {
61
+ rmSync(TEST_DIR, { recursive: true });
62
+ }
63
+ mkdirSync(SESSION_DIR, { recursive: true });
64
+ mkdirSync(WORK_DIR, { recursive: true });
65
+ });
66
+ afterEach(() => {
67
+ if (existsSync(TEST_DIR)) {
68
+ rmSync(TEST_DIR, { recursive: true });
69
+ }
70
+ });
71
+ // ===========================================================================
72
+ // AC1: Detect file create events
73
+ // ===========================================================================
74
+ describe('AC1: Detect file create events', () => {
75
+ it('should detect a newly created file', async () => {
76
+ // Baseline — no files yet
77
+ const baseline = await detectFileChanges(DEFAULT_CONFIG);
78
+ assert.ok(baseline.success);
79
+ // Create a file
80
+ writeFileSync(join(WORK_DIR, 'new-file.ts'), 'export const x = 1;');
81
+ // Detect changes
82
+ const result = await detectFileChanges(DEFAULT_CONFIG);
83
+ assert.ok(result.success);
84
+ assert.ok(result.data);
85
+ assert.ok(result.data.length > 0, 'Should detect at least one change');
86
+ const created = result.data.find((c) => c.path.includes('new-file.ts'));
87
+ assert.ok(created, 'Should find the created file');
88
+ assert.strictEqual(created.event, 'create');
89
+ });
90
+ it('should detect multiple created files in a single poll', async () => {
91
+ const baseline = await detectFileChanges(DEFAULT_CONFIG);
92
+ assert.ok(baseline.success);
93
+ writeFileSync(join(WORK_DIR, 'a.ts'), 'a');
94
+ writeFileSync(join(WORK_DIR, 'b.ts'), 'b');
95
+ writeFileSync(join(WORK_DIR, 'c.ts'), 'c');
96
+ const result = await detectFileChanges(DEFAULT_CONFIG);
97
+ assert.ok(result.success);
98
+ assert.ok(result.data);
99
+ assert.ok(result.data.length >= 3, `Expected ≥3 changes, got ${result.data.length}`);
100
+ });
101
+ it('should detect files created in subdirectories', async () => {
102
+ const baseline = await detectFileChanges(DEFAULT_CONFIG);
103
+ assert.ok(baseline.success);
104
+ const subDir = join(WORK_DIR, 'src', 'components');
105
+ mkdirSync(subDir, { recursive: true });
106
+ writeFileSync(join(subDir, 'Widget.tsx'), 'export function Widget() {}');
107
+ const result = await detectFileChanges(DEFAULT_CONFIG);
108
+ assert.ok(result.success);
109
+ assert.ok(result.data);
110
+ const created = result.data.find((c) => c.path.includes('Widget.tsx'));
111
+ assert.ok(created, 'Should find file in subdirectory');
112
+ });
113
+ });
114
+ // ===========================================================================
115
+ // AC2: Detect file modify events
116
+ // ===========================================================================
117
+ describe('AC2: Detect file modify events', () => {
118
+ it('should detect a modified file', async () => {
119
+ // Create file first
120
+ const filePath = join(WORK_DIR, 'existing.ts');
121
+ writeFileSync(filePath, 'export const x = 1;');
122
+ // Baseline with existing file
123
+ const baseline = await detectFileChanges(DEFAULT_CONFIG);
124
+ assert.ok(baseline.success);
125
+ // Modify the file
126
+ writeFileSync(filePath, 'export const x = 2;');
127
+ const result = await detectFileChanges(DEFAULT_CONFIG);
128
+ assert.ok(result.success);
129
+ assert.ok(result.data);
130
+ const modified = result.data.find((c) => c.path.includes('existing.ts'));
131
+ assert.ok(modified, 'Should find the modified file');
132
+ assert.strictEqual(modified.event, 'modify');
133
+ });
134
+ });
135
+ // ===========================================================================
136
+ // AC3: Detect file delete events
137
+ // ===========================================================================
138
+ describe('AC3: Detect file delete events', () => {
139
+ it('should detect a deleted file', async () => {
140
+ // Create file first
141
+ const filePath = join(WORK_DIR, 'to-delete.ts');
142
+ writeFileSync(filePath, 'export const temp = true;');
143
+ // Baseline
144
+ const baseline = await detectFileChanges(DEFAULT_CONFIG);
145
+ assert.ok(baseline.success);
146
+ // Delete the file
147
+ unlinkSync(filePath);
148
+ const result = await detectFileChanges(DEFAULT_CONFIG);
149
+ assert.ok(result.success);
150
+ assert.ok(result.data);
151
+ const deleted = result.data.find((c) => c.path.includes('to-delete.ts'));
152
+ assert.ok(deleted, 'Should find the deleted file');
153
+ assert.strictEqual(deleted.event, 'delete');
154
+ });
155
+ });
156
+ // ===========================================================================
157
+ // AC4: Detection within 5 seconds (poll interval)
158
+ // ===========================================================================
159
+ describe('AC4: Detection within 5 seconds', () => {
160
+ it('should accept poll interval ≤ 2000ms', () => {
161
+ // Verify the config accepts a valid poll interval
162
+ const config = {
163
+ ...DEFAULT_CONFIG,
164
+ pollIntervalMs: 2000,
165
+ };
166
+ assert.strictEqual(config.pollIntervalMs, 2000);
167
+ });
168
+ it('should default poll interval to ≤ 2000ms when not specified', async () => {
169
+ const configNoInterval = {
170
+ workDir: WORK_DIR,
171
+ sessionDir: SESSION_DIR,
172
+ storyId: '95-4',
173
+ agent: 'architect',
174
+ persona: 'Will Bailey',
175
+ phase: 'implement',
176
+ ignorePaths: [],
177
+ };
178
+ // createFileWatchScope should use a default interval ≤ 2000ms
179
+ const scope = createFileWatchScope(configNoInterval);
180
+ assert.ok(scope, 'Should create scope');
181
+ assert.ok(scope.pollIntervalMs <= 2000, `Default poll interval should be ≤ 2000ms, got ${scope.pollIntervalMs}`);
182
+ });
183
+ });
184
+ // ===========================================================================
185
+ // AC5: Non-blocking — functions return promptly
186
+ // ===========================================================================
187
+ describe('AC5: Non-blocking', () => {
188
+ it('detectFileChanges should resolve without long blocking', async () => {
189
+ const start = Date.now();
190
+ const result = await detectFileChanges(DEFAULT_CONFIG);
191
+ const elapsed = Date.now() - start;
192
+ assert.ok(result.success);
193
+ // Single detection cycle should complete in < 5000ms
194
+ assert.ok(elapsed < 5000, `detectFileChanges took ${elapsed}ms, expected < 5000ms`);
195
+ });
196
+ it('startFileWatcher should return handle immediately', async () => {
197
+ const start = Date.now();
198
+ const result = await startFileWatcher(DEFAULT_CONFIG);
199
+ const elapsed = Date.now() - start;
200
+ assert.ok(result.success);
201
+ assert.ok(result.data, 'Should return a handle');
202
+ // Start should be fast — sets up watcher, doesn't block
203
+ assert.ok(elapsed < 1000, `startFileWatcher took ${elapsed}ms, expected < 1000ms`);
204
+ // Cleanup
205
+ if (result.data) {
206
+ await stopFileWatcher(result.data);
207
+ }
208
+ });
209
+ });
210
+ // ===========================================================================
211
+ // AC6: Writes observations with file-watch trigger type
212
+ // ===========================================================================
213
+ describe('AC6: Writes file-watch observations', () => {
214
+ it('should write observation with file-watch trigger type on file create', async () => {
215
+ // Init observation file
216
+ const initResult = initObservationFile(OBS_CONFIG);
217
+ assert.ok(initResult.success);
218
+ assert.ok(initResult.data);
219
+ // Start watcher
220
+ const watchResult = await startFileWatcher({
221
+ ...DEFAULT_CONFIG,
222
+ observationFilePath: initResult.data.path,
223
+ });
224
+ assert.ok(watchResult.success);
225
+ assert.ok(watchResult.data);
226
+ // Create a file to trigger observation
227
+ writeFileSync(join(WORK_DIR, 'trigger.ts'), 'export const trigger = true;');
228
+ // Wait for at least one poll cycle
229
+ await new Promise(resolve => setTimeout(resolve, DEFAULT_POLL_MS * 3));
230
+ // Stop watcher
231
+ await stopFileWatcher(watchResult.data);
232
+ // Parse the observation file
233
+ const parsed = parseObservationFile(initResult.data.path);
234
+ assert.ok(parsed.success);
235
+ assert.ok(parsed.data);
236
+ assert.ok(parsed.data.entries.length > 0, 'Should have at least one observation entry');
237
+ const entry = parsed.data.entries[0];
238
+ assert.strictEqual(entry.triggerType, 'file-watch', 'Trigger type should be file-watch');
239
+ assert.ok(entry.triggerDetail.includes('trigger.ts'), 'Trigger detail should mention the file');
240
+ });
241
+ it('should include event type (create/modify/delete) in trigger detail', async () => {
242
+ const initResult = initObservationFile(OBS_CONFIG);
243
+ assert.ok(initResult.success);
244
+ assert.ok(initResult.data);
245
+ const watchResult = await startFileWatcher({
246
+ ...DEFAULT_CONFIG,
247
+ observationFilePath: initResult.data.path,
248
+ });
249
+ assert.ok(watchResult.success);
250
+ assert.ok(watchResult.data);
251
+ // Create a file
252
+ writeFileSync(join(WORK_DIR, 'event-type.ts'), 'content');
253
+ await new Promise(resolve => setTimeout(resolve, DEFAULT_POLL_MS * 3));
254
+ await stopFileWatcher(watchResult.data);
255
+ const parsed = parseObservationFile(initResult.data.path);
256
+ assert.ok(parsed.success);
257
+ assert.ok(parsed.data);
258
+ assert.ok(parsed.data.entries.length > 0);
259
+ // Trigger detail should contain the event type
260
+ const entry = parsed.data.entries[0];
261
+ assert.ok(entry.triggerDetail.includes('create') ||
262
+ entry.triggerDetail.includes('modify') ||
263
+ entry.triggerDetail.includes('delete'), `Trigger detail should include event type, got: "${entry.triggerDetail}"`);
264
+ });
265
+ });
266
+ // ===========================================================================
267
+ // AC7: Context accumulation — no redundant observations
268
+ // ===========================================================================
269
+ describe('AC7: Context accumulation', () => {
270
+ it('should not write duplicate observations for the same unchanged file', async () => {
271
+ const initResult = initObservationFile(OBS_CONFIG);
272
+ assert.ok(initResult.success);
273
+ assert.ok(initResult.data);
274
+ const watchResult = await startFileWatcher({
275
+ ...DEFAULT_CONFIG,
276
+ observationFilePath: initResult.data.path,
277
+ });
278
+ assert.ok(watchResult.success);
279
+ assert.ok(watchResult.data);
280
+ // Create a file
281
+ writeFileSync(join(WORK_DIR, 'once.ts'), 'content');
282
+ // Wait for multiple poll cycles
283
+ await new Promise(resolve => setTimeout(resolve, DEFAULT_POLL_MS * 6));
284
+ await stopFileWatcher(watchResult.data);
285
+ const parsed = parseObservationFile(initResult.data.path);
286
+ assert.ok(parsed.success);
287
+ assert.ok(parsed.data);
288
+ // File was created once and not modified again — should appear at most once
289
+ const onceEntries = parsed.data.entries.filter((e) => e.triggerDetail.includes('once.ts'));
290
+ assert.strictEqual(onceEntries.length, 1, `File should appear exactly once, got ${onceEntries.length}`);
291
+ });
292
+ it('should write a new observation when a previously seen file changes again', async () => {
293
+ const initResult = initObservationFile(OBS_CONFIG);
294
+ assert.ok(initResult.success);
295
+ assert.ok(initResult.data);
296
+ const watchResult = await startFileWatcher({
297
+ ...DEFAULT_CONFIG,
298
+ observationFilePath: initResult.data.path,
299
+ });
300
+ assert.ok(watchResult.success);
301
+ assert.ok(watchResult.data);
302
+ const filePath = join(WORK_DIR, 'changing.ts');
303
+ // Create file
304
+ writeFileSync(filePath, 'version 1');
305
+ await new Promise(resolve => setTimeout(resolve, DEFAULT_POLL_MS * 3));
306
+ // Modify the same file
307
+ writeFileSync(filePath, 'version 2');
308
+ await new Promise(resolve => setTimeout(resolve, DEFAULT_POLL_MS * 3));
309
+ await stopFileWatcher(watchResult.data);
310
+ const parsed = parseObservationFile(initResult.data.path);
311
+ assert.ok(parsed.success);
312
+ assert.ok(parsed.data);
313
+ const changingEntries = parsed.data.entries.filter((e) => e.triggerDetail.includes('changing.ts'));
314
+ // Should have at least 2 entries: create + modify
315
+ assert.ok(changingEntries.length >= 2, `Expected ≥2 entries for file, got ${changingEntries.length}`);
316
+ });
317
+ });
318
+ // ===========================================================================
319
+ // AC8: Ignores non-source directories
320
+ // ===========================================================================
321
+ describe('AC8: Ignores non-source paths', () => {
322
+ it('should ignore files in .pennyfarthing/ directory', async () => {
323
+ const baseline = await detectFileChanges(DEFAULT_CONFIG);
324
+ assert.ok(baseline.success);
325
+ const ignoredDir = join(WORK_DIR, '.pennyfarthing');
326
+ mkdirSync(ignoredDir, { recursive: true });
327
+ writeFileSync(join(ignoredDir, 'config.yaml'), 'ignored: true');
328
+ const result = await detectFileChanges(DEFAULT_CONFIG);
329
+ assert.ok(result.success);
330
+ const changes = result.data ?? [];
331
+ const pfChanges = changes.filter((c) => c.path.includes('.pennyfarthing'));
332
+ assert.strictEqual(pfChanges.length, 0, 'Should not detect changes in .pennyfarthing/');
333
+ });
334
+ it('should ignore files in node_modules/ directory', async () => {
335
+ const baseline = await detectFileChanges(DEFAULT_CONFIG);
336
+ assert.ok(baseline.success);
337
+ const ignoredDir = join(WORK_DIR, 'node_modules', 'some-pkg');
338
+ mkdirSync(ignoredDir, { recursive: true });
339
+ writeFileSync(join(ignoredDir, 'index.js'), 'module.exports = {}');
340
+ const result = await detectFileChanges(DEFAULT_CONFIG);
341
+ assert.ok(result.success);
342
+ const changes = result.data ?? [];
343
+ const nmChanges = changes.filter((c) => c.path.includes('node_modules'));
344
+ assert.strictEqual(nmChanges.length, 0, 'Should not detect changes in node_modules/');
345
+ });
346
+ it('should ignore files in .session/ directory', async () => {
347
+ const baseline = await detectFileChanges(DEFAULT_CONFIG);
348
+ assert.ok(baseline.success);
349
+ mkdirSync(join(WORK_DIR, '.session'), { recursive: true });
350
+ writeFileSync(join(WORK_DIR, '.session', 'state.md'), '# state');
351
+ const result = await detectFileChanges(DEFAULT_CONFIG);
352
+ assert.ok(result.success);
353
+ const changes = result.data ?? [];
354
+ // Note: .session within WORK_DIR, not SESSION_DIR
355
+ const sessionChanges = changes.filter((c) => c.path.includes('.session'));
356
+ assert.strictEqual(sessionChanges.length, 0, 'Should not detect changes in .session/');
357
+ });
358
+ it('should detect files in non-ignored directories', async () => {
359
+ const baseline = await detectFileChanges(DEFAULT_CONFIG);
360
+ assert.ok(baseline.success);
361
+ const srcDir = join(WORK_DIR, 'src');
362
+ mkdirSync(srcDir, { recursive: true });
363
+ writeFileSync(join(srcDir, 'app.ts'), 'export const app = true;');
364
+ const result = await detectFileChanges(DEFAULT_CONFIG);
365
+ assert.ok(result.success);
366
+ assert.ok(result.data);
367
+ assert.ok(result.data.length > 0, 'Should detect changes in src/');
368
+ });
369
+ });
370
+ // ===========================================================================
371
+ // AC9: Error resilience — continue if write fails
372
+ // ===========================================================================
373
+ describe('AC9: Error resilience', () => {
374
+ it('should return error result for invalid work directory', async () => {
375
+ const badConfig = {
376
+ ...DEFAULT_CONFIG,
377
+ workDir: '/nonexistent/path/that/does/not/exist',
378
+ };
379
+ const result = await detectFileChanges(badConfig);
380
+ // Should return error result, not throw
381
+ assert.strictEqual(result.success, false);
382
+ assert.ok(result.error, 'Should have error message');
383
+ });
384
+ it('startFileWatcher should continue polling after observation write error', async () => {
385
+ // Use a non-existent observation file path to trigger write errors
386
+ const watchResult = await startFileWatcher({
387
+ ...DEFAULT_CONFIG,
388
+ observationFilePath: '/nonexistent/obs.md',
389
+ });
390
+ assert.ok(watchResult.success, 'Watcher should start even with bad observation path');
391
+ assert.ok(watchResult.data);
392
+ // Create a file — should trigger detection but write will fail
393
+ writeFileSync(join(WORK_DIR, 'resilient.ts'), 'content');
394
+ // Wait for a few poll cycles — watcher should NOT crash
395
+ await new Promise(resolve => setTimeout(resolve, DEFAULT_POLL_MS * 5));
396
+ // Watcher should still be alive (stopFileWatcher should succeed)
397
+ const stopResult = await stopFileWatcher(watchResult.data);
398
+ assert.ok(stopResult.success, 'Should stop cleanly even after write errors');
399
+ });
400
+ });
401
+ // ===========================================================================
402
+ // AC10: Returns result objects per framework pattern
403
+ // ===========================================================================
404
+ describe('AC10: Result objects', () => {
405
+ it('detectFileChanges should return {success, data?, error?}', async () => {
406
+ const result = await detectFileChanges(DEFAULT_CONFIG);
407
+ assert.ok(typeof result === 'object');
408
+ assert.ok('success' in result, 'Result must have success field');
409
+ if (result.success) {
410
+ assert.ok('data' in result || result.data === undefined, 'Successful result may have data');
411
+ }
412
+ else {
413
+ assert.ok('error' in result, 'Failed result must have error');
414
+ }
415
+ });
416
+ it('startFileWatcher should return {success, data?: FileWatchHandle, error?}', async () => {
417
+ const result = await startFileWatcher(DEFAULT_CONFIG);
418
+ assert.ok(typeof result === 'object');
419
+ assert.ok('success' in result);
420
+ if (result.success && result.data) {
421
+ assert.ok('handle' in result.data || 'stop' in result.data || typeof result.data === 'object', 'Handle should be an object');
422
+ await stopFileWatcher(result.data);
423
+ }
424
+ });
425
+ it('stopFileWatcher should return {success, error?}', async () => {
426
+ const watchResult = await startFileWatcher(DEFAULT_CONFIG);
427
+ assert.ok(watchResult.success);
428
+ assert.ok(watchResult.data);
429
+ const stopResult = await stopFileWatcher(watchResult.data);
430
+ assert.ok(typeof stopResult === 'object');
431
+ assert.ok('success' in stopResult);
432
+ assert.ok(stopResult.success);
433
+ });
434
+ });
435
+ // ===========================================================================
436
+ // Edge cases
437
+ // ===========================================================================
438
+ describe('Edge cases', () => {
439
+ it('should handle empty working directory gracefully', async () => {
440
+ const result = await detectFileChanges(DEFAULT_CONFIG);
441
+ assert.ok(result.success);
442
+ assert.ok(Array.isArray(result.data));
443
+ assert.strictEqual(result.data.length, 0, 'No changes in empty directory');
444
+ });
445
+ it('should handle rapid successive file changes', async () => {
446
+ const baseline = await detectFileChanges(DEFAULT_CONFIG);
447
+ assert.ok(baseline.success);
448
+ // Create many files rapidly
449
+ for (let i = 0; i < 10; i++) {
450
+ writeFileSync(join(WORK_DIR, `rapid-${i}.ts`), `content ${i}`);
451
+ }
452
+ const result = await detectFileChanges(DEFAULT_CONFIG);
453
+ assert.ok(result.success);
454
+ assert.ok(result.data);
455
+ assert.strictEqual(result.data.length, 10, `Expected 10 changes, got ${result.data.length}`);
456
+ });
457
+ it('stopFileWatcher should be idempotent', async () => {
458
+ const watchResult = await startFileWatcher(DEFAULT_CONFIG);
459
+ assert.ok(watchResult.success);
460
+ assert.ok(watchResult.data);
461
+ // Stop twice — second should not throw
462
+ const stop1 = await stopFileWatcher(watchResult.data);
463
+ assert.ok(stop1.success);
464
+ const stop2 = await stopFileWatcher(watchResult.data);
465
+ assert.ok(stop2.success, 'Second stop should also succeed (idempotent)');
466
+ });
467
+ });
468
+ });
469
+ //# sourceMappingURL=file-watch.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-watch.test.js","sourceRoot":"","sources":["../../src/workflow/file-watch.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Observation File Writer for Story 95-3
3
+ *
4
+ * Creates and appends to observation files used by tandem backseat agents.
5
+ * Files are append-only markdown at `.session/{storyId}-tandem-{agent}.md`.
6
+ * Each write is entry-atomic — the file remains valid markdown on crash.
7
+ */
8
+ /**
9
+ * Configuration for initializing an observation file
10
+ */
11
+ export interface ObservationWriterConfig {
12
+ /** Current story ID */
13
+ storyId: string;
14
+ /** Observer agent name */
15
+ agent: string;
16
+ /** Observer persona name */
17
+ persona: string;
18
+ /** Current workflow phase */
19
+ phase: string;
20
+ /** Path to .session/ directory */
21
+ sessionDir: string;
22
+ }
23
+ /**
24
+ * A single observation entry to append
25
+ */
26
+ export interface ObservationEntry {
27
+ /** Trigger type: file-watch, tool-watch, context-watch */
28
+ triggerType: string;
29
+ /** Trigger detail, e.g. "src/foo.ts modified" */
30
+ triggerDetail: string;
31
+ /** The observation text */
32
+ observation: string;
33
+ }
34
+ /**
35
+ * Standard result object per framework pattern
36
+ */
37
+ export interface ObservationResult<T = unknown> {
38
+ success: boolean;
39
+ data?: T;
40
+ error?: string;
41
+ }
42
+ export interface ObservationFileHeader {
43
+ storyId: string;
44
+ observer: string;
45
+ phase: string;
46
+ started: string;
47
+ }
48
+ export interface ParsedObservationEntry {
49
+ timestamp: string;
50
+ triggerType: string;
51
+ triggerDetail: string;
52
+ observation: string;
53
+ }
54
+ /**
55
+ * Initialize an observation file with header metadata.
56
+ *
57
+ * Creates the file at `.session/{storyId}-tandem-{agent}.md` with
58
+ * a header containing observer agent, persona, phase, and start timestamp.
59
+ */
60
+ export declare function initObservationFile(config: ObservationWriterConfig): ObservationResult<{
61
+ path: string;
62
+ }>;
63
+ /**
64
+ * Append an observation entry to an existing observation file.
65
+ *
66
+ * Each append is entry-atomic: the complete entry (separator, timestamp,
67
+ * trigger, observation text) is written in a single operation.
68
+ */
69
+ export declare function appendObservation(filePath: string, entry: ObservationEntry): ObservationResult;
70
+ /**
71
+ * Parse an observation file and return its entries.
72
+ *
73
+ * Used by bell mode to read recent observations for injection.
74
+ */
75
+ export declare function parseObservationFile(filePath: string): ObservationResult<{
76
+ header: ObservationFileHeader;
77
+ entries: ParsedObservationEntry[];
78
+ }>;
79
+ //# sourceMappingURL=observation-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observation-writer.d.ts","sourceRoot":"","sources":["../../src/workflow/observation-writer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,aAAa,EAAE,MAAM,CAAC;IACtB,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG,OAAO;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AAMD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,uBAAuB,GAC9B,iBAAiB,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAkBrC;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,gBAAgB,GACtB,iBAAiB,CAkBnB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,GACf,iBAAiB,CAAC;IAAE,MAAM,EAAE,qBAAqB,CAAC;IAAC,OAAO,EAAE,sBAAsB,EAAE,CAAA;CAAE,CAAC,CAsCzF"}