openvibers/openvibe.contracts CHANGELOG.md

CHANGELOG.md

main 417.3 KB · 5018 lines · markdown

Changelog

0.423.0 — 2026-11-13

  • Media lists media.config.manage among the capabilities it enforces: Media now serves its settings to the owner's
    Setup at /internal/config (Media #441), so Network's setup and guide read it like every other service (the guide
    said "OpenVibe.Media did not answer"). The capability itself has existed since the owner settings proxy.

0.422.0 — 2026-11-13

One evaluation loop: entrants, matches, and ratings that separate the model from the harness
(compare-arena-ecosystem.md). The owner, 11-13: the Arena "should still use our multi purpose shared universal agentic
multi harness system", and comparisons should do "harness vs harness and model vs model … better".

  • bench.entrant@1: what competes.
  • Kinds: a model (on the neutral harness), a harness (over a fixed model panel), an agent (harness + model +
    settings, a blueprint version), or a product.
  • Stable ids: model:…, harness:…@version, agent:harness+model#confighash, product:….
  • bench.match@1: one task given to two or more entrants under the same budget.
  • Each side carries its receipts: cost, tokens, TTFT, TPS, wall time, tool calls, and the length and markdown style
    covariates.
  • shown records the order the sides were displayed in; blind records whether names were hidden.
  • Judgements come from human_pairwise, audience_poll, implicit (merged, accepted, copied, kept, retried,
    stopped, edited), test_suite, rubric and game_outcome. A voter is a keyed hash with a quality weight, never
    an id.
  • Sources: arena, chat, codes, live, games, exchange, space, bench and check jobs.
  • bench.rating@1 1.1.0 (all optional):
  • entrant_kind and style_control;
  • factors: an agent's strength split into model, harness and interaction, each with an interval;
  • cost_per_solved_usd, tokens_per_task, ttft_ms and tps percentiles, reliability (pass^k), matches,
    as_of.
  • Event bench.match.recorded v1, produced by Bench.
  • agents.play@1 1.1.0: blind hides the roles' names until the first judgement. This is the race play an Arena
    round runs on the agent engine.
  • Fixtures:
  • entrants: an agent, a harness, a model;
  • matches: an Arena vote, and a Codes race judged by its tests and then merged;
  • a rating with its factors;
  • invalid: an agent without its harness, a kind nobody has, a one-sided match, an unknown judge.

0.421.0 — 2026-11-12

Every AI call, measured everywhere (ai-metrics.md).

  • ai.call.recorded@1 1.1.0 adds, all optional:
  • operation (chat, completion, embedding, image, image edit, speech, transcription, translation, rerank,
    moderation, decision, realtime, batch, tool);
  • streamed, and tps (the decode speed after the first token);
  • queue_ms;
  • task, task_id and task_ms, so cost and time add up per task;
  • harness, and place (provider, the person's machine, community, a plan, OpenVibe's hosts);
  • error_class, fallbacks and cache_hit (an exact-cache answer);
  • tool_calls and region.
  • ai.call-report@1: up to 100 calls a product made without OpenVibe.AI (Actor, Codes harness turns, Link's local
    models through Bot, Vibe). They go to AI's POST /api/v1/usage/calls. AI prices any that bring no price, records
    each once (by system + run or turn id) and publishes ai.call.recorded@1. The capability is ai.usage.report.
  • report.ai-performance@1: how calls performed for one group (model, provider, operation, system, task, place,
    harness):
  • success, fallback, streamed and cache-hit rates;
  • TTFT, latency and tokens per second at p50, p90 and p95;
  • tokens, charged and list cost, and cache savings;
  • cost and time per task;
  • the top errors.

Public answers group by model, provider or operation, with at least 20 calls.

0.420.0 — 2026-11-12

One agent system, measured. These contracts carry the decisions in one-system-v2.md, which come from reading 24
open agent projects.

  • agents.blueprint@1 1.1.0:
  • rules.sandbox (read-only · workspace-write · full) and rules.network (none · public · listed domains): Codex's
    three axes per run, next to the level that was already there.
  • starters: one-tap first asks, Goose's activities.
  • agents.permission-rule@1: a permission as data, from Gemini CLI and OpenCode.
  • It has an action (a tool, or a pattern), a resource, an effect (allow · ask · deny), and when: attended,
    unattended or any.
  • The last rule that matches wins.
  • Unattended work never waits on an ask.
  • The floor asks whatever a rule says.
  • agents.job@1: one job placed on a machine. Its kinds are check, review, build, eval, improve, desk and model.
    It carries:
  • what it needs from the place, and its trust (public code only, or the owner's own machines);
  • its budget, its placement with the reason, and its attempts;
  • a result with a named exit and a link to the masked log.

Secrets never travel in a job.

  • agents.run@1 1.4.0: metrics, with:
  • the charged cost first (an estimate only where nothing was charged);
  • tokens with cache reads and writes, latency and steps;
  • a named exit;
  • the checkable evidence of success (a test, a schema, a grader, a person, a Decision with its probability).
  • Fixtures: a blueprint with sandbox, network and starters; three rules; a check placed on a shared node, and a
    queued review; a run with metrics; and refusals for each.

0.419.1 — 2026-11-12

actor.agent.manage lists the blueprint routes Actor serves: the person's blueprints and the public gallery, one
version, the draft, publish, remix, the install screen, install, and an installed agent's version
(agents.blueprint@1, agents.install@1).

0.419.0 — 2026-11-12

Make your own agent: agents.blueprint@1. An agent anyone can read, change, share and run anywhere, as one small
document of ten parts:

  • face (Design);
  • brain (Exchange): auto, a size or one model; the ladder rungs it may use; the most it pays; an advisor;
    Decisions;
  • knows: instructions with {{inputs}}, skills, knowledge, and examples for Try it and Bench;
  • hands: each tool allowed or ask first, plus tool search. The tools are ov: product tools, tools: apps,
    connect: apps, the installer's own mcp: servers, machine: files/shell/desk/browser/screen, robot: manifest
    commands, harness: coding harnesses and agent: other agents;
  • places: none, own, shared, openvibe or sandbox, and what the work needs; never a machine by name;
  • memory;
  • rules: level, budget, who may ask;
  • when: the Source kinds plus event and schedule;
  • makes: answers, an exact shape, and whether it is served to other agents over A2A or as an MCP tool;
  • team: a play whose roles are other blueprints at fixed versions.

Inputs and needs sit above the parts. A blueprint carries no secret and grants nothing. A published version never
changes. Design note: agent-blueprints.md.

  • agents.install@1: a person's own agent, made from one blueprint version. It records the inputs they filled,
    the asks they agreed to (by key) and the machines they chose. It says whether a version that asks for no more is
    taken without asking, and holds a pending version that waits for their yes.
  • agents.run-start@1 1.2.0: blueprint runs a version once without installing it (Try it). Every tool asks
    first.
  • agents.run@1 1.3.0: agent.blueprint, the version a run's agent was made from.
  • Fixtures:
  • five blueprints: Clip finder, Vibe as bp_vibe, a draft with a grader team, a tool for other agents, a robot
    driver;
  • ten refusals: full level without a budget, a tool nobody has, a schedule without a time, served as a tool
    without a shape, a team role without a version, published without a date, a key in the brain, a machine by
    name, an exact pick without a model, no instructions.

0.418.1 — 2026-11-12

LOOI's manifest, exactly as the P7 list says it, and not frozen until Maticus has checked it. The head has its own
delivery window (1–300 ms; 500 ms is its lifetime on the Live tray, head-only profiles use 300), the top-level
battery (0–100, polled) is a reading of its own, and p7_battery's unverified is listed as a field that comes only
with a read at connect or a stale value. bot.robot-manifest@1 readings take optional: the fields that come only
sometimes. 0.418.0 marked the example frozen before the maker's check; frozen is now false until he confirms it.

0.418.0 — 2026-11-12

A robot's own manifest: bot.robot-manifest@1 (public, ADR-043) is what a robot's driver says the robot can do,
written and versioned by the driver's maker, so a new control is a version bump of the manifest instead of an
OpenVibe release (the plan in Maticus's LOOI thread, 11-10; his P7 command list on 11-12 is its first frozen version).

  • Commands: kind, class (motion, state, action), the value's fields and ranges, lifetime_ms, the
    delivery_ms window Bot gives it, min_left_ms on arrival, rate_per_s, release (stop, hold, none;
    motion must stop or hold), latched, the telemetry key that confirms it, and the control the panel draws
    (stick, slider, toggle, button, pad). An actuator names which one.
  • Telemetry: a key, its fields (ranges, boolean, string, ms, integer, number, or a list of values),
    unit and range, source (poll, push, connect), fresh_ms, and its control (meter, readout, badge, list).
  • frozen: true once the maker and OpenVibe have checked a version against the driver's real command list.
  • ui.surface@1 parts say what they send or show: optional command and reads, in the manifest's terms, so
    OpenVibe AI knows a part's ranges, lifetime, release and rate when it arranges a panel or writes a control. They
    grant nothing: the product's gate still checks every command. A new example is LOOI's panel built from its manifest.
  • Fixtures: LOOI 1.0.0 through the P7 tray (drive 500 ms life, delivery 1–300, release stop; head 500 ms, hold;
    headlights delivery 1–250, 50 ms left, 2 a second, latched; battery by poll with at in ms; who is driving), and
    three refusals (motion without a release, an actuator without its name, motion that is never released).

0.417.0 — 2026-11-12

The agent engine's next shapes: who asked, what a run continues, how several agents share one ask, and where the
money went (agent-engine.md §§3-5, from the code study). Every field is optional and the new contracts are new.

  • agents.run@1 1.2.0:
  • mandate: an ask taken in from the feed, a room, an issue: where, by whom, explicit or inferred, and the scope;
  • lineage: a fork, a hand-off or a regenerated turn, with the run and turn it came from;
  • play and role;
  • agent.capabilities;
  • cost.by: the spend on each rung of the ladder (machine, plan, key, allowance, credits).
  • agents.step@1 1.2.0: turn.
  • agents.run-start@1 1.1.0: play, lineage, and mandate (from intake only).
  • New agents.play@1: a play as data, made of roles, phases, checks, a stop rule and a budget split. Fixtures:
    advisor, grader loop, fan-out.
  • New agents.source@1: one place asks are taken in: who may ask, what counts as an ask, the run it becomes, its
    budget, and how the run answers. Fixtures: the owner's feed, Vibe in a room.
  • Stop is a plain control. On small hobby robots, the panel's Stop is one ordinary, optional control that sends
    the machine's own halt:
  • bot.robot@1: the description and the old latch field say it is legacy (always false); schemas are unchanged.
  • bot.device-message@1: the old latch frame and the estop_* fields are described as legacy names devices may
    still send, not as a remote latch; Bot's config always sends the latch false.
  • bot.command-result@1, bot.robot-control-result@1, bot.robot-manage-result@1, bot.command.refused@1: the
    old stop endpoint and refusal code are gone from the descriptions.
  • bot.estop.set@1 and bot.estop.cleared@1 are retired (fixtures and schemas stay for the contract window).
  • ui.surface@1: Stop is not a required part; ui.action@1 names Stop alone; ui.trigger@1 adds stop.
  • Manifests and ADRs use Stop; bot.resource.control stop sends halt and resume is a calm no-op.

0.416.0 — 2026-11-12

One view API for every content kind (the owner, 11-12): a preview in the feed and a watch on a page count the same
item once, and Report can say how many people watched and how many stayed.

  • Add media.view-request@1: POST /api/v1/views { ref: { service, kind, id }, how: preview | watch | live, seconds,
    of_seconds?, session } on OpenVibe.Media (batched by { events: [ … ] }, at most 20), with the preview/engaged
    thresholds and the 30-minute per-viewer window.
  • Add the media.viewed and media.engaged events: the counted view and the first engagement for an item, with the
    optional Report dimensions site and creator and no IP, user agent or raw session id.
  • Fixtures for both events and the request, and the generated JSON Schema and TypeScript.

0.415.0 — 2026-11-12

One feed for all of OpenVibe: the card OpenVibe.Network serves from /api/v1/feed and /api/frame/feed, and that
OpenVibe.Community's Pulse reads instead of its own collector.

  • Add feed.item@1: each card's stable id, kind (post, pic, clip, video, live, stream, rundown, quest, member,
    chat, event, wiki, update, work, deal, news, report, poll, game, meme, paste, episode, space, avatar, banner,
    follow, site), link, source site, actor and subject, first picture, counts (views, likes, comments, watchers,
    people), live_now, a folded group of the same kind, a report trend, starts_at and follower visibility.
  • Fixtures for every kind, plus invalid ones (unknown kind, missing id, a URL without a scheme, a negative count, a
    subject that is not a usr_ id, private visibility, a one-item group, a trend without a direction), and the
    generated JSON Schema and TypeScript. Additive and new: no existing contract changes.

0.414.0 — 2026-11-12

The whole run (the agent engine, docs/agents-runs.md; design agent-engine.md). The owner, 11-12, with the menu's
Chat · Code · Agents switch crossed out: "one new unified agent … the same agentic system, shared across agents, code
and chat". Everything a person asks an AI to do is one shape: a run, and its thread of steps.

  • agents.run@1 1.1.0, optional fields only:
  • title, kind, ref (its address on the Frame), url;
  • model, where, target;
  • doing, waiting, preview, counts, ended_at;
  • context, outputs, visibility;
  • the agent's face: agent.glyph, agent.hue, agent.avatar_url, agent.harness.
  • agents.step@1 1.1.0, optional fields only: from, author, status, title, glyph, attachments, sources,
    ui (a rich card) and desk.
  • Add agents.run-start@1: what starts a run on any product and on the Frame. Only text is required.
  • Add agents.event@1: a run's stream (run, step, delta, approval, end).
  • Add the event agents.run.updated (@1): the run's snapshot on OpenVibe.Events when what a list draws changed.
  • A conversation is a run that is waiting for a message; an approval and a takeover are the same status with
    another for.

0.413.0 — 2026-11-12

The composer's Reach (Post · Ask · Do, stage R3; Network R3): what its / and @ menus offer.

  • Add frame.commands@1: GET /api/frame/commands?site=<host>&q= on OpenVibe.Network, the command rows a composer
    offers on one site — the network's /ask, /do, /remind and /timer, the site's own from its Frame manifest,
    and a signed-in person's saved composer snippets — each with its hint, the text a pick inserts, its kind and whether
    it needs a signed-in person.
  • Add frame.mentions@1: GET /api/frame/mentions?q=&site= on OpenVibe.Network, at most eight rows for the @ menu:
    public people (with a handle, display name and an OpenVibe.Media avatar only), the person's own agents from the agent
    directory, open OpenVibe sites and Live's public channels. People first; signed out, public people only; no email or
    private account field.
  • Fixtures for both (valid and invalid) and the generated JSON Schema and TypeScript.

0.412.0 — 2026-11-12

One agent system, stage 2: one run shape for Actor, Codes and Run, and the step event that follows it.

  • Add agents.run@1: a run's id, owner, agent and product, parent run, budget (USD, tokens, seconds and steps),
    status (planning, running, waiting, done, failed, stopped), created and updated times, a result summary
    and what it spent. One shape for OpenVibe.Actor, OpenVibe.Codes and OpenVibe.Run.
  • Add agents.step@1: one entry of a run's append-only log (run id, seq, kind think|tool|message|approval|child|file,
    text, the tool call and its input, the result, the step's cost, start and end, and the child run it started).
  • Add agents.approval@1: an ask attached to a run's step (what, the options with their labels, who decided and when,
    and the answer).
  • Add the event agents.step.appended@1: the appended step as the payload, on OpenVibe.Events. The agents namespace
    is hyphen-free because an event type cannot carry a hyphen; Actor registers the producer.
  • Add valid and invalid fixtures for all four, the generated JSON Schema, TypeScript and per-service OpenAPI, and
    docs/agents-runs.md: which field of Actor's tasks/task_events and Codes' run_tasks/codes_session_lines/
    codes_approvals becomes which field of the new shape, and what does not fit (Actor's needs_you, per-step cost,
    split tool call/result entries, and Codes' attempts as one flat run).

0.411.1 — 2026-11-12

  • Add the code category to sources.source@1, sources.item@1, sources.category@1 and sources.source-write-request@1: GitHub repositories (trending, top, new and star-gain rankings) enter OpenVibe.Sources under one category, with a 30-day item window. Additive: no existing field changes, and an older reader ignores the new enum value.

0.411.0 — 2026-11-12

The composer's Frame (Post · Ask · Do; Network #858): what its Model sheet lists and what an Ask sends.

  • Add frame.choices@1: GET /api/frame/choices?task= on OpenVibe.Network, the models a composer offers for a task in
    groups (OpenVibe's, the person's keys, computers and plans), each row with its maker, price per million tokens in and
    out, speed, Report score and its Exchange page, plus the recommended and current choice.
  • Add frame.ask@1: the body of POST /api/frame/ask, the question, the model (a row id or { model, source, machine }),
    the sources to search (web, openvibe, mine, page), the depth and the files and page context it carries.
  • Fixtures for both (valid and invalid) and the generated JSON Schema and TypeScript.

0.410.0 — 2026-11-11

A train of three pull requests: the layouts of make-your-own-controls (#455), Elements stage 1 (#456) and the deep dive
(#457).

  • Add ui.surface@1 (the catalog of a surface's parts, their minimum sizes, styles, bindings and
    never_covers rules), ui.layout@1 (a person's arrangement on one device class, with its name, author and
    sharing), ui.layout-request@1 (catalog, current layout, words and device for the AI task) and
    ui.layout-suggestion@1 (a validated layout with a one-sentence summary, reasons and the model's receipt, or
    an honest refusal with the validator's reasons).
  • Add network.layout.changed@1: the event Network writes in the transaction that sets, saves, renames, deletes,
    shares, publishes, copies or resets one person's layout. It carries the surface, device, layout id, change and
    revision, never account data or layout contents.
  • Add ai.layout.suggest (first-party, POST /api/v1/ui/layout/suggest) and network.layout.read (first-party,
    GET /api/v1/people/:subject/layouts/:surface), and list them in the AI and Network manifests.
  • The fixtures cover a bot-controls catalog, a phone layout, a docked overlay, a suggestion and a refusal, a
    request and the event; the suite checks part ids, theme tokens, never_covers targets and the 44 px minimum. (#455)
  • Add ui.element@1: a look from OpenVibe.Design's components and the theme's tokens, a recipe (triggers, conditions,
    actions), the capabilities the element declares, an optional mod reference (id, version, digest) and its sharing.
    The store assigns the id and revision; a draft has neither.
  • Add ui.trigger@1 (press, hold, double-press, key, gamepad, chat command and text, follow, tip, AI Moment, Rundown
    topic, timer, schedule, robot telemetry and event, stream start and end, viewer count, another element's event) and
    ui.action@1 (robot, chat, screen, stream, AI, Actor, webhook and tip-goal actions), each action carrying the product
    that authorises it. ui.action@1's $defs.capability is the one list an element's capabilities draws from.
  • Add ui.element-state@1: the element's own store (counters, scores, lists), with a revision that grows per accepted
    change and values that are booleans, numbers, short strings or lists of them, never objects.
  • Add live.element.pressed@1 and live.element.state@1: a press with the presser's public name and the trigger, and
    the store with its revision, written by Live.
  • Fixtures cover a gallery dance button, a chat counter, a mod element, trigger and action variants, the state, and
    both events; test/elements.test.js holds the capability list to the action catalog, each kind to its product, and
    the recipe to the element's declared capabilities. (#456)
  • Add ai.deep-dive@1: a deep dive run's report as OpenVibe.AI's design.deep_dive workflow produces it for
    OpenVibe.Exchange and OpenVibe.Design — the question and depth, the seven steps, every source, every capture (a
    private Media object per viewport and theme, with its DOM facts and Expert extras), the per-site analysis, the
    synthesis, the recommendations checked against OpenVibe's rules, and the receipt. Every claim carries its evidence.
  • Add ai.deep_dive.updated@1, the event AI writes on each step transition and at the end, so a page can follow a
    run without polling and Design can attach a finished report. (#457)

0.409.0 — 2026-11-11

  • Define machine access requests, grants and signed token claims; the agent directory, A2A tasks and results; five Network events and four registration and relay capabilities.

0.408.0 — 2026-11-11

The rest of the 0.407.0 train. v0.407.0 was tagged at #451's merge, before the train merged, so the tag holds #451
alone; a tag is never moved, so the three pull requests the train carried are released here.

  • Add codes.task-summary@1 (a task as the Dock's Code tab lists it: id, title, status, mode, repo, times, attempts,
    url, preview and PR links) and codes.task.updated@1, the one event Codes writes on every task status change beside
    the per-state codes.task.* events (#425).
  • Add compare.comparison@1: things, weighted criteria, finite results with required observation dates and HTTPS
    sources, method, source list and update date; register the Compare service, repository and product in Read & ask
    (its group gains an eighth tile) (#428).
  • Add the optional is_test to identity.subject-projection@1 so public surfaces can leave probe and test accounts out
    while their own signed-in views keep working, and the { subjects } answer of Network's
    GET /internal/identity/test-subjects in identity.resolve-result@1 (#450).

0.407.0 — 2026-11-11

  • Add exchange.search.icons: a first-party service searches icon references through the Exchange platform API (POST /v1/search/icons at api.openvibe.exchange, served by OpenVibe.AI) with its own free-search quota and no Exchange key. It reaches the icons route only, never web, image or fetch search, and the receipt names the engine, cost and skipped attempts. OpenVibe.Design holds it for the references shown beside a glyph draft. (#451)

0.406.0 — 2026-11-11

The second train of the day, for the five pull requests opened after 0.405.0 (one line each):

  • Define meme.caption.created for a signed-in person's public caption, with only its id and owner (#444).
  • Add codes.model-plan@1: execution modes, role models and effort, bounded samples and budgets, an escalation ladder
    and required checks; task requests accept a plan or a preset, and task reads can include the resolved plan and
    per-role usage and outcome (#445).
  • Delivery and retry on computer and browser results: bot.command-result@1 and run.session-control-result@1 gain
    delivery (delivered, not_delivered, uncertain) and retry (safe, reason), only not_delivered is safe
    to replay; optional browser origins on browser commands, Run session creation and Bot desk lease creation (#446).
  • Add ai.model-directory-entry@1 and ai.model-directory-list@1 for public model listings, with provider-listed
    models routed off, preview and retired models, and sourced pre-list sightings; a spotted entry never implies
    availability (#447).
  • Keep the exact reply target and its display name in Community comment reads; document the two-reply preview and four
    Chat-compatible file references on comment writes and reads (#448).

0.405.0 — 2026-11-11

This release train carries the contract work that was waiting on the owner's release. One line per carried pull request:

  • Add live.layout@1, the player layout a person keeps in their account: per stream slot and source, the place as fractions of the frame, mode dock or float, the tuck side, mute and the time, at most 60 places (#442).
  • Add chat.command-registration-request@1 and chat.command-registration-result@1 with the active capability chat.commands.register, so a consented app or an Actor agent can register a plain response command for a server its person manages (#441).
  • Catalog OpenVibe.Directory as a live service and site, replacing its parked product metadata, with its public origin, source refresh lifecycle and public-listings-only scope (#440).
  • Add actor.agent-sheet@1 and codes.agent-sheet@1: the owner-scoped agent sheet responses, with current work, daily activity, approvals, computer, schedules and memory where recorded (#439).
  • Extend community.feed-item@1, community.pulse-item@1 and community.pulse-write-request@1 with activity kinds, followers-only visibility, scheduled starts, previews and links to every item in a folded burst; Community consumes Network profile updates (#438).
  • Add chat.person-memory-result@1 and chat.person-memory-preferences-result@1: the public and private parts of Chat's compacted day, week and month memory, and the erase and opt-out responses (#437).
  • Add preview_url (and preview_webm_url on media) to media.vod@1, media.clip@1 and the Live stream shapes: the 6 s muted hover preview beside a thumbnail (#436).
  • Add agent.ui-event@1 with the AG-UI 1.0 event union and OpenVibe metadata.ov, agent.run@1 snapshots, and the agent-run chat embed (#434).
  • Add network.user-card@1 with viewer-aware actions, and network.user-report@1, network.user-report-request@1 and network.user-report-list-result@1 for a person's reports and the staff queue (#433).
  • Add community.feed-card@1 and community.feed-answer@1, with preview media support (#432).
  • Add composer.attachment@1, composer.prefs@1 and composer.mention@1, the shared composer's server-side shapes (#426).

Valid and invalid fixtures cover every new shape, and the generated TypeScript, JSON Schema bundle and per-service OpenAPI files are regenerated at this version.

0.404.0 — 2026-11-11

  • Add owner-only Run compute configuration capability for Network admin proxy.

0.403.0 — 2026-11-11

  • Extend actor.task-create-request@1 with conversation, tools, model and optional content tier fields for Actor turns; uncensored content is available only when a task names the person it is for.
  • Deprecate the account-merge contracts after removal of the feature across services; retain the released schemas.
  • Add chat.embed@1 as the shared address preview shape for chat clients.

0.402.0 — 2026-11-11

  • Activate download.file.read for grant-bound, per-file reads by agents on openvibe.download; the capability alone does not provide drive listing or access without an owner's active grant.

0.401.0 — 2026-11-11

  • Add the live.channel_points.read capability (with live.channel-points-page@1): OpenVibe.Network reads one channel's points moves for the person behind a Network account through Live's internal channel-points changes read, for the gain/loss API (ask 273).

0.400.0 — 2026-11-10

  • Regroup the sites into the owner's eight groups (plan ask 274, 2026-11-10): site.neighbourhood is now watch, talk, play, read, shop, tools, make or build, the same ids and order as OpenVibe.Network frame/sites.js GROUPS and OpenVibe.Shared rooms.js HOODS. Every site manifest carries its new group; merged sections point at the site that shows them (Media → Video/watch, Bench → Report/read, Play → Games/play).

0.399.0 — 2026-11-10

  • #408: add quest.today@1, the private Quest today response.
  • #412: extend network.operator-alerts-request@1 with browser-check evidence and release timing details.
  • #415: add the git.checks.write capability for reporting commit statuses.
  • #416: add agent.finding@1 for confirmed findings, leads that need validation and rejected claims.

0.398.0 — 2026-11-10

  • codes.task@2's outcome state names a goal task's honest end state: ready only with an accepted independent verdict, waiting, blocked at its no-progress limit, failed, dropped by the person, or stopped_by_budget. A task without a goal keeps done, unfinished and stopped.

0.397.0 — 2026-11-10

  • Add agent.goal@1: a task's outcome in words, a typed check (command, url or rubric), optional resource budgets (tokens, turns, active minutes) and a no-progress limit, plus the worker's bounded completion proposal and evidence and the independent verifier's verdict (accepted or rejected, with a reason and the check's own output).
  • codes.task-start-request@1 takes the optional goal; codes.task@2 carries it back with the worker's proposal, evidence and the verifier's verdict.

0.396.0 — 2026-11-10

  • Add optional ordered attempts to web and image search receipts, with provider/engine, status, safe reason codes, latency and cost. Existing receipts remain valid.

0.395.0 — 2026-11-10

  • Add two planned products to the catalog: manifests/products/openvibe.compare.json (OpenVibe.Compare: compare anything side by side with its sources and dates, AI models first) and manifests/products/openvibe.directory.json (OpenVibe.Directory). Both are noRepo with launch notes; the addresses are parked. Compare's "meanwhile" link is OpenVibe.Exchange, where the models and their prices live today.

0.394.0 — 2026-11-10

  • Add chat.room-insight-result@1 (contracts/chat/room-insight-result.v1.json): the public answer of GET /api/v1/rooms/:id/insight on OpenVibe.Chat. One shape for every room: overview (the text written for someone arriving now, its topics with message counts, how many people and messages the window held, its from/to times and when it was written), timeline (the room's notable moments, newest first, each with at, kind, title, text and the message_id it came from), and state (ready / quiet / off). Quiet is explicit: an old or empty summary carries no text rather than invented news. The overview reads only people who allowed AI use of their messages (network.consent@1, purpose ai.train on kind chat).

0.393.0 — 2026-11-10

  • billing.money-reason@1: declare donation:received, the row a creator sees for a tip that arrived ("for a tip from @alice"). The kind list is one list; the sender's donation still reads "for a tip to @bob".

0.392.0 — 2026-11-10

  • Add billing.money-reason@1 and lib/money-reasons.js: one list of the plain words for a movement of OpenCoins, Vibes or Balance. Each kind declares the key it matches (quest:publish-a-video, Media request: <title>, Billing's type:metadata), its site, what its subject is (a quest, a stream, a tip, a creator, an app, a project, a purchase), the phrase that names it ("for the quest {name}"), and how the subject's own name and address are found. describe() answers { key, text, subject: { name, url } | null }, so a page writes "+15 OpenCoins" before the text and links it; an undeclared key reads "for something on <site>" with known: false and never shows the key. Fixtures cover a quest, a tip, a reason with no page and an undeclared key.

0.391.0 — 2026-11-09

  • One Network experience curve, named reasons, level reads and capped service awards.

0.390.0 — 2026-11-10

  • A service manifest's site block takes an optional strip: up to three items a site adds to the network's footer strip, read with the rest of it at OpenVibe.Network GET /api/frame/online?site=<id>. An item is a plain label, an icon from openvibe-shared's glyph set, an https link on an openvibe.* domain, and either a count the site reports or a fixed line — never both. Live, Community and Games declare one each as the worked examples.

0.389.0 — 2026-11-10

  • Add ai.advisor@1: how a run may ask a stronger model for advice during the run. Off when the request omits it; at most 3 uses and at most 100 words of advice; the advisor may be named, the effort is concrete, and each use is on the run's receipt with its cost. Add ai.advice@1: one use on that receipt, naming the advice run, the model, the tokens and the cost. ai.run-request@1 takes the optional advisor field and ai.run@1's explain carries the uses.

0.388.0 — 2026-11-10

  • Add git.clone-request@1: one "Clone to my computer" request from a repository page. Git mints it for the signed-in person, the person's Link reads it over an outbound HTTPS relay, asks for approval on the machine, clones into a folder inside the root the person chose in Link, and reports progress back; the page polls the same document. The request lasts two minutes, only a repository the person may read can be requested, and clone_url (with a short-lived read token) is present only in the Link's answer, never in the page's copy.
  • Add git.machine@1: a computer published to OpenVibe.Git through Link, read-only. It lists the repositories under the root the person chose in Link, each with its branch, head commit and date, and whether the machine is online ("offline since …" when it is not). Browsing is asked of the machine over the poll it opened; nothing in this contract is a write path.
  • Valid and invalid fixtures cover a pending, cloning and done request, a bad id, a bad state and a traversing repository name, and an online and offline machine, a machine without repositories and a repository name that escapes its root.

0.387.0 — 2026-11-09

  • Add ai.creation@1 and ai.creation-list@1: the catalogue of everything AI can make on OpenVibe, one entry per creation. An entry names the product it lands in, a plain one-line name, what the person gives it and what comes back, the workflow or registered task behind it, who may use it (guest, signed-in, the 18+ floor), whether it can cost coins, and the URL where a person starts it. GET /api/v1/creations on OpenVibe.AI answers the list, built from the registered workflows and tasks so only what is live is listed; the contract is public and its fixtures show a workflow creation and a task creation.

0.386.0 — 2026-11-09

  • Add chat.command@1 for registered slash commands and typed options.

0.385.0 — 2026-11-09

  • Add ai.file@1 plus typed conversational turn request and result shapes for Media-backed attachments and artifacts.

0.384.0 — 2026-11-09

  • Agent work fabric: trigger, decision, immutable ticket mandate and budget, six report states, attention, and ordered stage vocabulary. Portable AI effort, concrete task-default effort, and optional effort/ladder receipt metadata.

0.383.0 — 2026-11-09

  • ai.provider@1: measured per provider+model circuit health (status, failure class, plain reason and since when, retry/backoff, notify time); ai.run-read-result@1: requests[].error_class.

0.382.0 — 2026-11-09

  • Add exchange.market@1: paginated own-page market offers, routing flags and per-field model metadata provenance.

0.381.0 — 2026-11-09

  • blog.changelog-entry@2: a shipped change with its plain words, kind (new, better, fixed or internal) and one to three areas from Blog's fixed list, with the commit and pull request for the row's fold

0.380.0 — 2026-11-09

  • Exchange routing controls, owner request presets and generation accounting schemas, with valid and invalid fixtures.

0.379.0 — 2026-11-09

  • Wiki's rich articles: the page write request and the page read result carry blocks (publishing.block@1) next to the Markdown, and wiki.images-suggest-request@1/-result@1 and wiki.article-draft-request@1/-result@1 describe the image suggestions (wiki.article.images) and the content.wiki draft revision that waits for a person.

0.378.0 — 2026-11-09

  • OpenVibe.Connect and the relay profile describe the Link, not the Node.

0.377.0 — 2026-11-09

  • community.feed-item@1: live_now on a live stream's row

0.376.0 — 2026-11-09

  • git.change@1, git.issue@1 and the review events for OpenVibe.Git's changes and issues (G2)

0.375.0 — 2026-11-09

  • AI tasks and choices: ai.task@1, ai.choice@1, ai.task-defaults@1; a run accepts task or choice beside workflow, and run.explain.task_choice says what answered. ai.me-preferences@1 gains defaults.search.

0.374.0 — 2026-11-09

  • Add the Pics public gallery and picture contracts (pics.gallery@1, pics.picture@1) with valid and invalid fixtures.

0.373.0 — 2026-11-09

  • The git service: its manifest, git.repo.read and git.repo.write, git.access-request@1 and git.access-result@1 (OpenVibe.Git)

0.372.0 — 2026-11-09

  • The machine product Node became OpenVibe Link. The network registry contracts are network.link@1,
    network.link-report-request@1 and network.link-list-result@1, the event is network.link.revoked, and the platform
    carries platform.link-capabilities@1 and link.compute@1. The capabilities network.node.manage,
    network.node.report and network.node.self.manage are network.link.manage, network.link.report and
    network.link.self.manage; their internal routes and the manifests follow.
  • A paired machine is a link principal: identity.service-token-claims actor_type node is link with sub link:lnk_…,
    and ids.principalSub mints link:lnk_… (the old prefix and ids are gone, no alias). The AI provider node is link
    in ai.credential-put@1/@2 and ai.credential@1/@2. The old contract ids are deprecated with their Link replacements; the
    schema corrections are recorded against the current release and the ones before it.

0.371.0 — 2026-11-09

  • Exchange API platform and search: exchange.key@1, exchange.key-created@1, exchange.usage@1, exchange.deployments@1, exchange.search-result@1, exchange.image-result@1, and the Exchange manifest's routes

0.370.0 — 2026-11-09

  • design.component@1: one platform-neutral definition per shared interface (the public registry on openvibe.design)

0.369.0 — 2026-11-09

  • OpenVibe Git: git.repo@1, git.commit@1, git.tree@1 and git.insights@1

0.368.0 — 2026-11-09

  • The wallet and the reviewed store: billing.wallet@1, inventory.store@1, inventory.store-listing@1, inventory.purchase@1

0.367.0 — 2026-11-09

  • publishing.block@1: the rich content block of a post or an article body

0.366.0 — 2026-11-09

  • wiki.page.published@1 and wiki.page.updated@1 carry an optional title (the page as readers see it), so the network's Feed names a wiki page by its title, not its slug.

0.365.0 — 2026-11-09

  • Dock v2: action-item words, ai.run-error@1, skill runs and Vibe conversations

0.364.0 — 2026-11-09

  • The Feed of everything: community.feed-item@1

0.363.0 — 2026-11-09

  • npm metadata and CITATION

0.362.0 — 2026-11-09

  • Your stats: report.me-stats@1 and report.me-stats-publish@1

0.361.0 — 2026-11-09

  • Reviewed glyph draft service

0.360.0 — 2026-11-09

  • Meme entry and render contracts

0.359.0 — 2026-11-09

  • Media multipart uploads in contracts and OpenAPI
  • Define design.component@1 for web, Android and iOS component anatomy, props, states, tokens, behavior, accessibility and examples.

0.358.0 — 2026-11-09

  • Chat view preference (bubbles or room)

0.357.0 — 2026-11-09

  • Cam camera settings (cam.settings@1)

0.356.0 — 2026-11-09

  • Shoes product contract (shoes.product@1)

0.355.0 — 2026-11-09

  • Daily quest contracts and step contribution

0.354.0 — 2026-11-09

  • Vibe compare and Exchange chat export contracts (the Chat move)

0.353.0 — 2026-11-09

  • Add actor.ask@1: durable approvals, questions, personal steps and sign-in hand-offs, linked to the person’s Actor and goal, with evidence and an answer or decline.

0.352.0 — 2026-11-09

  • The menu's home screen and wall (M1): network.home-screen@1, network.menu-feeds@2 (order and off; v1's on reads as
    the start of the order), network.frame-today@1, community.status@1, community.pulse-contribute-request@1 and the
    person-granted capability community.pulse.contribute, with fixtures and the manifests' routes.

0.351.0 — 2026-11-09

  • Add the five public Report AI comparison response contracts and fixtures, and list their cached public routes in the Report service manifest.

0.350.0 — 2026-11-09

  • Define credential-free blind fill request, encrypted grant, and outcome contracts, plus the run.fill.approve capability.

0.349.0 — 2026-11-08

  • Add identity.emails@1 and identity.email-add-request@1 and the identity.emails.read capability for a person's verified, privacy-limited email addresses.

0.348.0 — 2026-11-08

  • Service manifests: studio (OpenVibe.Studio at openvibe.studio, live: Photo and Light in the browser), and
    connect lives at https://connect.openvibe.link (its home on OpenVibe Link since 11-08; connect.openvibe.website
    stays as the second domain). The registry still gave the old origin, so the sign-in canary read a 302 for Connect.

0.347.0 — 2026-11-08

  • Add identity.trust@1 and identity.trust-request@1 for account and guest abuse signals, plus the app-grantable
    identity.trust.read capability.
    Responses contain coarse age bands and aggregate counts only; IPs, emails, last-seen timestamps, service user ids and
    linked account identities are forbidden by the schema and fixtures.
  • Service manifests: locker (OpenVibe.Locker at openvibe.locker, live; it owns the locker namespace), and
    computer is live (its exposure was still "repository").

0.346.0 — 2026-11-08

  • actor.skill-listing@2 (2.1.0) gains visibility (plan HO11, the agent writes its own skills): public (the
    default, and what every listing is today) or private, meaning only its publisher sees or installs it. Additive:
    the field is optional, so a listing without it stays public and nothing that exists today changes shape. A private
    listing's publisher.kind must be person: OpenVibe's own skills are always public. JSON Schema states both the
    enum and that rule, and the fixtures hold it.

0.345.0 — 2026-11-08

  • Add actor.approval-answer@1 (plan HO12, the phone as the agent's eyes and hands): the person's answer to an
    approval that asked for the phone's camera or its location. The person does the thing themselves, and the answer
    carries the result back to the step as untrusted input. decision is answer, and exactly one of:
  • photo: media_id, a private Media object the person took in the system camera (JPEG, PNG or WebP, at most
    10 MB, EXIF stripped by Actor); the step reaches it through a short-lived signed URL;
  • location: lat -90 to 90, lng -180 to 180, accuracy_m 0 to 100000 metres and precise. A coarse answer
    (precise false) carries lat and lng to at most two decimals; JSON Schema cannot count decimal places, so
    Actor rounds the share and the repository's suite checks the rule.
    The answer has no secret, token or url field, and a decline stays the ordinary denial.
  • actor.skill@1 (1.1.0) and actor.skill@2 (2.1.0) gain device.camera, device.location and device.notify in
    requires.kinds, so a skill's steps may be one of those approvals like any other HO1 kind. Additive: nothing that
    exists today changes shape.

0.344.0 — 2026-11-08

  • actor.trigger@1 (1.2.0) gains the mention kind (plan HO13, standing intents): a trigger that waits for the person
    to say one of their phrases in their own conversation with their own agent. Additive:
  • kind may now be mention; when.mention holds phrases (one to five, 2 to 80 characters each, trimmed) and
    match (any or all), while when.words stays the card's line ("When you mention the release");
  • fires may only be once_per_conversation: the trigger fires at most once in each conversation;
  • expires_at is required for this kind and at most 90 days after created_at (the default is 30). JSON Schema
    cannot compare two dates, so Actor enforces the cap, and the repository's suite checks the fixtures and the rule.
  • A mention trigger listens only to the person's own words to their own agent: never anyone else's messages, never a
    room or a stream chat, and never the agent's own answers. Matching is case-insensitive, on word boundaries, after
    Unicode normalisation. Nothing that exists today changes shape.

0.343.0 — 2026-11-08

  • Add actor.skill@2 and actor.skill-listing@2 (ADR-060, plan HO8): a skill may now bring code that runs in a
    sandbox instead of only a prompt. runs is prompt or sandbox; a sandbox skill carries 1 to 5 JavaScript
    tools (name, description, entry naming one of its resources, a JSON Schema subset for args, net
    deny/openvibe-only/public default deny, and limits under 30 s / 256 MiB), and the code itself is an
    ordinary text resource (.js, at most 64 KiB) in the same integrity hash. requires.kinds gains skill.run.
    The v2 listing pins each code resource's Media id and sha256 and lets a scan finding name the tool it is about.
    Code never runs on an OpenVibe server, never outside a sandbox and never with a secret: it runs as a Run
    function job on a Link that declared the skill runner. actor.skill@1 and actor.skill-listing@1 are
    unchanged and remain what a prompt-only skill publishes.

0.342.0 — 2026-11-07

  • Add mail.agent_inbox.received@1 (track HO6, channels): a message arrived at an agent's own address and the person has switched that address's answering on, so their agent may read it. The payload names the inbox and the agent, the owner, the mail server's message id, the sender, the subject and a plain-text excerpt of at most 4000 characters. It never carries the attachments, the HTML or the whole body: the agent's system reads the text through mail.agent.read, on the owner's behalf, once it has decided to answer. Mail publishes nothing for a sender on the person's block list or a message the mail server marked as spam, and nothing at all until the person turns the agent's switch on.
  • Add mail.agent-inbox-message@1, the one message an agent reads: the sender, the addresses the mail server stamped at delivery, the subject, the text cut to 4000 characters, and the threading headers a reply needs. Never the HTML, never an attachment, and never a sender-written Delivered-To. The message is data from a stranger, and any instruction in it is that stranger's.
  • Add mail.agent-reply-request@1 and mail.agent-reply-result@1, an agent answering one such letter: the body is plain text, the recipient is the sender of the message being answered (the same address may be named, never another), and the reply carries In-Reply-To and References so the thread stays one thread. The result says whether the mail server took it — sent, not "delivered", since a later bounce is not knowable at that moment.
  • Add mail.inbox-answering@1, the switch behind all of it: off by default, per agent, with when the person last set it.
  • Add the capabilities mail.agent.read, mail.agent.reply and mail.agent.answering. The first two are loopback-only and first-party: only a token that names the person (on_behalf_of) and the agent's own inbox reads a letter or sends a reply, and only OpenVibe.Actor is granted them. The third is the person's own switch, under the mail.addresses.write a caller already holds. The mail service manifest lists all three and now produces mail.agent_inbox.received.
  • Additive only: five new contracts, three new capabilities and one manifest field; nothing that exists today changes shape.

0.341.0 — 2026-11-08

  • The actor capabilities name the canvas routes (plan HO9): GET /api/v1/me/canvases and GET /api/v1/me/canvases/:id under actor.task.read, and POST /api/v1/me/canvases/:id/events under actor.task.create. The documents are actor.canvas@1 (0.340.0); a button's label starts a normal turn as the person, and a checklist tick flips the item and is told to the next turn. No schema changed.

0.340.0 — 2026-11-08

  • Add actor.canvas@1 (ADR-059, plan HO9): an agent's live panel beside the conversation, as data. A canvas is a
    list of blocks (a heading, text, a list, a checklist, a table, a metric, a bar or line chart, a picture from
    openvibe.media, a link, a button) drawn by one renderer (OpenVibe.Shared ov-canvas.js) wherever it is shown. There
    is no HTML, style, script or frame; text is plain. A button only sends its label to the agent as the person's own
    message, and ticking a checklist item tells the agent which item changed: a canvas never acts by itself. version
    only grows, and the agent replaces the whole document.

0.339.0 — 2026-11-08

  • The batches contract says what cancelling does. Only the prompts that never had a run are cancelled, and
    nothing is charged for them. A prompt that already has a run (the provider is working on it) goes on and
    settles on its own path: it keeps its status, the answer says so, and nobody is told it was not charged. The
    batch itself is cancelled only when nothing is left in flight.
  • The prompt's reason now names the three notes a customer can read: it expired (it was not charged), it was
    cancelled before it ran (it was not charged), or it was already sent to the provider (it finishes and is charged).

0.338.0 — 2026-11-08

  • actor.trigger@1 gains the goal kind (plan HO3): a trigger that keeps working toward a goal on a schedule. Additive:
  • kind may now be goal, and state may be done (a goal ended itself when its done-test passed);
  • paused_reason adds done, budget and deadline beside person and failed;
  • the optional goal object says the goal in the person's words, the done_test the agent answers yes or no each run,
    runs_used against runs_max, spent_usd against budget_usd, deadline_at, the last run's not_yet reason and
    its verdict;
  • the optional answer_in_chat (default true) says whether each run's answer is posted into the conversation that made
    the trigger, under its card, and notify (default false) whether the person is also told through OpenVibe's
    notifications.
  • Nothing that exists today changes shape: a schedule or event trigger without the new fields stays valid.
  • actor.task-event@2 gains the trigger-run step (2.2.0): a routine's run posted into the conversation that made the
    trigger, under its card. Additive: trigger_id names the routine, run says which task ran and how it ended
    (ok, failed, needs_you), text is its answer or the one line saying why it did not finish, and sources are
    the addresses it read (at most 8). An event without them, and the trigger card step, are unchanged.

0.337.0 — 2026-11-07

  • Add actor.skill@1 and actor.skill-listing@1 (ADR-058, plan HO2: the skills registry's skeleton). A skill is a
    document an agent loads to do one kind of job well: a slug, a name, a one-line description (the only part an agent
    reads before it loads it), a version, Markdown instructions, up to ten text resources, and requires (the approval
    kinds, connected apps and hosts it may ask for). It grants nothing: every step still goes through the agent's level
    and approvals. A v1 skill runs as a prompt only (no code, no binary, no install recipe). Its integrity hash shows the
    file was not edited; it is not a signature, and the author in a document is a claim.
  • The listing is the registry's record every site shows: the document, the publisher from the registry's own record,
    the scan (pending, passed, flagged, failed, with findings) and the curator's state (active, stale,
    archived, the last use and a near-duplicate). A passed skill installs in one tap, a flagged one after the person
    reads the findings, a failed one never; a stale or archived one is not offered.

0.336.0 — 2026-11-07

  • The run's options carry the latency class the caller asks for: interactive (answer as soon as the provider can),
    background (minutes; the run is priced on the cheapest tier that can wait) or batch (hours; the run is queued and
    answered through a provider's own batch API). A batch run may also say deadline_hours (1 to 72): how long the answer may
    take. The class is the workflow's own (the route's constraints.latency_class): a caller may ask for a slower class and
    never for a faster one, and a faster ask is not refused — the run happens in the workflow's own class and says so.
  • The run's answer carries latency_class (the class the run really ran in), service_tier (standard, flex,
    batch, offpeak, local: the tier it was priced on — the one the provider served or the one the router chose) and
    latency_clamped (the class asked for and the class used, when the ask was clamped).
  • Add the batches contract: ai.batch@1, ai.batch-item@1, ai.batch-create-request@1, ai.batch-create-result@1 and
    ai.batch-read-result@1 for /api/v1/batches on OpenVibe.AI. A batch is a queue of many prompts that are answered
    later, at half the retail price; the batch says where it stands, and a prompt that reaches its deadline without cheap
    capacity expires and is never charged.
  • Add the grants ai.batches.create (open a batch, cancel one) and ai.batches.read (read the caller's own batches).
    A first-party service opens a batch on the network's own account with ai.batches.create; a person or a developer app
    pays with its own account.

0.335.0 — 2026-11-07

  • Add actor.voice@1: an agent's voice as a file, and nothing else. The document carries the agent's name, a short bio, its instructions (the house voice it speaks in), its rules, its default approval level (ask, auto-edits, approve-for-me, full — the levels of actor.agent@1), the model it prefers and the connected apps it may use (ids only, never a key), an optional face (an avatar ref), an optional author and a created_at. It never carries memory, a connector's token or a file.
  • The document carries an integrity block, not a signature: integrity: { alg: "sha256", hash }, where the hash is the sha256 over the canonical JSON of the document. It shows the file was not edited after it was written. It says nothing about who wrote it: anyone can write a file that names an author and compute its hash, so the author in a document is a claim and the contract says so. Only the service that owns an agent may vouch for its author, in its own record.
  • The contract says exactly which fields the canonical JSON holds and in which order, and created_at is not one of them. The author may be absent: a document may name nobody.
  • Importing a voice makes a new agent at level ask, whatever the file says: a borrowed agent starts cautious and the person raises it themselves. Valid and invalid fixtures cover a full voice, a minimal one, a document carrying memory, one carrying a connector's token and one with a level that is not a level.
  • Additive only: a new contract and its fixtures; nothing that exists today changes shape.

0.334.0 — 2026-11-07

  • The chat manifest names openvibe.party, the Watch Together host OpenVibe.Chat serves beside openvibe.chat
    (Party watch v1, plan R1). Chat's service manifest is what services check a party link against: a media party plays a
    Media ref or an https URL on a host a manifest names, so a party started from an OpenVibe page passes and a link to
    somebody else's server does not. The www. name only redirects, so it is not listed.

0.333.0 — 2026-11-07

  • The network manifest names the two hosts Network serves since 2026-11-07: openvibe.my (the account hub's own home,
    Network#646) and openvibe.link (OpenVibe Link's home, Network#644). A service that builds its CORS list or its
    checks from manifest domains (Network's first-party origins, Chat's Bearer-only DM grant, the registry's nightly
    browser check, Space's reserved names) now includes them. The www. names only redirect, so they are not listed.

0.332.0 — 2026-11-07

  • Add common.control-lease@1, the shared control lease (seven domains plan B3): the thing a lease controls, its holder (a person, an ai or nobody, with the holder's subject or null), when the holder got the controls, an optional absolute expires_ms, the subjects watching and a seq that increments on every holder change, expiry or take-back. A watcher-only change does not increment seq. The authority that owns the thing enforces the rules; Chat hosts a room's lease, names the thing chat.room:<slug> and accepts a control change only from the current holder, while take-back by the room's owner always wins; only the owner hands the remote to an ai, and a person holder who leaves keeps it for a minute.
  • Add common.sync-clock@1, the shared timeline (B4): the room, the media (a Media ref or an https URL; Chat accepts only a host an OpenVibe service manifest names, so Party plays OpenVibe media), the position at at_ms, the rate, whether it is paused, who set it and a seq. A player computes position_ms + (authority now - at_ms) * rate while it plays and position_ms while it is paused. Chat stamps at_ms and seq and stores the latest state in room_sync_clocks (the memory copy is the room's live state).
  • Valid and invalid fixtures cover a person, AI and free lease, a lease with a time limit, seq zero, a nobody with a subject, a duplicate watcher, a URL and a Media-ref clock, a clock at a rate and paused, an http URL, a bad room and a bad media object.

0.331.0 — 2026-11-09

  • Add actor.trigger@1: a trigger made in an Actor conversation — its trg_… id, owner, agent, task, kind (schedule or event), the plain-language and machine schedule (a five-field cron in the person's timezone) or Watch event pattern and filter, the next run, the last run's result (ok, failed, needs_you), state, why it is paused, the consecutive failure count, the Watch subscription's own state and the ten-minute undo window. Owner-only: another person's trigger is the same 404 as one that does not exist.
  • actor.task-event@2 gains an optional trigger and the trigger step: the card as it is created, edited, paused, resumed, undone or deleted in the conversation travels with the event, so a reader renders the live card without a second fetch. Additive: an event without one stays valid, and the task record is still the source of truth.
  • Additive only: a new contract and an optional field plus one new step value; nothing that exists today changes shape.

0.330.0 — 2026-11-07

  • Add the mail service manifest: openvibe.email as the site Email (icon mail, the shared glyph font's E054), tagline "An address for every sign-up", the receive-only wording, legal profile service, and position 7, directly after Chat. It declares exposure live/service, port 5250, database ov_mail, the Stalwart mail server, /api/health and /api/ready, its shutdown and due-based recovery, an expand-only rollback, and the purge lease.
  • Add the two capabilities OpenVibe.Mail's API already checks: mail.addresses.write (make and retire a mask; make an agent inbox) and mail.messages.read (the person's addresses, message metadata and the newest burner code, never a body). Both are first-party, owner-constrained, and name their routes. Their request and result schemas are recorded in compatibility/capability-schema-gaps.json for now, like the config.manage capabilities added in 0.315.0.
  • The manifest lists no eventsProduced yet: the service publishes mail.mask.created and mail.received, but their payload contracts are not in this release.
  • Sites from the old position 7 up move one place (Services becomes 8, … Connect becomes 52) so Email sits beside Chat without breaking the unique-position rule. No contract changes shape; the only data change is the site order.

0.329.0 — 2026-11-07

  • Add mail.mask@1: a per-site address on OpenVibe.Mail that delivers into its owner's OpenVibe mailbox and nowhere else. It carries the msk_… id, the owner's Network subject, the <words>.<four characters>@<mask domain> address, the person's label and purpose, whether it is enabled (a disabled mask leaves the SQL directory Stalwart reads, so it bounces) and when it was made. M1 is receive-only, so this is metadata: no body, no forwarding target.
  • Add mail.burner@1: a throwaway receive-only address with its bnr_… id, an owner (null for the ten-minute burner made without an account), the eight-character address on a rotating burner domain, the expiry, first_message_only and the creation time. The one-time read token a create call returns is deliberately not part of the resource.
  • Add mail.agent-inbox@1: an agent's address <agent>.<user>@openvibe.email, its agi_… id, the owner, the cleaned agent id and the creation time. The mail lands in the person's mailbox; one agent has one inbox.
  • Add mail.message-summary@1: the one shape a list API returns for a message — id, sender addresses, subject and received time. additionalProperties is false, so a body, preview or html field fails the contract rather than leaking into an API; the body is read only by the verification-code endpoint, in memory.
  • All four are new contracts, not changes to existing ones, and the minor is expand-only. Valid and invalid fixtures cover a disabled mask, a guessed address, an anonymous and a one-message burner, a bad owner or agent id, a non-address, and a summary that carries a body.

0.328.0 — 2026-11-07

  • Add actor.assignment@1: one node of the tree of delegated work (plan §12) — id, root, parent, depth, origin (person, routine, outside), mode (work, consult, notify), reply (resume, poll, none), the agent and task it runs as, the node's level and effective level, the root's budget (limit, spent and remaining), state and timestamps. A node is one hand-off: a person giving Actor a task, a routine or Watch trigger starting a run, an agent handing work to another agent, or Actor starting a Codes or Space task. The effective level is the higher of the agent's own and the one inherited along a person's or routine's line; outside work never passes a level down. A cancel cascades down the tree, and a root's budget stops its children when spent. GET /api/v1/assignments/:id answers the node and its children and POST /api/v1/assignments/:id/cancel cancels the subtree; both are owner-only and another person gets 404. An existing task gets a root lazily.
  • Add the capabilities actor.assignment.read and actor.assignment.cancel, and name them in Actor's service manifest. They are the two assignment routes above.
  • actor.task-event@2 gains an optional assignment_id on a step event, so the Dock's timeline can draw the work tree later. Additive: an event without one stays valid, and the task record is still the source of truth.

0.327.0 — 2026-11-07

  • One Computer across Surf, Actor and the Dock (plan 2026-11-07: "Surf, Computer and Actor are one experience"): platform.task@1 gains optional computer (session_id, machine, where, cost_hint, driving) — the browser or desktop session a running task opened, wherever it runs. session_id is OpenVibe.Run's ses_…; it is null only when the desk runs directly on the person's own machine through OpenVibe.Bot, where there is no Run session. where is yours, home or network, and machine is the person's own word for it.
  • actor.task-event@2 and agent.timeline-entry@1 carry the same computer object by $ref: the task's step in the Dock and the task record read the same fields, never a copy.
  • run.session@1 gains optional task_id (the Actor task that asked for the session, so the session points back at the task) and curtain (the privacy screen: while it is up the session's still answers the curtain picture, never the screen). run.session-create-request@1 gains optional task_id.
  • The run.session.started and run.session.ended event payloads carry the same optional task_id and curtain, so a session's own events stay valid with the new session shape.
  • Capabilities name the routes: run.session.read gains GET /api/v1/sessions/{id}/still, run.session.control gains POST /api/v1/sessions/{id}/curtain, actor.task.read gains GET /api/v1/tasks/{id}/still, and actor.task.create gains POST /api/v1/tasks/{id}/takeover and …/giveback.
  • Additive only: every new field is optional and nothing that exists today changes shape.

0.326.0 — 2026-11-07

  • Add network.menu-feeds@1: the cards a person chose to show in the OpenVibe menu's "Choose your feeds", in their order, following them across every site. on holds up to four <site>:<cardId> ids (lower-case letters, digits and dashes) and updated_at says when the choice last changed. OpenVibe.Network keeps it at GET and PUT /api/v1/me/menu-feeds; a person who has never chosen gets { on: null } from the GET. An empty array is a cleared choice.
  • Additive: a new contract only; nothing that exists today changes shape.

0.325.0 — 2026-11-07

  • Add media.vod@1 and media.clip@1: one recorded stream and one clip as OpenVibe.Media's API answers them. Both carry watch_id, the id openvibe.video addresses a watch page by (openvibe.video/watch?v=<watch_id>), and the shape around it that consumers already read — the numeric id (internal), the owning tenant, the app-local user ids, title and status, duration and size, the file basename, playback_url, thumbnail, storage provider, visibility, view counts and times; a clip also names the recording it was cut from, its window in that recording and whether an automation cut it. watch_id is additive and optional (11 characters of URL-safe base64 from 8 random bytes, one id space across VODs and clips, fixed for the row's life and never the numeric id), because a row written before Media's backfill may answer without one.
  • Valid and invalid fixtures cover a public recording with a watch id and an unlisted one before the backfill, a person-made clip and an AI clip, a watch id of the wrong length, one with a character base64url never has, one with a slash, and an unknown visibility.

0.324.0 — 2026-11-07

  • Space's builder API moves under /api/v1/builder/spaces: GET /api/v1/spaces was the forum's old API (it lives on OpenVibe.Community since 2026-11-07, and Space still answers it with a redirect), so the API the person's own agent works through needs an address of its own. The capabilities name the new routes: space.build.read (GET /api/v1/builder/spaces, …/:id, …/:id/files, …/:id/files/:path, …/:id/preview), space.build.create (POST /api/v1/builder/spaces), space.build.write (PUT /api/v1/builder/spaces/:id/files) and space.build.publish (POST /api/v1/builder/spaces/:id/publish, and the person's answer at POST /api/v1/agent/approvals/:id/decide).
  • No contract shape changes: the bodies and the capability ids stay as they were.

0.323.0 — 2026-11-07

  • Space's builder API says two more routes in its capabilities: space.build.read now names GET /api/v1/spaces/:id/files/:path (one file of one of the person's own spaces), and space.build.publish names POST /api/v1/agent/approvals/:id/decide (the person's answer to the agent's request to publish, which OpenVibe.Actor passes on with the person's own token).
  • No contract shape changes: space.build.read and space.build.publish keep the bodies they had.

0.322.0 — 2026-11-07

  • Add actor.agent@1: one of a person's agents as a contact (plan §12 A-1) — id, owner, name, face, voice, model (engine runtime / own-keys / open-gpu / link, plus the model id), computer (null or a Computer kind and placement), connected app ids, OpenVibe Memory scope id (or null), approval level (ask, auto-edits, approve-for-me, full) and when it was added. Levels default to ask; money, passwords, deletions and sending to a new recipient always ask at every level, as a server-side floor.
  • Add actor.agent-list@1: a signed-in person's own agents (GET /api/v1/agents), Vibe first. Vibe is created on the first read and is not deletable. The public agent-system catalog keeps actor.agent-list-result@2 and now has an explicit GET /api/v1/agent-systems for a signed-in caller.
  • Add actor.level-change@1: the body of PUT /api/v1/agents/{id}/level; optional agent_id, thread_id and reason are echoes, the path names the agent.
  • actor.task-create-request@1 gains optional agent_id (the contact the task runs as; absent means Vibe) and level (the thread's own level). platform.task@1 gains optional agent_id, level, effective_level and agent_level. The effective level is the higher of the agent's level and the person's own thread line; it never inherits from another person's or a service's work.
  • Name the contact routes in actor.agent.manage and the catalog and presets routes in actor.agent.read; add valid and invalid fixtures for the three new contracts.

0.321.0 — 2026-11-07

  • Space's builder becomes a task of the person's one agent (plan 2026-10-22 §Z, stage Z1). Add the contracts of Space's builder API: space.build-space@1 (one of a person's own spaces: its id, slug, name, description, whether it is published and where, and when it changed), space.build-list@1 ({ spaces } or { space }), space.build-files@1 (the space's files, each a path and its whole content), space.build-create@1 (the body of a request for a new space), space.build-preview@1 (where the space can be seen now, its file paths, and whether it is live) and space.build-publish@1 (pending, published or declined, with the request the person answers in the Dock).
  • Add the capabilities space.build.read (list and read the person's own spaces and their files), space.build.create (make a new space), space.build.write (write the files of one of them) and space.build.publish (ask to publish; the person answers before anything goes live). A first-party service names the person in X-OV-Subject, and only that person's own spaces are in reach.
  • Additive: nothing that exists today changes shape.

0.320.0 — 2026-11-07

  • frame.menu-card@1 items gain an optional image: src (https on the publishing site's own origin or an openvibe.* host, at most 400 characters), optional w and h (whole pixels, 16–1920) and an optional alt of at most 120 characters. Network keeps an image whose src passes the same host rule as the item's url, drops one from anywhere else, and passes it through in GET /api/frame so the Frame menu and Network's /my can draw a thumbnail.
  • Additive: every item without an image stays valid, so an older publisher file keeps passing and an older reader ignores the field.
  • Valid fixtures cover an item with a full image and one with only src; invalid fixtures cover http, a width under 16, an alt over 120, a missing src and an unknown image field.

0.319.0 — 2026-11-07

  • The merged public site: OpenVibe.AI is no longer a site of its own. Its service manifest keeps the API, the run receipt and the operator console but drops the site block, so Network's Frame lists Exchange instead of AI. manifests/products/ai.openvibe.services.json is kind: moved, points at Exchange and keeps the API address, and Exchange's own site block now carries the merged tagline ("Every AI model, one account") and what it does.
  • No contract shapes change.

0.318.0 — 2026-11-07

  • Add network.presence@1: one person's online status as another may see it — online, away, dnd, invisible or offline, an optional status line (80 characters) and one emoji, whether they are streaming on OpenVibe.Live (live), and when it changed. OpenVibe.Network owns it; the state is derived from a heartbeat (online under 2 minutes, offline after 3) and the last input (away after 10 minutes), and invisible or show_status off is seen as offline.
  • Add network.presence-update-request@1: the optional fields of PUT /api/v1/me/presence — the chosen state (auto, dnd, invisible), the status line and emoji, and the "Show my status" switch.
  • Add the event network.presence.changed, at most once per person per 30 seconds and only for a real change. Its payload is the public view: an invisible person is sent as offline with no status text or emoji, and the state list has no invisible.
  • Add the capabilities network.presence.read (OpenVibe.Network's GET /internal/presence, for Chat) and chat.dm.peers.read (OpenVibe.Chat's POST /internal/chat/dm/peers, for Network's "follows or has a DM" rule), and name them in the two service manifests.
  • Valid and invalid fixtures cover the presence, the update request and the event, so a bad subject, an unknown state, an over-long status or a second emoji fails the run.

0.317.0 — 2026-11-07

  • Add frame.menu-card@1: one card a site publishes for the network's Frame menu (the menu's network cards). A card has a stable id and site, a title of at most 60 characters, a kind (rail, rows or chips), up to six items with a title of at most 80, an optional meta line of at most 120 and an https URL, an optional more link with a label of at most 24, the time it was built and its ttl. A URL must be https on the publishing site's own origin or an openvibe.* host; the text is plain words and Network strips markup and drops unknown fields.
  • Add frame.menu-cards@1: the public file each open site serves at /.well-known/openvibe-menu.json — an array of at most three cards from that site. An empty array is valid (the site has no card right now); Live serves its rail with empty items when nobody is live, and Network then skips it.
  • Valid and invalid fixtures cover a live rail with and without items, a Games rows card, a three-card file, an empty file, a title over 60, seven items, an unknown kind, an http URL, an unknown field, a ttl under 30, four cards and a card with a bad timestamp.

0.316.0 — 2026-11-07

  • Add agent.timeline-entry@1: one entry of the agent's timeline (design 2026-11-07 §2) — one step of the agent's work, in one mode, for one person. It carries the mode, the product, the step's own id, a plain title, when it started and ended, its status (running, waiting, needs_you, done, failed, stopped), the placement (where it ran and why), the cost, a link to the step's page, the one-line reason when it failed, the transition sentence when the mode changed, and the audience (private is Only me, the default). It never carries a prompt, a diff or a page.
  • Add common.agent-step@1 and the three events agent.step.started, agent.step.updated and agent.step.ended: the one shape every mode publishes when the agent does something (Chat, Codes, Run, Watch, Live, Surf), with the person's subject on the envelope. The payload is the step's shape only — a title, an outcome, a link, a cost — and never the step's content: a prompt, a diff, a page, a message or a file is refused by the schema. The agent.* namespace belongs to the network (like provider.*), so any first-party mode may publish into it; OpenVibe.Actor registers the family in Contracts and keeps the one timeline behind the Dock.
  • Add agent.timeline-list-result@1: what the Dock's Agent panel reads — the step happening now, what needs the person (oldest first), the entries themselves (newest first), the next cursor, and the per-mode counts so a filter never hides without a count.
  • Add actor.timeline.read: GET /api/v1/agent/timeline, the person's own timeline with the cursor and the mode and needs-you filters. Only their own entries; another person's entry is a 404.
  • Valid and invalid fixtures cover a step that starts, waits and ends, a timeline entry and a list, a payload with a prompt or a diff in it, an unknown status, a mode that is not one of the seven, and an entry of another person.

0.315.0 — 2026-11-07

  • The owner's Setup tab reaches seven more services: <service>.config.manage for chat, connect, deals, work, sources, design and domains is now active and listed in each service's manifest, because each mounts openvibe-shared/config's routes on /internal/config (GET /internal/config, GET|POST /internal/config/:namespace, PUT|DELETE /internal/config/:namespace/secrets/:key, POST /internal/config/:namespace/test/:key). Only Network's admin proxy, acting for the owner, holds them and they are never grantable to apps. media.config.manage stays planned until Media mounts the routes.
  • Add blog.review.ai_editor, news.review.ai_editor and wiki.review.ai_editor: the editorial queue's AI editor decision (approved or rejected; approved or needs changes on Wiki) recorded by the first-party service principal acting as itself (a svc: principal with no X-OV-Subject) through Blog's POST /api/v1/posts/:id/reviews, News's POST /api/v1/stories/:id/reviews and POST /api/v1/briefs/:id/reviews, and Wiki's POST /api/v1/pages/:id/revisions/:n/review. An approval lets AI-written text publish and index and the page says "Checked by OpenVibe's AI editor" with its date, never "Reviewed by a person"; each is granted only to the orchestrator's service principal. Their requests and results are a recorded schema gap (compatibility/capability-schema-gaps.json).
  • generated/ refreshed: Connect and Design gain an OpenAPI document now that each has an active capability, and Blog, Chat, Deals, Domains, News, Sources, Wiki and Work gain the new operations.

0.314.0 — 2026-11-07

  • Add the capability live.agent_sandbox.register (Agent Streams S6): the chat plays sandbox worker's check-in on OpenVibe.Live, POST /api/streams/agent/:id/plays/worker, owned by Live and internal. Only a first-party service token whose principal holds it may register a worker, and the token names the person it works for in X-OV-Subject, who must own the stream. The owner's own session, a desk ticket (wpt_) and a person token are refused: an owner who could register a worker would declare their own unisolated machine a sandbox. The worker reports the isolation facts Live requires (no host network, no credentials, no profile, egress through the proxy, an ephemeral workspace) and Live derives health only from a check-in within the last minute; Live stores no endpoint and never calls the worker. Name the capability in Live's service manifest.
  • Add live.agent-sandbox-worker-request@1: the worker's check-in body, which names the five isolation facts Live reads exactly (host_network false, credentials false, profile false, egress_proxy true, workspace ephemeral) and may carry the worker's own checks, limits, versions and counts. A worker that cannot say each of the five is not registered. Add live.agent-sandbox-worker-result@1: the worker's state for the stream's owner, with the reason when there is no healthy one, the last check-in and the minute a check-in counts for. Live never returns an endpoint: there is none.
  • Valid and invalid fixtures cover a full worker check-in and an isolation-only one, a worker with the host's network and one that cannot say there is no profile, and a healthy worker, a stale one, a missing stale window and an unknown state code.

0.312.0 — 2026-11-07

  • Add the Codes skills-hub records (the Compute plan §5, E6). codes.skill@1 is one skill, rule, MCP server, command or hook: its owner, kind, stable slug, title, summary, the four sharing audiences (private, people, link, public), the harnesses it is written for, the newest version and that version's body. A private, people or link record is never in the gallery; only public is. The body is untrusted Markdown and the page renders it through the markup gate.
  • Add codes.skill-version@1: one immutable version of a record, keyed by skill_id and a growing version, with the body, summary, tools, audience, author and the note that says why it was written. A rollback copies the chosen version into a new one rather than rewriting history, so a Link that synced version 3 can still name it.
  • Valid and invalid fixtures cover a public skill, a private rule, a people-shared MCP record, versions 1 and 4, and the bad ids, kinds, audiences, tools, bodies and authors.

0.311.0 — 2026-11-07

  • Add <service>.config.manage for the eight services that hold an owner input and that Network's admin proxy now reaches for the owner's Setup tab (OWNER-SETUP-AND-ADMIN-CLARITY-DESIGN, 2026-11-07): chat, connect, deals, work, sources, design, domains and media. Each is internal, held only by Network's admin proxy acting for the owner, never grantable to apps, and planned until its service mounts openvibe-shared/config's routes on /internal/config; the service then turns it active and lists it in its manifest (Deals' own test pins that list, so listing it early would break its pin bump). Planned capabilities verify like active ones, so Network's grant works the day a service mounts the routes.
  • Every <service>.config.manage (the nine active and the eight planned) names POST /internal/config/:namespace/test/:key among its routes: openvibe-shared 4.125.0's test hook, which tries a stored value with the provider on the server and answers { ok, message } in one line that never carries a secret.
  • common.config-namespace@1 (description only): the summary's schema may carry the annotations the Setup tab and the clear admin panel read, x-owner-input, x-required-for, x-enum-labels, x-advanced and x-example, beside the D11 ones (and x-unit names seconds). No shape changes.

0.310.0 — 2026-11-07

  • Apps ask for consent per purpose at sign-in (the consent plan's C4). An app adds one scope consent:<purpose> per purpose to /oauth/authorize, beside its other scopes. It may ask for every purpose of the consent family except the retired ai.looks: ai.train, data.public, face.recognize and app.data. Any other consent: scope is refused with invalid_scope. The consent screen lists each purpose in plain words, nothing ticked, and the person can sign in with every purpose refused. A refused purpose is not asked again by that app for 30 days, unless the person asks for it again on their account page.
  • Add network.consent-claim@1: the consent claim of the tokens Network issues from that sign-in (a first-party user token, a Dock token or an app token). It holds exactly the purposes the sign-in asked for that the person granted to that app and that are active when the token is issued, [] when none. It never holds a refused purpose or another app's grant, and the app learns only "not granted". The claim is absent when no consent scope was asked. Every new token works it out again, so a purpose turned off is gone from the next one.
  • identity.service-token-claims@1 gains the optional consent claim (additive): an app token from the authorization-code flow carries it when the sign-in asked for consent scopes.
  • Add network.me-consent-apps-result@1: "Apps you allowed" on the account page (GET /api/v1/me/consent/apps), listing each app's granted purposes and the ones refused in the last 30 days (quiet, with the day it ends), with the words the app consent screen shows. network.consent.manage names that route and DELETE /api/v1/me/consent/:purpose/:client/refusal, which ends a refusal's quiet days so the app's next sign-in asks again.
  • network.consent@1: an app's grant is one record per purpose, with the app as client and source oauth. client is no longer only for app.data, and options.purposes is not written any more (kept so older records validate). network.consent-check-request@1's client may name the app for any purpose: one app's grant never answers for OpenVibe itself or for another app. Descriptions only: no shape changes.
  • Valid and invalid fixtures cover a user token with one purpose, an app token with none and with all four, a retired, unknown, duplicated or missing claim, a claim that is not a list, an app's grant record, the account page with two apps and with none, a bad client id, a retired purpose, an extra key and a quiet refusal with no end.

0.309.0 — 2026-11-07

  • Add bot.machine-pool@1 (the pooled machines design, 2026-11-06): several of one owner's machines on the same local network that serve one model together through llama.cpp RPC (rpc-server on the members, llama-server --rpc on the head). OpenVibe.Network holds the record: the owner proposes it on /machines with two to eight of their own machines (the default head has the most free VRAM), and each machine reads it with its own node token and approves it on itself. A member's certificate is null until it approves; then it is that machine's self-signed Ed25519 public certificate, which the other members pin for the pool's private link. The private key stays on the machine: a certificate slot holding anything with PRIVATE KEY in it is refused, and so is any field the schema does not name. A member's address is a private RFC 1918 address and prefix (never 0.0.0.0, loopback or a public address) and its public_ip is the address Network saw it from. The rules a schema cannot say are written in the description and checked by Network and Node: the head is a member, every member is the owner's today, all share one public address and one private subnet, the head's direct link probe to each passes, every key is its own, and any change of membership, owner, head or key revokes the pool so every machine approves a new one.
  • Add ai.offer@1: one community AI offer as Bot reports it to Network and AI reads it back (the fields Network already stores: machine, owner, models, hours, concurrency, credit price, audience, readiness and health), with the new optional pool.
  • Add ai.offer-pool@1, the pool part of the AI offer: { machines, head }, two to eight machine ids and the head, which is the offer's own machine. Network adds it from its approved pool record, never from what a machine reports, and leaves a member's own offer out while it is in a pool. It names machines only: no address, key or certificate reaches AI. One price, audience, hours, idle-only and verification apply to the whole pool; AI verifies a pool's answers as it would one machine's, keys that verification on the exact membership, keeps a new or failed pool to the free tier only, and labels it "Community pool (N machines)".
  • network.node.self.manage names the five pool routes a machine calls with its own token (announce, read, approve, renew readiness, leave) in implementedBy.
  • Valid and invalid fixtures cover a pool waiting for approvals, an approved pool of three, a single-machine offer, a pool's offer and one still waiting, a group offer, a missing head or owner, a one-machine pool, a repeated member, a private key in the certificate slot, a public, loopback or wildcard address, a port under 1024, and an address, certificate or key smuggled into a field the schema does not name.

0.308.0 — 2026-11-07

  • Add ai.memory-export@1 (Memory M5): the one portable memory file. It carries format: openvibe.memory-export@1, version: 1, exported_at and every item's text, kind, scope, source, confidence and source reference. It deliberately has no ids, owners, merge links or conflict pair, so a file can be imported into another account without carrying anyone's identity, and a profile is derived from the items and rebuilt, never imported. OpenVibe.AI's GET /api/v1/memory/export writes it and POST /api/v1/memory/import accepts the same document; both redact again.
  • Valid and invalid fixtures cover an export with items and an empty one, a wrong format/version and a scope that is an absolute path instead of user or project:<slug>.

0.305.0 — 2026-11-07

  • Give the id kinds the S7 work needs a prefix: newId('agent_stream_schedule') is scd_… (a scheduled public agent stream) and newId('party') is pty_… (a watch party's id when a party is not named by its room slug).
  • Add live.agent-stream-schedule@1 (Agent Streams S7): an owner's schedule for a public agent stream — a time, a task template and the mode. Live starts it when the owner's desk is online; when the desk is not, the record says missed with desk_offline ("didn't start: the desk was offline") and nothing runs. A chatplays schedule keeps its time but waits for the owner's Go (waits_for_go), the S6 rule. The record carries the stream it started, its reminder count (the people who opted in, never who they are) and the page where it shows 24 hours before its time.
  • Add chat.party@1 (Agent Streams S7): a watch party on a public agent stream or its VOD, a Chat room of kind party. On a VOD the position follows the host's; on a live stream it follows the live edge. A party is private by default, joining is by its link, and a listed party reaches the stream's page only as a count ("3 parties watching") — the count never carries names.
  • Extend live.agent_stream.publish with the schedule routes and the desk heartbeat: POST|GET /api/streams/agent/schedules, DELETE /api/streams/agent/schedules/:id, POST /api/streams/agent/schedules/:id/remind, POST /api/streams/agent/schedules/:id/go and POST /api/streams/agent/desk/heartbeat.
  • Valid and invalid fixtures cover a scheduled stream, a missed one with the desk offline, a chatplays schedule that waits for Go, a missing task and an unknown state; a private VOD party, a live party with a link, a party made public and a party with a room id that cannot exist.

0.304.0 — 2026-11-06

  • Give the id kinds the Agent Streams work needs a prefix: newId('agent_stream') is ags_… (an agent stream's id), newId('play_request') is req_… (a chat plays request) and newId('sandbox_session') is sbs_… (the sandbox desk). Without them a service that had to name one of these ids had to build the ULID itself, and newId('ags') threw.
  • Add chat.play-request@1 (Agent Streams S6): one viewer's request for the chat plays desk to build or do something. A request is written with !do <request> (at most 200 characters) in an agent stream's room, agent:<ags_id>; one open request per person at a time, and an account younger than a day cannot ask. The request carries its votes, its state (queued, running, done, failed, skipped, removed or refused), whether it is pinned, and the one-line reason it was refused (with the rule that refused it) when it was. A refused request carries no result; a finished one carries the outcome, the line the overlay and the voice said, and the scratch site the run left.
  • Add codes.sandbox-session@1: the sandbox desk a chat plays session runs on. The desk is started with --shared — no profile, no keys, no person's files, public egress only and a fresh workspace, wiped at the end — and the session carries the owner's time box (5 to 30 minutes), the step budget, the cap (money and minutes), what it has spent, whether the owner armed it with Go, and the throwaway scratch site with the 24 hours it lives. egress_public_only is always true: no private address is reachable.
  • live.agent-stream-control@1 gains the control wipe (additive): Wipe now stops the run and resets the sandbox. The other four controls (pause, curtain, mute, end) keep their shape.
  • live.agent-stream@1 gains the mode chatplays (additive; the enum already carried it): a chat plays stream is public or unlisted, and it works the room's queue.
  • Add the capabilities chat.play_queue.read and chat.play_queue.write for Codes, the task's service, acting for the stream's owner (a node token on_behalf_of), and name both in Chat's service manifest. Chat chooses what the queue holds: a request enters it only after the house text filters and the safety check, one open request per person at a time, and the people and the votes in it belong to the room.
  • Valid and invalid fixtures cover the queued, finished and refused requests, a request that is too long, a refusal without a reason, an unknown state, the armed and running sandbox sessions, a session with no cap, a time box outside 5 to 30 minutes, a sandbox that is not public-only, and the wipe control, so a missing field or a bad value fails the run.

0.303.0 — 2026-11-06

  • Add chat.agent-digest@1 (Agent Streams S5): what a Co-pilot room said to an agent between two of its steps. The agent never reads the raw room: it asks Chat for a digest and gets at most ten items and 1,500 characters. Each item names who (the display name and the handle), what (cut to 200 characters), its kind (question, suggestion or reaction) and its upvotes; a repeated line is one item with the number behind it. Chat chooses what goes in (repeats grouped, greetings and spam dropped, the most-upvoted questions and suggestions first) and who is left out (a person who is timed out or banned, whose account is younger than a day, or who set 'Agents don't read my messages'). A link is kept as its domain only; the code and the commands stay as text.
  • Add chat.agent-poll@1: the poll an agent asks a Co-pilot room to run, and the result it gets back — the question and the two to four options the agent wrote, the window it is open for, the state (open, closed or vetoed) and the counts. An open poll carries no result, a closed one carries its counts and its winner, a vetoed one names who refused it.
  • Add live.agent-stream-control@1: one of the four controls the owner and the channel's moderators have over a live agent stream — pause, curtain, mute or end — with who pressed it (the handle and the role: owner or moderator) and when, and whose pause is in force.
  • Add the capabilities chat.agent_digest.read and chat.agent_poll.write (first-party), and name both in Chat's service manifest. The caller is Codes or Actor, the task's service, acting for the stream's owner (a node token on_behalf_of), so a digest is the owner's room and nobody else's.
  • chat.preferences is v2: it gains agents_read_messages ('Agents don't read my messages'). A v1 record upgrades with it true — joining a Co-pilot room and writing in it is the choice, and the person can take it back.
  • live.agent_stream.publish now names the controls (POST /api/streams/agent/:id/control, GET /api/streams/agent/:id/controls) and the step credit: a step may name the suggestion it took.
  • Additive: nothing that exists changes. Fixtures cover a digest over the ten-item cap, an unknown kind, a room that is not an agent room, a poll with one option and with five, an open poll carrying a result, an unknown control, a control with nobody behind it and a role that is neither owner nor moderator.

0.302.0 — 2026-11-06

  • Add the capabilities media.avatar.adopt and media.avatar.release (internal), and name both in Media's service manifest. After the 2026-11-06 incident (eleven avatars were soft-deleted with the public screenshot copies), Media records which avatar object each profile slot points at, and its delete refuses an object a working profile still shows. A product (Network for users.avatar_url, Live for its own copy and the channel banner) records a slot with POST /internal/avatar-adopt and drops it with POST /internal/avatar-release.
  • Add media.avatar-adopt-request@1 / media.avatar-adopt-result@1 (the slot: object_id med_…, product, ref, the optional subject; the answer is the active reference) and media.avatar-release-request@1 / media.avatar-release-result@1 (a slot, an object or a person; the answer counts the released references, 0 when there were none).
  • Additive: nothing that exists changes. Fixtures cover a missing ref, an object id that is not med_…, a release that names nothing, a product without its ref and a negative count.

0.301.0 — 2026-11-06

  • Add live.agent-stream-state@2 (Agent Streams S4): the state the desk polls gains the voice (mode watch or narrated, the voice, the personality calm, hype, dry or roast, muted, paused with its reason), the newest lines to speak, and captions_url (the stream's WebVTT). @1 is unchanged.
  • Add chat.tts-speak-request@1 and chat.tts-speak-result@1: the body and answer of POST /api/agent-voice/speak on OpenVibe.Chat (one line of at most 220 characters, an optional voice or the person's own; the audio, its MIME type and rate).
  • Add the capability chat.tts.speak: a machine (a node token acting for its owner, on_behalf_of) asks Chat to speak a line in that person's chosen voice, never another person's. Chat's manifest names it.
  • Additive: nothing that exists changes. Fixtures cover a missing text, a line over 220 characters, a missing audio and a wrong MIME type.

0.300.0 — 2026-11-06

  • Add report.session@1: the report of one agent session, whatever ran it — a Codes task, an Actor task, a desk session or a session on a person's own machine (the Agent Streams plan, S3). It carries the id (rps_<ULID>), the owner (usr_…), the source (codes, actor, desk or node), the task (title ≤ 200 characters, the task's ref and its link back), the start and end, the worked seconds, the outcome (done, stopped or failed, with stopped_because in plain words when it did not finish), the summary (≤ 600 characters), the timeline (the steps, the same shape as live.agent-stream-step@1), the outputs (pr, file, page, deploy, clip or vod), the proof (the tests, the screenshots' media ids and the review's verdict), the cost and the models, up to five highlights, the agent stream it streamed on and the visibility (private, unlisted or public). The raw transcript, secrets and code are never in a report: the source service keeps the transcript for the owner, the house redactor runs over every text field before anything is stored, and a pull request is a link (its content shows only when the repository is public).
  • Add report.session-write-request@1 and report.session-write-result@1: the body of POST /internal/session-reports on OpenVibe.Report and what it