Set CE caps to three agents
Epic 10745 "Close the identified gaps in Jaah CE". Original request (verbatim): "Close the identified gaps in Jaah CE". Settled inputs: PRD (Task 10746) and Architecture (Task 10747). Requirement and AC ids below are the PRD's; section refs (§) are the Architecture's. Read them with task_read on 10746/10747 if you need more than is quoted here.
## Requirement (verbatim)
R3 — CE caps: 3 agents, 3 provider accounts (PRD, verbatim). `CE_MAX_AGENTS` becomes 3 (from 10); `CE_MAX_ACCOUNTS` stays 3. Both the API copy and the node's own copy agree. Operator: "Set CE caps that fit the Free, Team and Business ladder." → "3 agents, 3 accounts".
R8 — Pre-public checklist (PRD, verbatim). `infra/community-edition/RELEASE-CHECKLIST.md` gains three human items before the public flip: legal review of LICENSE and the Jaah trademark; update the pricing doc's "platform repository is private" line; add CE to the site.
## Scope and approach
Child C4 of Architecture §7 (Architecture §4 + R8).
**Agent cap.**
- Set `CE_MAX_AGENTS = 3` in `apps/api/app/edition.py` and `apps/jaahd/edition.py`. `CE_MAX_ACCOUNTS` stays 3.
- Three enforcement points already read the constant, so no logic changes: the dispatch cap (`org_limits.DispatchBudget.take`, requeue with no attempt), the console door (`org_limits.require_headroom` → `ce_caps.refusal("agents")`) and the node (`apps/jaahd/ce_caps.capacity_refusal`).
- Fix the tests that pin 10.
**Delete the CE worktree cap.** Per D2: "Worktrees are not limited. Only concurrent agents. There are no existing CE installs." Remove:
- `apps/jaahd/ce_caps.worktree_refusal`;
- `pool_worktree_count`, if it has no other caller;
- its caller at `apps/jaahd/worktree_mechanics/lifecycle.py:470`;
- the "pool worktrees" node message;
- their tests (`apps/jaahd/tests/test_ce_caps.py`).
**Decouple the pool ceiling.**
- `ce_bootstrap._ensure_pool` uses a module constant `_CE_PORT_BLOCK = 11` for BOTH the pin (`port_block_size`) and the comparison (`pool_bound(...) != _CE_PORT_BLOCK - 1`). If only one changes, every boot rewrites the overrides.
- Fix the docstrings that tie the pool to the agent cap (`ce_bootstrap.py:17-18,248`; `apps/jaahd/ce_caps.py:4-5`).
- `_ensure_runner_caps` keeps reading `CE_MAX_AGENTS`.
**Copy.** Change `infra/community-edition/README.md:4` to "3 agents" and sweep every user-visible "10 agents" string.
**Release checklist.** In `infra/community-edition/RELEASE-CHECKLIST.md`, add a section "Before the public flip" with three unchecked one-line human items:
- legal review of LICENSE and the Jaah trademark;
- update the pricing doc's "platform repository is private" line;
- add CE to the site.
If C1's allowlist (`PENDING_SWEEP`/`EDITION_WIDE`) exists when you rebase and lists `worktree_refusal`'s site, delete that entry with the code.
Credentials & reach: (Architecture §10 rows, verbatim)
- Build, check (incl. gitleaks), tooling + app test suites | worktree only; gitleaks at `~/.local/bin/gitleaks` on node h2 | verified (binary present on h2)
- Jaah Deploy watch per child PR | `jaah-forge` read verbs (`pr checks`, `ci log`) | verified (same forge identity and read probe as above)
Out of scope: (PRD §3, verbatim — do NOT touch)
- MUST NOT make `jaah-ai/jaah-ce` public, change repo visibility, or run a `ce-mirror` publish.
- MUST NOT edit LICENSE text or any legal page (legal review is a human item).
- MUST NOT edit `docs/pricing.md` or the marketing site (deferred to the flip; not in this repo).
- MUST NOT add a second secret scanner (trufflehog etc.).
- MUST NOT add an env var, setting, build arg or runtime flag that selects an edition, enables a feature or moves a cap.
- MUST NOT change cloud behaviour or cloud plan entitlements/pricing; the R2 guard rewrite is behaviour-preserving for `cloud`.
- MUST NOT ship `.claude/skills/` (translate, marketing-copy) — named a deferred follow-up below.
- MUST NOT build an on-prem or enterprise edition — only make the map able to describe one.
Architecture boundaries:
- D4, D5: no monorepo file moves. `portfolio/fleet/*.md`, `docs/policies/context-architecture.md`, `.claude/agents/*.md`, hub pointers, `tools/check_context.py`, `tools/portable_standard.py`, `infra/local/Dockerfile.api` and `infra/host/fleet-harness/reconcile.py` stay untouched.
- D1: keep schema, strip logic. The enterprise ORM models and the squashed baseline migration stay. No edition-forked schema, no new migration.
Done means:
- AC3.1 → verify: built tree: `grep -n CE_MAX apps/api/app/edition.py apps/jaahd/edition.py` shows `3` and `3` in both.
- AC3.2 (enforced end-to-end) → verify on an installed CE: queue 4 tasks on one project; observe exactly 3 runner sessions live and the 4th task requeued (no attempt spent) until one ends; start a 4th console agent while 3 run → refused with "Jaah Community Edition runs 3 agents at once. For more, use Jaah Cloud." Add a 4th provider account → refused with the accounts message. (Here: unit/integration tests cover the three enforcement points at cap 3, with the exact refusal text. The installed-CE observation is C6's.)
- AC3.3 (upgrade path, reduced per D2) → a 4th pool worktree is created on a CE node; a 4th concurrent agent is not. Verify with jaahd tests:
- in CE mode, worktree creation succeeds with ≥10 existing pool worktrees;
- `capacity_refusal` refuses the 4th live agent;
- running `ce_bootstrap` twice in a row leaves the pool overrides unchanged on the second run (no re-pin).
- AC3.4 (copy) → verify: `infra/community-edition/README.md` and every user-visible string state "3 agents"; grep for "10 agents" in the tree returns nothing.
- AC8.1 → verify: read the file; three unchecked items, each one line naming the owner action.
- Quick gate `./dc check quick` green.
- `python3 tools/community_edition/build_tree.py $T && python3 tools/community_edition/check_tree.py $T` exits 0 (AC1.2: import closure intact).
- The PR's Jaah Deploy on GitHub succeeds. If not, fix it and re-merge; leave a cancelled or superseded deploy alone.
Outcome
CE_MAX_AGENTS is now 3 in both edition copies. The worktree cap is removed, and the pool ceiling (_CE_PORT_BLOCK) is separate from the agent cap. The README says 3 agents, and the checklist has a pre-public-flip section. Quick gate and changed-area tests are green. PR #7164 is queued in the merge lane. Memory: none applied.
Artifacts
Activity
- Draft
- Ready
- Runner started
- Runner ended (done)