refactor: rename pod crate to worker
This commit is contained in:
@@ -31,7 +31,7 @@ pub fn build_consolidate_input(
|
||||
"consolidation input. Run the integration step first \
|
||||
(fold the staging activity logs into memory and knowledge), then the \
|
||||
tidy step (clean up existing records). Use the memory tools for \
|
||||
every write — direct file writes are denied by the pod scope.\n\n",
|
||||
every write — direct file writes are denied by the worker scope.\n\n",
|
||||
);
|
||||
|
||||
out.push_str("## Staging entries (consumed by this run)\n\n");
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//!
|
||||
//! `docs/plan/memory.md` §並走防止 に従い:
|
||||
//!
|
||||
//! - ファイルが存在し、記録された Pod が動作している間、その Pod が排他占有
|
||||
//! - ファイルが存在し、記録された Worker が動作している間、その Worker が排他占有
|
||||
//! - クラッシュで残った stale lock は、所有者 PID が死んでいれば次回 spawn
|
||||
//! 時に上書き取得できる
|
||||
//! - cleanup は consumed ID の staging エントリのみ削除し、実行中に extract
|
||||
@@ -22,12 +22,12 @@ use crate::workspace::WorkspaceLayout;
|
||||
|
||||
const LOCK_FILE: &str = ".consolidation.lock";
|
||||
|
||||
/// 占有ファイルの中身。`pid` で stale 判定し、`pod_name` / `started_at` /
|
||||
/// 占有ファイルの中身。`pid` で stale 判定し、`worker_name` / `started_at` /
|
||||
/// `consumed_ids` は診断とクラッシュ復旧時の参照に使う。
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct LockRecord {
|
||||
pub pid: u32,
|
||||
pub pod_name: String,
|
||||
pub worker_name: String,
|
||||
pub started_at: DateTime<Utc>,
|
||||
/// この consolidation run が起動時スナップショットで確定した consumed staging
|
||||
/// entry の UUIDv7 列。完了時はこの列のみ削除し、追加分は残す。
|
||||
@@ -38,8 +38,8 @@ pub struct LockRecord {
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum LockError {
|
||||
/// 占有ファイルが既にあり、所有者 PID が生きているのでスキップ。
|
||||
#[error("consolidation lock held by live pid {pid} (pod {pod_name:?})")]
|
||||
InUse { pid: u32, pod_name: String },
|
||||
#[error("consolidation lock held by live pid {pid} (worker {worker_name:?})")]
|
||||
InUse { pid: u32, worker_name: String },
|
||||
#[error("io error at {}: {source}", .path.display())]
|
||||
Io {
|
||||
path: PathBuf,
|
||||
@@ -85,7 +85,7 @@ impl StagingLock {
|
||||
pub fn acquire(
|
||||
layout: &WorkspaceLayout,
|
||||
pid: u32,
|
||||
pod_name: impl Into<String>,
|
||||
worker_name: impl Into<String>,
|
||||
consumed_ids: Vec<Uuid>,
|
||||
) -> Result<Self, LockError> {
|
||||
let staging_dir = layout.staging_dir();
|
||||
@@ -99,12 +99,12 @@ impl StagingLock {
|
||||
if pid_is_alive(existing.pid) {
|
||||
return Err(LockError::InUse {
|
||||
pid: existing.pid,
|
||||
pod_name: existing.pod_name,
|
||||
worker_name: existing.worker_name,
|
||||
});
|
||||
}
|
||||
tracing::warn!(
|
||||
stale_pid = existing.pid,
|
||||
stale_pod = %existing.pod_name,
|
||||
stale_pod = %existing.worker_name,
|
||||
"consolidation stale lock detected, taking over"
|
||||
);
|
||||
} else {
|
||||
@@ -114,7 +114,7 @@ impl StagingLock {
|
||||
|
||||
let record = LockRecord {
|
||||
pid,
|
||||
pod_name: pod_name.into(),
|
||||
worker_name: worker_name.into(),
|
||||
started_at: Utc::now(),
|
||||
consumed_ids,
|
||||
};
|
||||
@@ -213,11 +213,11 @@ mod tests {
|
||||
#[test]
|
||||
fn acquire_writes_lock_file() {
|
||||
let (_dir, layout) = make_layout();
|
||||
let lock = StagingLock::acquire(&layout, std::process::id(), "pod", Vec::new()).unwrap();
|
||||
let lock = StagingLock::acquire(&layout, std::process::id(), "worker", Vec::new()).unwrap();
|
||||
let path = layout.staging_dir().join(LOCK_FILE);
|
||||
assert!(path.exists());
|
||||
assert_eq!(lock.record().pid, std::process::id());
|
||||
assert_eq!(lock.record().pod_name, "pod");
|
||||
assert_eq!(lock.record().worker_name, "worker");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -225,8 +225,8 @@ mod tests {
|
||||
let (_dir, layout) = make_layout();
|
||||
// Use this test process's pid — it's definitely alive.
|
||||
let _first =
|
||||
StagingLock::acquire(&layout, std::process::id(), "pod-a", Vec::new()).unwrap();
|
||||
let err = StagingLock::acquire(&layout, std::process::id(), "pod-b", Vec::new())
|
||||
StagingLock::acquire(&layout, std::process::id(), "worker-a", Vec::new()).unwrap();
|
||||
let err = StagingLock::acquire(&layout, std::process::id(), "worker-b", Vec::new())
|
||||
.expect_err("expected InUse");
|
||||
assert!(matches!(err, LockError::InUse { .. }));
|
||||
}
|
||||
@@ -239,7 +239,7 @@ mod tests {
|
||||
// dead on every platform we target.
|
||||
let stale = LockRecord {
|
||||
pid: u32::MAX,
|
||||
pod_name: "ghost".into(),
|
||||
worker_name: "ghost".into(),
|
||||
started_at: Utc::now(),
|
||||
consumed_ids: Vec::new(),
|
||||
};
|
||||
@@ -249,7 +249,7 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let lock = StagingLock::acquire(&layout, std::process::id(), "pod", Vec::new())
|
||||
let lock = StagingLock::acquire(&layout, std::process::id(), "worker", Vec::new())
|
||||
.expect("stale lock must be overwritable");
|
||||
assert_eq!(lock.record().pid, std::process::id());
|
||||
}
|
||||
@@ -276,7 +276,7 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let lock = StagingLock::acquire(&layout, std::process::id(), "pod", vec![id_a]).unwrap();
|
||||
let lock = StagingLock::acquire(&layout, std::process::id(), "worker", vec![id_a]).unwrap();
|
||||
let lock_path = lock.path().to_path_buf();
|
||||
lock.release_with_cleanup(&layout);
|
||||
|
||||
@@ -295,7 +295,8 @@ mod tests {
|
||||
fn release_is_resilient_to_missing_consumed_entries() {
|
||||
let (_dir, layout) = make_layout();
|
||||
let phantom = uuid::Uuid::now_v7();
|
||||
let lock = StagingLock::acquire(&layout, std::process::id(), "pod", vec![phantom]).unwrap();
|
||||
let lock =
|
||||
StagingLock::acquire(&layout, std::process::id(), "worker", vec![phantom]).unwrap();
|
||||
let lock_path = lock.path().to_path_buf();
|
||||
// No file at <staging>/<phantom>.json — release must not panic.
|
||||
lock.release_with_cleanup(&layout);
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
//!
|
||||
//! extract が staging に残した活動ログを `memory/*` / `knowledge/*` に
|
||||
//! 統合し、続けて既存 record を `outdated | superseded | unused | noisy`
|
||||
//! の観点で整理する disposable Engine を、Pod 側が組み立てるための
|
||||
//! ヘルパー群を提供する。Pod は次の手順で sub-Engine を構築する:
|
||||
//! の観点で整理する disposable Engine を、Worker 側が組み立てるための
|
||||
//! ヘルパー群を提供する。Worker は次の手順で sub-Engine を構築する:
|
||||
//!
|
||||
//! - [`build_consolidate_input`] を sub-Engine の最初の user 入力に
|
||||
//! - memory 専用 Tool (read / write / edit) と Knowledge / memory 検索ツールを登録
|
||||
@@ -11,8 +11,8 @@
|
||||
//! - sub-Engine run 完了後、[`StagingLock::release_with_cleanup`] で
|
||||
//! consumed ID 分の staging のみ削除し、占有ファイルを解放
|
||||
//!
|
||||
//! system prompt は Pod の `PromptCatalog`
|
||||
//! (`PodPrompt::MemoryConsolidationSystem`) で管理される。Usage report は
|
||||
//! system prompt は Worker の `PromptCatalog`
|
||||
//! (`WorkerPrompt::MemoryConsolidationSystem`) で管理される。Usage report は
|
||||
//! 判断材料として渡すだけで、ここでは Knowledge 化や protection の hard decision はしない
|
||||
//! (`docs/plan/memory.md` §Consolidation / 整理材料)。
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! extract sub-Engine への入力テキスト組み立て。
|
||||
//!
|
||||
//! `crates/pod/src/pod.rs::build_summary_prompt` と同じ方針で
|
||||
//! `crates/worker/src/worker.rs::build_summary_prompt` と同じ方針で
|
||||
//! Item 列を flat な行に落とす(reasoning は省く、tool call は名前のみ、
|
||||
//! tool result は summary のみ)。conversation 全体を Markdown の単一
|
||||
//! セクションとして渡し、抽出指示は system prompt 側に寄せる。
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
//! extract: 活動抽出。
|
||||
//!
|
||||
//! 通常 Pod の post-run hook で発火する disposable Engine と、その
|
||||
//! 通常 Worker の post-run hook で発火する disposable Engine と、その
|
||||
//! 出力を `<workspace>/.yoi/memory/_staging/<id>.json` に書き出す
|
||||
//! ヘルパーを提供する。Pod 側はこのモジュールから:
|
||||
//! ヘルパーを提供する。Worker 側はこのモジュールから:
|
||||
//!
|
||||
//! - [`build_extract_input`] を sub-Engine の最初の user 入力に
|
||||
//! - [`write_extracted_tool`] を唯一のツールとして
|
||||
//! - [`write_staging`] で受け取った JSON を staging に書き出し
|
||||
//!
|
||||
//! の順で組み立てる。system prompt は Pod の `PromptCatalog`
|
||||
//! (`PodPrompt::MemoryExtractSystem`) で管理される。pointer 永続化
|
||||
//! の順で組み立てる。system prompt は Worker の `PromptCatalog`
|
||||
//! (`WorkerPrompt::MemoryExtractSystem`) で管理される。pointer 永続化
|
||||
//! (session-store の `LogEntry::Extension`、domain `"memory.extract"`)は
|
||||
//! Pod 側が責務を持つ。
|
||||
//! Worker 側が責務を持つ。
|
||||
//!
|
||||
//! 出力 JSON の wrap は [`write_staging`] が `source: { segment_id, range }`
|
||||
//! を機械付与する形で担当し、LLM には source を推論させない。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! extract 抽出の出力 schema。
|
||||
//!
|
||||
//! LLM は [`ExtractedPayload`] そのもの(source 抜き)を返し、Pod 側
|
||||
//! LLM は [`ExtractedPayload`] そのもの(source 抜き)を返し、Worker 側
|
||||
//! ラッパーが [`StagingRecord`] に組み立てて staging へ書き出す。
|
||||
//! source は機械付与する契約 (`docs/plan/memory.md` §Extract)。
|
||||
|
||||
@@ -78,7 +78,7 @@ pub struct RequestEntry {
|
||||
|
||||
/// staging に書き出される 1 ファイル分のレコード。
|
||||
///
|
||||
/// `source` は Pod 側ラッパーが segment_id と log entry range を
|
||||
/// `source` は Worker 側ラッパーが segment_id と log entry range を
|
||||
/// 機械付与する。LLM はこのフィールドを見ない / 推論しない。
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct StagingRecord {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! `LogEntry::Extension { domain: "memory.extract", payload }` の payload 形式と
|
||||
//! restore 時の fold ヘルパー。memory crate がドメインを所有するので、
|
||||
//! session-store / Pod は payload 構造を知らない。
|
||||
//! session-store / Worker は payload 構造を知らない。
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//!
|
||||
//! sub-Engine からは extract worker が出した [`ExtractedPayload`] を
|
||||
//! 受け取って `Mutex` 越しに [`ExtractWorkerContext`] に置くだけ。
|
||||
//! Pod 側はランループ完了後に `take_payload()` で取り出して
|
||||
//! Worker 側はランループ完了後に `take_payload()` で取り出して
|
||||
//! [`super::staging::write_staging`] に渡す。
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
@@ -22,7 +22,7 @@ the wrapper attaches provenance mechanically.";
|
||||
pub struct ExtractWorkerContext {
|
||||
payload: Mutex<Option<ExtractedPayload>>,
|
||||
/// `write_extracted` が複数回呼ばれた回数(debug 用)。
|
||||
/// 後勝ちで上書きするが、Pod 側で warn を出したい場合に参照する。
|
||||
/// 後勝ちで上書きするが、Worker 側で warn を出したい場合に参照する。
|
||||
call_count: Mutex<usize>,
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ impl ExtractWorkerContext {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// sub-Engine 終了後に Pod が呼んで payload を取り出す。
|
||||
/// sub-Engine 終了後に Worker が呼んで payload を取り出す。
|
||||
/// 一度も `write_extracted` が呼ばれなければ `None`。
|
||||
pub fn take_payload(&self) -> Option<ExtractedPayload> {
|
||||
self.payload
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//! Self-contained: provides its own Tool implementations (read/write/edit)
|
||||
//! that target `<workspace>/memory/` and `<workspace>/knowledge/` only,
|
||||
//! with a pre-write Linter built in. Generic CRUD tools (in the `tools`
|
||||
//! crate) must not touch these directories — Pod is responsible for
|
||||
//! crate) must not touch these directories — Worker is responsible for
|
||||
//! denying them at the Scope level when memory is enabled.
|
||||
|
||||
pub mod audit;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Workspace memory resident-enumeration helpers.
|
||||
//!
|
||||
//! Surfaces used by the Pod system-prompt assembler:
|
||||
//! Surfaces used by the Worker system-prompt assembler:
|
||||
//!
|
||||
//! - [`collect_resident_knowledge`] — resident-injection candidates
|
||||
//! (`model_invokation: true`) returned as `(slug, description)` pairs.
|
||||
@@ -8,7 +8,7 @@
|
||||
//! `<workspace>/.yoi/memory/summary.md` when it parses as a summary
|
||||
//! record and has non-empty body.
|
||||
//! - [`list_knowledge_slugs`] — every slug whose file parses, regardless
|
||||
//! of `model_invokation`. Used by the Pod IPC layer to answer TUI `#`
|
||||
//! of `model_invokation`. Used by the Worker IPC layer to answer TUI `#`
|
||||
//! completion (`model_invokation` is a resident-injection flag, not a
|
||||
//! user-visibility flag).
|
||||
//!
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! Helpers for constructing `ScopeRule` entries that exclude the
|
||||
//! memory tree from the generic CRUD tools' write surface.
|
||||
//!
|
||||
//! Pod is expected to call [`deny_write_rules`] when memory is enabled
|
||||
//! Worker is expected to call [`deny_write_rules`] when memory is enabled
|
||||
//! and append the result to the manifest's `scope.deny` list before
|
||||
//! constructing the [`Scope`] passed to `tools::ScopedFs`. The memory
|
||||
//! tools themselves bypass `ScopedFs` and write directly under the
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//! `.yoi/workflow/`.
|
||||
//!
|
||||
//! `memory.workspace_root` pins this root explicitly. Without an explicit
|
||||
//! root, resolution searches upward from the Pod pwd for a `.yoi/memory`
|
||||
//! root, resolution searches upward from the Worker pwd for a `.yoi/memory`
|
||||
//! marker; `.yoi` project records alone are not a memory marker.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
Reference in New Issue
Block a user