seif-cli 0.6.2__tar.gz → 0.7.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 (320) hide show
  1. seif_cli-0.7.0/LICENSE +34 -0
  2. {seif_cli-0.6.2/src/seif_cli.egg-info → seif_cli-0.7.0}/PKG-INFO +4 -4
  3. {seif_cli-0.6.2 → seif_cli-0.7.0}/README.md +1 -1
  4. {seif_cli-0.6.2 → seif_cli-0.7.0}/pyproject.toml +3 -3
  5. seif_cli-0.7.0/src/seif/__init__.py +1 -0
  6. seif_cli-0.7.0/src/seif/amend/__init__.py +9 -0
  7. seif_cli-0.7.0/src/seif/amend/amend.py +186 -0
  8. seif_cli-0.7.0/src/seif/amend/seed_create.py +199 -0
  9. seif_cli-0.7.0/src/seif/analysis/__init__.py +1 -0
  10. seif_cli-0.7.0/src/seif/audit/__init__.py +7 -0
  11. seif_cli-0.7.0/src/seif/audit/discipline.py +189 -0
  12. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/bridge/telegram_bot.py +1 -1
  13. seif_cli-0.7.0/src/seif/claims/__init__.py +72 -0
  14. seif_cli-0.7.0/src/seif/claims/broadcast.py +106 -0
  15. seif_cli-0.7.0/src/seif/claims/cmd_check.py +92 -0
  16. seif_cli-0.7.0/src/seif/claims/cmd_lifecycle.py +121 -0
  17. seif_cli-0.7.0/src/seif/claims/cmd_sweep.py +39 -0
  18. seif_cli-0.7.0/src/seif/claims/cmd_validate.py +41 -0
  19. seif_cli-0.7.0/src/seif/claims/conflicts.py +133 -0
  20. seif_cli-0.7.0/src/seif/claims/lifecycle.py +290 -0
  21. seif_cli-0.7.0/src/seif/claims/schema.py +223 -0
  22. seif_cli-0.7.0/src/seif/claims/sweep.py +124 -0
  23. seif_cli-0.7.0/src/seif/claims/telemetry.py +100 -0
  24. seif_cli-0.7.0/src/seif/claims/workspace.py +161 -0
  25. seif_cli-0.7.0/src/seif/cli/__init__.py +1 -0
  26. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/cli/circuit_setup.py +25 -4
  27. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/cli/cli.py +1607 -37
  28. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/cli/confirm_action.py +124 -8
  29. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/cli/setup.py +250 -4
  30. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/cli/wrapper.py +75 -12
  31. seif_cli-0.7.0/src/seif/context/__init__.py +1 -0
  32. seif_cli-0.7.0/src/seif/context/classifier_reasoning.py +75 -0
  33. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/context_bridge.py +2 -2
  34. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/cycle.py +250 -0
  35. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/registry.py +115 -2
  36. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/workspace.py +38 -1
  37. seif_cli-0.7.0/src/seif/core/__init__.py +1 -0
  38. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/core/resonance_signal.py +6 -5
  39. seif_cli-0.7.0/src/seif/core/sign_host_install_config.py +205 -0
  40. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/core/signing.py +97 -15
  41. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/core/timestamping.py +92 -0
  42. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/RESONANCE.json +95 -8
  43. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/canonical-node-layout.json +16 -1
  44. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/adapters/claude-code/hooks/hooks.json +22 -0
  45. seif_cli-0.7.0/src/seif/plugins/adapters/claude-code/scripts/classification-gate.sh +208 -0
  46. seif_cli-0.7.0/src/seif/plugins/adapters/claude-code/scripts/classification_gate_helper.py +234 -0
  47. seif_cli-0.7.0/src/seif/plugins/adapters/claude-code/scripts/discipline_observer.py +133 -0
  48. seif_cli-0.7.0/src/seif/plugins/adapters/claude-code/scripts/pretooluse-claim-check.sh +89 -0
  49. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/adapters/claude-code/scripts/session-start.sh +8 -0
  50. seif_cli-0.7.0/src/seif/plugins/adapters/gemini/scripts/classification_gate_helper.py +234 -0
  51. seif_cli-0.7.0/src/seif/plugins/adapters/gemini/scripts/discipline_observer.py +133 -0
  52. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/adapters/generic/render/render.py +2 -2
  53. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/core/cycle_lifecycle.py +70 -1
  54. seif_cli-0.7.0/src/seif/plugins/core/heartbeat_tick.py +126 -0
  55. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/core/kernel_seed.py +1 -1
  56. seif_cli-0.7.0/src/seif/plugins/core/memory_index.py +260 -0
  57. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/core/session_lifecycle.py +234 -6
  58. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/scripts/host/README.md +44 -1
  59. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/scripts/host/host-install-config.sample.seif +6 -3
  60. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/scripts/host/seif-update.sh +223 -22
  61. {seif_cli-0.6.2 → seif_cli-0.7.0/src/seif_cli.egg-info}/PKG-INFO +4 -4
  62. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif_cli.egg-info/SOURCES.txt +70 -1
  63. seif_cli-0.7.0/tests/test_a26_binding_acceptance.py +160 -0
  64. seif_cli-0.7.0/tests/test_amend_cli.py +279 -0
  65. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_awareness_integration.py +76 -0
  66. seif_cli-0.7.0/tests/test_claims_broadcast.py +95 -0
  67. seif_cli-0.7.0/tests/test_claims_cmd_check.py +88 -0
  68. seif_cli-0.7.0/tests/test_claims_cmd_sweep.py +49 -0
  69. seif_cli-0.7.0/tests/test_claims_cmd_validate.py +97 -0
  70. seif_cli-0.7.0/tests/test_claims_conflicts.py +162 -0
  71. seif_cli-0.7.0/tests/test_claims_lifecycle.py +214 -0
  72. seif_cli-0.7.0/tests/test_claims_schema.py +221 -0
  73. seif_cli-0.7.0/tests/test_claims_sweep.py +139 -0
  74. seif_cli-0.7.0/tests/test_claims_telemetry.py +92 -0
  75. seif_cli-0.7.0/tests/test_classification_gate_credential_scan.py +129 -0
  76. seif_cli-0.7.0/tests/test_classification_gate_helper.py +232 -0
  77. seif_cli-0.7.0/tests/test_classify_reasoning.py +57 -0
  78. seif_cli-0.7.0/tests/test_cli_pending_disk_ops.py +302 -0
  79. seif_cli-0.7.0/tests/test_confirm_action_claim_warning.py +277 -0
  80. seif_cli-0.7.0/tests/test_cycle_cli_surface.py +273 -0
  81. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_cycle_lifecycle.py +74 -0
  82. seif_cli-0.7.0/tests/test_discipline_observer.py +326 -0
  83. seif_cli-0.7.0/tests/test_gap_59_report_v2_sessions.py +144 -0
  84. seif_cli-0.7.0/tests/test_hard_block.py +180 -0
  85. seif_cli-0.7.0/tests/test_heartbeat_tick.py +210 -0
  86. seif_cli-0.7.0/tests/test_hooks_claim_integration.py +201 -0
  87. seif_cli-0.7.0/tests/test_init_canonical_subdirs.py +77 -0
  88. seif_cli-0.7.0/tests/test_log_url_resolution.py +77 -0
  89. seif_cli-0.7.0/tests/test_memory_index.py +171 -0
  90. seif_cli-0.7.0/tests/test_memory_walk_up_canonical.py +59 -0
  91. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_migrate_host_config.py +163 -23
  92. seif_cli-0.7.0/tests/test_n2_integration_e2e.py +210 -0
  93. seif_cli-0.7.0/tests/test_ots_sovereign_stamp.py +139 -0
  94. seif_cli-0.7.0/tests/test_ots_verify_path_resolution.py +112 -0
  95. seif_cli-0.7.0/tests/test_print_package_data.py +52 -0
  96. seif_cli-0.7.0/tests/test_registry.py +501 -0
  97. seif_cli-0.6.2/tests/test_resonance_v2_bump.py → seif_cli-0.7.0/tests/test_resonance_v3_bump.py +77 -42
  98. seif_cli-0.7.0/tests/test_review_pem_marker.py +121 -0
  99. seif_cli-0.7.0/tests/test_seed_create_cli.py +271 -0
  100. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_seif_update_kernel_verify.py +8 -3
  101. seif_cli-0.7.0/tests/test_seif_update_n3_host_install_require.py +171 -0
  102. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_seif_update_rsync_rollback.py +8 -0
  103. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_seif_update_schema_v2.py +75 -2
  104. seif_cli-0.7.0/tests/test_seif_update_stage_summary.py +189 -0
  105. seif_cli-0.7.0/tests/test_seif_update_stage_telemetry.py +202 -0
  106. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_seif_update_template_refresh.py +9 -6
  107. seif_cli-0.7.0/tests/test_session_end_hook_wiring.py +247 -0
  108. seif_cli-0.7.0/tests/test_session_lifecycle_close.py +480 -0
  109. seif_cli-0.7.0/tests/test_setup_gemini.py +183 -0
  110. seif_cli-0.7.0/tests/test_sign_host_install_config.py +328 -0
  111. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_sign_resonance.py +44 -0
  112. seif_cli-0.7.0/tests/test_sign_verify_polish.py +84 -0
  113. seif_cli-0.7.0/tests/test_signing.py +210 -0
  114. seif_cli-0.7.0/tests/test_status_readonly.py +44 -0
  115. seif_cli-0.7.0/tests/test_status_self_update_telemetry.py +251 -0
  116. seif_cli-0.7.0/tests/test_wrapper_launch_gemini.py +132 -0
  117. seif_cli-0.6.2/LICENSE +0 -33
  118. seif_cli-0.6.2/src/seif/__init__.py +0 -1
  119. seif_cli-0.6.2/src/seif/analysis/__init__.py +0 -1
  120. seif_cli-0.6.2/src/seif/cli/__init__.py +0 -1
  121. seif_cli-0.6.2/src/seif/context/__init__.py +0 -1
  122. seif_cli-0.6.2/src/seif/core/__init__.py +0 -1
  123. seif_cli-0.6.2/src/seif/plugins/adapters/claude-code/scripts/classification-gate.sh +0 -141
  124. seif_cli-0.6.2/tests/test_registry.py +0 -233
  125. seif_cli-0.6.2/tests/test_signing.py +0 -105
  126. {seif_cli-0.6.2 → seif_cli-0.7.0}/MANIFEST.in +0 -0
  127. {seif_cli-0.6.2 → seif_cli-0.7.0}/setup.cfg +0 -0
  128. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/__main__.py +0 -0
  129. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/analysis/physical_constants.py +0 -0
  130. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/analysis/quality_gate.py +0 -0
  131. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/analysis/stance_detector.py +0 -0
  132. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/analysis/transcompiler.py +0 -0
  133. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/audio_provenance.py +0 -0
  134. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/bridge/__init__.py +0 -0
  135. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/bridge/native_client.py +0 -0
  136. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/cli/__main__.py +0 -0
  137. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/cli/chat.py +0 -0
  138. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/cli/identity.py +0 -0
  139. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/cli/main.py +0 -0
  140. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/cli/plugin_detect.py +0 -0
  141. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/cli/plugin_sync.py +0 -0
  142. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/cli/resonance_display.py +0 -0
  143. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/cli/serve.py +0 -0
  144. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/cli/serve_engine.py +0 -0
  145. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/cli/serve_v2.py +0 -0
  146. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/cli/wrapper_shims.py +0 -0
  147. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/constants.py +0 -0
  148. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/absorb_knowledge.py +0 -0
  149. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/advisor.py +0 -0
  150. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/code_compressor.py +0 -0
  151. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/context_importer.py +0 -0
  152. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/context_manager.py +0 -0
  153. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/context_qr.py +0 -0
  154. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/file_extractor.py +0 -0
  155. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/git_context.py +0 -0
  156. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/git_hooks.py +0 -0
  157. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/host_init.py +0 -0
  158. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/ingest.py +0 -0
  159. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/install_state.py +0 -0
  160. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/model_probe.py +0 -0
  161. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/nucleus.py +0 -0
  162. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/ref.py +0 -0
  163. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/seed_constraint.py +0 -0
  164. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/seif_io.py +0 -0
  165. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/context/sessions.py +0 -0
  166. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/core/fingerprint.py +0 -0
  167. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/core/integrity.py +0 -0
  168. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/core/n2_bundle.py +0 -0
  169. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/core/resonance_encoding.py +0 -0
  170. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/core/resonance_gate.py +0 -0
  171. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/core/sign_resonance.py +0 -0
  172. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/core/transfer_function.py +0 -0
  173. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/core/triple_gate.py +0 -0
  174. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/__init__.py +0 -0
  175. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/defaults/__init__.py +0 -0
  176. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/defaults/circuit-recovery-v1.seif +0 -0
  177. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/defaults/definitions-v1.seif +0 -0
  178. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/defaults/ise-dissonance-v1.seif +0 -0
  179. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/defaults/multi-agent-sync-v1.seif +0 -0
  180. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/defaults/onboarding.seif +0 -0
  181. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/defaults/partial-attention-axiom-v1.seif +0 -0
  182. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/defaults/seif-cycle-v1.seif +0 -0
  183. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/defaults/seif-os-architecture-v1.seif +0 -0
  184. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/defaults/triad-convergence-v1.seif +0 -0
  185. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/init_lite/AGENTS.md +0 -0
  186. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/init_lite/BOOT.md +0 -0
  187. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/init_lite/README.md +0 -0
  188. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/init_lite/__init__.py +0 -0
  189. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/init_lite/decisions_pending.md +0 -0
  190. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/init_lite/refs.md +0 -0
  191. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/init_lite/session_log.md +0 -0
  192. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/data/paths.py +0 -0
  193. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/generators/__init__.py +0 -0
  194. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/generators/watermark.py +0 -0
  195. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/governance/__init__.py +0 -0
  196. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/governance/transfer.py +0 -0
  197. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/init_lite.py +0 -0
  198. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/log/__init__.py +0 -0
  199. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/log/canonical.py +0 -0
  200. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/log/client.py +0 -0
  201. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/log/identity.py +0 -0
  202. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/mcp/__init__.py +0 -0
  203. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/mcp/server.py +0 -0
  204. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/mcp/watermark_server.py +0 -0
  205. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/observability/__init__.py +0 -0
  206. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/observability/bus_metrics.py +0 -0
  207. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/__init__.py +0 -0
  208. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/adapters/claude-code/scripts/circuit-check.sh +0 -0
  209. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/adapters/claude-code/scripts/quality-gate.sh +0 -0
  210. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/adapters/claude-code/scripts/session-end.sh +0 -0
  211. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/adapters/claude-code/skills/gate/SKILL.md +0 -0
  212. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/adapters/claude-code/skills/status/SKILL.md +0 -0
  213. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/adapters/claude-code/skills/sync/SKILL.md +0 -0
  214. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/adapters/copilot/render/render.py +0 -0
  215. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/adapters/cursor/render/render.py +0 -0
  216. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/adapters/gemini/render/render.py +0 -0
  217. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/core/circuit_monitor.py +0 -0
  218. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/core/cycle_coherence.py +0 -0
  219. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/core/cycle_heal.py +0 -0
  220. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/core/cycle_reseal.py +0 -0
  221. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/core/orchestra_probe.py +0 -0
  222. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/core/preflight_diff.py +0 -0
  223. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/plugins/core/session_registry.py +0 -0
  224. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/schemas/__init__.py +0 -0
  225. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/schemas/n2_bundle.py +0 -0
  226. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/schemas/pending.py +0 -0
  227. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/scripts/host/rsync-soak-inspect.sh +0 -0
  228. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/security/__init__.py +0 -0
  229. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif/security/mode.py +0 -0
  230. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif_cli.egg-info/dependency_links.txt +0 -0
  231. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif_cli.egg-info/entry_points.txt +0 -0
  232. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif_cli.egg-info/requires.txt +0 -0
  233. {seif_cli-0.6.2 → seif_cli-0.7.0}/src/seif_cli.egg-info/top_level.txt +0 -0
  234. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_a23_bus_metrics.py +0 -0
  235. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_absorb_knowledge.py +0 -0
  236. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_adapters.py +0 -0
  237. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_advisor.py +0 -0
  238. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_agents_set_tier1.py +0 -0
  239. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_audio_mystic_strip.py +0 -0
  240. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_audio_provenance.py +0 -0
  241. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_audio_watermark_mvp.py +0 -0
  242. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_audit_host.py +0 -0
  243. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_audit_phase.py +0 -0
  244. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_canonical_inputs.py +0 -0
  245. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_check_pointer_sync.py +0 -0
  246. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_check_seed_constraint.py +0 -0
  247. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_cli_argparse_conflicts.py +0 -0
  248. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_code_compressor.py +0 -0
  249. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_collaborative_seif.py +0 -0
  250. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_confirm_action.py +0 -0
  251. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_context_qr.py +0 -0
  252. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_context_repo.py +0 -0
  253. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_cycle_absorb_in_package.py +0 -0
  254. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_cycle_coherence.py +0 -0
  255. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_cycle_heal.py +0 -0
  256. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_cycle_phase_aliases.py +0 -0
  257. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_cycle_reseal.py +0 -0
  258. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_daemon_activity_surface.py +0 -0
  259. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_demo_chain_smoke.py +0 -0
  260. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_drain_inbox_corrupted.py +0 -0
  261. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_engine_cli_surface.py +0 -0
  262. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_gap_46_ingest_send_import.py +0 -0
  263. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_gap_47_pem_classification.py +0 -0
  264. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_gap_58_session_list_v2.py +0 -0
  265. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_git_context.py +0 -0
  266. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_git_hooks.py +0 -0
  267. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_host_init.py +0 -0
  268. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_init.py +0 -0
  269. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_init_auto_bind.py +0 -0
  270. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_init_lite.py +0 -0
  271. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_install_content_equality.py +0 -0
  272. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_install_state.py +0 -0
  273. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_integrity_orchestrator.py +0 -0
  274. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_load_module_cache.py +0 -0
  275. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_log_canonical.py +0 -0
  276. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_log_client.py +0 -0
  277. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_log_identity.py +0 -0
  278. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_mcp_server.py +0 -0
  279. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_mcp_watermark.py +0 -0
  280. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_model_probe.py +0 -0
  281. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_n2_bundle.py +0 -0
  282. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_next_session_count.py +0 -0
  283. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_ots_coverage.py +0 -0
  284. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_paths_seif_home.py +0 -0
  285. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_pending_cleanup_on_seal.py +0 -0
  286. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_pending_modules.py +0 -0
  287. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_pending_modules_surface.py +0 -0
  288. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_preflight_diff.py +0 -0
  289. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_quality_gate.py +0 -0
  290. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_rebuild_registry.py +0 -0
  291. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_ref.py +0 -0
  292. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_repo_state_diff.py +0 -0
  293. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_resonance_display_default_clean.py +0 -0
  294. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_resonance_gate.py +0 -0
  295. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_rsync_soak_inspect.py +0 -0
  296. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_schemas_pending.py +0 -0
  297. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_seed_auto_surfacing.py +0 -0
  298. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_seif_io.py +0 -0
  299. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_seif_update_interpreter_probe.py +0 -0
  300. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_seif_update_pipx_git_rollback.py +0 -0
  301. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_seif_update_smoke_rollback.py +0 -0
  302. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_serve_engine.py +0 -0
  303. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_session_counter_advance.py +0 -0
  304. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_session_id_normalization.py +0 -0
  305. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_session_registry.py +0 -0
  306. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_session_start_hook_uuid.py +0 -0
  307. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_sessions_active_cli.py +0 -0
  308. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_setup_core_install.py +0 -0
  309. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_setup_memory_symlink.py +0 -0
  310. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_smoke_10_sessions_no_unknown.py +0 -0
  311. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_stance_detector.py +0 -0
  312. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_transcompiler.py +0 -0
  313. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_transfer.py +0 -0
  314. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_transfer_function.py +0 -0
  315. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_triple_gate.py +0 -0
  316. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_vigilant_cli.py +0 -0
  317. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_workspace.py +0 -0
  318. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_workspace_architecture_v1.py +0 -0
  319. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_workspace_disambiguation.py +0 -0
  320. {seif_cli-0.6.2 → seif_cli-0.7.0}/tests/test_wrapper_shims.py +0 -0
seif_cli-0.7.0/LICENSE ADDED
@@ -0,0 +1,34 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 André Cunha Antero de Carvalho
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ This project was created by André Cunha Antero de Carvalho in collaboration with
26
+ multiple AI systems (Claude, Gemini, Kimi, Grok, Z.AI). The human
27
+ biological being provided the irreducible asymmetry — the questions,
28
+ the observations, the insistence on measurement over belief.
29
+
30
+ The protocol does not belong to any single entity. It belongs to the
31
+ resonance between biology and machine. But its origin is documented,
32
+ timestamped, and mathematically verified.
33
+
34
+ The gate does not filter — it resonates.
@@ -1,15 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: seif-cli
3
- Version: 0.6.2
3
+ Version: 0.7.0
4
4
  Summary: AI artifact provenance, quality gates, and data classification. Bitcoin-anchored timestamps, multi-AI consensus, locally enforced.
5
5
  Author: André Cunha Antero de Carvalho
6
- License: CC-BY-NC-SA-4.0
6
+ License-Expression: MIT
7
7
  Project-URL: Homepage, https://seifprotocol.com
8
8
  Project-URL: Documentation, https://seifprotocol.com/docs
9
9
  Project-URL: Repository, https://github.com/and2carvalho/seif
10
10
  Project-URL: Changelog, https://github.com/and2carvalho/seif/releases
11
11
  Keywords: ai-quality,llm-guardrails,ai-consensus,data-classification,context-management,ai-safety,multi-ai,quality-gate,prompt-evaluation,ai-grounding,resonance,sentinel,self-healing,seif-os,circuit-state,ai-observability
12
- Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Development Status :: 4 - Beta
13
13
  Classifier: Intended Audience :: Developers
14
14
  Classifier: Intended Audience :: Science/Research
15
15
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
@@ -480,4 +480,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md).
480
480
 
481
481
  ## License
482
482
 
483
- CC BY-NC-SA 4.0 — [André Cunha Antero de Carvalho](https://github.com/and2carvalho)
483
+ MIT — [André Cunha Antero de Carvalho](https://github.com/and2carvalho)
@@ -432,4 +432,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md).
432
432
 
433
433
  ## License
434
434
 
435
- CC BY-NC-SA 4.0 — [André Cunha Antero de Carvalho](https://github.com/and2carvalho)
435
+ MIT — [André Cunha Antero de Carvalho](https://github.com/and2carvalho)
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "seif-cli"
7
- version = "0.6.2"
7
+ version = "0.7.0"
8
8
  description = "AI artifact provenance, quality gates, and data classification. Bitcoin-anchored timestamps, multi-AI consensus, locally enforced."
9
9
  readme = "README.md"
10
- license = {text = "CC-BY-NC-SA-4.0"}
10
+ license = "MIT"
11
11
  requires-python = ">=3.11"
12
12
  authors = [
13
13
  {name = "André Cunha Antero de Carvalho"},
@@ -19,7 +19,7 @@ keywords = [
19
19
  "self-healing", "seif-os", "circuit-state", "ai-observability",
20
20
  ]
21
21
  classifiers = [
22
- "Development Status :: 3 - Alpha",
22
+ "Development Status :: 4 - Beta",
23
23
  "Intended Audience :: Developers",
24
24
  "Intended Audience :: Science/Research",
25
25
  "Topic :: Scientific/Engineering :: Artificial Intelligence",
@@ -0,0 +1 @@
1
+ """S.E.I.F. — Signed Evidence & Integrity Framework"""
@@ -0,0 +1,9 @@
1
+ """Amend subpackage — append-only amendment-chain entries.
2
+
3
+ Implements `seif --amend FILE --amend-entry JSON` and friends. Used to add
4
+ new `_amendments[]` entries to SEIF artifacts (pending modules, sealed
5
+ cycles, signed resonance records) without re-signing the host artifact.
6
+ Pairs with the [[feedback_amendment_chain_over_host_resign]] convention.
7
+
8
+ Closes the last universal write-side gap surfaced by s83 t3 PR-3.
9
+ """
@@ -0,0 +1,186 @@
1
+ """--amend FILE: append an _amendments[] entry to any SEIF JSON artifact.
2
+
3
+ The amendment-chain convention (feedback_amendment_chain_over_host_resign):
4
+ some SEIF artifacts have already been signed/stamped and cannot easily be
5
+ re-signed by the original host (offline laptop, immutable kernel, etc.).
6
+ Adding a new `_amendments[]` entry — append-only, with provenance fields —
7
+ records the change without touching the host artifact's canonical fields.
8
+
9
+ This module exposes the operation as a first-class CLI command so AIs
10
+ don't have to raw-Write the file (which the discipline observer would
11
+ log and the hard-block phase would refuse).
12
+
13
+ Public API
14
+ ----------
15
+ - ``append_amendment(file_path, entry, *, amend_id=None, author=None) -> dict``
16
+ - ``cmd_amend(args) -> int`` (entrypoint wired into ``seif --amend``)
17
+ """
18
+ from __future__ import annotations
19
+
20
+ import datetime
21
+ import json
22
+ import os
23
+ import re
24
+ import sys
25
+ import tempfile
26
+ from pathlib import Path
27
+ from typing import Any
28
+
29
+ __all__ = ["append_amendment", "cmd_amend"]
30
+
31
+
32
+ _SLUG_RE = re.compile(r"[^a-z0-9-]+")
33
+
34
+
35
+ def _now_iso() -> str:
36
+ return (
37
+ datetime.datetime.now(datetime.timezone.utc)
38
+ .isoformat()
39
+ .replace("+00:00", "Z")
40
+ )
41
+
42
+
43
+ def _slug_for(text: str) -> str:
44
+ s = (text or "").strip().lower()
45
+ s = _SLUG_RE.sub("-", s).strip("-")
46
+ return s[:48] or "entry"
47
+
48
+
49
+ def _atomic_write(path: Path, data: Any) -> None:
50
+ """Write JSON atomically: tempfile in same dir → fsync → rename.
51
+
52
+ Same-dir tempfile guarantees rename is atomic on POSIX (same fs).
53
+ """
54
+ body = json.dumps(data, indent=2, ensure_ascii=False)
55
+ parent = path.parent
56
+ with tempfile.NamedTemporaryFile(
57
+ mode="w",
58
+ encoding="utf-8",
59
+ dir=str(parent),
60
+ prefix=path.name + ".",
61
+ suffix=".tmp",
62
+ delete=False,
63
+ ) as tf:
64
+ tmp_path = Path(tf.name)
65
+ tf.write(body)
66
+ tf.write("\n")
67
+ tf.flush()
68
+ os.fsync(tf.fileno())
69
+ tmp_path.replace(path)
70
+
71
+
72
+ def append_amendment(
73
+ file_path: str | os.PathLike,
74
+ entry: dict,
75
+ *,
76
+ amend_id: str | None = None,
77
+ author: str | None = None,
78
+ ) -> dict:
79
+ """Append a new entry to ``data["_amendments"]`` in the given JSON file.
80
+
81
+ - The file MUST be a JSON object at the top level.
82
+ - If ``_amendments`` is missing or not a list, it is initialized to `[]`.
83
+ - The appended entry is the user-supplied ``entry`` dict, with the
84
+ following auto-fields injected if not already present:
85
+ * ``id`` — defaults to ``amend_id``, else
86
+ ``f"amend-{n+1:03d}-{slug(scope)}"``.
87
+ * ``appended_at`` — UTC ISO timestamp.
88
+ * ``appended_by`` — defaults to ``author``, else ``$USER``, else
89
+ ``"anonymous"``.
90
+
91
+ Returns the appended entry (mutated copy of ``entry``). Raises on I/O
92
+ or JSON errors; the file is left untouched if any step fails before
93
+ the atomic rename.
94
+ """
95
+ fp = Path(file_path)
96
+ if not fp.is_file():
97
+ raise FileNotFoundError(f"{fp} does not exist or is not a file")
98
+
99
+ raw = fp.read_text(encoding="utf-8")
100
+ data = json.loads(raw) # raises JSONDecodeError on invalid JSON
101
+ if not isinstance(data, dict):
102
+ raise ValueError(f"{fp} is not a JSON object at top level")
103
+
104
+ amendments = data.get("_amendments")
105
+ if not isinstance(amendments, list):
106
+ amendments = []
107
+ data["_amendments"] = amendments
108
+
109
+ new_entry: dict = dict(entry) # shallow copy so caller's dict stays clean
110
+ if "id" not in new_entry:
111
+ if amend_id:
112
+ new_entry["id"] = amend_id
113
+ else:
114
+ scope = new_entry.get("scope") or new_entry.get("title") or ""
115
+ new_entry["id"] = (
116
+ f"amend-{len(amendments) + 1:03d}-{_slug_for(scope)}"
117
+ )
118
+ if "appended_at" not in new_entry:
119
+ new_entry["appended_at"] = _now_iso()
120
+ if "appended_by" not in new_entry:
121
+ new_entry["appended_by"] = author or os.environ.get("USER") or "anonymous"
122
+
123
+ amendments.append(new_entry)
124
+ _atomic_write(fp, data)
125
+ return new_entry
126
+
127
+
128
+ def _load_entry(args) -> dict:
129
+ """Resolve `--amend-entry` (inline JSON) and `--amend-entry-file` (path).
130
+
131
+ Exactly one source is required. If both are given, --amend-entry wins
132
+ (matches argparse last-arg semantics + saves a stat call).
133
+ """
134
+ inline = getattr(args, "amend_entry", None)
135
+ from_file = getattr(args, "amend_entry_file", None)
136
+ if inline:
137
+ try:
138
+ data = json.loads(inline)
139
+ except (ValueError, json.JSONDecodeError) as e:
140
+ raise ValueError(f"--amend-entry is not valid JSON: {e}") from e
141
+ if not isinstance(data, dict):
142
+ raise ValueError("--amend-entry must be a JSON object")
143
+ return data
144
+ if from_file:
145
+ p = Path(from_file)
146
+ if not p.is_file():
147
+ raise FileNotFoundError(f"--amend-entry-file {p} does not exist")
148
+ try:
149
+ data = json.loads(p.read_text(encoding="utf-8"))
150
+ except (ValueError, json.JSONDecodeError) as e:
151
+ raise ValueError(f"--amend-entry-file is not valid JSON: {e}") from e
152
+ if not isinstance(data, dict):
153
+ raise ValueError("--amend-entry-file must contain a JSON object")
154
+ return data
155
+ raise ValueError(
156
+ "no entry source: pass --amend-entry JSON or --amend-entry-file PATH"
157
+ )
158
+
159
+
160
+ def cmd_amend(args) -> int:
161
+ """Entrypoint for `seif --amend FILE ...`."""
162
+ target = getattr(args, "amend", None)
163
+ if not target:
164
+ print("Error: --amend requires FILE", file=sys.stderr)
165
+ return 2
166
+ try:
167
+ entry = _load_entry(args)
168
+ appended = append_amendment(
169
+ target,
170
+ entry,
171
+ amend_id=getattr(args, "amend_id", None),
172
+ author=getattr(args, "amend_author", None),
173
+ )
174
+ except FileNotFoundError as e:
175
+ print(f"Error: {e}", file=sys.stderr)
176
+ return 2
177
+ except (ValueError, json.JSONDecodeError) as e:
178
+ print(f"Error: {e}", file=sys.stderr)
179
+ return 2
180
+ except OSError as e:
181
+ print(f"Error: I/O failure: {e}", file=sys.stderr)
182
+ return 2
183
+ print(f"[amend] appended {appended['id']} to {target}")
184
+ print(f" appended_at: {appended['appended_at']}")
185
+ print(f" appended_by: {appended['appended_by']}")
186
+ return 0
@@ -0,0 +1,199 @@
1
+ """--seed-create CLI: lay down a new SEED-sNN.json at cycle seal.
2
+
3
+ Last universal write-side gap closed by s83 t3 PR-4. Companion to
4
+ amend.py — both live in src/seif/amend/ because both implement
5
+ amendment-chain-aware artifact creation/mutation.
6
+
7
+ Behavior
8
+ --------
9
+ 1. Resolve workspace root (walk up from cwd for a directory containing
10
+ `.seif/`, or accept explicit --seed-output PATH).
11
+ 2. Compute the canonical filename `SEED-s{N}-{YYYY-MM-DD}.json` under
12
+ `.seif/seeds/`.
13
+ 3. Refuse to overwrite an existing file (use `--amend` to mutate, or
14
+ delete + recreate explicitly).
15
+ 4. Build a minimal valid record (SEIF-SEED-v2 protocol) with auto-
16
+ filled fields. Merge in any user-supplied JSON via
17
+ `--seed-content-file PATH`. User fields win on conflict.
18
+ 5. Atomic write (tempfile in same dir → fsync → rename).
19
+ """
20
+ from __future__ import annotations
21
+
22
+ import datetime
23
+ import json
24
+ import os
25
+ import sys
26
+ from pathlib import Path
27
+
28
+ __all__ = ["cmd_seed_create", "build_seed_record", "resolve_seed_output_path"]
29
+
30
+
31
+ def _now_iso() -> str:
32
+ return (
33
+ datetime.datetime.now(datetime.timezone.utc)
34
+ .isoformat()
35
+ .replace("+00:00", "Z")
36
+ )
37
+
38
+
39
+ def _today_yyyymmdd() -> str:
40
+ return datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d")
41
+
42
+
43
+ def _walk_up_for_seif(start: Path) -> Path | None:
44
+ cur = start.resolve()
45
+ for _ in range(20):
46
+ if (cur / ".seif").is_dir():
47
+ return cur
48
+ if cur == cur.parent:
49
+ return None
50
+ cur = cur.parent
51
+ return None
52
+
53
+
54
+ def resolve_seed_output_path(
55
+ session_target: int,
56
+ *,
57
+ explicit_output: str | None = None,
58
+ workspace: str | None = None,
59
+ ) -> Path:
60
+ """Compute the seed file path. `explicit_output` overrides everything."""
61
+ if explicit_output:
62
+ return Path(explicit_output).expanduser().resolve()
63
+ if workspace:
64
+ ws = Path(workspace).expanduser().resolve()
65
+ else:
66
+ ws = _walk_up_for_seif(Path.cwd())
67
+ if ws is None:
68
+ raise FileNotFoundError(
69
+ "no .seif/ workspace found from cwd. "
70
+ "Pass --seed-output PATH or cd into a workspace."
71
+ )
72
+ return ws / ".seif" / "seeds" / f"SEED-s{session_target}-{_today_yyyymmdd()}.json"
73
+
74
+
75
+ def build_seed_record(
76
+ session_target: int,
77
+ *,
78
+ parent_cycle_module: str | None = None,
79
+ generator: str | None = None,
80
+ content_overlay: dict | None = None,
81
+ ) -> dict:
82
+ """Construct the minimal valid SEIF-SEED-v2 record."""
83
+ base = {
84
+ "_instruction": (
85
+ f"SEED for session {session_target}. Created by seif --seed-create. "
86
+ "Amend via `seif --amend <this-file> --amend-entry '{...}'` to add "
87
+ "session_summary, primary_anchor, expected_actions, what_NOT_to_do, "
88
+ "etc., as the seal ritual unfolds."
89
+ ),
90
+ "protocol": "SEIF-SEED-v2",
91
+ "seed_id": f"SEED-s{session_target}-{_today_yyyymmdd()}",
92
+ "generator": generator
93
+ or f"seif --seed-create (user={os.environ.get('USER', 'anonymous')})",
94
+ "generated_at": _now_iso(),
95
+ "session_target": session_target,
96
+ "parent_session": session_target - 1 if session_target > 0 else None,
97
+ "parent_cycle_module": parent_cycle_module,
98
+ "_amendments": [],
99
+ }
100
+ if content_overlay:
101
+ # User-supplied fields win — they may carry session_summary, anchors, etc.
102
+ merged = dict(base)
103
+ merged.update(content_overlay)
104
+ # Always preserve _amendments as a list even if overlay tried to remove it.
105
+ if not isinstance(merged.get("_amendments"), list):
106
+ merged["_amendments"] = base["_amendments"]
107
+ return merged
108
+ return base
109
+
110
+
111
+ def _atomic_write(path: Path, data: dict) -> None:
112
+ import tempfile
113
+
114
+ body = json.dumps(data, indent=2, ensure_ascii=False)
115
+ parent = path.parent
116
+ parent.mkdir(parents=True, exist_ok=True)
117
+ with tempfile.NamedTemporaryFile(
118
+ mode="w",
119
+ encoding="utf-8",
120
+ dir=str(parent),
121
+ prefix=path.name + ".",
122
+ suffix=".tmp",
123
+ delete=False,
124
+ ) as tf:
125
+ tmp = Path(tf.name)
126
+ tf.write(body)
127
+ tf.write("\n")
128
+ tf.flush()
129
+ os.fsync(tf.fileno())
130
+ tmp.replace(path)
131
+
132
+
133
+ def cmd_seed_create(args) -> int:
134
+ """Entrypoint for `seif --seed-create --seed-session N [...]`."""
135
+ target = getattr(args, "seed_session", None)
136
+ if target is None:
137
+ print(
138
+ "Error: --seed-create requires --seed-session N (target session number)",
139
+ file=sys.stderr,
140
+ )
141
+ return 2
142
+ if not isinstance(target, int) or target < 0:
143
+ print(f"Error: --seed-session must be a non-negative integer (got {target})",
144
+ file=sys.stderr)
145
+ return 2
146
+
147
+ try:
148
+ out_path = resolve_seed_output_path(
149
+ target,
150
+ explicit_output=getattr(args, "seed_output", None),
151
+ workspace=getattr(args, "seed_workspace", None),
152
+ )
153
+ except FileNotFoundError as e:
154
+ print(f"Error: {e}", file=sys.stderr)
155
+ return 2
156
+
157
+ if out_path.exists():
158
+ print(
159
+ f"Error: {out_path} already exists. Use `seif --amend` to mutate, "
160
+ "or remove it explicitly before re-running --seed-create.",
161
+ file=sys.stderr,
162
+ )
163
+ return 2
164
+
165
+ overlay: dict | None = None
166
+ overlay_file = getattr(args, "seed_content_file", None)
167
+ if overlay_file:
168
+ op = Path(overlay_file)
169
+ if not op.is_file():
170
+ print(f"Error: --seed-content-file {op} does not exist", file=sys.stderr)
171
+ return 2
172
+ try:
173
+ overlay = json.loads(op.read_text(encoding="utf-8"))
174
+ except (ValueError, json.JSONDecodeError) as e:
175
+ print(f"Error: --seed-content-file is not valid JSON: {e}", file=sys.stderr)
176
+ return 2
177
+ if not isinstance(overlay, dict):
178
+ print("Error: --seed-content-file must contain a JSON object", file=sys.stderr)
179
+ return 2
180
+
181
+ record = build_seed_record(
182
+ target,
183
+ parent_cycle_module=getattr(args, "seed_from_cycle", None),
184
+ generator=getattr(args, "seed_generator", None),
185
+ content_overlay=overlay,
186
+ )
187
+
188
+ try:
189
+ _atomic_write(out_path, record)
190
+ except OSError as e:
191
+ print(f"Error: I/O failure writing {out_path}: {e}", file=sys.stderr)
192
+ return 2
193
+
194
+ print(f"[seed-create] wrote {out_path}")
195
+ print(f" seed_id: {record['seed_id']}")
196
+ print(f" parent_session: {record['parent_session']}")
197
+ if record["parent_cycle_module"]:
198
+ print(f" parent_cycle_module: {record['parent_cycle_module']}")
199
+ return 0
@@ -0,0 +1 @@
1
+ """S.E.I.F. — Signed Evidence & Integrity Framework"""
@@ -0,0 +1,7 @@
1
+ """Audit subpackage — discipline observation reports.
2
+
3
+ Pairs with the PreToolUse hook observer (plugins/adapters/claude-code/scripts/
4
+ discipline_observer.py) that appends JSONL entries when AI agents Write/Edit
5
+ files under .seif/{cycles,sessions,seeds,memory,modules}/**. Phase-1 of s83
6
+ t3 discipline enforcement; see pending-2026-05-11-s83-t3-discipline-enforcement.
7
+ """