@coralai/sps-cli 0.56.2 → 0.57.0
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/console/routes/chat.d.ts +8 -0
- package/dist/console/routes/chat.d.ts.map +1 -1
- package/dist/console/routes/chat.js +186 -31
- package/dist/console/routes/chat.js.map +1 -1
- package/dist/console/routes/processes.d.ts.map +1 -1
- package/dist/console/routes/processes.js +12 -0
- package/dist/console/routes/processes.js.map +1 -1
- package/dist/console-assets/assets/{index-CWkYVI5d.js → index-BL7haI2Z.js} +195 -190
- package/dist/console-assets/assets/{index-CnUBHNsN.css → index-BOpxRNe1.css} +1 -1
- package/dist/console-assets/index.html +2 -2
- package/dist/core/pipelineSession.d.ts +15 -0
- package/dist/core/pipelineSession.d.ts.map +1 -0
- package/dist/core/pipelineSession.js +45 -0
- package/dist/core/pipelineSession.js.map +1 -0
- package/dist/core/reclaimConfig.d.ts +6 -0
- package/dist/core/reclaimConfig.d.ts.map +1 -0
- package/dist/core/reclaimConfig.js +33 -0
- package/dist/core/reclaimConfig.js.map +1 -0
- package/dist/daemon/sessionDaemon.d.ts +6 -0
- package/dist/daemon/sessionDaemon.d.ts.map +1 -1
- package/dist/daemon/sessionDaemon.js +39 -15
- package/dist/daemon/sessionDaemon.js.map +1 -1
- package/dist/engines/StageEngine.d.ts.map +1 -1
- package/dist/engines/StageEngine.js +15 -0
- package/dist/engines/StageEngine.js.map +1 -1
- package/dist/main.js +0 -0
- package/dist/manager/worker-manager-impl.d.ts.map +1 -1
- package/dist/manager/worker-manager-impl.js +7 -3
- package/dist/manager/worker-manager-impl.js.map +1 -1
- package/dist/manager/worker-manager.d.ts +5 -0
- package/dist/manager/worker-manager.d.ts.map +1 -1
- package/dist/providers/ACPWorkerRuntime.d.ts +1 -0
- package/dist/providers/ACPWorkerRuntime.d.ts.map +1 -1
- package/dist/providers/ACPWorkerRuntime.js +4 -1
- package/dist/providers/ACPWorkerRuntime.js.map +1 -1
- package/dist/services/ChatService.d.ts +10 -0
- package/dist/services/ChatService.d.ts.map +1 -1
- package/dist/services/ChatService.js +25 -2
- package/dist/services/ChatService.js.map +1 -1
- package/package.json +2 -2
- package/dist/commands/wikiCommand.d.ts +0 -77
- package/dist/commands/wikiCommand.d.ts.map +0 -1
- package/dist/commands/wikiCommand.js +0 -489
- package/dist/commands/wikiCommand.js.map +0 -1
- package/dist/core/skillStore.d.ts +0 -55
- package/dist/core/skillStore.d.ts.map +0 -1
- package/dist/core/skillStore.js +0 -224
- package/dist/core/skillStore.js.map +0 -1
- package/dist/core/wiki/frontmatter.d.ts +0 -55
- package/dist/core/wiki/frontmatter.d.ts.map +0 -1
- package/dist/core/wiki/frontmatter.js +0 -109
- package/dist/core/wiki/frontmatter.js.map +0 -1
- package/dist/core/wiki/hot.d.ts +0 -27
- package/dist/core/wiki/hot.d.ts.map +0 -1
- package/dist/core/wiki/hot.js +0 -124
- package/dist/core/wiki/hot.js.map +0 -1
- package/dist/core/wiki/index-builder.d.ts +0 -37
- package/dist/core/wiki/index-builder.d.ts.map +0 -1
- package/dist/core/wiki/index-builder.js +0 -130
- package/dist/core/wiki/index-builder.js.map +0 -1
- package/dist/core/wiki/linter.d.ts +0 -76
- package/dist/core/wiki/linter.d.ts.map +0 -1
- package/dist/core/wiki/linter.js +0 -280
- package/dist/core/wiki/linter.js.map +0 -1
- package/dist/core/wiki/log.d.ts +0 -24
- package/dist/core/wiki/log.d.ts.map +0 -1
- package/dist/core/wiki/log.js +0 -107
- package/dist/core/wiki/log.js.map +0 -1
- package/dist/core/wiki/manifest.d.ts +0 -59
- package/dist/core/wiki/manifest.d.ts.map +0 -1
- package/dist/core/wiki/manifest.js +0 -180
- package/dist/core/wiki/manifest.js.map +0 -1
- package/dist/core/wiki/page.d.ts +0 -72
- package/dist/core/wiki/page.d.ts.map +0 -1
- package/dist/core/wiki/page.js +0 -221
- package/dist/core/wiki/page.js.map +0 -1
- package/dist/core/wiki/reader.d.ts +0 -102
- package/dist/core/wiki/reader.d.ts.map +0 -1
- package/dist/core/wiki/reader.js +0 -225
- package/dist/core/wiki/reader.js.map +0 -1
- package/dist/core/wiki/scaffold.d.ts +0 -42
- package/dist/core/wiki/scaffold.d.ts.map +0 -1
- package/dist/core/wiki/scaffold.js +0 -223
- package/dist/core/wiki/scaffold.js.map +0 -1
- package/dist/core/wiki/searcher.d.ts +0 -73
- package/dist/core/wiki/searcher.d.ts.map +0 -1
- package/dist/core/wiki/searcher.js +0 -216
- package/dist/core/wiki/searcher.js.map +0 -1
- package/dist/core/wiki/sources.d.ts +0 -84
- package/dist/core/wiki/sources.d.ts.map +0 -1
- package/dist/core/wiki/sources.js +0 -261
- package/dist/core/wiki/sources.js.map +0 -1
- package/dist/core/wiki/types.d.ts +0 -441
- package/dist/core/wiki/types.d.ts.map +0 -1
- package/dist/core/wiki/types.js +0 -109
- package/dist/core/wiki/types.js.map +0 -1
- package/dist/shared/wikiPaths.d.ts +0 -38
- package/dist/shared/wikiPaths.d.ts.map +0 -1
- package/dist/shared/wikiPaths.js +0 -89
- package/dist/shared/wikiPaths.js.map +0 -1
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module core/wiki/index-builder
|
|
3
|
-
* @description 渲染 wiki/index.md:全部 page 的 catalog,按类型分组
|
|
4
|
-
*
|
|
5
|
-
* @layer core
|
|
6
|
-
*
|
|
7
|
-
* doc-28 §10:reader 5 层注入策略里"index 节选 top-30 行"是 Worker prompt
|
|
8
|
-
* 知识地图来源——所以 index.md 必须**密集且 LLM-friendly**:
|
|
9
|
-
* - 每条一行:`- [[type/Title]]: TL;DR 摘要`
|
|
10
|
-
* - 按类型分组(### Modules / ### Concepts / ### Lessons / ...)
|
|
11
|
-
* - 不写废话头(无引子、无 stats 表格之类)
|
|
12
|
-
*
|
|
13
|
-
* 重建时机:每次 ingest / write 后调用一次(cheap,纯函数+1 次 writeFile)。
|
|
14
|
-
*/
|
|
15
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
16
|
-
import { dirname } from 'node:path';
|
|
17
|
-
import { wikiIndexFile } from '../../shared/wikiPaths.js';
|
|
18
|
-
import { extractTLDR } from './searcher.js';
|
|
19
|
-
// ─── Render ───────────────────────────────────────────────────────
|
|
20
|
-
const SECTIONS = [
|
|
21
|
-
{ type: 'module', label: 'Modules' },
|
|
22
|
-
{ type: 'concept', label: 'Concepts' },
|
|
23
|
-
{ type: 'decision', label: 'Decisions' },
|
|
24
|
-
{ type: 'lesson', label: 'Lessons' },
|
|
25
|
-
{ type: 'source', label: 'Sources' },
|
|
26
|
-
];
|
|
27
|
-
/**
|
|
28
|
-
* 从 page 列表渲染 index.md 完整内容。
|
|
29
|
-
*
|
|
30
|
-
* 输出形如:
|
|
31
|
-
* ```md
|
|
32
|
-
* ---
|
|
33
|
-
* type: meta
|
|
34
|
-
* title: Wiki Index
|
|
35
|
-
* updated: 2026-04-27
|
|
36
|
-
* ---
|
|
37
|
-
*
|
|
38
|
-
* # Wiki Index
|
|
39
|
-
*
|
|
40
|
-
* Pages: 12 · Updated 2026-04-27
|
|
41
|
-
*
|
|
42
|
-
* ## Modules (3)
|
|
43
|
-
* - [[modules/PipelineService]]: TL;DR 摘要短句...
|
|
44
|
-
* - ...
|
|
45
|
-
*
|
|
46
|
-
* ## Lessons (4)
|
|
47
|
-
* - [[lessons/Stop Hook Race]]: ...
|
|
48
|
-
* ```
|
|
49
|
-
*/
|
|
50
|
-
export function renderIndex(pages, opts = {}) {
|
|
51
|
-
const ts = opts.updatedAt ?? new Date().toISOString().slice(0, 10);
|
|
52
|
-
const total = pages.length;
|
|
53
|
-
const lines = [
|
|
54
|
-
'---',
|
|
55
|
-
'type: meta',
|
|
56
|
-
'title: Wiki Index',
|
|
57
|
-
`updated: ${ts}`,
|
|
58
|
-
'---',
|
|
59
|
-
'',
|
|
60
|
-
'# Wiki Index',
|
|
61
|
-
'',
|
|
62
|
-
`Pages: ${total} · Updated ${ts}`,
|
|
63
|
-
'',
|
|
64
|
-
];
|
|
65
|
-
for (const section of SECTIONS) {
|
|
66
|
-
const inSection = pages.filter((p) => p.frontmatter.type === section.type);
|
|
67
|
-
if (inSection.length === 0)
|
|
68
|
-
continue;
|
|
69
|
-
lines.push(`## ${section.label} (${inSection.length})`);
|
|
70
|
-
// 按 title 字典序排
|
|
71
|
-
const sorted = inSection.slice().sort((a, b) => a.frontmatter.title.localeCompare(b.frontmatter.title, 'en'));
|
|
72
|
-
for (const page of sorted) {
|
|
73
|
-
const tldr = extractTLDR(page.body);
|
|
74
|
-
const oneliner = squashToOneLine(tldr, 120);
|
|
75
|
-
lines.push(`- [[${page.pageId}]]: ${oneliner}`);
|
|
76
|
-
}
|
|
77
|
-
lines.push('');
|
|
78
|
-
}
|
|
79
|
-
if (total === 0) {
|
|
80
|
-
lines.push('(empty—— run `sps wiki update` to populate)');
|
|
81
|
-
lines.push('');
|
|
82
|
-
}
|
|
83
|
-
return lines.join('\n');
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* 写 index.md(全量重建)。
|
|
87
|
-
*/
|
|
88
|
-
export function writeIndex(repoDir, pages) {
|
|
89
|
-
const path = wikiIndexFile(repoDir);
|
|
90
|
-
const dir = dirname(path);
|
|
91
|
-
if (!existsSync(dir))
|
|
92
|
-
mkdirSync(dir, { recursive: true });
|
|
93
|
-
const content = renderIndex(pages);
|
|
94
|
-
writeFileSync(path, content, { encoding: 'utf-8', mode: 0o644 });
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* 取 index.md 节选 top-N 行(不含 frontmatter)。
|
|
98
|
-
* 给 reader.ts 的 Layer 2 用——总是注入这一段。
|
|
99
|
-
*/
|
|
100
|
-
export function readIndexSummary(repoDir, maxLines = 30) {
|
|
101
|
-
const path = wikiIndexFile(repoDir);
|
|
102
|
-
if (!existsSync(path))
|
|
103
|
-
return '';
|
|
104
|
-
let content;
|
|
105
|
-
try {
|
|
106
|
-
content = readFileSync(path, 'utf-8');
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
return '';
|
|
110
|
-
}
|
|
111
|
-
// strip frontmatter
|
|
112
|
-
const body = content.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, '').trim();
|
|
113
|
-
const lines = body.split('\n');
|
|
114
|
-
// 跳过 # Wiki Index 标题 + 空行
|
|
115
|
-
const start = lines.findIndex((l) => l.startsWith('## '));
|
|
116
|
-
if (start === -1)
|
|
117
|
-
return body.split('\n').slice(0, maxLines).join('\n');
|
|
118
|
-
return lines.slice(start, start + maxLines).join('\n');
|
|
119
|
-
}
|
|
120
|
-
// ─── helpers ──────────────────────────────────────────────────────
|
|
121
|
-
/**
|
|
122
|
-
* 把 TL;DR 拍扁成一行 + 截短。给 Worker prompt 注入用——不能多行。
|
|
123
|
-
*/
|
|
124
|
-
function squashToOneLine(text, maxLen) {
|
|
125
|
-
const flat = text.replace(/\s+/g, ' ').trim();
|
|
126
|
-
if (flat.length <= maxLen)
|
|
127
|
-
return flat;
|
|
128
|
-
return flat.slice(0, maxLen - 1) + '…';
|
|
129
|
-
}
|
|
130
|
-
//# sourceMappingURL=index-builder.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-builder.js","sourceRoot":"","sources":["../../../src/core/wiki/index-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import type { Manifest, Page } from './types.js';
|
|
2
|
-
export type IssueKind = 'orphan' | 'dead-link' | 'fm-gap' | 'stale';
|
|
3
|
-
export type IssueSeverity = 'warn' | 'error';
|
|
4
|
-
export interface LintIssue {
|
|
5
|
-
readonly kind: IssueKind;
|
|
6
|
-
readonly severity: IssueSeverity;
|
|
7
|
-
/** Page id where issue was found; null when issue is repo-level (e.g. stale source) */
|
|
8
|
-
readonly pageId: string | null;
|
|
9
|
-
/** One-line message */
|
|
10
|
-
readonly message: string;
|
|
11
|
-
/** Optional context: target page id / source path / field name */
|
|
12
|
-
readonly target?: string;
|
|
13
|
-
}
|
|
14
|
-
export interface LintReport {
|
|
15
|
-
readonly issues: readonly LintIssue[];
|
|
16
|
-
/** Counts grouped by kind for fast summary */
|
|
17
|
-
readonly counts: Record<IssueKind, number>;
|
|
18
|
-
readonly errorCount: number;
|
|
19
|
-
readonly warnCount: number;
|
|
20
|
-
}
|
|
21
|
-
export interface LintInput {
|
|
22
|
-
readonly pages: readonly Page[];
|
|
23
|
-
readonly manifest: Manifest;
|
|
24
|
-
readonly repoDir: string;
|
|
25
|
-
}
|
|
26
|
-
export declare function lintWiki(input: LintInput): LintReport;
|
|
27
|
-
/**
|
|
28
|
-
* Orphan = page that nobody links to (via frontmatter related[] OR body wikilink).
|
|
29
|
-
*
|
|
30
|
-
* A solo page can still be valuable (e.g. just-written lesson) — orphan is **warn**,
|
|
31
|
-
* not error.
|
|
32
|
-
*/
|
|
33
|
-
export declare function checkOrphans(pages: readonly Page[]): LintIssue[];
|
|
34
|
-
/**
|
|
35
|
-
* Dead link = wikilink "[[X]]" where X (resolved) is not in the page set.
|
|
36
|
-
*
|
|
37
|
-
* Errors for related[] (frontmatter); warnings for body links (in-flight writing).
|
|
38
|
-
*/
|
|
39
|
-
export declare function checkDeadLinks(pages: readonly Page[]): LintIssue[];
|
|
40
|
-
/**
|
|
41
|
-
* Catches missing soft-required fields the zod schema can't enforce
|
|
42
|
-
* (e.g. empty title, empty TL;DR, all default tags). Schema-level errors
|
|
43
|
-
* are caught at parse time — this is a content sniff.
|
|
44
|
-
*/
|
|
45
|
-
export declare function checkFrontmatterGaps(pages: readonly Page[]): LintIssue[];
|
|
46
|
-
/**
|
|
47
|
-
* Compare manifest's stored sha256 against current file hash on disk.
|
|
48
|
-
* Mismatch = source has drifted since last ingest → its derived pages may be stale.
|
|
49
|
-
*
|
|
50
|
-
* Files that don't exist on disk anymore are flagged as 'stale' too (they should
|
|
51
|
-
* be removed from manifest via finalize).
|
|
52
|
-
*/
|
|
53
|
-
export declare function checkStaleSources(manifest: Manifest, repoDir: string): LintIssue[];
|
|
54
|
-
/**
|
|
55
|
-
* Resolve a "[[X]]" or "[[type/X]]" wikilink against the known pageId set.
|
|
56
|
-
*
|
|
57
|
-
* Strategy:
|
|
58
|
-
* - "[[type/X]]" → look up exact pageId
|
|
59
|
-
* - "[[X]]" → look up any pageId ending with "/X" (any type matches)
|
|
60
|
-
*
|
|
61
|
-
* Returns the resolved pageId, or null if unresolvable.
|
|
62
|
-
*/
|
|
63
|
-
export declare function resolveLinkToId(wikilink: string, ids: ReadonlySet<string>): string | null;
|
|
64
|
-
export declare function extractBodyWikilinks(body: string): string[];
|
|
65
|
-
/**
|
|
66
|
-
* Compare source mtime vs page mtime. Returns paths whose source is newer.
|
|
67
|
-
*
|
|
68
|
-
* Best-effort — file mtime precision varies (ext4 ns vs HFS+ 1s); we use a
|
|
69
|
-
* 60s threshold to avoid false positives.
|
|
70
|
-
*/
|
|
71
|
-
export declare function findOutdatedPages(manifest: Manifest, pages: readonly Page[], repoDir: string, thresholdMs?: number): {
|
|
72
|
-
sourcePath: string;
|
|
73
|
-
pageIds: string[];
|
|
74
|
-
sourceMtime: Date;
|
|
75
|
-
}[];
|
|
76
|
-
//# sourceMappingURL=linter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"linter.d.ts","sourceRoot":"","sources":["../../../src/core/wiki/linter.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIjD,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AACpE,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC;AAE7C,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,uFAAuF;IACvF,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,uBAAuB;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,8CAA8C;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC3C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAID,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,UAAU,CAOrD;AAID;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,SAAS,EAAE,CA+BhE;AAID;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,SAAS,EAAE,CA4BlE;AAID;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,SAAS,EAAE,CAiCxE;AAID;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,CA4BlF;AAID;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,WAAW,CAAC,MAAM,CAAC,GACvB,MAAM,GAAG,IAAI,CAaf;AAID,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAM3D;AA0BD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,SAAS,IAAI,EAAE,EACtB,OAAO,EAAE,MAAM,EACf,WAAW,SAAS,GACnB;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,IAAI,CAAA;CAAE,EAAE,CA4BhE"}
|
package/dist/core/wiki/linter.js
DELETED
|
@@ -1,280 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module core/wiki/linter
|
|
3
|
-
* @description Wiki lint:orphan / dead link / frontmatter gap / stale 检查
|
|
4
|
-
*
|
|
5
|
-
* @layer core
|
|
6
|
-
*
|
|
7
|
-
* doc-28 §10 wiki check 的代码实现。纯函数(除文件 mtime 读取):给一组 Page +
|
|
8
|
-
* manifest,返一份 Report。
|
|
9
|
-
*
|
|
10
|
-
* 四类问题:
|
|
11
|
-
* - orphan — 页未被任何其他页 related[] 或 body wikilink 引用
|
|
12
|
-
* - dead-link — wikilink 指向不存在的 page
|
|
13
|
-
* - fm-gap — frontmatter 缺关键字段(其实 zod schema 已校验,这里防漏)
|
|
14
|
-
* - stale — manifest 里 source 的 hash 跟当前文件不一致(content drift)
|
|
15
|
-
*
|
|
16
|
-
* 不做:
|
|
17
|
-
* - 自动修复(删 dead link、合并 orphan)—— 安全交给人决定
|
|
18
|
-
* - 跨项目检查
|
|
19
|
-
*/
|
|
20
|
-
import { existsSync, statSync } from 'node:fs';
|
|
21
|
-
import { resolve } from 'node:path';
|
|
22
|
-
import { tryHashFile } from './manifest.js';
|
|
23
|
-
export function lintWiki(input) {
|
|
24
|
-
const issues = [];
|
|
25
|
-
issues.push(...checkOrphans(input.pages));
|
|
26
|
-
issues.push(...checkDeadLinks(input.pages));
|
|
27
|
-
issues.push(...checkFrontmatterGaps(input.pages));
|
|
28
|
-
issues.push(...checkStaleSources(input.manifest, input.repoDir));
|
|
29
|
-
return summarize(issues);
|
|
30
|
-
}
|
|
31
|
-
// ─── Orphan detection ────────────────────────────────────────────
|
|
32
|
-
/**
|
|
33
|
-
* Orphan = page that nobody links to (via frontmatter related[] OR body wikilink).
|
|
34
|
-
*
|
|
35
|
-
* A solo page can still be valuable (e.g. just-written lesson) — orphan is **warn**,
|
|
36
|
-
* not error.
|
|
37
|
-
*/
|
|
38
|
-
export function checkOrphans(pages) {
|
|
39
|
-
const ids = new Set(pages.map((p) => p.pageId));
|
|
40
|
-
const refCount = new Map();
|
|
41
|
-
for (const id of ids)
|
|
42
|
-
refCount.set(id, 0);
|
|
43
|
-
for (const p of pages) {
|
|
44
|
-
// related[] is wikilinks "[[Page Name]]" — strip brackets and check both
|
|
45
|
-
// bare-title and "type/title" forms against ids.
|
|
46
|
-
for (const link of p.frontmatter.related) {
|
|
47
|
-
const target = resolveLinkToId(link, ids);
|
|
48
|
-
if (target)
|
|
49
|
-
refCount.set(target, (refCount.get(target) ?? 0) + 1);
|
|
50
|
-
}
|
|
51
|
-
// Body wikilinks
|
|
52
|
-
for (const link of extractBodyWikilinks(p.body)) {
|
|
53
|
-
const target = resolveLinkToId(`[[${link}]]`, ids);
|
|
54
|
-
if (target)
|
|
55
|
-
refCount.set(target, (refCount.get(target) ?? 0) + 1);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
const out = [];
|
|
59
|
-
for (const [pageId, count] of refCount) {
|
|
60
|
-
if (count === 0) {
|
|
61
|
-
out.push({
|
|
62
|
-
kind: 'orphan',
|
|
63
|
-
severity: 'warn',
|
|
64
|
-
pageId,
|
|
65
|
-
message: `Page "${pageId}" is not referenced by any other page.`,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return out;
|
|
70
|
-
}
|
|
71
|
-
// ─── Dead-link detection ─────────────────────────────────────────
|
|
72
|
-
/**
|
|
73
|
-
* Dead link = wikilink "[[X]]" where X (resolved) is not in the page set.
|
|
74
|
-
*
|
|
75
|
-
* Errors for related[] (frontmatter); warnings for body links (in-flight writing).
|
|
76
|
-
*/
|
|
77
|
-
export function checkDeadLinks(pages) {
|
|
78
|
-
const ids = new Set(pages.map((p) => p.pageId));
|
|
79
|
-
const out = [];
|
|
80
|
-
for (const p of pages) {
|
|
81
|
-
for (const link of p.frontmatter.related) {
|
|
82
|
-
if (!resolveLinkToId(link, ids)) {
|
|
83
|
-
out.push({
|
|
84
|
-
kind: 'dead-link',
|
|
85
|
-
severity: 'error',
|
|
86
|
-
pageId: p.pageId,
|
|
87
|
-
target: link,
|
|
88
|
-
message: `frontmatter related: "${link}" does not resolve to any page.`,
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
for (const link of extractBodyWikilinks(p.body)) {
|
|
93
|
-
if (!resolveLinkToId(`[[${link}]]`, ids)) {
|
|
94
|
-
out.push({
|
|
95
|
-
kind: 'dead-link',
|
|
96
|
-
severity: 'warn',
|
|
97
|
-
pageId: p.pageId,
|
|
98
|
-
target: link,
|
|
99
|
-
message: `body wikilink: "[[${link}]]" does not resolve.`,
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return out;
|
|
105
|
-
}
|
|
106
|
-
// ─── Frontmatter gap detection ───────────────────────────────────
|
|
107
|
-
/**
|
|
108
|
-
* Catches missing soft-required fields the zod schema can't enforce
|
|
109
|
-
* (e.g. empty title, empty TL;DR, all default tags). Schema-level errors
|
|
110
|
-
* are caught at parse time — this is a content sniff.
|
|
111
|
-
*/
|
|
112
|
-
export function checkFrontmatterGaps(pages) {
|
|
113
|
-
const out = [];
|
|
114
|
-
for (const p of pages) {
|
|
115
|
-
const fm = p.frontmatter;
|
|
116
|
-
if (!fm.title.trim()) {
|
|
117
|
-
out.push({
|
|
118
|
-
kind: 'fm-gap',
|
|
119
|
-
severity: 'error',
|
|
120
|
-
pageId: p.pageId,
|
|
121
|
-
target: 'title',
|
|
122
|
-
message: 'frontmatter title is empty.',
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
if (fm.tags.length === 0) {
|
|
126
|
-
out.push({
|
|
127
|
-
kind: 'fm-gap',
|
|
128
|
-
severity: 'warn',
|
|
129
|
-
pageId: p.pageId,
|
|
130
|
-
target: 'tags',
|
|
131
|
-
message: 'frontmatter tags is empty (page won\'t match any skill).',
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
if (!hasTLDR(p.body)) {
|
|
135
|
-
out.push({
|
|
136
|
-
kind: 'fm-gap',
|
|
137
|
-
severity: 'warn',
|
|
138
|
-
pageId: p.pageId,
|
|
139
|
-
target: 'body',
|
|
140
|
-
message: 'body has no `## TL;DR` section (search/preview will use fallback).',
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
return out;
|
|
145
|
-
}
|
|
146
|
-
// ─── Stale source detection ──────────────────────────────────────
|
|
147
|
-
/**
|
|
148
|
-
* Compare manifest's stored sha256 against current file hash on disk.
|
|
149
|
-
* Mismatch = source has drifted since last ingest → its derived pages may be stale.
|
|
150
|
-
*
|
|
151
|
-
* Files that don't exist on disk anymore are flagged as 'stale' too (they should
|
|
152
|
-
* be removed from manifest via finalize).
|
|
153
|
-
*/
|
|
154
|
-
export function checkStaleSources(manifest, repoDir) {
|
|
155
|
-
const out = [];
|
|
156
|
-
for (const [path, entry] of Object.entries(manifest.sources)) {
|
|
157
|
-
const abs = resolve(repoDir, path);
|
|
158
|
-
if (!existsSync(abs)) {
|
|
159
|
-
out.push({
|
|
160
|
-
kind: 'stale',
|
|
161
|
-
severity: 'warn',
|
|
162
|
-
pageId: null,
|
|
163
|
-
target: path,
|
|
164
|
-
message: `Source "${path}" no longer exists. Run \`sps wiki update <project> --finalize\` to clean.`,
|
|
165
|
-
});
|
|
166
|
-
continue;
|
|
167
|
-
}
|
|
168
|
-
const currentHash = tryHashFile(abs);
|
|
169
|
-
if (currentHash && currentHash !== entry.sha256) {
|
|
170
|
-
// Best effort: include affected pages
|
|
171
|
-
const affected = entry.pages.length > 0 ? ` (affects: ${entry.pages.join(', ')})` : '';
|
|
172
|
-
out.push({
|
|
173
|
-
kind: 'stale',
|
|
174
|
-
severity: 'warn',
|
|
175
|
-
pageId: null,
|
|
176
|
-
target: path,
|
|
177
|
-
message: `Source "${path}" has changed since ingest${affected}.`,
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
return out;
|
|
182
|
-
}
|
|
183
|
-
// ─── Helpers ──────────────────────────────────────────────────────
|
|
184
|
-
/**
|
|
185
|
-
* Resolve a "[[X]]" or "[[type/X]]" wikilink against the known pageId set.
|
|
186
|
-
*
|
|
187
|
-
* Strategy:
|
|
188
|
-
* - "[[type/X]]" → look up exact pageId
|
|
189
|
-
* - "[[X]]" → look up any pageId ending with "/X" (any type matches)
|
|
190
|
-
*
|
|
191
|
-
* Returns the resolved pageId, or null if unresolvable.
|
|
192
|
-
*/
|
|
193
|
-
export function resolveLinkToId(wikilink, ids) {
|
|
194
|
-
const m = wikilink.match(/^\[\[([^[\]]+)\]\]$/);
|
|
195
|
-
if (!m)
|
|
196
|
-
return null;
|
|
197
|
-
const target = m[1].trim();
|
|
198
|
-
if (target.includes('/')) {
|
|
199
|
-
return ids.has(target) ? target : null;
|
|
200
|
-
}
|
|
201
|
-
// No prefix — find any pageId whose title matches
|
|
202
|
-
for (const id of ids) {
|
|
203
|
-
const slash = id.lastIndexOf('/');
|
|
204
|
-
if (slash >= 0 && id.slice(slash + 1) === target)
|
|
205
|
-
return id;
|
|
206
|
-
}
|
|
207
|
-
return null;
|
|
208
|
-
}
|
|
209
|
-
const BODY_LINK_RE = /\[\[([^[\]]+)\]\]/g;
|
|
210
|
-
export function extractBodyWikilinks(body) {
|
|
211
|
-
const out = [];
|
|
212
|
-
for (const m of body.matchAll(BODY_LINK_RE)) {
|
|
213
|
-
out.push(m[1].trim());
|
|
214
|
-
}
|
|
215
|
-
return out;
|
|
216
|
-
}
|
|
217
|
-
const TLDR_RE = /^##\s+TL;DR\b/m;
|
|
218
|
-
function hasTLDR(body) {
|
|
219
|
-
return TLDR_RE.test(body);
|
|
220
|
-
}
|
|
221
|
-
function summarize(issues) {
|
|
222
|
-
const counts = {
|
|
223
|
-
orphan: 0,
|
|
224
|
-
'dead-link': 0,
|
|
225
|
-
'fm-gap': 0,
|
|
226
|
-
stale: 0,
|
|
227
|
-
};
|
|
228
|
-
let errorCount = 0;
|
|
229
|
-
let warnCount = 0;
|
|
230
|
-
for (const i of issues) {
|
|
231
|
-
counts[i.kind] += 1;
|
|
232
|
-
if (i.severity === 'error')
|
|
233
|
-
errorCount += 1;
|
|
234
|
-
else
|
|
235
|
-
warnCount += 1;
|
|
236
|
-
}
|
|
237
|
-
return { issues: [...issues], counts, errorCount, warnCount };
|
|
238
|
-
}
|
|
239
|
-
// ─── Mtime helper (used by status command) ────────────────────────
|
|
240
|
-
/**
|
|
241
|
-
* Compare source mtime vs page mtime. Returns paths whose source is newer.
|
|
242
|
-
*
|
|
243
|
-
* Best-effort — file mtime precision varies (ext4 ns vs HFS+ 1s); we use a
|
|
244
|
-
* 60s threshold to avoid false positives.
|
|
245
|
-
*/
|
|
246
|
-
export function findOutdatedPages(manifest, pages, repoDir, thresholdMs = 60_000) {
|
|
247
|
-
const out = [];
|
|
248
|
-
const pageMtimeById = new Map();
|
|
249
|
-
for (const p of pages) {
|
|
250
|
-
try {
|
|
251
|
-
pageMtimeById.set(p.pageId, statSync(p.filePath).mtime);
|
|
252
|
-
}
|
|
253
|
-
catch {
|
|
254
|
-
// ignore
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
for (const [sourcePath, entry] of Object.entries(manifest.sources)) {
|
|
258
|
-
if (entry.pages.length === 0)
|
|
259
|
-
continue;
|
|
260
|
-
let sourceMtime;
|
|
261
|
-
try {
|
|
262
|
-
sourceMtime = statSync(resolve(repoDir, sourcePath)).mtime;
|
|
263
|
-
}
|
|
264
|
-
catch {
|
|
265
|
-
continue;
|
|
266
|
-
}
|
|
267
|
-
const outdated = [];
|
|
268
|
-
for (const pid of entry.pages) {
|
|
269
|
-
const pmtime = pageMtimeById.get(pid);
|
|
270
|
-
if (!pmtime)
|
|
271
|
-
continue;
|
|
272
|
-
if (sourceMtime.getTime() - pmtime.getTime() > thresholdMs)
|
|
273
|
-
outdated.push(pid);
|
|
274
|
-
}
|
|
275
|
-
if (outdated.length > 0)
|
|
276
|
-
out.push({ sourcePath, pageIds: outdated, sourceMtime });
|
|
277
|
-
}
|
|
278
|
-
return out;
|
|
279
|
-
}
|
|
280
|
-
//# sourceMappingURL=linter.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"linter.js","sourceRoot":"","sources":["../../../src/core/wiki/linter.ts"],"names":[],"mappings":"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"}
|
package/dist/core/wiki/log.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export type LogAction = 'ingest' | 'write' | 'update' | 'lint' | 'init' | 'add' | 'delete';
|
|
2
|
-
export interface LogEntry {
|
|
3
|
-
action: LogAction;
|
|
4
|
-
/** 时间戳;缺省 now */
|
|
5
|
-
timestamp?: string;
|
|
6
|
-
/** Source 路径或 page id 或简短描述 */
|
|
7
|
-
target: string;
|
|
8
|
-
/** 一句话描述(≤ 100 字符) */
|
|
9
|
-
message: string;
|
|
10
|
-
/** 受影响的 page id 列表(可选) */
|
|
11
|
-
pages?: readonly string[];
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* 在 log.md 顶部插入一条 entry。
|
|
15
|
-
*
|
|
16
|
-
* - 文件不存在:创建带 header
|
|
17
|
-
* - 已有内容:保留最近 MAX_ENTRIES 条(旧的截掉)
|
|
18
|
-
*/
|
|
19
|
-
export declare function appendLog(repoDir: string, entry: LogEntry): void;
|
|
20
|
-
/**
|
|
21
|
-
* 读 log.md 全文。文件不存在返默认 header。
|
|
22
|
-
*/
|
|
23
|
-
export declare function readLog(repoDir: string): string;
|
|
24
|
-
//# sourceMappingURL=log.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../../src/core/wiki/log.ts"],"names":[],"mappings":"AA+BA,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE3F,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,SAAS,CAAC;IAClB,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI,CAwChE;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQ/C"}
|
package/dist/core/wiki/log.js
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module core/wiki/log
|
|
3
|
-
* @description Wiki .log.md:操作时间序列(per-instance,gitignored)
|
|
4
|
-
*
|
|
5
|
-
* @layer core
|
|
6
|
-
*
|
|
7
|
-
* 借鉴 claude-obsidian 的 wiki/log.md:每次 ingest / write / lint 在文件
|
|
8
|
-
* 顶部追加一条事件,便于 Worker / 用户回看 "最近 wiki 怎么变的"。
|
|
9
|
-
*
|
|
10
|
-
* 实现选择:
|
|
11
|
-
* - 新条目**顶部追加**(最新在最前),方便 Worker 默认读前几条就看到 latest
|
|
12
|
-
* - hard cap 500 条(~5000 行),超过截尾——log 不是 audit,旧条目用 git/hot.md 找
|
|
13
|
-
* - frontmatter 固定(type=meta),不需要解析
|
|
14
|
-
*/
|
|
15
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
16
|
-
import { dirname } from 'node:path';
|
|
17
|
-
import { wikiLogFile } from '../../shared/wikiPaths.js';
|
|
18
|
-
const HEADER = `---
|
|
19
|
-
type: meta
|
|
20
|
-
title: Wiki Operation Log
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
# Wiki Operation Log
|
|
24
|
-
|
|
25
|
-
`;
|
|
26
|
-
const MAX_ENTRIES = 500;
|
|
27
|
-
/**
|
|
28
|
-
* 在 log.md 顶部插入一条 entry。
|
|
29
|
-
*
|
|
30
|
-
* - 文件不存在:创建带 header
|
|
31
|
-
* - 已有内容:保留最近 MAX_ENTRIES 条(旧的截掉)
|
|
32
|
-
*/
|
|
33
|
-
export function appendLog(repoDir, entry) {
|
|
34
|
-
const path = wikiLogFile(repoDir);
|
|
35
|
-
const ts = entry.timestamp ?? new Date().toISOString();
|
|
36
|
-
const block = renderEntry({ ...entry, timestamp: ts });
|
|
37
|
-
let existing;
|
|
38
|
-
if (existsSync(path)) {
|
|
39
|
-
try {
|
|
40
|
-
existing = readFileSync(path, 'utf-8');
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
existing = HEADER;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
existing = HEADER;
|
|
48
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
49
|
-
}
|
|
50
|
-
// 拆 header + 旧 entries
|
|
51
|
-
const headerEnd = existing.indexOf('# Wiki Operation Log\n');
|
|
52
|
-
let header;
|
|
53
|
-
let entries;
|
|
54
|
-
if (headerEnd === -1) {
|
|
55
|
-
header = HEADER;
|
|
56
|
-
entries = '';
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
const afterHeader = existing.indexOf('\n', headerEnd) + 1;
|
|
60
|
-
header = existing.slice(0, afterHeader + 1);
|
|
61
|
-
entries = existing.slice(afterHeader + 1);
|
|
62
|
-
}
|
|
63
|
-
// 拆现有 entries(按 ## 开头分组),去除可能的 trailing whitespace
|
|
64
|
-
const oldBlocks = entries.split(/(?=^## )/m).filter((b) => b.trim().length > 0);
|
|
65
|
-
// 顶部插入新 block
|
|
66
|
-
const updatedBlocks = [block, ...oldBlocks];
|
|
67
|
-
// cap 数量
|
|
68
|
-
const truncated = updatedBlocks.slice(0, MAX_ENTRIES);
|
|
69
|
-
const final = header + truncated.join('') + (truncated.length === MAX_ENTRIES ? '\n…(older entries truncated)\n' : '');
|
|
70
|
-
writeFileSync(path, final, { encoding: 'utf-8', mode: 0o644 });
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* 读 log.md 全文。文件不存在返默认 header。
|
|
74
|
-
*/
|
|
75
|
-
export function readLog(repoDir) {
|
|
76
|
-
const path = wikiLogFile(repoDir);
|
|
77
|
-
if (!existsSync(path))
|
|
78
|
-
return HEADER;
|
|
79
|
-
try {
|
|
80
|
-
return readFileSync(path, 'utf-8');
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
return HEADER;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
// ─── Render ───────────────────────────────────────────────────────
|
|
87
|
-
/**
|
|
88
|
-
* 单条 log entry 渲染:
|
|
89
|
-
*
|
|
90
|
-
* ```md
|
|
91
|
-
* ## 2026-04-27T18:30:00Z · update · src/X.ts
|
|
92
|
-
* 增量 ingest:3 个文件改动
|
|
93
|
-
* - Pages: [[modules/X]], [[lessons/Stop Hook Race]]
|
|
94
|
-
* ```
|
|
95
|
-
*/
|
|
96
|
-
function renderEntry(entry) {
|
|
97
|
-
const lines = [];
|
|
98
|
-
lines.push(`## ${entry.timestamp} · ${entry.action} · ${entry.target}`);
|
|
99
|
-
lines.push(entry.message.trim());
|
|
100
|
-
if (entry.pages && entry.pages.length > 0) {
|
|
101
|
-
const wikilinks = entry.pages.map((p) => `[[${p}]]`).join(', ');
|
|
102
|
-
lines.push(`- Pages: ${wikilinks}`);
|
|
103
|
-
}
|
|
104
|
-
lines.push('');
|
|
105
|
-
return lines.join('\n');
|
|
106
|
-
}
|
|
107
|
-
//# sourceMappingURL=log.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"log.js","sourceRoot":"","sources":["../../../src/core/wiki/log.ts"],"names":[],"mappings":"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"}
|