@tznthou/ccrecall 0.4.8 → 0.5.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.
Files changed (49) hide show
  1. package/README.md +28 -52
  2. package/README_ZH.md +28 -53
  3. package/dist/api/routes.d.ts +0 -10
  4. package/dist/api/routes.d.ts.map +1 -1
  5. package/dist/api/routes.js +4 -354
  6. package/dist/api/routes.js.map +1 -1
  7. package/dist/api/server.js +3 -3
  8. package/dist/api/server.js.map +1 -1
  9. package/dist/core/database.d.ts +14 -49
  10. package/dist/core/database.d.ts.map +1 -1
  11. package/dist/core/database.js +104 -225
  12. package/dist/core/database.js.map +1 -1
  13. package/dist/core/indexer.d.ts.map +1 -1
  14. package/dist/core/indexer.js +0 -1
  15. package/dist/core/indexer.js.map +1 -1
  16. package/dist/core/maintenance-coordinator.d.ts +3 -9
  17. package/dist/core/maintenance-coordinator.d.ts.map +1 -1
  18. package/dist/core/maintenance-coordinator.js +4 -24
  19. package/dist/core/maintenance-coordinator.js.map +1 -1
  20. package/dist/core/summarizer.d.ts.map +1 -1
  21. package/dist/core/summarizer.js +0 -22
  22. package/dist/core/summarizer.js.map +1 -1
  23. package/dist/core/types.d.ts +0 -87
  24. package/dist/core/types.d.ts.map +1 -1
  25. package/dist/core/types.js.map +1 -1
  26. package/dist/index.js +0 -16
  27. package/dist/index.js.map +1 -1
  28. package/hooks/README.md +2 -2
  29. package/package.json +2 -1
  30. package/scripts/backfill-memory-topics.ts +29 -0
  31. package/scripts/extraction-prompt.md +96 -0
  32. package/scripts/post-session-extract.sh +290 -0
  33. package/scripts/recall-hit-rate-report.ts +91 -0
  34. package/dist/cli/journal.d.ts +0 -11
  35. package/dist/cli/journal.d.ts.map +0 -1
  36. package/dist/cli/journal.js +0 -111
  37. package/dist/cli/journal.js.map +0 -1
  38. package/dist/core/lint.d.ts +0 -17
  39. package/dist/core/lint.d.ts.map +0 -1
  40. package/dist/core/lint.js +0 -51
  41. package/dist/core/lint.js.map +0 -1
  42. package/dist/core/outcome-extractor.d.ts +0 -6
  43. package/dist/core/outcome-extractor.d.ts.map +0 -1
  44. package/dist/core/outcome-extractor.js +0 -39
  45. package/dist/core/outcome-extractor.js.map +0 -1
  46. package/dist/core/outcome-scorer.d.ts +0 -8
  47. package/dist/core/outcome-scorer.d.ts.map +0 -1
  48. package/dist/core/outcome-scorer.js +0 -103
  49. package/dist/core/outcome-scorer.js.map +0 -1
@@ -1,11 +0,0 @@
1
- export interface PromoteOptions {
2
- type?: string;
3
- confidence?: number;
4
- }
5
- export declare function parsePromoteFlags(args: string[]): {
6
- idStr?: string;
7
- opts: PromoteOptions;
8
- };
9
- export declare function runPromote(idStr: string | undefined, opts?: PromoteOptions): Promise<number>;
10
- export declare function runReject(idStr: string | undefined): Promise<number>;
11
- //# sourceMappingURL=journal.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"journal.d.ts","sourceRoot":"","sources":["../../src/cli/journal.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AA6CD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,cAAc,CAAA;CAAE,CAe1F;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAwBtG;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAwB1E"}
@@ -1,111 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- import http from 'node:http';
3
- const DEFAULT_PORT = 7749;
4
- function getPort() {
5
- const raw = parseInt(process.env.CCRECALL_PORT ?? String(DEFAULT_PORT), 10);
6
- return Number.isFinite(raw) && raw > 0 && raw <= 65535 ? raw : DEFAULT_PORT;
7
- }
8
- function postJson(reqPath, payload) {
9
- return new Promise((resolve, reject) => {
10
- const port = getPort();
11
- const data = JSON.stringify(payload);
12
- const req = http.request({
13
- hostname: '127.0.0.1', port, path: reqPath, method: 'POST',
14
- headers: {
15
- 'Content-Type': 'application/json',
16
- 'Content-Length': Buffer.byteLength(data),
17
- },
18
- }, (res) => {
19
- const chunks = [];
20
- res.on('data', (chunk) => chunks.push(chunk));
21
- res.on('end', () => {
22
- try {
23
- const parsed = JSON.parse(Buffer.concat(chunks).toString());
24
- resolve({ status: res.statusCode ?? 0, body: parsed });
25
- }
26
- catch (err) {
27
- reject(err);
28
- }
29
- });
30
- res.on('error', reject);
31
- });
32
- req.on('error', (err) => {
33
- if (err.code === 'ECONNREFUSED') {
34
- reject(new Error(`Cannot connect to daemon on 127.0.0.1:${port}. Is ccRecall daemon running?`));
35
- }
36
- else {
37
- reject(err);
38
- }
39
- });
40
- req.write(data);
41
- req.end();
42
- });
43
- }
44
- export function parsePromoteFlags(args) {
45
- let idStr;
46
- const opts = {};
47
- for (let i = 0; i < args.length; i++) {
48
- const a = args[i];
49
- if (a === '--type' && i + 1 < args.length) {
50
- opts.type = args[++i];
51
- }
52
- else if (a === '--confidence' && i + 1 < args.length) {
53
- const c = parseFloat(args[++i]);
54
- if (Number.isFinite(c))
55
- opts.confidence = c;
56
- }
57
- else if (!a.startsWith('--') && idStr === undefined) {
58
- idStr = a;
59
- }
60
- }
61
- return { idStr, opts };
62
- }
63
- export async function runPromote(idStr, opts = {}) {
64
- if (!idStr) {
65
- console.error('Usage: ccmem promote <journal_id> [--type discovery|decision|...] [--confidence 0.7]');
66
- return 1;
67
- }
68
- const id = parseInt(idStr, 10);
69
- if (!Number.isInteger(id) || id <= 0) {
70
- console.error(`Invalid id: ${idStr}`);
71
- return 1;
72
- }
73
- try {
74
- const { status, body } = await postJson('/journal/promote', { id, type: opts.type, confidence: opts.confidence });
75
- if (status === 200 && body.ok) {
76
- console.log(`Promoted journal #${body.journalId} → memory #${body.memoryId}`);
77
- return 0;
78
- }
79
- console.error(`promote failed (${status}): ${body.error ?? 'unknown error'}`);
80
- return 1;
81
- }
82
- catch (err) {
83
- console.error(err.message);
84
- return 1;
85
- }
86
- }
87
- export async function runReject(idStr) {
88
- if (!idStr) {
89
- console.error('Usage: ccmem reject <journal_id>');
90
- return 1;
91
- }
92
- const id = parseInt(idStr, 10);
93
- if (!Number.isInteger(id) || id <= 0) {
94
- console.error(`Invalid id: ${idStr}`);
95
- return 1;
96
- }
97
- try {
98
- const { status, body } = await postJson('/journal/reject', { id });
99
- if (status === 200 && body.ok) {
100
- console.log(`Rejected journal #${body.journalId} — expires ${body.expiresAt}`);
101
- return 0;
102
- }
103
- console.error(`reject failed (${status}): ${body.error ?? 'unknown error'}`);
104
- return 1;
105
- }
106
- catch (err) {
107
- console.error(err.message);
108
- return 1;
109
- }
110
- }
111
- //# sourceMappingURL=journal.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"journal.js","sourceRoot":"","sources":["../../src/cli/journal.ts"],"names":[],"mappings":"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"}
@@ -1,17 +0,0 @@
1
- import type { Database } from './database.js';
2
- export type LintKind = 'orphan' | 'stale';
3
- export interface LintWarning {
4
- memoryId: number;
5
- kind: LintKind;
6
- details: string;
7
- }
8
- export interface LintReport {
9
- warnings: LintWarning[];
10
- counts: {
11
- orphan: number;
12
- stale: number;
13
- total: number;
14
- };
15
- }
16
- export declare function runLint(db: Database): LintReport;
17
- //# sourceMappingURL=lint.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/core/lint.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAuB7C,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAA;AAEzC,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,QAAQ,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB,MAAM,EAAE;QACN,MAAM,EAAE,MAAM,CAAA;QACd,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;CACF;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,QAAQ,GAAG,UAAU,CAgChD"}
package/dist/core/lint.js DELETED
@@ -1,51 +0,0 @@
1
- /**
2
- * Phase 4d: memory health lint — emits warnings, never mutates.
3
- *
4
- * Two checks:
5
- * - `orphan`: memory.session_id references a session row that no longer exists.
6
- * Usually a manual scrub of ~/.claude/projects, but also a symptom of a
7
- * partial reindex. The compression auto-delete path needs `session_id IS
8
- * NOT NULL`, so orphans accumulate silently without this warning.
9
- * - `stale`: memory has effectively zero residual confidence, has never been
10
- * accessed, and is older than 90 days. Compression would already have
11
- * demoted it to L2; lint surfaces the long-dead tail so the user can
12
- * decide whether to purge.
13
- *
14
- * Deliberately on-demand (no persisted `lint_warnings` table). Lint output is
15
- * always fresh against the current decay formula and avoids a separate write
16
- * path that could drift from the source of truth.
17
- */
18
- const STALE_EFFECTIVE_CONFIDENCE = 0.1;
19
- const STALE_AGE_DAYS = 90;
20
- export function runLint(db) {
21
- const orphans = db.getOrphanMemoryIds();
22
- const stales = db.getStaleMemoryIds({
23
- effectiveConfidence: STALE_EFFECTIVE_CONFIDENCE,
24
- ageDays: STALE_AGE_DAYS,
25
- });
26
- const warnings = [];
27
- for (const o of orphans) {
28
- warnings.push({
29
- memoryId: o.memoryId,
30
- kind: 'orphan',
31
- details: `session ${o.sessionId} no longer exists in sessions table`,
32
- });
33
- }
34
- for (const s of stales) {
35
- warnings.push({
36
- memoryId: s.memoryId,
37
- kind: 'stale',
38
- details: `age=${s.ageDays.toFixed(1)}d effective=${s.effectiveConfidence.toFixed(4)} access=0`,
39
- });
40
- }
41
- warnings.sort((a, b) => a.memoryId - b.memoryId);
42
- return {
43
- warnings,
44
- counts: {
45
- orphan: orphans.length,
46
- stale: stales.length,
47
- total: warnings.length,
48
- },
49
- };
50
- }
51
- //# sourceMappingURL=lint.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"lint.js","sourceRoot":"","sources":["../../src/core/lint.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,0BAA0B,GAAG,GAAG,CAAA;AACtC,MAAM,cAAc,GAAG,EAAE,CAAA;AAmBzB,MAAM,UAAU,OAAO,CAAC,EAAY;IAClC,MAAM,OAAO,GAAG,EAAE,CAAC,kBAAkB,EAAE,CAAA;IACvC,MAAM,MAAM,GAAG,EAAE,CAAC,iBAAiB,CAAC;QAClC,mBAAmB,EAAE,0BAA0B;QAC/C,OAAO,EAAE,cAAc;KACxB,CAAC,CAAA;IAEF,MAAM,QAAQ,GAAkB,EAAE,CAAA;IAClC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC;YACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,WAAW,CAAC,CAAC,SAAS,qCAAqC;SACrE,CAAC,CAAA;IACJ,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,QAAQ,CAAC,IAAI,CAAC;YACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW;SAC/F,CAAC,CAAA;IACJ,CAAC;IACD,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAA;IAEhD,OAAO;QACL,QAAQ;QACR,MAAM,EAAE;YACN,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,KAAK,EAAE,MAAM,CAAC,MAAM;YACpB,KAAK,EAAE,QAAQ,CAAC,MAAM;SACvB;KACF,CAAA;AACH,CAAC"}
@@ -1,6 +0,0 @@
1
- import type { ParsedLine } from './types.js';
2
- export interface OutcomeExtraction {
3
- candidateText: string | null;
4
- }
5
- export declare function extractOutcome(messages: ParsedLine[]): OutcomeExtraction;
6
- //# sourceMappingURL=outcome-extractor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"outcome-extractor.d.ts","sourceRoot":"","sources":["../../src/core/outcome-extractor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAQ5C,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;CAC7B;AAUD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,iBAAiB,CAExE"}
@@ -1,39 +0,0 @@
1
- import { scoreKnowledgeBearing, isProcessReport } from './outcome-scorer.js';
2
- const SUBSTANTIAL_MIN_CHARS = 200;
3
- const STRUCTURAL_RES = [
4
- /^#{1,6}\s/m, // markdown header
5
- /```/, // fenced code
6
- /^[-*]\s/m, // bullet list
7
- /\[\s?[xX ]?\s?\]/, // checkbox
8
- ];
9
- export function extractOutcome(messages) {
10
- return { candidateText: pickLastSubstantialAssistant(messages) };
11
- }
12
- function pickLastSubstantialAssistant(messages) {
13
- for (let i = messages.length - 1; i >= 0; i--) {
14
- const msg = messages[i];
15
- if (msg.role !== 'assistant')
16
- continue;
17
- const text = msg.contentText?.trim();
18
- if (!text)
19
- continue;
20
- if (isProcessReport(text))
21
- continue;
22
- if (isSubstantial(text))
23
- return text;
24
- }
25
- return null;
26
- }
27
- // length / markdown 結構是廉價 fast-path;短而高 signal 的純文字結語(例「Root cause:
28
- // x.ts:42。495/495 tests pass.」、「我們決定改用 SQLite」)走 scorer 兜底。
29
- // v0.3.0 (#21 P1): 門檻從 score >= 2 降為 score >= 1。理由——P1 移除 persistence
30
- // gate 後, score 0/1 也應進 journal 留作 candidate, walk-back 上游不該預先濾掉。
31
- // score=0 (含 noise / process-report 短路) 仍擋, 不會引入空字串/純 ack 雜訊。
32
- function isSubstantial(text) {
33
- if (text.length >= SUBSTANTIAL_MIN_CHARS)
34
- return true;
35
- if (STRUCTURAL_RES.some(p => p.test(text)))
36
- return true;
37
- return scoreKnowledgeBearing(text).score >= 1;
38
- }
39
- //# sourceMappingURL=outcome-extractor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"outcome-extractor.js","sourceRoot":"","sources":["../../src/core/outcome-extractor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAW5E,MAAM,qBAAqB,GAAG,GAAG,CAAA;AACjC,MAAM,cAAc,GAA0B;IAC5C,YAAY,EAAU,kBAAkB;IACxC,KAAK,EAAiB,cAAc;IACpC,UAAU,EAAY,cAAc;IACpC,kBAAkB,EAAI,WAAW;CAClC,CAAA;AAED,MAAM,UAAU,cAAc,CAAC,QAAsB;IACnD,OAAO,EAAE,aAAa,EAAE,4BAA4B,CAAC,QAAQ,CAAC,EAAE,CAAA;AAClE,CAAC;AAED,SAAS,4BAA4B,CAAC,QAAsB;IAC1D,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;QACvB,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW;YAAE,SAAQ;QACtC,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,IAAI,EAAE,CAAA;QACpC,IAAI,CAAC,IAAI;YAAE,SAAQ;QACnB,IAAI,eAAe,CAAC,IAAI,CAAC;YAAE,SAAQ;QACnC,IAAI,aAAa,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAA;IACtC,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,oEAAoE;AACpE,4DAA4D;AAC5D,sEAAsE;AACtE,kEAAkE;AAClE,8DAA8D;AAC9D,SAAS,aAAa,CAAC,IAAY;IACjC,IAAI,IAAI,CAAC,MAAM,IAAI,qBAAqB;QAAE,OAAO,IAAI,CAAA;IACrD,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAA;IACvD,OAAO,qBAAqB,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAA;AAC/C,CAAC"}
@@ -1,8 +0,0 @@
1
- export declare const KNOWLEDGE_THRESHOLD = 2;
2
- export interface ScoreResult {
3
- score: number;
4
- reasons: string[];
5
- }
6
- export declare function scoreKnowledgeBearing(text: string): ScoreResult;
7
- export declare function isProcessReport(text: string): boolean;
8
- //# sourceMappingURL=outcome-scorer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"outcome-scorer.d.ts","sourceRoot":"","sources":["../../src/core/outcome-scorer.ts"],"names":[],"mappings":"AA2FA,eAAO,MAAM,mBAAmB,IAAI,CAAA;AAEpC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAc/D;AAOD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGrD"}
@@ -1,103 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // 對 assistant text 做 knowledge-bearing scoring。設計意圖(Codex):require either one
3
- // strong structural signal or multiple weak semantic signals — categories 多樣性才能體現
4
- // asymmetry,砍 categories 等於退化為 boolean × N。
5
- //
6
- // 5 categories(decision-language / impl-facts / constraints / cause-effect / validation),
7
- // 每類起手 1-3 個 high-signal patterns(保守先發);threshold >= 2 hardcoded。
8
- // 每類的 patterns 數量會在 commit 1 corpus(線上 89 筆 + 10 outcome session)實測後決定擴增,
9
- // 避免上線一發就靠拍腦袋。
10
- //
11
- // 內部 noise short-circuit:assistant 端短 ack token(done / 完成 / ok)單獨命中時直接歸 0,
12
- // 避免被下面的 weak-signal 累計湊到 threshold。Pattern 採 anchored-only 設計,長文本不誤殺。
13
- const NOISE_MAX_LEN = 50;
14
- // Process-report headers are short (save-t reports are <2KB in practice).
15
- // Length gate prevents regex linear-scan on megabyte-scale assistant text.
16
- const PROCESS_REPORT_MAX_LEN = 5000;
17
- const NOISE_RES = [
18
- /^\s*(?:done|完成|處理好了|實作好了|搞定|fixed|implemented|ok|okay)\s*[.!。!]*\s*$/i,
19
- /^\s*(?:對|不對|是的|沒錯|好的|yes|no|yep|nope)\s*[.!。!]*\s*$/i,
20
- ];
21
- // dogfood corpus 實證(2026-05-06): 39 筆 v=2 committed/tested sessions 全部 sub-threshold,
22
- // 因為 last substantial assistant 抓到 save-t 收尾報告(process meta)而非真實 outcome。
23
- // Anchor 在開頭(^),長文本 mid-text 提及 save-t 不誤殺。
24
- const PROCESS_REPORT_RES = [
25
- /^[#\s💾🟢✅_*-]*\/?save[\s-]?t(?:\s*[::]\s*|\s+)(?:完成|流程完整|完整|done|finished|completed?)/iu,
26
- // #27: save-t skill output may open with CJK verb form 「存檔完成」 instead of /save-t literal.
27
- // Lookahead requires save-t process-report signal within 80 chars OR 「## 更新摘要/清單」 heading,
28
- // narrow enough to let real outcome openers (e.g. 「存檔完成,但 root cause 是 ...」) pass through.
29
- /^[#\s💾🟢✅_*-]*存檔完成\s*[—,,.。::!!](?=(?:[^\n]{0,80}(?:\/compact|結束 session|雙寫同步)|\s*\n\s*##\s*(?:更新摘要|更新清單)))/u,
30
- ];
31
- const DECISION_LANGUAGE = {
32
- name: 'decision-language',
33
- patterns: [
34
- /(?:我們|本案)?(?:決議|決定|拍板|定案)/,
35
- /\b(?:we|i)\s+(?:decided|chose|opted)\b/i,
36
- /(?:採|改|換)成\b/,
37
- ],
38
- };
39
- const IMPL_FACTS = {
40
- name: 'impl-facts',
41
- patterns: [
42
- /[`\w./_-]+\.(?:tsx|ts|jsx|js|py|go|rs|sql|md):\d+/,
43
- /\b(?:added|created|wrote|implemented)\s+[`\w./_-]+\.(?:tsx|ts|jsx|js|py|go|rs|sql|md)\b/i,
44
- /\bcommit\s+[a-f0-9]{6,}\b/i,
45
- ],
46
- };
47
- const CONSTRAINTS = {
48
- name: 'constraints',
49
- patterns: [
50
- /(?:不可|禁止|必須|絕不|不能)\S/,
51
- /\b(?:must not|never|cannot|forbidden|invariant)\b/i,
52
- ],
53
- };
54
- const CAUSE_EFFECT = {
55
- name: 'cause-effect',
56
- patterns: [
57
- /(?:因為|是因為|根本原因|root cause|原因是)/,
58
- /\b(?:because|due to|root cause|caused by)\b/i,
59
- ],
60
- };
61
- const VALIDATION = {
62
- name: 'validation',
63
- patterns: [
64
- /\d+\/\d+\s+(?:tests?|綠|passing|pass)/i,
65
- /\b(?:verified|all tests pass|all green)\b/i,
66
- /(?:驗證(?:過|完|通過)|測試(?:過|完|通過|綠))/,
67
- ],
68
- };
69
- const ALL_CATEGORIES = [
70
- DECISION_LANGUAGE,
71
- IMPL_FACTS,
72
- CONSTRAINTS,
73
- CAUSE_EFFECT,
74
- VALIDATION,
75
- ];
76
- export const KNOWLEDGE_THRESHOLD = 2;
77
- export function scoreKnowledgeBearing(text) {
78
- const trimmed = text.trim();
79
- if (isAssistantNoise(trimmed))
80
- return { score: 0, reasons: ['noise'] };
81
- if (isProcessReport(trimmed))
82
- return { score: 0, reasons: ['process-report'] };
83
- const reasons = [];
84
- let score = 0;
85
- for (const cat of ALL_CATEGORIES) {
86
- if (cat.patterns.some(p => p.test(trimmed))) {
87
- score++;
88
- reasons.push(cat.name);
89
- }
90
- }
91
- return { score, reasons };
92
- }
93
- function isAssistantNoise(text) {
94
- if (text.length > NOISE_MAX_LEN)
95
- return false;
96
- return NOISE_RES.some(p => p.test(text));
97
- }
98
- export function isProcessReport(text) {
99
- if (text.length > PROCESS_REPORT_MAX_LEN)
100
- return false;
101
- return PROCESS_REPORT_RES.some(p => p.test(text));
102
- }
103
- //# sourceMappingURL=outcome-scorer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"outcome-scorer.js","sourceRoot":"","sources":["../../src/core/outcome-scorer.ts"],"names":[],"mappings":"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"}