Files
Maven/docs/capabilities/gaps.md
T
claude 8153e5eaa5 Classify every gap and rank the work (V-725)
Session 2 step 3, and the end of the explanation half.

gaps.md compares responsibilities and never package names. Eight classes. The
four capability classes are derived from the ledger's gap_class field and
rebuild with build_ledger.py. The four architecture classes are read from
findings.md and invariants.md, and every entry names the capability or invariant
it affects. An entry naming neither is marked non-blocking cleanup in those
words, which is the whole of class 8 and its eleven rows.

Of 46 v1 capabilities: 5 missing, 21 partial and reachable, 9 built and
unreachable, 11 reachable and unverified.

The nine unreachable ones are seven config blocks and two compose entries. Not
one is a code defect.

The ranked list puts phrasing first: speak-as-herself fails all three criteria,
and everything that asks the resident model to write a Russian sentence inherits
that. His own name not being stored is second. Nine capabilities one config
change from reachable is fourth, and it is the highest ratio of capability to
work in the list.

Items 10, 12 and 13 stall on unresolved invariants and are the owner's call, not
work.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 12:44:15 +04:00

14 KiB
Raw Blame History

Gaps: what is missing, and what the architecture does about it

Hand-written, except the four capability classes, which are derived.

This file compares responsibilities. It never compares package names. A package existing is not a capability, and a capability can be spread over six packages and still be missing.

Where each class comes from

Classes 1 through 4 are the gap_class field in docs/capabilities/ledger.yaml, derived from the seven implementation dimensions and the criteria verdicts. Rebuild them:

python3 docs/capabilities/build_ledger.py

Classes 5 through 8 are read from docs/architecture/findings.md and docs/capabilities/invariants.md. Every entry names the capability or invariant it affects. An entry affecting neither is marked non-blocking cleanup, in those words, and it is the whole of class 8.

Counts are over the 46 v1 capabilities. The 5 deferred ones are excluded.


1. Capability missing (5)

Nothing carries it. code_present: no.

capability criteria note
summaries 0 pass, 3 fail no package. Wanted by email-triage, web-crawling, hearing and rss-and-news, each of which would consume it
webhooks 0 pass, 3 fail no package. Telegram's own inbound channel is mapped to telegram, not here
command-chaining 0 pass, 3 fail no package. The chain in internal/router is the world chain and the source chain
learning-the-style 1 pass, 2 fail the pass is a negative criterion satisfied by absence. The build reports it as an anomaly
learning-from-mistakes 0 pass, 2 fail no package

The last two are invariant 10, and it is unresolved. Whether behavioural learning is wanted is a product question, so these two are not automatically work.

2. Capability partial (21)

Reachable, and at least one criterion was observed failing. This is the class that matters most, because a user can get to all 21 today and 21 misbehave.

route-an-utterance, ask-instead-of-guessing, answer-from-your-own-data, answer-from-the-world, read-an-encyclopedia, facts, notes, recall, reminders, voice, web-ui, desk-notifications, wake-word, nexus, praxis, the-deployed-stack, encrypted-database, passkey-and-step-up, tests-and-analyzers, web-crawling, cron-jobs.

wake-word is the sharpest: reachable on every dimension and 0 of 2 criteria pass.

3. Capability exists but unreachable (9)

Built, and the deployed configuration does not reach it.

capability why class of fix
speak-as-herself reachable: partial on core.model_seam configuration
weather no weather key in the deployed voice block configuration
see-an-image no media block configuration
memory-evaluation worker is configured-off configuration
ntfy present in the config and disabled there configuration
hearing capture.enabled false and no capture client ships (V-514) configuration and code
mcps no MCP server configured, and V-478 blocks the one candidate deployment
email-triage mavmaild is not in docker-compose.yml deployment
calendar-management mavcaldav is not in docker-compose.yml deployment

None of these nine is a code defect. Seven are one config block and two are one compose entry. docs/spec.md says this about the audit's four and it still holds for these nine.

4. Capability exists but unverified (11)

Reachable, nothing observed failing, and not all criteria pass. These are measurement gaps, not defects.

interruption-policy, digest-of-held-nudges, morning-routine, routine-proposals, tasks, rss-and-news, telegram, speech-to-text, text-to-speech, hexis, network-scans.

Four of them, the whole Proactive cluster, are untested on every criterion, because a proactive behaviour cannot be probed by sending an utterance. That is the shape of the gap and it needs a different harness, not more probes.


5. Duplicated mechanism (6)

what affects owned?
Two independent arbitrations decide one turn: seven intents, then twenty-two ordered query sources (findings.md 2.1) invariant 11, route-an-utterance, answer-from-your-own-data no
A third arbitration runs before both: eleven stateful pre-emptors in the pre-route ladder (findings.md 2.2) invariant 11, invariant 6, ask-instead-of-guessing no
Two tier systems. internal/auth does not bind the turn path, internal/tool is not keyed on the reach (findings.md 6.3, 6.3b) invariant 8, hexis, passkey-and-step-up no
Two representations of reach, both ignored (findings.md 6.3) invariant 8, voice no
Two digest mechanisms with the same word in the name, flushed six lines apart (findings.md 2.4) invariant 5, digest-of-held-nudges no
Restraint decided twice: the gate decides whether a rule emits, delivery decides where it lands (findings.md 2.3) interruption-policy yes, argued in channel.go

The last row is duplication that is owned. It is listed so it is not rediscovered as a defect.

6. Missing shared mechanism (6)

what is missing affects
A single point that decides whether this origin may perform this effect with this evidence. origin × effect × evidence → permit is the target and nothing computes it invariant 8, hexis, praxis, voice, passkey-and-step-up
An owner for a key namespace. facts has nine writers, notes six, tools three unrelated proposers (findings.md 1.1, 1.2, 1.3) invariant 2, facts, notes, recall
A comparable unit of evidence, so claimants can answer "is this more mine than yours?". internal/claim is that unit, written, tested and called by nothing (findings.md 6.1) invariant 11, command-chaining
A conversation that spans reaches. mavweb instead hardcodes one conversation id for the whole web reach invariant 1, web-ui, voice, telegram
A stated rule for what survives a restart. Six stores, six independent choices, two of them argued invariant 12, ask-instead-of-guessing
A summariser. Four capabilities would consume one and none exists summaries, email-triage, web-crawling, hearing

7. Current architecture conflicts with target behavior (10)

The class where the code works as written and the written thing is not what the spec asks for.

conflict affects
Four silent degradations stack on one turn, and docs/spec.md writes every v1 DoD at "honest" (findings.md 8.1) invariant 7, answer-from-the-world, speech-to-text, route-an-utterance, speak-as-herself
praxisItemAction.handle calls straight through: acknowledge, resolve, ignore and pin run on first hearing with no tier and no confirm turn (findings.md 6.3c, cmd/mavend/ecosystem_acts.go:158) invariant 8, praxis
weather is a live query source with guesses: true and the deployed config selects no provider, so it can claim a turn and answer from a stub (findings.md 11.3) invariant 7, weather
loop.State.CalendarBusy reads facts mavcaldav never writes, so the do-not-nag-mid-meeting suppressor is permanently false (findings.md 8.2) invariant 3, interruption-policy, calendar-management
Recurring reminders have a column, an IPC parameter and no caller. actionReminder passes "" (findings.md 8.3) reminders, cron-jobs
The clarify store is not persisted and the expired-clarify notice reads the store that is gone (findings.md 7.5) invariant 6, invariant 12, ask-instead-of-guessing
Claim.Coverage returns 1.0 for a claim that extracted nothing (findings.md 6.3d) invariant 11. Latent: it corrupts the fix for class 6 row 3 before that fix ships
The act executor runs inside the key holder, and the process boundary is not one of the controls (findings.md 5.4) invariant 8, hexis, encrypted-database
The voice wire's whole security argument is external: loopback publish plus an ssh tunnel, so one compose edit removes it (findings.md 5.5) invariant 8, voice
make test is green with the four TestONNX* measurements silently skipped, because the recipe does not set MAVEN_ONNX_LIB tests-and-analyzers, recall. It is why the predecessor audit had a green suite and 22 dead capabilities

8. Architecture concern with no current product impact (11)

Every row here is non-blocking cleanup. None names a capability or an invariant, which is the test for belonging in this class rather than in 5, 6 or 7.

  • reactiveHandler has 34 fields (findings.md 4.1).
  • runTurn is one function with eleven early returns (4.2).
  • tick runs thirteen jobs in one function (4.3).
  • wireVoice is one constructor for seventeen subsystems (4.4).
  • mavsttd and mavttsd are separate processes at a scale that does not need it (5.1).
  • Three IPC connections from one process (5.2).
  • A construction cycle between the API layer and the turn layer (3.1).
  • The handler holds the raw store beside the mediated one (3.2).
  • queryDayPlan reads the proactive scheduler, the single call across that line (3.4).
  • internal/modes is imported by nothing outside itself (6.2).
  • The daemon is wired twice, in two places (8.6).

Two entries were considered for this class and moved out. queryNetwork triggering a live LAN scan inside a read path (6.4) affects network-scans, whose two remaining criteria are unknown. actionFact re-routing into the query chain (6.5) affects facts and route-an-utterance, which is where the "меня зовут Ками" misroute lives.


Priority

One list. The rank is the plan's, and it is about impact today, not about how ugly the code is. An unwired or unreachable future defect never outranks a live user-visible failure because its architecture is offensive.

1. Prevents intended everyday use today

  1. speak-as-herself fails all three criteria. The deployed resident model, maven-instruct-b2-Q4_K_XL, produces Russian sentences that no longer hold together, and the phrasing checks that would catch it run in the eval and not on the outbound path. Everything that asks the model to write a sentence inherits this. Formal вас and вы reached the wire while CheckFeminine passed.
  2. His own name is not stored as a fact. "меня зовут Ками" routes to chat, so nothing is written, and "что ты помнишь обо мне?" routes to chat too. Two of the seven audit probes, still broken and now broken differently.
  3. wake-word fails both criteria while reachable on every dimension. Voice is the spine of v1 and the always-on half of it does not work.
  4. Nine capabilities are one config block or one compose entry from reachable. weather, ntfy, see-an-image, memory-evaluation, email-triage, calendar-management and mcps are the cheap ones. This is the highest ratio of capability to work in the whole list.

2. Makes existing behavior incorrect or unreliable

  1. The Praxis lifecycle path has no gate. Four remote mutations run on first hearing. This is live today and needs no new wiring to matter.
  2. weather answers from a stub and is allowed to claim the turn. A source marked guesses: true with no provider is worse than a named gap.
  3. The busy suppressor is permanently false. Every interruption decision that should have deferred to a meeting fails open.
  4. Four silent degradations stack, and nothing in a reply distinguishes the worst case from the best. Invariant 7 has no written boundary between "only better" and "cannot do the job".
  5. A parked clarify survived five consecutive turns and was released by a path other than отмена. Invariant 6 says nobody owns closing it.

3. Blocks multiple capabilities

  1. No single authorization point. Invariant 8, unresolved, and the third of the three questions the freeze was called to answer. It blocks hexis, praxis, voice and passkey-and-step-up, and it is the one property nobody can currently state.
  2. No owner for a key namespace. A fetch watermark and a tuning parameter live in the table recall embeds and queryFactByKey reads back as an answer.
  3. No comparable unit of evidence. Three ordered lists decide one turn. command-chaining cannot be built on top of them, and internal/claim carries a live defect before it is wired.
  4. No summariser. Four capabilities would consume one.

4. Prevents verification

  1. make test is green with four measurements skipped. The recipe does not set MAVEN_ONNX_LIB. This is the exact trap CLAUDE.md describes, and the baseline walked into it while measuring whether other things had.
  2. The whole Proactive cluster is untested on every criterion. A proactive behaviour cannot be probed by sending an utterance. It needs a clock-driving harness, not more probes.
  3. 26 of 31 named scenarios do not exist on disk. Only 5 of 51 spec entries cite a scenario that is there (findings.md 9.5).
  4. POST /api/ptt was called unreachable in an earlier draft and is not. Four speech criteria were filed deployment missing when the deployment is present and the probe was never written.

5. Architectural cleanup with no present user impact

  1. Everything in class 8, in any order. None of it blocks a capability or an invariant, and that is why it is last.

What this file does not do

It does not schedule. docs/roadmap.md orders the work and this file feeds it.

It does not decide the four unresolved invariants. Authority and confirmation, learning from outcomes, capability composition and the shelf life of a held nudge are the owner's, and items 10, 12 and 13 above stall on them.