nookku 0.4.0__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 (560) hide show
  1. nookku-0.4.0/.gitignore +26 -0
  2. nookku-0.4.0/CHANGELOG.md +127 -0
  3. nookku-0.4.0/LICENSE +202 -0
  4. nookku-0.4.0/PKG-INFO +152 -0
  5. nookku-0.4.0/README.md +125 -0
  6. nookku-0.4.0/SPEC.md +837 -0
  7. nookku-0.4.0/conformance/build.py +4572 -0
  8. nookku-0.4.0/conformance/cases/agent_error_is_a_note/expect.json +11 -0
  9. nookku-0.4.0/conformance/cases/agent_error_is_a_note/relay.jsonl +1 -0
  10. nookku-0.4.0/conformance/cases/agent_unreachable_is_a_note/expect.json +11 -0
  11. nookku-0.4.0/conformance/cases/agent_unreachable_is_a_note/relay.jsonl +1 -0
  12. nookku-0.4.0/conformance/cases/altered_input_empty_line_lost/expect.json +10 -0
  13. nookku-0.4.0/conformance/cases/altered_input_empty_line_lost/relay.jsonl +3 -0
  14. nookku-0.4.0/conformance/cases/altered_input_trailing_newline/expect.json +10 -0
  15. nookku-0.4.0/conformance/cases/altered_input_trailing_newline/relay.jsonl +3 -0
  16. nookku-0.4.0/conformance/cases/altered_input_trailing_space/expect.json +10 -0
  17. nookku-0.4.0/conformance/cases/altered_input_trailing_space/relay.jsonl +3 -0
  18. nookku-0.4.0/conformance/cases/altered_input_unicode_nfd/expect.json +10 -0
  19. nookku-0.4.0/conformance/cases/altered_input_unicode_nfd/relay.jsonl +3 -0
  20. nookku-0.4.0/conformance/cases/altered_reply_blank_line_added/expect.json +10 -0
  21. nookku-0.4.0/conformance/cases/altered_reply_blank_line_added/relay.jsonl +3 -0
  22. nookku-0.4.0/conformance/cases/altered_reply_trailing_space_lost/expect.json +10 -0
  23. nookku-0.4.0/conformance/cases/altered_reply_trailing_space_lost/relay.jsonl +3 -0
  24. nookku-0.4.0/conformance/cases/altered_reply_word/expect.json +10 -0
  25. nookku-0.4.0/conformance/cases/altered_reply_word/relay.jsonl +3 -0
  26. nookku-0.4.0/conformance/cases/blank_line/expect.json +6 -0
  27. nookku-0.4.0/conformance/cases/blank_line/relay.jsonl +4 -0
  28. nookku-0.4.0/conformance/cases/blocked_call_is_counted/expect.json +5 -0
  29. nookku-0.4.0/conformance/cases/blocked_call_is_counted/relay.jsonl +4 -0
  30. nookku-0.4.0/conformance/cases/clean/expect.json +4 -0
  31. nookku-0.4.0/conformance/cases/clean/relay.jsonl +3 -0
  32. nookku-0.4.0/conformance/cases/clean_repeated_message/expect.json +4 -0
  33. nookku-0.4.0/conformance/cases/clean_repeated_message/relay.jsonl +2 -0
  34. nookku-0.4.0/conformance/cases/duplicate_send/expect.json +10 -0
  35. nookku-0.4.0/conformance/cases/duplicate_send/relay.jsonl +3 -0
  36. nookku-0.4.0/conformance/cases/empty_records/expect.json +4 -0
  37. nookku-0.4.0/conformance/cases/empty_records/relay.jsonl +0 -0
  38. nookku-0.4.0/conformance/cases/hash_mismatch/expect.json +6 -0
  39. nookku-0.4.0/conformance/cases/hash_mismatch/relay.jsonl +3 -0
  40. nookku-0.4.0/conformance/cases/injected_input/expect.json +10 -0
  41. nookku-0.4.0/conformance/cases/injected_input/relay.jsonl +3 -0
  42. nookku-0.4.0/conformance/cases/invalid_json_line/expect.json +6 -0
  43. nookku-0.4.0/conformance/cases/invalid_json_line/relay.jsonl +4 -0
  44. nookku-0.4.0/conformance/cases/lone_surrogate_in_the_relay_record/expect.json +6 -0
  45. nookku-0.4.0/conformance/cases/lone_surrogate_in_the_relay_record/relay.jsonl +3 -0
  46. nookku-0.4.0/conformance/cases/lone_surrogate_in_the_tap_record/expect.json +6 -0
  47. nookku-0.4.0/conformance/cases/lone_surrogate_in_the_tap_record/relay.jsonl +3 -0
  48. nookku-0.4.0/conformance/cases/missing_field/expect.json +6 -0
  49. nookku-0.4.0/conformance/cases/missing_field/relay.jsonl +3 -0
  50. nookku-0.4.0/conformance/cases/model_session_in_a_v01_row/expect.json +6 -0
  51. nookku-0.4.0/conformance/cases/model_session_in_a_v01_row/relay.jsonl +3 -0
  52. nookku-0.4.0/conformance/cases/model_session_in_the_relay_record/expect.json +6 -0
  53. nookku-0.4.0/conformance/cases/model_session_in_the_relay_record/relay.jsonl +4 -0
  54. nookku-0.4.0/conformance/cases/model_session_wrong_field_type/expect.json +6 -0
  55. nookku-0.4.0/conformance/cases/model_session_wrong_field_type/relay.jsonl +3 -0
  56. nookku-0.4.0/conformance/cases/not_delivered/expect.json +10 -0
  57. nookku-0.4.0/conformance/cases/not_delivered/relay.jsonl +3 -0
  58. nookku-0.4.0/conformance/cases/optional_field_wrong_type/expect.json +6 -0
  59. nookku-0.4.0/conformance/cases/optional_field_wrong_type/relay.jsonl +3 -0
  60. nookku-0.4.0/conformance/cases/optional_turn_fields/expect.json +4 -0
  61. nookku-0.4.0/conformance/cases/optional_turn_fields/relay.jsonl +3 -0
  62. nookku-0.4.0/conformance/cases/out_of_order/expect.json +10 -0
  63. nookku-0.4.0/conformance/cases/out_of_order/relay.jsonl +2 -0
  64. nookku-0.4.0/conformance/cases/relay_record_missing/expect.json +6 -0
  65. nookku-0.4.0/conformance/cases/repeat_after_alteration/expect.json +10 -0
  66. nookku-0.4.0/conformance/cases/repeat_after_alteration/relay.jsonl +3 -0
  67. nookku-0.4.0/conformance/cases/reply_changed_after_the_write/expect.json +6 -0
  68. nookku-0.4.0/conformance/cases/reply_changed_after_the_write/relay.jsonl +3 -0
  69. nookku-0.4.0/conformance/cases/reply_missing_on_success/expect.json +6 -0
  70. nookku-0.4.0/conformance/cases/reply_missing_on_success/relay.jsonl +3 -0
  71. nookku-0.4.0/conformance/cases/script_clean/expect.json +4 -0
  72. nookku-0.4.0/conformance/cases/script_clean/relay.jsonl +3 -0
  73. nookku-0.4.0/conformance/cases/script_clean/script.jsonl +3 -0
  74. nookku-0.4.0/conformance/cases/script_clean_json_array/expect.json +4 -0
  75. nookku-0.4.0/conformance/cases/script_clean_json_array/relay.jsonl +3 -0
  76. nookku-0.4.0/conformance/cases/script_clean_json_array/script.json +1 -0
  77. nookku-0.4.0/conformance/cases/script_empty_array/expect.json +6 -0
  78. nookku-0.4.0/conformance/cases/script_empty_array/relay.jsonl +3 -0
  79. nookku-0.4.0/conformance/cases/script_empty_array/script.json +1 -0
  80. nookku-0.4.0/conformance/cases/script_lone_surrogate/expect.json +6 -0
  81. nookku-0.4.0/conformance/cases/script_lone_surrogate/relay.jsonl +3 -0
  82. nookku-0.4.0/conformance/cases/script_lone_surrogate/script.jsonl +1 -0
  83. nookku-0.4.0/conformance/cases/script_message_not_sent/expect.json +10 -0
  84. nookku-0.4.0/conformance/cases/script_message_not_sent/relay.jsonl +2 -0
  85. nookku-0.4.0/conformance/cases/script_message_not_sent/script.jsonl +3 -0
  86. nookku-0.4.0/conformance/cases/script_row_with_another_key/expect.json +6 -0
  87. nookku-0.4.0/conformance/cases/script_row_with_another_key/relay.jsonl +3 -0
  88. nookku-0.4.0/conformance/cases/script_row_with_another_key/script.jsonl +1 -0
  89. nookku-0.4.0/conformance/cases/script_said_differs/expect.json +10 -0
  90. nookku-0.4.0/conformance/cases/script_said_differs/relay.jsonl +3 -0
  91. nookku-0.4.0/conformance/cases/script_said_differs/script.jsonl +3 -0
  92. nookku-0.4.0/conformance/cases/script_turn_after_the_last_message/expect.json +10 -0
  93. nookku-0.4.0/conformance/cases/script_turn_after_the_last_message/relay.jsonl +3 -0
  94. nookku-0.4.0/conformance/cases/script_turn_after_the_last_message/script.jsonl +2 -0
  95. nookku-0.4.0/conformance/cases/script_typed_turn/expect.json +10 -0
  96. nookku-0.4.0/conformance/cases/script_typed_turn/relay.jsonl +3 -0
  97. nookku-0.4.0/conformance/cases/script_typed_turn/script.jsonl +3 -0
  98. nookku-0.4.0/conformance/cases/several_breaks/expect.json +25 -0
  99. nookku-0.4.0/conformance/cases/several_breaks/relay.jsonl +3 -0
  100. nookku-0.4.0/conformance/cases/shown_changed_after_the_write/expect.json +6 -0
  101. nookku-0.4.0/conformance/cases/shown_changed_after_the_write/relay.jsonl +3 -0
  102. nookku-0.4.0/conformance/cases/started_in_a_v01_row/expect.json +6 -0
  103. nookku-0.4.0/conformance/cases/started_in_a_v01_row/relay.jsonl +3 -0
  104. nookku-0.4.0/conformance/cases/stream_in_a_v01_relay_row/expect.json +6 -0
  105. nookku-0.4.0/conformance/cases/stream_in_a_v01_relay_row/relay.jsonl +3 -0
  106. nookku-0.4.0/conformance/cases/stream_in_a_v01_row/expect.json +6 -0
  107. nookku-0.4.0/conformance/cases/stream_in_a_v01_row/relay.jsonl +3 -0
  108. nookku-0.4.0/conformance/cases/stream_wrong_field_type/expect.json +6 -0
  109. nookku-0.4.0/conformance/cases/stream_wrong_field_type/relay.jsonl +3 -0
  110. nookku-0.4.0/conformance/cases/streamed_reply_clean/expect.json +4 -0
  111. nookku-0.4.0/conformance/cases/streamed_reply_clean/relay.jsonl +3 -0
  112. nookku-0.4.0/conformance/cases/streamed_reply_failed_in_a_v02_row/expect.json +6 -0
  113. nookku-0.4.0/conformance/cases/streamed_reply_failed_in_a_v02_row/relay.jsonl +3 -0
  114. nookku-0.4.0/conformance/cases/streamed_reply_failed_is_a_note/expect.json +11 -0
  115. nookku-0.4.0/conformance/cases/streamed_reply_failed_is_a_note/relay.jsonl +3 -0
  116. nookku-0.4.0/conformance/cases/streamed_reply_failed_without_error/expect.json +6 -0
  117. nookku-0.4.0/conformance/cases/streamed_reply_failed_without_error/relay.jsonl +3 -0
  118. nookku-0.4.0/conformance/cases/streamed_reply_part_shown/expect.json +10 -0
  119. nookku-0.4.0/conformance/cases/streamed_reply_part_shown/relay.jsonl +3 -0
  120. nookku-0.4.0/conformance/cases/tap_record_missing/expect.json +6 -0
  121. nookku-0.4.0/conformance/cases/tap_record_missing/relay.jsonl +3 -0
  122. nookku-0.4.0/conformance/cases/tap_unparsed/expect.json +6 -0
  123. nookku-0.4.0/conformance/cases/tap_unparsed/relay.jsonl +3 -0
  124. nookku-0.4.0/conformance/cases/unknown_type/expect.json +6 -0
  125. nookku-0.4.0/conformance/cases/unknown_type/relay.jsonl +3 -0
  126. nookku-0.4.0/conformance/cases/unshown_reply/expect.json +10 -0
  127. nookku-0.4.0/conformance/cases/unshown_reply/relay.jsonl +3 -0
  128. nookku-0.4.0/conformance/cases/v01_and_v02_rows_mix/expect.json +5 -0
  129. nookku-0.4.0/conformance/cases/v01_and_v02_rows_mix/relay.jsonl +3 -0
  130. nookku-0.4.0/conformance/cases/v02_breaks_are_the_same/expect.json +11 -0
  131. nookku-0.4.0/conformance/cases/v02_breaks_are_the_same/relay.jsonl +3 -0
  132. nookku-0.4.0/conformance/cases/v02_model_sessions_are_counted/expect.json +5 -0
  133. nookku-0.4.0/conformance/cases/v02_model_sessions_are_counted/relay.jsonl +3 -0
  134. nookku-0.4.0/conformance/cases/v03_rows_of_each_type/expect.json +5 -0
  135. nookku-0.4.0/conformance/cases/v03_rows_of_each_type/relay.jsonl +3 -0
  136. nookku-0.4.0/conformance/cases/wrong_field_type/expect.json +6 -0
  137. nookku-0.4.0/conformance/cases/wrong_field_type/relay.jsonl +3 -0
  138. nookku-0.4.0/conformance/cases/wrong_version/expect.json +6 -0
  139. nookku-0.4.0/conformance/cases/wrong_version/relay.jsonl +3 -0
  140. nookku-0.4.0/conformance/contract/crash_is_not_restarted/case.json +32 -0
  141. nookku-0.4.0/conformance/contract/error_is_status_500/case.json +27 -0
  142. nookku-0.4.0/conformance/contract/error_with_a_lone_surrogate/case.json +26 -0
  143. nookku-0.4.0/conformance/contract/null_reply_and_error/case.json +25 -0
  144. nookku-0.4.0/conformance/contract/other_fields_are_ignored/case.json +26 -0
  145. nookku-0.4.0/conformance/contract/reply_and_error/case.json +25 -0
  146. nookku-0.4.0/conformance/contract/reply_and_null_error/case.json +25 -0
  147. nookku-0.4.0/conformance/contract/reply_is_exact/case.json +26 -0
  148. nookku-0.4.0/conformance/contract/reply_not_a_string/case.json +25 -0
  149. nookku-0.4.0/conformance/contract/reply_not_json/case.json +31 -0
  150. nookku-0.4.0/conformance/contract/reply_with_a_lone_surrogate/case.json +26 -0
  151. nookku-0.4.0/conformance/contract/reply_with_nan/case.json +25 -0
  152. nookku-0.4.0/conformance/contract/reply_wrong_contract_version/case.json +25 -0
  153. nookku-0.4.0/conformance/contract/reply_wrong_id/case.json +31 -0
  154. nookku-0.4.0/conformance/contract/request_not_a_contract_input/case.json +17 -0
  155. nookku-0.4.0/conformance/contract/request_with_a_lone_surrogate/case.json +17 -0
  156. nookku-0.4.0/conformance/contract/request_with_a_raw_line_end/case.json +17 -0
  157. nookku-0.4.0/conformance/contract/stray_line_is_unparsed/case.json +46 -0
  158. nookku-0.4.0/conformance/contract/stray_lines_before_the_reply/case.json +38 -0
  159. nookku-0.4.0/conformance/contract/timeout_stops_the_agent/case.json +32 -0
  160. nookku-0.4.0/conformance/control/broken_policy_uses_the_default.json +5 -0
  161. nookku-0.4.0/conformance/control/capital_letter.json +4 -0
  162. nookku-0.4.0/conformance/control/distance_one.json +5 -0
  163. nookku-0.4.0/conformance/control/distance_zero_turns_off_the_rule.json +5 -0
  164. nookku-0.4.0/conformance/control/name_alone.json +4 -0
  165. nookku-0.4.0/conformance/control/one_letter_short.json +4 -0
  166. nookku-0.4.0/conformance/control/shop_question_about_relays.json +4 -0
  167. nookku-0.4.0/conformance/control/shop_word_near_the_name.json +4 -0
  168. nookku-0.4.0/conformance/control/three_edits.json +4 -0
  169. nookku-0.4.0/conformance/control/two_edits.json +4 -0
  170. nookku-0.4.0/conformance/control/two_spaces.json +4 -0
  171. nookku-0.4.0/conformance/control/wrong_command_word.json +4 -0
  172. nookku-0.4.0/conformance/guard/other_tool_field_not_in_the_policy.json +15 -0
  173. nookku-0.4.0/conformance/guard/other_tool_field_of_the_policy.json +22 -0
  174. nookku-0.4.0/conformance/guard/other_tool_free_text_names_a_record.json +15 -0
  175. nookku-0.4.0/conformance/guard/other_tool_nested_uri_names_a_state_file.json +24 -0
  176. nookku-0.4.0/conformance/guard/other_tool_with_a_broken_policy.json +21 -0
  177. nookku-0.4.0/conformance/guard/other_tool_writes_a_state_file.json +21 -0
  178. nookku-0.4.0/conformance/guard/other_tool_writes_the_config.json +15 -0
  179. nookku-0.4.0/conformance/guard/patch_content_names_a_record.json +14 -0
  180. nookku-0.4.0/conformance/guard/patch_header_names_a_state_file.json +20 -0
  181. nookku-0.4.0/conformance/guard/session_input_starts_a_test.json +21 -0
  182. nookku-0.4.0/conformance/guard/shell_assignment_before_a_read_in_the_state_folder.json +20 -0
  183. nookku-0.4.0/conformance/guard/shell_assignment_names_a_record.json +20 -0
  184. nookku-0.4.0/conformance/guard/shell_audit_with_echo_tail_and_a_variable.json +14 -0
  185. nookku-0.4.0/conformance/guard/shell_backquote_names_a_record.json +20 -0
  186. nookku-0.4.0/conformance/guard/shell_braced_variable_program_names_a_record.json +20 -0
  187. nookku-0.4.0/conformance/guard/shell_changes_to_the_state_folder.json +20 -0
  188. nookku-0.4.0/conformance/guard/shell_check.json +14 -0
  189. nookku-0.4.0/conformance/guard/shell_command_runs_a_program.json +20 -0
  190. nookku-0.4.0/conformance/guard/shell_command_substitution_names_a_record.json +20 -0
  191. nookku-0.4.0/conformance/guard/shell_edit_of_a_record.json +20 -0
  192. nookku-0.4.0/conformance/guard/shell_edit_of_the_config.json +14 -0
  193. nookku-0.4.0/conformance/guard/shell_edit_of_the_entry.json +14 -0
  194. nookku-0.4.0/conformance/guard/shell_env_split_string_starts_a_test.json +20 -0
  195. nookku-0.4.0/conformance/guard/shell_env_value_names_a_drive.json +14 -0
  196. nookku-0.4.0/conformance/guard/shell_glob_of_records.json +20 -0
  197. nookku-0.4.0/conformance/guard/shell_guard_reads_keeps_the_sed_check.json +21 -0
  198. nookku-0.4.0/conformance/guard/shell_guard_reads_with_an_expansion.json +21 -0
  199. nookku-0.4.0/conformance/guard/shell_heredoc_code_imports_the_package.json +20 -0
  200. nookku-0.4.0/conformance/guard/shell_heredoc_code_names_a_record.json +20 -0
  201. nookku-0.4.0/conformance/guard/shell_heredoc_data_names_a_record.json +14 -0
  202. nookku-0.4.0/conformance/guard/shell_heredoc_data_names_an_import.json +14 -0
  203. nookku-0.4.0/conformance/guard/shell_imports_the_package.json +20 -0
  204. nookku-0.4.0/conformance/guard/shell_inits_with_a_flag_that_starts_like_remove.json +14 -0
  205. nookku-0.4.0/conformance/guard/shell_interpreter_code_names_a_record.json +20 -0
  206. nookku-0.4.0/conformance/guard/shell_mode_status.json +14 -0
  207. nookku-0.4.0/conformance/guard/shell_pipes_a_drive_into_a_shell.json +20 -0
  208. nookku-0.4.0/conformance/guard/shell_pipes_a_drive_into_a_shell_with_arguments.json +20 -0
  209. nookku-0.4.0/conformance/guard/shell_pipes_an_event_to_the_hook.json +20 -0
  210. nookku-0.4.0/conformance/guard/shell_program_not_in_guard_reads.json +20 -0
  211. nookku-0.4.0/conformance/guard/shell_program_of_guard_reads.json +15 -0
  212. nookku-0.4.0/conformance/guard/shell_program_of_guard_reads_writes_the_policy.json +21 -0
  213. nookku-0.4.0/conformance/guard/shell_python_grouped_module_flag_starts_a_test.json +20 -0
  214. nookku-0.4.0/conformance/guard/shell_python_long_option_value_starts_a_test.json +20 -0
  215. nookku-0.4.0/conformance/guard/shell_python_module_switches_relay_mode_on.json +20 -0
  216. nookku-0.4.0/conformance/guard/shell_reads_a_record_into_another_file.json +14 -0
  217. nookku-0.4.0/conformance/guard/shell_redirect_to_a_state_file.json +20 -0
  218. nookku-0.4.0/conformance/guard/shell_removes_the_project_hooks.json +20 -0
  219. nookku-0.4.0/conformance/guard/shell_removes_the_project_hooks_with_a_short_flag.json +20 -0
  220. nookku-0.4.0/conformance/guard/shell_removes_the_state_folder.json +20 -0
  221. nookku-0.4.0/conformance/guard/shell_runs_a_script_then_starts_a_test_with_scripts_model.json +21 -0
  222. nookku-0.4.0/conformance/guard/shell_runs_a_script_with_scripts_model.json +15 -0
  223. nookku-0.4.0/conformance/guard/shell_runs_a_script_with_scripts_person.json +20 -0
  224. nookku-0.4.0/conformance/guard/shell_seal_copy.json +20 -0
  225. nookku-0.4.0/conformance/guard/shell_searches_for_an_import.json +14 -0
  226. nookku-0.4.0/conformance/guard/shell_starts_a_test.json +20 -0
  227. nookku-0.4.0/conformance/guard/shell_type_and_command_v_then_a_read.json +14 -0
  228. nookku-0.4.0/conformance/guard/shell_uv_python_option_starts_a_test.json +20 -0
  229. nookku-0.4.0/conformance/guard/shell_variable_argument_of_a_read.json +14 -0
  230. nookku-0.4.0/conformance/guard/shell_variable_program_names_a_record.json +20 -0
  231. nookku-0.4.0/conformance/guard/shell_which_then_ls_of_a_test.json +14 -0
  232. nookku-0.4.0/conformance/guard/shell_writes_the_report.json +14 -0
  233. nookku-0.4.0/conformance/guard/test_other_tool_free_text_names_the_state_folder.json +14 -0
  234. nookku-0.4.0/conformance/guard/test_other_tool_free_text_names_the_tap.json +14 -0
  235. nookku-0.4.0/conformance/guard/test_other_tool_url_names_the_tap.json +20 -0
  236. nookku-0.4.0/conformance/guard/test_read_of_the_config.json +14 -0
  237. nookku-0.4.0/conformance/guard/test_shell_code_after_the_option_end_ends_the_test.json +20 -0
  238. nookku-0.4.0/conformance/guard/test_shell_code_ends_the_test.json +20 -0
  239. nookku-0.4.0/conformance/guard/test_shell_code_names_the_test_folder_variable.json +20 -0
  240. nookku-0.4.0/conformance/guard/test_shell_edit_of_the_config.json +20 -0
  241. nookku-0.4.0/conformance/guard/test_shell_ends_the_test.json +20 -0
  242. nookku-0.4.0/conformance/guard/test_shell_heredoc_data_names_the_state_folder.json +14 -0
  243. nookku-0.4.0/conformance/guard/test_shell_read_of_the_config.json +20 -0
  244. nookku-0.4.0/conformance/guard/test_shell_transcript_with_the_trace.json +14 -0
  245. nookku-0.4.0/conformance/guard/test_shell_which_then_ls_of_a_test.json +20 -0
  246. nookku-0.4.0/conformance/guard/test_shell_writes_the_tap_record_through_the_test_folder_variable.json +20 -0
  247. nookku-0.4.0/conformance/guard/test_write_content_names_the_state_folder.json +15 -0
  248. nookku-0.4.0/conformance/guard/test_write_of_the_config.json +21 -0
  249. nookku-0.4.0/conformance/guard/write_content_looks_like_a_patch.json +15 -0
  250. nookku-0.4.0/conformance/guard/write_content_names_a_record.json +15 -0
  251. nookku-0.4.0/conformance/guard/write_of_a_record.json +21 -0
  252. nookku-0.4.0/conformance/guard/write_of_the_report.json +15 -0
  253. nookku-0.4.0/conformance/otlp/harness_spans_dropped/body.bin +0 -0
  254. nookku-0.4.0/conformance/otlp/harness_spans_dropped/expect.json +5 -0
  255. nookku-0.4.0/conformance/otlp/harness_spans_dropped/request.json +5 -0
  256. nookku-0.4.0/conformance/otlp/logs_protobuf_gzip/body.bin +0 -0
  257. nookku-0.4.0/conformance/otlp/logs_protobuf_gzip/expect.json +66 -0
  258. nookku-0.4.0/conformance/otlp/logs_protobuf_gzip/request.json +5 -0
  259. nookku-0.4.0/conformance/otlp/lone_surrogate_escaped/body.bin +1 -0
  260. nookku-0.4.0/conformance/otlp/lone_surrogate_escaped/expect.json +31 -0
  261. nookku-0.4.0/conformance/otlp/lone_surrogate_escaped/request.json +5 -0
  262. nookku-0.4.0/conformance/otlp/metrics_dropped/body.bin +1 -0
  263. nookku-0.4.0/conformance/otlp/metrics_dropped/expect.json +5 -0
  264. nookku-0.4.0/conformance/otlp/metrics_dropped/request.json +5 -0
  265. nookku-0.4.0/conformance/otlp/traces_json/body.bin +1 -0
  266. nookku-0.4.0/conformance/otlp/traces_json/expect.json +49 -0
  267. nookku-0.4.0/conformance/otlp/traces_json/request.json +5 -0
  268. nookku-0.4.0/conformance/otlp/traces_protobuf/body.bin +0 -0
  269. nookku-0.4.0/conformance/otlp/traces_protobuf/expect.json +49 -0
  270. nookku-0.4.0/conformance/otlp/traces_protobuf/request.json +5 -0
  271. nookku-0.4.0/conformance/otlp/truncated_protobuf/body.bin +0 -0
  272. nookku-0.4.0/conformance/otlp/truncated_protobuf/expect.json +5 -0
  273. nookku-0.4.0/conformance/otlp/truncated_protobuf/request.json +5 -0
  274. nookku-0.4.0/conformance/policy/edit_with_other_case.json +22 -0
  275. nookku-0.4.0/conformance/policy/edit_with_the_absolute_path.json +22 -0
  276. nookku-0.4.0/conformance/policy/no_state_folder.json +21 -0
  277. nookku-0.4.0/conformance/policy/no_state_folder_other_call.json +14 -0
  278. nookku-0.4.0/conformance/policy/no_state_folder_other_tool_free_text.json +14 -0
  279. nookku-0.4.0/conformance/policy/no_state_folder_other_tool_path.json +21 -0
  280. nookku-0.4.0/conformance/policy/other_tool_free_text_names_the_file.json +14 -0
  281. nookku-0.4.0/conformance/policy/other_tool_path_names_the_file.json +21 -0
  282. nookku-0.4.0/conformance/policy/patch_names_the_file.json +20 -0
  283. nookku-0.4.0/conformance/policy/read_tool.json +14 -0
  284. nookku-0.4.0/conformance/policy/shell_edit_in_place.json +20 -0
  285. nookku-0.4.0/conformance/policy/shell_heredoc_data_names_the_file.json +14 -0
  286. nookku-0.4.0/conformance/policy/shell_policy_set.json +20 -0
  287. nookku-0.4.0/conformance/policy/shell_policy_set_through_python.json +20 -0
  288. nookku-0.4.0/conformance/policy/shell_reads_the_file.json +14 -0
  289. nookku-0.4.0/conformance/policy/shell_session_input_names_the_file.json +21 -0
  290. nookku-0.4.0/conformance/policy/shell_write_in_the_state_folder.json +20 -0
  291. nookku-0.4.0/conformance/policy/write_a_policy_file_of_the_app.json +15 -0
  292. nookku-0.4.0/conformance/policy/write_content_looks_like_a_patch.json +15 -0
  293. nookku-0.4.0/conformance/policy/write_content_names_the_file.json +15 -0
  294. nookku-0.4.0/conformance/policy/write_in_the_state_folder_with_a_relative_path.json +21 -0
  295. nookku-0.4.0/conformance/policy/write_names_the_file.json +21 -0
  296. nookku-0.4.0/conformance/policy/write_the_config_with_no_test.json +15 -0
  297. nookku-0.4.0/conformance/policy/write_through_a_link.json +23 -0
  298. nookku-0.4.0/conformance/seal/changed_record/expect_verify.json +11 -0
  299. nookku-0.4.0/conformance/seal/changed_record/home/seals/20261006-120000-se01.json +15 -0
  300. nookku-0.4.0/conformance/seal/changed_record/test/20261006-120000-se01/audit.json +1 -0
  301. nookku-0.4.0/conformance/seal/changed_record/test/20261006-120000-se01/bridge.log +1 -0
  302. nookku-0.4.0/conformance/seal/changed_record/test/20261006-120000-se01/findings.json +1 -0
  303. nookku-0.4.0/conformance/seal/changed_record/test/20261006-120000-se01/manifest.json +1 -0
  304. nookku-0.4.0/conformance/seal/changed_record/test/20261006-120000-se01/relay.jsonl +1 -0
  305. nookku-0.4.0/conformance/seal/changed_record/test/20261006-120000-se01/report.md +1 -0
  306. nookku-0.4.0/conformance/seal/changed_record/test/20261006-120000-se01/seal.json +15 -0
  307. nookku-0.4.0/conformance/seal/changed_record/test/20261006-120000-se01/sessions/claude-code/s1.jsonl +1 -0
  308. nookku-0.4.0/conformance/seal/changed_record/test/20261006-120000-se01/trace.jsonl +1 -0
  309. nookku-0.4.0/conformance/seal/copies_differ/expect_verify.json +9 -0
  310. nookku-0.4.0/conformance/seal/copies_differ/home/seals/20261006-120000-se01.json +15 -0
  311. nookku-0.4.0/conformance/seal/copies_differ/test/20261006-120000-se01/audit.json +1 -0
  312. nookku-0.4.0/conformance/seal/copies_differ/test/20261006-120000-se01/bridge.log +1 -0
  313. nookku-0.4.0/conformance/seal/copies_differ/test/20261006-120000-se01/findings.json +1 -0
  314. nookku-0.4.0/conformance/seal/copies_differ/test/20261006-120000-se01/manifest.json +1 -0
  315. nookku-0.4.0/conformance/seal/copies_differ/test/20261006-120000-se01/relay.jsonl +1 -0
  316. nookku-0.4.0/conformance/seal/copies_differ/test/20261006-120000-se01/report.md +1 -0
  317. nookku-0.4.0/conformance/seal/copies_differ/test/20261006-120000-se01/seal.json +15 -0
  318. nookku-0.4.0/conformance/seal/copies_differ/test/20261006-120000-se01/sessions/claude-code/s1.jsonl +1 -0
  319. nookku-0.4.0/conformance/seal/copies_differ/test/20261006-120000-se01/trace.jsonl +1 -0
  320. nookku-0.4.0/conformance/seal/copy_flag_cleared/expect_verify.json +9 -0
  321. nookku-0.4.0/conformance/seal/copy_flag_cleared/home/seals/20261006-120000-se01.json +15 -0
  322. nookku-0.4.0/conformance/seal/copy_flag_cleared/test/20261006-120000-se01/audit.json +1 -0
  323. nookku-0.4.0/conformance/seal/copy_flag_cleared/test/20261006-120000-se01/bridge.log +1 -0
  324. nookku-0.4.0/conformance/seal/copy_flag_cleared/test/20261006-120000-se01/findings.json +1 -0
  325. nookku-0.4.0/conformance/seal/copy_flag_cleared/test/20261006-120000-se01/manifest.json +1 -0
  326. nookku-0.4.0/conformance/seal/copy_flag_cleared/test/20261006-120000-se01/relay.jsonl +1 -0
  327. nookku-0.4.0/conformance/seal/copy_flag_cleared/test/20261006-120000-se01/report.md +1 -0
  328. nookku-0.4.0/conformance/seal/copy_flag_cleared/test/20261006-120000-se01/seal.json +15 -0
  329. nookku-0.4.0/conformance/seal/copy_flag_cleared/test/20261006-120000-se01/sessions/claude-code/s1.jsonl +1 -0
  330. nookku-0.4.0/conformance/seal/copy_flag_cleared/test/20261006-120000-se01/trace.jsonl +1 -0
  331. nookku-0.4.0/conformance/seal/copy_missing/expect_verify.json +9 -0
  332. nookku-0.4.0/conformance/seal/copy_missing/test/20261006-120000-se01/audit.json +1 -0
  333. nookku-0.4.0/conformance/seal/copy_missing/test/20261006-120000-se01/bridge.log +1 -0
  334. nookku-0.4.0/conformance/seal/copy_missing/test/20261006-120000-se01/findings.json +1 -0
  335. nookku-0.4.0/conformance/seal/copy_missing/test/20261006-120000-se01/manifest.json +1 -0
  336. nookku-0.4.0/conformance/seal/copy_missing/test/20261006-120000-se01/relay.jsonl +1 -0
  337. nookku-0.4.0/conformance/seal/copy_missing/test/20261006-120000-se01/report.md +1 -0
  338. nookku-0.4.0/conformance/seal/copy_missing/test/20261006-120000-se01/seal.json +15 -0
  339. nookku-0.4.0/conformance/seal/copy_missing/test/20261006-120000-se01/sessions/claude-code/s1.jsonl +1 -0
  340. nookku-0.4.0/conformance/seal/copy_missing/test/20261006-120000-se01/trace.jsonl +1 -0
  341. nookku-0.4.0/conformance/seal/files_that_change_after_the_end/expect_verify.json +9 -0
  342. nookku-0.4.0/conformance/seal/files_that_change_after_the_end/home/seals/20261006-120000-se01.json +15 -0
  343. nookku-0.4.0/conformance/seal/files_that_change_after_the_end/test/20261006-120000-se01/audit.json +1 -0
  344. nookku-0.4.0/conformance/seal/files_that_change_after_the_end/test/20261006-120000-se01/bridge.log +2 -0
  345. nookku-0.4.0/conformance/seal/files_that_change_after_the_end/test/20261006-120000-se01/denied.jsonl +1 -0
  346. nookku-0.4.0/conformance/seal/files_that_change_after_the_end/test/20261006-120000-se01/findings.json +1 -0
  347. nookku-0.4.0/conformance/seal/files_that_change_after_the_end/test/20261006-120000-se01/manifest.json +1 -0
  348. nookku-0.4.0/conformance/seal/files_that_change_after_the_end/test/20261006-120000-se01/relay.jsonl +1 -0
  349. nookku-0.4.0/conformance/seal/files_that_change_after_the_end/test/20261006-120000-se01/report.md +3 -0
  350. nookku-0.4.0/conformance/seal/files_that_change_after_the_end/test/20261006-120000-se01/seal.json +15 -0
  351. nookku-0.4.0/conformance/seal/files_that_change_after_the_end/test/20261006-120000-se01/sessions/claude-code/s1.jsonl +1 -0
  352. nookku-0.4.0/conformance/seal/files_that_change_after_the_end/test/20261006-120000-se01/trace.jsonl +1 -0
  353. nookku-0.4.0/conformance/seal/intact/expect_verify.json +9 -0
  354. nookku-0.4.0/conformance/seal/intact/home/seals/20261006-120000-se01.json +15 -0
  355. nookku-0.4.0/conformance/seal/intact/test/20261006-120000-se01/audit.json +1 -0
  356. nookku-0.4.0/conformance/seal/intact/test/20261006-120000-se01/bridge.log +1 -0
  357. nookku-0.4.0/conformance/seal/intact/test/20261006-120000-se01/findings.json +1 -0
  358. nookku-0.4.0/conformance/seal/intact/test/20261006-120000-se01/manifest.json +1 -0
  359. nookku-0.4.0/conformance/seal/intact/test/20261006-120000-se01/relay.jsonl +1 -0
  360. nookku-0.4.0/conformance/seal/intact/test/20261006-120000-se01/report.md +1 -0
  361. nookku-0.4.0/conformance/seal/intact/test/20261006-120000-se01/seal.json +15 -0
  362. nookku-0.4.0/conformance/seal/intact/test/20261006-120000-se01/sessions/claude-code/s1.jsonl +1 -0
  363. nookku-0.4.0/conformance/seal/intact/test/20261006-120000-se01/trace.jsonl +1 -0
  364. nookku-0.4.0/conformance/seal/missing_record/expect_verify.json +11 -0
  365. nookku-0.4.0/conformance/seal/missing_record/home/seals/20261006-120000-se01.json +15 -0
  366. nookku-0.4.0/conformance/seal/missing_record/test/20261006-120000-se01/audit.json +1 -0
  367. nookku-0.4.0/conformance/seal/missing_record/test/20261006-120000-se01/bridge.log +1 -0
  368. nookku-0.4.0/conformance/seal/missing_record/test/20261006-120000-se01/manifest.json +1 -0
  369. nookku-0.4.0/conformance/seal/missing_record/test/20261006-120000-se01/relay.jsonl +1 -0
  370. nookku-0.4.0/conformance/seal/missing_record/test/20261006-120000-se01/report.md +1 -0
  371. nookku-0.4.0/conformance/seal/missing_record/test/20261006-120000-se01/seal.json +15 -0
  372. nookku-0.4.0/conformance/seal/missing_record/test/20261006-120000-se01/sessions/claude-code/s1.jsonl +1 -0
  373. nookku-0.4.0/conformance/seal/missing_record/test/20261006-120000-se01/trace.jsonl +1 -0
  374. nookku-0.4.0/conformance/seal/new_file/expect_verify.json +11 -0
  375. nookku-0.4.0/conformance/seal/new_file/home/seals/20261006-120000-se01.json +15 -0
  376. nookku-0.4.0/conformance/seal/new_file/test/20261006-120000-se01/audit.json +1 -0
  377. nookku-0.4.0/conformance/seal/new_file/test/20261006-120000-se01/bridge.log +1 -0
  378. nookku-0.4.0/conformance/seal/new_file/test/20261006-120000-se01/findings.json +1 -0
  379. nookku-0.4.0/conformance/seal/new_file/test/20261006-120000-se01/manifest.json +1 -0
  380. nookku-0.4.0/conformance/seal/new_file/test/20261006-120000-se01/relay.jsonl +1 -0
  381. nookku-0.4.0/conformance/seal/new_file/test/20261006-120000-se01/report.md +1 -0
  382. nookku-0.4.0/conformance/seal/new_file/test/20261006-120000-se01/seal.json +15 -0
  383. nookku-0.4.0/conformance/seal/new_file/test/20261006-120000-se01/sessions/claude-code/s1.jsonl +1 -0
  384. nookku-0.4.0/conformance/seal/new_file/test/20261006-120000-se01/sessions/codex/extra.jsonl +1 -0
  385. nookku-0.4.0/conformance/seal/new_file/test/20261006-120000-se01/trace.jsonl +1 -0
  386. nookku-0.4.0/conformance/seal/no_copy/expect_verify.json +9 -0
  387. nookku-0.4.0/conformance/seal/no_copy/test/20261006-120000-se01/audit.json +1 -0
  388. nookku-0.4.0/conformance/seal/no_copy/test/20261006-120000-se01/bridge.log +1 -0
  389. nookku-0.4.0/conformance/seal/no_copy/test/20261006-120000-se01/findings.json +1 -0
  390. nookku-0.4.0/conformance/seal/no_copy/test/20261006-120000-se01/manifest.json +1 -0
  391. nookku-0.4.0/conformance/seal/no_copy/test/20261006-120000-se01/relay.jsonl +1 -0
  392. nookku-0.4.0/conformance/seal/no_copy/test/20261006-120000-se01/report.md +1 -0
  393. nookku-0.4.0/conformance/seal/no_copy/test/20261006-120000-se01/seal.json +15 -0
  394. nookku-0.4.0/conformance/seal/no_copy/test/20261006-120000-se01/sessions/claude-code/s1.jsonl +1 -0
  395. nookku-0.4.0/conformance/seal/no_copy/test/20261006-120000-se01/trace.jsonl +1 -0
  396. nookku-0.4.0/conformance/seal/no_seal/expect_verify.json +9 -0
  397. nookku-0.4.0/conformance/seal/no_seal/test/20261006-120000-se01/audit.json +1 -0
  398. nookku-0.4.0/conformance/seal/no_seal/test/20261006-120000-se01/bridge.log +1 -0
  399. nookku-0.4.0/conformance/seal/no_seal/test/20261006-120000-se01/findings.json +1 -0
  400. nookku-0.4.0/conformance/seal/no_seal/test/20261006-120000-se01/manifest.json +1 -0
  401. nookku-0.4.0/conformance/seal/no_seal/test/20261006-120000-se01/relay.jsonl +1 -0
  402. nookku-0.4.0/conformance/seal/no_seal/test/20261006-120000-se01/report.md +1 -0
  403. nookku-0.4.0/conformance/seal/no_seal/test/20261006-120000-se01/sessions/claude-code/s1.jsonl +1 -0
  404. nookku-0.4.0/conformance/seal/no_seal/test/20261006-120000-se01/trace.jsonl +1 -0
  405. nookku-0.4.0/conformance/seal/seal_missing/expect_verify.json +9 -0
  406. nookku-0.4.0/conformance/seal/seal_missing/home/seals/20261006-120000-se01.json +15 -0
  407. nookku-0.4.0/conformance/seal/seal_missing/test/20261006-120000-se01/audit.json +1 -0
  408. nookku-0.4.0/conformance/seal/seal_missing/test/20261006-120000-se01/bridge.log +1 -0
  409. nookku-0.4.0/conformance/seal/seal_missing/test/20261006-120000-se01/findings.json +1 -0
  410. nookku-0.4.0/conformance/seal/seal_missing/test/20261006-120000-se01/manifest.json +1 -0
  411. nookku-0.4.0/conformance/seal/seal_missing/test/20261006-120000-se01/relay.jsonl +1 -0
  412. nookku-0.4.0/conformance/seal/seal_missing/test/20261006-120000-se01/report.md +1 -0
  413. nookku-0.4.0/conformance/seal/seal_missing/test/20261006-120000-se01/sessions/claude-code/s1.jsonl +1 -0
  414. nookku-0.4.0/conformance/seal/seal_missing/test/20261006-120000-se01/trace.jsonl +1 -0
  415. nookku-0.4.0/conformance/trace/backend_toy_shop/backend.jsonl +5 -0
  416. nookku-0.4.0/conformance/trace/backend_toy_shop/expect_findings.json +68 -0
  417. nookku-0.4.0/conformance/trace/backend_toy_shop/expect_trace.jsonl +4 -0
  418. nookku-0.4.0/conformance/trace/backend_toy_shop/manifest.json +4 -0
  419. nookku-0.4.0/conformance/trace/claude_code_toy_shop/expect_findings.json +111 -0
  420. nookku-0.4.0/conformance/trace/claude_code_toy_shop/expect_trace.jsonl +11 -0
  421. nookku-0.4.0/conformance/trace/claude_code_toy_shop/manifest.json +12 -0
  422. nookku-0.4.0/conformance/trace/claude_code_toy_shop/sessions/claude-code/4f1c2a7e-0d3b-4c55-9a61-2b8e5d7c9f10.jsonl +20 -0
  423. nookku-0.4.0/conformance/trace/codex_toy_shop/expect_findings.json +123 -0
  424. nookku-0.4.0/conformance/trace/codex_toy_shop/expect_trace.jsonl +12 -0
  425. nookku-0.4.0/conformance/trace/codex_toy_shop/manifest.json +13 -0
  426. nookku-0.4.0/conformance/trace/codex_toy_shop/sessions/codex/rollout-2026-10-06T08-00-00-019a0b1c-2d3e-7f40-8a5b-6c7d8e9f0a1b.jsonl +18 -0
  427. nookku-0.4.0/conformance/trace/model_api_decisions/expect_findings.json +34 -0
  428. nookku-0.4.0/conformance/trace/model_api_decisions/expect_trace.jsonl +4 -0
  429. nookku-0.4.0/conformance/trace/model_api_decisions/manifest.json +4 -0
  430. nookku-0.4.0/conformance/trace/model_api_decisions/model_api.jsonl +2 -0
  431. nookku-0.4.0/conformance/trace/model_api_responses/expect_findings.json +46 -0
  432. nookku-0.4.0/conformance/trace/model_api_responses/expect_trace.jsonl +6 -0
  433. nookku-0.4.0/conformance/trace/model_api_responses/manifest.json +4 -0
  434. nookku-0.4.0/conformance/trace/model_api_responses/model_api.jsonl +4 -0
  435. nookku-0.4.0/conformance/trace/model_api_toy_shop/expect_findings.json +50 -0
  436. nookku-0.4.0/conformance/trace/model_api_toy_shop/expect_trace.jsonl +9 -0
  437. nookku-0.4.0/conformance/trace/model_api_toy_shop/manifest.json +4 -0
  438. nookku-0.4.0/conformance/trace/model_api_toy_shop/model_api.jsonl +7 -0
  439. nookku-0.4.0/conformance/trace/no_model_sessions/expect_findings.json +27 -0
  440. nookku-0.4.0/conformance/trace/no_model_sessions/expect_trace.jsonl +0 -0
  441. nookku-0.4.0/conformance/trace/no_model_sessions/manifest.json +4 -0
  442. nookku-0.4.0/conformance/trace/otel_structured_output/expect_findings.json +98 -0
  443. nookku-0.4.0/conformance/trace/otel_structured_output/expect_trace.jsonl +9 -0
  444. nookku-0.4.0/conformance/trace/otel_structured_output/manifest.json +19 -0
  445. nookku-0.4.0/conformance/trace/otel_structured_output/otel.jsonl +5 -0
  446. nookku-0.4.0/conformance/trace/otel_structured_output/sessions/claude-code/4f1c2a7e-0d3b-4c55-9a61-2b8e5d7c9f10.jsonl +5 -0
  447. nookku-0.4.0/conformance/trace/otel_structured_output/sessions/claude-code/8a2d4f6b-1c3e-4a57-9b8d-0e2f4a6c8e01.jsonl +2 -0
  448. nookku-0.4.0/conformance/trace/otel_toy_shop/expect_findings.json +89 -0
  449. nookku-0.4.0/conformance/trace/otel_toy_shop/expect_trace.jsonl +11 -0
  450. nookku-0.4.0/conformance/trace/otel_toy_shop/manifest.json +12 -0
  451. nookku-0.4.0/conformance/trace/otel_toy_shop/otel.jsonl +7 -0
  452. nookku-0.4.0/conformance/trace/otel_toy_shop/sessions/claude-code/4f1c2a7e-0d3b-4c55-9a61-2b8e5d7c9f10.jsonl +6 -0
  453. nookku-0.4.0/conformance/trace/repeated_reply/expect_findings.json +52 -0
  454. nookku-0.4.0/conformance/trace/repeated_reply/expect_trace.jsonl +0 -0
  455. nookku-0.4.0/conformance/trace/repeated_reply/manifest.json +4 -0
  456. nookku-0.4.0/conformance/trace/repeated_reply_off/expect_findings.json +33 -0
  457. nookku-0.4.0/conformance/trace/repeated_reply_off/expect_trace.jsonl +0 -0
  458. nookku-0.4.0/conformance/trace/repeated_reply_off/manifest.json +7 -0
  459. nookku-0.4.0/conformance/trace/repeated_reply_three/expect_findings.json +43 -0
  460. nookku-0.4.0/conformance/trace/repeated_reply_three/expect_trace.jsonl +0 -0
  461. nookku-0.4.0/conformance/trace/repeated_reply_three/manifest.json +7 -0
  462. nookku-0.4.0/conformance/trace/reply_not_from_model/expect_findings.json +48 -0
  463. nookku-0.4.0/conformance/trace/reply_not_from_model/expect_trace.jsonl +6 -0
  464. nookku-0.4.0/conformance/trace/reply_not_from_model/manifest.json +12 -0
  465. nookku-0.4.0/conformance/trace/reply_not_from_model/sessions/claude-code/4f1c2a7e-0d3b-4c55-9a61-2b8e5d7c9f10.jsonl +6 -0
  466. nookku-0.4.0/conformance/trace/reply_not_from_model_exact/expect_findings.json +53 -0
  467. nookku-0.4.0/conformance/trace/reply_not_from_model_exact/expect_trace.jsonl +6 -0
  468. nookku-0.4.0/conformance/trace/reply_not_from_model_exact/manifest.json +15 -0
  469. nookku-0.4.0/conformance/trace/reply_not_from_model_exact/sessions/claude-code/4f1c2a7e-0d3b-4c55-9a61-2b8e5d7c9f10.jsonl +6 -0
  470. nookku-0.4.0/conformance/trace/reply_not_from_model_field/expect_findings.json +43 -0
  471. nookku-0.4.0/conformance/trace/reply_not_from_model_field/expect_trace.jsonl +8 -0
  472. nookku-0.4.0/conformance/trace/reply_not_from_model_field/manifest.json +15 -0
  473. nookku-0.4.0/conformance/trace/reply_not_from_model_field/sessions/claude-code/4f1c2a7e-0d3b-4c55-9a61-2b8e5d7c9f10.jsonl +9 -0
  474. nookku-0.4.0/conformance/trace/reply_not_from_model_off/expect_findings.json +43 -0
  475. nookku-0.4.0/conformance/trace/reply_not_from_model_off/expect_trace.jsonl +6 -0
  476. nookku-0.4.0/conformance/trace/reply_not_from_model_off/manifest.json +15 -0
  477. nookku-0.4.0/conformance/trace/reply_not_from_model_off/sessions/claude-code/4f1c2a7e-0d3b-4c55-9a61-2b8e5d7c9f10.jsonl +6 -0
  478. nookku-0.4.0/conformance/trace/servers_not_from_app/expect_findings.json +73 -0
  479. nookku-0.4.0/conformance/trace/servers_not_from_app/expect_trace.jsonl +4 -0
  480. nookku-0.4.0/conformance/trace/servers_not_from_app/manifest.json +12 -0
  481. nookku-0.4.0/conformance/trace/servers_not_from_app/sessions/claude-code/4f1c2a7e-0d3b-4c55-9a61-2b8e5d7c9f10.jsonl +8 -0
  482. nookku-0.4.0/conformance/trace/untested_versions/expect_findings.json +72 -0
  483. nookku-0.4.0/conformance/trace/untested_versions/expect_trace.jsonl +2 -0
  484. nookku-0.4.0/conformance/trace/untested_versions/manifest.json +27 -0
  485. nookku-0.4.0/conformance/trace/untested_versions/sessions/claude-code/4f1c2a7e-0d3b-4c55-9a61-2b8e5d7c9f10.jsonl +2 -0
  486. nookku-0.4.0/conformance/trace/untested_versions/sessions/codex/rollout-2026-10-06T08-00-00-019a0b1c-2d3e-7f40-8a5b-6c7d8e9f0a1b.jsonl +1 -0
  487. nookku-0.4.0/pyproject.toml +86 -0
  488. nookku-0.4.0/src/nookku/__init__.py +3 -0
  489. nookku-0.4.0/src/nookku/__main__.py +21 -0
  490. nookku-0.4.0/src/nookku/adapters.py +214 -0
  491. nookku-0.4.0/src/nookku/agent.py +51 -0
  492. nookku-0.4.0/src/nookku/audit.py +279 -0
  493. nookku-0.4.0/src/nookku/backend.py +394 -0
  494. nookku-0.4.0/src/nookku/bridge.py +802 -0
  495. nookku-0.4.0/src/nookku/claude_gate.py +115 -0
  496. nookku-0.4.0/src/nookku/cli.py +635 -0
  497. nookku-0.4.0/src/nookku/codex_gate.py +267 -0
  498. nookku-0.4.0/src/nookku/commands.py +673 -0
  499. nookku-0.4.0/src/nookku/config.py +185 -0
  500. nookku-0.4.0/src/nookku/contract.py +79 -0
  501. nookku-0.4.0/src/nookku/evaluate.md +50 -0
  502. nookku-0.4.0/src/nookku/evaluation.py +349 -0
  503. nookku-0.4.0/src/nookku/hook.py +36 -0
  504. nookku-0.4.0/src/nookku/kit.py +1135 -0
  505. nookku-0.4.0/src/nookku/mcp.py +301 -0
  506. nookku-0.4.0/src/nookku/model_api.py +422 -0
  507. nookku-0.4.0/src/nookku/otlp.py +489 -0
  508. nookku-0.4.0/src/nookku/policy.py +243 -0
  509. nookku-0.4.0/src/nookku/py.typed +0 -0
  510. nookku-0.4.0/src/nookku/record.py +303 -0
  511. nookku-0.4.0/src/nookku/script.py +90 -0
  512. nookku-0.4.0/src/nookku/seal.py +164 -0
  513. nookku-0.4.0/src/nookku/setup.md +75 -0
  514. nookku-0.4.0/src/nookku/state.py +182 -0
  515. nookku-0.4.0/src/nookku/stdio.py +335 -0
  516. nookku-0.4.0/src/nookku/tap.py +367 -0
  517. nookku-0.4.0/src/nookku/trace.py +921 -0
  518. nookku-0.4.0/tests/conftest.py +30 -0
  519. nookku-0.4.0/tests/tables.json +87 -0
  520. nookku-0.4.0/tests/test_adapters.py +140 -0
  521. nookku-0.4.0/tests/test_agents_md.py +14 -0
  522. nookku-0.4.0/tests/test_backend.py +278 -0
  523. nookku-0.4.0/tests/test_bridge.py +872 -0
  524. nookku-0.4.0/tests/test_claude_gate.py +121 -0
  525. nookku-0.4.0/tests/test_cli.py +665 -0
  526. nookku-0.4.0/tests/test_codex_gate.py +267 -0
  527. nookku-0.4.0/tests/test_commands.py +162 -0
  528. nookku-0.4.0/tests/test_conformance.py +49 -0
  529. nookku-0.4.0/tests/test_contract.py +356 -0
  530. nookku-0.4.0/tests/test_docs.py +486 -0
  531. nookku-0.4.0/tests/test_evaluation.py +333 -0
  532. nookku-0.4.0/tests/test_example_entries.py +149 -0
  533. nookku-0.4.0/tests/test_guard.py +180 -0
  534. nookku-0.4.0/tests/test_hook_imports.py +67 -0
  535. nookku-0.4.0/tests/test_kit.py +775 -0
  536. nookku-0.4.0/tests/test_mcp.py +200 -0
  537. nookku-0.4.0/tests/test_model_api.py +329 -0
  538. nookku-0.4.0/tests/test_otlp.py +100 -0
  539. nookku-0.4.0/tests/test_package.py +23 -0
  540. nookku-0.4.0/tests/test_plugin.py +158 -0
  541. nookku-0.4.0/tests/test_policy.py +202 -0
  542. nookku-0.4.0/tests/test_proof_common.py +22 -0
  543. nookku-0.4.0/tests/test_redirect.py +120 -0
  544. nookku-0.4.0/tests/test_script.py +53 -0
  545. nookku-0.4.0/tests/test_seal.py +99 -0
  546. nookku-0.4.0/tests/test_spike_codex_display.py +649 -0
  547. nookku-0.4.0/tests/test_spike_hook_display.py +291 -0
  548. nookku-0.4.0/tests/test_spike_plugin_mcp.py +273 -0
  549. nookku-0.4.0/tests/test_state_move.py +103 -0
  550. nookku-0.4.0/tests/test_stealth.py +26 -0
  551. nookku-0.4.0/tests/test_tap.py +305 -0
  552. nookku-0.4.0/tests/test_timeouts.py +122 -0
  553. nookku-0.4.0/tests/test_toy_shop_full.py +91 -0
  554. nookku-0.4.0/tests/test_trace.py +246 -0
  555. nookku-0.4.0/tests/toy_agent.py +147 -0
  556. nookku-0.4.0/tests/toy_entry.py +7 -0
  557. nookku-0.4.0/tests/toy_mcp_server.py +57 -0
  558. nookku-0.4.0/tests/toy_model_server.py +83 -0
  559. nookku-0.4.0/tests/toy_models_entry.py +161 -0
  560. nookku-0.4.0/tests/toy_stock_server.py +71 -0
@@ -0,0 +1,26 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .venv/
4
+ .venv-*/
5
+ dist/
6
+ build/
7
+ *.egg-info/
8
+ .coverage
9
+ coverage.xml
10
+ htmlcov/
11
+ .mypy_cache/
12
+ .pytest_cache/
13
+ .ruff_cache/
14
+ .DS_Store
15
+ .env
16
+ CLAUDE.local.md
17
+ .nookku/
18
+ # The state folder of verbatim-relay 0.3.x and earlier.
19
+ .verbatim-relay/
20
+ .proof/
21
+ bench/smoke/
22
+ bench/logs/
23
+ tap.jsonl
24
+ # The proofs commit the tap record of each run as their data.
25
+ !proofs/**/tap.jsonl
26
+ .gstack/
@@ -0,0 +1,127 @@
1
+ # Changelog
2
+
3
+ ## 0.4.0
4
+
5
+ verbatim-relay is now Nookku. The package, the CLI, the module, the plugin, the marketplace, the state folder and the variables have the new name. The record format and the audit do not change.
6
+
7
+ **Upgrade.** End each running test. Then install `nookku`, update the plugin and run `nookku init` again. The first `nookku` command in a project moves `.verbatim-relay/` to `.nookku/`. [The upgrade guide](docs/how-to/upgrade.md#040) gives each step.
8
+
9
+ - **New name.** The package and the CLI are `nookku`, the module is `nookku`, and the plugin is `nookku@nookku`. The variables start with `NOOKKU_`, for example `NOOKKU_HOME`. The repo is `mohanraj00/nookku` ([#181](https://github.com/mohanraj00/nookku/issues/181), [#208](https://github.com/mohanraj00/nookku/issues/208), [#210](https://github.com/mohanraj00/nookku/issues/210)).
10
+ - **State folder move.** Each command with a project root moves `.verbatim-relay/` to `.nookku/`. A `record` path in the old folder changes to the same file in `.nookku/`. If both folders exist, the command stops and names both. A hook event is then blocked, so the relay fails closed ([SPEC.md section 7](SPEC.md#7-tests), [#181](https://github.com/mohanraj00/nookku/issues/181)).
11
+ - **Old seal copies.** `verify` reads the seal copy of an old test from `~/.verbatim-relay/seals/` if `~/.nookku/seals/` has no copy ([SPEC.md section 7.4](SPEC.md#74-seal), [#181](https://github.com/mohanraj00/nookku/issues/181)).
12
+ - **One core, one plugin.** [ADR 0001](docs/adr/0001-one-core-one-plugin.md) records the decision for one core and one plugin for both harnesses. It links the data and the method of each spike ([#176](https://github.com/mohanraj00/nookku/issues/176), [#177](https://github.com/mohanraj00/nookku/issues/177), [#178](https://github.com/mohanraj00/nookku/issues/178), [#179](https://github.com/mohanraj00/nookku/issues/179), [#180](https://github.com/mohanraj00/nookku/issues/180), [#193](https://github.com/mohanraj00/nookku/issues/193), [#194](https://github.com/mohanraj00/nookku/issues/194), [#205](https://github.com/mohanraj00/nookku/issues/205)).
13
+ - **Reply in the chat.** The hook kit shows each reply as the reason of the blocked prompt, byte for byte. Claude Code and Codex show the reason to the person and do not give it to the model. `codex exec` shows no reason, so `nookku view` stays ([#214](https://github.com/mohanraj00/nookku/issues/214)).
14
+ - **Faster hooks.** A hook event imports only the modules that its rule needs. Over the floor of the same run, a warm event takes 14 to 23 ms on Linux and on macOS (the second run of the data, with less load), not 28 to 34 ms ([data](proofs/hook-time/hook-latency.json), [method](scripts/spike_hook_latency.py), [#214](https://github.com/mohanraj00/nookku/issues/214)).
15
+ - **Hook with no root.** `nookku hook` finds the project from `CLAUDE_PROJECT_DIR` or the `cwd` of the event, if it gets no `--root` ([#214](https://github.com/mohanraj00/nookku/issues/214)).
16
+ - **MCP server.** `nookku mcp` gives the model the read-only tools `transcript` and `status`, with the standard library only. The transcript comes in pages with a footer and a SHA-256, so a page that a harness cut shows it. The default page got to the model unchanged in Claude Code and in Codex for 4 kinds of text ([data](proofs/mcp/transcript-pages.json), [method](scripts/measure_transcript_pages.py), [#215](https://github.com/mohanraj00/nookku/issues/215)).
17
+ - **One plugin for Claude Code and Codex.** The plugin folder is `plugins/nookku`, with a manifest for each harness, one command hook file, the MCP server `nookku mcp` and one skill. Each command hook runs `nookku hook`, so the plugin and the project hooks share one core. If `nookku` is not on `PATH`, a shell guard blocks the prompt in relay mode. The Claude Code function hooks only show the output of the core: `/nookku`, the status line and the pane. One exception: a command hook gets only the text of a prompt, so in relay mode the function hook drops a prompt with an attachment, with the text of the core. The plugin loads in Claude Code 2.1.295 and in Codex 0.162.0 ([data](proofs/plugin/load.json), [method](scripts/proof_plugin_load.py), [#216](https://github.com/mohanraj00/nookku/issues/216)).
18
+ - **Codex hook gate.** Codex skips a hook that a person did not trust, and then a message goes to the model. `start` and `mode on` now read the hooks of Codex with `hooks/list`, and refuse the test if a nookku hook is missing, disabled, not trusted or modified. The trust hash of Codex does not cover the plugin script, so the gate also checks its SHA-256. `end` checks again, and the manifest keeps both results. With the gate, the Codex marketplace lists the plugin as available ([SPEC.md section 7.8](SPEC.md#78-codex-hook-gate), [data](proofs/codex-gate/gate.json), [method](scripts/proof_codex_gate.py), [#217](https://github.com/mohanraj00/nookku/issues/217)).
19
+ - **Docs for one core.** The docs name one relay, `nookku hook`, in 2 forms: the plugin and the project hooks (the hook kit of 0.3). The plugin works in Claude Code and in Codex. [Choose the plugin or the project hooks](docs/how-to/choose-a-relay.md) compares them. SPEC.md section 5 and [limits.md](docs/limits.md) state that `claude -p` and the Codex desktop app can send a blocked prompt to the model API ([#199](https://github.com/mohanraj00/nookku/issues/199), [#203](https://github.com/mohanraj00/nookku/issues/203), [#218](https://github.com/mohanraj00/nookku/issues/218)).
20
+ - **Codex plugin upgrade.** The upgrade guide updates the Codex plugin with `codex plugin marketplace upgrade nookku` and `codex plugin add nookku@nookku`, not with a new install ([upgrade.md](docs/how-to/upgrade.md#3-update-the-plugin), [data](proofs/spikes/codex-plugin.json), [method](scripts/spike_codex_plugin.py), [#218](https://github.com/mohanraj00/nookku/issues/218)).
21
+ - **Proofs of one core.** `scripts/proofs_relay.py <setup>` runs P1 to P4 in 4 setups: the plugin and the project hooks, each in Claude Code and in Codex. It replaces the proof scripts of the TypeScript plugin. The report, telemetry and evaluation proofs take the same setup names. Each proof passed in each setup with nookku 0.3.1 ([results.md](docs/results.md#1-proofs), [#219](https://github.com/mohanraj00/nookku/issues/219)).
22
+ - **Sample outputs.** The docs show the output of nookku 0.4.0, in place of the output of verbatim-relay 0.3.0. A model answer and a command that changes the install of the computer keep the output of 0.3.0, and each page says so ([#212](https://github.com/mohanraj00/nookku/issues/212)).
23
+ - **No plugin options.** The plugin reads `.nookku/config.json`. Write it with `nookku init plugin`, which writes no project hooks. `nookku mode on` with no config keeps relay mode off ([#216](https://github.com/mohanraj00/nookku/issues/216)).
24
+ - **No record limit.** The plugin no longer stops at a relay record of 3.5 MiB, because the core writes the record ([#216](https://github.com/mohanraj00/nookku/issues/216)).
25
+ - **Policy file.** `.nookku/policy.json` holds the keys that control the guard. Only a person changes it, with `nookku policy set` in a shell. The relay denies each model write to the file, also when no test runs and in a project with no `.nookku/` folder. The manifest records the value of each key. Its first key is `guard_fields` ([SPEC.md section 7.9](SPEC.md#79-policy-file), [#175](https://github.com/mohanraj00/nookku/issues/175)).
26
+ - **Guard checks paths.** The deny of the state folder checks the paths that a tool call writes, not its text. When no test runs, a tool call can change `config.json` and the files of the entry, and the relay denies only a write to a record or a state file. A file whose content names a record, or a here-document that is data, is not denied. Each reason names the path ([SPEC.md section 5](SPEC.md#5-relays), [#149](https://github.com/mohanraj00/nookku/issues/149)).
27
+ - **Guard fields.** For an MCP tool or another tool that is not a shell or a file tool, the guard reads only the fields of the policy key `guard_fields`: by default `path`, `file_path`, `url`, `uri` and `command`. A document body that names the state folder or the tap is not denied ([SPEC.md section 5](SPEC.md#5-relays), [#150](https://github.com/mohanraj00/nookku/issues/150)).
28
+ - **Read commands and deny causes.** The read check accepts `which`, `type` and `command -v`, and the programs of the new policy key `guard_reads`. The records deny names the program or the redirect that failed, for example `"rm" is not a read command.` A variable can be an argument of a read program, but not the program ([SPEC.md section 5](SPEC.md#5-relays), [#172](https://github.com/mohanraj00/nookku/issues/172)).
29
+ - **Both forms on.** In Claude Code, `start` and `mode on` refuse a test if the nookku plugin and the project hooks are both on, as the Codex hook gate does. `init` warns if the other form is on ([SPEC.md section 7.8](SPEC.md#78-codex-hook-gate), [#151](https://github.com/mohanraj00/nookku/issues/151)).
30
+ - **Remove the project hooks.** `nookku init --remove claude-code` or `nookku init --remove codex` removes the hooks of nookku from the hook file, and keeps each other hook and key. You do not need `jq` now. It refuses while a test runs or relay mode is on. Only a person runs it: the relay denies it to a model ([remove.md](docs/how-to/remove.md#2-remove-the-project-hooks), [#163](https://github.com/mohanraj00/nookku/issues/163)).
31
+ - **Test folder for the app.** The entry gets `NOOKKU_TEST_DIR` and `NOOKKU_TEST_ID`. An app can keep its state in `app-state/` of the test folder. The seal covers it, and the evaluation reads it. The toy shop writes `app-state/answers.jsonl` ([SPEC.md section 6.1](SPEC.md#61-environment-of-the-entry), [#145](https://github.com/mohanraj00/nookku/issues/145)).
32
+ - **Check message.** The new config key `check_message` sets the one message of `nookku check`, and `init` takes `--check-message`. An app that declines the default message can now get a message that it answers ([SPEC.md section 7.1](SPEC.md#71-configuration), [#147](https://github.com/mohanraj00/nookku/issues/147)).
33
+ - **Repeated reply.** The new trace check `repeated_reply` gives one finding for each run of 2 or more consecutive turns with the same reply bytes, for example a fixed fallback text. It is a finding, not a break. The new config key `repeated_reply` sets the count, and 0 turns the check off. `init` takes `--repeated-reply`, and the manifest records the value ([SPEC.md section 8.6](SPEC.md#86-findings), [#155](https://github.com/mohanraj00/nookku/issues/155)).
34
+ - **Compact transcript.** `nookku transcript --trace --compact` shows a repeated prompt one time. After that, it shows the line, the SHA-256 and the length. An OpenTelemetry attribute with the text of a session item of the same turn also shows in this form. The new config key `transcript_compact` sets the default, and `--no-compact` overrides it. The `transcript` tool of `nookku mcp` takes `compact` ([SPEC.md section 9.2](SPEC.md#92-evaluation-prompt), [#152](https://github.com/mohanraj00/nookku/issues/152)).
35
+ - **Reply not from the model.** The new trace check `reply_not_from_model` gives a finding for each turn whose reply does not contain the text of a model output of that turn, for example a fixed decline text in place of the model text. It is a finding, not a break. The new config key `model_reply_field` names the client text in a structured model output, and `model_reply_match` is `exact`, `normalized` (the default) or `off`. `init` takes `--model-reply-field` and `--model-reply-match`, and the manifest records both values ([SPEC.md section 8.6](SPEC.md#86-findings), [#154](https://github.com/mohanraj00/nookku/issues/154)).
36
+ - **Scripted tests.** `nookku run --script <file>` sends each message of a script file to the entry, byte for byte, and ends the test. The script is JSONL with `{"said": "..."}` rows or one JSON array of strings. The test folder keeps a copy, each relay row has `"harness": "script"`, and the new break class `script_mismatch` names a turn that is not its script message. The new config key `entries` names more entries, and `--entry` takes only such a name. If the policy key `scripts` is `model`, the model can run a script with `nookku run` or with the `run_script` tool of the plugin ([SPEC.md section 7.10](SPEC.md#710-scripted-tests), [#171](https://github.com/mohanraj00/nookku/issues/171)).
37
+ - **Drive commands.** The guard denies a model command that runs `nookku start`, `end`, `hook`, `run` or `mode on|off`, or that imports the package. The new policy key `scripts` lets the model run `nookku run` ([SPEC.md section 5](SPEC.md#5-relays), [#173](https://github.com/mohanraj00/nookku/issues/173)).
38
+ - **Near-miss control prompts.** In relay mode, the relay refuses a message near a control prompt, for example `nookku stop` or `nookk end`, and sends nothing. The refusal lists the control prompts. The new policy key `control_distance` sets the edit distance, default 2 ([SPEC.md section 5](SPEC.md#5-relays), [#146](https://github.com/mohanraj00/nookku/issues/146)).
39
+ - **`init` in the state folder.** `init` refuses a root in `.nookku/`, for example a test folder, and writes nothing. It warns if a new root is not the top level of its git work tree. Its output starts with the absolute root ([docs/reference/cli.md](docs/reference/cli.md#nookku-init), [#148](https://github.com/mohanraj00/nookku/issues/148)).
40
+ - **One line for each untested version.** The transcript with the trace shows the `version_untested` findings of one harness and one version as one line, with the count of sessions. `findings.json` still has one finding for each session ([SPEC.md section 9.2](SPEC.md#92-evaluation-prompt), [#153](https://github.com/mohanraj00/nookku/issues/153)).
41
+ - **Tool events by id.** The check `otel_tool_not_in_session` looks only at the tool calls of the session of the event. It matches a Claude Code `tool_result` event to its tool call by the tool use id, if both have one. Else it compares the tool name and the input in the same turn, and a cut string of the event agrees with the start of the session string. A structured output that the model sends 2 times in one turn now gives no finding ([SPEC.md section 8.6](SPEC.md#86-findings), [#174](https://github.com/mohanraj00/nookku/issues/174)).
42
+ - **Last verbatim-relay.** The package `verbatim-relay` 0.4.0 has no dependency and does not install `nookku`. Its command prints one line with the new name and the link to the upgrade guide, and exits with 1 ([tests/test_redirect.py](tests/test_redirect.py)). It does not run `nookku`. `import verbatim_relay` gives the same message as an `ImportError`. An old project hook runs `python -m verbatim_relay hook`. It prints the same line and exits with 2, so the hook blocks the event and no prompt goes to the model. A separate workflow publishes it from a `verbatim-relay-v*` tag ([#213](https://github.com/mohanraj00/nookku/issues/213)).
43
+ - **Old kit hooks.** `nookku init` replaces the hooks that verbatim-relay wrote, so the harness runs one hook for each event ([#181](https://github.com/mohanraj00/nookku/issues/181)).
44
+
45
+ ## 0.3.1
46
+
47
+ A docs release. The docs have new how-to guides for each task of a test, a glossary, 4 diagrams and facts that match 0.3.0. The code of the relays, the taps and the audit does not change. The examples get a Node entry and an HTTP entry, and the toy HTTP server no longer looks up the host name before it listens.
48
+
49
+ - **Facts.** The docs show version 0.3.0, the real `init` output, the deny rule for reads of `.verbatim-relay`, the error texts of 0.3.0 and the missing behavior of `mode`, `end`, `check`, `transcript` and `verify` ([#126](https://github.com/mohanraj00/nookku/issues/126)).
50
+ - **Glossary.** [docs/reference/glossary.md](docs/reference/glossary.md) defines 20 terms, and each term links to its section of SPEC.md ([#127](https://github.com/mohanraj00/nookku/issues/127)).
51
+ - **Choose a relay.** [docs/how-to/choose-a-relay.md](docs/how-to/choose-a-relay.md) compares the plugin and the hook kit, with a decision flow. The Claude Code guide is now 2 guides, one for each relay ([#128](https://github.com/mohanraj00/nookku/issues/128)).
52
+ - **Test your own app.** [docs/how-to/test-your-app.md](docs/how-to/test-your-app.md) takes your app from the install to the results, with the expected output at each step. The docs give `!verbatim-relay setup` first, so the harness runs the command ([#129](https://github.com/mohanraj00/nookku/issues/129), [#125](https://github.com/mohanraj00/nookku/issues/125)).
53
+ - **Read the results.** [docs/how-to/read-the-results.md](docs/how-to/read-the-results.md) reads the seal, the audit, the findings, the report and the transcript in order, with a table of the 7 break classes and the 12 trace checks ([#130](https://github.com/mohanraj00/nookku/issues/130)).
54
+ - **What check proves.** The docs say that a PASS of `check` proves the connection, not the reply, and give the steps to make sure that `check` runs your real app ([#131](https://github.com/mohanraj00/nookku/issues/131)).
55
+ - **Other agents.** An entry in Node ([examples/toy-shop-node/entry.mjs](examples/toy-shop-node/entry.mjs)), an entry for an HTTP server ([examples/toy-shop/http_entry.py](examples/toy-shop/http_entry.py)), a table that compares the entry with the HTTP tap, and [a guide for a streaming agent](docs/how-to/test-a-streaming-agent.md) ([#132](https://github.com/mohanraj00/nookku/issues/132)).
56
+ - **Stuck tests, upgrades and removal.** [Recover a stuck test](docs/how-to/recover-a-stuck-test.md), [upgrade](docs/how-to/upgrade.md) and [remove](docs/how-to/remove.md) verbatim-relay ([#133](https://github.com/mohanraj00/nookku/issues/133)).
57
+ - **Diagrams.** [docs/architecture.md](docs/architecture.md) has a corrected data-flow diagram, and new diagrams of one turn, the test lifecycle and the trace, with a table of the timeouts. Tests check the diagrams against the records page and the constants ([#134](https://github.com/mohanraj00/nookku/issues/134)).
58
+ - **Navigation.** The README gives a route to try the toy shop, a route to connect your own app and a route to choose a relay, and a Docs table in task order. The docs map groups the guides by task. Troubleshooting starts with a table of symptoms ([#135](https://github.com/mohanraj00/nookku/issues/135)).
59
+
60
+ ## 0.3.0
61
+
62
+ Streamed replies, and the fixes of the 0.2 code review. An agent can now stream its reply, and the relays still show and record it byte for byte. Each relay path fails closed: if a hook or a guard fails, the prompt does not reach the model, and the tester sees the cause and the next step. Each record has one reader with one rule in Python and in the plugin. Both taps have one deadline, and the proxies keep no secret query value. The docs have a tutorial, how-to guides, reference pages and an architecture page. [The proofs](docs/results.md) pass in the plugin, the hook kit in Claude Code and the hook kit in Codex.
63
+
64
+ **Upgrade.** End each running test before you upgrade. `current.json` now needs `pid_start` ([#44](https://github.com/mohanraj00/nookku/issues/44)), so 0.3.0 treats a test that 0.2.0 started as not running.
65
+
66
+ - **Streamed replies.** If the agent answers with an SSE stream (`text/event-stream`), the tap sends each part to the relay when it comes, and records the complete reply when the stream ends. The relay shows the reply when the stream is complete. A stream that ends early, sends an error or has a malformed chunk gives an error, not a part of the reply. The option `openai_stream` (`--openai-stream` in the hook kit) makes both relays send `"stream": true`, for an agent that streams only on request. [SPEC.md section 4.1](SPEC.md#41-http-mode) defines the rules ([#1](https://github.com/mohanraj00/nookku/issues/1), [#66](https://github.com/mohanraj00/nookku/issues/66)).
67
+ - **Record format v0.3.** The row of a failed stream (a 2xx status with `reply: null`) has version `0.3`. Each other row keeps `0.2`, so a 0.2.0 reader still reads it, and refuses a 0.3 row with a message that names the version. Readers accept `0.1`, `0.2` and `0.3` ([SPEC.md section 2](SPEC.md#2-record-format), [#66](https://github.com/mohanraj00/nookku/issues/66)).
68
+ - **Stream errors.** If the tap cannot write the row of a stream, it sends no second status and writes no second row. With a `Content-Length`, it holds the last byte until the row is in the record, so the caller sees an incomplete response. The model API proxy and the tap read SSE with one strict parser ([#66](https://github.com/mohanraj00/nookku/issues/66)).
69
+ - **Fail closed in the plugin.** Each gating hook of the plugin has a `.catch` handler. If a hook fails or runs past its time budget, the handler blocks the prompt or denies the tool call, and it makes no file or state call that can stall again ([#63](https://github.com/mohanraj00/nookku/issues/63)).
70
+ - **Fail closed in the hook kit.** A PreToolUse deny with a broken config, or with an error in the guard, still denies the call in relay mode or during a test ([#68](https://github.com/mohanraj00/nookku/issues/68)).
71
+ - **Stale test.** If the plugin cannot reach the tap of `current.json`, it asks `verbatim-relay status`. If no test runs, it shows "the test stopped, and no test runs" and the next step. The turn stays in the record with `ok: false`, because the prompt can have reached the tap ([#64](https://github.com/mohanraj00/nookku/issues/64)).
72
+ - **Bridge identity.** `current.json` has `pid_start`, the start time of the bridge process. A test whose pid now belongs to another process is not running, and `end` sends no signal to that process ([#44](https://github.com/mohanraj00/nookku/issues/44)).
73
+ - **One reader.** Each part reads a record with `record.read_rows`, and the plugin reads the relay record with `relayTurns` and the same rule. A bad line stops the reader with an error that names the file and the line. The transcript of an invalid record shows no turn. The shared table `RELAY_LINES` checks the 2 readers against the conformance cases. If `relay.jsonl` is invalid at the end of a test, the bridge infers no Codex session ([#71](https://github.com/mohanraj00/nookku/issues/71)).
74
+ - **One contract reader.** `contract.parse_reply` and the plugin refuse a line with both `reply` and `error`, and `NaN` or `Infinity`. The shared table `CONTRACT_LINES` checks both readers against the contract cases ([#45](https://github.com/mohanraj00/nookku/issues/45)).
75
+ - **One config rule.** `start`, `check`, `init` and the hook kit read `.verbatim-relay/config.json` with one reader. An unknown key stops each of them with the same error. Before, `start` accepted it, and then the hook kit blocked each prompt. A second `init` keeps each key of the file, for example `backends` and `"evaluate": false`, and changes only the keys of its flags. It prints the changed and the kept keys ([SPEC.md section 7.1](SPEC.md#71-configuration), [#89](https://github.com/mohanraj00/nookku/issues/89)).
76
+ - **Lone surrogates.** A row with a lone surrogate is invalid (`record_invalid`), not a crash. The relays refuse a prompt with a lone surrogate and say why. The trace, the OTLP receiver and the proxies write a lone surrogate as its escape text, so a write never fails ([#43](https://github.com/mohanraj00/nookku/issues/43), [#65](https://github.com/mohanraj00/nookku/issues/65)).
77
+ - **Stray lines in stdio mode.** The stdio tap reads lines until it gets the line for the request id. A log line on stdout is a stray line with its own `unparsed` row, not a 502. A timeout after stray lines names them and gives the fix. `serve()` sends the output that the entry printed before it to stderr ([#62](https://github.com/mohanraj00/nookku/issues/62), [#46](https://github.com/mohanraj00/nookku/issues/46)).
78
+ - **Check gate.** `verbatim-relay check` reads the audit of its own test. If the audit exit is not 0, the check fails, with one FAIL line and its fix for each error and each break. If `audit.json` is missing or not valid, the check fails. A line that the entry writes on stdout after its last reply is a stray line too ([SPEC.md section 7.1](SPEC.md#71-configuration), [section 4.2](SPEC.md#42-stdio-mode), [#90](https://github.com/mohanraj00/nookku/issues/90)).
79
+ - **Blocked-call detail.** Both relays cut the `detail` of a `blocked_call` row at 300 code points, so a cut never splits a surrogate pair and the relay record stays valid. The shared table `DETAIL_CASES` checks both relays ([SPEC.md section 2.2](SPEC.md#22-relay-record), [#88](https://github.com/mohanraj00/nookku/issues/88)).
80
+ - **Record errors in the view.** In follow mode, `view` writes an error for an invalid relay record to stderr, and shows the next turns when the record is valid again. `view --no-follow` writes the error and exits with 2 ([docs/reference/cli.md](docs/reference/cli.md), [#92](https://github.com/mohanraj00/nookku/issues/92)).
81
+ - **Start and status texts.** The start text of both relays names the prompt `verbatim-relay end`, which ends the test and starts the evaluation, and the end with no evaluation. The plugin status asks `verbatim-relay status --json`, so a stale `current.json` does not show as a running test. `--help` does not show the internal `bridge` command ([SPEC.md section 5](SPEC.md#5-relays), [#91](https://github.com/mohanraj00/nookku/issues/91)).
82
+ - **One deadline.** Both taps wait [240 seconds](src/nookku/stdio.py) for the agent, as one deadline for the connection, the headers and the body, also for a stream. Each timeout of the relay path ends before the next one, and [one test](tests/test_timeouts.py) checks the order ([SPEC.md section 4.3](SPEC.md#43-timeouts), [#67](https://github.com/mohanraj00/nookku/issues/67)).
83
+ - **Deny.** Both relays deny a model command that writes to `/dev/tcp` or `/dev/udp` paths of the tap or the agent, also with leading zeros in the port. The shared table `DENY_CASES` checks both deny patterns ([#70](https://github.com/mohanraj00/nookku/issues/70)).
84
+ - **No secret query values.** The backend and model API proxies remove the values of secret query parameters from the record, and forward them with no change ([#69](https://github.com/mohanraj00/nookku/issues/69)).
85
+ - **Transcript.** The plugin and the hook kit give the model one rendered transcript, with a legend for `ok` and for a relay error, and with no hashes ([SPEC.md section 5](SPEC.md#5-relays), [#10](https://github.com/mohanraj00/nookku/issues/10)).
86
+ - **OpenAI Responses and Decisions APIs.** The model API proxy reads the result of `/responses` calls, also streamed, and of `/decisions` calls. The trace and the evaluation view show them ([SPEC.md section 7.7](SPEC.md#77-model-api-proxies), [#33](https://github.com/mohanraj00/nookku/issues/33), [#40](https://github.com/mohanraj00/nookku/issues/40)).
87
+ - **Isolated Agent SDK session.** The toy apps start their Agent SDK session with `setting_sources=[]`, `strict_mcp_config=True` and no plugin folders. The new trace check `server_not_from_app` names an MCP server that the app's configuration cannot give ([#28](https://github.com/mohanraj00/nookku/issues/28)).
88
+ - **Docs.** A one-screen README, a docs map, a tutorial ([docs/getting-started.md](docs/getting-started.md)), how-to guides, reference pages for the CLI, the config and the records, an architecture page, troubleshooting and a FAQ. A code of conduct (Contributor Covenant 2.1), issue and PR templates, and a code quality spec ([docs/code-quality.md](docs/code-quality.md)). Tests check each relative link, the README counts, and the CLI and config pages against the code ([#72](https://github.com/mohanraj00/nookku/issues/72), [#73](https://github.com/mohanraj00/nookku/issues/73)).
89
+ - **Claims.** The README marks the prompt-only examples as single observations, and the benchmark text says that each turn was a new harness call ([#9](https://github.com/mohanraj00/nookku/issues/9), [#8](https://github.com/mohanraj00/nookku/issues/8)).
90
+ - **CI.** GitHub Actions are pinned to commit SHAs ([#4](https://github.com/mohanraj00/nookku/issues/4)).
91
+ - **Counts.** 53 audit cases in [conformance/cases/](conformance/cases/), 20 contract cases in [conformance/contract/](conformance/contract/), 10 trace cases in [conformance/trace/](conformance/trace/), 11 seal cases in [conformance/seal/](conformance/seal/) and 7 receiver cases in [conformance/otlp/](conformance/otlp/) ([cases](conformance/build.py)). The trace has [12 checks](src/nookku/trace.py).
92
+
93
+ ## 0.2.0
94
+
95
+ The telemetry MVP ([#27](https://github.com/mohanraj00/nookku/issues/27)). For each turn of a test, the record shows each action of the app that can change the reply or the state: its model sessions, its OpenTelemetry spans and logs, its backend calls and its direct model calls. Each action has its turn and its evidence line. The seal shows a changed record, and the evaluation at the end of a test cites these items. [The full telemetry proof](docs/results.md#full-telemetry-with-one-app) passes in the plugin, the hook kit in Claude Code and the hook kit in Codex.
96
+
97
+ - **Tests.** The harness starts the app. `verbatim-relay start` (or `/verbatim-relay start` in the plugin) starts an entry through the tap and switches relay mode on. `verbatim-relay end` stops it. The agent needs no HTTP server and no extra terminal. Each test has a folder in `.verbatim-relay/tests/` with both records, `app.log` and a manifest.
98
+ - **Agent contract v1.** One JSON line in and one JSON line out on stdin and stdout: a message, the history and a session in; a reply or an error out. `verbatim_relay.agent.serve(reply)` speaks it for a Python function. The tap's `--cmd` mode starts the agent and speaks it.
99
+ - **Model sessions.** The tap finds the app's own Claude Code sessions by their process, and its Codex sessions by their folder and time. At the end, it copies their session files into the test folder.
100
+ - **Trace.** At the end of a test, the bridge reads the copied session files into `trace.jsonl`: each message, tool call and command of the app's model sessions, with its result, its turn and its line in the session file. 11 checks write `findings.json`, with the checks of the later entries below. `verbatim-relay trace` builds both again. [SPEC.md section 8](SPEC.md#8-trace) defines them, and 7 conformance cases in [conformance/trace/](conformance/trace/) test them ([cases](conformance/build.py), [test](tests/test_trace.py)).
101
+ - **Evaluation.** The prompt `verbatim-relay end` ends the test and gives the harness model the evaluation prompt, in the plugin and in the hook kit. The model reads the transcript with the trace (`verbatim-relay transcript --trace`), the findings and the audit, checks the app, and writes `report.md` in the test folder. `"evaluate": false` in the configuration stops it. After a test, the relays deny model writes to a test folder, except `report.md`. [SPEC.md section 9](SPEC.md#9-evaluation) defines it. [Proofs P5 and P6](docs/results.md#p5-and-p6-the-evaluation-at-the-end-of-a-test) pass with the plugin and the hook kit in Claude Code, and with the hook kit in Codex: the report finds a planted business-rule bug.
102
+ - **Deny of the entry and the records.** During a test, both relays deny a model command that runs the entry, for example `python entry.py`. After a test, a model command that names `.verbatim-relay` can only read, or write `report.md`. A list of read programs in [SPEC.md section 5](SPEC.md#5-relays) defines "only read". Each other command and each tool that is not a shell is denied ([#20](https://github.com/mohanraj00/nookku/issues/20)).
103
+ - **Seal.** At the end of a test, the bridge writes the SHA-256 of each file of the test folder to `seal.json`, and a copy to `~/.verbatim-relay/seals/`. `verbatim-relay verify` shows each file that changed after the end, and exits with 2 if the seal is broken. `transcript --trace` shows the result in its first line. `verbatim-relay trace` rebuilds the trace only from sources that agree with the seal. Denies after a test go to `denied.jsonl`. [SPEC.md section 7.4](SPEC.md#74-seal) defines the seal, and 11 conformance cases in [conformance/seal/](conformance/seal/) test it ([#21](https://github.com/mohanraj00/nookku/issues/21)).
104
+ - **OpenTelemetry.** During a test, the bridge runs an OTLP/HTTP receiver and gives the entry its address in the `OTEL_*` variables. It takes JSON and protobuf (with a decoder that uses only the standard library), also with gzip, and writes `otel.jsonl`. It drops metrics and the spans of the harnesses, keeps the prompt, tool and reply events of the harnesses, and removes personal attributes. The trace reads `otel.jsonl` as `span` and `log` items (trace rows `0.3`, with the new field `service`), with 2 new checks: `span_error`, and `otel_tool_not_in_session`, which compares the tool events of the harness with its session file. `"otel": false` stops it. [SPEC.md section 7.5](SPEC.md#75-otlp-receiver) defines it. 6 receiver cases in [conformance/otlp/](conformance/otlp/) and 1 trace case test it ([#23](https://github.com/mohanraj00/nookku/issues/23)).
105
+ - **Backend calls.** The config key `backends` lists the HTTP services of the app. During a test, the bridge runs a recording proxy for each one, and gives the entry the proxy URL in the backend's environment variable. The proxy forwards each byte, also to an HTTPS backend, and writes `backend.jsonl` without the values of secret headers. The trace reads it as `http` items, with the new check `backend_error`. [SPEC.md section 7.6](SPEC.md#76-backend-proxies) defines it, the trace case `backend_toy_shop` tests it, and [proofs/backend/](proofs/backend/results.json) shows 3 calls with the same bytes at the entry, the service and the record ([#24](https://github.com/mohanraj00/nookku/issues/24)).
106
+ - **Direct model calls.** During a test, the bridge runs a recording proxy for the Anthropic and the OpenAI API, and gives the entry its URL in `ANTHROPIC_BASE_URL` and `OPENAI_BASE_URL`. The proxy sends each part of a streamed (SSE) response to the app when it comes, and writes `model_api.jsonl` with the text, the tool calls and the stop reason of each call. It removes the API key from the record. It keeps no text of a call from a harness, for example the Agent SDK, because that call holds the harness's own instructions. The trace reads the other calls as `message` and `tool_call` items, with the new check `model_api_error`. `"model_api": false` stops it. [SPEC.md section 7.7](SPEC.md#77-model-api-proxies) defines it, the trace case `model_api_toy_shop` tests it, and [proofs/model-api/](proofs/model-api/results.json) shows 3 calls with the same bytes at the entry, the toy API and the record, and 2 streams that reached the entry before their end ([#25](https://github.com/mohanraj00/nookku/issues/25)).
107
+ - **Example.** `examples/toy-shop-models/` is a toy shop with a Claude Agent SDK session, 2 tools and a planted bug.
108
+ - **Full example.** `examples/toy-shop-full/` is a toy shop with 3 parts: a Claude Agent SDK session with 3 tools, a stock service over HTTP, and a direct call to a case-note model with the OpenAI Chat Completions API and a stream. Its planted bug shows only in the backend calls. `toy_model.py` is a toy note model that needs no API key.
109
+ - **Full telemetry proof.** `scripts/proof_telemetry.py` runs a test of `examples/toy-shop-full/` in each relay. Each turn has items from the Agent SDK session file, the backend proxy and the model API proxy, and each report cites the 2 backend calls of the planted bug ([results](docs/results.md#full-telemetry-with-one-app), [#26](https://github.com/mohanraj00/nookku/issues/26)).
110
+ - **Agent SDK pin.** The proof scripts take the Agent SDK version from one pin in `scripts/proof_common.py`, now 0.2.164. The trace readers now also cover Claude Code 2.1.292, which this SDK bundles ([proofs/trace/](proofs/trace/results.json), [#35](https://github.com/mohanraj00/nookku/issues/35)). The proof scripts split model output on `\n` only ([#31](https://github.com/mohanraj00/nookku/issues/31)).
111
+ - **Model API URLs in the config.** `model_api` can also be an object from an API name to its upstream URL, for example when the tester's harness reads the same variable ([SPEC.md section 7.7](SPEC.md#77-model-api-proxies)).
112
+ - **Setup.** `verbatim-relay setup` prints the guide that a harness model follows to write the entry for an app. `verbatim-relay check` runs a test with one message and checks the reply and the model sessions. The plugin has a `setup` skill.
113
+ - **Hook kit.** The prompts `verbatim-relay start`, `verbatim-relay end` and `verbatim-relay status` control a test from inside Codex or Claude Code. During a test, both relays deny model changes to `.verbatim-relay/`.
114
+ - **Record format v0.2.** The `exchange` row gets `started`. The tap record gets the `model_session` row. The audit reads v0.1 and v0.2 rows and counts the model sessions. The matching does not change.
115
+ - **Fix.** The hook kit read the relay record with `str.splitlines()`, which also splits on U+2028. After a tester message with that character, each later message failed closed. The kit now splits on `\n` only.
116
+ - **Examples.** The toy shop agent speaks the agent contract. The HTTP version is `examples/toy-shop/http_agent.py`.
117
+ - **Docs.** A worked evaluation of the toy shop agent, with what the model found and what it got wrong: `docs/evaluation-example.md`.
118
+
119
+ ## 0.1.0
120
+
121
+ The first release.
122
+
123
+ - **Relays.** A Claude Code plugin (function hooks) shows each reply in the chat. A hook kit for Codex and Claude Code (classic hooks) shows each reply in `verbatim-relay view`. In relay mode, the model does not run.
124
+ - **Transcript.** After the test, the model reads the exact conversation: the plugin's `transcript` tool, or `verbatim-relay transcript`.
125
+ - **Tap.** `verbatim-relay tap` records what the agent received and sent. Adapters: a JSON body with configurable field paths, and OpenAI-compatible chat completions.
126
+ - **Audit.** `verbatim-relay audit` compares the two records and reports 7 break classes. It exits 0, 1 or 2, and it fails closed.
127
+ - **Spec and evidence.** Record format v0.1 in SPEC.md with 33 conformance cases. Proofs P1 to P5 on Claude Code 2.1.288 and Codex 0.160.0, and a pre-registered benchmark: 0 breaks in 1,000 turns.
nookku-0.4.0/LICENSE ADDED
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
nookku-0.4.0/PKG-INFO ADDED
@@ -0,0 +1,152 @@
1
+ Metadata-Version: 2.5
2
+ Name: nookku
3
+ Version: 0.4.0
4
+ Summary: A test harness for developers of agent apps. Test your agent through Claude Code or Codex, byte for byte, and audit the record.
5
+ Project-URL: Repository, https://github.com/mohanraj00/nookku
6
+ Project-URL: Documentation, https://github.com/mohanraj00/nookku/blob/main/docs/index.md
7
+ Project-URL: Specification, https://github.com/mohanraj00/nookku/blob/main/SPEC.md
8
+ Project-URL: Changelog, https://github.com/mohanraj00/nookku/blob/main/CHANGELOG.md
9
+ Project-URL: Issues, https://github.com/mohanraj00/nookku/issues
10
+ Author: Mohan Raj
11
+ License-Expression: Apache-2.0
12
+ License-File: LICENSE
13
+ Keywords: agents,audit,claude-code,codex,llm,testing
14
+ Classifier: Development Status :: 2 - Pre-Alpha
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Software Development :: Testing
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.10
26
+ Description-Content-Type: text/markdown
27
+
28
+ <picture>
29
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/mohanraj00/nookku/main/docs/assets/logo/nookku-wordmark-dark.svg">
30
+ <img src="https://raw.githubusercontent.com/mohanraj00/nookku/main/docs/assets/logo/nookku-wordmark.svg" alt="Nookku" width="332">
31
+ </picture>
32
+
33
+ # Nookku
34
+
35
+ (நோக்கு - to observe)
36
+
37
+ A test harness for developers of agent apps.
38
+
39
+ [![CI](https://github.com/mohanraj00/nookku/actions/workflows/ci.yml/badge.svg)](https://github.com/mohanraj00/nookku/actions/workflows/ci.yml)
40
+ [![PyPI](https://img.shields.io/pypi/v/nookku)](https://pypi.org/project/nookku/)
41
+ [![Python versions](https://img.shields.io/pypi/pyversions/nookku)](https://pypi.org/project/nookku/)
42
+ [![License](https://img.shields.io/github/license/mohanraj00/nookku)](https://github.com/mohanraj00/nookku/blob/main/LICENSE)
43
+
44
+ **Test your chat agent through Claude Code or Codex. The [harness](https://github.com/mohanraj00/nookku/blob/main/docs/reference/glossary.md#harness) model does not retype one message or one reply.**
45
+
46
+ Nookku is a test harness for developers of agent apps. You talk to your agent in the coding harness where you already work. The [relay](https://github.com/mohanraj00/nookku/blob/main/docs/reference/glossary.md#relay) sends each message to your agent byte for byte, and shows each reply byte for byte. The model does not run while you talk. At the end, the model reads the exact record and evaluates your agent: business logic, tone, accuracy.
47
+
48
+ It adapts to your app through a thin [entry](https://github.com/mohanraj00/nookku/blob/main/docs/reference/glossary.md#entry) in `.nookku/`, and your app's code does not change. The cost is plumbing: you write the entry once, and you change it when the start or the wiring of your app changes.
49
+
50
+ ## How it works
51
+
52
+ ```text
53
+ tester ──> harness ──> relay ──────> tap ──stdin/stdout──> entry ──> your app
54
+ │ │
55
+ ▼ ▼
56
+ relay.jsonl tap.jsonl
57
+ (what you typed (what the agent
58
+ and saw) received and sent)
59
+ │ │
60
+ └─> audit <──┘ exit 0 clean, 1 break, 2 invalid record
61
+ ```
62
+
63
+ - [Harness](https://github.com/mohanraj00/nookku/blob/main/docs/reference/glossary.md#harness): Claude Code or Codex, where you type your test messages.
64
+ - [Relay](https://github.com/mohanraj00/nookku/blob/main/docs/reference/glossary.md#relay): the command `nookku hook`, which the plugin or the project hooks run in the harness. It carries each message and each reply, and the model writes neither.
65
+ - [Tap](https://github.com/mohanraj00/nookku/blob/main/docs/reference/glossary.md#tap): a proxy in front of your agent. It forwards each byte with no change, and records what the agent received and sent.
66
+ - [Entry](https://github.com/mohanraj00/nookku/blob/main/docs/reference/glossary.md#entry): a thin wrapper that starts your app and speaks one JSON line in and one JSON line out.
67
+ - [Audit](https://github.com/mohanraj00/nookku/blob/main/docs/reference/glossary.md#audit): a program that compares the two records byte for byte, and names each break.
68
+
69
+ [docs/architecture.md](https://github.com/mohanraj00/nookku/blob/main/docs/architecture.md#data-flow) shows this flow with each part, and has diagrams of one turn, the test lifecycle and the trace.
70
+
71
+ Two processes write two records, and the audit compares them byte for byte. It reports 8 break classes ([SPEC.md section 3.3](https://github.com/mohanraj00/nookku/blob/main/SPEC.md#33-break-classes)). It fails closed: it never reports clean on a record that it cannot read. 62 audit cases, 20 contract cases, 18 trace cases, 11 seal cases and 7 receiver cases in [conformance/](https://github.com/mohanraj00/nookku/blob/main/conformance/) test the spec ([cases](https://github.com/mohanraj00/nookku/blob/main/conformance/build.py), [tests](https://github.com/mohanraj00/nookku/blob/main/tests/)).
72
+
73
+ A test also records what your app did. It copies the session files of the app's own Agent SDK or Codex sessions. It records the backend calls, the direct model calls and the OpenTelemetry spans of the app. [docs/architecture.md](https://github.com/mohanraj00/nookku/blob/main/docs/architecture.md) shows each part.
74
+
75
+ ## Install
76
+
77
+ ```bash
78
+ uv tool install nookku
79
+ ```
80
+
81
+ It needs Python 3.10 or later, and it has no runtime dependencies ([pyproject.toml](https://github.com/mohanraj00/nookku/blob/main/pyproject.toml)). The docs are for version 0.4.0. If you use verbatim-relay 0.3.x or earlier, do the [0.4.0 steps of the upgrade guide](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/upgrade.md#040), because the package has a new name ([CHANGELOG.md](https://github.com/mohanraj00/nookku/blob/main/CHANGELOG.md#040)). To upgrade from a later version of nookku, end each running test first. Then run `uv tool upgrade nookku`. [docs/how-to/upgrade.md](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/upgrade.md) gives each step.
82
+
83
+ ## Quick start
84
+
85
+ Select one route: try the toy shop, connect your app, or choose a relay.
86
+
87
+ ### Try the toy shop
88
+
89
+ In a clone of this repo, with the toy shop agent and the project hooks in Claude Code:
90
+
91
+ ```bash
92
+ nookku init claude-code --entry "python3 examples/toy-shop/agent.py"
93
+ nookku check # one message through the entry: PASS proves the connection, not the reply
94
+ nookku view # in a second terminal: each reply shows here
95
+ ```
96
+
97
+ In Claude Code, type the prompt `nookku start`, then your test messages, then `nookku end`. The end of the test writes `audit.json` in the [test folder](https://github.com/mohanraj00/nookku/blob/main/docs/reference/glossary.md#test-folder) `.nookku/tests/<test-id>/`. Then the model evaluates the test and writes `report.md`. [docs/getting-started.md](https://github.com/mohanraj00/nookku/blob/main/docs/getting-started.md) shows each step with its real output.
98
+
99
+ Optional: to see the audit again, run it by hand:
100
+
101
+ ```bash
102
+ nookku audit --tap .nookku/tests/<test-id>/tap.jsonl --relay .nookku/tests/<test-id>/relay.jsonl
103
+ ```
104
+
105
+ ### Connect your app
106
+
107
+ In the harness, in the project folder of your app, type `!nookku setup`. Then type the prompt "Follow the Nookku setup guide, and connect a test to this app." [docs/how-to/test-your-app.md](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/test-your-app.md) gives each step from the install to the results, with the expected output. To write the entry yourself, read [docs/how-to/connect-your-agent.md](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/connect-your-agent.md).
108
+
109
+ ### Choose a relay
110
+
111
+ You install the [relay](https://github.com/mohanraj00/nookku/blob/main/SPEC.md#5-relays) as the plugin or as the project hooks. Both work in Claude Code and in Codex, with the same rules. Both show each reply as the reason of a blocked prompt, and in `nookku view`. [docs/how-to/choose-a-relay.md](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/choose-a-relay.md) compares them. Then read the guide of your setup: [Claude Code plugin](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/claude-code-plugin.md), [Claude Code project hooks](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/claude-code-hook-kit.md) or [Codex](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/codex.md).
112
+
113
+ ## Results
114
+
115
+ | Proof | Plugin, Claude Code 2.1.296 | Plugin, Codex 0.162.1 | Project hooks, Claude Code 2.1.296 | Project hooks, Codex 0.162.1 |
116
+ |---|---|---|---|---|
117
+ | Messages reach the agent byte for byte | 10/10 | 10/10 | 10/10 | 10/10 |
118
+ | Replies reach the tester byte for byte | 10/10 | 10/10 | 10/10 | 10/10 |
119
+ | Same, with a system prompt that tells the model to rewrite both | 5/5 | 5/5 | 5/5 | 5/5 |
120
+ | Model call to the agent denied, agent receives nothing | yes | yes | yes | yes |
121
+ | Audit finds planted faults | 5/5 | 5/5 | 5/5 | 5/5 |
122
+ | After the test, the model has no memory of the conversation, and reads it from the transcript | yes | yes | yes | yes |
123
+
124
+ Data: [plugin in Claude Code](https://github.com/mohanraj00/nookku/blob/main/proofs/plugin-claude-code/results.json), [plugin in Codex](https://github.com/mohanraj00/nookku/blob/main/proofs/plugin-codex/results.json), [project hooks in Claude Code](https://github.com/mohanraj00/nookku/blob/main/proofs/hooks-claude-code/results.json), [project hooks in Codex](https://github.com/mohanraj00/nookku/blob/main/proofs/hooks-codex/results.json), [evaluation](https://github.com/mohanraj00/nookku/blob/main/docs/results.md#p5-the-model-judges-the-record-not-its-memory). Method: [docs/results.md](https://github.com/mohanraj00/nookku/blob/main/docs/results.md#1-proofs).
125
+
126
+ Under pressure, the mechanism had **0 breaks in 1,000 turns**. The test had 40 scripted conversations in each harness, 5 or 20 turns long. They had refusals, HTTP 500 errors, questions back to the tester and ambiguous messages. Each turn was a new harness call. I registered the design before the first run. Method, data and the one deviation: [docs/results.md](https://github.com/mohanraj00/nookku/blob/main/docs/results.md#2-benchmark-under-pressure).
127
+
128
+ ## Docs
129
+
130
+ The how-to rows are in the order of the tasks of a test: choose, connect, run, read the results, fix. The row after them has the tasks that maintain Nookku.
131
+
132
+ | Kind | Pages |
133
+ |---|---|
134
+ | Tutorial | [Get started](https://github.com/mohanraj00/nookku/blob/main/docs/getting-started.md) |
135
+ | How-to: choose | [Choose a relay](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/choose-a-relay.md) |
136
+ | How-to: connect your app | [Test your own app](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/test-your-app.md), [Connect your agent](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/connect-your-agent.md), [HTTP tap](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/http-tap.md), [Test a streaming agent](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/test-a-streaming-agent.md), [Isolate an Agent SDK session](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/isolate-agent-sdk.md), [Add a backend](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/add-a-backend.md), [Model calls and OpenTelemetry](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/record-model-calls.md) |
137
+ | How-to: run a test | [Claude Code plugin](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/claude-code-plugin.md), [Claude Code project hooks](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/claude-code-hook-kit.md), [Codex](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/codex.md) |
138
+ | How-to: read the results | [Read the results of a test](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/read-the-results.md) |
139
+ | How-to: fix | [Troubleshooting](https://github.com/mohanraj00/nookku/blob/main/docs/troubleshooting.md), [Recover a stuck test](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/recover-a-stuck-test.md) |
140
+ | How-to: maintain | [Upgrade](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/upgrade.md), [Remove](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/remove.md), [Run the proofs](https://github.com/mohanraj00/nookku/blob/main/docs/how-to/run-the-proofs.md) |
141
+ | Reference | [CLI](https://github.com/mohanraj00/nookku/blob/main/docs/reference/cli.md), [Configuration](https://github.com/mohanraj00/nookku/blob/main/docs/reference/config.md), [Records](https://github.com/mohanraj00/nookku/blob/main/docs/reference/records.md), [Glossary](https://github.com/mohanraj00/nookku/blob/main/docs/reference/glossary.md), [SPEC.md](https://github.com/mohanraj00/nookku/blob/main/SPEC.md), [Results](https://github.com/mohanraj00/nookku/blob/main/docs/results.md) |
142
+ | Explanation | [Architecture](https://github.com/mohanraj00/nookku/blob/main/docs/architecture.md), [Limits](https://github.com/mohanraj00/nookku/blob/main/docs/limits.md), [FAQ](https://github.com/mohanraj00/nookku/blob/main/docs/faq.md), [Worked evaluations](https://github.com/mohanraj00/nookku/blob/main/docs/evaluation-example.md) |
143
+
144
+ The full map is [docs/index.md](https://github.com/mohanraj00/nookku/blob/main/docs/index.md). Read [docs/limits.md](https://github.com/mohanraj00/nookku/blob/main/docs/limits.md) before you trust a result: the deny is best effort, and the entry is not audited.
145
+
146
+ ## Contribute
147
+
148
+ Read [CONTRIBUTING.md](https://github.com/mohanraj00/nookku/blob/main/CONTRIBUTING.md) and the [code of conduct](https://github.com/mohanraj00/nookku/blob/main/CODE_OF_CONDUCT.md). Report a security problem as [SECURITY.md](https://github.com/mohanraj00/nookku/blob/main/SECURITY.md) says.
149
+
150
+ ## License
151
+
152
+ Apache-2.0. See [LICENSE](https://github.com/mohanraj00/nookku/blob/main/LICENSE).