graphban-cli 0.8.0__tar.gz → 0.8.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/PKG-INFO +5 -3
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/README.md +4 -2
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/pyproject.toml +1 -1
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/src/gban/cli.py +3 -1
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/src/gban/data/stack_sdks.toml +31 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/src/gban/skills/graphban-delegation/SKILL.md +7 -4
- graphban_cli-0.8.2/src/gban/skills/graphban-grill/SKILL.md +56 -0
- graphban_cli-0.8.2/src/gban/skills/graphban-scan/SKILL.md +31 -0
- graphban_cli-0.8.2/src/gban/skills/graphban-wave/SKILL.md +64 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/src/gban/stackmap.py +475 -74
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/tests/test_setup.py +16 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/tests/test_stackmap.py +236 -14
- graphban_cli-0.8.2/uv.lock +207 -0
- graphban_cli-0.8.0/src/gban/skills/graphban-scan/SKILL.md +0 -23
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/.gitignore +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/LICENSE +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/src/gban/__init__.py +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/src/gban/client.py +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/src/gban/config.py +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/src/gban/doctor.py +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/src/gban/gitignore.py +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/src/gban/setup.py +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/src/gban/skills/graphban-orient/SKILL.md +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/src/gban/skills/graphban-prd/SKILL.md +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/src/gban/skills/graphban-review/SKILL.md +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/src/gban/skills/graphban-work/SKILL.md +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/src/gban/skills/watch-wave/SKILL.md +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/src/gban/swamp.py +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/tests/test_acts.py +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/tests/test_doctor.py +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/tests/test_login_projects.py +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/tests/test_packaging.py +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/tests/test_session.py +0 -0
- {graphban_cli-0.8.0 → graphban_cli-0.8.2}/tests/test_swamp.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: graphban-cli
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.2
|
|
4
4
|
Summary: gban — a Graphban client for the human at a terminal
|
|
5
5
|
Project-URL: Homepage, https://github.com/asc-me/graphban
|
|
6
6
|
Project-URL: Repository, https://github.com/asc-me/graphban
|
|
@@ -202,8 +202,10 @@ What it reads:
|
|
|
202
202
|
|
|
203
203
|
- Compose files (`compose.yml`, `docker-compose.yml`, and the `compose.*` / `docker-compose.*` variants): a service with `build` is a deployable, a service with only `image` is infrastructure, and `depends_on` is an edge. `environment` contributes variable **names** and, when a value is a literal URL, the bare host.
|
|
204
204
|
- Dockerfiles (`Dockerfile`, `Dockerfile.*`, `*.Dockerfile`), for the deployable they sit in and for a `FROM` image the table knows.
|
|
205
|
-
- Dependency manifests (`package.json`, `pyproject.toml`, `requirements*.txt`, `go.mod`, `Cargo.toml`, `Gemfile`)
|
|
206
|
-
-
|
|
205
|
+
- Dependency manifests (`package.json`, `pyproject.toml`, `requirements*.txt`, `go.mod`, `Cargo.toml`, `Gemfile`). Every `package.json` and `Cargo.toml` is a component named from the manifest's `name`. The known-SDK table adds edges; it is not what decides whether the component exists. `file:` and `workspace:` dependencies (and a Cargo `path` or `workspace = true`) are internal edges. Other manifests still become a component only when a dependency hits the table, and that edge is attributed to the component whose directory contains the file.
|
|
206
|
+
- Deploy manifests (`vercel.json`, `railway.json`, `railway.toml`, `fly.toml`, `netlify.toml`, `render.yaml`) are a platform node. The file body is not stored.
|
|
207
|
+
- `.env.example` only. A real `.env` is not a template and is not opened. A commented `KEY=` is read and the edge is `state: documented` rather than `set`. `*_TOKEN`, `*_CLIENT_ID`, and `*_CLIENT_SECRET` count, and so do `*_BASE` and `*_ISSUER` when the value is a URL. A passphrase (`AUTH_SECRET`, `ENCRYPTION_KEY`) is not an edge unless a table row names it. Values stay out of the record.
|
|
208
|
+
- Source files are not scanned. There is no source-HTTP pass in this command. stderr always prints a coverage line: files read, files that produced nothing, commented template keys skipped, and that source was not scanned. Exit 0 means the record was built.
|
|
207
209
|
|
|
208
210
|
The known-SDK table ships at `cli/src/gban/data/stack_sdks.toml` and is versioned with `gban`. A checkout may add rows in `.graphban/stack-sdks.toml` (same shape); those rows are consulted first.
|
|
209
211
|
|
|
@@ -187,8 +187,10 @@ What it reads:
|
|
|
187
187
|
|
|
188
188
|
- Compose files (`compose.yml`, `docker-compose.yml`, and the `compose.*` / `docker-compose.*` variants): a service with `build` is a deployable, a service with only `image` is infrastructure, and `depends_on` is an edge. `environment` contributes variable **names** and, when a value is a literal URL, the bare host.
|
|
189
189
|
- Dockerfiles (`Dockerfile`, `Dockerfile.*`, `*.Dockerfile`), for the deployable they sit in and for a `FROM` image the table knows.
|
|
190
|
-
- Dependency manifests (`package.json`, `pyproject.toml`, `requirements*.txt`, `go.mod`, `Cargo.toml`, `Gemfile`)
|
|
191
|
-
-
|
|
190
|
+
- Dependency manifests (`package.json`, `pyproject.toml`, `requirements*.txt`, `go.mod`, `Cargo.toml`, `Gemfile`). Every `package.json` and `Cargo.toml` is a component named from the manifest's `name`. The known-SDK table adds edges; it is not what decides whether the component exists. `file:` and `workspace:` dependencies (and a Cargo `path` or `workspace = true`) are internal edges. Other manifests still become a component only when a dependency hits the table, and that edge is attributed to the component whose directory contains the file.
|
|
191
|
+
- Deploy manifests (`vercel.json`, `railway.json`, `railway.toml`, `fly.toml`, `netlify.toml`, `render.yaml`) are a platform node. The file body is not stored.
|
|
192
|
+
- `.env.example` only. A real `.env` is not a template and is not opened. A commented `KEY=` is read and the edge is `state: documented` rather than `set`. `*_TOKEN`, `*_CLIENT_ID`, and `*_CLIENT_SECRET` count, and so do `*_BASE` and `*_ISSUER` when the value is a URL. A passphrase (`AUTH_SECRET`, `ENCRYPTION_KEY`) is not an edge unless a table row names it. Values stay out of the record.
|
|
193
|
+
- Source files are not scanned. There is no source-HTTP pass in this command. stderr always prints a coverage line: files read, files that produced nothing, commented template keys skipped, and that source was not scanned. Exit 0 means the record was built.
|
|
192
194
|
|
|
193
195
|
The known-SDK table ships at `cli/src/gban/data/stack_sdks.toml` and is versioned with `gban`. A checkout may add rows in `.graphban/stack-sdks.toml` (same shape); those rows are consulted first.
|
|
194
196
|
|
|
@@ -433,12 +433,14 @@ def cmd_stack(args) -> int:
|
|
|
433
433
|
start = Path(args.repo).expanduser() if args.repo else Path.cwd()
|
|
434
434
|
project = (config.resolve(args.project, config.PROJECT_ENV, "project") or "").strip()
|
|
435
435
|
try:
|
|
436
|
-
record, warnings = stackmap.build_record(start, project_id=project)
|
|
436
|
+
record, warnings, coverage = stackmap.build_record(start, project_id=project)
|
|
437
437
|
except stackmap.MapError as exc:
|
|
438
438
|
print(f"{PROG}: {exc}", file=sys.stderr)
|
|
439
439
|
return EXIT_REFUSED
|
|
440
440
|
for warning in warnings:
|
|
441
441
|
print(f"{PROG}: {warning}", file=sys.stderr)
|
|
442
|
+
# Always. A three-node map that exits 0 is not a finished topology.
|
|
443
|
+
print(f"{PROG}: {coverage}", file=sys.stderr)
|
|
442
444
|
text = stackmap.canonical(record)
|
|
443
445
|
if args.dry_run:
|
|
444
446
|
sys.stdout.write(text)
|
|
@@ -148,6 +148,27 @@ label = "SendGrid"
|
|
|
148
148
|
protocol = "https"
|
|
149
149
|
domains = ["sendgrid.com", "sendgrid.net"]
|
|
150
150
|
|
|
151
|
+
[[sdk]]
|
|
152
|
+
id = "resend"
|
|
153
|
+
packages = ["resend"]
|
|
154
|
+
node = "resend"
|
|
155
|
+
group = "external"
|
|
156
|
+
kind = ""
|
|
157
|
+
label = "Resend"
|
|
158
|
+
protocol = "https"
|
|
159
|
+
domains = ["resend.com"]
|
|
160
|
+
|
|
161
|
+
[[sdk]]
|
|
162
|
+
id = "vercel"
|
|
163
|
+
packages = ["@vercel/functions"]
|
|
164
|
+
prefix = "@vercel/"
|
|
165
|
+
node = "vercel"
|
|
166
|
+
group = "external"
|
|
167
|
+
kind = ""
|
|
168
|
+
label = "Vercel"
|
|
169
|
+
protocol = "https"
|
|
170
|
+
domains = ["vercel.com", "vercel.app"]
|
|
171
|
+
|
|
151
172
|
[[sdk]]
|
|
152
173
|
id = "supabase"
|
|
153
174
|
packages = ["supabase", "@supabase/supabase-js"]
|
|
@@ -175,3 +196,13 @@ group = "infrastructure"
|
|
|
175
196
|
kind = "redis"
|
|
176
197
|
label = "Redis"
|
|
177
198
|
protocol = "redis"
|
|
199
|
+
|
|
200
|
+
[[env]]
|
|
201
|
+
id = "creem"
|
|
202
|
+
names = ["CREEM_API_KEY"]
|
|
203
|
+
node = "creem"
|
|
204
|
+
group = "external"
|
|
205
|
+
kind = ""
|
|
206
|
+
label = "Creem"
|
|
207
|
+
protocol = "https"
|
|
208
|
+
domains = ["creem.io"]
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: graphban-delegation
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Hand one Graphban item to one child on a cheaper model, and enable
|
|
5
|
+
delegation on a project that does not have it yet. Use when asked to
|
|
6
|
+
delegate one item, spawn one worker, mint seats, or retire a wave.
|
|
7
|
+
A whole PRD is /graphban-wave.
|
|
4
8
|
---
|
|
5
9
|
|
|
6
10
|
# Delegating a Graphban item
|
|
@@ -197,6 +201,5 @@ So a delegated item needs a second agent to review it. Plan for that, or the wor
|
|
|
197
201
|
|
|
198
202
|
## When not to use this
|
|
199
203
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
entire length just to poll and adjudicate.
|
|
204
|
+
A whole PRD is `graphban-wave`. It runs `gbfleet until` for that PRD. Fanning the items out
|
|
205
|
+
from here keeps a frontier context polling for the wave's whole length.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: graphban-grill
|
|
3
|
+
description: >
|
|
4
|
+
Settle a Graphban PRD grill from the product why and the PRD's intent.
|
|
5
|
+
Auto-record answers the context already decides, and ask the user only
|
|
6
|
+
the questions it does not. Use when grilling a PRD, running a grill,
|
|
7
|
+
answer_grill, or when the user runs /graphban-grill.
|
|
8
|
+
user-invocable: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Grill
|
|
12
|
+
|
|
13
|
+
`grill_prd` returns questions and records nothing. An answer counts only after `answer_grill`. The grader ignores the PRD body: a decision that exists only in the document is still unanswered.
|
|
14
|
+
|
|
15
|
+
## Sources
|
|
16
|
+
|
|
17
|
+
Read both before you classify a question.
|
|
18
|
+
|
|
19
|
+
1. `get_prd`. The intent is the framing: Problem, Goals, Non-goals, and an intent heading when the PRD has one.
|
|
20
|
+
2. Why the app exists: `docs/product-overview.md` (philosophy, goals, non-goals) and `docs/design-philosophy.md`. This bounds the PRD. It does not fill a hole the PRD left open.
|
|
21
|
+
|
|
22
|
+
A source decides a question only when you can quote the sentence. Memory, code, and a guess are not sources.
|
|
23
|
+
|
|
24
|
+
## Split
|
|
25
|
+
|
|
26
|
+
For each question, write a one- or two-sentence recommendation, then:
|
|
27
|
+
|
|
28
|
+
- **accept** — that sentence already decides it, the two sources do not conflict, and the answer is words rather than a prototype. Record it.
|
|
29
|
+
- **ask** — the sources are silent, they conflict, both readings are reasonable, or the question needs a prototype. These are the only questions you put to the user.
|
|
30
|
+
|
|
31
|
+
Silence is ask. A fluent inference is ask. Do not accept a new boundary, a new error behavior, or a new contract field that neither source states.
|
|
32
|
+
|
|
33
|
+
## Record an accept
|
|
34
|
+
|
|
35
|
+
Fold the decision into the PRD with `update_prd(section=...)` first. Then `answer_grill` once, with that decision alone.
|
|
36
|
+
|
|
37
|
+
One call per decision. A reply that covers several dimensions is one answer, and the grader leaves the rest outstanding.
|
|
38
|
+
|
|
39
|
+
Say `deferred` only when a source already defers it. "Later" without that word stays unanswered.
|
|
40
|
+
|
|
41
|
+
Read the return:
|
|
42
|
+
|
|
43
|
+
- `graded: false` — stop. Say `ungraded_reason`. Do not send another answer.
|
|
44
|
+
- `stalled: true` — stop. Tell the user. Three answers moved nothing.
|
|
45
|
+
- `complete: true` — the grill finished and the body just froze. The fold had to happen before this call.
|
|
46
|
+
- `body_absorbed: false` — the transcript is ahead of the spec. Fold the answers it names before you continue.
|
|
47
|
+
|
|
48
|
+
Do not set `approved`. Finishing the grill does that.
|
|
49
|
+
|
|
50
|
+
## Ask
|
|
51
|
+
|
|
52
|
+
Show only the ask list. For each: the question, the recommendation, and one line on why the sources do not decide it.
|
|
53
|
+
|
|
54
|
+
Record nothing from this list until the user answers. `answer_grill` with their words. Fold that section the same way, before the next call.
|
|
55
|
+
|
|
56
|
+
If they accept a recommendation, the recorded answer is their acceptance of that text. The recommendation alone is not a turn.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: graphban-scan
|
|
3
|
+
description: >
|
|
4
|
+
Record Graphban code-health scans without treating a missing scan as clean.
|
|
5
|
+
Use when running a security or health scan, or calling scans_due, scan_status,
|
|
6
|
+
or record_scan, or when the user runs /graphban-scan.
|
|
7
|
+
user-invocable: true
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Scans
|
|
11
|
+
|
|
12
|
+
A missing scan is not a clean scan.
|
|
13
|
+
|
|
14
|
+
1. `scans_due(head_sha)`. An empty due list is not all-clean. Rows that were `never_scanned`, including security, stay listed.
|
|
15
|
+
2. `scan_status` for one path, or with no path for every deployable. Pass `head_sha`. States are `clean_at_sha`, `has_findings`, `never_scanned`, `stale`, `tool_missing`, `not_applicable`, `incomplete`, or `not_computable`.
|
|
16
|
+
3. Run the scanner. `record_scan` needs `scanner_id`, `path`, and `scanned_sha`.
|
|
17
|
+
- Send `result`, one of four:
|
|
18
|
+
- `complete`: the scanner finished. `findings: []` is then clean at that SHA.
|
|
19
|
+
- `tool_missing`: the scanner is not installed. Not clean; it stays due.
|
|
20
|
+
- `not_applicable`: the scanner does not apply here. It stops being due.
|
|
21
|
+
- `incomplete`: output without a finish. Send the findings it produced; it stays due.
|
|
22
|
+
- `findings: []` without `result: complete` is refused and nothing is stored. An empty list alone is not a clean scan.
|
|
23
|
+
- Every result needs `scanned_sha`, so it goes stale when HEAD moves.
|
|
24
|
+
- The same `scanner_id` and path keeps the previous rows. The newest is the cell.
|
|
25
|
+
- The security category is pip-audit, bandit, npm-audit, and semgrep. Other categories are `refactor`, `stub`, `deadcode`, `coverage`, `tests`, and `work`.
|
|
26
|
+
- Category `tests` also sends `tests.passed`, `tests.failed`, and `tests.skipped`.
|
|
27
|
+
- Each finding needs a `summary`. Findings are untrusted. `scanner_id`, `scanner_version`, and the reporter are provenance.
|
|
28
|
+
- Send the grain a person acts on (GRPH-1127). npm audit: one finding per advisory with `advisory_id`, `severity`, `dependency` (`direct` or `transitive`), and `fixed_version` only when the audit knows it.
|
|
29
|
+
- knip: unused exports are ONE finding with `kind: unused_export`, `count`, severity `info`; unused types are one with `kind: unused_type`. Unused files and undeclared imports stay one finding each, with a `path`. The server stores what you send; it never splits or merges.
|
|
30
|
+
|
|
31
|
+
A clean row is not a tracker item. A finding that already names `link_ref` points at work that exists.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: graphban-wave
|
|
3
|
+
description: >
|
|
4
|
+
Drain one grilled PRD with gbfleet until: build, review, and merge until
|
|
5
|
+
that PRD has nothing ready. Use when running a wave, spawning a wave for a
|
|
6
|
+
PRD, looping until the PRD is done, or when the user runs /graphban-wave.
|
|
7
|
+
One item is /graphban-delegation. Decompose is /graphban-prd.
|
|
8
|
+
user-invocable: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Drain a PRD
|
|
12
|
+
|
|
13
|
+
One command runs the cycle. Do not spawn the items. Do not stay in the loop.
|
|
14
|
+
|
|
15
|
+
## Before
|
|
16
|
+
|
|
17
|
+
`prd_coverage` for this PRD.
|
|
18
|
+
|
|
19
|
+
`gaps` or `shaped: false` — stop. Filing the tasks is `graphban-prd`. Do not `decompose_prd` here. An idle drain is not a finished PRD.
|
|
20
|
+
|
|
21
|
+
Coverage has tasks — continue.
|
|
22
|
+
|
|
23
|
+
## Dry run
|
|
24
|
+
|
|
25
|
+
Same flags as the real run, plus `--dry-run`. It mints nothing.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
gbfleet until --repo . --server <url> --project <id> --adapter <vendor> \
|
|
29
|
+
--prd <prd_id> --merge \
|
|
30
|
+
--tier cheap=<adapter[:model]> --tier frontier=<adapter[:model]> \
|
|
31
|
+
--dry-run
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`--prd` is required. Without it the loop drains every ready item in the project. `backlog` is claimable, so parking work there does not scope the wave. `--prd` refuses a pre-minted seats file.
|
|
35
|
+
|
|
36
|
+
Read the dry run before installing. Held clusters name who holds them. `predicted: true` is a lower-confidence grouping. A plan for the wrong PRD is a stop.
|
|
37
|
+
|
|
38
|
+
A backend change whose acceptance is the Postgres suite needs `--allow psql` on both the dry run and the install.
|
|
39
|
+
|
|
40
|
+
## Run
|
|
41
|
+
|
|
42
|
+
Drop `--dry-run` and hand the process to the machine. This session ending must not kill it.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
gbfleet service install --name <prd_id> -- --repo . --server <url> --project <id> \
|
|
46
|
+
--adapter <vendor> --prd <prd_id> --merge \
|
|
47
|
+
--tier cheap=<adapter[:model]> --tier frontier=<adapter[:model]>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`--tier` is what a tier means on this machine. Omit a tier the Fleet tier map already pins. `--request cheap` or `--request frontier` forces every delegation to that tier. The default follows each item's brief. Do not pick a model per item.
|
|
51
|
+
|
|
52
|
+
A service already installed under that name: `gbfleet service status --name <prd_id>` and leave it. A second `until` on the same repo mints another child onto the same cluster.
|
|
53
|
+
|
|
54
|
+
`gbfleet service status` prints the PATH the unit captured. An empty PATH is a drain that will not find the adapter. The API key is the one already stored for this repo. Do not print it, and do not pass a new one.
|
|
55
|
+
|
|
56
|
+
## While it runs
|
|
57
|
+
|
|
58
|
+
Status is `gbfleet service status --name <prd_id>`. The ledger is `fleet_status`. Do not attach a spawn watcher, and do not spawn a replacement.
|
|
59
|
+
|
|
60
|
+
`until` is idle when that PRD has nothing ready, nothing unsigned, and no live lease. `WAVE_IDLE` while items are still `next`, or held in review, is not done.
|
|
61
|
+
|
|
62
|
+
`review-unsigned` can be a review row outside this PRD. Say which item. Do not start another drain over it, and do not `sign_off` it yourself.
|
|
63
|
+
|
|
64
|
+
`--merge` lands the pull requests this wave opened. Leave every other open pull request. A salvage branch can be the only copy of the work.
|