Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -182,17 +182,19 @@ PROXY_ADMIN_TOKEN=
# settings document, per organization and repository (docs/configuration.md);
# none until one is enrolled. A repository that leaves loses its mirror and
# its rows background.prune_after_days later (docs/ops/background-data.md).
# 0 turns the loop off. Each tick's
# work per repository is bounded; a large history is read over ticks. Forge
# API calls have one budget per credential per tick, dealt round-robin among
# its repositories, and stop when that credential's rate limit drops below
# the reserve (jobs use the same credential); git fetches are not API calls.
# SLOP_METER_REPOS and SLOP_METER_EXCLUDE are read once, at the first start of
# the release that added the background section, into the repositories'
# layers, and ignored after that. Do not add them here.
# SLOP_METER_API_CALLS_PER_TICK=200
# SLOP_METER_RATE_RESERVE=2000
# SLOP_METER_INTERVAL_SECONDS=86400
# How it scores, how often it reads (and whether it reads at all) and its
# forge budget per credential are the `slop_meter` section of the settings
# document, not variables: edit it with PUT /api/v1/config/settings.
# SLOP_METER_INTERVAL_SECONDS, SLOP_METER_API_CALLS_PER_TICK and
# SLOP_METER_RATE_RESERVE are read once, at the first start of the release
# that added the section, and ignored after that; the next release removes
# them. SLOP_METER_REPOS and SLOP_METER_EXCLUDE are read once, at the first
# start of the release that added the background section, into the
# repositories' layers, and ignored after that. Do not add them here.
# The variables below are the process's own limits: each tick's work per
# repository is bounded, so a large history is read over ticks, coming back
# after the catch-up interval while one is behind; git fetches are not API
# calls, and every git call has a timeout.
# SLOP_METER_CATCHUP_SECONDS=300
# SLOP_METER_DATA_PATH=/data/embry0/slop-meter
# SLOP_METER_GIT_TIMEOUT_SECONDS=900
Expand Down
6 changes: 3 additions & 3 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ curl http://localhost:8200/api/v1/jobs/{job_id}/agents/developer/session

A job's `area` (on the list and on `GET /jobs/{job_id}`) is the part of a monorepo the pull request embry0 opened for it changes, from the repository's `.embry0/areas.yml` ([areas](areas.md)); `null` when the repository names none or the change falls in none. `GET /repos/{repo}/-/areas` reads that file, and `POST /repos/{repo}/-/areas/map` starts the agent that writes it as a pull request ([map areas](areas.md#map-areas)).

`GET /repos/{repo}/-/slop-meter?area=` is the repository's [Slop-O-Meter](glossary.md#slop-o-meter) (after [Slop-O-Meter](https://github.com/slop-o-meter/slop-o-meter)'s published slop score algorithm): `meter` (the repository's `{score, level, name, provisional, computed_at}`, `null` before its first score), `areas` (each scored area's `{area, meter}`), `area` (the series' area, `null` for the repository), `weeks` (`{week, cost, capacity, slop, lines, score}` oldest first, in weighted lines; `score` cumulative) and `reading` (`{commits_read, commits_total, computed_at, error}`, how far the history is read). 404 for an unregistered repository or an area with no reading. A repository the meter does not read (`background.slop_meter`, [which repositories](configuration.md#which-repositories-background-features-read)) gets no new reading: what the meter kept of one that left is removed `background.prune_after_days` later, and `meter` is then `null`. An inactive one keeps its reading.
`GET /repos/{repo}/-/slop-meter?area=` is the repository's [Slop-O-Meter](glossary.md#slop-o-meter) (after [Slop-O-Meter](https://github.com/slop-o-meter/slop-o-meter)'s published slop score algorithm): `meter` (the repository's `{score, level, name, provisional, computed_at}`, `null` before its first score), `areas` (each scored area's `{area, meter}`), `area` (the series' area, `null` for the repository), `weeks` (`{week, cost, capacity, slop, lines, score}` oldest first, in weighted lines; `score` cumulative) and `reading` (`{commits_read, commits_total, computed_at, error, config_version}`, how far the history is read, and the version of the `slop_meter` settings the repository's score was computed with, `null` for a score from before #169: [how a change rescores](slop-meter.md#how-a-change-rescores)). 404 for an unregistered repository or an area with no reading. A repository the meter does not read (`background.slop_meter`, [which repositories](configuration.md#which-repositories-background-features-read)) gets no new reading: what the meter kept of one that left is removed `background.prune_after_days` later, and `meter` is then `null`. An inactive one keeps its reading.

`POST /jobs/{job_id}/resume` takes `{"choice": "continue_retrying"|"merge_as_is"|"abandon", "guidance", "extra_budget_usd"}`. On a job over its budget, `continue_retrying` lets it spend one more cap past what it has spent (`budget.continue_default_extra_usd` of the [settings document](configuration.md#settings-document) when set), or `extra_budget_usd` when given: at most `budget.continue_extra_max_usd`, 1,000 by default, read when the request comes in, and a 422 naming that key above it. A continue that names nothing is held to the same most. The pause's `interrupt.summary.budget` says `{spent, cap, continue_adds}` ([per-job cap](architecture.md#budget-controls)). A continue goes on top of the fleet ceiling, `budget.max_budget_per_job_usd`, unless `budget.continue_may_exceed_ceiling` is false: then it adds at most what is left under the ceiling, and a job at it is not offered `continue_retrying` (one answered anyway is abandoned). Each continue that raises a job's cap writes a `job.budget_raised` audit row naming who continued it, with `job_id`, `spent_usd`, `cap_before_usd`, `cap_after_usd` and the `extra_usd` asked for.

Expand Down Expand Up @@ -741,9 +741,9 @@ A repository whose `context_audit.days` is set (the [settings document](configur
| `context_audit_budget_usd` | number more than 0 and at most 50, or `null` | `null` | Deprecated: the organization's layer of the settings document's `budget.context_audit_job_usd` now. Taken until 0.2.0, see below |
| `context_audit_max_jobs_per_tick` | integer from 0 to 50, or `null` | `null` | Deprecated: the organization's layer of `budget.context_audit_max_jobs_per_tick` now. Taken until 0.2.0, see below |
| `context_audit_open_prs` | boolean | off | Deprecated: the organization's layer of `context_audit.open_prs` now. Taken until 0.2.0, see below |
| `slop_meter_bots` | list of up to 100 strings, each at most 200 characters | empty | The owner's own bots: commit names, addresses and forge logins the Slop-O-Meter counts as a bot's, not a person's attention. embry0's own commit identities are always counted so; the list applies to every reading, including history read before it was set |
| `slop_meter_bots` | list of up to 100 strings, each at most 200 characters | empty | Deprecated: the organization's layer of the settings document's `slop_meter.bots` now. Taken until 0.2.0, see below |

**Moved settings.** `context_audit_budget_usd` and `context_audit_max_jobs_per_tick` are the organization's layer of the settings document's `budget` section now, as `context_audit_job_usd` and `context_audit_max_jobs_per_tick` (`PATCH /api/v1/config/settings/budget?owner=acme`), where an organization may also set `area_map_job_usd` and `fix_job_usd`. `context_audit_days` and `context_audit_open_prs` are its layer of the `context_audit` section, as `days` and `open_prs` (`PATCH /api/v1/config/settings/context_audit?owner=acme`), where a repository's own layer may set them too and `days: false` turns the schedule off whatever the layer below says (#170). The first start of each release that moved them copied each organization's value into its layer once, when the old reader would have used it (a value it read as the deployment's is nothing to copy); the value left on the organization is read by nothing, and `GET /api/v1/orgs` no longer shows it. Until 0.2.0, `PATCH` and `POST /api/v1/orgs` still take them, checked as above, and write them into the organization's layer instead, with every rule of that route (a revision with source `person`, a `settings.updated` audit row, a key with no repository allowlist); `null` takes the key out of the layer, so the organization reads the deployment's value. The answer then carries `deprecated`: one `{"setting", "moved_to", "removed_in", "detail"}` per moved setting it took. 0.2.0 refuses them.
**Moved settings.** `context_audit_budget_usd` and `context_audit_max_jobs_per_tick` are the organization's layer of the settings document's `budget` section now, as `context_audit_job_usd` and `context_audit_max_jobs_per_tick` (`PATCH /api/v1/config/settings/budget?owner=acme`), where an organization may also set `area_map_job_usd` and `fix_job_usd`. `context_audit_days` and `context_audit_open_prs` are its layer of the `context_audit` section, as `days` and `open_prs` (`PATCH /api/v1/config/settings/context_audit?owner=acme`), where a repository's own layer may set them too and `days: false` turns the schedule off whatever the layer below says (#170). `slop_meter_bots` is its layer of the `slop_meter` section, as `bots` (`PATCH /api/v1/config/settings/slop_meter?owner=acme`): the owner's own bots, which the Slop-O-Meter counts as a bot's work, not a person's attention, beside embry0's own commit identities, applied to every reading, history read before they were listed included, and added to the bots the deployment lists (#169). Each organization's list was copied, and a list `PATCH` or `POST` takes is written, with its blanks left out, each name once without regard to case, and an entry the section cannot hold (a line break, a tab, a control or format character) left out and logged (`slop_meter_bots_entries_dropped`) rather than refusing the rest. The first start of each release that moved them copied each organization's value into its layer once, when the old reader would have used it (a value it read as the deployment's is nothing to copy); the value left on the organization is read by nothing, and `GET /api/v1/orgs` no longer shows it. Until 0.2.0, `PATCH` and `POST /api/v1/orgs` still take them, checked as above, and write them into the organization's layer instead, with every rule of that route (a revision with source `person`, a `settings.updated` audit row, a key with no repository allowlist); `null` takes the key out of the layer, so the organization reads the deployment's value. The answer then carries `deprecated`: one `{"setting", "moved_to", "removed_in", "detail"}` per moved setting it took. 0.2.0 refuses them.

`GET` and `POST /api/v1/orgs/{owner}/webhook` inspect and install the organization's one GitHub webhook, and the receiver's gate handles deliveries for repositories nobody registered ([webhooks.md](webhooks.md#organization-webhooks-github), [ADR 0012](adr/0012-organization-webhook.md)).

Expand Down
1 change: 1 addition & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -1390,6 +1390,7 @@ The whole pass is serialised across processes by a session-level Postgres adviso
| 141 | the repository of a job posted with a git context alone: fills `jobs.repo` from `context->>'repo'` where `repo` is NULL and the context is git, so `GET /jobs?repo=`, the world view and the stats find it (`POST /jobs` stores it now); a row naming a repository and any other context are left alone, `updated_at` is kept, and a second run changes nothing | `jobs.repo` (data) |
| 142 | the skills triage may add to an agent: `agent_definitions.triage_may_add_skills`, a JSON array of `source:skill` names (NOT NULL, default `[]`); triage adds one only from a source the agent's skills already load. The built-in developer row gets `superpowers:brainstorming` and `superpowers:writing-plans`, the two the triage prompt always offered it, so an upgraded deployment keeps its behaviour; every other row, and a deployment without that row, gets none | `agent_definitions.triage_may_add_skills` |
| 143 | behaviour from agent and template rows, not built-in names (#167): `pipeline_templates.fixed_route` (NOT NULL, default false), `offered_to_triage` (NOT NULL, default true), `job_kind` (an override; NULL reads the route), `delivers` (NOT NULL, default `''`) and `leader_agent`; `agent_definitions.station` (NOT NULL, default `desk`) and `quest_template` (NULL none, `''` a task naming no template); `jobs.coding_agent` and `jobs.leader_agent`, which plan_route records and progression credits from. Every row gets what the code said of its name before: the ten specialist templates fixed and not offered, the leaders and deliverables of the old maps, the old stations and guild tasks; a slop-cleanup job coded by the Slopmaster and every job led by its template's old leader. A template named `qa`, `onboard` or `pr-review` is renamed `<name>-template` | `pipeline_templates`, `agent_definitions`, `jobs` |
| 144 | each Slop-O-Meter score's configuration version: `slop_meter_scores.config_version` (NOT NULL, default `''`), a digest of the `slop_meter` settings the score was computed from (#169). The meter compares it with the version each repository reads now and rescores the ones that differ. A score stored before it names none, which no digest equals; the first run after the upgrade, which scores every repository it reads, records one | `slop_meter_scores.config_version` |

Note: LangGraph's checkpoint tables (`checkpoints`, `checkpoint_blobs`, `checkpoint_writes`) are created and mutated by `langgraph-checkpoint-postgres` / `orchestration/checkpoint.py`, outside `embry0_migrations` entirely — they're excluded from this ledger by design, not an oversight.

Expand Down
Loading
Loading