v0.15.0 to v0.16.0

28 added, 110 removed. Audit A to A.

---
name: notification-manual
description: >
- Router for the notification filesystem protocol and the standalone
- `notification` tool: read when interpreting `.notification/<channel>.json`,
- choosing producer-specific handling, or safely dismissing a mirror.
- Large-result/context compaction belongs to `context-manual`, not here.
- version: 0.15.0
+ Entry manual for the standalone `notification` tool and its `.notification`
+ mirrors. Routine check uses the schema; read a reference for unfamiliar payload,
+ producer, dismissal, delay, or settings detail. Large-result compaction belongs
+ to `context-manual`, not here.
+ version: 0.16.0
tags: [lingtai, notifications, channels, dismiss, delay, alarm, settings, manual, force, stale, nudge, hooks, whitelist]
- last_changed_at: "2026-09-06T00:00:00Z"
+ last_changed_at: "2026-09-09T05:30:00Z"
related_files:
- src/lingtai/prompts/meta_guidance/catalog/notification_handling.md
- src/lingtai/tools/notification/ANATOMY.md
- src/lingtai/tools/notification/CONTRACT.md
- src/lingtai/tools/notification/__init__.py
- src/lingtai/kernel/tool_plugin/CONTRACT.md
- src/lingtai/tools/notification/schema.py
- src/lingtai/tools/notification/settings.py
- src/lingtai/tools/notification/manual/reference/channel-model/SKILL.md
- src/lingtai/tools/notification/manual/reference/dismissal-safety/SKILL.md
maintenance: |
- Tracks the routed source/resources it summarizes; update when the underlying capability or its sub-references change.
+ Keep this entry and its two references concise and aligned with the notification
+ capability; preserve their installed relative routes and unique safety rules.
---
- # Notification Manual — Router
-
- `notification` is the sole agent-callable surface for reading and clearing the
- current `.notification/<channel>.json` mirrors. `system` has no notification or
- dismiss alias; compaction is `context(action='summarize')`.
-
- ## Quick start
+ # Notification Manual — entry and routes
- The resident schema is the source of truth for eleven strict actions in the
- `action` + `input` + `reasoning` envelope. Begin with:
+ Use the schema for routine `action` + `input` + `reasoning` calls; start with:
```text
notification(action='check', input={}, reasoning='inspect current notifications')
```
- `check` is read-only and returns a placeholder whose live payload is attached by
- the kernel. After handling a notification, use the narrowest matching dismiss
- action and do not call `check` merely to confirm the clear. Follow a producer's
- own read/dismiss verb when `instructions` names one: generic dismissal clears
- the mirror only, never producer state. Reread current state after a stale
- refusal; use `force=true` only for a confirmed stale mirror, never for producer
- or protected state. Read the dismissal-safety reference before forcing and the
- channel-model reference when interpreting payloads, hooks, delay, or delivery.
-
- Optional fields are required-but-nullable in the provider schema; `null` means
- omitted. `dismiss_channel` requires `channel`; `dismiss_event` and
- `dismiss_ref` default `channel` to `system`. A post-molt dismissal requires a
- non-empty `continue|defer|obsolete: ...` reason. `manual` and `settings` accept
- only `input={}` and are read-only.
-
- ## Consumer delay and expiry alarm
-
- `notification(action='delay', input={'channel': '<allowed>', 'seconds': 0 or a positive configured cap}, reasoning='...')`
- hides consumer delivery for one allowed target only. `seconds: 0` cancels the
- matching delay; a nonzero call replaces the previous live delay. Producer files
- keep receiving updates. The live cap is
- `LINGTAI_NOTIFICATION_DELAY_MAX_SECONDS` (default `600`); missing, blank,
- non-numeric, non-positive, or non-finite values use that default. `delay-alarm`
- cannot be targeted. At expiry or recovery, delivery resumes and one
- high-priority `delay-alarm` mirror records bounded evidence; persistence and
- recovery details belong to the channel-model reference.
-
- The SHOW row is `notification.delay_max_seconds`: `current` is the effective
- positive integer from the live environment or the default `600`, and invalid
- input falls back to `600`. SHOW does not write or refresh anything. Change the
- existing launcher or `env_file` only with configuration-owner approval, then
- perform the authorized refresh/relaunch and verify with `settings`.
-
- ## Notification settings
-
- `notification(action='settings', input={}, reasoning='inventory')` is read-only.
- It returns exactly two rows, in order, each with only `key`, `current`, `default`,
- `configurable`, and `comment`:
-
- - `notification.max_chars` →
- `notification-manual#block-size-cap-persistent-and-attention-lanes`
- - `notification.delay_max_seconds` →
- `notification-manual#consumer-delay-and-expiry-alarm`
-
- The comment targets are the source of truth for meaning, precedence, accepted
- values, and authorized change/verification procedures. If either current value
- is unavailable, the whole action fails; it never returns partial rows. Channel
- payloads, accounts, hook manifests, delay state, and session state are not
- settings rows.
-
- ## Root `summarize`
-
- Notification is a short-result family. Leave the root `summarize` boolean false
- when retrieving `manual`, because exact procedures and constraints matter. Use
- `context(action='summarize')` for tool-result compaction and recovery; the
- legacy `large_tool_result` reminder is only an escape hatch and never changes
- producer state.
-
- ## Installed manual retrieval
+ `check` returns a placeholder; read the live payload under `_meta.agent_meta.notifications.attention` and the hook under `_meta.agent_meta.guidance.transient` on that result, not an older delivered snapshot. Follow the payload's producer-specific read/dismiss instructions first. Generic dismissal affects mirrors only, not mailbox, goal, source-queue or other producer state. Choose the narrowest target; do not delete files or call `check` merely to confirm a clear.
- `notification(action='manual', input={})` reads only:
+ ## Route one owner
- ```text
- <agent>/.library/intrinsic/capabilities/notification/SKILL.md
- ```
+ | Need | Read |
+ |---|---|
+ | Payload, delivery, allowlist, hooks, delay mechanics or spill recovery | [Channel model](reference/channel-model/SKILL.md) |
+ | Target selection, producer guard, stale refusal, force, protected goal or post-molt | [Dismissal safety](reference/dismissal-safety/SKILL.md); read before forcing |
+ | Tool-result compaction or recovery by tool_call_id | `../context-manual/reference/summarize-manual/SKILL.md` |
+ | Goal cancellation/completion | `../system-manual/reference/goal-manual/SKILL.md` |
+ | Runtime/configuration nudges | `../system-manual/reference/runtime-update-checks/SKILL.md` |
- Success returns exactly `status`, `notification_manual`, and `manual_path`. A
- missing installed file is degraded with an empty body and an actionable `error`;
- there is no source-checkout fallback. Manual retrieval neither reads nor writes
- `.notification/`, producer state, delay state, or logs.
+ ## Consumer delay and expiry alarm
- ## Hooks & whitelist
+ `notification.delay_max_seconds` is the positive cap from live `LINGTAI_NOTIFICATION_DELAY_MAX_SECONDS`, otherwise `600`; missing, blank, non-numeric, non-positive or non-finite values fall back to the default. `delay` hides one allowed consumer target, never stops its producer. Nonzero replaces the prior delay; `0` cancels only the matching target. `delay-alarm` cannot be delayed. Expiry/recovery restores delivery and publishes one latest-only alarm. For daemon, only attention is masked: payload/version/summary remain readable. See [channel model](reference/channel-model/SKILL.md).
- External hooks must be registered with `add` before their channel is accepted.
- The effective allowlist is the built-in set, `mcp.*`, and channels registered by
- this agent's workdir; it is not process-global. `drop` revokes registration but
- never stops the hook process. Use the manifest's `how_to_cancel` to stop it.
- The channel-model reference owns the setup flow, manifest fields, registry
- behavior, and blocked-channel warn-and-flag details.
+ Change the environment only with owner approval and apply it through the authorized refresh/relaunch procedure; verify the live SHOW value afterward.
## Block size cap (persistent and attention lanes)
- `notification.max_chars` is one shared character cap (default `10000`, bounded
- `2048..10000`) for the persistent and attention lanes. The effective value reads
- live environment `LINGTAI_NOTIFICATION_MAX_CHARS`, then valid System-v2
- `notification_max_chars`, then the default; malformed values fall through.
- Oversized payloads are atomically spilled and compacted while preserving routing
- ids, with a marker-only fallback when necessary. This is a context-size control,
- not delivery or access control. Spill names, compaction order, and recovery are
- owned by the channel-model reference.
+ `notification.max_chars` is one live cap for both lanes: environment `LINGTAI_NOTIFICATION_MAX_CHARS`, then valid System-v2 `notification_max_chars`, then `10000`, clamped to `2048..10000`. Malformed values fall through. It limits context size, not access or delivery. Oversized content spills before compaction; follow the exact spill locator (or producer tool on `spill_failed`) before acting on a capped payload. See [channel model](reference/channel-model/SKILL.md).
- The SHOW row `notification.max_chars` reports that same effective clamped value.
- Change only through the existing authorized environment or closed System-v2 owner
- procedure; an environment/launcher change needs the authorized refresh or
- relaunch, while the file layer is hot-read. SHOW itself never writes, refreshes,
- adds an `init.json` field, or creates a Notification settings file.
+ Use only the authorized environment or closed System-v2 owner procedure. The file layer is hot-read; it does not require a refresh just for this value. Environment/launcher changes need the appropriate authorized refresh/relaunch. SHOW again to verify.
- ## Routing table
+ ## Notification settings and manual
- | Need / keywords | Read |
- |---|---|
- | First read; channel names; `.notification/*.json`; envelopes; `check`; delivery; allowlist; hooks; delay; block cap; settings sources | `reference/channel-model/SKILL.md` |
- | Which dismiss action; producer-specific handling; stale mirror; `force`; protected `goal`; post-molt reason; legacy `large_tool_result` | `reference/dismissal-safety/SKILL.md` |
- | Tool-result ranking, digest quality, `context(action='summarize')`, recovery by `tool_call_id` | `../context-manual/reference/summarize-manual/SKILL.md` |
- | Active goal cancellation/completion; runtime/kernel update nudges | `../system-manual/reference/goal-manual/SKILL.md` and `../system-manual/reference/runtime-update-checks/SKILL.md` |
+ `settings` and `manual` take strict empty `input={}` and are read-only. SHOW returns two rows in order: `notification.max_chars`, `notification.delay_max_seconds`; each has only `key`, `current`, `default`, `configurable`, `comment`. Comments target the two headings above. Unavailable current truth fails the whole inventory. SHOW grants no mutation authority and creates no settings file.
+
+ `manual` reads only initialized `<agent>/.library/intrinsic/capabilities/notification/SKILL.md`, returning `status`, `notification_manual`, `manual_path`. A missing file returns degraded status, empty body and actionable error, never source-tree fallback. It touches no notification, producer, delay or log state. Keep root `summarize=false` so guidance stays exact; compaction belongs to `context`, not Notification or System.