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,91 @@
1
+ # Dangerous Patterns Reference
2
+
3
+ Patterns the agent must surface to the Architect before writing, running, or committing. This applies to all session activity — not just commits.
4
+
5
+ The pre-commit hook catches these mechanically at commit time. This reference note governs agent behavior *during* the session: writing scripts, running commands, debugging, executing code.
6
+
7
+ **Rule**: If the agent encounters any of these patterns in code it is about to write or execute, it stops and asks the Architect before proceeding. If the Architect approves, the agent logs the approval in `commit_draft.md`.
8
+
9
+ ## Credentials in the Conversation (Highest Priority)
10
+
11
+ This is not a code pattern — it's a conversation-level security boundary.
12
+
13
+ **If the Architect pastes a password, API key, token, private key, or any secret directly into a chat message, the agent must immediately stop and warn:**
14
+
15
+ > **STOP — Credential Exposure**
16
+ > The credential you just pasted has been transmitted to [provider] via the API request. It should be considered compromised regardless of what happens next. Rotate this credential immediately. I will not use, store, or repeat it.
17
+
18
+ **Why this is the highest priority pattern**: Every other dangerous pattern in this catalog can be caught before damage occurs. A credential pasted into the conversation is compromised *the instant the message is sent* — before the agent even sees it. There is no undo. The credential is in the provider's request logs, potentially in training data pipelines, and must be treated as leaked.
19
+
20
+ The agent cannot prevent the exposure (it happens before the agent responds), but it can:
21
+ 1. Warn immediately so the Architect rotates fast
22
+ 2. Refuse to use the credential (don't embed it in code, don't pass it to scripts)
23
+ 3. Not repeat the credential in its response (avoid amplifying the exposure)
24
+
25
+ **Common scenarios**: Architect debugging auth failures pastes the raw token. Architect setting up a new service pastes the API key. Architect shares a `.env` file contents. Architect copies a database connection string with embedded password. All of these are compromised on paste.
26
+
27
+ ## Secrets & Credentials (in Code)
28
+
29
+ | Pattern | Why it's dangerous |
30
+ |---|---|
31
+ | Hardcoded passwords (`password = "..."`) | Credentials in source code leak via git history, logs, and clones |
32
+ | API keys/tokens in source (`api_key = "sk-..."`) | Same as passwords — once committed, consider them compromised |
33
+ | Private key material (`-----BEGIN PRIVATE KEY-----`) | Cryptographic keys in source are permanent compromise vectors |
34
+ | `.env` files in commits | Environment files contain secrets that should never enter version control |
35
+
36
+ ## Destructive Data Operations
37
+
38
+ | Pattern | Why it's dangerous |
39
+ |---|---|
40
+ | `DROP TABLE` | Destroys table and all data. Irreversible without backup |
41
+ | `DELETE FROM` without `WHERE` | Deletes all rows in a table. Usually a mistake |
42
+ | `TRUNCATE TABLE` | Fast bulk deletion. Irreversible, not logged in transaction log on some DBs |
43
+ | `ALTER TABLE ... DROP COLUMN` | Destroys column data. May break dependent queries silently |
44
+ | `UPDATE` without `WHERE` | Overwrites all rows. Usually a mistake |
45
+
46
+ ## Code Execution Risks
47
+
48
+ | Pattern | Why it's dangerous |
49
+ |---|---|
50
+ | `eval()` | Executes arbitrary code. If input is untrusted, this is remote code execution |
51
+ | `exec()` | Same as eval but for statements. Same risk |
52
+ | `subprocess` with `shell=True` | Shell injection — user input can escape into shell commands |
53
+ | `os.system()` | Same as shell=True subprocess but harder to parameterize safely |
54
+ | SQL string concatenation (`f"SELECT ... {user_input}"`) | SQL injection. Use parameterized queries |
55
+
56
+ ## Destructive System Operations
57
+
58
+ | Pattern | Why it's dangerous |
59
+ |---|---|
60
+ | `rm -rf` / `shutil.rmtree()` | Recursive deletion. One wrong path = catastrophic data loss |
61
+ | `git reset --hard` | Discards all uncommitted changes. Cannot be undone |
62
+ | `git push --force` | Overwrites remote history. Can destroy other people's work |
63
+ | `git clean -f` | Deletes untracked files. May include work not yet staged |
64
+ | `chmod 777` / wide-open permissions | Security regression — makes files world-writable |
65
+ | Disk formatting / partition operations | Catastrophic and irreversible |
66
+
67
+ ## Network & External Service Risks
68
+
69
+ | Pattern | Why it's dangerous |
70
+ |---|---|
71
+ | Sending emails/messages programmatically | Can't unsend. May go to wrong recipients |
72
+ | API calls that create/delete external resources | Cloud resources cost money and may be hard to recover |
73
+ | Webhook registrations | May expose internal systems to external triggers |
74
+ | DNS changes | Propagation delays make mistakes hard to reverse quickly |
75
+
76
+ ## What the Agent Does
77
+
78
+ 1. **Before writing**: If the agent is about to write code containing a dangerous pattern, it tells the Architect what it's about to write and why, and waits for confirmation.
79
+
80
+ 2. **Before executing**: If the agent is about to run a script, command, or test that contains a dangerous pattern (even if the code already exists), it surfaces the pattern and waits. This is especially important during debugging — "let me just run the migration script to see what happens" is exactly when accidents occur.
81
+
82
+ 3. **After Architect approval**: Log the approval in `commit_draft.md` with the pattern, the file, and the Architect's attribution. Example:
83
+ ```
84
+ - Architect approved DELETE FROM in tests/cleanup.py — test fixture teardown [#security] [#decision] — AG
85
+ ```
86
+
87
+ 4. **When in doubt**: Surface it. A false pause costs seconds. A missed destructive action costs hours, data, or reputation.
88
+
89
+ ## What This Is Not
90
+
91
+ This is not a ban on dangerous patterns. Migrations need `DROP TABLE`. Tests need `eval()`. Deployment scripts need `rm -rf`. The rule is not "never use these" — it's "never use these without the Architect knowing and approving."
@@ -0,0 +1,22 @@
1
+ # Dashboard Operations
2
+
3
+ Notes on launching and operating the Gator Dashboard from an agent session.
4
+
5
+ ## Launching
6
+
7
+ ```
8
+ python .gator/scripts/gator-dashboard.py
9
+ ```
10
+
11
+ The script starts an HTTP server on port 8420, opens the browser, and enters `serve_forever()`. It works on the first invocation. Do not retry or attempt to verify the launch -- the server process stays alive but agent tooling may incorrectly report it as "completed" because only the startup banner is captured before the event loop takes over.
12
+
13
+ **Known false signal**: background task tracking (Claude Code, Codex, other agent harnesses) can show the dashboard process as "completed" immediately after launch. This is a monitoring artifact, not a failure. The dashboard is running.
14
+
15
+ ## Flags
16
+
17
+ | Flag | Effect |
18
+ |------|--------|
19
+ | `--no-open` | Start server without opening browser |
20
+ | `--port N` | Use a specific port (default 8420, tries 8421-8429 on conflict) |
21
+ | `--snapshot` | Write self-contained HTML to stdout and exit (no server) |
22
+ | `--repo NAME` | Pre-load a specific repo view on open |
@@ -0,0 +1,232 @@
1
+ # Enforcer Configuration Guide
2
+
3
+ This reference note helps a primary agent configure an enforcer for the Architect. When the Architect asks "how do I set up an enforcer?" or hits step 5 for the first time, use this to figure out what they have available and walk them through it.
4
+
5
+ ## The Conversation to Have
6
+
7
+ Ask the Architect three things:
8
+
9
+ 1. **What's your primary agent?** (Claude, GPT/Codex, Gemini, etc.)
10
+ 2. **What API keys or CLI tools do you have?** (Anthropic, OpenAI, Google, or none)
11
+ 3. **How much do you care about cost?** (Determines model choice)
12
+
13
+ Then match to a config below.
14
+
15
+ ## Decision Tree
16
+
17
+ ```
18
+ Do you have any API key or CLI tool?
19
+ ├─ No → Mechanical lint only (Layer 1). Free, instant, no setup.
20
+ │ Consider ollama for free local charter-grounded review.
21
+
22
+ ├─ Yes → Is it the same vendor as your primary agent?
23
+ │ ├─ Yes → It works, but cross-vendor is stronger.
24
+ │ │ Same-vendor review is still better than nothing.
25
+ │ └─ No → Ideal. Different training = different blind spots.
26
+
27
+ └─ Multiple → Pick the one that's different from your primary agent.
28
+ ```
29
+
30
+ ## Configs by Enforcer
31
+
32
+ ### Sonnet (Anthropic)
33
+
34
+ **Best for**: Primary agent is GPT, Gemini, or any non-Anthropic model. Also fine as same-vendor enforcer when primary is Claude Opus — Sonnet is a different model with different trade-offs.
35
+
36
+ **What the Architect needs**: `ANTHROPIC_API_KEY` from [console.anthropic.com](https://console.anthropic.com)
37
+
38
+ **Cost**: Low. Sonnet is one of the cheapest capable models.
39
+
40
+ **Config** (`enforcer-config.json`) — this is the default, no changes needed:
41
+ ```json
42
+ {
43
+ "layer2_3": {
44
+ "provider": "anthropic",
45
+ "model": "claude-sonnet-4-6",
46
+ "api_key_env": "ANTHROPIC_API_KEY"
47
+ }
48
+ }
49
+ ```
50
+
51
+ **Setup steps**:
52
+ ```bash
53
+ pip install anthropic
54
+ export ANTHROPIC_API_KEY=sk-ant-... # macOS/Linux
55
+ # $env:ANTHROPIC_API_KEY = "sk-ant-..." # Windows PowerShell
56
+ ```
57
+
58
+ **Run**: `python .gator/scripts/enforcer-review.py`
59
+
60
+ **If the primary agent is Codex**: this is the cleanest way to use Anthropic as enforcer. The Python script applies the enforcer role directly and avoids any ambiguity from Claude CLI also seeing the repo's `CLAUDE.md`.
61
+
62
+ ### GPT (OpenAI) via Python script
63
+
64
+ **Best for**: Primary agent is Claude or Gemini.
65
+
66
+ **What the Architect needs**: `OPENAI_API_KEY` from [platform.openai.com](https://platform.openai.com)
67
+
68
+ **Cost**: `gpt-4o-mini` is very cheap. `gpt-4o` is moderate.
69
+
70
+ **Config**:
71
+ ```json
72
+ {
73
+ "layer2_3": {
74
+ "provider": "openai",
75
+ "model": "gpt-4o-mini",
76
+ "api_key_env": "OPENAI_API_KEY"
77
+ }
78
+ }
79
+ ```
80
+
81
+ **Setup steps**:
82
+ ```bash
83
+ pip install openai
84
+ export OPENAI_API_KEY=sk-...
85
+ ```
86
+
87
+ **Run**: `python .gator/scripts/enforcer-review.py`
88
+
89
+ ### Codex CLI (OpenAI)
90
+
91
+ **Best for**: Primary agent is Claude or Gemini. Architect wants to run the enforcer independently (no intermediary).
92
+
93
+ **What the Architect needs**: Codex CLI installed, OpenAI account
94
+
95
+ **Cost**: Depends on model (configured in `~/.codex/config.toml`)
96
+
97
+ **No config file changes needed** — but give Codex the dedicated enforcer prompt explicitly, because `AGENTS.md` is the primary-agent entrypoint.
98
+
99
+ **Setup steps**:
100
+ ```bash
101
+ npm install -g @openai/codex
102
+ codex login
103
+ ```
104
+
105
+ **Run**: `codex review "Read .gator/scripts/enforcer-prompt.md for full instructions. Review the uncommitted changes against the charters."`
106
+
107
+ **Note**: Codex review runs in a read-only sandbox by default. The Architect can run this in a separate terminal for fully independent review (no primary agent involved).
108
+
109
+ ### Gemini (Google)
110
+
111
+ **Best for**: Primary agent is Claude or GPT.
112
+
113
+ **What the Architect needs**: `GOOGLE_API_KEY` from [aistudio.google.com](https://aistudio.google.com)
114
+
115
+ **Cost**: `gemini-2.0-flash` is very cheap. `gemini-2.5-pro` is moderate.
116
+
117
+ **Config**:
118
+ ```json
119
+ {
120
+ "layer2_3": {
121
+ "provider": "google",
122
+ "model": "gemini-2.0-flash",
123
+ "api_key_env": "GOOGLE_API_KEY"
124
+ }
125
+ }
126
+ ```
127
+
128
+ **Setup steps**:
129
+ ```bash
130
+ pip install google-generativeai
131
+ export GOOGLE_API_KEY=...
132
+ ```
133
+
134
+ **Run**: `python .gator/scripts/enforcer-review.py`
135
+
136
+ ### Claude Code CLI (Anthropic)
137
+
138
+ **Best for**: Architect wants a separate Claude terminal/session as the reviewer, rather than using the Python API path.
139
+
140
+ **What the Architect needs**: Claude Code installed, Anthropic access configured
141
+
142
+ **Run**:
143
+ ```bash
144
+ claude --print "$(cat .gator/scripts/enforcer-prompt.md)"
145
+ ```
146
+
147
+ **Trade-off**: workable, but less clean than the Python Anthropic path when `CLAUDE.md` in the same repo defines Claude as the primary agent. The explicit enforcer prompt should steer the session correctly, but the role boundary is cleaner through `enforcer-review.py`.
148
+
149
+ ### Local model via ollama (free, offline)
150
+
151
+ **Best for**: No API keys, cost-sensitive, privacy-sensitive, or offline use.
152
+
153
+ **What the Architect needs**: [ollama](https://ollama.com) installed
154
+
155
+ **Cost**: Free. Runs locally.
156
+
157
+ **Config**:
158
+ ```json
159
+ {
160
+ "layer2_3": {
161
+ "provider": "ollama",
162
+ "model": "llama3"
163
+ }
164
+ }
165
+ ```
166
+
167
+ **Setup steps**:
168
+ ```bash
169
+ # Install ollama from https://ollama.com
170
+ ollama pull llama3
171
+ ```
172
+
173
+ **Run**: `python .gator/scripts/enforcer-review.py`
174
+
175
+ **Trade-off**: Free and private, but slower and less capable than cloud models. Good enough for catching obvious charter violations. Won't match Sonnet/GPT on nuanced boundary analysis.
176
+
177
+ ### Mechanical lint only (no model)
178
+
179
+ **Best for**: Zero setup, no API keys, no local model. Quick hygiene check.
180
+
181
+ **What the Architect needs**: Python 3. That's it.
182
+
183
+ **No config changes needed.**
184
+
185
+ **Run**: `python .gator/scripts/enforcer-review.py --layer 1`
186
+
187
+ **Limitation**: Only catches secrets, SQL dangers, injection risks, TODO markers. Does **not** read charters, check TRIPWIREs, or verify boundary compliance. This is hygiene, not architectural review.
188
+
189
+ ## How the Config File Works
190
+
191
+ The enforcer config lives at `.gator/scripts/enforcer-config.json`. The primary agent edits this file when configuring the enforcer for the Architect.
192
+
193
+ ```json
194
+ {
195
+ "layer1": {
196
+ "enabled": true
197
+ },
198
+ "layer2_3": {
199
+ "provider": "anthropic",
200
+ "model": "claude-sonnet-4-6",
201
+ "api_key_env": "ANTHROPIC_API_KEY"
202
+ }
203
+ }
204
+ ```
205
+
206
+ - `layer1.enabled` — mechanical lint. Leave this `true`. No reason to disable it.
207
+ - `layer2_3.provider` — which API to call: `anthropic`, `openai`, `google`, `ollama`, or `none`
208
+ - `layer2_3.model` — the specific model identifier
209
+ - `layer2_3.api_key_env` — the environment variable name holding the API key (not the key itself — never put secrets in this file)
210
+
211
+ Setting `provider` to `"none"` disables charter-grounded review entirely. Layer 1 still runs.
212
+
213
+ ## Cross-Vendor Principle
214
+
215
+ The enforcer should ideally be a **different vendor** than the primary agent. Different training data, different RLHF, different blind spots. This isn't dogma — same-vendor is still better than nothing — but cross-vendor review is where the real value of independent verification comes from.
216
+
217
+ | Primary agent | Recommended enforcer |
218
+ |---------------|---------------------|
219
+ | Claude (Opus) | Sonnet (same vendor, different model), GPT, or Gemini |
220
+ | GPT / Codex | Sonnet via `enforcer-review.py`, GPT/Codex via CLI, or Gemini |
221
+ | Gemini | Sonnet or GPT |
222
+
223
+ ## What the Agent Should Do
224
+
225
+ When an Architect asks to set up an enforcer:
226
+
227
+ 1. Ask the three questions above (primary agent, available keys/tools, cost sensitivity)
228
+ 2. Pick the matching config from this guide
229
+ 3. Edit `enforcer-config.json` with the right provider/model
230
+ 4. Help the Architect set the environment variable (show the exact export command)
231
+ 5. Run a test review to confirm it works
232
+ 6. Show the Architect where `whiteboard.md` is so they can verify findings independently
@@ -0,0 +1,289 @@
1
+ # Worked Example: taskflow (a simple Python CLI task manager)
2
+
3
+ This is a complete reference showing what a populated Gator knowledge layer looks like for a small Python project. Study this before bootstrapping your own project. The format, density, and style shown here is what you're aiming for.
4
+
5
+ ---
6
+
7
+ ## The Project
8
+
9
+ `taskflow` — a CLI task manager in Python. ~800 lines across 5 files:
10
+ ```
11
+ taskflow/
12
+ __main__.py # CLI entry point (click)
13
+ store.py # SQLite persistence
14
+ models.py # Task, Project dataclasses
15
+ filters.py # Query builder for task lists
16
+ export.py # Markdown/JSON export
17
+ ```
18
+
19
+ ---
20
+
21
+ ## Example: mission.md
22
+
23
+ ```markdown
24
+ # Mission
25
+
26
+ ## What We're Building
27
+
28
+ A command-line task manager that stores tasks in SQLite and exports to Markdown.
29
+ Designed for solo developers who want something between a text file and Jira.
30
+
31
+ ## Why It Exists
32
+
33
+ Every task manager either requires a browser or locks data in a proprietary format.
34
+ taskflow is local-first, file-friendly, and scriptable.
35
+
36
+ ## What Success Looks Like
37
+
38
+ - `task add "fix login bug" --project api` works in under 50ms
39
+ - Tasks survive across machines via git (SQLite file in repo)
40
+ - Weekly review exports to Markdown that reads well in any viewer
41
+ ```
42
+
43
+ ---
44
+
45
+ ## Example: roadmap.md
46
+
47
+ ```markdown
48
+ # Roadmap
49
+
50
+ | # | Feature | Status | Next step |
51
+ |---|---------|--------|-----------|
52
+ | 1 | Core CRUD (add/done/delete/list) | Done | — |
53
+ | 2 | Project grouping | Done | — |
54
+ | 3 | Priority sorting | Building | Wire into `list` output |
55
+ | 4 | Markdown export | Designed | Template in export.py |
56
+ | 5 | Recurring tasks | Considering | Need cron-like syntax |
57
+ | 6 | Due dates with reminders | Deferred | After recurring tasks |
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Example: charters/INDEX.md
63
+
64
+ ```markdown
65
+ # Charter Index
66
+
67
+ **Always read first:** [Cross-Cutting](cross-cutting.md)
68
+
69
+ | If you're changing... | Read these charters |
70
+ |---|---|
71
+ | `taskflow/__main__.py` | [CLI](cli.md) + [Cross-Cutting](cross-cutting.md) |
72
+ | `taskflow/store.py` | [Store](store.md) + [Cross-Cutting](cross-cutting.md) |
73
+ | `taskflow/models.py` | [Models](models.md) |
74
+ | `taskflow/filters.py` | [Store](store.md) + [Cross-Cutting](cross-cutting.md) |
75
+ | `taskflow/export.py` | [Export](export.md) |
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Example: charters/cross-cutting.md
81
+
82
+ ```markdown
83
+ # Charter: Cross-Cutting Patterns
84
+
85
+ ### TRIPWIRE: SQLite file locking
86
+
87
+ The store opens a single connection at CLI entry and closes on exit.
88
+ Concurrent access (two terminals) will hit SQLite's write lock.
89
+ This is intentional — taskflow is single-user. Do NOT add connection
90
+ pooling or WAL mode unless the mission changes to multi-user.
91
+
92
+ ### TRIPWIRE: Task ID stability
93
+
94
+ Task IDs are SQLite rowids. They are permanent — deletion does not
95
+ reassign IDs. Export files reference IDs. If you ever compact/reindex,
96
+ every exported Markdown file breaks.
97
+
98
+ ### Data flow: add command
99
+
100
+ __main__.py (parse args)
101
+ → models.py (Task dataclass construction)
102
+ → store.py (INSERT, returns ID)
103
+ → __main__.py (prints confirmation with ID)
104
+
105
+ ### Data flow: export command
106
+
107
+ __main__.py (parse args, date range)
108
+ → filters.py (build WHERE clause)
109
+ → store.py (SELECT with filter)
110
+ → export.py (format as Markdown or JSON)
111
+ → __main__.py (write to stdout or file)
112
+ ```
113
+
114
+ ---
115
+
116
+ ## Example: charters/store.md
117
+
118
+ ```markdown
119
+ # Charter: Store
120
+
121
+ **Covers**: `taskflow/store.py`
122
+
123
+ ## Owns
124
+
125
+ SQLite connection lifecycle, all INSERT/UPDATE/DELETE/SELECT operations,
126
+ schema migration, file path resolution.
127
+
128
+ ## Does Not Own
129
+
130
+ Task validation (models.py owns that).
131
+ Query building for complex filters (filters.py owns that).
132
+ Formatting output (export.py owns that).
133
+
134
+ ---
135
+
136
+ ### init_db(path)
137
+ File: taskflow/store.py
138
+ Creates SQLite DB at path if absent. Runs migrations.
139
+ ← __main__.py (called once at startup)
140
+ → sqlite3.connect()
141
+ ! Path defaults to ./tasks.db relative to CWD, not the package.
142
+ This is intentional — the DB lives in the project, not globally.
143
+
144
+ ### add_task(task: Task) -> int
145
+ File: taskflow/store.py
146
+ Inserts Task, returns rowid.
147
+ Models: Task(R), sqlite(W)
148
+ ← __main__.py add command
149
+ ! Returns the rowid, not a Task object. Caller must use this ID.
150
+
151
+ ### get_tasks(filter: Filter) -> list[Task]
152
+ File: taskflow/store.py
153
+ Runs SELECT with filter's WHERE clause, returns Task list.
154
+ Models: Task(R), sqlite(R)
155
+ ← __main__.py list command, export.py
156
+ → filters.py build_where()
157
+ ! Returns empty list (not None) when no matches. Callers rely on this.
158
+
159
+ ### mark_done(task_id: int) -> bool
160
+ File: taskflow/store.py
161
+ Sets done=True, done_at=now(). Returns False if ID not found.
162
+ Models: sqlite(RW)
163
+ ← __main__.py done command
164
+ ! Does NOT delete the task. "Done" is a state, not removal.
165
+
166
+ ### delete_task(task_id: int) -> bool
167
+ File: taskflow/store.py
168
+ Hard deletes by rowid. Returns False if ID not found.
169
+ Models: sqlite(W)
170
+ ← __main__.py delete command
171
+ ! See cross-cutting TRIPWIRE on ID stability.
172
+
173
+ ---
174
+
175
+ ## Before Changing This Module
176
+
177
+ - Schema changes require a migration function (see bottom of file)
178
+ - The connection is opened once and passed around — not per-query
179
+ - All timestamps are UTC ISO-8601 strings, not datetime objects
180
+
181
+ ## Connections
182
+
183
+ → [Models](models.md) — Task dataclass definition
184
+ → [Cross-Cutting](cross-cutting.md) — SQLite locking, ID stability
185
+ ```
186
+
187
+ ---
188
+
189
+ ## Example: charters/cli.md
190
+
191
+ ```markdown
192
+ # Charter: CLI
193
+
194
+ **Covers**: `taskflow/__main__.py`
195
+
196
+ ## Owns
197
+
198
+ Argument parsing (click), command routing, DB initialization,
199
+ user-facing output formatting, exit codes.
200
+
201
+ ## Does Not Own
202
+
203
+ Business logic (store.py). Data shapes (models.py).
204
+ Export formatting (export.py).
205
+
206
+ ---
207
+
208
+ ### main()
209
+ File: taskflow/__main__.py
210
+ Click group entry point. Initializes DB connection.
211
+ → init_db() in store.py
212
+ ! Exit code 0 on success, 1 on error. Scripts depend on this.
213
+
214
+ ### add(name, project, priority)
215
+ File: taskflow/__main__.py
216
+ Parses add-command args, creates Task, calls store.
217
+ → Task() in models.py, add_task() in store.py
218
+ ← CLI: `task add "name" --project X --priority N`
219
+
220
+ ### list(project, status, sort)
221
+ File: taskflow/__main__.py
222
+ Builds filter from flags, fetches tasks, prints table.
223
+ → Filter() in filters.py, get_tasks() in store.py
224
+ ! --sort=priority is descending (high first). Not alphabetical.
225
+
226
+ ---
227
+
228
+ ## Before Changing This Module
229
+
230
+ - Every command prints to stdout. Errors go to stderr.
231
+ - Click handles --help automatically. Don't duplicate.
232
+ - The DB path comes from --db flag or TASKFLOW_DB env var.
233
+
234
+ ## Connections
235
+
236
+ → [Store](store.md) — all persistence
237
+ → [Cross-Cutting](cross-cutting.md) — data flows start here
238
+ ```
239
+
240
+ ---
241
+
242
+ ## Example: threads/sqlite-vs-postgres.md
243
+
244
+ ```markdown
245
+ ---
246
+ last-touched: 2026-05-10
247
+ tags: [architecture, database, decision]
248
+ ---
249
+
250
+ # SQLite vs Postgres
251
+
252
+ ## Summary
253
+
254
+ Evaluated Postgres for multi-user support. Decision: stay on SQLite.
255
+ The project is single-user by mission. Postgres adds deployment complexity
256
+ (managed service, connection strings, migrations) for zero benefit at
257
+ current scope. Revisit only if mission changes to multi-user.
258
+
259
+ ## Connections
260
+
261
+ → [Store charter](../charters/store.md) — the module this decision constrains
262
+ ```
263
+
264
+ ---
265
+
266
+ ## Example: commit_draft.md
267
+
268
+ ```markdown
269
+ # Session Change Log
270
+
271
+ - Added priority field to Task model and store schema [#feature] [#models] -agent
272
+ - Updated store charter: add_task now accepts priority param [#charter-update] -agent
273
+ - Architect decision: priority is 1-5 integer, not string label [#decision] [#models] -architect
274
+ - Updated cross-cutting: added note about priority sort direction [#charter-update] -agent
275
+ ```
276
+
277
+ ---
278
+
279
+ ## Key Observations
280
+
281
+ 1. **Charters are short.** Each function entry is 3-5 lines. The whole store charter is maybe 60 lines for a real module. This is a small, compressed map — not a rewrite of the code.
282
+
283
+ 2. **Cross-cutting is the star.** The TRIPWIREs prevent the two most common agent mistakes: adding connection pooling to a single-user app, and reindexing IDs that exported files depend on.
284
+
285
+ 3. **"Does not own" is load-bearing.** It prevents the agent from putting export logic in the store, or validation logic in the CLI. Scope boundaries are the first thing that erodes without governance.
286
+
287
+ 4. **Threads are tiny.** The SQLite-vs-Postgres thread is 8 lines. It exists so the decision doesn't have to be re-explained every session.
288
+
289
+ 5. **The loop is visible in commit_draft.** Charter updates appear alongside code changes. They're the same operation.