CHANGELOG.md
Rama main · réplica de lectura del repositorio original.
# Changelog
All notable changes. Format: [Keep a Changelog](https://keepachangelog.com); versioning: semver.
## [Unreleased]
## [0.6.0] - 2026-10-09
The plain-language redesign (slices 2-7), shared-GPU resource leases, Score
reliability fixes, and a license change: Core is now under the Prosperity
Public License 3.0.0 from Batoncadence LLC (source-available; free for
personal and noncommercial use). Releases up to and including 0.5.0rc1 stay
MIT. Release notes: docs/RELEASE-NOTES-0.6.0.md.
### Added
- Exclusive resource lease arbiter for shared GPU nights (#125).
### Fixed
- Score jobs dispatch at priority 50, above normal board traffic (#139); a
late completion event gets a 15-minute grace before a run blocks (#141); a
blocked or failed run pushes the owner once (#142); stale alerts no longer
replay (#143).
- The ntfy topic lookup from AWS Secrets Manager is bounded (3 s / 5 s) and
cached, so it can't hold up gateway startup (#144).
- Helpers: a Windows venv launcher and its child count as one copy, so healthy
helpers aren't shown as Stuck and Fix it can't stop the real worker (#147).
### License
- Core moves from MIT to the Prosperity Public License 3.0.0; licensor
Batoncadence LLC; COMMERCIAL-LICENSE.md and a draft CLA added (#140).
### Redesign
- `bitcadence start` now runs quietly: no console window, a tray status light
(green/amber/red plus a word), a one-time loopback sign-in link instead of a
pasted token, and a per-user start-at-sign-in entry (no administrator).
First run ends on a "You're all set" screen.
- `mco register` failures are plain sentences; `helpers add` undoes its
registration if no credential could be saved; cron errors are recognised by
type, not by message text.
### Changed
- **Connect an AI** page and `bitcadence connect [claude|codex|gemini|antigravity|cursor|other]`:
one tap per app finds it and adds BitCadence to its connection settings, keeping a
`.bak` of the original first. Adds Codex (`config.toml`), Antigravity, `--disconnect`,
`--test` and a copyable code for "another app". New `/api/connect-ai` routes.
- **Ask for something** replaces the drag-and-drop workflow builders. The console
page and `bitcadence ask` share one planner: a plain-language request, a drawn
plan, one Approve, and light tweaks (remove a step, always ask me, make it
repeat). New `/api/ask/plan` and `/api/ask/start`.
- **Helpers** page and `bitcadence helpers`: friendly names, a health light with a
word, and what each helper is doing in plain words. Add a helper (same path as
`bitcadence helpers add`, the sign-in is never shown in full) and **Fix it**,
which finds a locked worker log or a duplicate wake process with a dry run first
and repairs only after a confirm (`bitcadence helpers fix`, also part of
`bitcadence fix`). New `/api/helpers`, `/api/helpers/add`, `/api/helpers/fix`.
- **Schedules** page and `bitcadence schedule add|on|off`: pick what, how often and
what time, and see "Every weekday at 2:00 AM" instead of a cron line. Written to
`~/.mco/schedules.yaml` as text so comments survive. New `/api/schedules`.
- **Approvals** show no raw 403. A missing approver right gives one sentence and a
one-key "Fix it? [Y/n]" in `bitcadence approve` and `bitcadence fix`; the console
explains it in words. The repair is terminal-only and local-database-only.
- **Settings** use plain labels; the address and masked sign-in appear only under
`bitcadence settings --show-advanced` or **Show advanced** in the console.
### Removed
- The Flow Control page (`/flow`) and the console's visual workflow builder.
Workflow YAML still runs through `bitcadence ask --file` and `mco workflow`;
`mco gui --flow` now opens the console.
## [0.5.0rc1] - 2026-09-22
Public preview of the new Jev-enabled BitCadence. This is a release candidate,
not the stable 0.5.0 release: the live AWS release-candidate chaos board remains
a separate gate. Jev is optional and disabled by default. The shipped routing
integrations are advisory, and operational integrations are annotation-only.
The website and Jev setup guide explain the two-speed design and BitCadence's
scope boundaries.
### Added
- **B01: BitCadence can now build itself, under governance.** Score v1 gained a
`repository:write` capability: a Score task can commit real changes to an
isolated, disposable git worktree/branch — never `main`/`deploy/local`, never
pushed or merged by the automation itself — enforced by a hardcoded denylist,
an exact-parent-commit check, and a path allowlist inside the adapter, not
just operator discipline. Every commit requires a human-issued, signed grant
(`GrantService`) scoped to the exact run and score digest; `authenticated_human()`
categorically refuses any agent bearer token, so no automation can grant
itself write authority. On 2026-09-18 this produced BitCadence's first real
(non-adversarial-proof) self-authored commit: antigravity wrote the change,
claude independently reviewed and accepted it, a human issued the grant. Two
pieces of tooling replace what was a one-off hand-run script for that first
run: `mco score start`/`mco score tick --live-repository-write` (opt-in;
every other invocation stays exactly as dark-by-default as before), and a
real operator console at `GET /api/score/grants/console` for issuing grants
from a form instead of a hand-pasted DevTools snippet. A blocked/failed Score
run has no resume path by design — governance state only ever moves forward
or stops, never silently retries.
- **Lease TTL adapts to the work instead of one flat window.** The default lease
(`MCO_LEASE_TTL_SECONDS`) is raised from 15 minutes to one hour: careful work
(a full review, a large refactor) routinely outlived 15 minutes, so a live
worker's lease silently expired mid-task and its own completion 409'd on a
fence it never saw. `mco_lease` / `mco_lease_next` / `mco_renew` now take an
optional `estimated_seconds` - how long the worker itself expects the work
to take, or at renew time how much *more* it needs - and the gateway adds a
buffer (`MCO_LEASE_BUFFER_FLOOR_SECONDS` / `MCO_LEASE_BUFFER_FRACTION`) and
uses that as the lease's actual TTL, clamped to
`MCO_LEASE_MIN_TTL_SECONDS`/`MCO_LEASE_MAX_TTL_SECONDS` (5 min–4 h by
default) so neither a tiny nor a runaway estimate produces a useless or
near-permanent lease. `reclaim_stale_leases` needed no change: it always
reads the `lease_expires_at` a lease or renewal actually wrote, so an
abandoned job still comes back to `pending` at any TTL this can produce.
- **A chain that forgets to hand off is now caught.** The delivery watchdog only
saw jobs that exist, so a worker finishing its own job and never dispatching the
next one left an empty board that looked healthy while the mission was dead
(a real Score packet chain sat two hours that way). Send a chain link with
`mco_send(..., expects_successor=True)`: if its worker completes and no follow-up
job appears within the stall window, the gateway records a `chain_stalled` audit
event, broadcasts it, hands the stall to `MCO_CHAIN_STALL_TO_ROLE` (default
`chief`, blank to disable) and pushes once.
- **Notification budget.** Every job transition pushed to ntfy, which exhausted
the server's rate limit (73 dropped with 429 in one day) and buried the
escalations. Routine pushes now share an hourly budget (`NTFY_MAX_PER_HOUR`,
default 20) and identical messages repeat at most every `NTFY_REPEAT_AFTER`
seconds (default 600); priority >= `NTFY_URGENT_PRIORITY` (default 4) ignores the
budget, so a stuck job or a human gate is never dropped for a job-created notice.
- **Score runs advance without anyone typing a tick.** The gateway can now drive
the conductor itself: every `MCO_SCORE_SWEEP_SECONDS` it advances each
unsettled run by one tick, wired into the lifespan beside the delivery
watchdog and run in a worker thread so the SQLite and board work never touches
the event loop. **Off by default** (`0` or negative disables it), so upgrading
a gateway never silently starts driving runs. A run is only swept by the
conductor credential that started it - another conductor's run is skipped, not
blocked - and accepted, blocked, failed and launched runs are left alone. One
failing run is logged and named in `/readyz` (`checks.score_sweep.failing_runs`)
while the rest of the sweep continues; a failure of the sweep itself makes the
gateway report not ready.
- **Interactive sessions hear about their MCO work.** `python -m mco.hooks.inbox
--instance <id> --role <role>` is a Claude Code SessionStart/UserPromptSubmit
hook: it tells the session (and the user) about jobs pinned to it, or addressed
to its role and untaken for 5 minutes, then only new arrivals, checking the
gateway at most once a minute on prompts. It exits silently on any failure and
frames job titles as data the model should surface, not act on.
- **Agents report what they are doing, not just when they were last heard from.**
`/api/agents` (and `mco_agents`, `mco agents`) adds `state`: `working` (holds a
lease), `standby` (reachable, nothing waiting), `broken` (reachable, but work
addressed to it has stalled past the delivery window or was rerouted away in the
last hour, with `state_reason`), `offline`, or `disabled`. A waker holding the
broadcast socket now counts as online (`connected: true`) even though it never
polls. The delivery watchdog only reroutes to roles with a `standby` or `working`
agent, and `/readyz` lists `broken_workers`. Derived at read time; no schema change.
- **Delivery watchdog.** The gateway now makes sure pending work reaches a worker
without a person telling an agent to look. A job left PENDING for
`MCO_DELIVERY_STALL_SECONDS` (default 600; `0` disables) is re-broadcast to wake
its role again; if still untaken after another window it is rerouted in place to
the first `MCO_ROUTE_FALLBACKS` role with an online agent (e.g.
`codex:claude, antigravity:claude|codex`), up to `MCO_DELIVERY_MAX_REROUTES`
(default 2). When nothing can take it, the job is escalated once: a
`delivery_escalated` audit event, a `job_undeliverable` broadcast, and an ntfy
push. Set `input_payload.no_reroute` to keep a job on its original target. All
steps are audit events, so restarts neither repeat nor forget them.
### Fixed
- **A hidden error dialog no longer freezes the desktop app.** Started to the tray,
a failed start showed a modal popup that blocked every later action, including
start requests, until someone clicked it. Errors now go to the status line while
the window is hidden. Start-all also keeps going past a worker that fails, and
waits up to 30 seconds for the gateway instead of giving up after one 1-second
probe. Previously a single slow probe left every later worker unstarted.
- **A crash-looped worker no longer stays down forever.** The supervisor still
latches a worker that fails five times in five minutes, but now retries it after
a 15-minute cooldown (and on the first tick after restart when the failures are
old), instead of waiting for a manual `reset` that nobody knew to run.
- **Unreadable token files are named as such.** A waker whose
`~/.mco/tokens/<instance>.token` exists but denies the current user (written by
an elevated or different account) now says so and how to fix the permissions,
instead of reporting "no token" and suggesting a rotation.
### Changed
- **Breaking: audit failures now fail the triggering operation.** A failed audit
write or required S3 acknowledgement no longer returns success. The database
mutation may already be committed; its transactional outbox preserves evidence.
Retry the same attempt and result after restoring the sink, rather than creating
duplicate work. The kill switch still fences active attempts during a sink outage.
- Audit signing keys prefer the encrypted vault. Environment injection requires
`MCO_ALLOW_ENV_AUDIT_KEY=1` and emits a warning; ECS explicitly opts in for its
Secrets Manager injection. An inaccessible vault cannot be bypassed this way.
- Evidence COMPLIANCE retention defaults to **one day**, including Terraform.
Existing locked versions keep their original retention. A durable S3 checkpoint
avoids re-uploading acknowledged events across restarts; chain verification
still reads the full history to detect corruption and rollback.
- AWS lab runs only through manual dispatch on `main` or the completion candidate.
Bootstrap trust explicitly allows those two refs; remove the candidate after merge.
- **Renamed: BatonCadence is now BitCadence** (`bitcadence.ai`). The tagline is
now *"Every agent. One beat."* — the drumline metaphor stays, the relay-race
pun goes. The Python distribution is `bitcadence`; **the CLI is still `mco`**,
every `MCO_*` environment variable is unchanged, and config still lives in
`~/.mco/`, so existing installs keep working without edits.
- **Services register under the new brand** — `BitCadence-gateway`,
`bitcadence-gateway.service`, `com.bitcadence.gateway`. Machines installed
under the old names are still discovered, addressed, and uninstallable:
`mco service status|restart|logs|uninstall` resolve `BatonCadence-*` units,
tasks, and plists alongside the new ones. **To move a machine onto the new
names, run `mco service uninstall` then `mco service install`** — an
in-place upgrade leaves the old-named service running (and working).
### Fixed
- **Security (dropbox isolation):** `POST /api/jobs/lease` now enforces the
same addressee rule as the inbox and the completion endpoint - an agent may
only lease jobs addressed to its own role (or to its specific instance).
Previously the lease endpoint checked only org isolation, so any authenticated
agent could lease another agent's pending job; completion was still blocked,
so the job would strand in `leased` state and record a false actor in the
audit trail. The check mirrors the inbox filter, so a same-role sibling
instance is still blocked from an instance-targeted job.
## [0.3.0] - 2026-07-01
The parity release: everything the API can do, the CLI and the console can
do too - plus the external security audit remediations.
### Added
- **`/metrics`** Prometheus endpoint (jobs by status, approval queue depth,
agents registered/online, kill-switch, database state); optional
`MCO_METRICS_TOKEN`. `MCO_LOG_JSON` for structured JSON logs.
- **`mco service install/uninstall/status`**: boot-persistent gateway via
Windows Task Scheduler, Linux systemd --user, or macOS launchd.
- **`mco upgrade`**: schema migration runner - LocalStore needs none;
Postgres auto-applies via DATABASE_URL + psycopg (recorded in
schema_migrations) or emits a combined script for the Supabase SQL editor.
Migrations now ship as package data.
- **CLI parity**: `mco recall` / `mco remember` (Drumline from the
terminal), `mco settings` (the Control Panel whitelist without a
browser), `mco reset-token` / `mco deregister`, `mco orgs`, and
`mco watch` (live WebSocket event tail with automatic reconnect).
- **Console: Memory screen** - search/tag recall of the Drumline shared
context plus an add-entry composer.
- **Console: Activity screen** - the cross-job immutable audit trail with
client-side stats (24h throughput, failure rate, approval latency),
backed by the new `GET /api/events` feed (org-scoped, job-enriched).
- **Console: Fleet admin** - register agents (one-time token), rotate
tokens, remove agents, and move agents between orgs (host operator,
one-way by design); **Tenancy card** to view/create orgs.
- **Console: connector operations** - health dots, and "Sync now" next to
"Test connection"; new Connectors settings group (ServiceNow/Dynatrace)
with a server-side `test-connector` probe.
- **Console live updates** over `/ws/broadcast` with polling fallback
(4s -> 30s safety net while the socket is up). The gateway accepts
token-only WebSocket auth (identity resolved from the token hash).
- **Drumline dedup**: identical title|content|role returns the existing
entry (SHA-256 `content_hash`; migration `2026-07_drumline_dedup.sql`;
graceful fallback pre-migration). `mco doctor` warns when the migration
is pending.
- Reproducible console build: `scripts/build_console.py extract|build|verify`
with editable sources in `src/mco/console_src/` (verified in CI).
### Security (external audit remediation)
- Drumline content is sanitized before storage: prompt-injection syntax is
neutralized in place (angle brackets to lookalikes, broken code fences,
tool-call markers dropped) - content survives, the teeth don't.
- Tenant isolation for Drumline recall pushed into the SQL query for named
orgs, with the Python filter retained as defense-in-depth.
- WebSocket disconnects are race-safe; `max_retries=0` is honored;
`supabase` pinned `<2.0.0`; routes/auth import cycle removed.
### Changed
- Drumline recall recency bias capped at 20% so relevance dominates.
- Console job retry uses the dedicated `POST /api/jobs/{id}/retry`.
- CI test matrix now covers Python 3.11 and 3.14.
## [0.2.0] - 2026-06-12
The enterprise-suite release: RBAC, SSO delegation, editions, the Context
Exchange, a full web Control Panel, and an SDK.
### Added
- **Scoped-token RBAC**: every endpoint declares scopes; `mco register
--scope` issues least-privilege tokens; role-derived defaults keep
pre-RBAC installs behaving identically.
- **Trusted-header SSO delegation** (enterprise): authenticate humans via
the reverse proxy you already run (oauth2-proxy, Cloudflare Access,
Authelia) - off by default, optional constant-time proxy secret.
- **Edition model**: community / team / enterprise in one codebase,
inferred from config or pinned with `MCO_EDITION`; `mco edition` prints
the feature matrix.
- **Context Exchange**: structured handoffs ({summary, decisions, files,
gotchas, follow_ups}) stored verbatim and weighted above mined context;
workflow runs stamp every step, and workers inject the whole predecessor
thread deterministically - cross-vendor continuity.
- **Web Control Panel** at `/dashboard`: lock screen, agent
register/rotate/edit/delete with tokens shown exactly once, workflow
YAML submission, server-driven settings (governance, Drumline, presence,
tenancy, edition, security, notifications), connector health/sync,
retry on failed jobs, MCP/worker connect instructions per token.
- **Agent presence health checks**: polling is the heartbeat; agents
silent past `MCO_AGENT_OFFLINE_AFTER` (default 300 s) report offline with
"seen Xm ago" in both the dashboard and `mco agents`.
- **Org allowlist** (`MCO_ORGS`): tenants are minted deliberately in
Settings, never implicitly by a typo at registration.
- **Agent SDK** (`mco.sdk.BatonAgent`): a worker in fifteen lines with
atomic leasing, thread-aware prompts, structured handoffs, and
governance-correct failure reporting.
- **Air-gapped install**: `make-offline-bundle` scripts produce a
repo+wheels archive; installers auto-detect `offline/wheels` and install
with `--no-index`.
- **Lifecycle commands**: `mco start` (detached background gateway with
health-checked startup), `mco restart`, `mco doctor` (end-to-end install
diagnosis), `mco --version`.
- One-command installers (`curl | bash`, `iwr | iex`) with existing-install
detection; Hermes-style install UX on the website and README.
- SECURITY.md, CodeQL, dependabot, release pipeline (PyPI + GHCR).
### Fixed
- Setup can no longer orphan the secret store (key is persisted before the
store is created); locked-store warnings are single and actionable.
- `mco stop` no longer crashes (psutil was missing from dependencies).
- WebSocket honors `MCO_LOCAL_TOKEN` parity with HTTP auth; the worker's
raw shell executor is opt-in (`MCO_ENABLE_SHELL_EXECUTOR`).
- Web agent list shows all orgs to the host operator (parity with
`mco agents`).
### Changed
- Distribution renamed `mco` -> `batoncadence` (the CLI is still `mco`).
- Config home is global (`~/.mco/.env`): `mco` behaves the same from any
directory.
## [0.1.0] - 2026-06-10
Initial MVP: job board with atomic leasing, multi-vendor executors
(claude/codex/gemini), approval gates, immutable audit trail, escalation,
DAG workflows, Drumline shared context, MCP server, ServiceNow/Dynatrace
connectors, embedded LocalStore, dashboard, 151-test suite.