docs: consolidate design documentation and standardize crate English

This commit is contained in:
2026-10-12 14:58:00 +09:00
parent a633a53274
commit 4efb0ace1f
404 changed files with 4556 additions and 11654 deletions
+7 -19
View File
@@ -1,23 +1,11 @@
# memory
## Role
Defines shared Memory schemas, extraction candidates, evidence, and typed communication.
Does not own persistence or implicitly convert between legacy single-document Workspace Memory and per-subject Memory.
`memory` owns the shared types used by Workspace-backed Memory operations:
## Main entry points
- Memory API request/response DTOs
- extraction candidate and evidence schemas
- audit event schemas
- pure Memory document frontmatter schemas and parsing helpers
## Boundaries
The crate does **not** own persistence. Workspace Memory records, staging candidates, and audit observations are stored by the Workspace Server control plane and accessed by Workers through typed API operations.
The crate intentionally contains no repository-local layout, cwd/ancestor discovery, resident-file reader, staging writer, audit/usage log writer, generic filesystem scope helper, or local backend executor. The product CLI does not expose `yoi memory lint`.
Memory is useful context, not implementation authority. Tickets, Objectives, repository files, Git history, and append-only session records remain the exact evidence surfaces for implementation state.
## See also
- [`../../docs/design/memory-knowledge.md`](../../docs/design/memory-knowledge.md)
- [`../../docs/development/work-items.md`](../../docs/development/work-items.md)
- [`backend`]: legacy Workspace Memory operation contracts and resident responses
- [`extract`]: candidate extraction and progress pointers
- [`schema`]: shared document and evidence types
- [`audit`]: audit-event transport types
+3 -3
View File
@@ -1,7 +1,7 @@
//! Typed Memory audit events sent to the Workspace authority.
//! Transport types for Memory audit events.
//!
//! Runtime Workers construct these DTOs and submit them through the Memory
//! backend operation boundary. Repository-local audit logs are not an authority.
//! Runtime Workers pass these DTOs to backend operations. This crate does not store audit logs,
//! and DTOs alone do not guarantee persistence. Session storage owns Session records.
use chrono::{DateTime, Utc};
use schemars::JsonSchema;
+7 -4
View File
@@ -1,8 +1,11 @@
//! Typed transport boundary for Workspace-backed Memory operations.
//! Typed communication boundary for legacy single-document Workspace Memory.
//!
//! Runtime Workers serialize these DTOs to the Workspace API. Persistence and
//! validation are owned by the Workspace authority; this crate deliberately has
//! no repository-local filesystem executor.
//! Workspace authority owns persistence and validation of documents, candidates, and dispositions.
//! Does not reinterpret existing input as subject Memory, implicitly assign subjects, or dual-write.
//! This module has no storage or fallback implementation that searches Repositories or ancestor directories.
//! Resident response types are shared with subject Memory, but do not imply identical storage destinations.
//! [`MemoryResidentSummaryOutput`] represents availability separately from body presence.
//! `Ready` without content is a successfully generated empty result, distinct from ungenerated, stale, or failed.
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
+5 -6
View File
@@ -1,13 +1,12 @@
//! extract sub-Engine への入力テキスト組み立て。
//! Builds input text for the extract sub-Engine.
//!
//! `crates/worker/src/worker.rs::build_summary_prompt` と同じ方針で
//! Item 列を flat な行に落とす(reasoning は省く、tool call は名前のみ、
//! tool result は summary のみ)。conversation 全体を Markdown の単一
//! セクションとして渡し、抽出指示は system prompt 側に寄せる。
//! Flattens the supplied Items into lines (omitting reasoning, keeping only tool-call names
//! and tool-result summaries). Passes the conversation slice as a single Markdown
//! section, leaving extraction instructions to the system prompt.
use agen::Item;
/// 与えられた `items` を extract sub-Engine の最初の user 入力に整形する。
/// Formats `items` as the extract sub-Engine's initial user input.
pub fn build_extract_input(items: &[Item]) -> String {
let mut out = String::new();
out.push_str(
+6 -6
View File
@@ -1,8 +1,8 @@
//! Memory candidate extraction domain types and Worker tool boundary.
//! Boundary for Memory extraction candidates and Worker-facing operations.
//!
//! Worker-side extraction produces typed candidates that are submitted to the
//! Workspace backend. Staging persistence is owned by that backend; this module
//! does not write repository-local files.
//! Extraction creates typed candidates and passes them to Host storage. Saving candidates and
//! committing the extraction pointer are separate responsibilities; generating candidates alone does not update committed Memory.
//! This module does not store data in Repository files.
mod input;
mod payload;
@@ -17,6 +17,6 @@ pub use payload::{
pub use pointer::{ExtractPointerPayload, fold_pointer};
pub use tool::{ExtractWorkerContext, write_extracted_tool};
/// session-store `LogEntry::Extension` で使う domain 名。
/// pointer の永続化と読み出しはこの定数を使う側が一致している必要がある。
/// Domain name used in session-store `LogEntry::Extension`.
/// Callers persisting and reading pointers must agree on this constant.
pub const EXTRACT_DOMAIN: &str = "memory.extract";
+16 -15
View File
@@ -1,28 +1,29 @@
//! `LogEntry::Extension { domain: "memory.extract", payload }` の payload 形式と
//! restore 時の fold ヘルパー。memory crate がドメインを所有するので、
//! session-store / Worker は payload 構造を知らない。
//! Payload format for `LogEntry::Extension { domain: "memory.extract", payload }`
//! and fold helper for restore. The memory crate owns the domain, so
//! session-store / Worker do not know the payload structure.
use serde::{Deserialize, Serialize};
use super::EXTRACT_DOMAIN;
/// extract 完了境界の永続化 payload。session log の Extension entry
/// として 1 回ずつ書かれ、最新の 1 件が現行 pointer として有効になる。
/// Payload recording an extraction completion boundary as a Session Extension entry.
/// Only the latest entry is the current pointer; the Host lifecycle checks storage completion conditions.
/// This commits separately from candidate storage, so saved candidates may remain even without a committed pointer.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ExtractPointerPayload {
/// 直近 extract が処理した最後の session-store LogEntry の index。
/// 次回の `source.range.start` はこの値 + 1。
/// Index of the last session-store LogEntry processed by the latest extraction.
/// The next `source.range.start` is this value + 1.
pub processed_through_entry: usize,
/// 直近 extract 時点の `history.len()`。次回入力は
/// `history[processed_through_history_len..]` を切り出す。
/// `history.len()` at the latest extraction. The next input slices
/// `history[processed_through_history_len..]`.
pub processed_through_history_len: usize,
/// 書き出した staging file の UUIDv7 文字列。LLM が空 payload を返した
/// 場合は staging file を作らず空文字列で記録する(pointer は前進する)。
/// Staging record ID returned by storage. Completion without candidates may use an empty value.
/// Does not denote a local file's existence or storage path.
pub staging_id: String,
}
/// `RestoredState.extensions` から最新の extract pointer を取り出す。
/// 未抽出セッションでは `None`。
/// Returns the latest extraction pointer, or `None` if absent or the latest payload is invalid.
/// No fallback: ignoring a corrupt latest entry and using an older pointer would yield the wrong re-extraction range.
pub fn fold_pointer(extensions: &[(String, serde_json::Value)]) -> Option<ExtractPointerPayload> {
extensions
.iter()
@@ -74,8 +75,8 @@ mod tests {
EXTRACT_DOMAIN.to_string(),
serde_json::json!({ "wrong_shape": true }),
)];
// 現状は最新を取り出して JSON 不一致なら None。古いものに fallback
// しないのは、壊れた最新を黙って無視すると意図しない再抽出を招くため。
// Takes the latest entry and returns None if its JSON does not match.
// No fallback: silently ignoring a corrupt latest entry could cause unintended re-extraction.
assert!(fold_pointer(&exts).is_none());
}
}
+10 -11
View File
@@ -1,9 +1,8 @@
//! `write_extracted` ツール実装と sub-Engine 用 context。
//! Temporary storage receiving `write_extracted` results for the legacy extraction engine.
//!
//! sub-Engine からは extract worker が出した [`ExtractedPayload`] を
//! 受け取って `Mutex` 越しに [`ExtractWorkerContext`] に置くだけ。
//! Worker 側はランループ完了後に `take_payload()` で取り出して
//! [`super::staging::write_staging`] に渡す。
//! Validates [`ExtractedPayload`] and holds it in [`ExtractWorkerContext`]'s Mutex.
//! Callers retrieve the result with [`ExtractWorkerContext::take_payload`].
//! This module neither persists candidates nor decides whether to adopt them.
use std::sync::{Arc, Mutex};
@@ -17,12 +16,12 @@ Pass an object with a `candidates` array. Each candidate must have `kind`, `clai
`staleness` and `evidence_ids` are optional. Call this exactly once and end the turn. Do not include \
record ids, source anchors, session metadata, or free-form prose — the wrapper attaches staging metadata mechanically.";
/// extract sub-Engine の出力受け口。`ExtractedPayload` 1 件をホストする。
/// Output receiver for the extract sub-Engine. Holds one `ExtractedPayload`.
#[derive(Debug, Default)]
pub struct ExtractWorkerContext {
payload: Mutex<Option<ExtractedPayload>>,
/// `write_extracted` が複数回呼ばれた回数(debug 用)。
/// 後勝ちで上書きするが、Worker 側で warn を出したい場合に参照する。
/// Count of `write_extracted` calls (for debugging).
/// Later calls overwrite earlier payloads; Workers can use this to emit a warning.
call_count: Mutex<usize>,
}
@@ -31,8 +30,8 @@ impl ExtractWorkerContext {
Self::default()
}
/// sub-Engine 終了後に Worker が呼んで payload を取り出す。
/// 一度も `write_extracted` が呼ばれなければ `None`。
/// Called by the Worker after the sub-Engine exits to retrieve the payload.
/// Returns `None` if `write_extracted` was never called.
pub fn take_payload(&self) -> Option<ExtractedPayload> {
self.payload
.lock()
@@ -90,7 +89,7 @@ impl Tool for WriteExtractedTool {
}
}
/// sub-Engine に register する `write_extracted` ツール定義を返す。
/// Returns the `write_extracted` tool definition to register with the sub-Engine.
pub fn write_extracted_tool(ctx: Arc<ExtractWorkerContext>) -> ToolDefinition {
Arc::new(move || {
let schema = schemars::schema_for!(ExtractedPayload);
+1 -5
View File
@@ -1,8 +1,4 @@
//! Shared Memory domain and Workspace API transport types.
//!
//! Normal Memory persistence is owned by the Workspace control plane. This crate
//! intentionally contains no repository-local `.yoi` layout, discovery, reader,
//! writer, or fallback implementation.
#![doc = include_str!("../README.md")]
pub mod audit;
pub mod backend;