gator-command 1.0.0__py3-none-any.whl

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 (110) hide show
  1. gator_command/__init__.py +2 -0
  2. gator_command/cli.py +137 -0
  3. gator_command/scripts/crawler.py +633 -0
  4. gator_command/scripts/dashboard/dashboard.css +982 -0
  5. gator_command/scripts/dashboard/dashboard.html +84 -0
  6. gator_command/scripts/dashboard/dashboard.js +419 -0
  7. gator_command/scripts/dashboard/views/audit.js +270 -0
  8. gator_command/scripts/dashboard/views/fleet.js +307 -0
  9. gator_command/scripts/dashboard/views/repo.js +599 -0
  10. gator_command/scripts/dashboard/views/settings.js +173 -0
  11. gator_command/scripts/dashboard/views/updates.js +308 -0
  12. gator_command/scripts/enforcer-prompt.md +22 -0
  13. gator_command/scripts/extract-claude-sessions.py +489 -0
  14. gator_command/scripts/extract-codex-sessions.py +477 -0
  15. gator_command/scripts/extract-gemini-sessions.py +410 -0
  16. gator_command/scripts/gator-audit.py +956 -0
  17. gator_command/scripts/gator-charter-draft.py +919 -0
  18. gator_command/scripts/gator-charter-lint.py +427 -0
  19. gator_command/scripts/gator-charter-verify.py +606 -0
  20. gator_command/scripts/gator-dashboard.py +1271 -0
  21. gator_command/scripts/gator-deploy.py +916 -0
  22. gator_command/scripts/gator-drift.py +569 -0
  23. gator_command/scripts/gator-enforce.py +82 -0
  24. gator_command/scripts/gator-fleet-intel.py +460 -0
  25. gator_command/scripts/gator-fleet-report.py +615 -0
  26. gator_command/scripts/gator-init-command-post.py +315 -0
  27. gator_command/scripts/gator-init.py +434 -0
  28. gator_command/scripts/gator-machine-id.py +153 -0
  29. gator_command/scripts/gator-policy-status.py +631 -0
  30. gator_command/scripts/gator-pulse.py +459 -0
  31. gator_command/scripts/gator-repo-status.py +649 -0
  32. gator_command/scripts/gator-session-common.py +372 -0
  33. gator_command/scripts/gator-session-sink.py +831 -0
  34. gator_command/scripts/gator-sessions.py +1244 -0
  35. gator_command/scripts/gator-update.py +615 -0
  36. gator_command/scripts/gator-version.py +38 -0
  37. gator_command/scripts/gator_core.py +489 -0
  38. gator_command/scripts/gator_remote.py +381 -0
  39. gator_command/scripts/gator_runtime.py +142 -0
  40. gator_command/scripts/gatorize-actions.sh +989 -0
  41. gator_command/scripts/gatorize-lib.sh +166 -0
  42. gator_command/scripts/gatorize-post.sh +394 -0
  43. gator_command/scripts/gatorize.py +1163 -0
  44. gator_command/scripts/gatorize.sh +185 -0
  45. gator_command/scripts/generate_markdown.py +212 -0
  46. gator_command/scripts/generate_wiki.py +424 -0
  47. gator_command/scripts/graph_health.py +780 -0
  48. gator_command/scripts/memex-lint.py +286 -0
  49. gator_command/scripts/memex-lint.sh +205 -0
  50. gator_command/scripts/memex.py +1472 -0
  51. gator_command/scripts/memex_formatters.py +191 -0
  52. gator_command/scripts/memex_state.py +236 -0
  53. gator_command/scripts/spawn.py +650 -0
  54. gator_command/templates/gator-starter/blueprints/README.md +32 -0
  55. gator_command/templates/gator-starter/charterignore +53 -0
  56. gator_command/templates/gator-starter/charters/README.md +178 -0
  57. gator_command/templates/gator-starter/charters/_template.md +31 -0
  58. gator_command/templates/gator-starter/commands/commit.md +33 -0
  59. gator_command/templates/gator-starter/commands/init.md +11 -0
  60. gator_command/templates/gator-starter/commands/update.md +5 -0
  61. gator_command/templates/gator-starter/constitution.md +165 -0
  62. gator_command/templates/gator-starter/field-guides/README.md +25 -0
  63. gator_command/templates/gator-starter/gator-start-up.md +119 -0
  64. gator_command/templates/gator-starter/procedures/charter-alignment.md +83 -0
  65. gator_command/templates/gator-starter/procedures/enforcer-review.md +317 -0
  66. gator_command/templates/gator-starter/procedures/field-guide-generation.md +176 -0
  67. gator_command/templates/gator-starter/procedures/knowledge-capture.md +57 -0
  68. gator_command/templates/gator-starter/procedures/significance-check.md +69 -0
  69. gator_command/templates/gator-starter/reference-notes/concierge-responses.md +535 -0
  70. gator_command/templates/gator-starter/reference-notes/dangerous-patterns.md +91 -0
  71. gator_command/templates/gator-starter/reference-notes/dashboard-operations.md +22 -0
  72. gator_command/templates/gator-starter/reference-notes/enforcer-configuration.md +232 -0
  73. gator_command/templates/gator-starter/reference-notes/example-project.md +289 -0
  74. gator_command/templates/gator-starter/reference-notes/failure-modes-and-self-correction.md +72 -0
  75. gator_command/templates/gator-starter/reference-notes/git-workflow.md +60 -0
  76. gator_command/templates/gator-starter/reference-notes/identity-and-ownership.md +37 -0
  77. gator_command/templates/gator-starter/reference-notes/refactor-approach.md +155 -0
  78. gator_command/templates/gator-starter/reference-notes/what-gator-requires-from-a-model.md +108 -0
  79. gator_command/templates/gator-starter/reference-notes/why-navigation-coding-feels-different.md +99 -0
  80. gator_command/templates/gator-starter/reference-notes/workflow-profiles.md +155 -0
  81. gator_command/templates/gator-starter/scripts/__pycache__/enforcer-review.cpython-313.pyc +0 -0
  82. gator_command/templates/gator-starter/scripts/__pycache__/gator-approve.cpython-313.pyc +0 -0
  83. gator_command/templates/gator-starter/scripts/__pycache__/gator-init.cpython-313.pyc +0 -0
  84. gator_command/templates/gator-starter/scripts/__pycache__/gator-pre-commit.cpython-313.pyc +0 -0
  85. gator_command/templates/gator-starter/scripts/__pycache__/gator-update.cpython-313.pyc +0 -0
  86. gator_command/templates/gator-starter/scripts/enforcer-prompt.md +55 -0
  87. gator_command/templates/gator-starter/scripts/enforcer-review.py +1551 -0
  88. gator_command/templates/gator-starter/scripts/gator-approve.py +139 -0
  89. gator_command/templates/gator-starter/scripts/gator-enforce.py +82 -0
  90. gator_command/templates/gator-starter/scripts/gator-init.py +434 -0
  91. gator_command/templates/gator-starter/scripts/gator-pre-commit.py +2670 -0
  92. gator_command/templates/gator-starter/scripts/gator-pulse.py +459 -0
  93. gator_command/templates/gator-starter/scripts/gator-update.py +615 -0
  94. gator_command/templates/gator-starter/scripts/gator-version.py +38 -0
  95. gator_command/templates/gator-starter/scripts/gator_core.py +487 -0
  96. gator_command/templates/gator-starter/scripts/hooks/__pycache__/commit-msgcpython-313.pyc +0 -0
  97. gator_command/templates/gator-starter/scripts/hooks/__pycache__/post-commitcpython-313.pyc +0 -0
  98. gator_command/templates/gator-starter/scripts/hooks/__pycache__/pre-commitcpython-313.pyc +0 -0
  99. gator_command/templates/gator-starter/scripts/hooks/commit-msg +5 -0
  100. gator_command/templates/gator-starter/scripts/hooks/post-commit +7 -0
  101. gator_command/templates/gator-starter/scripts/hooks/pre-commit +5 -0
  102. gator_command/templates/gator-starter/sessions/.gitignore +7 -0
  103. gator_command/templates/gator-starter/vault/.gitkeep +0 -0
  104. gator_command/templates/gator-starter/whiteboard.md +5 -0
  105. gator_command-1.0.0.dist-info/METADATA +122 -0
  106. gator_command-1.0.0.dist-info/RECORD +110 -0
  107. gator_command-1.0.0.dist-info/WHEEL +5 -0
  108. gator_command-1.0.0.dist-info/entry_points.txt +2 -0
  109. gator_command-1.0.0.dist-info/licenses/LICENSE +21 -0
  110. gator_command-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,315 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ gator init (command post) — Branded boot sequence for the Gator Command post.
4
+
5
+ Shows fleet-level status: registered repos with their gator generation,
6
+ charter coverage, active threads, inbox items, and issues. This is the
7
+ command-post counterpart to gator-init.py (which runs in governed repos).
8
+
9
+ Usage:
10
+ python gator-command/scripts/gator-init-command-post.py
11
+ python gator-command/scripts/gator-init-command-post.py --json
12
+
13
+ @reads: gator-command/ directory, registry.md, active-threads/, inbox.md, issues.md, roadmap.md
14
+ @reads: .gator/ in each registered repo (read-only fleet scan)
15
+ @writes: .git/hooks/ (self-heal only when hooks are missing or stale)
16
+ """
17
+
18
+ import argparse
19
+ import json
20
+ import re
21
+ import sys
22
+ from pathlib import Path
23
+
24
+ from gator_core import (
25
+ get_version, find_command_post, normalize_path, parse_registry,
26
+ ensure_utf8_stdout, import_sibling, GATOR_MARK_LINES,
27
+ )
28
+
29
+ VERSION = get_version()
30
+
31
+ TAGLINE = "command post online. fleet status follows."
32
+
33
+
34
+ def scan_repo(repo_entry):
35
+ """Scan a registered repo's .gator/ for status info.
36
+
37
+ @reads: .gator/ in the repo (read-only)
38
+ @does-not-own: modifying any fleet repo files
39
+ """
40
+ repo_path = Path(normalize_path(repo_entry["path"]))
41
+ gator_dir = repo_path / ".gator"
42
+
43
+ info = {
44
+ "name": repo_entry["name"],
45
+ "exists": repo_path.is_dir(),
46
+ "has_gator": gator_dir.is_dir(),
47
+ "generation": None,
48
+ "charters": 0,
49
+ "threads": 0,
50
+ "status_icon": "?",
51
+ }
52
+
53
+ if not info["exists"]:
54
+ # Repo not found locally — may be on a different machine
55
+ has_remote = repo_entry.get("remote", "—") not in ("—", "", None)
56
+ info["status_icon"] = "~" if has_remote else "?"
57
+ info["note"] = "remote only" if has_remote else "not found locally"
58
+ return info
59
+
60
+ if not info["has_gator"]:
61
+ info["status_icon"] = "✗"
62
+ info["note"] = "no .gator/"
63
+ return info
64
+
65
+ # Read generation
66
+ version_file = gator_dir / ".gator-version"
67
+ if version_file.exists():
68
+ for line in version_file.read_text(encoding="utf-8", errors="replace").splitlines():
69
+ if line.startswith("generation:"):
70
+ info["generation"] = line.split(":", 1)[1].strip()
71
+ elif (gator_dir / "command-post.md").exists():
72
+ info["generation"] = "1"
73
+ else:
74
+ info["generation"] = "0"
75
+
76
+ # Count charters
77
+ charters_dir = gator_dir / "charters"
78
+ if charters_dir.is_dir():
79
+ skip = {"_template.md", "README.md", "INDEX.md"}
80
+ info["charters"] = len([
81
+ f for f in charters_dir.iterdir()
82
+ if f.suffix == ".md" and f.name not in skip
83
+ ])
84
+
85
+ # Count threads
86
+ for subdir_name in ("active-threads", "threads"):
87
+ subdir = gator_dir / subdir_name
88
+ if subdir.is_dir():
89
+ info["threads"] += len([
90
+ f for f in subdir.iterdir()
91
+ if f.suffix == ".md" and f.name != ".gitkeep"
92
+ ])
93
+
94
+ info["status_icon"] = "✓"
95
+ return info
96
+
97
+
98
+ # --- Command post internals ---
99
+
100
+ def count_active_threads(command_post):
101
+ """Count active threads in the command post.
102
+
103
+ @reads: gator-command/active-threads/
104
+ """
105
+ threads_dir = command_post / "gator-command" / "active-threads"
106
+ if not threads_dir.is_dir():
107
+ return 0
108
+ return len([f for f in threads_dir.iterdir() if f.suffix == ".md"])
109
+
110
+
111
+ def count_inbox_items(command_post):
112
+ """Count pending inbox items.
113
+
114
+ @reads: gator-command/inbox.md
115
+ """
116
+ inbox = command_post / "gator-command" / "inbox.md"
117
+ if not inbox.exists():
118
+ return 0
119
+
120
+ count = 0
121
+ text = inbox.read_text(encoding="utf-8", errors="replace")
122
+ for line in text.splitlines():
123
+ if line.strip().startswith("- "):
124
+ count += 1
125
+ return count
126
+
127
+
128
+ def count_issues(command_post):
129
+ """Count open issues.
130
+
131
+ @reads: gator-command/issues.md
132
+ """
133
+ issues = command_post / "gator-command" / "issues.md"
134
+ if not issues.exists():
135
+ return 0
136
+
137
+ count = 0
138
+ text = issues.read_text(encoding="utf-8", errors="replace")
139
+ for line in text.splitlines():
140
+ if "**Status**: Open" in line or "**Status**: Working" in line:
141
+ count += 1
142
+ return count
143
+
144
+
145
+ def count_artifacts(command_post):
146
+ """Count artifacts.
147
+
148
+ @reads: gator-command/artifacts/
149
+ """
150
+ artifacts_dir = command_post / "gator-command" / "artifacts"
151
+ if not artifacts_dir.is_dir():
152
+ return 0
153
+ return len([f for f in artifacts_dir.iterdir() if f.suffix == ".md"])
154
+
155
+
156
+ # --- Hook self-heal ---
157
+
158
+ def _ensure_own_hooks(command_post):
159
+ """Self-heal git hooks for the command post's own repo.
160
+
161
+ The command post is itself a governed repo. Delegates to
162
+ gator-init.ensure_git_hooks() so hook format stays centralized.
163
+ """
164
+ gator_dir = command_post / ".gator"
165
+ if not gator_dir.is_dir():
166
+ return {"status": "unavailable", "detail": "no .gator/", "adds": 0, "updates": 0}
167
+
168
+ try:
169
+ gator_init = import_sibling("gator-init")
170
+ except ImportError:
171
+ return {"status": "error", "detail": "gator-init.py not found", "adds": 0, "updates": 0}
172
+ if gator_init is None:
173
+ return {"status": "error", "detail": "gator-init.py not found", "adds": 0, "updates": 0}
174
+
175
+ return gator_init.ensure_git_hooks(command_post, gator_dir)
176
+
177
+
178
+ # --- Output formatting ---
179
+
180
+ def format_check(label, value, width=16):
181
+ """Format a single status line."""
182
+ return f" \u2713 {label:<{width}}{value}"
183
+
184
+
185
+ def format_repo_line(info):
186
+ """Format a single fleet repo status line."""
187
+ icon = info["status_icon"]
188
+ name = info["name"]
189
+
190
+ # If repo isn't locally available, show the note instead of details
191
+ if "note" in info:
192
+ return f" {icon} {name:<20}{info['note']}"
193
+
194
+ gen = f"gen {info['generation']}" if info["generation"] else "unknown"
195
+
196
+ parts = []
197
+ if info["charters"] > 0:
198
+ parts.append(f"{info['charters']} charters")
199
+ if info["threads"] > 0:
200
+ parts.append(f"{info['threads']} threads")
201
+
202
+ detail = " \u00b7 ".join(parts) if parts else "fresh"
203
+
204
+ return f" {icon} {name:<20}{gen:<8}{detail}"
205
+
206
+
207
+ def print_boot_sequence(command_post, hook_status):
208
+ """Print the command-post boot sequence.
209
+
210
+ @reads: all detection functions above
211
+ @writes: stdout
212
+ """
213
+ # Header
214
+ print()
215
+ for line in GATOR_MARK_LINES:
216
+ print(f" {line}")
217
+ print()
218
+ print(f" {VERSION} · navigation coding, governed")
219
+ print()
220
+ print(f" $ gator init")
221
+ print()
222
+
223
+ # Command post status
224
+ thread_count = count_active_threads(command_post)
225
+ inbox_count = count_inbox_items(command_post)
226
+ issue_count = count_issues(command_post)
227
+ artifact_count = count_artifacts(command_post)
228
+
229
+ print(f" command post online")
230
+ print()
231
+ print(format_check("active threads", f"{thread_count}"))
232
+ print(format_check("inbox", f"{inbox_count} items pending" if inbox_count > 0 else "clear"))
233
+ print(format_check("issues", f"{issue_count} open" if issue_count > 0 else "none"))
234
+ print(format_check("artifacts", f"{artifact_count}"))
235
+ print(format_check("hooks", hook_status["detail"]))
236
+
237
+ # Fleet
238
+ repos = parse_registry(command_post)
239
+ if repos:
240
+ print()
241
+ print(f" fleet: {len(repos)} repos")
242
+ print()
243
+ for entry in repos:
244
+ info = scan_repo(entry)
245
+ print(format_repo_line(info))
246
+
247
+ # Tagline
248
+ print()
249
+ print(f" {TAGLINE}")
250
+ print(f" \u25b8")
251
+ print()
252
+
253
+
254
+ def print_json(command_post, hook_status):
255
+ """Print command post status as JSON."""
256
+ repos = parse_registry(command_post)
257
+ fleet = [scan_repo(entry) for entry in repos]
258
+
259
+ data = {
260
+ "version": VERSION,
261
+ "type": "command-post",
262
+ "active_threads": count_active_threads(command_post),
263
+ "inbox_items": count_inbox_items(command_post),
264
+ "open_issues": count_issues(command_post),
265
+ "artifacts": count_artifacts(command_post),
266
+ "hooks": hook_status,
267
+ "fleet": fleet,
268
+ }
269
+
270
+ print(json.dumps(data, indent=2))
271
+
272
+
273
+ # --- Entry point ---
274
+
275
+ def main():
276
+ ensure_utf8_stdout()
277
+
278
+ parser = argparse.ArgumentParser(
279
+ description="Gator init (command post) — fleet-level boot sequence."
280
+ )
281
+ parser.add_argument(
282
+ "--path", "-p",
283
+ help="Path to the command post (default: current directory)",
284
+ )
285
+ parser.add_argument(
286
+ "--json", "-j",
287
+ action="store_true",
288
+ help="Output as JSON instead of formatted display",
289
+ )
290
+ args = parser.parse_args()
291
+
292
+ command_post = find_command_post(args.path)
293
+
294
+ if not command_post:
295
+ print()
296
+ for line in GATOR_MARK_LINES:
297
+ print(f" {line}")
298
+ print()
299
+ print(f" {VERSION} · navigation coding, governed")
300
+ print()
301
+ print(" no command post found.")
302
+ print()
303
+ sys.exit(1)
304
+
305
+ # Self-heal hooks for the command post's own repo
306
+ hook_status = _ensure_own_hooks(command_post)
307
+
308
+ if args.json:
309
+ print_json(command_post, hook_status)
310
+ else:
311
+ print_boot_sequence(command_post, hook_status)
312
+
313
+
314
+ if __name__ == "__main__":
315
+ main()