Skip to main content

GenerationState

Struct GenerationState 

Source
pub struct GenerationState {
    pub last_commit_hash: Option<String>,
    pub file_fingerprints: HashMap<String, String>,
    pub generated_at: String,
    pub doc_fingerprints: HashMap<String, String>,
    pub doc_modules: HashMap<String, String>,
    pub protected_docs: Vec<String>,
    pub tool_version: Option<String>,
    pub failed_modules: Vec<String>,
}
Expand description

生成状态

记录上一次生成时的 commit hash 和文件指纹, 用于增量更新时检测变更。

Fields§

§last_commit_hash: Option<String>

上一次生成时的 commit hash

§file_fingerprints: HashMap<String, String>

文件路径 → SHA256 指纹

§generated_at: String

生成时间(ISO 8601)

§doc_fingerprints: HashMap<String, String>

已生成文档路径 → SHA256 指纹(用于检测人工修改)

§doc_modules: HashMap<String, String>

已生成文档路径 → 所属模块名(人工修改反向同步的精确归属依据; 全局文档 api/overview/toc 无模块归属,不记录。模块名压平为 “::” 连接(module_path.join(“::”)),与卡片 module_name 同规则, 精确匹配,杜绝 stem 匹配的下划线歧义)

§protected_docs: Vec<String>

人工修改过的文档路径集合(保护集:下次自动更新不覆盖,直到 –force 清空)

§tool_version: Option<String>

生成时工具版本(v19 t01 版本自检依据)

from_insights 写入 env!(“CARGO_PKG_VERSION”);doctor 读取并对比 当前二进制版本,捕获「PATH 里的旧版二进制生成产物后又被新版 调用」的静默漂移(旧版缺 doctor/dry-run,实测报 unrecognized subcommand exit 2,用户无从知道产物是旧格式)。旧状态文件无此 字段(serde default None)→ doctor 提示无法判断,不误报。

§failed_modules: Vec<String>

上次生成失败被隔离的模块名(卡片或页面生成失败,v22 修复)

失败隔离(generate_wiki_pages/generate_all_cards 的 record_failure) 只跳过失败模块、不中断整体生成——但失败模块若源码不再变更将永远 无法补生成(增量以 git diff 触发,失败模块不在 diff 中)。 本轮生成结束时把失败模块写入状态,下次 update 时并入变更集重试; no-op 快速判定(should_skip_noop)也因非空跳过。清空时机: 成功重试(该模块生成成功)或全量生成(自然覆盖)。

Implementations§

Source§

impl GenerationState

Source

pub fn load(state_dir: &Path) -> Result<Self>

从状态目录加载生成状态

Source

pub fn save(&self, state_dir: &Path) -> Result<()>

保存生成状态到目录(原子写:fs::write_file_atomic 临时文件 + rename 覆盖,防止崩溃留下半截 JSON——半截状态会被 load 判为 损坏,进而触发调用方的 fail-loud 路径,见 lib.rs load_protection)

确定性序列化:file_fingerprints/doc_fingerprints/doc_modules 是 HashMap,迭代序随 RandomState 每次进程而异——直序列化会让状态 文件字节级漂移(同样的内容两次写入字节不同,git diff 噪音且 破坏“同输入同输出“的确定性契约)。写入前把三个 map 按键排序 组装成 serde_json::Map,保证同状态同字节;load 反序列化对 JSON 对象键序不敏感,旧文件完全兼容。

Source

pub fn preserve_protection(&mut self, old: &GenerationState)

生成前中途存盘的保护字段保留(票 03)

from_insights 构造的新状态只含 file_fingerprints/commit hash—— 若在 LLM 生成(流水线 Phase 3,最常见失败点)之前直接落盘, doc_fingerprints/protected_docs/doc_modules 全空;一旦生成失败, 磁盘状态即“无保护“版本,下次运行的人工修改保护失效。 本方法把旧状态中的保护字段合并进新状态,使中途存盘只推进 代码侧状态(commit hash/文件指纹),产物侧保护信息不因中途 失败而丢失。新状态保护字段非空时保留新值(正常全量完成后 Phase 6 的最终保存不受影响)。

Source

pub fn from_insights( root: &ProjectRoot, insights: &[FileInsight], commit_hash: &str, ) -> Result<Self>

从文件解析结果和 commit hash 构建新的生成状态

root 注入:insight.path 是相对项目根的路径,指纹计算必须先与 root 拼接——直接相对 cwd 打开会随进程 cwd 漂移而错读(watch 常驻进程的 cwd 漂移不再影响指纹基准)。

Source

pub fn compute_file_fingerprint(path: &Path) -> Result<String>

计算文件的 SHA256 指纹

非 UTF-8 文件返回错误。

Source

pub fn record_doc_fingerprints( docs: &[WikiDocument], cards: &[KnowledgeCard], output_dir: &Path, languages: &[String], ) -> Result<(HashMap<String, String>, HashMap<String, String>)>

记录所有已生成文档的 SHA256 指纹

路径与 render_all 实际写盘路径一致:{output_dir}/wiki/{lang}/{file}.md, 文件名复用 output::wiki_page_path(ArchitectureOverview 特判写 architecture.md),languages 为主语言 + 扩展语言(与 output::wiki_languages 保持一致)。 另补记三个全局文档(api.md / overview.md / toc.md)的指纹, 路径复用 output::api_doc_path / overview_doc_path / toc_doc_path, 与 render_all 的保护判定路径同一规则产出。 卡片同样计入指纹(路径 cards/{lang}/{module.replace(“::”,“”)}.md,与 render_all 写盘路径一致),使人工编辑的卡片与 wiki 页一样被 detect_manually_modified 识别并纳入保护集,全量 generate 不再静默覆盖。

返回值:(文档指纹表, 文档模块归属表)。模块归属 = 产物路径 → 模块名 (wiki 页取 module_path.join(“::”),卡片取 module_name;api/overview/toc 全局文档无模块归属不记录),供人工修改反向同步的精确归属—— 精确匹配杜绝了 stem 匹配在模块名含下划线时的串卡片歧义。

Source

pub fn detect_manually_modified(&self) -> Vec<String>

比对磁盘文档与生成时指纹,返回人工修改的文档路径集合

磁盘文件不存在时不视为人工修改(跳过保护);指纹读取失败时 保守计入修改集(保护优先)——宁可多保护一次也不让人工编辑 内容在下次生成中被静默覆盖(读取失败通常伴随权限/IO 异常, 此时无法确认磁盘内容是否仍是上次生成的原样)。

Source

pub fn is_file_changed(&self, root: &ProjectRoot, path: &Path) -> Result<bool>

检查文件是否已变更

如果文件不在指纹表中(新增文件)或指纹不匹配,返回 true。 root 注入:path 是相对项目根的路径,与 root 拼接后计算 (同 from_insights,不依赖进程 cwd)。

Trait Implementations§

Source§

impl Clone for GenerationState

Source§

fn clone(&self) -> GenerationState

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for GenerationState

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for GenerationState

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for GenerationState

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more