gator-command 1.4.0__tar.gz → 1.5.2__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 (147) hide show
  1. {gator_command-1.4.0/src/gator_command.egg-info → gator_command-1.5.2}/PKG-INFO +1 -1
  2. gator_command-1.5.2/pyproject.toml +91 -0
  3. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/cli.py +0 -4
  4. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/dashboard/dashboard.css +83 -0
  5. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/dashboard/dashboard.html +3 -3
  6. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/dashboard/dashboard.js +17 -10
  7. gator_command-1.5.2/src/gator_command/scripts/dashboard/views/history.js +107 -0
  8. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-dashboard.py +93 -10
  9. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-deploy.py +67 -5
  10. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-repo-status.py +28 -25
  11. gator_command-1.5.2/src/gator_command/templates/gator-starter/scripts/__pycache__/gator-pre-commit.cpython-313.pyc +0 -0
  12. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/gator-pre-commit.py +13 -337
  13. {gator_command-1.4.0 → gator_command-1.5.2/src/gator_command.egg-info}/PKG-INFO +1 -1
  14. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command.egg-info/SOURCES.txt +1 -0
  15. gator_command-1.4.0/pyproject.toml +0 -44
  16. gator_command-1.4.0/src/gator_command/templates/gator-starter/scripts/__pycache__/gator-pre-commit.cpython-313.pyc +0 -0
  17. {gator_command-1.4.0 → gator_command-1.5.2}/LICENSE +0 -0
  18. {gator_command-1.4.0 → gator_command-1.5.2}/PYPI_README.md +0 -0
  19. {gator_command-1.4.0 → gator_command-1.5.2}/README.md +0 -0
  20. {gator_command-1.4.0 → gator_command-1.5.2}/setup.cfg +0 -0
  21. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/__init__.py +0 -0
  22. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/crawler.py +0 -0
  23. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/dashboard/views/audit.js +0 -0
  24. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/dashboard/views/fleet.js +0 -0
  25. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/dashboard/views/repo.js +0 -0
  26. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/dashboard/views/settings.js +0 -0
  27. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/dashboard/views/updates.js +0 -0
  28. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/enforcer-prompt.md +0 -0
  29. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/extract-claude-sessions.py +0 -0
  30. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/extract-codex-sessions.py +0 -0
  31. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/extract-gemini-sessions.py +0 -0
  32. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-audit-renderers.py +0 -0
  33. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-audit.py +0 -0
  34. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-charter-draft.py +0 -0
  35. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-charter-lint.py +0 -0
  36. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-charter-verify.py +0 -0
  37. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-drift.py +0 -0
  38. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-enforce.py +0 -0
  39. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-fleet-intel.py +0 -0
  40. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-fleet-report.py +0 -0
  41. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-init-command-post.py +0 -0
  42. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-init.py +0 -0
  43. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-machine-id.py +0 -0
  44. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-policy-status.py +0 -0
  45. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-pulse.py +0 -0
  46. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-session-aggregator.py +0 -0
  47. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-session-block.py +0 -0
  48. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-session-common.py +0 -0
  49. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-session-sink.py +0 -0
  50. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-sessions.py +0 -0
  51. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-update.py +0 -0
  52. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator-version.py +0 -0
  53. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator_core.py +0 -0
  54. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator_remote.py +0 -0
  55. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gator_runtime.py +0 -0
  56. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gatorize-actions.sh +0 -0
  57. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gatorize-lib.sh +0 -0
  58. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gatorize-post.sh +0 -0
  59. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gatorize.py +0 -0
  60. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/gatorize.sh +0 -0
  61. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/generate_markdown.py +0 -0
  62. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/generate_wiki.py +0 -0
  63. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/graph_health.py +0 -0
  64. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/memex-lint.py +0 -0
  65. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/memex-lint.sh +0 -0
  66. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/memex.py +0 -0
  67. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/memex_formatters.py +0 -0
  68. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/memex_state.py +0 -0
  69. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/scripts/spawn.py +0 -0
  70. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/blueprints/README.md +0 -0
  71. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/charterignore +0 -0
  72. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/charters/README.md +0 -0
  73. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/charters/_template.md +0 -0
  74. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/commands/commit.md +0 -0
  75. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/commands/init.md +0 -0
  76. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/commands/update.md +0 -0
  77. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/constitution.md +0 -0
  78. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/field-guides/README.md +0 -0
  79. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/gator-start-up.md +0 -0
  80. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/procedures/charter-alignment.md +0 -0
  81. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/procedures/enforcer-review.md +0 -0
  82. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/procedures/field-guide-generation.md +0 -0
  83. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/procedures/knowledge-capture.md +0 -0
  84. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/procedures/significance-check.md +0 -0
  85. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/reference-notes/concierge-responses.md +0 -0
  86. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/reference-notes/dangerous-patterns.md +0 -0
  87. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/reference-notes/dashboard-operations.md +0 -0
  88. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/reference-notes/enforcer-configuration.md +0 -0
  89. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/reference-notes/example-project.md +0 -0
  90. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/reference-notes/failure-modes-and-self-correction.md +0 -0
  91. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/reference-notes/git-workflow.md +0 -0
  92. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/reference-notes/identity-and-ownership.md +0 -0
  93. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/reference-notes/refactor-approach.md +0 -0
  94. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/reference-notes/what-gator-requires-from-a-model.md +0 -0
  95. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/reference-notes/why-navigation-coding-feels-different.md +0 -0
  96. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/reference-notes/workflow-profiles.md +0 -0
  97. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/__pycache__/enforcer-review.cpython-313.pyc +0 -0
  98. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/__pycache__/gator-approve.cpython-313.pyc +0 -0
  99. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/__pycache__/gator-init.cpython-313.pyc +0 -0
  100. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/__pycache__/gator-update.cpython-313.pyc +0 -0
  101. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/enforcer-prompt.md +0 -0
  102. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/enforcer-review.py +0 -0
  103. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/gator-approve.py +0 -0
  104. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/gator-enforce.py +0 -0
  105. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/gator-init.py +0 -0
  106. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/gator-pulse.py +0 -0
  107. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/gator-session-start.py +0 -0
  108. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/gator-update.py +0 -0
  109. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/gator-version.py +0 -0
  110. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/gator_core.py +0 -0
  111. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/hooks/__pycache__/commit-msgcpython-313.pyc +0 -0
  112. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/hooks/__pycache__/post-commitcpython-313.pyc +0 -0
  113. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/hooks/__pycache__/pre-commitcpython-313.pyc +0 -0
  114. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/hooks/commit-msg +0 -0
  115. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/hooks/post-commit +0 -0
  116. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/scripts/hooks/pre-commit +0 -0
  117. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/sessions/.gitignore +0 -0
  118. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/vault/.gitkeep +0 -0
  119. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/vendor-hooks/claude-settings.json +0 -0
  120. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/vendor-hooks/codex-hooks.json +0 -0
  121. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/vendor-hooks/gemini-settings.json +0 -0
  122. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command/templates/gator-starter/whiteboard.md +0 -0
  123. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command.egg-info/dependency_links.txt +0 -0
  124. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command.egg-info/entry_points.txt +0 -0
  125. {gator_command-1.4.0 → gator_command-1.5.2}/src/gator_command.egg-info/top_level.txt +0 -0
  126. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_audit.py +0 -0
  127. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_audit_integration.py +0 -0
  128. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_charter_lint.py +0 -0
  129. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_dashboard_sessions.py +0 -0
  130. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_deploy.py +0 -0
  131. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_drift.py +0 -0
  132. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_fleet_intel.py +0 -0
  133. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_fleet_report.py +0 -0
  134. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_gator_core.py +0 -0
  135. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_gatorize.py +0 -0
  136. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_hooks.py +0 -0
  137. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_init.py +0 -0
  138. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_memex_state.py +0 -0
  139. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_packaging.py +0 -0
  140. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_pre_commit.py +0 -0
  141. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_remote.py +0 -0
  142. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_session_aggregator.py +0 -0
  143. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_session_block.py +0 -0
  144. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_session_sink.py +0 -0
  145. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_session_start.py +0 -0
  146. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_sessions.py +0 -0
  147. {gator_command-1.4.0 → gator_command-1.5.2}/tests/test_vendor_hooks.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gator-command
3
- Version: 1.4.0
3
+ Version: 1.5.2
4
4
  Summary: Git-native governance for AI-assisted engineering
5
5
  Author-email: Cumberland Laboratories <support@cumberlandlaboratories.com>
6
6
  License: MIT
@@ -0,0 +1,91 @@
1
+ [build-system]
2
+ requires = ["setuptools>=64", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "gator-command"
7
+ version = "1.5.2"
8
+ description = "Git-native governance for AI-assisted engineering"
9
+ readme = "PYPI_README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.9"
12
+ authors = [
13
+ {name = "Cumberland Laboratories", email = "support@cumberlandlaboratories.com"},
14
+ ]
15
+ urls = {Homepage = "https://github.com/cumberland-laboratories/gator", Repository = "https://github.com/cumberland-laboratories/gator"}
16
+ keywords = ["governance", "ai", "git", "charters", "audit", "compliance"]
17
+ classifiers = [
18
+ "Development Status :: 4 - Beta",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.9",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Topic :: Software Development :: Quality Assurance",
27
+ "Topic :: Software Development :: Version Control :: Git",
28
+ ]
29
+
30
+ [project.scripts]
31
+ gator = "gator_command.cli:main"
32
+
33
+ [tool.setuptools]
34
+ # Only the top-level package is a Python package. scripts/ and templates/
35
+ # are package DATA, not importable sub-packages. This prevents setuptools
36
+ # from auto-including enterprise .py files as Python modules.
37
+ packages = ["gator_command"]
38
+ package-dir = {"" = "src"}
39
+ # Disable auto-inclusion of VCS-tracked files — we control package contents
40
+ # explicitly via package-data. Enterprise-only scripts are intentionally absent.
41
+ include-package-data = false
42
+
43
+ # Gator Individual package data — explicit file lists for scripts.
44
+ # Enterprise-only scripts are NOT listed here and do not enter the wheel.
45
+ [tool.setuptools.package-data]
46
+ gator_command = [
47
+ "scripts/crawler.py",
48
+ "scripts/gator-charter-draft.py",
49
+ "scripts/gator-charter-lint.py",
50
+ "scripts/gator-charter-verify.py",
51
+ "scripts/gator-dashboard.py",
52
+ "scripts/gator-deploy.py",
53
+ "scripts/gator-enforce.py",
54
+ "scripts/gator-init-command-post.py",
55
+ "scripts/gator-init.py",
56
+ "scripts/gator-machine-id.py",
57
+ "scripts/gator-policy-status.py",
58
+ "scripts/gator-pulse.py",
59
+ "scripts/gator-repo-status.py",
60
+ "scripts/gator-update.py",
61
+ "scripts/gator-version.py",
62
+ "scripts/gator_core.py",
63
+ "scripts/gator_remote.py",
64
+ "scripts/gator_runtime.py",
65
+ "scripts/gatorize.py",
66
+ "scripts/generate_markdown.py",
67
+ "scripts/generate_wiki.py",
68
+ "scripts/graph_health.py",
69
+ "scripts/memex-lint.py",
70
+ "scripts/memex.py",
71
+ "scripts/memex_formatters.py",
72
+ "scripts/memex_state.py",
73
+ "scripts/spawn.py",
74
+ "scripts/gatorize-actions.sh",
75
+ "scripts/gatorize-lib.sh",
76
+ "scripts/gatorize-post.sh",
77
+ "scripts/gatorize.sh",
78
+ "scripts/memex-lint.sh",
79
+ "scripts/enforcer-prompt.md",
80
+ "scripts/dashboard/**/*",
81
+ "templates/**/*",
82
+ "templates/**/.*",
83
+ ]
84
+
85
+ # Enterprise-only template/dashboard files excluded from the wheel.
86
+ [tool.setuptools.exclude-package-data]
87
+ gator_command = [
88
+ "scripts/dashboard/views/audit.js",
89
+ "templates/gator-starter/scripts/gator-session-start.py",
90
+ "templates/gator-starter/vendor-hooks/*",
91
+ ]
@@ -72,10 +72,6 @@ COMMANDS = {
72
72
  "init": ("gator-init.py", "Run session-opening procedure"),
73
73
  "pulse": ("gator-pulse.py", "Generate strategic operations brief"),
74
74
  "dashboard": ("gator-dashboard.py", "Start the governance dashboard"),
75
- "audit": ("gator-audit.py", "Run governance audit"),
76
- "drift": ("gator-drift.py", "Check fleet for governance drift"),
77
- "fleet": ("gator-fleet-report.py", "Fleet status report"),
78
- "session-blocks": ("gator-session-block.py", "Generate session-block companions"),
79
75
  }
80
76
 
81
77
 
@@ -1162,3 +1162,86 @@ mark.search-hit {
1162
1162
  .md-table tr:nth-child(even) {
1163
1163
  background: #fafbfc;
1164
1164
  }
1165
+
1166
+ /* ── History view ────────────────────────────────────────────────────── */
1167
+
1168
+ .history-commit {
1169
+ border: 1px solid #e1e4e8;
1170
+ border-radius: 6px;
1171
+ padding: 12px 16px;
1172
+ margin-bottom: 8px;
1173
+ background: #fff;
1174
+ }
1175
+
1176
+ .history-commit.has-body {
1177
+ cursor: default;
1178
+ }
1179
+
1180
+ .history-header {
1181
+ display: flex;
1182
+ align-items: baseline;
1183
+ gap: 8px;
1184
+ flex-wrap: wrap;
1185
+ }
1186
+
1187
+ .history-hash {
1188
+ font-size: 12px;
1189
+ color: #6a737d;
1190
+ background: #f6f8fa;
1191
+ padding: 1px 6px;
1192
+ border-radius: 3px;
1193
+ flex-shrink: 0;
1194
+ }
1195
+
1196
+ .history-subject {
1197
+ font-weight: 600;
1198
+ font-size: 14px;
1199
+ color: #24292e;
1200
+ }
1201
+
1202
+ .history-meta {
1203
+ font-size: 12px;
1204
+ color: #6a737d;
1205
+ margin-left: auto;
1206
+ flex-shrink: 0;
1207
+ white-space: nowrap;
1208
+ }
1209
+
1210
+ .history-badge {
1211
+ font-size: 11px;
1212
+ padding: 1px 6px;
1213
+ border-radius: 3px;
1214
+ flex-shrink: 0;
1215
+ }
1216
+
1217
+ .history-badge.agent {
1218
+ background: #e3f2fd;
1219
+ color: #1565c0;
1220
+ }
1221
+
1222
+ .history-badge.architect {
1223
+ background: #e8f5e9;
1224
+ color: #2e7d32;
1225
+ }
1226
+
1227
+ .history-body {
1228
+ margin-top: 8px;
1229
+ padding-top: 8px;
1230
+ border-top: 1px solid #f0f0f0;
1231
+ font-size: 13px;
1232
+ color: #444;
1233
+ line-height: 1.5;
1234
+ }
1235
+
1236
+ .history-body p {
1237
+ margin: 4px 0;
1238
+ }
1239
+
1240
+ .history-body ul {
1241
+ margin: 4px 0;
1242
+ padding-left: 20px;
1243
+ }
1244
+
1245
+ .history-body li {
1246
+ margin: 2px 0;
1247
+ }
@@ -23,8 +23,8 @@
23
23
  <button class="sidebar-item dimmed" data-view="repo" id="repo-tab" style="padding-left:28px">
24
24
  <span class="sidebar-icon">▸</span> Repo
25
25
  </button>
26
- <button class="sidebar-item" data-view="audit">
27
- <span class="sidebar-icon">◉</span> Audit
26
+ <button class="sidebar-item" data-view="history">
27
+ <span class="sidebar-icon">◉</span> History
28
28
  </button>
29
29
 
30
30
  <div class="nav-group-label">Knowledge</div>
@@ -76,7 +76,7 @@
76
76
  </div>
77
77
 
78
78
  <script src="views/fleet.js"></script>
79
- <script src="views/audit.js"></script>
79
+ <script src="views/history.js"></script>
80
80
  <script src="views/repo.js"></script>
81
81
  <script src="views/updates.js"></script>
82
82
  <script src="views/settings.js"></script>
@@ -29,7 +29,7 @@
29
29
 
30
30
  const VIEW_META = {
31
31
  fleet: { title: "Fleet", subtitle: "" },
32
- audit: { title: "Audit", subtitle: "" },
32
+ history: { title: "History", subtitle: "" },
33
33
  repo: { title: "Repo", subtitle: "" },
34
34
  updates: { title: "Updates", subtitle: "" },
35
35
  settings: { title: "Settings", subtitle: "" },
@@ -107,10 +107,17 @@
107
107
  const views = window.GatorViews || {};
108
108
 
109
109
  if (name === "fleet") {
110
- const fleet = state.data && state.data.fleet || {};
111
- const summary = fleet.summary || {};
112
- const total = summary.total || (fleet.repos || []).length;
113
- const accessible = summary.accessible || 0;
110
+ let total, accessible;
111
+ if (state.data && state.data.standalone) {
112
+ const repos = state.data.repos || [];
113
+ total = repos.length;
114
+ accessible = repos.filter(r => r.accessible).length;
115
+ } else {
116
+ const fleet = state.data && state.data.fleet || {};
117
+ const summary = fleet.summary || {};
118
+ total = summary.total || (fleet.repos || []).length;
119
+ accessible = summary.accessible || 0;
120
+ }
114
121
  updateTopbar("fleet", `${total} repos · ${accessible} accessible`);
115
122
  if (views.fleet) {
116
123
  views.fleet(state.data, viewSlot);
@@ -120,12 +127,12 @@
120
127
  return;
121
128
  }
122
129
 
123
- if (name === "audit") {
124
- updateTopbar("audit", "Governance posture");
125
- if (views.audit) {
126
- views.audit(state.data, viewSlot, state.activeRepoKey);
130
+ if (name === "history") {
131
+ updateTopbar("history", "Recent commits");
132
+ if (views.history) {
133
+ views.history(state.data, viewSlot, state.activeRepo);
127
134
  } else {
128
- viewSlot.innerHTML = "<p class='muted'>Audit view not available.</p>";
135
+ viewSlot.innerHTML = "<p class='muted'>History view not available.</p>";
129
136
  }
130
137
  return;
131
138
  }
@@ -0,0 +1,107 @@
1
+ /**
2
+ * history.js — History view for Gator Dashboard.
3
+ *
4
+ * Shows recent commits from git log with rich descriptions.
5
+ * Pure git — no session dependency, no aggregator, no snippets.
6
+ *
7
+ * Data source: GET /api/repo/<name>/history?limit=20
8
+ */
9
+
10
+ (function () {
11
+ "use strict";
12
+
13
+ window.GatorViews = window.GatorViews || {};
14
+
15
+ function escHtml(str) {
16
+ return String(str)
17
+ .replace(/&/g, "&amp;")
18
+ .replace(/</g, "&lt;")
19
+ .replace(/>/g, "&gt;")
20
+ .replace(/"/g, "&quot;");
21
+ }
22
+
23
+ function fmtDate(ts) {
24
+ if (!ts) return "";
25
+ try {
26
+ return new Date(ts).toLocaleDateString(undefined, {
27
+ year: "numeric", month: "short", day: "numeric",
28
+ hour: "2-digit", minute: "2-digit",
29
+ });
30
+ } catch (_) { return ts; }
31
+ }
32
+
33
+ function renderBody(body) {
34
+ if (!body) return "";
35
+ // Convert markdown-like bullet lists to HTML
36
+ const lines = body.split("\n");
37
+ const parts = [];
38
+ let inList = false;
39
+ for (const line of lines) {
40
+ const trimmed = line.trim();
41
+ if (trimmed.startsWith("- ") || trimmed.startsWith("* ")) {
42
+ if (!inList) { parts.push("<ul>"); inList = true; }
43
+ parts.push("<li>" + escHtml(trimmed.slice(2)) + "</li>");
44
+ } else {
45
+ if (inList) { parts.push("</ul>"); inList = false; }
46
+ if (trimmed) {
47
+ parts.push("<p>" + escHtml(trimmed) + "</p>");
48
+ }
49
+ }
50
+ }
51
+ if (inList) parts.push("</ul>");
52
+ return parts.join("\n");
53
+ }
54
+
55
+ window.GatorViews.history = function (data, container, repoName) {
56
+ container.innerHTML = "<p class='muted' style='padding:20px'>Loading history...</p>";
57
+
58
+ if (!repoName) {
59
+ container.innerHTML = "<p class='muted' style='padding:40px;text-align:center'>Select a repo from the Fleet view to see its history.</p>";
60
+ return;
61
+ }
62
+
63
+ fetch("/api/repo/" + encodeURIComponent(repoName) + "/history?limit=30")
64
+ .then(function (r) { return r.json(); })
65
+ .then(function (result) {
66
+ if (result.error) {
67
+ container.innerHTML = "<p class='muted'>" + escHtml(result.error) + "</p>";
68
+ return;
69
+ }
70
+ const commits = result.commits || [];
71
+ if (commits.length === 0) {
72
+ container.innerHTML = "<p class='muted' style='padding:20px'>No commits found.</p>";
73
+ return;
74
+ }
75
+
76
+ var html = "<div class='history-view' style='padding:16px;max-width:900px'>";
77
+ html += "<h2 style='margin:0 0 16px 0;font-size:18px;font-weight:600'>" + escHtml(repoName) + " — Recent Commits</h2>";
78
+
79
+ for (var i = 0; i < commits.length; i++) {
80
+ var c = commits[i];
81
+ var hasBody = c.body && c.body.trim();
82
+ var agentBadge = c.agent ? "<span class='history-badge agent'>" + escHtml(c.agent) + "</span>" : "";
83
+ var architectBadge = c.architect ? "<span class='history-badge architect'>" + escHtml(c.architect) + "</span>" : "";
84
+
85
+ html += "<div class='history-commit" + (hasBody ? " has-body" : "") + "'>";
86
+ html += "<div class='history-header'>";
87
+ html += "<code class='history-hash'>" + escHtml(c.short_hash) + "</code>";
88
+ html += "<span class='history-subject'>" + escHtml(c.subject) + "</span>";
89
+ html += "<span class='history-meta'>" + fmtDate(c.date) + " · " + escHtml(c.author) + "</span>";
90
+ html += agentBadge + architectBadge;
91
+ html += "</div>";
92
+
93
+ if (hasBody) {
94
+ html += "<div class='history-body'>" + renderBody(c.body) + "</div>";
95
+ }
96
+
97
+ html += "</div>";
98
+ }
99
+
100
+ html += "</div>";
101
+ container.innerHTML = html;
102
+ })
103
+ .catch(function (err) {
104
+ container.innerHTML = "<p class='muted'>Error loading history: " + escHtml(err.message) + "</p>";
105
+ });
106
+ };
107
+ })();
@@ -39,7 +39,7 @@ DASHBOARD_DIR = SCRIPTS_DIR / "dashboard"
39
39
  COMMAND_POST_ROOT = SCRIPTS_DIR.parent.parent.parent # repo root (src/gator_command/scripts/ → repo root)
40
40
 
41
41
  sys.path.insert(0, str(SCRIPTS_DIR))
42
- from gator_core import get_version, find_command_post, parse_registry, import_sibling # noqa: E402
42
+ from gator_core import get_version, find_command_post, parse_registry, import_sibling, git # noqa: E402
43
43
 
44
44
  # ── settings ──────────────────────────────────────────────────────────────────
45
45
  # No dashboard-wide mode toggle. Topology is per-repo, not dashboard-global.
@@ -287,6 +287,51 @@ def _resolve_repo_path(repo_name):
287
287
  return ""
288
288
 
289
289
 
290
+ def _get_repo_history(repo_path, limit=20):
291
+ """Get recent commit history from a repo via git log.
292
+
293
+ Returns list of commit dicts with hash, short_hash, date, author,
294
+ subject, body, and trailers. Pure git — no session dependency.
295
+ """
296
+ # Use %x00 as field separator, %x01 as record separator
297
+ fmt = "%H%x00%h%x00%aI%x00%an%x00%s%x00%b%x00%(trailers:key=Gator-Agent)%x00%(trailers:key=Gator-Architect)%x01"
298
+ out, ok = git(
299
+ "log", f"--max-count={limit}", f"--format={fmt}",
300
+ cwd=repo_path,
301
+ )
302
+ if not ok or not out:
303
+ return []
304
+
305
+ commits = []
306
+ for record in out.split("\x01"):
307
+ record = record.strip()
308
+ if not record:
309
+ continue
310
+ parts = record.split("\x00")
311
+ if len(parts) < 6:
312
+ continue
313
+ commit_hash = parts[0]
314
+ short_hash = parts[1]
315
+ date = parts[2]
316
+ author = parts[3]
317
+ subject = parts[4]
318
+ body = parts[5].strip()
319
+ agent = parts[6].strip().replace("Gator-Agent: ", "") if len(parts) > 6 else ""
320
+ architect = parts[7].strip().replace("Gator-Architect: ", "") if len(parts) > 7 else ""
321
+
322
+ commits.append({
323
+ "hash": commit_hash,
324
+ "short_hash": short_hash,
325
+ "date": date,
326
+ "author": author,
327
+ "subject": subject,
328
+ "body": body,
329
+ "agent": agent,
330
+ "architect": architect,
331
+ })
332
+ return commits
333
+
334
+
290
335
  def _resolve_audit_sessions(repo_hash=None, fleet=False, refresh=False,
291
336
  registry_repos=None):
292
337
  """Resolve and return session summaries for the audit endpoint.
@@ -478,13 +523,24 @@ def _inject_repo_keys(fast_data):
478
523
 
479
524
 
480
525
  def collect_fast_data():
481
- """Tier 1: collect fleet, drift, and audit data. Runs at startup and on Refresh."""
526
+ """Tier 1: collect fleet, drift, and audit data. Runs at startup and on Refresh.
527
+
528
+ Fleet-report, drift, and audit are enterprise-only scripts. They degrade
529
+ gracefully when absent (Individual wheel does not ship them).
530
+ """
482
531
  data = {
483
532
  "generated_at": datetime.now(tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
484
- "fleet": run_json("gator-fleet-report"),
485
- "drift": run_json("gator-drift"),
486
- "audit": run_json("gator-audit"),
487
533
  }
534
+ # Enterprise-only scripts — degrade gracefully if not present
535
+ fleet_data = run_json("gator-fleet-report")
536
+ if fleet_data and "error" not in fleet_data:
537
+ data["fleet"] = fleet_data
538
+ drift_data = run_json("gator-drift")
539
+ if drift_data and "error" not in drift_data:
540
+ data["drift"] = drift_data
541
+ audit_data = run_json("gator-audit")
542
+ if audit_data and "error" not in audit_data:
543
+ data["audit"] = audit_data
488
544
  data = _inject_command_post(data)
489
545
  return _inject_repo_keys(data)
490
546
 
@@ -528,6 +584,8 @@ def collect_standalone_data():
528
584
  "session_summary_count": status.get("session_summary_count", 0),
529
585
  "override_events": status.get("override_events", []),
530
586
  })
587
+ elif status and status.get("error"):
588
+ repo_data["status_error"] = status["error"]
531
589
  repos.append(repo_data)
532
590
  return {
533
591
  "standalone": True,
@@ -630,11 +688,28 @@ class DashboardHandler(BaseHTTPRequestHandler):
630
688
  self._send_json({"status": "already_refreshing"})
631
689
  return
632
690
 
633
- # Session summaries — lazy / on-demand aggregation
691
+ # Session summaries — lazy / on-demand aggregation (enterprise)
634
692
  if path == "/api/audit/sessions":
635
693
  self._handle_audit_sessions()
636
694
  return
637
695
 
696
+ # Commit history — git log based, no session dependency
697
+ if path.startswith("/api/repo/") and path.endswith("/history"):
698
+ repo_name = path[len("/api/repo/"):-len("/history")]
699
+ if not repo_name:
700
+ self._send_json({"error": "repo name required"}, 400)
701
+ return
702
+ repo_path = _resolve_repo_path(repo_name)
703
+ if not repo_path or not Path(repo_path).is_dir():
704
+ self._send_json({"error": "repo not accessible"}, 400)
705
+ return
706
+ from urllib.parse import urlparse, parse_qs
707
+ qs = parse_qs(urlparse(self.path).query)
708
+ limit = int(qs.get("limit", ["20"])[0])
709
+ commits = _get_repo_history(repo_path, limit)
710
+ self._send_json({"commits": commits, "repo": repo_name})
711
+ return
712
+
638
713
  # Cross-document search — server-side grep
639
714
  if path.startswith("/api/repo/") and path.endswith("/search"):
640
715
  repo_name = path[len("/api/repo/"):-len("/search")]
@@ -1348,7 +1423,15 @@ def build_snapshot():
1348
1423
  html = _read_asset("dashboard.html")
1349
1424
  css = _read_asset("dashboard.css")
1350
1425
  fleet_js = _read_asset("views/fleet.js")
1351
- audit_js = _read_asset("views/audit.js")
1426
+ # history.js replaces audit.js in Individual; read whichever exists
1427
+ history_path = DASHBOARD_DIR / "views" / "history.js"
1428
+ audit_path = DASHBOARD_DIR / "views" / "audit.js"
1429
+ if history_path.exists():
1430
+ history_or_audit_js = history_path.read_text(encoding="utf-8")
1431
+ elif audit_path.exists():
1432
+ history_or_audit_js = audit_path.read_text(encoding="utf-8")
1433
+ else:
1434
+ history_or_audit_js = ""
1352
1435
  repo_js = _read_asset("views/repo.js")
1353
1436
  updates_js = _read_asset("views/updates.js")
1354
1437
  settings_js = _read_asset("views/settings.js")
@@ -1372,10 +1455,10 @@ def build_snapshot():
1372
1455
  html,
1373
1456
  )
1374
1457
 
1375
- # Replace the four script tags (with any leading whitespace) with inlined versions
1458
+ # Replace the view script tags with inlined versions
1376
1459
  scripts_block = (
1377
1460
  f"\n<script>\n{fleet_js}\n</script>\n"
1378
- f"<script>\n{audit_js}\n</script>\n"
1461
+ f"<script>\n{history_or_audit_js}\n</script>\n"
1379
1462
  f"<script>\n{repo_js}\n</script>\n"
1380
1463
  f"<script>\n{updates_js}\n</script>\n"
1381
1464
  f"<script>\n{settings_js}\n</script>\n"
@@ -1384,7 +1467,7 @@ def build_snapshot():
1384
1467
  )
1385
1468
  html = _re.sub(
1386
1469
  r'\s*<script src="views/fleet\.js"></script>\s*'
1387
- r'<script src="views/audit\.js"></script>\s*'
1470
+ r'<script src="views/history\.js"></script>\s*'
1388
1471
  r'<script src="views/repo\.js"></script>\s*'
1389
1472
  r'<script src="views/updates\.js"></script>\s*'
1390
1473
  r'<script src="views/settings\.js"></script>\s*'
@@ -356,33 +356,90 @@ def ensure_gitkeep_dirs(base_dir, dir_names, dry_run=False):
356
356
  (path / ".gitkeep").touch()
357
357
 
358
358
 
359
- def copy_matching_files(src_dir, dest_dir, suffixes, results, result_prefix, dry_run=False):
359
+ # Enterprise-only files excluded from public deploy.
360
+ # These stay in the source tree but never enter the public gator repo.
361
+ ENTERPRISE_ONLY_SCRIPTS = {
362
+ "gator-session-block.py",
363
+ "gator-session-aggregator.py",
364
+ "gator-session-sink.py",
365
+ "gator-session-common.py",
366
+ "gator-sessions.py",
367
+ "gator-session-start.py",
368
+ "gator-pre-commit.py",
369
+ "gator-audit.py",
370
+ "gator-audit-renderers.py",
371
+ "gator-fleet-report.py",
372
+ "gator-fleet-intel.py",
373
+ "gator-drift.py",
374
+ "extract-claude-sessions.py",
375
+ "extract-codex-sessions.py",
376
+ "extract-gemini-sessions.py",
377
+ }
378
+
379
+ ENTERPRISE_ONLY_TESTS = {
380
+ "test_session_block.py",
381
+ "test_session_sink.py",
382
+ "test_session_start.py",
383
+ "test_session_aggregator.py",
384
+ "test_sessions.py",
385
+ "test_dashboard_sessions.py",
386
+ "test_audit.py",
387
+ "test_audit_integration.py",
388
+ }
389
+
390
+ ENTERPRISE_ONLY_TEMPLATES = {
391
+ "gator-session-start.py",
392
+ }
393
+
394
+ ENTERPRISE_ONLY_TEMPLATE_DIRS = {
395
+ "vendor-hooks",
396
+ }
397
+
398
+
399
+ def copy_matching_files(src_dir, dest_dir, suffixes, results, result_prefix,
400
+ dry_run=False, exclude=None):
360
401
  """Copy files from a directory when their suffix matches."""
361
402
  if not dry_run:
362
403
  dest_dir.mkdir(parents=True, exist_ok=True)
363
404
 
405
+ exclude = exclude or set()
364
406
  for src in sorted(src_dir.iterdir()):
365
- if src.is_file() and src.suffix in suffixes:
407
+ if src.is_file() and src.suffix in suffixes and src.name not in exclude:
366
408
  copy_file(src, dest_dir / src.name, dry_run)
367
409
  results["created"].append(f"{result_prefix}/{src.name}")
368
410
 
369
411
 
370
412
  def copy_optional_tree(src_dir, dest_dir, results, result_label, dry_run=False,
371
- overlay=False):
413
+ overlay=False, exclude_files=None, exclude_dirs=None):
372
414
  """Copy a directory if it exists and record a concise result label.
373
415
 
374
416
  overlay=False (default): mirror mode — exact copy, prune stale files.
375
417
  Use for product-owned directories.
376
418
  overlay=True: overlay mode — update same-named, preserve extras.
377
419
  Use for user-owned directories.
420
+ exclude_files: set of filenames to skip during copy.
421
+ exclude_dirs: set of directory names to skip during copy.
378
422
  """
379
423
  if not src_dir.is_dir():
380
424
  return
381
425
  if overlay:
382
426
  copy_tree_overlay(src_dir, dest_dir, dry_run)
383
427
  else:
384
- copy_tree_mirror(src_dir, dest_dir, dry_run)
385
- count = sum(1 for item in src_dir.rglob("*") if item.is_file())
428
+ # Build ignore function combining standard ignores and enterprise excludes
429
+ ignore_patterns = ["__pycache__", "*.pyc"]
430
+ if exclude_files or exclude_dirs:
431
+ all_excludes = set(exclude_files or set()) | set(exclude_dirs or set())
432
+ def _ignore(directory, contents):
433
+ ignored = set(shutil.ignore_patterns(*ignore_patterns)(directory, contents))
434
+ return ignored | (all_excludes & set(contents))
435
+ if not dry_run:
436
+ dest_dir.parent.mkdir(parents=True, exist_ok=True)
437
+ if dest_dir.exists():
438
+ shutil.rmtree(dest_dir)
439
+ shutil.copytree(src_dir, dest_dir, ignore=_ignore)
440
+ else:
441
+ copy_tree_mirror(src_dir, dest_dir, dry_run)
442
+ count = sum(1 for item in dest_dir.rglob("*") if item.is_file()) if dest_dir.exists() else 0
386
443
  results["created"].append(f"{result_label} ({count} files)")
387
444
 
388
445
 
@@ -441,6 +498,7 @@ def build_engine(source, target, results, dry_run=False):
441
498
  results,
442
499
  "gator-engine/scripts",
443
500
  dry_run,
501
+ exclude=ENTERPRISE_ONLY_SCRIPTS,
444
502
  )
445
503
 
446
504
  copy_optional_tree(
@@ -449,6 +507,7 @@ def build_engine(source, target, results, dry_run=False):
449
507
  results,
450
508
  "gator-engine/scripts/dashboard/",
451
509
  dry_run,
510
+ exclude_files={"audit.js"},
452
511
  )
453
512
  copy_optional_tree(
454
513
  pkg / "templates" / "gator-starter",
@@ -456,6 +515,8 @@ def build_engine(source, target, results, dry_run=False):
456
515
  results,
457
516
  "gator-engine/templates/gator-starter/",
458
517
  dry_run,
518
+ exclude_files=ENTERPRISE_ONLY_TEMPLATES,
519
+ exclude_dirs=ENTERPRISE_ONLY_TEMPLATE_DIRS,
459
520
  )
460
521
  copy_optional_tree(
461
522
  source / "tests",
@@ -463,6 +524,7 @@ def build_engine(source, target, results, dry_run=False):
463
524
  results,
464
525
  "gator-engine/tests/",
465
526
  dry_run,
527
+ exclude_files=ENTERPRISE_ONLY_TESTS,
466
528
  )
467
529
  _fixup_test_paths(engine / "tests", dry_run)
468
530