@whispering233/ai-editor-tools 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analysis/conflict.d.ts +20 -0
- package/dist/analysis/conflict.d.ts.map +1 -0
- package/dist/analysis/conflict.js +116 -0
- package/dist/analysis/conflict.js.map +1 -0
- package/dist/analysis/consistency.d.ts +28 -0
- package/dist/analysis/consistency.d.ts.map +1 -0
- package/dist/analysis/consistency.js +108 -0
- package/dist/analysis/consistency.js.map +1 -0
- package/dist/analysis/hook.d.ts +157 -0
- package/dist/analysis/hook.d.ts.map +1 -0
- package/dist/analysis/hook.js +381 -0
- package/dist/analysis/hook.js.map +1 -0
- package/dist/analysis/orphan.d.ts +60 -0
- package/dist/analysis/orphan.d.ts.map +1 -0
- package/dist/analysis/orphan.js +153 -0
- package/dist/analysis/orphan.js.map +1 -0
- package/dist/analysis/path.d.ts +23 -0
- package/dist/analysis/path.d.ts.map +1 -0
- package/dist/analysis/path.js +114 -0
- package/dist/analysis/path.js.map +1 -0
- package/dist/analysis/suggest.d.ts +19 -0
- package/dist/analysis/suggest.d.ts.map +1 -0
- package/dist/analysis/suggest.js +92 -0
- package/dist/analysis/suggest.js.map +1 -0
- package/dist/analysis/utils.d.ts +54 -0
- package/dist/analysis/utils.d.ts.map +1 -0
- package/dist/analysis/utils.js +123 -0
- package/dist/analysis/utils.js.map +1 -0
- package/dist/context.d.ts +10 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +11 -0
- package/dist/context.js.map +1 -0
- package/dist/executor/delta.d.ts +4 -0
- package/dist/executor/delta.d.ts.map +1 -0
- package/dist/executor/delta.js +22 -0
- package/dist/executor/delta.js.map +1 -0
- package/dist/executor/entity.d.ts +8 -0
- package/dist/executor/entity.d.ts.map +1 -0
- package/dist/executor/entity.js +47 -0
- package/dist/executor/entity.js.map +1 -0
- package/dist/executor/hook.d.ts +8 -0
- package/dist/executor/hook.d.ts.map +1 -0
- package/dist/executor/hook.js +183 -0
- package/dist/executor/hook.js.map +1 -0
- package/dist/executor/index.d.ts +22 -0
- package/dist/executor/index.d.ts.map +1 -0
- package/dist/executor/index.js +89 -0
- package/dist/executor/index.js.map +1 -0
- package/dist/executor/outline.d.ts +8 -0
- package/dist/executor/outline.d.ts.map +1 -0
- package/dist/executor/outline.js +39 -0
- package/dist/executor/outline.js.map +1 -0
- package/dist/executor/relation.d.ts +6 -0
- package/dist/executor/relation.d.ts.map +1 -0
- package/dist/executor/relation.js +33 -0
- package/dist/executor/relation.js.map +1 -0
- package/dist/executor/types.d.ts +25 -0
- package/dist/executor/types.d.ts.map +1 -0
- package/dist/executor/types.js +54 -0
- package/dist/executor/types.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +359 -0
- package/dist/index.js.map +1 -0
- package/dist/proposal/delta.d.ts +8 -0
- package/dist/proposal/delta.d.ts.map +1 -0
- package/dist/proposal/delta.js +29 -0
- package/dist/proposal/delta.js.map +1 -0
- package/dist/proposal/entity.d.ts +16 -0
- package/dist/proposal/entity.d.ts.map +1 -0
- package/dist/proposal/entity.js +54 -0
- package/dist/proposal/entity.js.map +1 -0
- package/dist/proposal/hook.d.ts +24 -0
- package/dist/proposal/hook.d.ts.map +1 -0
- package/dist/proposal/hook.js +81 -0
- package/dist/proposal/hook.js.map +1 -0
- package/dist/proposal/outline.d.ts +24 -0
- package/dist/proposal/outline.d.ts.map +1 -0
- package/dist/proposal/outline.js +78 -0
- package/dist/proposal/outline.js.map +1 -0
- package/dist/proposal/relation.d.ts +12 -0
- package/dist/proposal/relation.d.ts.map +1 -0
- package/dist/proposal/relation.js +50 -0
- package/dist/proposal/relation.js.map +1 -0
- package/dist/proposal/types.d.ts +72 -0
- package/dist/proposal/types.d.ts.map +1 -0
- package/dist/proposal/types.js +105 -0
- package/dist/proposal/types.js.map +1 -0
- package/dist/query/delta.d.ts +20 -0
- package/dist/query/delta.d.ts.map +1 -0
- package/dist/query/delta.js +41 -0
- package/dist/query/delta.js.map +1 -0
- package/dist/query/entity.d.ts +29 -0
- package/dist/query/entity.d.ts.map +1 -0
- package/dist/query/entity.js +53 -0
- package/dist/query/entity.js.map +1 -0
- package/dist/query/outline.d.ts +20 -0
- package/dist/query/outline.d.ts.map +1 -0
- package/dist/query/outline.js +68 -0
- package/dist/query/outline.js.map +1 -0
- package/dist/query/relation.d.ts +12 -0
- package/dist/query/relation.d.ts.map +1 -0
- package/dist/query/relation.js +30 -0
- package/dist/query/relation.js.map +1 -0
- package/dist/registry.d.ts +41 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +46 -0
- package/dist/registry.js.map +1 -0
- package/package.json +35 -0
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
// 分析类工具:伏笔分析(S6.5,hooks.md「工具扩展」+ 决策 21)
|
|
2
|
+
// 5 个工具:analyze_hook_health / trace_hook_lifecycle / suggest_hook_payoff /
|
|
3
|
+
// find_hook_opportunities / detect_hook_conflicts
|
|
4
|
+
//
|
|
5
|
+
// **`_health` 健康指标(决策 21 口径,本文件核心)**:
|
|
6
|
+
// - 章节序:全局章序号(跨卷连续累计)先序遍历;scene 归入所属 chapter;**chapter 不落库**——
|
|
7
|
+
// plants/advances/resolves 不存章节元数据,由关系 source_id 经 ChapterIndex(查询时现推,
|
|
8
|
+
// 节点 move 后不陈旧)
|
|
9
|
+
// - 当前章节 = project.json 的 current_position(经共享 ChapterIndex,与 S6.4 孤儿工具同口径)
|
|
10
|
+
// - half_life:显式优先;缺省按 payoff_timing 映射(immediate=3/near_term=8/mid_arc=15/
|
|
11
|
+
// slow_burn=25/endgame=40);payoff_timing 缺失/非法 → slow_burn(长线保守默认)
|
|
12
|
+
// - ready_to_resolve:expected_resolve_node_id 设置时 = current >= 该节点章节序;
|
|
13
|
+
// 未设置/节点无章号 → 未计算(null),不猜测
|
|
14
|
+
// - blocked:本 hook 依赖(depends_on 的 target)尚未 resolved
|
|
15
|
+
// - **`_health` 不入库**:运行时计算,绝不写回 data(本模块不修改实体行)
|
|
16
|
+
//
|
|
17
|
+
// 数据访问:db 查询层(listEntities/listRelations/getEntity)+ 纯函数分析,**零原生 SQL**。
|
|
18
|
+
// 软删过滤:listEntities/listRelations/getEntity 默认过滤(决策 12)。
|
|
19
|
+
// signal:全量 hook 遍历为长任务候选,循环中检查(AbortedError,决策 16 ③)。
|
|
20
|
+
import { findOutlineNode, getEntity, listEntities, listRelations, readOutlineFile } from "@whispering233/ai-editor-db";
|
|
21
|
+
import { DEFAULT_HALF_LIFE, PAYOFF_TIMING } from "@whispering233/ai-editor-shared";
|
|
22
|
+
import { buildChapterIndex, outlineNodeName, throwIfAborted, } from "./utils.js";
|
|
23
|
+
/**
|
|
24
|
+
* 收集全部非软删伏笔及其生命周期关系(一次 listEntities + 两次 listRelations 查询层调用)。
|
|
25
|
+
* status 缺失的 hook 视为 planted(hooks.md 生命周期:创建即埋设)——hookStatuses 供 blocked 判定。
|
|
26
|
+
*/
|
|
27
|
+
function collectHooks(ctx, signal) {
|
|
28
|
+
const hooks = new Map();
|
|
29
|
+
const hookStatuses = new Map();
|
|
30
|
+
for (const summary of listEntities(ctx.db, { type: "hook", limit: 200 }).items) {
|
|
31
|
+
throwIfAborted(signal);
|
|
32
|
+
const entity = getEntity(ctx.db, summary.id);
|
|
33
|
+
if (entity === null)
|
|
34
|
+
continue; // 防御:摘要与详情不一致(不应出现)
|
|
35
|
+
hooks.set(summary.id, { entity, plants: [], advances: [], resolves: [], dependsOn: [], dependedOnBy: [] });
|
|
36
|
+
const status = entity.data.status;
|
|
37
|
+
hookStatuses.set(summary.id, typeof status === "string" && status !== "" ? status : "planted");
|
|
38
|
+
}
|
|
39
|
+
// 指向 hook 的关系(plants/advances/resolves 的 target 均为 hook;depends_on 单独处理)
|
|
40
|
+
for (const r of listRelations(ctx.db, { targetType: "hook" }, 1, ctx.outlineDir).relations) {
|
|
41
|
+
const rec = hooks.get(r.targetId);
|
|
42
|
+
if (rec === undefined)
|
|
43
|
+
continue;
|
|
44
|
+
if (r.relationType === "plants")
|
|
45
|
+
rec.plants.push(r);
|
|
46
|
+
else if (r.relationType === "advances")
|
|
47
|
+
rec.advances.push(r);
|
|
48
|
+
else if (r.relationType === "resolves")
|
|
49
|
+
rec.resolves.push(r);
|
|
50
|
+
}
|
|
51
|
+
// depends_on 全量:双向登记(source=依赖方、target=被依赖方)
|
|
52
|
+
for (const r of listRelations(ctx.db, { relationType: "depends_on" }, 1, ctx.outlineDir).relations) {
|
|
53
|
+
const source = hooks.get(r.sourceId);
|
|
54
|
+
const target = hooks.get(r.targetId);
|
|
55
|
+
if (source !== undefined)
|
|
56
|
+
source.dependsOn.push(r);
|
|
57
|
+
if (target !== undefined)
|
|
58
|
+
target.dependedOnBy.push(r);
|
|
59
|
+
}
|
|
60
|
+
return { hooks, hookStatuses };
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* half_life 缺省映射(决策 21):显式 half_life(正数)优先;
|
|
64
|
+
* 未设置按 payoff_timing 取 DEFAULT_HALF_LIFE;payoff_timing 缺失/非法 → slow_burn
|
|
65
|
+
* (长线保守默认——避免过早判定 stale 误报)。
|
|
66
|
+
* 防御:trunc 后再次检查 > 0——0 < half_life < 1(如 0.5)截断为 0 会让 stale/overdue 恒真,
|
|
67
|
+
* 此时退化走 payoff_timing 映射(oracle 修复轮)。
|
|
68
|
+
*/
|
|
69
|
+
export function resolveHalfLife(data) {
|
|
70
|
+
if (typeof data.half_life === "number" && Number.isFinite(data.half_life) && data.half_life > 0) {
|
|
71
|
+
const truncated = Math.trunc(data.half_life);
|
|
72
|
+
if (truncated > 0)
|
|
73
|
+
return truncated;
|
|
74
|
+
}
|
|
75
|
+
const timing = data.payoff_timing;
|
|
76
|
+
if (typeof timing === "string" && PAYOFF_TIMING.includes(timing)) {
|
|
77
|
+
return DEFAULT_HALF_LIFE[timing];
|
|
78
|
+
}
|
|
79
|
+
return DEFAULT_HALF_LIFE.slow_burn;
|
|
80
|
+
}
|
|
81
|
+
/** 关系源节点章节序列表(过滤无章号节点;plants 取最早埋设、advances 取最新推进) */
|
|
82
|
+
function chapterNumbersOf(chapterIndex, relations) {
|
|
83
|
+
const out = [];
|
|
84
|
+
for (const r of relations) {
|
|
85
|
+
const chapter = chapterIndex.chapterOf(r.sourceId);
|
|
86
|
+
if (chapter !== null)
|
|
87
|
+
out.push(chapter);
|
|
88
|
+
}
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* 健康指标计算(决策 21;**纯函数,不修改任何输入**——绝不写回 data):
|
|
93
|
+
* - age:current - 最早埋设章(plants 章节序 min)
|
|
94
|
+
* - dormancy:current - 最后活跃章(advances 章节序 max;无 advances → 埋设章——埋下后从未推进)
|
|
95
|
+
* - stale/overdue/ready_to_resolve/blocked 见 HookHealth 注释
|
|
96
|
+
*/
|
|
97
|
+
export function computeHookHealth(chapterIndex, rec, hookStatuses) {
|
|
98
|
+
const halfLife = resolveHalfLife(rec.entity.data);
|
|
99
|
+
const current = chapterIndex.currentChapter;
|
|
100
|
+
const plantChapters = chapterNumbersOf(chapterIndex, rec.plants);
|
|
101
|
+
const plantChapter = plantChapters.length > 0 ? Math.min(...plantChapters) : null;
|
|
102
|
+
const advanceChapters = chapterNumbersOf(chapterIndex, rec.advances);
|
|
103
|
+
const lastActiveChapter = advanceChapters.length > 0 ? Math.max(...advanceChapters) : plantChapter;
|
|
104
|
+
const age = current !== null && plantChapter !== null ? current - plantChapter : null;
|
|
105
|
+
const dormancy = current !== null && lastActiveChapter !== null ? current - lastActiveChapter : null;
|
|
106
|
+
const stale = dormancy !== null ? dormancy > halfLife : null;
|
|
107
|
+
const overdue = age !== null ? age > halfLife * 2 : null;
|
|
108
|
+
// ready_to_resolve:expected_resolve_node_id 已设置 → current >= 节点章节序;否则未计算(不猜测)。
|
|
109
|
+
// 指向软删/不存在的节点 → null(决策 12 可见性:软删节点不可作为兑现依据——
|
|
110
|
+
// 与 consistency R4「兑现节点软删报 error」同口径,指标不基于不可见节点计算)
|
|
111
|
+
let readyToResolve = null;
|
|
112
|
+
const expectedNodeId = rec.entity.data.expected_resolve_node_id;
|
|
113
|
+
if (typeof expectedNodeId === "string" && expectedNodeId !== "") {
|
|
114
|
+
const resolveChapter = chapterIndex.chapterOf(expectedNodeId);
|
|
115
|
+
if (resolveChapter !== null && current !== null) {
|
|
116
|
+
readyToResolve = current >= resolveChapter;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// blocked:本 hook 依赖(depends_on 的 target)尚未 resolved(abandoned 亦未回收 → 永久阻塞)。
|
|
120
|
+
// 软删的依赖 hook 不阻塞(决策 12:软删对象不可见——MVP 取舍,可争辩:软删依赖亦无法满足,
|
|
121
|
+
// 但回收站对象不参与健康判定更符合「不可见即不存在」语义)
|
|
122
|
+
const blockedBy = [];
|
|
123
|
+
for (const r of rec.dependsOn) {
|
|
124
|
+
const status = hookStatuses.get(r.targetId);
|
|
125
|
+
if (status !== undefined && status !== "resolved")
|
|
126
|
+
blockedBy.push(r.targetId);
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
age,
|
|
130
|
+
dormancy,
|
|
131
|
+
stale,
|
|
132
|
+
overdue,
|
|
133
|
+
ready_to_resolve: readyToResolve,
|
|
134
|
+
blocked: blockedBy.length > 0,
|
|
135
|
+
blocked_by: blockedBy,
|
|
136
|
+
half_life: halfLife,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/** 活跃判定(status 缺失视为 planted——hooks.md 生命周期创建即埋设) */
|
|
140
|
+
function isActive(hookStatuses, hookId) {
|
|
141
|
+
const status = hookStatuses.get(hookId) ?? "planted";
|
|
142
|
+
return status === "planted" || status === "progressing";
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* 伏笔健康总览(hooks.md analyze_hook_health(),无参全项目扫描)。
|
|
146
|
+
* 仅统计活跃伏笔(planted/progressing);_health 为运行时计算,不写回 data。
|
|
147
|
+
* 输出按 hook id 升序(稳定排序);signal:循环中检查(决策 16 ③)。
|
|
148
|
+
*/
|
|
149
|
+
export function runAnalyzeHookHealth(ctx, _args, signal) {
|
|
150
|
+
const chapterIndex = buildChapterIndex(ctx);
|
|
151
|
+
const { hooks, hookStatuses } = collectHooks(ctx, signal);
|
|
152
|
+
const overview = {
|
|
153
|
+
current_chapter: chapterIndex.currentChapter,
|
|
154
|
+
active_count: 0,
|
|
155
|
+
stale: [],
|
|
156
|
+
overdue: [],
|
|
157
|
+
blocked_chains: [],
|
|
158
|
+
warnings: [],
|
|
159
|
+
};
|
|
160
|
+
for (const [hookId, rec] of hooks) {
|
|
161
|
+
throwIfAborted(signal);
|
|
162
|
+
if (!isActive(hookStatuses, hookId))
|
|
163
|
+
continue;
|
|
164
|
+
overview.active_count += 1;
|
|
165
|
+
const health = computeHookHealth(chapterIndex, rec, hookStatuses);
|
|
166
|
+
const name = rec.entity.name;
|
|
167
|
+
if (health.stale === true) {
|
|
168
|
+
overview.stale.push(hookId);
|
|
169
|
+
overview.warnings.push(`「${name}」已 ${health.dormancy} 章未推进,半衰期 ${health.half_life}(stale)`);
|
|
170
|
+
}
|
|
171
|
+
if (health.overdue === true) {
|
|
172
|
+
overview.overdue.push(hookId);
|
|
173
|
+
overview.warnings.push(`「${name}」埋设已 ${health.age} 章,超过两倍半衰期(${health.half_life * 2}),建议尽快回收`);
|
|
174
|
+
}
|
|
175
|
+
if (health.blocked) {
|
|
176
|
+
overview.blocked_chains.push({ hookId, blockedBy: [...health.blocked_by] });
|
|
177
|
+
const blockers = health.blocked_by.map((id) => hooks.get(id)?.entity.name ?? id).join("、");
|
|
178
|
+
overview.warnings.push(`「${name}」被「${blockers}」阻塞(依赖尚未回收)`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// 稳定排序(输出可预测)
|
|
182
|
+
overview.stale.sort();
|
|
183
|
+
overview.overdue.sort();
|
|
184
|
+
overview.blocked_chains.sort((a, b) => a.hookId.localeCompare(b.hookId));
|
|
185
|
+
return overview;
|
|
186
|
+
}
|
|
187
|
+
/** 关系 → 节点事件(source 为大纲节点;name 取 outline title) */
|
|
188
|
+
function toNodeEvent(tree, chapterIndex, r) {
|
|
189
|
+
return { nodeId: r.sourceId, nodeName: outlineNodeName(tree, r.sourceId), chapter: chapterIndex.chapterOf(r.sourceId) };
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* 生命周期追踪(hooks.md trace_hook_lifecycle(hook_id))。
|
|
193
|
+
* hook 不存在/已软删 → null(查询无结果);plant 取最早埋设节点、resolve 取最新回收节点;
|
|
194
|
+
* dormancy 口径与 _health 一致(advances 最新,无 advances → 埋设章)。
|
|
195
|
+
*/
|
|
196
|
+
export function runTraceHookLifecycle(ctx, args, signal) {
|
|
197
|
+
const entity = getEntity(ctx.db, args.hook_id);
|
|
198
|
+
if (entity === null || entity.type !== "hook")
|
|
199
|
+
return null;
|
|
200
|
+
throwIfAborted(signal);
|
|
201
|
+
const tree = readOutlineFile(ctx.outlineDir);
|
|
202
|
+
const chapterIndex = buildChapterIndex(ctx);
|
|
203
|
+
const relations = listRelations(ctx.db, { targetType: "hook", targetId: args.hook_id }, 1, ctx.outlineDir).relations;
|
|
204
|
+
const plants = relations.filter((r) => r.relationType === "plants").map((r) => toNodeEvent(tree, chapterIndex, r));
|
|
205
|
+
const advances = relations.filter((r) => r.relationType === "advances").map((r) => toNodeEvent(tree, chapterIndex, r));
|
|
206
|
+
const resolves = relations.filter((r) => r.relationType === "resolves").map((r) => toNodeEvent(tree, chapterIndex, r));
|
|
207
|
+
// plant 取最早(章节序 min;无章号节点按原序保留)、resolve 取最新
|
|
208
|
+
const byChapter = (a, b) => (a.chapter ?? Infinity) - (b.chapter ?? Infinity);
|
|
209
|
+
const plant = plants.length > 0 ? [...plants].sort(byChapter)[0] : null;
|
|
210
|
+
const resolve = resolves.length > 0 ? [...resolves].sort(byChapter).reverse()[0] : null;
|
|
211
|
+
advances.sort(byChapter);
|
|
212
|
+
// dormancy:current - 最后活跃章(advances 最新或埋设章;hooks.md 公式仅计 advances——
|
|
213
|
+
// resolve 不参与,回收后休眠语义由 status=resolved 表达)
|
|
214
|
+
const lastActive = advances.length > 0 ? advances[advances.length - 1].chapter : plant?.chapter ?? null;
|
|
215
|
+
const dormancy = chapterIndex.currentChapter !== null && lastActive !== null ? chapterIndex.currentChapter - lastActive : null;
|
|
216
|
+
// 时间线图:plant/advance/resolve 按章节序合并
|
|
217
|
+
const events = [
|
|
218
|
+
...(plant !== null ? [{ ...plant, kind: "plant" }] : []),
|
|
219
|
+
...advances.map((e) => ({ ...e, kind: "advance" })),
|
|
220
|
+
...(resolve !== null ? [{ ...resolve, kind: "resolve" }] : []),
|
|
221
|
+
].sort((a, b) => (a.chapter ?? Infinity) - (b.chapter ?? Infinity));
|
|
222
|
+
return { hook: entity, plant, advances, resolve, dormancy, timeline_graph: { events } };
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* 回收建议(hooks.md suggest_hook_payoff(hook_id)):
|
|
226
|
+
* 候选 = 大纲中**当前章节之后**(含当前章)的场景节点(非软删),排除已回收节点;
|
|
227
|
+
* 理想回收点 = 埋设章 + 半衰期(节奏匹配);按与理想点距离升序取 top 3。
|
|
228
|
+
* hook 不存在/已软删 → null;无埋设记录或大纲无候选场景 → 空建议。
|
|
229
|
+
*/
|
|
230
|
+
export function runSuggestHookPayoff(ctx, args, signal) {
|
|
231
|
+
const entity = getEntity(ctx.db, args.hook_id);
|
|
232
|
+
if (entity === null || entity.type !== "hook")
|
|
233
|
+
return null;
|
|
234
|
+
throwIfAborted(signal);
|
|
235
|
+
const tree = readOutlineFile(ctx.outlineDir);
|
|
236
|
+
const chapterIndex = buildChapterIndex(ctx);
|
|
237
|
+
const halfLife = resolveHalfLife(entity.data);
|
|
238
|
+
const plants = listRelations(ctx.db, { targetType: "hook", targetId: args.hook_id, relationType: "plants" }, 1, ctx.outlineDir).relations;
|
|
239
|
+
const plantChapters = chapterNumbersOf(chapterIndex, plants);
|
|
240
|
+
if (plantChapters.length === 0)
|
|
241
|
+
return { suggestions: [] }; // 无埋设记录 → 无法基于节奏建议
|
|
242
|
+
const plantChapter = Math.min(...plantChapters);
|
|
243
|
+
const idealChapter = plantChapter + halfLife;
|
|
244
|
+
// 已回收节点(排除)
|
|
245
|
+
const resolvedNodes = new Set(listRelations(ctx.db, { targetType: "hook", targetId: args.hook_id, relationType: "resolves" }, 1, ctx.outlineDir).relations.map((r) => r.sourceId));
|
|
246
|
+
const candidates = [];
|
|
247
|
+
const visit = (nodes) => {
|
|
248
|
+
for (const node of nodes) {
|
|
249
|
+
if (node.type === "scene" && node.deleted !== true && !resolvedNodes.has(node.id)) {
|
|
250
|
+
const chapter = chapterIndex.chapterOf(node.id);
|
|
251
|
+
if (chapter !== null && (chapterIndex.currentChapter === null || chapter >= chapterIndex.currentChapter)) {
|
|
252
|
+
candidates.push({ nodeId: node.id, nodeName: node.title, chapter });
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
const children = node.children;
|
|
256
|
+
if (children !== undefined)
|
|
257
|
+
visit(children);
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
visit(tree.children);
|
|
261
|
+
candidates.sort((a, b) => Math.abs(a.chapter - idealChapter) - Math.abs(b.chapter - idealChapter));
|
|
262
|
+
const suggestions = candidates.slice(0, 3).map((c) => ({
|
|
263
|
+
at_node: c.nodeId,
|
|
264
|
+
reason: `伏笔埋设于第 ${plantChapter} 章(半衰期 ${halfLife}),理想回收点约第 ${idealChapter} 章——「${c.nodeName}」(第 ${c.chapter} 章)节奏匹配,建议在此回收`,
|
|
265
|
+
}));
|
|
266
|
+
return { suggestions };
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* 埋设机会发现(hooks.md find_hook_opportunities(outline_node_id)):
|
|
270
|
+
* 基于节点叙事特征建议适合的伏笔类别(每类别至多一条,规则表驱动):
|
|
271
|
+
* - R1 无伏笔埋设(无 plants 关系)→ mystery(悬念/谜团)
|
|
272
|
+
* - R2 角色在场 ≥ 2(appears_in 目标)→ relationship(人物关系)
|
|
273
|
+
* - R3 scene 冲突含外部层面(extra_personal)→ world_building(世界观)
|
|
274
|
+
* - R4 scene 价值转向(value_from ≠ value_to 且均非空)→ character_growth(角色成长)
|
|
275
|
+
* 节点不存在/已软删 → null。
|
|
276
|
+
*/
|
|
277
|
+
export function runFindHookOpportunities(ctx, args, signal) {
|
|
278
|
+
const tree = readOutlineFile(ctx.outlineDir);
|
|
279
|
+
const node = findOutlineNode(tree, args.outline_node_id);
|
|
280
|
+
if (node === undefined || node.deleted === true)
|
|
281
|
+
return null;
|
|
282
|
+
throwIfAborted(signal);
|
|
283
|
+
const opportunities = [];
|
|
284
|
+
// R1:节点尚无伏笔埋设(plants 关系 source = 本节点)
|
|
285
|
+
const plantsCount = listRelations(ctx.db, { sourceType: "outline_node", sourceId: args.outline_node_id, relationType: "plants" }, 1, ctx.outlineDir).relations.length;
|
|
286
|
+
if (plantsCount === 0) {
|
|
287
|
+
opportunities.push({ category: "mystery", reason: "该节点尚无伏笔埋设,适合设置悬念/谜团类伏笔(mystery)" });
|
|
288
|
+
}
|
|
289
|
+
// R2:在场角色数(appears_in 目标 = 本节点)
|
|
290
|
+
const castCount = listRelations(ctx.db, { targetType: "outline_node", targetId: args.outline_node_id, relationType: "appears_in" }, 1, ctx.outlineDir).relations.length;
|
|
291
|
+
if (castCount >= 2) {
|
|
292
|
+
opportunities.push({ category: "relationship", reason: `节点有 ${castCount} 个角色在场,适合人物关系类伏笔(relationship)` });
|
|
293
|
+
}
|
|
294
|
+
// R3/R4:scene 叙事特征(麦基字段集,决策 23)
|
|
295
|
+
if (node.type === "scene") {
|
|
296
|
+
const conflictLevels = node.data?.conflict_levels;
|
|
297
|
+
if (Array.isArray(conflictLevels) && conflictLevels.includes("extra_personal")) {
|
|
298
|
+
opportunities.push({ category: "world_building", reason: "场景冲突含外部层面(extra_personal),适合世界观类伏笔(world_building)" });
|
|
299
|
+
}
|
|
300
|
+
const valueFrom = node.data?.value_from;
|
|
301
|
+
const valueTo = node.data?.value_to;
|
|
302
|
+
if (typeof valueFrom === "string" && valueFrom !== "" && typeof valueTo === "string" && valueTo !== "" && valueFrom !== valueTo) {
|
|
303
|
+
opportunities.push({ category: "character_growth", reason: `场景价值转向(${valueFrom} → ${valueTo}),适合角色成长类伏笔(character_growth)` });
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return { opportunities };
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* 伏笔矛盾检测(hooks.md detect_hook_conflicts(),无参全项目扫描):
|
|
310
|
+
* - R1 循环依赖(error):A depends_on B 且 B depends_on A——永远无法同时回收
|
|
311
|
+
* **限制(MVP)**:仅检测二元互依赖(A↔B);三节点及以上长环零检出——依赖图按
|
|
312
|
+
* depends_on 稀疏构建,长环罕见,需 DFS 找环(后续切片评估),此处明示不静默承诺
|
|
313
|
+
* - R2 依赖已废弃(error):A depends_on B 且 B abandoned——依赖永远无法满足
|
|
314
|
+
* - R3 回收早于埋设(error):resolves 节点章节 < plants 节点章节——时间悖论
|
|
315
|
+
* - R4 推进早于埋设(error):advances 节点章节 < plants 节点章节——时间悖论
|
|
316
|
+
* 输出按 (hook_a, hook_b) 稳定排序;signal:循环中检查(决策 16 ③)。
|
|
317
|
+
*/
|
|
318
|
+
export function runDetectHookConflicts(ctx, _args, signal) {
|
|
319
|
+
const chapterIndex = buildChapterIndex(ctx);
|
|
320
|
+
const { hooks, hookStatuses } = collectHooks(ctx, signal);
|
|
321
|
+
const conflicts = [];
|
|
322
|
+
for (const [hookId, rec] of hooks) {
|
|
323
|
+
throwIfAborted(signal);
|
|
324
|
+
const name = rec.entity.name;
|
|
325
|
+
// R1 循环依赖:A 依赖 B 且 B 依赖 A(**仅二元互依赖**,见函数头限制注释;
|
|
326
|
+
// 每对只报一次——仅字典序小者视角检查,hook_a < hook_b)
|
|
327
|
+
for (const r of rec.dependsOn) {
|
|
328
|
+
const other = hooks.get(r.targetId);
|
|
329
|
+
if (other === undefined)
|
|
330
|
+
continue;
|
|
331
|
+
const otherName = other.entity.name;
|
|
332
|
+
if (hookId < r.targetId && other.dependsOn.some((x) => x.targetId === hookId)) {
|
|
333
|
+
conflicts.push({
|
|
334
|
+
hook_a: hookId,
|
|
335
|
+
hook_b: r.targetId,
|
|
336
|
+
field: "depends_on",
|
|
337
|
+
description: `伏笔「${name}」与「${otherName}」互相依赖(循环依赖),永远无法同时回收`,
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
// R2 依赖已废弃
|
|
341
|
+
if (hookStatuses.get(r.targetId) === "abandoned") {
|
|
342
|
+
conflicts.push({
|
|
343
|
+
hook_a: hookId,
|
|
344
|
+
hook_b: r.targetId,
|
|
345
|
+
field: "depends_on",
|
|
346
|
+
description: `「${name}」依赖的伏笔「${otherName}」已废弃(abandoned),依赖永远无法满足`,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// R3/R4 时间悖论(对比章节序;无章号节点跳过——不做宽松猜测)
|
|
351
|
+
const plantChapters = chapterNumbersOf(chapterIndex, rec.plants);
|
|
352
|
+
if (plantChapters.length > 0) {
|
|
353
|
+
const plantChapter = Math.min(...plantChapters);
|
|
354
|
+
for (const r of rec.resolves) {
|
|
355
|
+
const chapter = chapterIndex.chapterOf(r.sourceId);
|
|
356
|
+
if (chapter !== null && chapter < plantChapter) {
|
|
357
|
+
conflicts.push({
|
|
358
|
+
hook_a: hookId,
|
|
359
|
+
hook_b: hookId,
|
|
360
|
+
field: "timeline",
|
|
361
|
+
description: `伏笔「${name}」的回收节点(第 ${chapter} 章)早于埋设节点(第 ${plantChapter} 章),时间悖论`,
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
for (const r of rec.advances) {
|
|
366
|
+
const chapter = chapterIndex.chapterOf(r.sourceId);
|
|
367
|
+
if (chapter !== null && chapter < plantChapter) {
|
|
368
|
+
conflicts.push({
|
|
369
|
+
hook_a: hookId,
|
|
370
|
+
hook_b: hookId,
|
|
371
|
+
field: "timeline",
|
|
372
|
+
description: `伏笔「${name}」的推进节点(第 ${chapter} 章)早于埋设节点(第 ${plantChapter} 章),时间悖论`,
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
conflicts.sort((a, b) => (a.hook_a === b.hook_a ? a.hook_b.localeCompare(b.hook_b) : a.hook_a.localeCompare(b.hook_a)));
|
|
379
|
+
return { conflicts };
|
|
380
|
+
}
|
|
381
|
+
//# sourceMappingURL=hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.js","sourceRoot":"","sources":["../../src/analysis/hook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { ToolContext } from "../context.js";
|
|
2
|
+
import type { FindOrphanElementsArgs } from "@whispering233/ai-editor-shared";
|
|
3
|
+
/** 闲置角色条目 */
|
|
4
|
+
export interface UnusedCharacter {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
/** 最后活跃章序号(从未出场为 null) */
|
|
8
|
+
lastActiveChapter: number | null;
|
|
9
|
+
description: string;
|
|
10
|
+
}
|
|
11
|
+
/** 未解决变更条目(delta 自身未软删但不可见) */
|
|
12
|
+
export interface UnresolvedDelta {
|
|
13
|
+
id: string;
|
|
14
|
+
nodeId: string;
|
|
15
|
+
targetType: string;
|
|
16
|
+
targetId: string;
|
|
17
|
+
description: string;
|
|
18
|
+
/** 不可见原因(listDanglingDeltas reason,触发/目标侧) */
|
|
19
|
+
reason: string;
|
|
20
|
+
}
|
|
21
|
+
/** 悬空关系条目(端点已物理删除) */
|
|
22
|
+
export interface DanglingRelation {
|
|
23
|
+
id: string;
|
|
24
|
+
sourceId: string;
|
|
25
|
+
targetId: string;
|
|
26
|
+
relationType: string;
|
|
27
|
+
reason: string;
|
|
28
|
+
}
|
|
29
|
+
/** 跨存储软删不一致条目(大纲节点软删但 DB 记录未级联) */
|
|
30
|
+
export interface InconsistentSoftDelete {
|
|
31
|
+
kind: "relation" | "delta";
|
|
32
|
+
recordId: string;
|
|
33
|
+
/** delta 侧:触发节点 id;relation 侧:null */
|
|
34
|
+
nodeId: string | null;
|
|
35
|
+
/** relation 侧:已软删的端点 id;delta 侧:null */
|
|
36
|
+
endpointId: string | null;
|
|
37
|
+
description: string;
|
|
38
|
+
}
|
|
39
|
+
/** 孤立元素诊断结果(tools.md find_orphan_elements 返回结构) */
|
|
40
|
+
export interface OrphanElementsResult {
|
|
41
|
+
unused_characters: UnusedCharacter[];
|
|
42
|
+
unresolved_deltas: UnresolvedDelta[];
|
|
43
|
+
dangling_relations: DanglingRelation[];
|
|
44
|
+
inconsistent_soft_deletes: InconsistentSoftDelete[];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* 孤立元素诊断(tools.md find_orphan_elements(),无参全项目扫描)。
|
|
48
|
+
* 软删对象(回收站)不计入任何维度(listEntities/listRelations 过滤 + listDangling* 自身
|
|
49
|
+
* 未软删的前提,决策 12)。signal:各维度循环中检查(决策 16 ③)。
|
|
50
|
+
*
|
|
51
|
+
* **inconsistent_soft_deletes 与 S4.2 启动一致性校验补标范围对齐**(server/consistency.ts,
|
|
52
|
+
* 决策 16 修订——本工具诊断、S4.2 兜底修复,两侧口径必须一致):
|
|
53
|
+
* - S4.2 补标范围:relation 按端点(source_id/target_id 命中软删节点)、delta 按触发节点
|
|
54
|
+
* (node_id 命中软删节点)——对应本维度的 relation *_deleted 与 delta trigger_deleted
|
|
55
|
+
* - **delta 的大纲 target(目标端点为大纲节点且已软删)不在 S4.2 补标范围**(补标不看
|
|
56
|
+
* target)——该形态归 unresolved_deltas(reason=target_deleted),不列为本维度;
|
|
57
|
+
* 维护者不得将 target_deleted 移入本维度(否则与 S4.2 修复范围脱节)
|
|
58
|
+
*/
|
|
59
|
+
export declare function runFindOrphanElements(ctx: ToolContext, _args: FindOrphanElementsArgs, signal?: AbortSignal): OrphanElementsResult;
|
|
60
|
+
//# sourceMappingURL=orphan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orphan.d.ts","sourceRoot":"","sources":["../../src/analysis/orphan.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAE9E,aAAa;AACb,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,+BAA+B;AAC/B,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,sBAAsB;AACtB,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,mCAAmC;AACnC,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wCAAwC;IACxC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,mDAAmD;AACnD,MAAM,WAAW,oBAAoB;IACnC,iBAAiB,EAAE,eAAe,EAAE,CAAC;IACrC,iBAAiB,EAAE,eAAe,EAAE,CAAC;IACrC,kBAAkB,EAAE,gBAAgB,EAAE,CAAC;IACvC,yBAAyB,EAAE,sBAAsB,EAAE,CAAC;CACrD;AAsED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,oBAAoB,CA8DjI"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// 分析类工具:find_orphan_elements(孤立元素诊断,S6.4)
|
|
2
|
+
// 契约来源:doc/api/tools.md「孤立元素」→ { unused_characters, unresolved_deltas,
|
|
3
|
+
// dangling_relations, inconsistent_soft_deletes }
|
|
4
|
+
// 语义(四维诊断,全项目扫描):
|
|
5
|
+
// 1. unused_characters:闲置角色——从未出场(无 appears_in 且无属性变更记录),或
|
|
6
|
+
// 最后活跃章序号 < 当前最新章序号(「写到第30章但角色C第10章后就没出现」,决策 21 章序号现推)
|
|
7
|
+
// 2. unresolved_deltas:未解决变更——delta 自身未软删但已不可见(触发节点缺失 /
|
|
8
|
+
// 目标端点软删或缺失),永不生效的「幽灵变更」
|
|
9
|
+
// 3. dangling_relations:悬空关系——关系自身未软删但端点已物理删除(purge 残留)
|
|
10
|
+
// 4. inconsistent_soft_deletes:跨存储软删不一致——大纲节点已软删但关联 relation/delta
|
|
11
|
+
// 未级联软删(「可见记录指向已软删节点」的幽灵形态;诊断用途,兜底修复由启动一致性校验承担,
|
|
12
|
+
// 决策 16 修订——本工具只诊断与引导修复)
|
|
13
|
+
// 数据访问:db 查询层(listEntities/listRelations/listDeltasByTarget/listDanglingDeltas/
|
|
14
|
+
// listDanglingRelations/deriveChapterOrder/getChapterNumber)+ 纯函数分析,无原生 SQL。
|
|
15
|
+
// signal:多角色 × 多记录的遍历为长任务候选,循环中检查(决策 16 ③)。
|
|
16
|
+
import { listDanglingDeltas, listDanglingRelations, listDeltasByTarget, listEntities, listRelations, } from "@whispering233/ai-editor-db";
|
|
17
|
+
import { buildChapterIndex, throwIfAborted } from "./utils.js";
|
|
18
|
+
/**
|
|
19
|
+
* 角色活跃度:appears_in 目标节点 + Delta 触发节点合并去重(卷级节点无章号,跳过)。
|
|
20
|
+
* @returns { active, lastChapter }——active=false 表示从未出场;lastChapter 为最后活跃
|
|
21
|
+
* 章序号(活跃点均在卷级等无章号节点时为 null,不做宽松猜测)。
|
|
22
|
+
* 章序号经共享 ChapterIndex(决策 21 口径,S6.5 与伏笔工具同源)。
|
|
23
|
+
*/
|
|
24
|
+
function activityOf(ctx, chapterIndex, characterId, appearsIn) {
|
|
25
|
+
const activeNodeIds = new Set();
|
|
26
|
+
for (const nodeId of appearsIn.get(characterId) ?? [])
|
|
27
|
+
activeNodeIds.add(nodeId);
|
|
28
|
+
for (const delta of listDeltasByTarget(ctx.db, characterId, ctx.outlineDir))
|
|
29
|
+
activeNodeIds.add(delta.nodeId);
|
|
30
|
+
if (activeNodeIds.size === 0)
|
|
31
|
+
return { active: false, lastChapter: null };
|
|
32
|
+
let last = null;
|
|
33
|
+
for (const nodeId of activeNodeIds) {
|
|
34
|
+
const chapter = chapterIndex.chapterOf(nodeId);
|
|
35
|
+
if (chapter !== null) {
|
|
36
|
+
last = last === null ? chapter : Math.max(last, chapter);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return { active: true, lastChapter: last };
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 闲置角色诊断(tools.md「写到第30章但角色C第10章后就没出现」):
|
|
43
|
+
* - 从未出场:无 appears_in 关系且无 Delta 记录
|
|
44
|
+
* - 掉线角色:最后活跃章 < 当前最新章(「当前最新章」= current_position 所属章,
|
|
45
|
+
* 决策 21 口径,经共享 ChapterIndex 推导——规划 40 章只写到 30 章时,活跃于第 35 章
|
|
46
|
+
* (未写章节)的角色不算闲置;大纲无章或角色活跃点无章号时不下结论——不做宽松猜测)
|
|
47
|
+
* 输出按 id 升序(稳定排序,跨维度可预测)。
|
|
48
|
+
*/
|
|
49
|
+
function collectUnusedCharacters(ctx, signal) {
|
|
50
|
+
const characters = listEntities(ctx.db, { type: "character", limit: 200 }).items;
|
|
51
|
+
// appears_in(角色 → 大纲节点)按 sourceId 分组
|
|
52
|
+
const appearsIn = new Map();
|
|
53
|
+
for (const r of listRelations(ctx.db, { sourceType: "character", relationType: "appears_in" }, 1, ctx.outlineDir).relations) {
|
|
54
|
+
const list = appearsIn.get(r.sourceId) ?? [];
|
|
55
|
+
list.push(r.targetId);
|
|
56
|
+
appearsIn.set(r.sourceId, list);
|
|
57
|
+
}
|
|
58
|
+
const chapterIndex = buildChapterIndex(ctx); // 一次读树支撑全量活跃度查询
|
|
59
|
+
const latestChapter = chapterIndex.currentChapter;
|
|
60
|
+
const out = [];
|
|
61
|
+
for (const c of characters) {
|
|
62
|
+
throwIfAborted(signal);
|
|
63
|
+
const { active, lastChapter } = activityOf(ctx, chapterIndex, c.id, appearsIn);
|
|
64
|
+
if (!active) {
|
|
65
|
+
out.push({ id: c.id, name: c.name, lastActiveChapter: null, description: "从未出场(无 appears_in 关系且无属性变更记录)" });
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (lastChapter !== null && latestChapter !== null && lastChapter < latestChapter) {
|
|
69
|
+
out.push({
|
|
70
|
+
id: c.id,
|
|
71
|
+
name: c.name,
|
|
72
|
+
lastActiveChapter: lastChapter,
|
|
73
|
+
description: `最后活跃于第 ${lastChapter} 章(当前最新第 ${latestChapter} 章),已 ${latestChapter - lastChapter} 章未出场`,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
out.sort((a, b) => a.id.localeCompare(b.id)); // 稳定排序(输出可预测)
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* 孤立元素诊断(tools.md find_orphan_elements(),无参全项目扫描)。
|
|
82
|
+
* 软删对象(回收站)不计入任何维度(listEntities/listRelations 过滤 + listDangling* 自身
|
|
83
|
+
* 未软删的前提,决策 12)。signal:各维度循环中检查(决策 16 ③)。
|
|
84
|
+
*
|
|
85
|
+
* **inconsistent_soft_deletes 与 S4.2 启动一致性校验补标范围对齐**(server/consistency.ts,
|
|
86
|
+
* 决策 16 修订——本工具诊断、S4.2 兜底修复,两侧口径必须一致):
|
|
87
|
+
* - S4.2 补标范围:relation 按端点(source_id/target_id 命中软删节点)、delta 按触发节点
|
|
88
|
+
* (node_id 命中软删节点)——对应本维度的 relation *_deleted 与 delta trigger_deleted
|
|
89
|
+
* - **delta 的大纲 target(目标端点为大纲节点且已软删)不在 S4.2 补标范围**(补标不看
|
|
90
|
+
* target)——该形态归 unresolved_deltas(reason=target_deleted),不列为本维度;
|
|
91
|
+
* 维护者不得将 target_deleted 移入本维度(否则与 S4.2 修复范围脱节)
|
|
92
|
+
*/
|
|
93
|
+
export function runFindOrphanElements(ctx, _args, signal) {
|
|
94
|
+
// 1. 闲置角色
|
|
95
|
+
const unusedCharacters = collectUnusedCharacters(ctx, signal);
|
|
96
|
+
// 2-4. 悬空记录(db 诊断层:delta 自身/关系自身均未软删,只报不可见/悬空形态)
|
|
97
|
+
const danglingDeltas = listDanglingDeltas(ctx.db, ctx.outlineDir);
|
|
98
|
+
const danglingRelations = listDanglingRelations(ctx.db, ctx.outlineDir);
|
|
99
|
+
throwIfAborted(signal);
|
|
100
|
+
// 2. 未解决变更:触发节点缺失 / 目标端点软删或缺失(目标侧不可见)
|
|
101
|
+
const unresolvedDeltas = [];
|
|
102
|
+
// 3. 悬空关系:端点物理删除
|
|
103
|
+
const danglingRelationList = [];
|
|
104
|
+
// 4. 跨存储软删不一致:大纲节点已软删但记录未级联(trigger_deleted / *_deleted;
|
|
105
|
+
// 口径见函数头注释——与 S4.2 补标范围对齐,delta 大纲 target 归 unresolved_deltas)
|
|
106
|
+
const inconsistentSoftDeletes = [];
|
|
107
|
+
for (const d of danglingDeltas) {
|
|
108
|
+
throwIfAborted(signal);
|
|
109
|
+
if (d.reason === "trigger_deleted") {
|
|
110
|
+
inconsistentSoftDeletes.push({
|
|
111
|
+
kind: "delta",
|
|
112
|
+
recordId: d.id,
|
|
113
|
+
nodeId: d.nodeId,
|
|
114
|
+
endpointId: null,
|
|
115
|
+
description: `Delta「${d.description}」的触发节点 ${d.nodeId} 已软删,但本记录未级联软删(跨存储不一致)`,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
unresolvedDeltas.push({
|
|
120
|
+
id: d.id,
|
|
121
|
+
nodeId: d.nodeId,
|
|
122
|
+
targetType: d.targetType,
|
|
123
|
+
targetId: d.targetId,
|
|
124
|
+
description: d.description,
|
|
125
|
+
reason: d.reason,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
for (const r of danglingRelations) {
|
|
130
|
+
throwIfAborted(signal);
|
|
131
|
+
if (r.reason === "source_missing" || r.reason === "target_missing") {
|
|
132
|
+
danglingRelationList.push({ id: r.id, sourceId: r.sourceId, targetId: r.targetId, relationType: r.relationType, reason: r.reason });
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
const endpointId = r.reason === "source_deleted" ? r.sourceId : r.targetId;
|
|
136
|
+
inconsistentSoftDeletes.push({
|
|
137
|
+
kind: "relation",
|
|
138
|
+
recordId: r.id,
|
|
139
|
+
nodeId: null,
|
|
140
|
+
endpointId,
|
|
141
|
+
description: `关系 ${r.sourceId} → ${r.targetId}(${r.relationType})指向已软删端点 ${endpointId},但本记录未级联软删(跨存储不一致)`,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
inconsistentSoftDeletes.sort((a, b) => a.recordId.localeCompare(b.recordId)); // 稳定排序(输出可预测)
|
|
146
|
+
return {
|
|
147
|
+
unused_characters: unusedCharacters,
|
|
148
|
+
unresolved_deltas: unresolvedDeltas,
|
|
149
|
+
dangling_relations: danglingRelationList,
|
|
150
|
+
inconsistent_soft_deletes: inconsistentSoftDeletes,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=orphan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orphan.js","sourceRoot":"","sources":["../../src/analysis/orphan.ts"],"names":[],"mappings":"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"}
|