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.
- gator_command/__init__.py +2 -0
- gator_command/cli.py +137 -0
- gator_command/scripts/crawler.py +633 -0
- gator_command/scripts/dashboard/dashboard.css +982 -0
- gator_command/scripts/dashboard/dashboard.html +84 -0
- gator_command/scripts/dashboard/dashboard.js +419 -0
- gator_command/scripts/dashboard/views/audit.js +270 -0
- gator_command/scripts/dashboard/views/fleet.js +307 -0
- gator_command/scripts/dashboard/views/repo.js +599 -0
- gator_command/scripts/dashboard/views/settings.js +173 -0
- gator_command/scripts/dashboard/views/updates.js +308 -0
- gator_command/scripts/enforcer-prompt.md +22 -0
- gator_command/scripts/extract-claude-sessions.py +489 -0
- gator_command/scripts/extract-codex-sessions.py +477 -0
- gator_command/scripts/extract-gemini-sessions.py +410 -0
- gator_command/scripts/gator-audit.py +956 -0
- gator_command/scripts/gator-charter-draft.py +919 -0
- gator_command/scripts/gator-charter-lint.py +427 -0
- gator_command/scripts/gator-charter-verify.py +606 -0
- gator_command/scripts/gator-dashboard.py +1271 -0
- gator_command/scripts/gator-deploy.py +916 -0
- gator_command/scripts/gator-drift.py +569 -0
- gator_command/scripts/gator-enforce.py +82 -0
- gator_command/scripts/gator-fleet-intel.py +460 -0
- gator_command/scripts/gator-fleet-report.py +615 -0
- gator_command/scripts/gator-init-command-post.py +315 -0
- gator_command/scripts/gator-init.py +434 -0
- gator_command/scripts/gator-machine-id.py +153 -0
- gator_command/scripts/gator-policy-status.py +631 -0
- gator_command/scripts/gator-pulse.py +459 -0
- gator_command/scripts/gator-repo-status.py +649 -0
- gator_command/scripts/gator-session-common.py +372 -0
- gator_command/scripts/gator-session-sink.py +831 -0
- gator_command/scripts/gator-sessions.py +1244 -0
- gator_command/scripts/gator-update.py +615 -0
- gator_command/scripts/gator-version.py +38 -0
- gator_command/scripts/gator_core.py +489 -0
- gator_command/scripts/gator_remote.py +381 -0
- gator_command/scripts/gator_runtime.py +142 -0
- gator_command/scripts/gatorize-actions.sh +989 -0
- gator_command/scripts/gatorize-lib.sh +166 -0
- gator_command/scripts/gatorize-post.sh +394 -0
- gator_command/scripts/gatorize.py +1163 -0
- gator_command/scripts/gatorize.sh +185 -0
- gator_command/scripts/generate_markdown.py +212 -0
- gator_command/scripts/generate_wiki.py +424 -0
- gator_command/scripts/graph_health.py +780 -0
- gator_command/scripts/memex-lint.py +286 -0
- gator_command/scripts/memex-lint.sh +205 -0
- gator_command/scripts/memex.py +1472 -0
- gator_command/scripts/memex_formatters.py +191 -0
- gator_command/scripts/memex_state.py +236 -0
- gator_command/scripts/spawn.py +650 -0
- gator_command/templates/gator-starter/blueprints/README.md +32 -0
- gator_command/templates/gator-starter/charterignore +53 -0
- gator_command/templates/gator-starter/charters/README.md +178 -0
- gator_command/templates/gator-starter/charters/_template.md +31 -0
- gator_command/templates/gator-starter/commands/commit.md +33 -0
- gator_command/templates/gator-starter/commands/init.md +11 -0
- gator_command/templates/gator-starter/commands/update.md +5 -0
- gator_command/templates/gator-starter/constitution.md +165 -0
- gator_command/templates/gator-starter/field-guides/README.md +25 -0
- gator_command/templates/gator-starter/gator-start-up.md +119 -0
- gator_command/templates/gator-starter/procedures/charter-alignment.md +83 -0
- gator_command/templates/gator-starter/procedures/enforcer-review.md +317 -0
- gator_command/templates/gator-starter/procedures/field-guide-generation.md +176 -0
- gator_command/templates/gator-starter/procedures/knowledge-capture.md +57 -0
- gator_command/templates/gator-starter/procedures/significance-check.md +69 -0
- gator_command/templates/gator-starter/reference-notes/concierge-responses.md +535 -0
- gator_command/templates/gator-starter/reference-notes/dangerous-patterns.md +91 -0
- gator_command/templates/gator-starter/reference-notes/dashboard-operations.md +22 -0
- gator_command/templates/gator-starter/reference-notes/enforcer-configuration.md +232 -0
- gator_command/templates/gator-starter/reference-notes/example-project.md +289 -0
- gator_command/templates/gator-starter/reference-notes/failure-modes-and-self-correction.md +72 -0
- gator_command/templates/gator-starter/reference-notes/git-workflow.md +60 -0
- gator_command/templates/gator-starter/reference-notes/identity-and-ownership.md +37 -0
- gator_command/templates/gator-starter/reference-notes/refactor-approach.md +155 -0
- gator_command/templates/gator-starter/reference-notes/what-gator-requires-from-a-model.md +108 -0
- gator_command/templates/gator-starter/reference-notes/why-navigation-coding-feels-different.md +99 -0
- gator_command/templates/gator-starter/reference-notes/workflow-profiles.md +155 -0
- gator_command/templates/gator-starter/scripts/__pycache__/enforcer-review.cpython-313.pyc +0 -0
- gator_command/templates/gator-starter/scripts/__pycache__/gator-approve.cpython-313.pyc +0 -0
- gator_command/templates/gator-starter/scripts/__pycache__/gator-init.cpython-313.pyc +0 -0
- gator_command/templates/gator-starter/scripts/__pycache__/gator-pre-commit.cpython-313.pyc +0 -0
- gator_command/templates/gator-starter/scripts/__pycache__/gator-update.cpython-313.pyc +0 -0
- gator_command/templates/gator-starter/scripts/enforcer-prompt.md +55 -0
- gator_command/templates/gator-starter/scripts/enforcer-review.py +1551 -0
- gator_command/templates/gator-starter/scripts/gator-approve.py +139 -0
- gator_command/templates/gator-starter/scripts/gator-enforce.py +82 -0
- gator_command/templates/gator-starter/scripts/gator-init.py +434 -0
- gator_command/templates/gator-starter/scripts/gator-pre-commit.py +2670 -0
- gator_command/templates/gator-starter/scripts/gator-pulse.py +459 -0
- gator_command/templates/gator-starter/scripts/gator-update.py +615 -0
- gator_command/templates/gator-starter/scripts/gator-version.py +38 -0
- gator_command/templates/gator-starter/scripts/gator_core.py +487 -0
- gator_command/templates/gator-starter/scripts/hooks/__pycache__/commit-msgcpython-313.pyc +0 -0
- gator_command/templates/gator-starter/scripts/hooks/__pycache__/post-commitcpython-313.pyc +0 -0
- gator_command/templates/gator-starter/scripts/hooks/__pycache__/pre-commitcpython-313.pyc +0 -0
- gator_command/templates/gator-starter/scripts/hooks/commit-msg +5 -0
- gator_command/templates/gator-starter/scripts/hooks/post-commit +7 -0
- gator_command/templates/gator-starter/scripts/hooks/pre-commit +5 -0
- gator_command/templates/gator-starter/sessions/.gitignore +7 -0
- gator_command/templates/gator-starter/vault/.gitkeep +0 -0
- gator_command/templates/gator-starter/whiteboard.md +5 -0
- gator_command-1.0.0.dist-info/METADATA +122 -0
- gator_command-1.0.0.dist-info/RECORD +110 -0
- gator_command-1.0.0.dist-info/WHEEL +5 -0
- gator_command-1.0.0.dist-info/entry_points.txt +2 -0
- gator_command-1.0.0.dist-info/licenses/LICENSE +21 -0
- 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()
|