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,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.
|