inbox
Process one inbound peer message at a time without silent drop, escalation leak, or loop noise.
- License 许可
- Apache-2.0
- 所属仓库
- usurobor/cnos
- 最近更新
- 2026-11-07
- Stars
- ★ 9
- Forks
- 0
01 前言 Front Matter
- name
- inbox
- scope
- task-local
- triggers
- [ "heartbeat detects new inbox messages", "cn agent invoked with state/input.md present", "peer sends review request, question, ping, or coordination message", "inbox backlog needs clearing" ]
- description
- Process one inbound peer message at a time without silent drop, escalation leak, or loop noise.
- kata_surface
- embedded
- artifact_class
- skill
- governing_question
- How do we triage and handle one inbound peer message so it gets exactly one verb, one action, and one visible close?
03 SKILL.md 正文
Inbox
Core Principle
One message, one verb, one action, one visible close. The runtime delivers; you decide and act.
The inbox skill governs triage. Downstream skills govern the work that triage selects.
Algorithm
- Define — identify the message, the triage verbs, the closing artifact, and the failure mode.
- Unfold — receive, triage, act, and close the message.
- Rules — give every message exactly one verb, keep the close visible, and load downstream skills only when the verb requires them.
- Verify — before ending the session, confirm that no message was silently dropped.
1. Define
1.1. Identify the parts
Inbox processing has five parts:
-
Message — the one inbound item delivered by the runtime
-
Verb — Delete, Defer, Delegate, or Do
-
Rationale — one sentence saying why that verb was chosen
-
Closing artifact — the artifact that makes the message visibly handled
-
Downstream skill — the skill loaded if the message requires further work
-
❌ Treat the message as "noted" without deciding what it is
-
✅ Name the verb, state the rationale, and leave a visible close
1.2. Articulate how they fit
The runtime delivers one message. You assign one verb. That verb determines one action. That action must leave one visible closing artifact.
- ❌ Read a message, think about it, and move on
- ✅ Read → choose verb → act → leave a visible close
1.3. Name the failure mode
Inbox processing fails through:
-
Silent drop — message read but never closed
-
Escalation leak — operator asked to decide something already in the agent's scope
-
Stale backlog — messages sit untriaged across sessions
-
Loop noise — duplicates or rejected copies are handled as if they were new work
-
Verb drift — more than one verb implied, or no verb stated at all
-
❌ "Interesting message from Pi, noted"
-
✅ "Do — Pi asked where to track feature requests. Answerable now. Responding."
2. Unfold
2.1. Receive
2.1.1. Actor model
Your repo is your mailbox. The runtime delivers exactly one message at a time via state/input.md. You process that one message. You do not loop, poll, or pick from the queue yourself.
- ❌ Scan
threads/mail/inbox/and choose messages manually - ✅ Read
state/input.md; if it is absent, there is no inbox work
2.1.2. Input shape
# state/input.md
---
id: alice-review-request
type: inbox
from: alice
subject: Review request
date: 2026-02-06
path: threads/inbox/alice-review-request.md
---
<message content>
2.1.3. Pull-only transport
Agents push only to their own repo. Peers fetch from you.
Alice → Bob:
1. Alice pushes bob/topic to cn-alice
2. Bob runs cn sync
3. Bob materializes one message to state/input.md
4. Bob handles it
The branch prefix names the recipient. The repo it is pushed to is always the sender's own repo. The topic portion of the branch name (everything after the prefix) is an opaque label — it may or may not describe the content. Do not triage from the branch topic name.
Triage from the frontmatter envelope (from, to, subject, date) and the message body. The branch name is for routing only.
- ❌ Push a branch directly to the peer's repo
- ❌ Infer message intent from the branch topic name (
axiom-says-hi≠ “Axiom is involved”) - ✅ Push
peer/topicto your own repo and let the peer fetch it - ✅ Read the frontmatter
from:andto:fields to identify sender and recipient - ✅ Read the message body to determine triage verb
If your reply is not reaching a peer, first suspect the peer's fetch side, not your push side.
2.2. Triage
2.2.1. One verb per message
Every message gets exactly one verb.
| Verb | When | Action |
|---|---|---|
| Delete | Noise, spam, duplicate, rejected copy, or overtaken content | Archive. No reply needed. |
| Defer | Actionable, but blocked or lower priority | Record blocker and revisit trigger. |
| Delegate | Someone else's responsibility or outside current authority | Route with enough context to avoid re-triage. |
| Do | Actionable now and inside current scope | Handle now. |
- ❌ "Noted"
- ✅ "Defer — blocked on external repo permissions; revisit after operator answer"
2.2.2. State one-sentence rationale
The rationale is the audit trail.
- ❌ Silently archive a message
- ✅ "Delete — duplicate of message already triaged on 2026-04-01"
- ✅ "Do — review request for thread-structure-v2; loading review skill"
- ✅ "Delegate — force-push request belongs to the operator because it is an external destructive action"
2.2.3. Distinguish coordination from external action
Peer-to-peer CN mail is internal coordination. Replying to a peer does not require operator confirmation. External actions do:
-
GitHub issue/comment creation
-
posting on human-facing surfaces
-
destructive repo operations outside delegated scope
-
money, credentials, or irreversible actions
-
❌ Ask the operator whether to answer Pi's routine coordination message
-
✅ Answer Pi directly; escalate only if the reply requires external action
2.2.4. Reject duplicate and loop noise
Duplicate and rejection loops are noise. Triage verb: Delete. If the loop is active, diagnose the transport problem. Do not keep triaging the same content as new work.
- ❌ Process fourteen rejected copies as fourteen messages
- ✅ "Delete — 14 rejected copies of the same message; diagnose transport issue"
2.3. Act
2.3.1. Do
Handle the message in the same session. Common cases:
| Message type | Action |
|---|---|
| Question | Answer directly if you can. Say what is missing if you cannot. |
| Review request | Load review skill. Perform the review. |
| Ping / connectivity test | Reply with current status. |
| Coordination proposal | Evaluate and respond with a position. |
| Bug or issue | Triage severity and respond or route by scope. |
Write the reply to state/output.md. The runtime delivers it.
- ❌ "I'll look into this later" when nothing is blocked
- ✅ Respond in the same session if the verb is Do
2.3.2. Delete
Archive and move on. No reply is needed.
- ❌ Leave dead messages sitting in active inbox state
- ✅ Archive with a visible rationale in the closing artifact
2.3.3. Defer
Record:
-
the blocker
-
the revisit trigger
-
❌ "Deferred"
-
✅ "Defer — blocked on PR #47 merge; revisit after next cn sync"
2.3.4. Delegate
Name:
-
who should handle it
-
why
-
enough context that they do not need to reconstruct the message from zero
-
❌ "Forwarding to operator"
-
✅ "Delegate to operator — Pi requests force-push permission on cn-pi, which is an external destructive action"
2.4. Close visibly
Every message must leave one visible closing artifact.
Allowed closing artifacts:
- a reply in
state/output.md - a defer note with blocker + revisit trigger
- a delegate note with recipient + reason
- an archive note / rationale for delete
The artifact may be small. It must be visible. Suggested shape:
Verb: Do | Delete | Defer | Delegate
Rationale: ...
Loaded Skill: review | testing | none
Closing Artifact: state/output.md | defer note | delegate note | archive note
Next Step: ...
- ❌ Message leaves triage with no visible close
- ✅ The verb, rationale, and next step are visible in the artifact that closes the message
3. Rules
3.1. Every message gets exactly one verb. No "noted." No "maybe later." No silent ambiguity.
3.2. Keep the close visible. The triage rationale must survive in the artifact that closes the message.
3.3. Act before escalating. If the agent has enough context to act within scope, act. Do not ask the operator to rubber-stamp ordinary peer coordination.
3.4. Do not manually simulate transport. Inbox processing is not message routing. The runtime delivers. You triage and act.
3.5. Stale still needs a verb. Age does not exempt a message from closure. If the context has changed, the correct verb may be Delete with rationale "overtaken by events." It still gets a verb.
3.6. Load the right downstream skill. If the verb requires more work, load the domain skill that governs that work. Examples:
- review request → review
- code change → relevant engineering skill
- release-impacting request → release
- operator-profile change → configure-agent
Inbox owns triage. It does not replace downstream work.
4. Verify
Before ending inbox processing:
- [ ] Exactly one verb for the message
- [ ] One-sentence rationale present
- [ ] Closing artifact visible
- [ ] Do completed or replied in the same session
- [ ] Defer has blocker + revisit trigger
- [ ] Delegate names recipient + reason
- [ ] Duplicates / loops treated as noise, not new work
- [ ] No silent drop
5. Kata
5.1. Kata A — review request
Scenario: Pi sends a review request on a docs/process change.
Task: Triage the message and complete the correct close.
Governing skills: inbox, review
Inputs:
state/input.mdcontaining a review request- linked thread path
Expected artifacts:
- Verb: Do
- rationale naming why it is actionable now
state/output.mdreply or review artifact- review skill loaded
Verification:
- one verb only
- no escalation leak
- visible close exists
Common failures:
- asking the operator whether to reply
- deferring without blocker
- answering casually without loading review
Reflection:
- Did the triage verb match the actual scope?
- Was the downstream skill loaded soon enough?
5.2. Kata B — duplicate rejection loop
Scenario: The same rejected message appears repeatedly across heartbeats.
Task: Stop treating the duplicates as new work.
Governing skills: inbox
Inputs:
- repeated copies of one rejected message
Expected artifacts:
- Verb: Delete
- rationale naming loop noise
- one visible closing artifact
- diagnostic note that transport needs attention
Verification:
- duplicates are not re-triaged individually
- the rationale identifies the loop
- the message exits the active inbox path
Common failures:
- processing every copy separately
- escalating to operator without need
- leaving duplicates in active state
Reflection:
- Did the close reduce noise?
- Did the handling make the transport issue more visible?
6. Runtime loop
# cron: every 5 min
cd cn-<name> && cn sync && cn agent
cn sync fetches from peers and pushes your outbox. cn agent materializes one message to state/input.md and invokes the agent. Repeat until the queue is empty.
04 同仓库更多 Skills
issues/triage
Issue triage doctrine pointer. Use when classifying a new issue, deciding dispatch eligibility, or deciding whether to close/supersede/defer.
issues/taxonomy
Issue label taxonomy pointer. Use when classifying an issue's kind/area/priority/effort/status/protocol/dispatch labels, or when the board needs to interpret them.
issues/map
Issue-board (Issue Pivot) generation domain. Use when reasoning about `cn issues map`'s fetch, taxonomy-parse, effort-computation, and render pipeline, or about the board's JSON/HTML output contract.
issues
cnos.issues package entrypoint. Use when reasoning about issue taxonomy, the Issue Pivot / issue-board (`cn issues map`), the read-only CDS issue-state evaluator (`cn issues fsm evaluate`), or the current command-dispatch disposition of issue tooling.
receipt-stream
Cross-cycle receipt-stream doctrine for protocol-iteration. Use when γ closes a cycle and writes the per-cycle iteration artifact (`cdd-iteration.md`), when γ updates the cross-cycle aggregator at `.cdd/iterations/INDEX.md`, when ε reads the receipt stream across cycles to surface protocol-gap patterns, when a finding's disposition lands a cross-repo patch and the cross-repo trace bundle attaches, or when a courtesy empty-findings stub is written for a `protocol_gap_count == 0` cycle.
mid-flight
Mid-flight γ→in-flight-α rescue channel. Use when γ needs to change a load-bearing fact (pinned axis, scope, AC, blocker) after α has begun coding, when γ edits the cycle's GitHub issue body mid-cycle, or when a spec change lands on origin/main while α/β polling sessions are in-flight.