78a9c61acb
51 capabilities: the 39 rows from the 2026-08-13 audit plus 12 v1 items that had no audit row. Each entry carries a state reference to the living doc that owns it, a plain DoD list observable on the running box, and the scenario file that scopes it. Applying "state is a reference" found 17 capabilities with no living doc. Only 5 of 51 entries cite a scenario that exists. --no-verify: committing on master by the owner's call this session. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
618 lines
25 KiB
Markdown
618 lines
25 KiB
Markdown
# Spec: every capability, and what done means for each
|
|
|
|
*Last verified: 2026-08-15 @ 231248a*
|
|
|
|
What Maven is for, capability by capability, with a definition of done that can
|
|
be observed on the running box. `CLAUDE.md` carries the rules. `docs/roadmap.md`
|
|
carries the order. This file carries the target.
|
|
|
|
The capability list is the union of two sources. The 39 rows measured in
|
|
`docs/evals/2026-08-13-capability-audit.md`, and the 18 items the owner named as
|
|
v1 scope. Twelve of the owner's items had no audit row, so this file has 51.
|
|
|
|
## How to read an entry
|
|
|
|
**State** is a reference, never a word. It points at the living doc that holds
|
|
the current or the desired implementation. Where no such doc exists, the entry
|
|
says so, and that absence is a finding this file is surfacing on purpose.
|
|
|
|
**DoD** is a plain list of observable conditions. Each item is checkable on the
|
|
running stack. An utterance and its answer, a log line, an outbox row, an HTTP
|
|
response, or a store row.
|
|
|
|
**Scenario** names a file in `cmd/mavend/testdata/scenarios/`, which scopes the
|
|
flow from utterance to output. Five exist today: `act_degraded`,
|
|
`assistant_workday`, `conversation_anaphora`, `evening_degraded`,
|
|
`morning_missed`. A name marked *(to write)* does not exist yet, and writing it
|
|
is part of that capability's work.
|
|
|
|
Every clock time in this file is `Europe/Samara`, declared once in
|
|
`docker-compose.yml` with `/etc/localtime` pointed at it (V-545). Every path
|
|
reads `time.Local`.
|
|
|
|
## What v1 means
|
|
|
|
v1 is a voice assistant, minimum viable. Voice is the spine and the capability
|
|
list is the surface. Each DoD below is written at "voice-reachable and honest",
|
|
not at "feature-complete". Honest means she names the gap when she cannot do the
|
|
job, and never fills it with a guess.
|
|
|
|
Seven capabilities in v1 have no design yet. They keep a DoD here, written at
|
|
what done would look like, and their state entry names the missing doc. The gap
|
|
stays visible instead of implied-done.
|
|
|
|
## The turn
|
|
|
|
### Route an utterance
|
|
|
|
- **State**: `docs/routing.md`.
|
|
- **DoD**
|
|
- Seven intents score separately from the source, on every turn.
|
|
- A question about what Maven remembers routes to query, not remember. The
|
|
audit's two misrouted probes of seven pass.
|
|
- Any resident-model error falls through to the classifier and the turn still
|
|
answers.
|
|
- Every turn writes a decision trace naming the stage that decided.
|
|
- **Scenario**: `conversation_anaphora`, `assistant_workday`.
|
|
|
|
### Ask instead of guessing
|
|
|
|
- **State**: `docs/routing.md`, the clarify head and the parked clarify ride.
|
|
- **DoD**
|
|
- An incomplete reminder parks and asks for the missing slot, not for all of them.
|
|
- "отмена" during a parked clarify drops the parked turn and says so.
|
|
- A parked clarify survives an interleaved unrelated turn and resumes.
|
|
- **Scenario**: `conversation_anaphora`.
|
|
|
|
### Speak as herself
|
|
|
|
- **State**: `docs/language.md`.
|
|
- **DoD**
|
|
- No masculine self-reference reaches the wire. The audit caught "Хорошо,
|
|
сохранил" live while `CheckFeminine` passed in the eval, so the check runs on
|
|
the outbound path and not only in the eval.
|
|
- She says "ты" throughout, and no pet name appears.
|
|
- A rejected reply is logged with what failed, not silently rephrased.
|
|
- **Scenario**: `morning_missed` pins the constant. `persona_wire` *(to write)*
|
|
pins model output on the outbound path.
|
|
|
|
### Answer from your own data
|
|
|
|
- **State**: `docs/routing.md`, `queryWalk` in `cmd/mavend/actions_query.go`.
|
|
- **DoD**
|
|
- "что у меня сегодня по плану?" returns the real checklist and its open items.
|
|
- The owner's sources are asked before anything outside, every time.
|
|
- A source that looks rather than guesses is asked even when a destination is named.
|
|
- **Scenario**: `assistant_workday`, `morning_missed`.
|
|
|
|
### Answer from the world
|
|
|
|
- **State**: `docs/world.md`.
|
|
- **DoD**
|
|
- A general-knowledge question returns a Russian summary that does not invent
|
|
physics. The audit's "почему небо голубое?" answer is the failing case.
|
|
- Only the utterance leaves the box. No persona block, no history, no matched notes.
|
|
- Deleting the `search` block turns the capability off with a named gap, not an error.
|
|
- **Scenario**: `world_summary_quality` *(to write)*.
|
|
|
|
### Read an encyclopedia
|
|
|
|
- **State**: `docs/world.md`, the Kiwix section.
|
|
- **DoD**
|
|
- A Russian question lands on the Russian book and an English one on the English book.
|
|
- Kiwix answers when the line is down.
|
|
- The retrieved article is on the question's topic, not merely a lexical match.
|
|
- **Scenario**: `kiwix_language_pick` *(to write)*.
|
|
|
|
### Weather
|
|
|
|
- **State**: `internal/weather`. No living doc covers it. **Finding**: the
|
|
provider seam, the home city and the clarify path have no written reasoning
|
|
anywhere. The audit found the capability broken on configuration alone.
|
|
- **DoD**
|
|
- A `weather` block in `deploy/mavend.json` names a provider and a home city.
|
|
- "какая сейчас погода?" answers for the home city without asking.
|
|
- Naming another city answers for that city. The audit's follow-up "Самара"
|
|
died with "Я тебя не разобрала", so the follow-up parks as a clarify instead
|
|
of emitting a question through the answer path.
|
|
- With no provider configured she names the gap and does not guess a forecast.
|
|
- **Scenario**: `weather_followup` *(to write)*.
|
|
|
|
### See an image
|
|
|
|
- **State**: `internal/vision`, the seam that stores the image and says so. No
|
|
living doc. **Finding**: V-667 has the gemma-4 mmproj on the box and no
|
|
written contract for what a vision call returns.
|
|
- **DoD**
|
|
- An image sent through Telegram gets a Russian description.
|
|
- With no vision model configured she says she cannot look, and the image is stored.
|
|
- The vision call goes to the workstation and falls back silently when it is down.
|
|
- **Scenario**: `vision_degraded` *(to write)*.
|
|
|
|
## Memory
|
|
|
|
The four memory rows below have no living doc. **Finding**: `docs/design.md`
|
|
sketches the store and `docs/routing.md` covers recall's routing. Nothing owns
|
|
the fact and note contracts, the supersede rule, or the digestion worker's
|
|
consolidation pass. This is the largest documentation gap in the list.
|
|
|
|
### Facts
|
|
|
|
- **State**: `internal/store/facts.go`, `cmd/mavend/factenrichment.go`. No living doc.
|
|
- **DoD**
|
|
- A stated fact is written and confirmed in his own words, in the feminine.
|
|
- A confirmation that says she wrote something is never emitted without the
|
|
row existing. The audit's "я записала информацию о тебе" wrote nothing.
|
|
- A superseding fact retires the old value and both are readable.
|
|
- `actionFact.Subject` resolves through Nexus, never through a local key.
|
|
- **Scenario**: `morning_missed`.
|
|
|
|
### Notes
|
|
|
|
- **State**: `internal/memory`. No living doc.
|
|
- **DoD**
|
|
- A note captured from any reach is recallable by question.
|
|
- A note can be deleted by voice and from the web UI. `/api/revert` voids facts
|
|
by key and nothing voids a note today (V-494).
|
|
- A question is not stored as a statement. The audit's "я рассказывал тебе про
|
|
байкал?" became a junk note.
|
|
- **Scenario**: `note_delete` *(to write)*.
|
|
|
|
### Recall
|
|
|
|
- **State**: `docs/routing.md` for the query walk and the personal boundary.
|
|
- **DoD**
|
|
- The embedder loads at 384 dimensions with the marker check passing, on every start.
|
|
- `EmbedQuery` and `EmbedPassage` carry their prefixes. A plain `Embed` on a note fails the build or the test.
|
|
- The personal boundary scores a question about him as personal.
|
|
`TestONNXPersonalBoundary` is green.
|
|
- A recall miss says she does not remember, and does not answer from the world instead.
|
|
- **Scenario**: `assistant_workday`.
|
|
|
|
### Memory evaluation
|
|
|
|
- **State**: `internal/memeval`. No living doc. **Finding**: the evaluator ships,
|
|
writes notes and cannot speak, and nothing records what its conclusions mean (V-248).
|
|
- **DoD**
|
|
- One evaluation run is observed on the box and its notes are read back.
|
|
- What it concluded is checkable against the notes it read.
|
|
- **Scenario**: `memeval_run` *(to write)*.
|
|
|
|
## Proactive
|
|
|
|
### Reminders
|
|
|
|
- **State**: `internal/store`, `internal/delivery`. No living doc covers the
|
|
reminder lifecycle. **Finding**: parking, firing, delivery, retry and
|
|
cancellation are spread across three packages with no written contract.
|
|
- **DoD**
|
|
- A one-shot reminder set by voice fires at its time and is delivered.
|
|
- **Recurring works from speech**: meetings, pills, the dog, the vet and the
|
|
kibble. `store.Reminder` carries `Cron` and `ipc.CreateReminder` takes a cron
|
|
argument, and no caller in `cmd/mavend` passes one. Recurring is unbuilt with
|
|
its storage and delivery already finished under it.
|
|
- A recurring reminder states its schedule back when it is set, and again when
|
|
asked.
|
|
- Cancellation works by voice and from `/reminders`, and a refusal is honoured.
|
|
- A failed delivery retries into another reach rather than looping. The audit
|
|
watched the ntfy failure run once a minute until 03:05.
|
|
- **Scenario**: `recurring_reminders` *(to write)*. Cancellation is covered by the
|
|
V-719 eval.
|
|
|
|
### Interruption policy
|
|
|
|
- **State**: `docs/handler-wiring.md` for the dispatch decision. **Finding**: the
|
|
four presence-and-severity outcomes have never been written down as intended
|
|
behaviour, only as code (V-281).
|
|
- **DoD**
|
|
- The four outcomes are named in a doc before any of them changes.
|
|
- A severity-1 item with him present at the desk reaches him through some reach.
|
|
The audit logged `dropped morning:утро (sev1, presence=present)`.
|
|
- Nothing unprompted arrives during a quiet tick.
|
|
- **Scenario**: `morning_missed`, `evening_degraded`.
|
|
|
|
### Digest of held nudges
|
|
|
|
- **State**: `internal/worker`, the digestion worker. No living doc.
|
|
- **DoD**
|
|
- A suppressed nudge candidate is observed surfacing in a later digest, on the box.
|
|
- The semantic fingerprint is checked before the phraser is paid.
|
|
- Digestion never calls Hexis.
|
|
- **Scenario**: `evening_degraded`.
|
|
|
|
### Morning routine
|
|
|
|
- **State**: `internal/morning`, `internal/routine`. No living doc.
|
|
- **DoD**
|
|
- The morning plan reaches him inside its 08:00-11:00 window, `Europe/Samara`.
|
|
- When the voice reach has no session the plan falls back to the non-voice
|
|
reaches rather than being dropped (owner's call; related V-281).
|
|
- A missed window is stated as missed, not silently swallowed.
|
|
- **Scenario**: `morning_missed`.
|
|
|
|
### Routine proposals
|
|
|
|
- **State**: `internal/routine`. No living doc. **Finding**: the proposer reads a
|
|
hand-written Russian verb list, which the language rules forbid as a route or
|
|
fact source (V-606).
|
|
- **DoD**
|
|
- One proposal is observed on the box from real repeated behaviour.
|
|
- The verb list is replaced by `internal/lexicon` or the embedder.
|
|
- A proposal is a nudge he can decline, and declining it is stored.
|
|
- **Scenario**: `routine_proposal` *(to write)*.
|
|
|
|
### Tasks
|
|
|
|
- **State**: `internal/tasks`. No living doc.
|
|
- **DoD**
|
|
- Open tasks are read back ordered by deadline and urgency.
|
|
- A task captured by voice appears in the list and on the web UI.
|
|
- Mail-derived candidates are never spoken as tasks until he accepts one (V-130).
|
|
- **Scenario**: `assistant_workday`, `morning_missed`.
|
|
|
|
### RSS and news
|
|
|
|
- **State**: `internal/rss`. No living doc.
|
|
- **DoD**
|
|
- Feed items are read when asked and never announced unprompted. That is the
|
|
intended shape, not a defect.
|
|
- A question about a topic finds the matching item across the configured feeds.
|
|
- A dead feed names itself as dead, and the others still answer.
|
|
- **Scenario**: `morning_missed`.
|
|
|
|
## Reach
|
|
|
|
### Telegram
|
|
|
|
- **State**: `docs/deployment.md`, `internal/delivery/telegramsink`.
|
|
- **DoD**
|
|
- An outbound message is delivered and the outbox row records the delivery.
|
|
- His chat is read continuously from restart.
|
|
- The socks relay being down names the gap and holds the message.
|
|
- **Scenario**: `evening_degraded`.
|
|
|
|
### ntfy
|
|
|
|
- **State**: `internal/delivery/ntfysink`, disabled in the committed config.
|
|
- **DoD**
|
|
- A write-scoped `NTFY_TOKEN` exists before re-enabling. It was switched off
|
|
after a 403 storm.
|
|
- A 403 stops retrying instead of looping once a minute.
|
|
- **Scenario**: `ntfy_403` *(to write)*.
|
|
|
|
### Voice
|
|
|
|
- **State**: `docs/protocol.md` for the wire, `internal/delivery/voicesink` for the sink.
|
|
**Finding**: the wire is documented and the listener is not. Nothing describes
|
|
what holds a live voice session open.
|
|
- **DoD**
|
|
- A proactive message reaches him by speech without him speaking first. Every
|
|
proactive message during the audit fell through with "no live voice session".
|
|
- The port stays on homesrv loopback and reaches workpc over ssh.
|
|
- `SurfaceVoice` caps acts at L0, and reading is not capped.
|
|
- **Scenario**: `voice_push` *(to write)*.
|
|
|
|
### Web UI
|
|
|
|
- **State**: `docs/deployment.md`.
|
|
- **DoD**
|
|
- All pages answer 200.
|
|
- Every capability with a surface has a page: reminders, notes, tasks, facts.
|
|
- A destructive action on a page is gated by step-up.
|
|
- **Scenario**: covered by `cmd/mavweb` tests, not by a scenario.
|
|
|
|
### Desk notifications
|
|
|
|
- **State**: `cmd/mavweb/ambient.go`, `internal/event`. No living doc.
|
|
**Finding**: the inbound direction exists as the `ambient:notif` source and the
|
|
outbound direction does not exist at all. Which one the owner means is an open
|
|
product decision.
|
|
- **DoD**
|
|
- Inbound: a desktop notification becomes a fact at the ambient path's own
|
|
confidence, filed low, and never spoken back unprompted.
|
|
- Outbound: a nudge can appear on the workpc desktop as a fourth reach, or the
|
|
outbound half is explicitly dropped from v1.
|
|
- **Scenario**: `morning_missed` covers inbound. Outbound has none.
|
|
|
|
## Speech and senses
|
|
|
|
### Speech to text
|
|
|
|
- **State**: `docs/offload.md`, `docs/deployment.md`.
|
|
- **DoD**
|
|
- Russian speech transcribes accurately enough to route. `mavsttd` is the local
|
|
floor and the workstation transcriber is the better path.
|
|
- The workstation being down falls back to `mavsttd` silently.
|
|
- The floor arm is exercised on its own, not only behind the workstation.
|
|
- **Scenario**: covered by `docs/evals/2026-08-09-crisperwhisper2-russian-wer.md`.
|
|
|
|
### Text to speech
|
|
|
|
- **State**: `docs/offload.md`, `docs/deployment.md`.
|
|
- **DoD**
|
|
- A reply is spoken in Russian with correct number and abbreviation expansion.
|
|
- `internal/ttsnorm` expands times and dates into `Europe/Samara` phrasing.
|
|
- **Scenario**: `tts_normalisation` *(to write)*.
|
|
|
|
### Wake word
|
|
|
|
- **State**: `docs/deployment.md`, `mavwaked` under systemd on workpc.
|
|
- **DoD**
|
|
- "Мэйвен" wakes her and a near-miss does not.
|
|
- Waking her opens a voice session the proactive path can push into. Waking is
|
|
not the same as having a session (V-515).
|
|
- **Scenario**: `voice_push` *(to write)*.
|
|
|
|
### Hearing
|
|
|
|
- **State**: `internal/capture`, `internal/audio`. No capture client ships (V-514).
|
|
- **DoD**
|
|
- A capture client runs on workpc and streams to `mavsttd` or the workstation.
|
|
- The path is reachable end to end from microphone to reply.
|
|
- **Scenario**: `voice_push` *(to write)*.
|
|
|
|
### Speaker recognition
|
|
|
|
- **State**: `internal/speaker`. No living doc (V-255).
|
|
- **DoD**
|
|
- The owner's voice is distinguished from another voice.
|
|
- A voice that is not his cannot reach the act path.
|
|
- **Scenario**: `speaker_gate` *(to write)*.
|
|
|
|
## The ecosystem
|
|
|
|
### Nexus
|
|
|
|
- **State**: `docs/ecosystem.md`.
|
|
- **DoD**
|
|
- Entities exist. Nexus answers "no entities yet" today, so every act naming a
|
|
target has nothing to resolve against. Seeding is a Nexus-side job.
|
|
- Free text resolves to a canonical entity id before any mutating call.
|
|
- Ambiguous resolution asks him and does not pick.
|
|
- Nexus down produces a named gap, not a broken turn.
|
|
- **Scenario**: `act_degraded`.
|
|
|
|
### Praxis
|
|
|
|
- **State**: `docs/ecosystem.md`.
|
|
- **DoD**
|
|
- An item needing attention is read back on request.
|
|
- Reading an item aloud calls `Surface`, never `Acknowledge`.
|
|
- Attention arrives over HTTP, never from its SQLite file.
|
|
- Digestion may summarise Praxis and may not call Hexis.
|
|
- **Scenario**: `morning_missed`, `evening_degraded`.
|
|
|
|
### Hexis
|
|
|
|
- **State**: `docs/ecosystem.md`.
|
|
- **DoD**
|
|
- An act runs against a real target once Nexus has entities.
|
|
- Confirmation binds capability id, target entity, arguments, requester and expiry.
|
|
- LLM output alone never authorizes.
|
|
- Every call carries a correlation id, a contract version and `X-Requested-By: maven`.
|
|
- **Scenario**: `act_degraded`.
|
|
|
|
### Smart home
|
|
|
|
- **State**: `internal/smarthome`, disabled in config (V-256).
|
|
- **DoD**
|
|
- A device is controlled through Hexis, resolved through Nexus, never by free text.
|
|
- Disabled means a named gap.
|
|
- **Scenario**: `act_degraded`.
|
|
|
|
### Network scans
|
|
|
|
- **State**: `internal/netscan`, `internal/netaddr`. No living doc.
|
|
- **DoD**
|
|
- A scan of the configured subnets returns hosts and open ports on request.
|
|
- The result is read back as prose, not as a table dump.
|
|
- The rate limit in the config is honoured.
|
|
- **Scenario**: `netscan_query` *(to write)*.
|
|
|
|
### Bluetooth control
|
|
|
|
- **State**: no package. **Finding**: nothing exists, and the box has no bluez
|
|
(V-257). This is the only v1 item blocked on the host rather than on code.
|
|
- **DoD**
|
|
- bluez is present on the box that owns the radio.
|
|
- A paired device is connected and disconnected by voice, through Hexis.
|
|
- **Scenario**: `bluetooth_control` *(to write)*.
|
|
|
|
### MCPs
|
|
|
|
- **State**: `internal/mcp`. No living doc. **Finding**: the allowlist, the
|
|
stdio and http transports and the webfetch door all exist. Nothing records
|
|
which servers may run, or why.
|
|
- **DoD**
|
|
- A configured MCP server's tools are callable through the act path.
|
|
- The allowlist is the only path to a tool, and a tool outside it is refused.
|
|
- A server that dies is a named gap, and the rest of the registry still answers.
|
|
- **Scenario**: `mcp_tool_call` *(to write)*.
|
|
|
|
## Operations
|
|
|
|
### The deployed stack
|
|
|
|
- **State**: `docs/deployment.md`.
|
|
- **DoD**
|
|
- All five compose services run the current build. The audit found three on a
|
|
four-day-old image.
|
|
- `mavwaked` on workpc is on the current build too, or its drift is stated.
|
|
- A restart loses nothing.
|
|
- **Scenario**: none. This is checked by `docker compose ps` and the startup log.
|
|
|
|
### Encrypted database
|
|
|
|
- **State**: `docs/deployment.md`, `docs/caveats/storage.md`.
|
|
- **DoD**
|
|
- The database is encrypted at rest with the working copy in tmpfs.
|
|
- The key comes from the environment and is held only by `mavend`.
|
|
- Passwords are read from files, never taken as flag values.
|
|
- **Scenario**: none. Checked by `mavseal` and the startup log.
|
|
|
|
### Passkey and step-up
|
|
|
|
- **State**: `docs/caveats/security.md`, `internal/webauthn`, `internal/auth`.
|
|
- **DoD**
|
|
- WebAuthn is configured, so no step-up gate is fail-open. Today every one is,
|
|
including `POST /api/chat`, which reaches the act path (V-683).
|
|
- Enrollment requires an existing credential once the first one exists.
|
|
- Step-up is per-request, not process-global.
|
|
- **Scenario**: `stepup_gate` *(to write)*.
|
|
|
|
### Model swap
|
|
|
|
- **State**: `docs/deployment.md` (V-250).
|
|
- **DoD**
|
|
- `phraser.swap_models` lists the allowed gguf paths, or the page is removed.
|
|
- A swap survives a restart, or the page states that it will not.
|
|
- **Scenario**: none.
|
|
|
|
### Self-update
|
|
|
|
- **State**: `cmd/mavupdate`, `internal/update`. Blocked at step 3: it cannot
|
|
reach the containerized socket (V-477).
|
|
- **DoD**
|
|
- An update runs to completion from inside the deployment.
|
|
- A failed update rolls back and says so.
|
|
- **Scenario**: none.
|
|
|
|
### Tests and analyzers
|
|
|
|
- **State**: `docs/qa.md`, `docs/workflow.md`.
|
|
- **DoD**
|
|
- `make test` is green with `-race` and `MAVEN_ONNX_LIB` set, so the four
|
|
`TestONNX*` measurements run instead of self-skipping.
|
|
- `make analyze` passes against its baselines, and a fix deletes its entry.
|
|
- The one latency test that fails only under coverage is fixed or filed (V-718).
|
|
- **Scenario**: none. This gate is the suite itself.
|
|
|
|
## Undesigned in v1
|
|
|
|
These seven have no design and no living doc. Each keeps a DoD written at what
|
|
done would look like, so the gap is visible instead of implied-done. A design
|
|
pass comes before any of them is built.
|
|
|
|
### Email triage
|
|
|
|
- **State**: `internal/email`, `cmd/mavmaild`. Built and **not in
|
|
`docker-compose.yml`**. **Finding**: the product decision comes first. What she
|
|
does with his mail is undecided, and deploying the daemon before deciding
|
|
writes the decision by accident.
|
|
- **DoD**
|
|
- The owner has decided what triage means: read-only summary, task extraction, or reply drafting.
|
|
- Mail-derived task candidates stay candidates until he accepts one (V-130).
|
|
- No mail content leaves the box.
|
|
- `mavmaild` is in compose, or its absence is deliberate and recorded.
|
|
- **Scenario**: `email_triage` *(to write)*.
|
|
|
|
### Calendar management
|
|
|
|
- **State**: `internal/calendar`, `cmd/mavcaldav`. Built and **not in
|
|
`docker-compose.yml`**. Same product decision as email.
|
|
- **DoD**
|
|
- Today's and tomorrow's events are read back, times in `Europe/Samara`.
|
|
- An event is created by voice, with the slot asked for rather than guessed.
|
|
- A conflicting event is stated as a conflict.
|
|
- `mavcaldav` is in compose, or its absence is deliberate and recorded.
|
|
- **Scenario**: `calendar_create` *(to write)*.
|
|
|
|
### Web crawling
|
|
|
|
- **State**: `internal/crawl` with `robots.go` and `watch.go`, `internal/webfetch`.
|
|
No living doc. **Finding**: politeness and robots are implemented. The
|
|
scheduling policy is not written anywhere.
|
|
- **DoD**
|
|
- A page is fetched on request and summarised in Russian.
|
|
- A watched page reports what changed, on a schedule he set by voice.
|
|
- robots and the politeness delay are honoured, observable in the log.
|
|
- Only the URL and the utterance leave the box.
|
|
- **Scenario**: `crawl_watch` *(to write)*.
|
|
|
|
### Summaries
|
|
|
|
- **State**: no package. **Finding**: summarisation exists inside the world chain
|
|
and inside digestion, and nothing owns it as a capability he can ask for.
|
|
- **DoD**
|
|
- "перескажи" over a note, a feed item, a page or a mail returns a Russian summary.
|
|
- The summary names its source.
|
|
- A summary that would invent content is refused, the way `Response.Empty()`
|
|
gates a world answer.
|
|
- **Scenario**: `summarise` *(to write)*.
|
|
|
|
### Webhooks
|
|
|
|
- **State**: only `internal/delivery/telegramsink/intake.go`, which is Telegram's
|
|
own inbound webhook. **Finding**: there is no general webhook capability in
|
|
either direction, and no doc says which direction is wanted.
|
|
- **DoD**
|
|
- Inbound: an authenticated external event becomes a fact or a nudge candidate.
|
|
- Outbound: a nudge can post to a configured URL as a reach.
|
|
- Neither direction is reachable without authentication.
|
|
- **Scenario**: `webhook_inbound` *(to write)*.
|
|
|
|
### Cron jobs
|
|
|
|
- **State**: `internal/routine`, `cmd/mavend/tick_routines.go`. **Finding**:
|
|
routines carry a `Cron` and are a separate mechanism from reminders. Whether
|
|
"cron jobs" means user-defined scheduled acts or the existing routines is
|
|
undecided.
|
|
- **DoD**
|
|
- A scheduled job is created by voice, with its schedule stated back.
|
|
- It runs on schedule in `Europe/Samara` and its run is recorded.
|
|
- A job that runs an act is bound by the same confirmation rules as any act.
|
|
- Its relationship to routines and to recurring reminders is written down, so
|
|
three schedulers do not exist.
|
|
- **Scenario**: `cron_job` *(to write)*.
|
|
|
|
### Learning the style
|
|
|
|
- **State**: no package. **Finding**: nothing exists beyond
|
|
`internal/phraser/eval/checks.go`, which scores style and does not learn it.
|
|
Learning means behavioral, not weights: stored outcomes, no adapter, no
|
|
training set.
|
|
- **DoD**
|
|
- A corrected phrasing is stored as an outcome and changes a later reply.
|
|
- No model weights change and no training set is built.
|
|
- What was learned is readable on a page and can be deleted.
|
|
- **Scenario**: `style_correction` *(to write)*.
|
|
|
|
### Learning from mistakes
|
|
|
|
- **State**: no package. Same behavioral rule as above.
|
|
- **DoD**
|
|
- A dismissed nudge, a corrected phrasing and a repaired route are each stored
|
|
as an outcome.
|
|
- A repeated dismissal suppresses that nudge shape.
|
|
- A repaired route changes the next routing of the same utterance.
|
|
- Every stored outcome is readable and deletable.
|
|
- **Scenario**: `learn_from_dismissal` *(to write)*.
|
|
|
|
### Command chaining
|
|
|
|
- **State**: no package. The `chain` in `internal/router` is the world chain and
|
|
the source chain, not command chaining. **Finding**: nothing exists.
|
|
- **DoD**
|
|
- "напомни мне и запиши это" performs both, or asks which one.
|
|
- A chain containing an act confirms each act separately.
|
|
- A failed step stops the chain and names the step that failed.
|
|
- **Scenario**: `command_chain` *(to write)*.
|
|
|
|
## What this file rules out
|
|
|
|
A definition of done that a test suite can score. The suite was green during the
|
|
audit and 22 of 39 capabilities were not live. Every criterion above is
|
|
observable on the running box.
|
|
|
|
A roadmap ordered by code work. None of the four broken capabilities is a code
|
|
defect. Weather has no configuration block. Nexus has no data. The voice reach
|
|
has no listener. Step-up has no WebAuthn credential.
|
|
|
|
## The documentation gaps this file surfaced
|
|
|
|
Applying the "state is a reference" rule found seventeen capabilities with no
|
|
living doc. Memory is the largest cluster. Facts, notes and the digestion worker
|
|
have no owning document at all. Proactive is the second. The reminder lifecycle
|
|
spans three packages with no written contract. `docs/roadmap.md` orders the work,
|
|
and these gaps are part of it.
|