Release 0.80.0 — a capability the deployment does not have - #23
Merged
Merged
Conversation
Spec v0.80 cuts Part L, extensions. Part G has said since v0.9 that UIs and bots are MCP/library clients, not plugins, and that sentence left a whole class of work with nowhere to stand: a transcriber, a converter for a format nobody here has heard of, an OCR pass, each arriving with a dependency that LICENSING.md's Apache/AGPL split cannot pin without making this project their distributor. An extension is a package that contributes at named seams (L.3) and never patches; register(api) is enumerated like ScopedVine; a heavy handler runs in its own environment and process (L.5). This project distributes nothing (L.0, L.2): four sources through one resolver, every one resolved to an immutable artifact before it is validated, three trust tiers, and the conformance kit runs before anything is registered, never before third-party build code runs. The mechanism is the engine's and the governance is the Station's (L.12); a contribution the host cannot serve is inert and named (L.10); the console surface is declarative (L.11). Amends J.4.2 (the audit row's via), J.10 (roles carry a kind, an extension registers a role and never holds a key) and J.5 (the Extensions console). Acceptance F.174-F.198. tasks/T18 records the decisions, the costs accepted and what remains: F.194's gpg measurement, the curated index, the console's browser pass. Signed-off-by: Jimmy Wesley <[email protected]>
The v0.80 Part L runtime: src/monkeyllm/extensions (manifest, sources, installer, store, loader, worker, conformance kit, forest config), the vine ext CLI (install, update, list, remove, config, enable, disable), the Station's governance and /v1/ext routes, the Studio Extensions console with its three catalogues, and all ten L.3 seams wired where the host that declares each one reads it: converters in the Gardener, curation after the host's hooks, events on the one emitter that decides webhooks, tools on the MCP menu, routes, jobs, ranking inside harvest before the budget, prompt on both modes, roles beside every other binding. Audit rows gain via; roles gain kind; quota is per extension per forest and exhaustion is a refusal. extensions/whisper is the first real extension: it registers the transcribe role and turns a recording into a media node whose body is the transcript, adding no package to the engine's environment. Three things caught before release and kept in the task file: the loader executed a module twice, so module-level state split in half with no error (it imports once per installed tree now); the extension list was gated on "has a grant" where it meant "is admin", caught by the route canary; and the tools/list filter's fallback returned the unfiltered menu on an unrecognised SDK shape, which a visibility filter must never do. pyproject declares an empty extensions extra as the name a future dependency lands under, so a plain install keeps loading with the loader inert. CLAUDE.md carries the entry. Tests: tests/test_v080_*.py. Signed-off-by: Jimmy Wesley <[email protected]>
MiniCPM5-2B, asked for one JSON object per turn, answers in JSON on most turns and on some falls back into the function syntax it was trained on: <function name="locate"><param name="query">x</param></function>. Its reasoning picks the right tool and the right branch; only the spelling is wrong, and bouncing it with "Invalid format" makes it repeat the spelling until the step budget is gone. On the Phase-0 fixture that was 7/10 with the three misses at zero tool calls each. parse_action now translates that syntax into the same action. Each argument is read by the type the engine's signature table declares for it, so k is an integer, terms and filter are a list and an object, and query="2026" stays the string it is; null is None; a value that cannot be read as its type is left as text for the primitive to refuse. No navigation help is added. With nothing else changed the fixture scored 10/10 on two consecutive runs, and the bench forest 18/18 (v2), 11/11 (v3) and 7/8 (v4) with BM25-only entry search. Signed-off-by: Jimmy Wesley <[email protected]>
New section 5.4 records the 2026-09-11 replication of the navigation arm with MiniCPM5-2B on the same forest and the same three question sets: 18/18, 11/11 and 7/8, precision 1.00 on the first two, median tokens 1,422 / 1,583 / 2,850, BM25-only entry search, one run per set. The one miss (v4-07) is described as what it was: two correct queries, a correct answer at step 5, and the harness's proof audit rejecting it because a SQL result set has no sentence to quote. The harness change that made the run possible is reported because its symptom scores exactly like a wrong answer. Wall-clock is not reported: the model was served over the network by a shared host. Abstract, the 1.3 table, contribution 3, the related-work SLM paragraph, the setup's models paragraph, the Forest Principle, limitation (iii) and the quickstart are updated to point at 5.4. Document version 1.0.0 to 1.1.0. Signed-off-by: Jimmy Wesley <[email protected]>
One spec version since 0.79.0 (v0.80). Behaviour changes worth reading before upgrading: - Extensions (Part L). A plain pip install monkeyllm is unchanged: nothing is loaded until an operator installs an extension (vine ext install) and a forest enables it in _meta/extensions.yaml. That file is versioned and travels in a snapshot; validate reports an extension a forest expects and this deployment does not have, as a health line and never as an install. A declared secret may not be written there. - An extension contributes at named seams (converters, curation, events, tools, routes under /v1/ext/<id>/, jobs, ranking, prompt, roles) and never patches. A contribution the host cannot serve is inert and named, never an error. Handlers marked heavy run in the extension's own environment and process. - Audit rows gain via (ext:<id>), nullable. A row written before this version reads it as absent. principal stays whoever caused the act. - Model roles carry a kind (chat, embed, vision, transcribe, rerank). An extension registers a role and is handed a bound caller, never an endpoint or a key; its spend is metered and capped per extension per forest, and exhaustion is a refusal. - The MCP tools/list menu may carry extension tools; its visibility filter fails closed, so an unrecognised SDK shape yields fewer tools, never more. - Station: /v1/ext routes, admin-gated; Studio gains an Extensions console. New environment: MONKEYLLM_EXT_HOME, MONKEYLLM_EXT_INDEX, MONKEYLLM_EXT_WORKER_TIMEOUT. pyproject declares an empty extensions extra as the name a future dependency lands under. - The demo harness (examples/demo) accepts a model's native function-call syntax beside the JSON it asks for. Product behaviour is unchanged. Signed-off-by: Jimmy Wesley <[email protected]>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release 0.80.0 — a capability the deployment does not have
One spec version, v0.80, and the package moves 0.79.0 → 0.80.0. It comes
from a sentence Part G has carried since v0.9: UIs and bots are MCP/library
clients, not plugins. The line was drawn correctly and it left a whole
class of work with nowhere to stand: transcribing audio, converting a format
nobody here has heard of, reading a proprietary export. Not a client, not a
contract change, a capability this deployment simply lacks. Each arrives
with a dependency, and the dependency is the problem: FFmpeg is GPL or LGPL
depending on the build, a converter drags a machine-learning stack, a
transcriber drags another.
LICENSING.mdsplits this tree Apache-2.0 /AGPL-3.0-only, and that split holds only while the dependency list stays
clean. Pinning any of them makes this project their distributor.
What changed
Part L, extensions (new). An extension is a package that contributes at
named seams and never patches:
converters(read by the Gardener aboveextra_convertersand below an operator's own command hook),curation,events(on the one emitter that already decides webhooks),tools(on theMCP menu),
routes(under/v1/ext/<id>/),jobs(pulled, neverscheduled),
ranking(insideharvest, before the budget),prompt, androles.register(api)is enumerated the wayScopedVineis: a new enginecapability needs its own line before an extension can reach it. A handler
marked
heavyruns in the extension's own environment and its own process,which is what keeps the motivating dependency out of the process that
serves the forest.
This project distributes nothing. Four sources (curated index, git,
archive, local file) resolve through one resolver, and whatever the source,
it becomes an immutable artifact before it is validated: a git ref becomes
a commit SHA, because a tag can be force-pushed and the thing that was
signed must be the thing that runs. A moving ref is allowed and marked
tracking,unverifiedby construction. Three tiers,verifiedfrom theindex,
signedfrom a signed tag checked against the forge's publishedkeys,
unverifiedfor everything else. Resolvingrequirements.txtexecutes third-party build code, so the conformance kit runs before
anything is registered, and never before third-party code runs. The
documentation says so in those words.
The mechanism is the engine's, the governance is the Station's. An
operator with no Station installs extensions from the CLI:
vine ext install|update|list|remove|config|enable|disable. Global install is ahost-level directory (
MONKEYLLM_EXT_HOME); per-forest enablement is_meta/extensions.yaml, so it is versioned, travels in a snapshot, andvalidatereports an extension a forest expects and does not have._metadeclares expectation and never grants it, and a declared secret may not be
written there.
Inert and named, never an error. A contribution the host cannot serve is
listed as inert. The config schema is the source of truth and a panel is
decoration over it, enforced by the kit, so a console-less host stays
first-class. The console surface is declarative, because J.5.13 admits no
third-party script in the console's origin and that rule is not relaxed for
an extension. Studio gains an Extensions console.
Amends J.4.2, J.10, J.5. The audit row gains
via(ext:<id>,nullable, absent on rows written before this version) while
principalstays whoever caused the act: a forensic question is who asked for this,
and an extension is not an answer to it. A model role gains a
kind(
chat/embed/vision/transcribe/rerank), and an extension registersa role rather than carrying a key: it is handed a bound caller, never an
endpoint or a credential, so its spend is configured, metered and audited
where all other spend is. Quota is per extension per forest and exhaustion
is a refusal, never silence.
The first real extension.
extensions/whisperregisters thetranscriberole and turns a recording into amedianode whose body isthe transcript, so
snifffinds a word that was only ever spoken. It addsno package to the engine's environment, which is the point of it.
Three things caught before release, kept in the task file. The loader
executed an extension's module twice (once for
register, once perhandler), so module-level state split in half with no error; it now imports
once per installed tree. The extension list was gated on "has a grant"
where it meant "is admin", caught by the route canary in
test_station_admin_scope. And the MCPtools/listfilter's fallbackreturned the unfiltered list on an SDK shape it did not recognise; a
visibility filter fails closed.
Also in this release
sometimes emits a tool call in its native XML-like function syntax
instead of the JSON the prompt asks for;
parse_actionnow translatesit, typed by the engine's signature table, with no navigation help. With
it, the 2B scores 18/18 (v2), 11/11 (v3), 7/8 (v4) on the bench
forest with BM25-only entry search, the same scores as the 12B rows.
run per set, wall-clock not comparable, navigator arm only); abstract,
setup, Forest Principle, limitations and quickstart updated.
Leftovers, named
implemented and not measured.
Acceptance
F.174 – F.198. Full suite green locally on the release commit (1816 passed,
0 skipped, Python 3.12) and running in CI on this PR;
python -m build+twine checkpassed (wheel 243 kB, sdist 562 kB; the wheel carriesmonkeyllm/extensions/andcli_ext.py, and nothing of the Station).