taskuary 0.3.6.2__tar.gz → 0.3.6.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (525) hide show
  1. {taskuary-0.3.6.2/taskuary.egg-info → taskuary-0.3.6.4}/PKG-INFO +5 -5
  2. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/README.md +4 -4
  3. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/pyproject.toml +5 -4
  4. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/assistant.py +29 -12
  5. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/channels.py +9 -0
  6. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/cli.py +28 -0
  7. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/coder.py +65 -1
  8. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/concierge.py +94 -52
  9. taskuary-0.3.6.4/taskuary/connectorcatalog.json +2397 -0
  10. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/demo.py +71 -40
  11. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/funnel.py +24 -6
  12. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/funnel_selection.py +3 -9
  13. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/general.py +6 -0
  14. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/ingest.py +75 -2
  15. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_all.py +1 -1
  16. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_order.py +2 -2
  17. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_unread.py +72 -6
  18. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/remote_assistant.py +196 -60
  19. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/reports.py +79 -5
  20. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/routing.py +5 -4
  21. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/scopes.py +3 -0
  22. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/selfclose.py +19 -2
  23. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/server.py +69 -11
  24. taskuary-0.3.6.4/taskuary/settings_schema.json +483 -0
  25. taskuary-0.3.6.4/taskuary/social.py +241 -0
  26. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/store.py +90 -28
  27. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/agent.md +2 -1
  28. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/coder.md +4 -3
  29. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/triage.md +5 -5
  30. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/toolcatalog.py +9 -2
  31. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/triage.py +37 -13
  32. taskuary-0.3.6.4/taskuary/triage_kind_rules.json +18 -0
  33. taskuary-0.3.6.4/taskuary/web/assets/AssistantGame-COau3nxm.js +4 -0
  34. taskuary-0.3.6.4/taskuary/web/assets/GameScene-CcQhDNj4.js +1 -0
  35. taskuary-0.3.6.2/taskuary/web/assets/HubView-BjL1r12I.js → taskuary-0.3.6.4/taskuary/web/assets/HubView-DUp1o1rB.js +1 -1
  36. taskuary-0.3.6.4/taskuary/web/assets/RoundedBoxGeometry-BE4rf3sD.js +3840 -0
  37. taskuary-0.3.6.4/taskuary/web/assets/StudioScene-BTJBGMHD.js +1 -0
  38. taskuary-0.3.6.2/taskuary/web/assets/index-Bsld__8Y.css → taskuary-0.3.6.4/taskuary/web/assets/index-CKQunODG.css +1 -1
  39. taskuary-0.3.6.4/taskuary/web/assets/index-DbbLj0HN.js +597 -0
  40. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/index.html +2 -2
  41. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/workerstate.py +5 -1
  42. {taskuary-0.3.6.2 → taskuary-0.3.6.4/taskuary.egg-info}/PKG-INFO +5 -5
  43. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary.egg-info/SOURCES.txt +18 -4
  44. taskuary-0.3.6.4/tests/test_agent_reply.py +111 -0
  45. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_an_inbox_is_not_a_destination.py +28 -0
  46. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_api.py +2 -0
  47. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant.py +21 -3
  48. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_blocks.py +17 -10
  49. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_presentation.py +24 -0
  50. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_reactions.py +10 -8
  51. taskuary-0.3.6.4/tests/test_banner_is_one_rule.py +32 -0
  52. taskuary-0.3.6.4/tests/test_chat_echo_mail.py +73 -0
  53. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chatformat.py +2 -1
  54. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_concierge.py +10 -0
  55. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_core.py +3 -3
  56. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_demo.py +19 -0
  57. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_digest_brief.py +4 -4
  58. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_docs_and_llm.py +9 -6
  59. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_every_card_is_reachable.py +22 -0
  60. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_funnel.py +137 -4
  61. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_ideas_triage.py +21 -0
  62. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_kind_dispatch.py +29 -3
  63. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_lane_vocabulary.py +8 -2
  64. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_morning_line.py +3 -1
  65. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_not_coding.py +8 -8
  66. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_onboarding_walk.py +1 -1
  67. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_phone_walk_ux.py +58 -4
  68. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_pypi_downloads.py +31 -2
  69. taskuary-0.3.6.4/tests/test_read_text.py +36 -0
  70. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_remote_assistant.py +7 -9
  71. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reply_always_drafts.py +5 -5
  72. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_order_and_research.py +1 -1
  73. taskuary-0.3.6.4/tests/test_same_failure_is_quiet.py +30 -0
  74. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_seeded_reports.py +41 -9
  75. taskuary-0.3.6.4/tests/test_social.py +263 -0
  76. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_the_exe_ships_what_the_wheel_ships.py +11 -5
  77. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_urgent_and_handoff.py +1 -1
  78. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_verdict_shape.py +14 -0
  79. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_walk_order.py +13 -7
  80. taskuary-0.3.6.4/tests/test_workerstate_said.py +19 -0
  81. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_zz_toolcatalog.py +18 -0
  82. taskuary-0.3.6.2/taskuary/web/assets/StudioScene-DXPO8NCz.js +0 -3840
  83. taskuary-0.3.6.2/taskuary/web/assets/index-D5A7qNvG.js +0 -498
  84. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/LICENSE +0 -0
  85. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/setup.cfg +0 -0
  86. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/__init__.py +0 -0
  87. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/acp.py +0 -0
  88. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/agents.py +0 -0
  89. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/aidefaults.py +0 -0
  90. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/aisetup.py +0 -0
  91. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/alchemy.py +0 -0
  92. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/appfacts.py +0 -0
  93. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/artifacts.py +0 -0
  94. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/assistantblocks.py +0 -0
  95. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/aws.py +0 -0
  96. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/azure.py +0 -0
  97. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/blackboard.py +0 -0
  98. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/brief.py +0 -0
  99. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/browserview.py +0 -0
  100. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/calendar.py +0 -0
  101. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/categories.py +0 -0
  102. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/chains.py +0 -0
  103. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/chatformat.py +0 -0
  104. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/chatservers.py +0 -0
  105. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/ci.py +0 -0
  106. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/cli_connections.py +0 -0
  107. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/cli_install_terminal.py +0 -0
  108. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/cliinstall.py +0 -0
  109. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/climodels.py +0 -0
  110. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/clis.py +0 -0
  111. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/clisetup.py +0 -0
  112. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/compose.py +0 -0
  113. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/config.py +0 -0
  114. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/connectorcatalog.py +0 -0
  115. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/context.py +0 -0
  116. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/continuity.py +0 -0
  117. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/counsel.py +0 -0
  118. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/databases.py +0 -0
  119. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/db.py +0 -0
  120. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/deps.py +0 -0
  121. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/desktop.py +0 -0
  122. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/devtools.py +0 -0
  123. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/digest.py +0 -0
  124. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/docsync.py +0 -0
  125. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/evalset.py +0 -0
  126. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/evening.py +0 -0
  127. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/files.py +0 -0
  128. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/funnel_presentation.py +0 -0
  129. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/github.py +0 -0
  130. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/guard.py +0 -0
  131. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/handbook.py +0 -0
  132. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/handraise.py +0 -0
  133. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/histgen.py +0 -0
  134. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/hooks.py +0 -0
  135. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/hub.py +0 -0
  136. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/images.py +0 -0
  137. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/imapmail.py +0 -0
  138. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/imessage.py +0 -0
  139. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/intacct.py +0 -0
  140. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/interview.py +0 -0
  141. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/invoice_workflow.py +0 -0
  142. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/jev.py +0 -0
  143. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/knowledge.py +0 -0
  144. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/lanes.json +0 -0
  145. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/learn.py +0 -0
  146. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/learnedgraph.py +0 -0
  147. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/linkedin.py +0 -0
  148. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/live.py +0 -0
  149. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/llm.py +0 -0
  150. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/logs.py +0 -0
  151. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/markets.py +0 -0
  152. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/mcp.py +0 -0
  153. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/messengers.py +0 -0
  154. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/msauth.py +0 -0
  155. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/mssql.py +0 -0
  156. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/operations.py +0 -0
  157. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/outbound.py +0 -0
  158. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/outbox.py +0 -0
  159. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/ownwork.py +0 -0
  160. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/phone.py +0 -0
  161. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/playbooks.py +0 -0
  162. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/pm.py +0 -0
  163. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/policy.py +0 -0
  164. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/problems.py +0 -0
  165. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing.py +0 -0
  166. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_inventory.py +0 -0
  167. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_membership.py +0 -0
  168. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_navigation.py +0 -0
  169. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_projection.py +0 -0
  170. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_rail.py +0 -0
  171. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_reads.py +0 -0
  172. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_startup.py +0 -0
  173. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/projects.py +0 -0
  174. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/promptmap.py +0 -0
  175. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/proof.py +0 -0
  176. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/proposals.py +0 -0
  177. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/quickbooks.py +0 -0
  178. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/rank.py +0 -0
  179. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/redact.py +0 -0
  180. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/research.py +0 -0
  181. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/reshape.py +0 -0
  182. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/responder.py +0 -0
  183. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/retention.py +0 -0
  184. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/robinhood.py +0 -0
  185. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/routingmemory.py +0 -0
  186. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/semantic.py +0 -0
  187. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/senders.py +0 -0
  188. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/session_artifacts.py +0 -0
  189. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/sessionfiles.py +0 -0
  190. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/settings_schema.py +0 -0
  191. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/setup.py +0 -0
  192. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/sharepoint.py +0 -0
  193. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/sheets.py +0 -0
  194. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/simplefin.py +0 -0
  195. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/skillimport.py +0 -0
  196. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/skills/soul-interview/SKILL.md +0 -0
  197. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/skills/taskuary-setup/SKILL.md +0 -0
  198. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/spawn.py +0 -0
  199. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/teller.py +0 -0
  200. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/analyst.md +0 -0
  201. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/coordinator.md +0 -0
  202. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/counsel.md +0 -0
  203. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/digest.md +0 -0
  204. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/history/counsel-0.3.3.5.md +0 -0
  205. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/how-it-works.md +0 -0
  206. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/learned.md +0 -0
  207. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/marketer.md +0 -0
  208. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/playbook.md +0 -0
  209. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/profile.md +0 -0
  210. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/researcher.md +0 -0
  211. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/soul.md +0 -0
  212. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/style.md +0 -0
  213. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/trader.md +0 -0
  214. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/terminal.py +0 -0
  215. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/testing.py +0 -0
  216. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/toil.py +0 -0
  217. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/treg.py +0 -0
  218. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/update.py +0 -0
  219. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/verdicts.py +0 -0
  220. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/voice.py +0 -0
  221. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/wabridge.py +0 -0
  222. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/waitroom.py +0 -0
  223. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/walk.py +0 -0
  224. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/favicon.ico +0 -0
  225. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/favicon.png +0 -0
  226. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/walk/assistant.png +0 -0
  227. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/walk/board.png +0 -0
  228. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/walk/connections.png +0 -0
  229. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/walk/docs.png +0 -0
  230. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/walk/hub.png +0 -0
  231. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/walk/reports.png +0 -0
  232. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/walk/settings.png +0 -0
  233. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/walk/tasks.png +0 -0
  234. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/webguard.py +0 -0
  235. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/whatsapp/bridge.mjs +0 -0
  236. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/whatsapp/package.json +0 -0
  237. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/whatsapp/policy.mjs +0 -0
  238. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/whatsapp/policy.test.mjs +0 -0
  239. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/whatsapp/roster.mjs +0 -0
  240. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/whatsapp/roster.test.mjs +0 -0
  241. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/whoami.py +0 -0
  242. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/witness.py +0 -0
  243. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/workflows.py +0 -0
  244. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/zoho.py +0 -0
  245. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary.egg-info/dependency_links.txt +0 -0
  246. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary.egg-info/entry_points.txt +0 -0
  247. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary.egg-info/requires.txt +0 -0
  248. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary.egg-info/top_level.txt +0 -0
  249. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_acp.py +0 -0
  250. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_agent_answer_route.py +0 -0
  251. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_agent_environment.py +0 -0
  252. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_agent_identity.py +0 -0
  253. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_agent_profiles.py +0 -0
  254. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_agent_sentence.py +0 -0
  255. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_agent_source.py +0 -0
  256. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_agent_wall.py +0 -0
  257. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_ai_defaults.py +0 -0
  258. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_aisetup.py +0 -0
  259. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_alchemy.py +0 -0
  260. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_answered_yourself.py +0 -0
  261. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_answers.py +0 -0
  262. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_api_worker_signals.py +0 -0
  263. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_app_uptime.py +0 -0
  264. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_appfacts.py +0 -0
  265. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_approval_interrupt.py +0 -0
  266. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_acts.py +0 -0
  267. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_can_look_things_up.py +0 -0
  268. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_doorways.py +0 -0
  269. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_ideas.py +0 -0
  270. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_notifications.py +0 -0
  271. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_opens.py +0 -0
  272. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_verdicts.py +0 -0
  273. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_async_triage.py +0 -0
  274. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_audit_chain.py +0 -0
  275. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_audit_fixes.py +0 -0
  276. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_auto_start.py +0 -0
  277. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_aws_region.py +0 -0
  278. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_blackboard.py +0 -0
  279. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_brain_layer.py +0 -0
  280. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_brain_reaches_the_session.py +0 -0
  281. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_browser_session.py +0 -0
  282. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_browser_workflow.py +0 -0
  283. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_browserview.py +0 -0
  284. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_calendar.py +0 -0
  285. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_calendar_today.py +0 -0
  286. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_categories.py +0 -0
  287. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cc.py +0 -0
  288. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cc_triage.py +0 -0
  289. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chat_doors.py +0 -0
  290. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chat_freshness.py +0 -0
  291. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chat_is_not_one_task.py +0 -0
  292. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chat_proposals.py +0 -0
  293. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chat_queue.py +0 -0
  294. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chat_relationship.py +0 -0
  295. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chat_retention.py +0 -0
  296. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chat_setup.py +0 -0
  297. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chatservers.py +0 -0
  298. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chinese_clis.py +0 -0
  299. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_clean_context.py +0 -0
  300. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cli_connections.py +0 -0
  301. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cli_failure.py +0 -0
  302. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cli_install.py +0 -0
  303. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cli_install_terminal.py +0 -0
  304. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cli_on_fresh_path.py +0 -0
  305. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cli_setup.py +0 -0
  306. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cli_update.py +0 -0
  307. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_climodels.py +0 -0
  308. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_clis.py +0 -0
  309. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cloud.py +0 -0
  310. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cloud_sources.py +0 -0
  311. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_coder_session_continuity.py +0 -0
  312. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_completion_freshness.py +0 -0
  313. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_compose.py +0 -0
  314. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_compose_sources.py +0 -0
  315. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_compose_workflows.py +0 -0
  316. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_concierge_counsel.py +0 -0
  317. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_config.py +0 -0
  318. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_context.py +0 -0
  319. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_context_refresh_freshness.py +0 -0
  320. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_coordination.py +0 -0
  321. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_correction_doors.py +0 -0
  322. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_counsel.py +0 -0
  323. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_counsel_consumers.py +0 -0
  324. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_counsel_migration.py +0 -0
  325. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_counsel_sections.py +0 -0
  326. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_current_restore.py +0 -0
  327. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cwlogs_paging.py +0 -0
  328. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_databases.py +0 -0
  329. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_deps.py +0 -0
  330. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_desktop.py +0 -0
  331. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_devin.py +0 -0
  332. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_devtools.py +0 -0
  333. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_diff_review.py +0 -0
  334. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_dispatch_retries.py +0 -0
  335. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_docs_flow.py +0 -0
  336. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_duplicate_connectors.py +0 -0
  337. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_email_chains.py +0 -0
  338. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_email_identity_routing.py +0 -0
  339. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_ending_a_run_writes_the_answer.py +0 -0
  340. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_evening_brief.py +0 -0
  341. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_every_cli_startable.py +0 -0
  342. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_explicit_completion.py +0 -0
  343. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_factory.py +0 -0
  344. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_feed_working.py +0 -0
  345. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_files.py +0 -0
  346. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_final_answer_capture.py +0 -0
  347. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_finished_chat_stays_finished.py +0 -0
  348. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_floating_assistant.py +0 -0
  349. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_follow_up_verdict.py +0 -0
  350. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_fresh_evaluation.py +0 -0
  351. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_freshness.py +0 -0
  352. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_freshness_walk.py +0 -0
  353. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_general.py +0 -0
  354. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_github_auto.py +0 -0
  355. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_github_images.py +0 -0
  356. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_guard.py +0 -0
  357. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_handbook.py +0 -0
  358. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_handbook_topics.py +0 -0
  359. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_handoff_channels.py +0 -0
  360. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_handraise.py +0 -0
  361. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_harvest.py +0 -0
  362. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_histgen.py +0 -0
  363. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_home_is_never_yours.py +0 -0
  364. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_hooks_events.py +0 -0
  365. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_hooks_version.py +0 -0
  366. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_ignore_sender.py +0 -0
  367. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_ignore_sender_quiets_its_work.py +0 -0
  368. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_images.py +0 -0
  369. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_imap_catchup.py +0 -0
  370. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_imap_history.py +0 -0
  371. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_imapmail.py +0 -0
  372. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_imessage.py +0 -0
  373. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_intacct.py +0 -0
  374. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_interrupted_work.py +0 -0
  375. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_invite_is_not_work.py +0 -0
  376. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_invoice_workflow.py +0 -0
  377. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_jev.py +0 -0
  378. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_judge_reads_the_conclusion.py +0 -0
  379. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_knowledge.py +0 -0
  380. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_learnedgraph.py +0 -0
  381. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_lifecycle.py +0 -0
  382. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_lifespan_loops_are_guarded.py +0 -0
  383. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_linkedin.py +0 -0
  384. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_linkedin_signin.py +0 -0
  385. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_live.py +0 -0
  386. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_local_file.py +0 -0
  387. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_mail_catchup.py +0 -0
  388. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_mail_fetch_cost.py +0 -0
  389. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_mail_folders.py +0 -0
  390. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_mark_read.py +0 -0
  391. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_markets.py +0 -0
  392. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_mcp.py +0 -0
  393. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_meeting_prep.py +0 -0
  394. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_message_thread.py +0 -0
  395. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_messengers.py +0 -0
  396. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_msauth.py +0 -0
  397. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_mssql.py +0 -0
  398. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_muse.py +0 -0
  399. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_noop_ending.py +0 -0
  400. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_note_retrieval.py +0 -0
  401. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_one_app_one_reason.py +0 -0
  402. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_one_pty_one_geometry.py +0 -0
  403. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_only_your_own_thread.py +0 -0
  404. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_openai_compatible_brains.py +0 -0
  405. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_operations.py +0 -0
  406. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_outbound_reports.py +0 -0
  407. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_outbox.py +0 -0
  408. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_own_rows_no_reply.py +0 -0
  409. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_playbook_setup.py +0 -0
  410. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_playbooks.py +0 -0
  411. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_pm.py +0 -0
  412. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_poll_lanes.py +0 -0
  413. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_poll_overlap.py +0 -0
  414. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_poll_parallel.py +0 -0
  415. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_poll_sources.py +0 -0
  416. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_pr_comments.py +0 -0
  417. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_problems.py +0 -0
  418. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_problems_dismiss.py +0 -0
  419. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_procedure_selection.py +0 -0
  420. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_processing_demo_replay.py +0 -0
  421. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_processing_ledger.py +0 -0
  422. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_profile_is_a_role.py +0 -0
  423. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_projects.py +0 -0
  424. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_prompt_sources.py +0 -0
  425. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_promptmap_and_catalog.py +0 -0
  426. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_proof_ci_proposals.py +0 -0
  427. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_quickbooks.py +0 -0
  428. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_qwen.py +0 -0
  429. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_rank.py +0 -0
  430. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_rate_limit.py +0 -0
  431. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_recent_closures.py +0 -0
  432. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reclassify.py +0 -0
  433. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_redact.py +0 -0
  434. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_redact_doors.py +0 -0
  435. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reply_attachments.py +0 -0
  436. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reply_channels.py +0 -0
  437. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reply_envelope.py +0 -0
  438. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reply_needs_a_correspondent.py +0 -0
  439. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reply_sources.py +0 -0
  440. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reply_voice.py +0 -0
  441. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_repo_choice_triage.py +0 -0
  442. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_alerts.py +0 -0
  443. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_deliver.py +0 -0
  444. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_headline.py +0 -0
  445. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_prompt_isolation.py +0 -0
  446. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_reach.py +0 -0
  447. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_refusal.py +0 -0
  448. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_routing.py +0 -0
  449. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_triage.py +0 -0
  450. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_research.py +0 -0
  451. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_research_more.py +0 -0
  452. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_review_task.py +0 -0
  453. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reviews.py +0 -0
  454. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_robinhood.py +0 -0
  455. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_routing_memory.py +0 -0
  456. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_s3_poll_paging.py +0 -0
  457. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_scopes.py +0 -0
  458. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_seed_fits_a_tty.py +0 -0
  459. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_selector_vocabulary.py +0 -0
  460. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_semantic.py +0 -0
  461. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_send_outcomes.py +0 -0
  462. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_send_targets.py +0 -0
  463. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_sender_trust.py +0 -0
  464. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_sender_words.py +0 -0
  465. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_session_artifacts.py +0 -0
  466. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_session_continuity.py +0 -0
  467. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_session_files.py +0 -0
  468. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_settings_schema.py +0 -0
  469. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_setup.py +0 -0
  470. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_setup_skill.py +0 -0
  471. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_setup_walk.py +0 -0
  472. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_sheets_sharepoint.py +0 -0
  473. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_simplefin.py +0 -0
  474. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_skillimport.py +0 -0
  475. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_someone_else_replied.py +0 -0
  476. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_soul_interview.py +0 -0
  477. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_startup_contract.py +0 -0
  478. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_stay_open.py +0 -0
  479. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_stay_open_doors.py +0 -0
  480. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_store_app_cli.py +0 -0
  481. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_store_hotpaths.py +0 -0
  482. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_store_pokes.py +0 -0
  483. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_sync_clock.py +0 -0
  484. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_task_ask.py +0 -0
  485. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_task_checklist.py +0 -0
  486. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_task_controls_operations.py +0 -0
  487. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_task_identity.py +0 -0
  488. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_teller.py +0 -0
  489. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_terminal.py +0 -0
  490. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_the_split_holds.py +0 -0
  491. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_toil.py +0 -0
  492. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_tracker_revisions.py +0 -0
  493. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_treg.py +0 -0
  494. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_triage_dataset.py +0 -0
  495. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_triage_errors.py +0 -0
  496. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_triage_images.py +0 -0
  497. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_triage_pr_rule.py +0 -0
  498. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_triage_retry_sweep.py +0 -0
  499. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_update.py +0 -0
  500. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_update_refused.py +0 -0
  501. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_verdict_paths.py +0 -0
  502. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_verdict_sticks.py +0 -0
  503. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_vision.py +0 -0
  504. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_voice.py +0 -0
  505. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_wabridge.py +0 -0
  506. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_wabridge_log_trim.py +0 -0
  507. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_waitroom.py +0 -0
  508. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_watermark.py +0 -0
  509. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_web_entrypoint.py +0 -0
  510. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_webguard.py +0 -0
  511. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_whatsapp_documents.py +0 -0
  512. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_whatsapp_images.py +0 -0
  513. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_whoami.py +0 -0
  514. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_why_not_started.py +0 -0
  515. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_withdrawn.py +0 -0
  516. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_witness.py +0 -0
  517. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_worker_brief.py +0 -0
  518. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_worker_events.py +0 -0
  519. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_worker_resumes.py +0 -0
  520. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_worker_scenarios.py +0 -0
  521. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_worker_surfaces.py +0 -0
  522. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_workflows.py +0 -0
  523. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_zz_chipverbs.py +0 -0
  524. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_zz_lastword.py +0 -0
  525. {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_zz_setupchat.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: taskuary
3
- Version: 0.3.6.2
3
+ Version: 0.3.6.4
4
4
  Summary: Automate your job - the local-first operating system for your work: AI triage in, coding agents out.
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/ldbumble/taskuary
@@ -69,7 +69,7 @@ Dynamic: license-file
69
69
 
70
70
  [![CI](https://github.com/ldbumble/taskuary/actions/workflows/ci.yml/badge.svg)](https://github.com/ldbumble/taskuary/actions/workflows/ci.yml)
71
71
  [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/ldbumble/taskuary/badge)](https://scorecard.dev/viewer/?uri=github.com/ldbumble/taskuary)
72
- [![PyPI](https://img.shields.io/pypi/v/taskuary.svg?cacheSeconds=300&release=0.3.6.2&asof=2026-09-22g)](https://pypi.org/project/taskuary/)
72
+ [![PyPI](https://img.shields.io/pypi/v/taskuary.svg?cacheSeconds=300&release=0.3.6.4&asof=2026-09-24)](https://pypi.org/project/taskuary/)
73
73
  [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-3776ab.svg)](https://github.com/ldbumble/taskuary)
74
74
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
75
75
  [![Stars](https://img.shields.io/github/stars/ldbumble/taskuary?style=flat&color=d4a72c&label=%E2%98%85%20stars)](https://github.com/ldbumble/taskuary/stargazers)
@@ -83,7 +83,7 @@ your agents, and brings decisions back to you. Nothing sends or ships without yo
83
83
 
84
84
  ![The Taskuary Studio assembling as work arrives and AI agents take their seats.](https://raw.githubusercontent.com/ldbumble/taskuary/master/docs/hero.gif?v=workspace)
85
85
 
86
- Taskuary is early—currently **v0.3.6.2**—so breaking changes are still possible before 1.0.
86
+ Taskuary is early—currently **v0.3.6.4**—so breaking changes are still possible before 1.0.
87
87
 
88
88
  <p align="center">
89
89
  <a href="https://taskuary.com/demo/"><img
@@ -270,10 +270,10 @@ outside systems, send messages, run tools, or start agents. Its changes reset wh
270
270
 
271
271
  ## Installs
272
272
 
273
- ![Daily installs of taskuary from PyPI, mirror traffic excluded](https://raw.githubusercontent.com/ldbumble/taskuary/master/docs/downloads.svg)
273
+ ![Daily installs of taskuary from PyPI, mirror traffic excluded](https://raw.githubusercontent.com/ldbumble/taskuary/stats/downloads.svg)
274
274
 
275
275
  Updated daily from PyPI with mirror traffic excluded. The raw series is
276
- [docs/downloads.csv](docs/downloads.csv).
276
+ [downloads.csv on the `stats` branch](https://github.com/ldbumble/taskuary/blob/stats/downloads.csv).
277
277
 
278
278
  ## Documentation
279
279
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  [![CI](https://github.com/ldbumble/taskuary/actions/workflows/ci.yml/badge.svg)](https://github.com/ldbumble/taskuary/actions/workflows/ci.yml)
6
6
  [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/ldbumble/taskuary/badge)](https://scorecard.dev/viewer/?uri=github.com/ldbumble/taskuary)
7
- [![PyPI](https://img.shields.io/pypi/v/taskuary.svg?cacheSeconds=300&release=0.3.6.2&asof=2026-09-22g)](https://pypi.org/project/taskuary/)
7
+ [![PyPI](https://img.shields.io/pypi/v/taskuary.svg?cacheSeconds=300&release=0.3.6.4&asof=2026-09-24)](https://pypi.org/project/taskuary/)
8
8
  [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-3776ab.svg)](https://github.com/ldbumble/taskuary)
9
9
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
10
10
  [![Stars](https://img.shields.io/github/stars/ldbumble/taskuary?style=flat&color=d4a72c&label=%E2%98%85%20stars)](https://github.com/ldbumble/taskuary/stargazers)
@@ -18,7 +18,7 @@ your agents, and brings decisions back to you. Nothing sends or ships without yo
18
18
 
19
19
  ![The Taskuary Studio assembling as work arrives and AI agents take their seats.](https://raw.githubusercontent.com/ldbumble/taskuary/master/docs/hero.gif?v=workspace)
20
20
 
21
- Taskuary is early—currently **v0.3.6.2**—so breaking changes are still possible before 1.0.
21
+ Taskuary is early—currently **v0.3.6.4**—so breaking changes are still possible before 1.0.
22
22
 
23
23
  <p align="center">
24
24
  <a href="https://taskuary.com/demo/"><img
@@ -205,10 +205,10 @@ outside systems, send messages, run tools, or start agents. Its changes reset wh
205
205
 
206
206
  ## Installs
207
207
 
208
- ![Daily installs of taskuary from PyPI, mirror traffic excluded](https://raw.githubusercontent.com/ldbumble/taskuary/master/docs/downloads.svg)
208
+ ![Daily installs of taskuary from PyPI, mirror traffic excluded](https://raw.githubusercontent.com/ldbumble/taskuary/stats/downloads.svg)
209
209
 
210
210
  Updated daily from PyPI with mirror traffic excluded. The raw series is
211
- [docs/downloads.csv](docs/downloads.csv).
211
+ [downloads.csv on the `stats` branch](https://github.com/ldbumble/taskuary/blob/stats/downloads.csv).
212
212
 
213
213
  ## Documentation
214
214
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "taskuary"
7
- version = "0.3.6.2"
7
+ version = "0.3.6.4"
8
8
  description = "Automate your job - the local-first operating system for your work: AI triage in, coding agents out."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -71,10 +71,11 @@ include = ["taskuary*"]
71
71
  [tool.setuptools.package-data]
72
72
  # whatsapp/ too: the bridge error tells you to run `node bridge.mjs` out of the package, and
73
73
  # a pip install without it is an instruction pointing at a directory that does not exist.
74
- # lanes.json is the ONE lane vocabulary the desktop imports at build time and funnel.py reads at
75
- # runtime - a wheel without it cannot name a lane at all.
74
+ # *.json: every data file at the package root is read at runtime - lanes.json is the ONE lane
75
+ # vocabulary, and triage_kind_rules.json, settings_schema.json and connectorcatalog.json were all
76
+ # missing from the wheel once (the container died on the first; 2026-09-23). Name them by glob.
76
77
  # A GLOB HERE DOES NOT CROSS A DIRECTORY SEPARATOR: `web/*` matches nothing inside `web/assets/`,
77
78
  # which is why that line exists - and `web/walk/*` had to be added after the setup walk's nine
78
79
  # screenshots shipped broken. Every new subdirectory under web/ needs its own line, or its files
79
80
  # are simply absent from the wheel while the repo tree looks right.
80
- taskuary = ["lanes.json", "web/*", "web/assets/*", "web/walk/*", "templates/*.md", "templates/history/*.md", "skills/*/*.md", "whatsapp/*"]
81
+ taskuary = ["*.json", "web/*", "web/assets/*", "web/walk/*", "templates/*.md", "templates/history/*.md", "skills/*/*.md", "whatsapp/*"]
@@ -25,7 +25,7 @@ it brings in until it says something useful and surprising"). Handed only subjec
25
25
  wrote 'no content given' in its own notes; so the check now reads WHAT PEOPLE SAID (the words of every
26
26
  human thread of the last two days, the owner's lines marked), who is OUT OF OFFICE (from auto-replies -
27
27
  a chase to someone away is worse than silence), the CALENDAR, and the actual words in every rolled-up
28
- arrival (including machine mail), with each report's schedule and each failure's cause beside the count. That is where "Yittie said exporting freezes the
28
+ arrival (including machine mail), with each report's schedule, when it last ran and what that run did, and each failure's cause beside the count. That is where "Yittie said exporting freezes the
29
29
  app - and she is in Monday's meeting" comes from.
30
30
 
31
31
  It also leaves itself a NOTE: each check ends with what it looked at and found nothing in, when
@@ -503,7 +503,7 @@ def blk_label(bid: str) -> str:
503
503
  # ── the model's pass: its own read, given what it already said ───────────────────────────────
504
504
  CONTRACT = ('\n\nYou are writing your POST on the owner\'s Timeline - the short list of things worth saying right now. You get '
505
505
  'CANDIDATES the hub found itself (each with a key), WHAT PEOPLE SAID (the words, by thread), who is OUT OF OFFICE, the '
506
- 'CALENDAR, what arrived (with each report\'s schedule and each failure\'s cause), what got done, what is open, and WHAT '
506
+ 'CALENDAR, what arrived (with each report\'s schedule, when it last ran and what that run did, and each failure\'s cause), what got done, what is open, and WHAT '
507
507
  'YOU ALREADY SAID. Answer JSON only: {"say": [{"key": "<a candidate key, or idea:<short-slug> for a thought of your own>", '
508
508
  '"text": "<one line, under 30 words, first person: the fact and what I would do - quote the phrase or name the cause when there is one>", '
509
509
  '"section": "<people|loose|ideas|systems - which part of the post this belongs under: people = what somebody said '
@@ -536,14 +536,26 @@ def _schedules(store) -> dict:
536
536
  nothing without its clock: 25 digests in two days on an on_startup report is 25 launches, not a
537
537
  scheduler bug, and two seeded reports at one timestamp is one launch, not a restart to explain."""
538
538
  from . import reports
539
- out = {}
539
+ out, st = {}, store.get_settings()
540
540
  for src in store.list_sources(active_only=False):
541
541
  if src.get('Channel') != 'report': continue
542
542
  try: c = json.loads(src.get('ConfigJson') or '{}')
543
543
  except ValueError: continue
544
- out[c.get('title') or src.get('Address')] = reports.schedule_words(c)
544
+ out[c.get('title') or src.get('Address')] = reports.schedule_words(c) + _last_run(st, src)
545
545
  return out
546
546
 
547
+ def _last_run(settings: dict, src: dict) -> str:
548
+ """'; last ran Tue 22 Sep 20:37, nothing to report so nothing was filed' - or ''. The clock alone
549
+ misled: a routed report whose judge holds a run back files NO message, so the newest mid read as
550
+ the last firing and a 140-minute timer looked stalled two runs after it fired on time (TQ-0685).
551
+ The run record on the source (reports.LAST_RUN) is the receipt the arrivals cannot carry."""
552
+ from .reports import LAST_RUN
553
+ try: rec = json.loads(settings.get(f"{LAST_RUN}{src['SourceId']}") or '{}')
554
+ except (ValueError, TypeError): rec = {}
555
+ if not rec.get('at'): return ''
556
+ what = 'failed' if rec.get('failed') else f"posted mid {rec['message_id']}" if rec.get('message_id') else 'nothing to report so nothing was filed'
557
+ return f"; last ran {_when(rec['at'])}, {what}"
558
+
547
559
  _FAILS = re.compile(r'fail|error|denied|timeout|could not|unable', re.I)
548
560
  _GH_FAILED = re.compile(r'^(.+?) Failed in ', re.M) # the job lines of GitHub's "Run failed" mail
549
561
  def _cause(r: dict) -> str:
@@ -852,7 +864,7 @@ def system_checks(store, source_ids=None, inline=None) -> str:
852
864
  ids = saved if source_ids is None else _ids(source_ids)
853
865
  subs = own if inline is None else _inline(inline)
854
866
  if not ids and not subs:
855
- return '(none selected - add a data source, or choose saved data views, on Reports -> Assistant)'
867
+ return '(none selected - add a data source, or choose saved data views, on Reports -> Advisor)'
856
868
  from . import reports
857
869
  found = {s['SourceId']: s for s in store.list_sources(active_only=False) if s.get('Channel') == 'report'}
858
870
  jobs = [] # (title, cfg to render, or a note to print instead)
@@ -862,7 +874,7 @@ def system_checks(store, source_ids=None, inline=None) -> str:
862
874
  try: cfg_ = json.loads(src.get('ConfigJson') or '{}')
863
875
  except ValueError: cfg_ = {}
864
876
  title = str(cfg_.get('title') or src.get('Address') or f'report {sid}')
865
- if cfg_.get('type') == 'assistant': jobs.append((title, None, 'Skipped: an Assistant cannot watch itself.'))
877
+ if cfg_.get('type') == 'assistant': jobs.append((title, None, 'Skipped: an Advisor cannot watch itself.'))
866
878
  else: jobs.append((title, cfg_, None))
867
879
  for i, sub in enumerate(subs, 1):
868
880
  jobs.append((str(sub.get('label') or sub.get('title') or '').strip() or f"{sub.get('type')} #{i}", sub, None))
@@ -1166,10 +1178,10 @@ def _idea_message(store, i: dict, a: dict, report_title=None) -> tuple:
1166
1178
  active = bool(task and task.get('Status') in ('open', 'in_progress', 'waiting'))
1167
1179
  working = bool(active and any(r.get('Status') == 'running' for r in store.list_runs(tid)))
1168
1180
  stamp = i.get('LastSaid') or i.get('FirstSeen') or datetime.now().strftime('%Y-%m-%d %H:%M:%S')
1169
- who = report_title or 'Assistant'
1181
+ who = report_title or 'Advisor'
1170
1182
  # one arrival per idea: the stamp in the id made every re-say a fresh message, and a fresh task once the first closed
1171
1183
  msg = {'external_id': f"idea:{i['IdeaId']}", 'channel': CHANNEL, 'from_name': who, 'source_name': who,
1172
- 'conversation_id': str(i.get('Key') or f"idea:{i['IdeaId']}"), 'subject': f"Assistant idea: {_cut(i.get('Text'), 100)}",
1184
+ 'conversation_id': str(i.get('Key') or f"idea:{i['IdeaId']}"), 'subject': f"Advisor idea: {_cut(i.get('Text'), 100)}",
1173
1185
  'sent_at': stamp, 'body': str(i.get('Text') or '') + (f"\n\nwhy: {a.get('why')}" if a.get('why') else ''),
1174
1186
  'idea_context': {'report': report_title, 'kind': i.get('Kind'),
1175
1187
  'linked_task': f"{task_ref(tid)} [{task.get('Status')}] {_short(task.get('Title'), 80)}" if task else None,
@@ -1448,7 +1460,7 @@ def _run(store, llm, instruction, watch_source_ids, watch_sources, systems_only=
1448
1460
  if systems_only and not (_ids(watch_source_ids) or _inline(watch_sources)):
1449
1461
  why = ('this report reads nothing: no Taskuary block is ticked and no data source is chosen '
1450
1462
  '- tick a block, or choose a source, on the report')
1451
- logger.warning(f"assistant: {report_title or 'Assistant'} ran and read nothing - {why}")
1463
+ logger.warning(f"assistant: {report_title or 'Advisor'} ran and read nothing - {why}")
1452
1464
  return {'ran': True, 'said': 0, 'reads_nothing': True, 'summary': why, 'inputs': '',
1453
1465
  'reviewed': {'notes': '', 'scope': 'nothing', 'systems': 0, 'why': why}}
1454
1466
  state = {i['Key']: i for i in store.list_ideas()}
@@ -1522,7 +1534,7 @@ def _run(store, llm, instruction, watch_source_ids, watch_sources, systems_only=
1522
1534
  # chose "every run", in which case the check still says it ran, in one line, with what it
1523
1535
  # read behind it. A setting that promises every run and then shows nothing is a lie.
1524
1536
  if not always_post: return {'ran': True, 'said': 0, 'reviewed': rv, 'inputs': read}
1525
- who = (report_title or 'Assistant') if own_post else 'Assistant'
1537
+ who = (report_title or 'Advisor') if own_post else 'Advisor'
1526
1538
  me = f'assistant:{report_id}' if own_post else 'assistant'
1527
1539
  mid = store.add_message({'TaskId': None, 'ExternalId': f'{me}:{stamp}', 'ConversationId': me, 'Channel': CHANNEL,
1528
1540
  'SourceName': who, 'Subject': f'{who} - nothing to report', 'FromName': who,
@@ -1551,7 +1563,7 @@ def _run(store, llm, instruction, watch_source_ids, watch_sources, systems_only=
1551
1563
  head = rows[0]['Text'] if len(rows[0]['Text']) <= 90 else rows[0]['Text'][:90].rsplit(' ', 1)[0] + '…'
1552
1564
  subj = head + (f' (+{len(rows) - 1} more)' if len(rows) > 1 else '')
1553
1565
  identity = f'assistant:{report_id}' if own_post else 'assistant'
1554
- name = (report_title or 'Assistant') if own_post else 'Assistant'
1566
+ name = (report_title or 'Advisor') if own_post else 'Advisor'
1555
1567
  mid = store.add_message({'TaskId': None, 'ExternalId': f'{identity}:{stamp}', 'ConversationId': identity, 'Channel': CHANNEL,
1556
1568
  'SourceName': name, 'Subject': subj, 'FromName': name, 'SentAt': stamp,
1557
1569
  'BodyText': body, 'Status': 'feed'})
@@ -1623,7 +1635,7 @@ def act(store, idea_id: int, verb: str, actor: str = 'owner', llm=None, days: in
1623
1635
  # This is NEW work noticed after an earlier task was completed. A message can point
1624
1636
  # at only one task, so do not steal it from history or rename/reopen the completed
1625
1637
  # task. Carry the evidence into a fresh assistant-owned task instead.
1626
- title = str(a.get('title') or i.get('Text') or 'Assistant follow-up').strip()[:200]
1638
+ title = str(a.get('title') or i.get('Text') or 'Advisor follow-up').strip()[:200]
1627
1639
  source_text = str(message.get('BodyText') or '').strip()
1628
1640
  summary = str(i.get('Text') or '').strip()
1629
1641
  if source_text and source_text not in summary: summary += f'\n\nSource message: {source_text}'
@@ -1640,6 +1652,11 @@ def act(store, idea_id: int, verb: str, actor: str = 'owner', llm=None, days: in
1640
1652
  brief = str(a.get('title') or i.get('Text') or task.get('Title') or '').strip()
1641
1653
  why = str(a.get('why') or '').strip()
1642
1654
  if why: brief += f'\n\nWhy the assistant raised it: {why}'
1655
+ # ...and the report it points at, or the agent can only ask for it to be pasted (2026-09-23)
1656
+ src = store.get_message(int(a['mid'])) if str(a.get('mid') or '').isdigit() else None
1657
+ if src and src.get('Channel') != 'assistant' and src.get('BodyText'):
1658
+ brief += (f"\n\nThe source - {src.get('Subject') or 'the message'}:\n"
1659
+ + src['BodyText'].split('\n--- raw data ---')[0].strip()[:6000])
1643
1660
  if kind == 'general':
1644
1661
  ingest._spawn(_auto_general, store, tid, brief)
1645
1662
  elif store.get_settings().get('coder_auto_enabled') == '1':
@@ -336,6 +336,15 @@ def test_connector(store, cid: int) -> dict:
336
336
  elif c['Type'] == 'robinhood':
337
337
  from . import robinhood
338
338
  detail = robinhood.test(store, c)
339
+ elif c['Type'] in ('bluesky', 'mastodon'):
340
+ # whoami, like LinkedIn: the one call that proves the credential AND comes back
341
+ # with something the owner recognises. Posting would be a strange thing for Test.
342
+ from .reports import REGISTRY, resolve_cfg
343
+ rtype = f"{c['Type']}_me"
344
+ out = REGISTRY[rtype](resolve_cfg(store, {'type': rtype}))
345
+ row = (out.get('rows') or [{}])[0]
346
+ detail = (f"signed in as {row.get('handle') or '?'}"
347
+ f" - {row.get('followers')} followers, {row.get('posts')} posts")
339
348
  elif c['Type'] == 'linkedin':
340
349
  # whoami, which is the one call that proves the token AND returns something the
341
350
  # owner recognises - a post would be a strange thing for a Test button to do
@@ -122,6 +122,11 @@ def main():
122
122
  'this transcript, and draft the reply the sender gets (you are not '
123
123
  'sending it - the owner approves it). Give one sentence on what you did '
124
124
  'or found. Do not run this while waiting on the owner.')
125
+ ap.add_argument('--reply', metavar='TEXT',
126
+ help="write the reply the person who asked will get, in your own words - it becomes this "
127
+ "task's pending reply for the owner to approve (you are not sending it), and "
128
+ "finishing keeps it instead of redrafting. Use - to read it from stdin.")
129
+ ap.add_argument('--reply-file', metavar='PATH', help='--reply, read from a file (for a long or multi-line reply)')
125
130
  args = ap.parse_args()
126
131
  if args.demo:
127
132
  import os, tempfile
@@ -133,6 +138,29 @@ def main():
133
138
  # --done goes over HTTP, unlike --note. A note is a database row and any process can write
134
139
  # one; ENDING a task needs the live session's scrollback, which exists only inside the
135
140
  # running server - this process would find no transcript and wrap an empty one.
141
+ if args.reply is not None or args.reply_file:
142
+ import os, sys, requests
143
+ try: sys.stdout.reconfigure(encoding='utf-8', errors='replace')
144
+ except (AttributeError, OSError): pass
145
+ tid = os.environ.get('TASKUARY_TASK')
146
+ if not str(tid).isdigit():
147
+ print('not in a Taskuary session - TASKUARY_TASK is not set, so there is no task to reply on')
148
+ return
149
+ if args.reply_file: text = open(args.reply_file, encoding='utf-8').read()
150
+ else: text = sys.stdin.read() if args.reply == '-' else args.reply
151
+ srv = config.load()['server']
152
+ host = '127.0.0.1' if srv.get('host') in ('0.0.0.0', '::', '', None) else srv['host']
153
+ base = f"http://{host}:{srv.get('port') or 7787}"
154
+ hdr = {'X-Taskuary-Token': srv['token']} if srv.get('token') else {}
155
+ try:
156
+ r = requests.post(f'{base}/api/agent/reply', timeout=60, headers=hdr,
157
+ json={'task_id': int(tid), 'text': text, 'agent': os.environ.get('TASKUARY_AGENT') or 'agent'})
158
+ out = r.json() if r.headers.get('content-type', '').startswith('application/json') else {}
159
+ except Exception as e:
160
+ print(f'could not reach Taskuary at {base}: {e}'); return
161
+ print('reply saved on the task, waiting on the owner to approve and send it.' if out.get('ok')
162
+ else f"not saved: {out.get('why') or out.get('detail') or r.text[:200]}")
163
+ return
136
164
  if args.done is not None:
137
165
  import os, sys, requests
138
166
  try: sys.stdout.reconfigure(encoding='utf-8', errors='replace')
@@ -105,6 +105,54 @@ def reply_target(store, task_id: int):
105
105
  return next((m['MessageId'] for m in reversed(store.list_messages(task_id)) if m.get('Status') != 'context'), None)
106
106
 
107
107
 
108
+ # ── the agent's own words ───────────────────────────────────────────────────────────────
109
+ # The agent that did the work often writes the better answer: it knows what it found, and a second
110
+ # model redrafting from its transcript loses the nuance (the owner, 2026-09-23: "sometimes the agent
111
+ # that did the work is better for response than another ai generating it based off of transcript").
112
+ # It used to have no way to hand that answer over - it asked "should I draft the reply?", wrote it
113
+ # on its own screen, and the task's reply stayed empty until the responder wrote a different one.
114
+ # Now it says so: `taskuary --reply` (a shell) or a [[TASKUARY-REPLY]] block (the general chat), the
115
+ # text becomes the task's pending reply as written, and the end of the run keeps it.
116
+ AGENT_DRAFT = 'agent:'
117
+
118
+ def agent_drafted(rv) -> bool:
119
+ return bool(rv) and str(rv.get('DraftBy') or '').startswith(AGENT_DRAFT) and bool(str(rv.get('DraftText') or '').strip())
120
+
121
+
122
+ def own_draft(store, task_id: int):
123
+ """The pending reply the agent wrote itself, if there is one."""
124
+ return next((r for r in (store.pending_review(task_id, 'draft_reply', live_only=False),
125
+ store.pending_review(task_id, 'draft', live_only=False)) if agent_drafted(r)), None)
126
+
127
+
128
+ def agent_reply(store, task_id: int, text: str, agent: str = 'agent', run_id: int = None) -> dict:
129
+ """Put the agent's reply on the task as the pending draft - the same review the responder would
130
+ write into (held, live or new; one per answer, PW-236), marked as the agent's. Nothing is sent:
131
+ the owner approves it like every other reply."""
132
+ text = str(text or '').strip()
133
+ if not text: return {'ok': False, 'why': 'no reply text'}
134
+ held = store.held_review(task_id) or {}
135
+ mid = reply_target(store, task_id) or held.get('MessageId')
136
+ if not mid: return {'ok': False, 'why': 'nobody is waiting on a reply on this task - there is no one to draft it to'}
137
+ # work the owner started here (a brief typed in the chat) has only their own words behind it: the agent's
138
+ # answer IS the result, and filing it as a reply "waiting on your approval" addressed it to them (2026-09-23)
139
+ if not held and no_one_behind((store.get_message(mid) or {}).get('Channel')):
140
+ return {'ok': False, 'why': 'nobody sent this task - its result stays on the task, there is no one to reply to'}
141
+ live = None if held else (store.pending_review(task_id, 'draft_reply', live_only=False) or store.pending_review(task_id, 'draft', live_only=False))
142
+ why = f'{agent} wrote this reply in its session - approve to send'
143
+ if held:
144
+ rid = held['ReviewId']; store.unhold_review(rid, why)
145
+ elif live:
146
+ rid = live['ReviewId']; store.update_review_reason(rid, why, run_id)
147
+ else:
148
+ rid = store.add_review({'TaskId': task_id, 'MessageId': mid, 'RunId': run_id, 'Kind': 'draft_reply', 'Status': 'pending', 'Reason': why})
149
+ rv = store.get_review(rid) or {}
150
+ if rv.get('MessageId') != mid: store.update_review_message(rid, mid)
151
+ store.update_review_draft(rid, text, run_id or rv.get('RunId'), by=AGENT_DRAFT + agent)
152
+ store.add_comment(task_id, agent, 'agent', f'{agent} drafted the reply itself - it is on the task, waiting on your approval.')
153
+ return {'ok': True, 'review_id': rid, 'message_id': mid}
154
+
155
+
108
156
  # ── the cheap ending ────────────────────────────────────────────────────────────────────
109
157
  # Almost everything a keyboard can do goes to the coding agent (the owner's rule), and the
110
158
  # whole bargain is that an agent with nothing to do says "nothing to do here" and stops CHEAPLY.
@@ -213,7 +261,7 @@ def finish(store, task_id: int, rep: dict, run_id: int = None, actor: str = 'cod
213
261
  # nobody can send does not hold a task the owner just closed
214
262
  if owner_done and mid and not can_send: mid = None
215
263
  # a held draft is proof somebody IS waiting on an answer, so it is never quietly dropped here
216
- if mid and not held and nobody_waiting(store, mid, rep):
264
+ if mid and not held and not own_draft(store, task_id) and nobody_waiting(store, mid, rep):
217
265
  store.add_comment(task_id, actor, 'agent', 'Nothing needed doing here and the sender is not waiting on an '
218
266
  'answer - filed with the report, no reply drafted.')
219
267
  mid = None
@@ -432,6 +480,16 @@ def raise_reply(store, task_id: int, mid: int, run_id: int, rep: dict,
432
480
  rid = store.add_review({'TaskId': task_id, 'MessageId': mid, 'RunId': run_id, 'Kind': 'draft_reply', 'Status': 'pending',
433
481
  'Reason': why if fresh.get('state') in ('changed', 'unresolved') else 'coder finished the work - reply awaiting approval'})
434
482
  if (held or live) and (held or live).get('MessageId') != mid: store.update_review_message(rid, mid)
483
+ rv = store.get_review(rid) or {}
484
+ if agent_drafted(rv):
485
+ # the agent that did the work wrote this reply itself (agent_reply): its words stand and no second
486
+ # model rewrites them - only a thread that moved on (or could not be checked) is flagged for a reread
487
+ who = str(rv.get('DraftBy'))[len(AGENT_DRAFT):] or 'the agent'
488
+ store.update_review_reason(rid, f"{who}'s own reply from the session - approve to send"
489
+ + (' (the thread moved on after it was written - reread it)' if fresh.get('state') == 'changed' else ''), run_id)
490
+ if fresh.get('state') in ('changed', 'unresolved'): store.mark_review_stale(rid)
491
+ _notify_done(store, task_id, rid)
492
+ return
435
493
  src = complete_result or resolution_text(rep)
436
494
  if fresh.get('state') == 'changed' and fresh.get('latest'):
437
495
  l = fresh['latest']
@@ -450,6 +508,10 @@ def raise_reply(store, task_id: int, mid: int, run_id: int, rep: dict,
450
508
  except Exception as e: logger.warning(f'reply draft failed for task {task_id}: {e}')
451
509
  # a refresh that failed is an unresolved freshness state the owner sees: the draft waits, stale, for one that succeeds
452
510
  if fresh.get('state') == 'unresolved': store.mark_review_stale(rid)
511
+ _notify_done(store, task_id, rid)
512
+
513
+
514
+ def _notify_done(store, task_id: int, rid: int) -> None:
453
515
  # the ping that matters most: work FINISHED and its reply is sitting on the task on you
454
516
  if (store.get_settings().get('notify_level') or 'needs_me') != 'off':
455
517
  from .outbound import notify
@@ -463,3 +525,5 @@ def raise_reply(store, task_id: int, mid: int, run_id: int, rep: dict,
463
525
  try: notify(store, f'{task_ref(task_id)} is done - the reply is drafted and waiting on '
464
526
  f'your approval on the task.\n{head}{tail}')
465
527
  except Exception as e: logger.warning(f'notify failed for task {task_id}: {e}')
528
+
529
+