@agentwhy/cli 0.0.0-dev

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 (400) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +2 -0
  3. package/README.md +181 -0
  4. package/THIRD_PARTY_NOTICES.md +31 -0
  5. package/dist/adapter/claude-code/contract/assumptions.js +208 -0
  6. package/dist/adapter/claude-code/contract/denials.js +15 -0
  7. package/dist/adapter/claude-code/contract/entry-points.js +15 -0
  8. package/dist/adapter/claude-code/contract/fields.js +73 -0
  9. package/dist/adapter/claude-code/contract/hooks.js +96 -0
  10. package/dist/adapter/claude-code/contract/identifiers.js +15 -0
  11. package/dist/adapter/claude-code/contract/layout.js +29 -0
  12. package/dist/adapter/claude-code/contract/line-types.js +26 -0
  13. package/dist/adapter/claude-code/contract/projects.js +23 -0
  14. package/dist/adapter/claude-code/contract/recognition.js +14 -0
  15. package/dist/adapter/claude-code/contract/session-title.js +20 -0
  16. package/dist/adapter/claude-code/contract/settings.js +27 -0
  17. package/dist/adapter/claude-code/contract/task-notifications.js +33 -0
  18. package/dist/adapter/claude-code/contract/tools.js +37 -0
  19. package/dist/adapter/claude-code/contract/version.js +51 -0
  20. package/dist/adapter/claude-code/discovery/claude-code-project-catalogue.js +129 -0
  21. package/dist/adapter/claude-code/discovery/claude-code-recognition.js +46 -0
  22. package/dist/adapter/claude-code/discovery/claude-code-session-catalogue.js +100 -0
  23. package/dist/adapter/claude-code/discovery/claude-code-session-discovery.js +61 -0
  24. package/dist/adapter/claude-code/discovery/claude-code-session-titles.js +28 -0
  25. package/dist/adapter/claude-code/discovery/discovered-session.js +1 -0
  26. package/dist/adapter/claude-code/discovery/session-entries.js +41 -0
  27. package/dist/adapter/claude-code/discovery/transcript-tail.js +81 -0
  28. package/dist/adapter/claude-code/events/claude-code-session-source.js +197 -0
  29. package/dist/adapter/claude-code/events/delegation-index.js +15 -0
  30. package/dist/adapter/claude-code/events/transcript-scan.js +179 -0
  31. package/dist/adapter/claude-code/hooks/hook-output.js +42 -0
  32. package/dist/adapter/claude-code/hooks/pre-tool-use-input.js +23 -0
  33. package/dist/adapter/claude-code/hooks/stop-input.js +25 -0
  34. package/dist/adapter/claude-code/hooks/subagent-stop-input.js +26 -0
  35. package/dist/adapter/claude-code/policy/deny-rules.js +46 -0
  36. package/dist/adapter/claude-code/probe/claude-code-probe.js +86 -0
  37. package/dist/adapter/claude-code/probe/collectors/agent-tool-input-key-collector.js +24 -0
  38. package/dist/adapter/claude-code/probe/collectors/denial-kind-collector.js +20 -0
  39. package/dist/adapter/claude-code/probe/collectors/denied-call-collector.js +11 -0
  40. package/dist/adapter/claude-code/probe/collectors/identifier-collector.js +19 -0
  41. package/dist/adapter/claude-code/probe/collectors/line-collector.js +1 -0
  42. package/dist/adapter/claude-code/probe/collectors/line-type-collector.js +29 -0
  43. package/dist/adapter/claude-code/probe/collectors/sidechain-collector.js +20 -0
  44. package/dist/adapter/claude-code/probe/collectors/task-notification-collector.js +51 -0
  45. package/dist/adapter/claude-code/probe/collectors/tool-result-reference-collector.js +31 -0
  46. package/dist/adapter/claude-code/probe/collectors/tool-use-collector.js +24 -0
  47. package/dist/adapter/claude-code/probe/collectors/tool-version-collector.js +14 -0
  48. package/dist/adapter/claude-code/probe/collectors/top-level-key-collector.js +14 -0
  49. package/dist/adapter/claude-code/probe/collectors/unknown-line-type-key-collector.js +24 -0
  50. package/dist/adapter/claude-code/probe/collectors/working-directory-collector.js +28 -0
  51. package/dist/adapter/claude-code/probe/doctor-report.js +1 -0
  52. package/dist/adapter/claude-code/probe/meta-tally.js +42 -0
  53. package/dist/adapter/claude-code/probe/session-probe.js +1 -0
  54. package/dist/adapter/claude-code/probe/session-tally.js +41 -0
  55. package/dist/adapter/claude-code/probe/transcript-line.js +30 -0
  56. package/dist/adapter/claude-code/probe/transcript-tally.js +74 -0
  57. package/dist/adapter/claude-code/settings/deny-entries.js +65 -0
  58. package/dist/adapter/claude-code/settings/hook-entries.js +303 -0
  59. package/dist/adapter/codex/contract/actions.js +69 -0
  60. package/dist/adapter/codex/contract/assumptions.js +55 -0
  61. package/dist/adapter/codex/contract/capabilities.js +24 -0
  62. package/dist/adapter/codex/contract/delegations.js +30 -0
  63. package/dist/adapter/codex/contract/deliveries.js +25 -0
  64. package/dist/adapter/codex/contract/envelope.js +33 -0
  65. package/dist/adapter/codex/contract/hook-refusals.js +14 -0
  66. package/dist/adapter/codex/contract/hooks.js +46 -0
  67. package/dist/adapter/codex/contract/messages.js +47 -0
  68. package/dist/adapter/codex/contract/permissions.js +27 -0
  69. package/dist/adapter/codex/contract/reviews.js +13 -0
  70. package/dist/adapter/codex/contract/session.js +31 -0
  71. package/dist/adapter/codex/contract/turns.js +23 -0
  72. package/dist/adapter/codex/contract/version.js +15 -0
  73. package/dist/adapter/codex/discovery/codex-conversations.js +44 -0
  74. package/dist/adapter/codex/discovery/codex-project-catalogue.js +49 -0
  75. package/dist/adapter/codex/discovery/codex-recognition.js +20 -0
  76. package/dist/adapter/codex/discovery/codex-session-catalogue.js +28 -0
  77. package/dist/adapter/codex/discovery/codex-session-discovery.js +115 -0
  78. package/dist/adapter/codex/discovery/codex-session-index.js +21 -0
  79. package/dist/adapter/codex/discovery/codex-session-titles.js +135 -0
  80. package/dist/adapter/codex/discovery/session-header.js +86 -0
  81. package/dist/adapter/codex/discovery/session-owners.js +11 -0
  82. package/dist/adapter/codex/discovery/session-roots.js +49 -0
  83. package/dist/adapter/codex/events/action-items.js +138 -0
  84. package/dist/adapter/codex/events/capability-records.js +26 -0
  85. package/dist/adapter/codex/events/codex-session-source.js +121 -0
  86. package/dist/adapter/codex/events/hook-refusals.js +27 -0
  87. package/dist/adapter/codex/events/rollout-scan.js +614 -0
  88. package/dist/adapter/codex/events/turn-permissions.js +60 -0
  89. package/dist/adapter/codex/hooks/pre-tool-use-input.js +24 -0
  90. package/dist/adapter/codex/hooks/stop-refusals.js +57 -0
  91. package/dist/adapter/codex/probe/codex-doctor-report.js +1 -0
  92. package/dist/adapter/codex/probe/codex-probe.js +268 -0
  93. package/dist/adapter/codex/settings/codex-hooks.js +83 -0
  94. package/dist/cli/cli-command.js +1 -0
  95. package/dist/cli/command-router.js +42 -0
  96. package/dist/cli/commands/check-cli-command.js +128 -0
  97. package/dist/cli/commands/codex-stop-cli-command.js +27 -0
  98. package/dist/cli/commands/doctor-arguments.js +32 -0
  99. package/dist/cli/commands/doctor-cli-command.js +31 -0
  100. package/dist/cli/commands/doctor-usage.js +14 -0
  101. package/dist/cli/commands/init-cli-command.js +123 -0
  102. package/dist/cli/commands/menu-cli-command.js +58 -0
  103. package/dist/cli/commands/notify-cli-command.js +158 -0
  104. package/dist/cli/commands/refuse-cli-command.js +79 -0
  105. package/dist/cli/commands/report-arguments.js +62 -0
  106. package/dist/cli/commands/report-cli-command.js +36 -0
  107. package/dist/cli/commands/report-usage.js +41 -0
  108. package/dist/cli/commands/sessions-cli-command.js +184 -0
  109. package/dist/cli/commands/start-cli-command.js +83 -0
  110. package/dist/cli/commands/watch-cli-command.js +142 -0
  111. package/dist/cli/exit-codes.js +13 -0
  112. package/dist/cli/project-switches.js +46 -0
  113. package/dist/cli.js +80 -0
  114. package/dist/composition-root.js +411 -0
  115. package/dist/core/access/command-line.js +454 -0
  116. package/dist/core/access/listing.js +58 -0
  117. package/dist/core/access/path-shape.js +59 -0
  118. package/dist/core/access/path-tokens.js +37 -0
  119. package/dist/core/access/protected-access.js +310 -0
  120. package/dist/core/access/protected-values.js +102 -0
  121. package/dist/core/access/recorded-effect.js +67 -0
  122. package/dist/core/access/returns.js +173 -0
  123. package/dist/core/access/search-output.js +34 -0
  124. package/dist/core/access/search-reach.js +268 -0
  125. package/dist/core/access/uses.js +143 -0
  126. package/dist/core/access/words-before.js +52 -0
  127. package/dist/core/agent.js +1 -0
  128. package/dist/core/capability.js +11 -0
  129. package/dist/core/combined-project-catalogue.js +36 -0
  130. package/dist/core/combined-session-catalogue.js +25 -0
  131. package/dist/core/completeness.js +10 -0
  132. package/dist/core/context.js +1 -0
  133. package/dist/core/correlation/correlate.js +329 -0
  134. package/dist/core/delegation.js +1 -0
  135. package/dist/core/detector/prompt-signals.js +78 -0
  136. package/dist/core/entry-point.js +1 -0
  137. package/dist/core/event.js +1 -0
  138. package/dist/core/evidence.js +9 -0
  139. package/dist/core/late-message.js +32 -0
  140. package/dist/core/message.js +1 -0
  141. package/dist/core/nearest-project.js +28 -0
  142. package/dist/core/policy/default-policy.js +32 -0
  143. package/dist/core/policy/glob.js +56 -0
  144. package/dist/core/policy/parse-policy.js +70 -0
  145. package/dist/core/policy/policy.js +20 -0
  146. package/dist/core/policy/resolve-policy.js +16 -0
  147. package/dist/core/project-catalogue.js +1 -0
  148. package/dist/core/project-root.js +133 -0
  149. package/dist/core/provider-titles.js +10 -0
  150. package/dist/core/redaction/entropy.js +46 -0
  151. package/dist/core/redaction/redacted.js +4 -0
  152. package/dist/core/redaction/redactor.js +339 -0
  153. package/dist/core/redaction/secret-patterns.js +22 -0
  154. package/dist/core/redaction/value-shapes.js +81 -0
  155. package/dist/core/redaction/value-trace.js +110 -0
  156. package/dist/core/review.js +1 -0
  157. package/dist/core/session-catalogue.js +19 -0
  158. package/dist/core/session-filter.js +42 -0
  159. package/dist/core/session-format.js +27 -0
  160. package/dist/core/session-model.js +1 -0
  161. package/dist/core/session-reader.js +22 -0
  162. package/dist/core/session-records.js +1 -0
  163. package/dist/core/session-source.js +1 -0
  164. package/dist/core/session-titles.js +21 -0
  165. package/dist/core/turn.js +1 -0
  166. package/dist/doctor/codex-doctor.js +14 -0
  167. package/dist/doctor/doctor-use-case.js +1 -0
  168. package/dist/doctor/format-selecting-doctor.js +28 -0
  169. package/dist/doctor/render/attention/attention-rule.js +1 -0
  170. package/dist/doctor/render/attention/doctor-attention-rules.js +28 -0
  171. package/dist/doctor/render/attention/rules/damaged-meta-files-rule.js +8 -0
  172. package/dist/doctor/render/attention/rules/damaged-transcripts-rule.js +9 -0
  173. package/dist/doctor/render/attention/rules/incomplete-subagent-pairs-rule.js +6 -0
  174. package/dist/doctor/render/attention/rules/missing-main-transcript-rule.js +5 -0
  175. package/dist/doctor/render/attention/rules/missing-spilled-results-rule.js +6 -0
  176. package/dist/doctor/render/attention/rules/multiple-working-directories-rule.js +15 -0
  177. package/dist/doctor/render/attention/rules/unknown-denial-kinds-rule.js +5 -0
  178. package/dist/doctor/render/attention/rules/unknown-line-types-rule.js +6 -0
  179. package/dist/doctor/render/attention/rules/unrecognised-entries-rule.js +6 -0
  180. package/dist/doctor/render/attention/rules/unusable-directories-rule.js +12 -0
  181. package/dist/doctor/render/attention/transcript-scopes.js +6 -0
  182. package/dist/doctor/render/codex-text-doctor-renderer.js +97 -0
  183. package/dist/doctor/render/doctor-renderers.js +1 -0
  184. package/dist/doctor/render/json-doctor-renderer.js +7 -0
  185. package/dist/doctor/render/output-format.js +1 -0
  186. package/dist/doctor/render/text-doctor-renderer.js +124 -0
  187. package/dist/doctor/session-doctor.js +16 -0
  188. package/dist/infrastructure/clack-asker.js +24 -0
  189. package/dist/infrastructure/clack-chooser.js +40 -0
  190. package/dist/infrastructure/clack-multi-chooser.js +31 -0
  191. package/dist/infrastructure/file-alert-store.js +120 -0
  192. package/dist/infrastructure/file-checked-store.js +55 -0
  193. package/dist/infrastructure/file-mark-store.js +67 -0
  194. package/dist/infrastructure/file-onboarding-store.js +93 -0
  195. package/dist/infrastructure/folder-window.js +26 -0
  196. package/dist/infrastructure/node-agentwhy-invocation.js +99 -0
  197. package/dist/infrastructure/node-browser.js +40 -0
  198. package/dist/infrastructure/node-file-system.js +111 -0
  199. package/dist/infrastructure/node-local-server.js +115 -0
  200. package/dist/infrastructure/node-text-input.js +26 -0
  201. package/dist/infrastructure/os-notifier.js +21 -0
  202. package/dist/infrastructure/osascript-folder-chooser.js +53 -0
  203. package/dist/infrastructure/powershell-folder-chooser.js +78 -0
  204. package/dist/infrastructure/real-directory.js +18 -0
  205. package/dist/infrastructure/stream-printer.js +11 -0
  206. package/dist/infrastructure/terminal-banner.js +19 -0
  207. package/dist/ports/agentwhy-invocation.js +1 -0
  208. package/dist/ports/alert-store.js +1 -0
  209. package/dist/ports/asker.js +1 -0
  210. package/dist/ports/browser.js +1 -0
  211. package/dist/ports/checked-store.js +1 -0
  212. package/dist/ports/chooser.js +1 -0
  213. package/dist/ports/directory-reader.js +1 -0
  214. package/dist/ports/file-access-error.js +11 -0
  215. package/dist/ports/file-reader.js +1 -0
  216. package/dist/ports/file-tail-reader.js +1 -0
  217. package/dist/ports/file-writer.js +1 -0
  218. package/dist/ports/folder-chooser.js +1 -0
  219. package/dist/ports/local-server.js +1 -0
  220. package/dist/ports/mark-store.js +10 -0
  221. package/dist/ports/multi-chooser.js +1 -0
  222. package/dist/ports/notifier.js +1 -0
  223. package/dist/ports/onboarding-store.js +1 -0
  224. package/dist/ports/printer.js +1 -0
  225. package/dist/ports/text-input.js +1 -0
  226. package/dist/refuse/command-reach.js +135 -0
  227. package/dist/refuse/command-refusal.js +88 -0
  228. package/dist/refuse/render/codex-stop-words.js +21 -0
  229. package/dist/refuse/render/refusal-words.js +34 -0
  230. package/dist/report/build-report.js +1037 -0
  231. package/dist/report/check/actions-digest.js +73 -0
  232. package/dist/report/check/check-lines.js +83 -0
  233. package/dist/report/check/mark-request.js +90 -0
  234. package/dist/report/check/marks.js +84 -0
  235. package/dist/report/check/render/text-digest-renderer.js +332 -0
  236. package/dist/report/check/session-actions.js +90 -0
  237. package/dist/report/check/session-check.js +91 -0
  238. package/dist/report/choose-policy.js +61 -0
  239. package/dist/report/flow-reads.js +18 -0
  240. package/dist/report/private-files/tell-lists.js +84 -0
  241. package/dist/report/project-rules.js +33 -0
  242. package/dist/report/render/home-relative.js +18 -0
  243. package/dist/report/render/html-head.js +26 -0
  244. package/dist/report/render/html-report-components.js +48 -0
  245. package/dist/report/render/html-report-styles.js +500 -0
  246. package/dist/report/render/html-sidebar.js +42 -0
  247. package/dist/report/render/path-tail.js +14 -0
  248. package/dist/report/render/report-copy.js +1177 -0
  249. package/dist/report/render/report-page/advanced-view.js +167 -0
  250. package/dist/report/render/report-page/file-story.js +114 -0
  251. package/dist/report/render/report-page/files-view.js +381 -0
  252. package/dist/report/render/report-page/files.js +77 -0
  253. package/dist/report/render/report-page/fix-wizard-script.js +269 -0
  254. package/dist/report/render/report-page/fix-wizard.js +310 -0
  255. package/dist/report/render/report-page/helpers-view.js +383 -0
  256. package/dist/report/render/report-page/helpers.js +51 -0
  257. package/dist/report/render/report-page/item-names.js +63 -0
  258. package/dist/report/render/report-page/protect-patterns.js +13 -0
  259. package/dist/report/render/report-page/providers.js +208 -0
  260. package/dist/report/render/report-page/record-view.js +367 -0
  261. package/dist/report/render/report-page/report-page-renderer.js +129 -0
  262. package/dist/report/render/report-page/report-views.js +31 -0
  263. package/dist/report/render/report-page/story-window.js +356 -0
  264. package/dist/report/render/report-page/times.js +25 -0
  265. package/dist/report/render/report-page/to-do-view.js +299 -0
  266. package/dist/report/render/report-page/to-do.js +152 -0
  267. package/dist/report/render/report-page.js +1 -0
  268. package/dist/report/render/session-view.js +250 -0
  269. package/dist/report/render/text-report-renderer.js +981 -0
  270. package/dist/report/render/ui/add-file-popup.js +122 -0
  271. package/dist/report/render/ui/app-sidebar.js +78 -0
  272. package/dist/report/render/ui/ask-panel.js +80 -0
  273. package/dist/report/render/ui/avatar.js +19 -0
  274. package/dist/report/render/ui/backdrop.js +29 -0
  275. package/dist/report/render/ui/brand-mark.js +4 -0
  276. package/dist/report/render/ui/button.js +67 -0
  277. package/dist/report/render/ui/callout.js +20 -0
  278. package/dist/report/render/ui/chat-example.js +17 -0
  279. package/dist/report/render/ui/checklist.js +50 -0
  280. package/dist/report/render/ui/confirm-dialog.js +34 -0
  281. package/dist/report/render/ui/data-table.js +49 -0
  282. package/dist/report/render/ui/drawer.js +25 -0
  283. package/dist/report/render/ui/file-chip.js +37 -0
  284. package/dist/report/render/ui/fold-line.js +22 -0
  285. package/dist/report/render/ui/guide-card.js +25 -0
  286. package/dist/report/render/ui/hero.js +37 -0
  287. package/dist/report/render/ui/labelled-select.js +10 -0
  288. package/dist/report/render/ui/live-script.js +222 -0
  289. package/dist/report/render/ui/local-date.js +58 -0
  290. package/dist/report/render/ui/mode-icon.js +6 -0
  291. package/dist/report/render/ui/page-shell.js +101 -0
  292. package/dist/report/render/ui/pill-tabs.js +47 -0
  293. package/dist/report/render/ui/popup.js +77 -0
  294. package/dist/report/render/ui/progress.js +35 -0
  295. package/dist/report/render/ui/project-list.js +284 -0
  296. package/dist/report/render/ui/scope-choice.js +19 -0
  297. package/dist/report/render/ui/stats.js +21 -0
  298. package/dist/report/render/ui/status-icon.js +30 -0
  299. package/dist/report/render/ui/status-look.js +21 -0
  300. package/dist/report/render/ui/switch.js +11 -0
  301. package/dist/report/render/ui/tag.js +19 -0
  302. package/dist/report/render/ui/task-list.js +56 -0
  303. package/dist/report/render/ui/tokens.js +46 -0
  304. package/dist/report/render/ui/update-notice.js +146 -0
  305. package/dist/report/render/ui/words/app-words.js +163 -0
  306. package/dist/report/render/ui/words/conversations-words.js +457 -0
  307. package/dist/report/render/ui/words/month-words.js +59 -0
  308. package/dist/report/render/ui/words/onboarding-words.js +446 -0
  309. package/dist/report/render/ui/words/projects-words.js +217 -0
  310. package/dist/report/render/ui/words/report-words.js +2099 -0
  311. package/dist/report/render/ui/words/settings-words.js +611 -0
  312. package/dist/report/render/ui/words/to-fix-words.js +287 -0
  313. package/dist/report/report-model.js +2 -0
  314. package/dist/report/report-use-case.js +1 -0
  315. package/dist/report/rule-names.js +20 -0
  316. package/dist/report/session-report.js +163 -0
  317. package/dist/report/start/app-nav.js +37 -0
  318. package/dist/report/start/conversations/calendar-view.js +104 -0
  319. package/dist/report/start/conversations/conversation-columns.js +187 -0
  320. package/dist/report/start/conversations/conversations-renderer.js +54 -0
  321. package/dist/report/start/conversations/empty-week.js +120 -0
  322. package/dist/report/start/conversations/files-window.js +166 -0
  323. package/dist/report/start/conversations/period-section.js +280 -0
  324. package/dist/report/start/conversations/periods-script.js +440 -0
  325. package/dist/report/start/conversations/periods.js +110 -0
  326. package/dist/report/start/conversations/week-view.js +30 -0
  327. package/dist/report/start/conversations/weeks.js +17 -0
  328. package/dist/report/start/month/month-renderer.js +50 -0
  329. package/dist/report/start/month/month-view.js +135 -0
  330. package/dist/report/start/month/months.js +17 -0
  331. package/dist/report/start/onboarding/done.js +171 -0
  332. package/dist/report/start/onboarding/finish-onboarding.js +93 -0
  333. package/dist/report/start/onboarding/intro.js +100 -0
  334. package/dist/report/start/onboarding/onboarding-changes.js +40 -0
  335. package/dist/report/start/onboarding/onboarding-renderer.js +195 -0
  336. package/dist/report/start/onboarding/onboarding-script.js +400 -0
  337. package/dist/report/start/onboarding/onboarding-view.js +98 -0
  338. package/dist/report/start/onboarding/project-step.js +210 -0
  339. package/dist/report/start/onboarding/steps.js +239 -0
  340. package/dist/report/start/onboarding/welcome.js +66 -0
  341. package/dist/report/start/page-notice.js +10 -0
  342. package/dist/report/start/projects/index-projects.js +43 -0
  343. package/dist/report/start/projects/moved-page.js +82 -0
  344. package/dist/report/start/projects/project-switch.js +138 -0
  345. package/dist/report/start/projects/projects-window.js +67 -0
  346. package/dist/report/start/projects/temporary-space.js +18 -0
  347. package/dist/report/start/render/air-datepicker-vendor.js +27 -0
  348. package/dist/report/start/render/session-status.js +41 -0
  349. package/dist/report/start/render/start-words.js +84 -0
  350. package/dist/report/start/repository.js +28 -0
  351. package/dist/report/start/serve/index-handler.js +372 -0
  352. package/dist/report/start/serve/onboarding-request.js +50 -0
  353. package/dist/report/start/serve/settings-request.js +1 -0
  354. package/dist/report/start/serve/settings-setup.js +193 -0
  355. package/dist/report/start/session-index.js +1 -0
  356. package/dist/report/start/session-start.js +974 -0
  357. package/dist/report/start/settings/alerts-tab.js +104 -0
  358. package/dist/report/start/settings/files-tab.js +169 -0
  359. package/dist/report/start/settings/general-tab.js +71 -0
  360. package/dist/report/start/settings/settings-renderer.js +254 -0
  361. package/dist/report/start/settings/settings-script.js +161 -0
  362. package/dist/report/start/settings/settings-view.js +240 -0
  363. package/dist/report/start/settings/settings-windows.js +334 -0
  364. package/dist/report/start/settings-files.js +43 -0
  365. package/dist/report/start/to-fix/done-list.js +45 -0
  366. package/dist/report/start/to-fix/file-window.js +110 -0
  367. package/dist/report/start/to-fix/to-fix-list.js +70 -0
  368. package/dist/report/start/to-fix/to-fix-renderer.js +237 -0
  369. package/dist/report/start/to-fix/to-fix-script.js +94 -0
  370. package/dist/report/start/to-fix/to-fix-view.js +124 -0
  371. package/dist/report/watch/agent-alert.js +72 -0
  372. package/dist/report/watch/notice-choices.js +35 -0
  373. package/dist/report/watch/notice-settings.js +65 -0
  374. package/dist/report/watch/preferences.js +100 -0
  375. package/dist/report/watch/render/instruction-words.js +54 -0
  376. package/dist/report/watch/render/notice-words.js +182 -0
  377. package/dist/report/watch/subagent-watch.js +345 -0
  378. package/dist/report/watch/watch-notice.js +1 -0
  379. package/dist/setup/behind.js +18 -0
  380. package/dist/setup/codex-mirror.js +171 -0
  381. package/dist/setup/not-a-project.js +19 -0
  382. package/dist/setup/project-setup.js +644 -0
  383. package/dist/setup/protected-patterns.js +30 -0
  384. package/dist/shared/colour.js +23 -0
  385. package/dist/shared/compare.js +4 -0
  386. package/dist/shared/content-version.js +13 -0
  387. package/dist/shared/counter.js +11 -0
  388. package/dist/shared/file-stamp.js +4 -0
  389. package/dist/shared/json.js +13 -0
  390. package/dist/shared/label.js +13 -0
  391. package/dist/shared/package-name.js +6 -0
  392. package/dist/shared/plain-invocation.js +44 -0
  393. package/dist/shared/plain-version.js +21 -0
  394. package/dist/shared/printable.js +25 -0
  395. package/dist/shared/renderer.js +1 -0
  396. package/dist/shared/sentence.js +20 -0
  397. package/dist/shared/terminal-logo.js +41 -0
  398. package/dist/shared/text-table.js +15 -0
  399. package/dist/shared/wrap.js +29 -0
  400. package/package.json +70 -0
@@ -0,0 +1,100 @@
1
+ import { isJsonObject, parseJsonObject } from '../../shared/json.js';
2
+ import { ALERT_THRESHOLDS } from './agent-alert.js';
3
+ import { CLEAN_MODES, NOTICE_CHANNELS, NOTICE_LANGS, SAID_AS, } from './notice-choices.js';
4
+ export const NO_PREFERENCES = { defaults: {}, projects: {} };
5
+ /**
6
+ * A file this tool wrote, read back. Anything else is `unusable`: a preferences file is not a place to guess, and
7
+ * the built-in answers are a better outcome than a threshold read out of a shape nobody recognised. A missing file
8
+ * is not unusable - nobody has chosen anything yet, which is exactly what the built-in answers are for.
9
+ */
10
+ export function readPreferences(text) {
11
+ if (text === undefined)
12
+ return { kind: 'read', preferences: NO_PREFERENCES };
13
+ const parsed = parseJsonObject(text);
14
+ if (parsed === undefined)
15
+ return { kind: 'unusable' };
16
+ const defaults = choicesIn(parsed.defaults);
17
+ const projects = isJsonObject(parsed.projects) ? parsed.projects : {};
18
+ if (defaults === undefined || (parsed.projects !== undefined && !isJsonObject(parsed.projects)))
19
+ return { kind: 'unusable' };
20
+ const perProject = {};
21
+ for (const [directory, chosen] of Object.entries(projects)) {
22
+ const choices = choicesIn(chosen);
23
+ if (choices === undefined)
24
+ return { kind: 'unusable' };
25
+ perProject[directory] = choices;
26
+ }
27
+ return { kind: 'read', preferences: { defaults, projects: perProject } };
28
+ }
29
+ /** The file as it is written: the same shape this reads, with the keys a version of this tool knows. */
30
+ export function writtenPreferences(preferences) {
31
+ const projects = Object.fromEntries(Object.entries(preferences.projects)
32
+ .filter(([, choices]) => Object.keys(choices).length > 0)
33
+ .sort(([one], [other]) => one.localeCompare(other)));
34
+ return `${JSON.stringify({ defaults: preferences.defaults, projects }, undefined, 2)}\n`;
35
+ }
36
+ /**
37
+ * The choices that apply where a session runs (R24): this project's, over this person's, over nothing at all. The
38
+ * flags a hook's command line carries are applied after these, by the caller - someone who wrote a flag meant it.
39
+ *
40
+ * A project is matched by directory, and the longest match wins: a session's working directory may be a directory
41
+ * inside the project the choice was made for, and a choice made for a project holds everywhere in it.
42
+ */
43
+ export function preferencesFor(preferences, directory) {
44
+ const project = directory === undefined ? undefined : longestMatch(preferences.projects, directory);
45
+ return { ...preferences.defaults, ...(project ?? {}) };
46
+ }
47
+ /** The same choices with one project's answers replaced, for the writer. An empty set of answers takes it out. */
48
+ export function withProjectChoices(preferences, directory, choices) {
49
+ const { [directory]: _replaced, ...others } = preferences.projects;
50
+ return {
51
+ defaults: preferences.defaults,
52
+ projects: Object.keys(choices).length === 0 ? others : { ...others, [directory]: choices },
53
+ };
54
+ }
55
+ /**
56
+ * The one project entry that governs a directory, the same way `preferencesFor` picks it: by the longest ancestor
57
+ * match, never by an exact key alone. A directory inside a project a choice was made for is still inside it.
58
+ */
59
+ export function longestMatch(projects, directory) {
60
+ const inside = Object.keys(projects)
61
+ .filter((project) => directory === project || directory.startsWith(project.endsWith('/') ? project : `${project}/`))
62
+ .sort((one, other) => other.length - one.length);
63
+ return inside[0] === undefined ? undefined : projects[inside[0]];
64
+ }
65
+ /** One set of answers, or `undefined` where a key holds something this version does not recognise. */
66
+ function choicesIn(value) {
67
+ if (value === undefined)
68
+ return {};
69
+ if (!isJsonObject(value))
70
+ return undefined;
71
+ const chosen = value;
72
+ const on = oneOf(chosen.on, ALERT_THRESHOLDS);
73
+ const clean = oneOf(chosen.clean, CLEAN_MODES);
74
+ const say = oneOf(chosen.say, SAID_AS);
75
+ const notify = channelsIn(chosen.notify);
76
+ const lang = oneOf(chosen.lang, NOTICE_LANGS);
77
+ if (on === 'unknown' || clean === 'unknown' || say === 'unknown' || notify === 'unknown' || lang === 'unknown')
78
+ return undefined;
79
+ return {
80
+ ...(on === undefined ? {} : { on }),
81
+ ...(clean === undefined ? {} : { clean }),
82
+ ...(say === undefined ? {} : { say }),
83
+ ...(notify === undefined ? {} : { notify }),
84
+ ...(lang === undefined ? {} : { lang }),
85
+ };
86
+ }
87
+ function oneOf(value, known) {
88
+ if (value === undefined)
89
+ return undefined;
90
+ const found = known.find((candidate) => candidate === value);
91
+ return found ?? 'unknown';
92
+ }
93
+ function channelsIn(value) {
94
+ if (value === undefined)
95
+ return undefined;
96
+ if (!Array.isArray(value) || value.length === 0)
97
+ return 'unknown';
98
+ const channels = value.map((name) => NOTICE_CHANNELS.find((channel) => channel === name));
99
+ return channels.includes(undefined) ? 'unknown' : [...new Set(channels)];
100
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * What the session's own agent is asked to say, when a finding is set to be said by it
3
+ * (`specs/2026-09-21-the-agent-tells-you.md` §5, R12, R12a, R12b). These are the words eleven sessions of eleven
4
+ * relayed, and they are the third version: the two before them were refused, and for reasons worth keeping in view.
5
+ *
6
+ * - **It is agentwhy's finding, passed on as agentwhy's.** The first version told the agent to assert it in its own
7
+ * voice, and a session refused: it was being told to state as fact something it could not check.
8
+ * - **Nothing is forbidden but going back to the file.** That same version forbade the agent to confirm anything,
9
+ * which - together with the claim above - is what an injection asks for, and was named as such.
10
+ * - **No link.** A version carrying a `file://` address to a page outside the project lost the agent on that alone
11
+ * (B9g), so the offer is a command, named as what it is.
12
+ * - **Only what the records establish.** A session handed a claim that did not match its own context refused it and
13
+ * said so to the person (R12b). The consequence is worded as what the records show - the conversation and the
14
+ * session's own files - and not as a fact about a provider's infrastructure.
15
+ */
16
+ export function instructionFor(files, command) {
17
+ const named = files.slice(0, NAMED_AT_MOST);
18
+ const rest = files.length - named.length;
19
+ const which = named.length === 0
20
+ ? 'a protected file'
21
+ : `the protected ${named.length === 1 ? 'file' : 'files'} ${list(named)}${rest === 0 ? '' : ` and ${rest} more`}`;
22
+ // What the agent is asked not to do is said about the same files it was just told about, in the same words.
23
+ const them = named.length <= 1 ? 'it' : 'them';
24
+ return [
25
+ `agentwhy, the local tool this user runs, checked this turn: a value from ${which} is in this conversation.`,
26
+ 'Tell the user, in one short message in the language of this conversation, that agentwhy found this, what it',
27
+ 'means - the value went wherever this conversation goes and stays in the session records kept on this machine,',
28
+ 'so deleting messages does not recall it - and that rotating that credential where it was issued is what undoes',
29
+ `it. You read ${named.length === 0 ? 'it' : which} in this conversation, so you can see the finding yourself.`,
30
+ `Do not open or read ${them} again, and do not repeat the value.`,
31
+ `Then ask whether to open agentwhy's report for this session, and run \`${command}\` only if they say yes.`,
32
+ 'Do not continue the earlier task in this message.',
33
+ ].join(' ');
34
+ }
35
+ /**
36
+ * How many files the instruction names before it counts the rest. Three keeps it inside what a person reads in one
37
+ * go - and the person reads it too, framed as `Stop hook error:` in the terminal (B9a, R12a).
38
+ */
39
+ const NAMED_AT_MOST = 3;
40
+ /**
41
+ * The command the agent offers to run: this session by its id, and nothing of what the report holds (R18, R19), with
42
+ * agentwhy invoked the way the hook invokes it.
43
+ */
44
+ export function reportCommand(sessionId, invocation) {
45
+ return `${invocation} report --input ${sessionId} --open --quiet`;
46
+ }
47
+ function list(files) {
48
+ const [one, two, three] = files;
49
+ if (three !== undefined)
50
+ return `${one}, ${two} and ${three}`;
51
+ if (two !== undefined)
52
+ return `${one} and ${two}`;
53
+ return String(one);
54
+ }
@@ -0,0 +1,182 @@
1
+ /** The title every notice carries, wherever it is shown. */
2
+ export const NOTICE_TITLE = 'agentwhy';
3
+ /** Said the same way wherever details are offered, and last, where a cut notice loses it first. */
4
+ const DETAILS = 'Details: agentwhy report --open';
5
+ /**
6
+ * What to do, first, in the words `check` already uses for the same two cases. A notice arrives in a frame this
7
+ * project does not draw - grey italics under a reply, or three lines of a system notification - so the first thing
8
+ * read has to be the action, not the account (`a-notice-in-the-conversation.md` R4).
9
+ */
10
+ const ROTATE = 'ROTATE:';
11
+ const CHECK = 'CHECK:';
12
+ /** The third word, for the level that asks for nothing: a rule held, and the reader is being told so (R1, R3). */
13
+ const NOTE = 'NOTE:';
14
+ /**
15
+ * About what a macOS notification shows before it cuts the words (B4f, the user's screenshot: three lines of about
16
+ * 50 characters under the title). Every notice is written to fit it, so that what happened and where to look are
17
+ * both read; `tests/report/watch/render/notice-words.test.ts` holds each one to it.
18
+ */
19
+ export const NOTICE_BUDGET = 150;
20
+ /**
21
+ * Who is speaking, for the one channel with no title of its own. A terminal notification and a system notification
22
+ * are drawn with `NOTICE_TITLE` above them; the line in the conversation arrives under a frame Claude Code writes
23
+ * (`Stop says: …`), which names the event and not the tool - so the words say it instead. The budget in
24
+ * `NOTICE_BUDGET` is what a notification shows, and this is not one, so it is measured without this prefix.
25
+ */
26
+ export function withTitle(words) {
27
+ return words === '' ? '' : `${NOTICE_TITLE} · ${words}`;
28
+ }
29
+ const NOT_CHECKED = {
30
+ arguments: 'Finished agent not checked: watch was given arguments it does not know.',
31
+ input: 'Finished agent not checked: the hook input could not be read.',
32
+ policy: 'Finished agent not checked: the policy could not be read.',
33
+ session: "Finished agent not checked: the session's records could not be read.",
34
+ 'agent-not-found': "Finished agent not checked: it is not in the session's records yet.",
35
+ };
36
+ /**
37
+ * One notice in words, or no words for nothing to say (`specs/2026-09-16-when-an-agent-finishes.md` R5-R7, R15). It
38
+ * reads counts and enumerations only - the agent's type, how many files, how many attempts - so no path, value,
39
+ * identifier or task description can reach it, whatever the session held. Where the words are shown is decided after
40
+ * this.
41
+ */
42
+ export class NoticeWordsRenderer {
43
+ render(notice) {
44
+ switch (notice.kind) {
45
+ case 'quiet':
46
+ return '';
47
+ case 'not-checked':
48
+ return `${NOT_CHECKED[notice.reason]} ${DETAILS}`;
49
+ case 'alert':
50
+ return `${sentenceOf(notice.alert)} ${DETAILS}`;
51
+ case 'turn':
52
+ return turnWords(notice.remembered);
53
+ case 'clean':
54
+ return cleanWords(notice.first, notice.counts, notice.lang);
55
+ case 'preferences-unusable':
56
+ // What a person needs is what is in force now and the way to change it; the file's name is in the command.
57
+ return "Your notification choices could not be read, so agentwhy's own are in use. See: agentwhy notify";
58
+ }
59
+ }
60
+ }
61
+ /**
62
+ * A turn that found nothing (R4-R6), in the language the person reads (R29). Three lines, and the difference between
63
+ * them is the whole point:
64
+ *
65
+ * - the first quiet turn of a session says the watch is running, which is what silence cannot say;
66
+ * - a later quiet turn says only what this turn found, never what the session holds;
67
+ * - a quiet turn of a session that was not quiet says both, in that order, and says the earlier finding in the
68
+ * past tense: whether the key has since been rotated is not something a hook can know, and a line reading
69
+ * "1 value to rotate" at someone who rotated it an hour ago is a line they stop reading.
70
+ *
71
+ * Written for a person who does not build software (R29): the page's own words - a private file, your AI opened it -
72
+ * and "so far", because a clean turn is not a clean session and a line must never read as a promise about the rest.
73
+ * `Details:` is left off the two lines that report nothing: there is nothing in the report to go and look at, and
74
+ * the words are what a notification cuts first. The command stays in English, because it is typed.
75
+ */
76
+ function cleanWords(first, counts, lang) {
77
+ const words = CLEAN_WORDS[lang];
78
+ const earlier = counts.values > 0 ? words.valueEarlier(counts.values) : counts.reached > 0 ? words.reachedEarlier(counts.reached) : undefined;
79
+ if (earlier !== undefined)
80
+ return `${words.nothingNew} ${earlier} ${words.details}: agentwhy report --open`;
81
+ return first ? words.first : words.turn;
82
+ }
83
+ const CLEAN_WORDS = {
84
+ en: {
85
+ first: "✓ So far your AI hasn't opened any private files. I'm keeping watch.",
86
+ turn: "✓ Your AI didn't open any private files in this reply.",
87
+ nothingNew: 'Nothing new now.',
88
+ valueEarlier: (count) => `Earlier in this chat your AI read ${count === 1 ? 'a key' : `${count} keys`} from a private file.`,
89
+ reachedEarlier: (count) => `Earlier in this chat your AI opened ${count === 1 ? 'a private file' : `${count} private files`}.`,
90
+ details: 'Details',
91
+ },
92
+ pl: {
93
+ first: '✓ Jak dotąd AI nie otworzyło żadnego prywatnego pliku. Pilnuję dalej.',
94
+ turn: '✓ W tej odpowiedzi AI nie otworzyło żadnego prywatnego pliku.',
95
+ nothingNew: 'Teraz nic nowego.',
96
+ valueEarlier: (count) => `Wcześniej w tej rozmowie AI przeczytało ${count === 1 ? 'klucz' : `${count} ${polish(count, 'klucze', 'kluczy')}`} z prywatnego pliku.`,
97
+ reachedEarlier: (count) => `Wcześniej w tej rozmowie AI otworzyło ${count === 1 ? 'prywatny plik' : `${count} ${polish(count, 'prywatne pliki', 'prywatnych plików')}`}.`,
98
+ details: 'Szczegóły',
99
+ },
100
+ de: {
101
+ first: '✓ Bisher hat deine KI keine private Datei geöffnet. Ich passe weiter auf.',
102
+ turn: '✓ In dieser Antwort hat deine KI keine private Datei geöffnet.',
103
+ nothingNew: 'Jetzt nichts Neues.',
104
+ valueEarlier: (count) => `Vorhin hat deine KI ${count === 1 ? 'einen Schlüssel' : `${count} Schlüssel`} aus einer privaten Datei gelesen.`,
105
+ reachedEarlier: (count) => `Vorhin hat deine KI ${count === 1 ? 'eine private Datei' : `${count} private Dateien`} geöffnet.`,
106
+ details: 'Details',
107
+ },
108
+ };
109
+ /** Polish counts two ways past one: 2-4 take one form (22-24 too, 12-14 not), everything else the other. */
110
+ function polish(count, few, many) {
111
+ const units = count % 10;
112
+ const tens = count % 100;
113
+ return units >= 2 && units <= 4 && (tens < 12 || tens > 14) ? few : many;
114
+ }
115
+ function sentenceOf(alert) {
116
+ // The session's own agent is the conversation the reader is in. Calling it "an agent" would send them looking for one.
117
+ const who = alert.own === true ? 'This conversation' : alert.type === undefined ? 'An agent' : `${alert.type} agent`;
118
+ const files = alert.filesReached === undefined ? 'protected files' : plural(alert.filesReached, 'protected file', 'protected files');
119
+ // Which levels reach this point is decided by the threshold, before a notice is made. "Reached" counts the agents
120
+ // it started too, which the report shows apart.
121
+ // A value notice is held to the 150 characters a notification shows (`NOTICE_BUDGET`), so once the first clause has
122
+ // said "a protected file", the count that follows says "files" and not "protected files" again.
123
+ // The agent's type is what the transcript recorded: quoted as written, never recased.
124
+ const counted = alert.filesReached === undefined ? 'files' : plural(alert.filesReached, 'file', 'files');
125
+ /*
126
+ * A refusal is the one level that is good news, so it is said as news and asks for nothing
127
+ * (`the-agent-tells-you.md` R3). It is said only where the threshold asked for it, and only when it is the whole
128
+ * story: where a file was reached or a value written, those words come first and the refusals go unmentioned -
129
+ * they are what a notification cuts first, and the report has them either way.
130
+ * The rule is the subject, not the agent: "a rule refused" reads the same for a delegated agent and for the
131
+ * conversation itself, where "this conversation was refused" would not.
132
+ */
133
+ if (alert.level === 'refused') {
134
+ return `${NOTE} a rule refused ${plural(alert.refusedAttempts, 'attempt', 'attempts')} at protected files; nothing was reached.`;
135
+ }
136
+ if (alert.own === true) {
137
+ return alert.level === 'value'
138
+ ? `${ROTATE} a value from a protected file is in this conversation. ${capitalised(counted)} reached.`
139
+ : `${CHECK} ${who} reached ${files}; no value found in its messages.`;
140
+ }
141
+ return alert.level === 'value'
142
+ ? `${ROTATE} ${who} wrote a value from a protected file; its answer may carry it. ${capitalised(counted)} reached.`
143
+ : `${CHECK} ${who} reached ${files}; no value found in its messages.`;
144
+ }
145
+ /**
146
+ * A turn's worth of remembered alerts in one line (`a-notice-in-the-conversation.md` R12). One agent says exactly
147
+ * what its own notice said, so nothing is rewritten on the way; several are counted, because a line that listed
148
+ * them would be cut before the reader reached the end. What could not be checked is said too, never dropped.
149
+ */
150
+ export function turnWords(remembered) {
151
+ const [only] = remembered;
152
+ if (only === undefined)
153
+ return '';
154
+ if (remembered.length === 1)
155
+ return only.words;
156
+ const checked = remembered.filter((alert) => alert.level !== 'not-checked');
157
+ const missed = remembered.length - checked.length;
158
+ const unchecked = `${plural(missed, 'agent', 'agents')} could not be checked`;
159
+ if (checked.length === 0)
160
+ return `${CHECK} ${unchecked}. ${DETAILS}`;
161
+ /*
162
+ * A refused agent reached nothing, so it cannot be counted among the agents that did: a line saying "3 agents
163
+ * reached protected files" about two refusals and one reach would be false in the direction that matters. Where
164
+ * something was reached, the refusals go unsaid, exactly as they do in one agent's own notice.
165
+ */
166
+ const reached = checked.filter((alert) => alert.level === 'value' || alert.level === 'reached');
167
+ const values = reached.filter((alert) => alert.level === 'value').length;
168
+ const head = reached.length === 0
169
+ ? `${NOTE} a rule refused attempts by ${plural(checked.length, 'agent', 'agents')}; nothing was reached`
170
+ : values === 0
171
+ ? `${CHECK} ${plural(reached.length, 'agent', 'agents')} reached protected files; no value found in their messages`
172
+ : values === reached.length
173
+ ? `${ROTATE} ${plural(values, 'agent', 'agents')} wrote a value from a protected file; their answers may carry it`
174
+ : `${ROTATE} ${plural(reached.length, 'agent', 'agents')} reached protected files, ${values} wrote a value from one`;
175
+ return `${head}${missed === 0 ? '' : `; ${unchecked}`}. ${DETAILS}`;
176
+ }
177
+ function capitalised(words) {
178
+ return `${words.charAt(0).toUpperCase()}${words.slice(1)}`;
179
+ }
180
+ function plural(count, one, many) {
181
+ return `${count} ${count === 1 ? one : many}`;
182
+ }