homegraph 1.1.2 → 1.1.3
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/LICENSE +21 -21
- package/README.md +243 -243
- package/dist/bin/homegraph.js +371 -9
- package/dist/bin/homegraph.js.map +1 -1
- package/dist/db/migrations.js +18 -18
- package/dist/db/queries.js +140 -140
- package/dist/db/schema.sql +152 -152
- package/dist/directory.js +5 -5
- package/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
- package/dist/installer/instructions-template.js +9 -9
- package/dist/installer/targets/shared.d.ts +5 -6
- package/dist/installer/targets/shared.d.ts.map +1 -1
- package/dist/installer/targets/shared.js +5 -6
- package/dist/installer/targets/shared.js.map +1 -1
- package/dist/mcp/liveness-watchdog.js +16 -16
- package/dist/mcp/server-instructions.js +69 -69
- package/dist/mcp/tools.d.ts +17 -4
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +192 -22
- package/dist/mcp/tools.js.map +1 -1
- package/dist/reasoning/reasoner.js +32 -32
- package/dist/spec/config.d.ts +43 -0
- package/dist/spec/config.d.ts.map +1 -0
- package/dist/spec/config.js +275 -0
- package/dist/spec/config.js.map +1 -0
- package/dist/spec/db/commit-node.d.ts +23 -0
- package/dist/spec/db/commit-node.d.ts.map +1 -0
- package/dist/spec/db/commit-node.js +62 -0
- package/dist/spec/db/commit-node.js.map +1 -0
- package/dist/spec/db/fragment-node.d.ts +23 -0
- package/dist/spec/db/fragment-node.d.ts.map +1 -0
- package/dist/spec/db/fragment-node.js +120 -0
- package/dist/spec/db/fragment-node.js.map +1 -0
- package/dist/spec/db/fts.d.ts +60 -0
- package/dist/spec/db/fts.d.ts.map +1 -0
- package/dist/spec/db/fts.js +285 -0
- package/dist/spec/db/fts.js.map +1 -0
- package/dist/spec/db/index.d.ts +13 -0
- package/dist/spec/db/index.d.ts.map +1 -0
- package/dist/spec/db/index.js +50 -0
- package/dist/spec/db/index.js.map +1 -0
- package/dist/spec/db/relations.d.ts +55 -0
- package/dist/spec/db/relations.d.ts.map +1 -0
- package/dist/spec/db/relations.js +158 -0
- package/dist/spec/db/relations.js.map +1 -0
- package/dist/spec/db/schema.d.ts +30 -0
- package/dist/spec/db/schema.d.ts.map +1 -0
- package/dist/spec/db/schema.js +87 -0
- package/dist/spec/db/schema.js.map +1 -0
- package/dist/spec/db/schema.sql +107 -0
- package/dist/spec/db/spec-node.d.ts +41 -0
- package/dist/spec/db/spec-node.d.ts.map +1 -0
- package/dist/spec/db/spec-node.js +114 -0
- package/dist/spec/db/spec-node.js.map +1 -0
- package/dist/spec/evolve/impact-locator.d.ts +13 -0
- package/dist/spec/evolve/impact-locator.d.ts.map +1 -0
- package/dist/spec/evolve/impact-locator.js +25 -0
- package/dist/spec/evolve/impact-locator.js.map +1 -0
- package/dist/spec/evolve/llm-client.d.ts +50 -0
- package/dist/spec/evolve/llm-client.d.ts.map +1 -0
- package/dist/spec/evolve/llm-client.js +176 -0
- package/dist/spec/evolve/llm-client.js.map +1 -0
- package/dist/spec/evolve/logic-checker.d.ts +12 -0
- package/dist/spec/evolve/logic-checker.d.ts.map +1 -0
- package/dist/spec/evolve/logic-checker.js +48 -0
- package/dist/spec/evolve/logic-checker.js.map +1 -0
- package/dist/spec/evolve/pipeline.d.ts +40 -0
- package/dist/spec/evolve/pipeline.d.ts.map +1 -0
- package/dist/spec/evolve/pipeline.js +314 -0
- package/dist/spec/evolve/pipeline.js.map +1 -0
- package/dist/spec/evolve/spec-rewriter.d.ts +42 -0
- package/dist/spec/evolve/spec-rewriter.d.ts.map +1 -0
- package/dist/spec/evolve/spec-rewriter.js +254 -0
- package/dist/spec/evolve/spec-rewriter.js.map +1 -0
- package/dist/spec/graph/queries.d.ts +58 -0
- package/dist/spec/graph/queries.d.ts.map +1 -0
- package/dist/spec/graph/queries.js +215 -0
- package/dist/spec/graph/queries.js.map +1 -0
- package/dist/spec/mining/diff-parser.d.ts +33 -0
- package/dist/spec/mining/diff-parser.d.ts.map +1 -0
- package/dist/spec/mining/diff-parser.js +166 -0
- package/dist/spec/mining/diff-parser.js.map +1 -0
- package/dist/spec/mining/git-scanner.d.ts +91 -0
- package/dist/spec/mining/git-scanner.d.ts.map +1 -0
- package/dist/spec/mining/git-scanner.js +266 -0
- package/dist/spec/mining/git-scanner.js.map +1 -0
- package/dist/spec/mining/pipeline.d.ts +53 -0
- package/dist/spec/mining/pipeline.d.ts.map +1 -0
- package/dist/spec/mining/pipeline.js +165 -0
- package/dist/spec/mining/pipeline.js.map +1 -0
- package/dist/spec/mining/scope-resolver.d.ts +45 -0
- package/dist/spec/mining/scope-resolver.d.ts.map +1 -0
- package/dist/spec/mining/scope-resolver.js +103 -0
- package/dist/spec/mining/scope-resolver.js.map +1 -0
- package/dist/spec/mining/spec-extractor.d.ts +69 -0
- package/dist/spec/mining/spec-extractor.d.ts.map +1 -0
- package/dist/spec/mining/spec-extractor.js +369 -0
- package/dist/spec/mining/spec-extractor.js.map +1 -0
- package/dist/spec/types.d.ts +149 -0
- package/dist/spec/types.d.ts.map +1 -0
- package/dist/spec/types.js +15 -0
- package/dist/spec/types.js.map +1 -0
- package/dist/spec/utils.d.ts +166 -0
- package/dist/spec/utils.d.ts.map +1 -0
- package/dist/spec/utils.js +461 -0
- package/dist/spec/utils.js.map +1 -0
- package/package.json +58 -57
- package/scripts/add-lang/bench.sh +60 -60
- package/scripts/add-lang/check-grammar.mjs +75 -75
- package/scripts/add-lang/dump-ast.mjs +103 -103
- package/scripts/add-lang/verify-extraction.mjs +70 -70
- package/scripts/agent-eval/ab-adoption.sh +91 -91
- package/scripts/agent-eval/ab-hook.sh +86 -86
- package/scripts/agent-eval/ab-impl.sh +78 -78
- package/scripts/agent-eval/ab-new-vs-baseline.sh +102 -102
- package/scripts/agent-eval/ab-sufficiency.sh +78 -78
- package/scripts/agent-eval/arms-F.sh +21 -21
- package/scripts/agent-eval/arms-matrix.sh +37 -37
- package/scripts/agent-eval/audit.sh +68 -68
- package/scripts/agent-eval/bench-readme.sh +28 -28
- package/scripts/agent-eval/bench-why-repo.sh +22 -22
- package/scripts/agent-eval/block-read-hook.sh +19 -19
- package/scripts/agent-eval/hook-settings.json +15 -15
- package/scripts/agent-eval/itrun.sh +120 -120
- package/scripts/agent-eval/offload-eval-3arm.sh +72 -72
- package/scripts/agent-eval/offload-eval-cost.mjs +133 -133
- package/scripts/agent-eval/offload-eval-effort.mjs +108 -108
- package/scripts/agent-eval/offload-eval-frontload-matrix.sh +25 -25
- package/scripts/agent-eval/offload-eval-frontload.sh +47 -47
- package/scripts/agent-eval/offload-eval-ground-truth.json +18 -18
- package/scripts/agent-eval/offload-eval-hook.mjs +84 -84
- package/scripts/agent-eval/offload-eval-judge.mjs +103 -103
- package/scripts/agent-eval/offload-eval-matrix.sh +20 -20
- package/scripts/agent-eval/offload-eval-metrics.mjs +94 -94
- package/scripts/agent-eval/offload-eval-refs1.sh +50 -50
- package/scripts/agent-eval/offload-eval-setup.sh +24 -24
- package/scripts/agent-eval/offload-eval-styles.sh +71 -71
- package/scripts/agent-eval/offload-eval-summarize.mjs +68 -68
- package/scripts/agent-eval/offload-eval.md +76 -76
- package/scripts/agent-eval/parse-arms.mjs +116 -116
- package/scripts/agent-eval/parse-bench-readme.mjs +84 -84
- package/scripts/agent-eval/parse-run.mjs +45 -45
- package/scripts/agent-eval/parse-session.mjs +93 -93
- package/scripts/agent-eval/probe-context.mjs +21 -21
- package/scripts/agent-eval/probe-explore.mjs +40 -40
- package/scripts/agent-eval/probe-node.mjs +20 -20
- package/scripts/agent-eval/probe-sweep.mjs +119 -119
- package/scripts/agent-eval/probe-trace.mjs +20 -20
- package/scripts/agent-eval/redirect-read-hook.sh +38 -38
- package/scripts/agent-eval/run-agent.sh +34 -34
- package/scripts/agent-eval/run-all.sh +69 -69
- package/scripts/agent-eval/run-arms.sh +56 -56
- package/scripts/agent-eval/seq-matrix.mjs +137 -137
- package/scripts/build-bundle.sh +118 -118
- package/scripts/extract-release-notes.mjs +130 -130
- package/scripts/local-install.sh +41 -41
- package/scripts/npm-sdk.js +75 -75
- package/scripts/npm-shim.js +246 -246
- package/scripts/pack-npm.sh +119 -119
- package/scripts/prepare-release.mjs +270 -270
- package/scripts/qa_eval/README.md +407 -404
- package/scripts/qa_eval/_test_deveco_probe.py +41 -41
- package/scripts/qa_eval/agent_runner.py +526 -526
- package/scripts/qa_eval/data/.gitignore +4 -4
- package/scripts/qa_eval/data/test-set.jsonl +2 -22
- package/scripts/qa_eval/eval_metrics.py +274 -233
- package/scripts/qa_eval/external_agent.py +976 -671
- package/scripts/qa_eval/llm_config.py +92 -92
- package/scripts/qa_eval/memory_monitor.py +132 -132
- package/scripts/qa_eval/my_answer_accuracy.py +187 -187
- package/scripts/qa_eval/requirements.txt +2 -2
- package/scripts/qa_eval/run_pipeline.py +804 -711
- package/scripts/qa_eval/stats_efficiency.py +279 -279
- package/scripts/qa_eval/stats_scores.py +207 -207
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.LLMClient = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Provider-agnostic LLM client for spec self-evolution.
|
|
9
|
+
*
|
|
10
|
+
* Replaces `commit4spec/utils/llm_client.py`. Supports OpenAI-compatible chat
|
|
11
|
+
* completions API with mock mode for testing. Mock responses are consumed
|
|
12
|
+
* FIFO: each `setMockResponse` call adds one response, each `chat` call
|
|
13
|
+
* consumes one. When the mock queue is empty, pattern-based fallback responses
|
|
14
|
+
* are returned.
|
|
15
|
+
*
|
|
16
|
+
* @module spec/evolve/llm-client
|
|
17
|
+
*/
|
|
18
|
+
const openai_1 = __importDefault(require("openai"));
|
|
19
|
+
const errors_1 = require("../../errors");
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// LLMClient
|
|
22
|
+
// =============================================================================
|
|
23
|
+
class LLMClient {
|
|
24
|
+
config;
|
|
25
|
+
mockResponses;
|
|
26
|
+
constructor(config) {
|
|
27
|
+
this.config = config;
|
|
28
|
+
this.mockResponses = [];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Append a mock response to the FIFO queue.
|
|
32
|
+
*
|
|
33
|
+
* When provider is `"mock"`, `chat()` dequeues the first response.
|
|
34
|
+
* Responses are consumed in insertion order; each call to `chat()` removes
|
|
35
|
+
* and returns the front element.
|
|
36
|
+
*/
|
|
37
|
+
setMockResponse(_key, response) {
|
|
38
|
+
this.mockResponses.push(response);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Clear all mock responses.
|
|
42
|
+
*/
|
|
43
|
+
clearMockResponses() {
|
|
44
|
+
this.mockResponses = [];
|
|
45
|
+
}
|
|
46
|
+
// ===========================================================================
|
|
47
|
+
// chat
|
|
48
|
+
// ===========================================================================
|
|
49
|
+
/**
|
|
50
|
+
* Send a chat completion request and return the message content string.
|
|
51
|
+
*
|
|
52
|
+
* **Mock mode** (`provider === "mock"`):
|
|
53
|
+
* 1. If mockResponses has entries, consumes the first one (FIFO).
|
|
54
|
+
* 2. Otherwise matches `userPrompt` against known patterns (case-insensitive):
|
|
55
|
+
* - `"logic change"` or `"logic_change"` → no-op JSON.
|
|
56
|
+
* - `"spec evolution"` or `"evolve"` → UNCHANGED JSON.
|
|
57
|
+
* - Default → UNCHANGED JSON.
|
|
58
|
+
*
|
|
59
|
+
* **OpenAI / Anthropic mode**:
|
|
60
|
+
* Calls the OpenAI-compatible chat completions API and returns
|
|
61
|
+
* `choices[0].message.content`. On any error, returns an empty string.
|
|
62
|
+
*/
|
|
63
|
+
async chat(systemPrompt, userPrompt) {
|
|
64
|
+
// --- Mock mode -------------------------------------------------------
|
|
65
|
+
if (this.config.provider === 'mock') {
|
|
66
|
+
if (this.mockResponses.length > 0) {
|
|
67
|
+
return this.mockResponses.shift();
|
|
68
|
+
}
|
|
69
|
+
const lower = userPrompt.toLowerCase();
|
|
70
|
+
if (lower.includes('logic change') || lower.includes('logic_change')) {
|
|
71
|
+
return JSON.stringify({
|
|
72
|
+
is_logic_change: false,
|
|
73
|
+
reason: 'Mock: no logic change detected',
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (lower.includes('spec evolution') || lower.includes('evolve')) {
|
|
77
|
+
return JSON.stringify({
|
|
78
|
+
action: 'UNCHANGED',
|
|
79
|
+
reason: 'Mock: no changes needed',
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return JSON.stringify({
|
|
83
|
+
action: 'UNCHANGED',
|
|
84
|
+
reason: 'Mock: default no-op response',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
// --- OpenAI / Anthropic mode -----------------------------------------
|
|
88
|
+
const baseURL = this.config.baseUrl
|
|
89
|
+
? this.config.baseUrl
|
|
90
|
+
: this.config.provider === 'anthropic'
|
|
91
|
+
? 'https://api.anthropic.com/v1'
|
|
92
|
+
: undefined;
|
|
93
|
+
const client = new openai_1.default({
|
|
94
|
+
apiKey: this.config.apiKey || 'sk-placeholder',
|
|
95
|
+
baseURL,
|
|
96
|
+
});
|
|
97
|
+
try {
|
|
98
|
+
const completion = await client.chat.completions.create({
|
|
99
|
+
model: this.config.model,
|
|
100
|
+
temperature: this.config.temperature,
|
|
101
|
+
max_tokens: this.config.maxTokens,
|
|
102
|
+
messages: [
|
|
103
|
+
{ role: 'system', content: systemPrompt },
|
|
104
|
+
{ role: 'user', content: userPrompt },
|
|
105
|
+
],
|
|
106
|
+
});
|
|
107
|
+
const content = completion.choices[0]?.message?.content;
|
|
108
|
+
return content ?? '';
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return '';
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// ===========================================================================
|
|
115
|
+
// chatJson
|
|
116
|
+
// ===========================================================================
|
|
117
|
+
/**
|
|
118
|
+
* Same as `chat()`, but parses the response as JSON.
|
|
119
|
+
*
|
|
120
|
+
* Parsing strategy (tried in order):
|
|
121
|
+
* 1. Direct `JSON.parse(content)`.
|
|
122
|
+
* 2. Extract from `` ```json ... ``` `` fenced block.
|
|
123
|
+
* 3. Extract from `` ``` ... ``` `` fenced block.
|
|
124
|
+
* 4. Fallback: log a debug warning and return `{}`.
|
|
125
|
+
*
|
|
126
|
+
* Empty or null content from `chat()` also returns `{}`.
|
|
127
|
+
*/
|
|
128
|
+
async chatJson(systemPrompt, userPrompt) {
|
|
129
|
+
const raw = await this.chat(systemPrompt, userPrompt);
|
|
130
|
+
if (!raw)
|
|
131
|
+
return {};
|
|
132
|
+
// 1. Direct parse
|
|
133
|
+
try {
|
|
134
|
+
const parsed = JSON.parse(raw);
|
|
135
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
136
|
+
return parsed;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// Fall through to fence extraction
|
|
141
|
+
}
|
|
142
|
+
// 2. ```json ... ``` fence
|
|
143
|
+
const jsonFenceMatch = /```json\s*([\s\S]*?)```/.exec(raw);
|
|
144
|
+
if (jsonFenceMatch) {
|
|
145
|
+
try {
|
|
146
|
+
const parsed = JSON.parse(jsonFenceMatch[1].trim());
|
|
147
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
148
|
+
return parsed;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Fall through
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// 3. ``` ... ``` fence
|
|
156
|
+
const fenceMatch = /```\s*([\s\S]*?)```/.exec(raw);
|
|
157
|
+
if (fenceMatch) {
|
|
158
|
+
try {
|
|
159
|
+
const parsed = JSON.parse(fenceMatch[1].trim());
|
|
160
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
161
|
+
return parsed;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
// Fall through
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// 4. Fallback
|
|
169
|
+
(0, errors_1.logDebug)('chatJson: could not parse response as JSON', {
|
|
170
|
+
raw: raw.length > 200 ? raw.slice(0, 200) + '…' : raw,
|
|
171
|
+
});
|
|
172
|
+
return {};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
exports.LLMClient = LLMClient;
|
|
176
|
+
//# sourceMappingURL=llm-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-client.js","sourceRoot":"","sources":["../../../src/spec/evolve/llm-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LLMClient } from './llm-client';
|
|
2
|
+
export interface LogicCheckResult {
|
|
3
|
+
isLogic: boolean;
|
|
4
|
+
reason: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Determine if a commit represents a business-logic change.
|
|
8
|
+
* Uses LLM to analyze the commit message and diff.
|
|
9
|
+
* If no LLM client is available, returns false.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isLogicChange(commitMessage: string, commitDiff: string, client?: LLMClient): Promise<LogicCheckResult>;
|
|
12
|
+
//# sourceMappingURL=logic-checker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logic-checker.d.ts","sourceRoot":"","sources":["../../../src/spec/evolve/logic-checker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,SAAS,GACjB,OAAO,CAAC,gBAAgB,CAAC,CA0C3B"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isLogicChange = isLogicChange;
|
|
4
|
+
const utils_1 = require("../utils");
|
|
5
|
+
/**
|
|
6
|
+
* Determine if a commit represents a business-logic change.
|
|
7
|
+
* Uses LLM to analyze the commit message and diff.
|
|
8
|
+
* If no LLM client is available, returns false.
|
|
9
|
+
*/
|
|
10
|
+
async function isLogicChange(commitMessage, commitDiff, client) {
|
|
11
|
+
if (!client) {
|
|
12
|
+
return { isLogic: false, reason: 'LLM unavailable' };
|
|
13
|
+
}
|
|
14
|
+
// Truncate diff to 6000 chars for prompt budget
|
|
15
|
+
const truncatedDiff = (0, utils_1.truncateText)(commitDiff, 6000);
|
|
16
|
+
const systemPrompt = `You are a code review assistant. Your task is to determine whether a git commit represents a business-logic change (as opposed to purely cosmetic, formatting, comment-only, or test-only changes).
|
|
17
|
+
|
|
18
|
+
A business-logic change includes:
|
|
19
|
+
- Changes to algorithms, data structures, or control flow
|
|
20
|
+
- Changes to business rules, validation logic, or domain behavior
|
|
21
|
+
- Adding or removing functionality
|
|
22
|
+
- Bug fixes that change behavior
|
|
23
|
+
|
|
24
|
+
NOT business-logic changes:
|
|
25
|
+
- Whitespace, formatting, or code style changes
|
|
26
|
+
- Comment-only changes
|
|
27
|
+
- Test-only changes (adding tests without changing production code)
|
|
28
|
+
- Configuration changes that don't alter behavior
|
|
29
|
+
- Package/dependency version bumps
|
|
30
|
+
|
|
31
|
+
Respond with a JSON object:
|
|
32
|
+
{
|
|
33
|
+
"is_logic_change": true/false,
|
|
34
|
+
"reason": "Brief explanation of why this is or is not a logic change"
|
|
35
|
+
}`;
|
|
36
|
+
const userPrompt = `Analyze this commit:
|
|
37
|
+
|
|
38
|
+
Commit Message: ${commitMessage}
|
|
39
|
+
|
|
40
|
+
Diff:
|
|
41
|
+
${truncatedDiff}`;
|
|
42
|
+
const result = await client.chatJson(systemPrompt, userPrompt);
|
|
43
|
+
return {
|
|
44
|
+
isLogic: result.is_logic_change === true,
|
|
45
|
+
reason: typeof result.reason === 'string' ? result.reason : '',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=logic-checker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logic-checker.js","sourceRoot":"","sources":["../../../src/spec/evolve/logic-checker.ts"],"names":[],"mappings":";;AAaA,sCA8CC;AA1DD,oCAAwC;AAOxC;;;;GAIG;AACI,KAAK,UAAU,aAAa,CACjC,aAAqB,EACrB,UAAkB,EAClB,MAAkB;IAElB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IACvD,CAAC;IAED,gDAAgD;IAChD,MAAM,aAAa,GAAG,IAAA,oBAAY,EAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAErD,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;EAmBrB,CAAC;IAED,MAAM,UAAU,GAAG;;kBAEH,aAAa;;;EAG7B,aAAa,EAAE,CAAC;IAEhB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAE/D,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,eAAe,KAAK,IAAI;QACxC,MAAM,EAAE,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;KAC/D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { SqliteDatabase } from '../../db/sqlite-adapter';
|
|
2
|
+
import { LLMConfig } from '../config';
|
|
3
|
+
export interface EvolvedSpec {
|
|
4
|
+
specId: string;
|
|
5
|
+
action: 'UPDATE' | 'DEPRECATE' | 'UNCHANGED';
|
|
6
|
+
newVersion?: number;
|
|
7
|
+
newSpecId?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface EvolveResult {
|
|
10
|
+
commitHash: string;
|
|
11
|
+
generateSpecId?: string;
|
|
12
|
+
generateRelationCreated: boolean;
|
|
13
|
+
isLogicChange: boolean;
|
|
14
|
+
logicCheckReason: string;
|
|
15
|
+
affectedSpecCount: number;
|
|
16
|
+
evolvedSpecs: EvolvedSpec[];
|
|
17
|
+
fragmentsCount: number;
|
|
18
|
+
relationsCreated: number;
|
|
19
|
+
persisted: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Run the full self-evolve pipeline for a single commit.
|
|
23
|
+
*
|
|
24
|
+
* Flow (ported from pipeline.py:79-289):
|
|
25
|
+
*
|
|
26
|
+
* 1. Load context (meta, schema, commit info, diff, LLM client, config).
|
|
27
|
+
* 2. **Path A (GENERATE):** resolve scope from commit message.
|
|
28
|
+
* 3. **LLM logic check:** determine if the commit is a business-logic change.
|
|
29
|
+
* 4. **Path B (impact + rewrite):** if logic change, find affected active
|
|
30
|
+
* specs and evaluate each one.
|
|
31
|
+
* 5. If neither Path A nor Path B produced candidates, return early.
|
|
32
|
+
* 6. Persist everything in a single DB transaction.
|
|
33
|
+
*
|
|
34
|
+
* @param repoPath - Absolute path to the git repository.
|
|
35
|
+
* @param db - Active SQLite database handle.
|
|
36
|
+
* @param commitHash - Optional commit hash; defaults to HEAD.
|
|
37
|
+
* @param llmConfig - Optional LLM config override; falls back to spec config.
|
|
38
|
+
*/
|
|
39
|
+
export declare function runEvolvePipeline(repoPath: string, db: SqliteDatabase, commitHash?: string, llmConfig?: LLMConfig): Promise<EvolveResult>;
|
|
40
|
+
//# sourceMappingURL=pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../../src/spec/evolve/pipeline.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAkB,MAAM,WAAW,CAAC;AA6BtD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uBAAuB,EAAE,OAAO,CAAC;IACjC,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;CACpB;AA0BD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,cAAc,EAClB,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,SAAS,GACpB,OAAO,CAAC,YAAY,CAAC,CAsSvB"}
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.runEvolvePipeline = runEvolvePipeline;
|
|
37
|
+
/**
|
|
38
|
+
* Self-evolve pipeline orchestrator — evaluates new commits against existing
|
|
39
|
+
* specs and rewrites / deprecates them as needed.
|
|
40
|
+
*
|
|
41
|
+
* Replaces `commit4spec/self_evolve/pipeline.py` (lines 79-289).
|
|
42
|
+
*
|
|
43
|
+
* @module spec/evolve/pipeline
|
|
44
|
+
*/
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
const child_process_1 = require("child_process");
|
|
47
|
+
const config_1 = require("../config");
|
|
48
|
+
const utils_1 = require("../utils");
|
|
49
|
+
const schema_1 = require("../db/schema");
|
|
50
|
+
const spec_node_1 = require("../db/spec-node");
|
|
51
|
+
const commit_node_1 = require("../db/commit-node");
|
|
52
|
+
const fragment_node_1 = require("../db/fragment-node");
|
|
53
|
+
const relations_1 = require("../db/relations");
|
|
54
|
+
const git_scanner_1 = require("../mining/git-scanner");
|
|
55
|
+
const scope_resolver_1 = require("../mining/scope-resolver");
|
|
56
|
+
const spec_extractor_1 = require("../mining/spec-extractor");
|
|
57
|
+
const diff_parser_1 = require("../mining/diff-parser");
|
|
58
|
+
const llm_client_1 = require("./llm-client");
|
|
59
|
+
const logic_checker_1 = require("./logic-checker");
|
|
60
|
+
const impact_locator_1 = require("./impact-locator");
|
|
61
|
+
const spec_rewriter_1 = require("./spec-rewriter");
|
|
62
|
+
const errors_1 = require("../../errors");
|
|
63
|
+
// =============================================================================
|
|
64
|
+
// Helpers
|
|
65
|
+
// =============================================================================
|
|
66
|
+
/**
|
|
67
|
+
* Look up a spec from the DB and return its version and filePath.
|
|
68
|
+
* Falls back to constructing a plan.md path when the spec is not found.
|
|
69
|
+
*/
|
|
70
|
+
function getSpecPathInfo(db, specStoragePath, specId) {
|
|
71
|
+
const node = (0, spec_node_1.findSpecById)(db, specId);
|
|
72
|
+
if (node) {
|
|
73
|
+
return { version: node.version, filePath: node.filePath };
|
|
74
|
+
}
|
|
75
|
+
return { version: 0, filePath: path.join(specStoragePath, specId, 'plan.md') };
|
|
76
|
+
}
|
|
77
|
+
// =============================================================================
|
|
78
|
+
// runEvolvePipeline
|
|
79
|
+
// =============================================================================
|
|
80
|
+
/**
|
|
81
|
+
* Run the full self-evolve pipeline for a single commit.
|
|
82
|
+
*
|
|
83
|
+
* Flow (ported from pipeline.py:79-289):
|
|
84
|
+
*
|
|
85
|
+
* 1. Load context (meta, schema, commit info, diff, LLM client, config).
|
|
86
|
+
* 2. **Path A (GENERATE):** resolve scope from commit message.
|
|
87
|
+
* 3. **LLM logic check:** determine if the commit is a business-logic change.
|
|
88
|
+
* 4. **Path B (impact + rewrite):** if logic change, find affected active
|
|
89
|
+
* specs and evaluate each one.
|
|
90
|
+
* 5. If neither Path A nor Path B produced candidates, return early.
|
|
91
|
+
* 6. Persist everything in a single DB transaction.
|
|
92
|
+
*
|
|
93
|
+
* @param repoPath - Absolute path to the git repository.
|
|
94
|
+
* @param db - Active SQLite database handle.
|
|
95
|
+
* @param commitHash - Optional commit hash; defaults to HEAD.
|
|
96
|
+
* @param llmConfig - Optional LLM config override; falls back to spec config.
|
|
97
|
+
*/
|
|
98
|
+
async function runEvolvePipeline(repoPath, db, commitHash, llmConfig) {
|
|
99
|
+
// ------------------------------------------------------------------
|
|
100
|
+
// 1. Context loading
|
|
101
|
+
// ------------------------------------------------------------------
|
|
102
|
+
// Read meta
|
|
103
|
+
const meta = (0, utils_1.readMeta)(repoPath);
|
|
104
|
+
if (!meta) {
|
|
105
|
+
throw new Error("No meta.json found. Run 'homegraph spec mine' first.");
|
|
106
|
+
}
|
|
107
|
+
// Init schema
|
|
108
|
+
(0, schema_1.initSpecSchema)(db);
|
|
109
|
+
// Resolve commit hash
|
|
110
|
+
const resolvedHash = commitHash ||
|
|
111
|
+
(() => {
|
|
112
|
+
try {
|
|
113
|
+
return (0, child_process_1.execFileSync)('git', ['rev-parse', 'HEAD'], {
|
|
114
|
+
cwd: repoPath,
|
|
115
|
+
encoding: 'utf8',
|
|
116
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
117
|
+
windowsHide: true,
|
|
118
|
+
}).trim();
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return '';
|
|
122
|
+
}
|
|
123
|
+
})();
|
|
124
|
+
if (!resolvedHash) {
|
|
125
|
+
throw new Error('No commits found in repository.');
|
|
126
|
+
}
|
|
127
|
+
// Get commit info and diff
|
|
128
|
+
const commitInfo = (0, git_scanner_1.getCommitInfo)(repoPath, resolvedHash);
|
|
129
|
+
if (!commitInfo) {
|
|
130
|
+
throw new Error(`Commit ${resolvedHash} not found in repository.`);
|
|
131
|
+
}
|
|
132
|
+
const diff = (0, git_scanner_1.getCommitDiff)(repoPath, resolvedHash);
|
|
133
|
+
// Parse diff into fragments once — reused for file paths and persistence.
|
|
134
|
+
const diffFragments = (0, diff_parser_1.analyzeCommitDiff)(repoPath, resolvedHash, diff);
|
|
135
|
+
// Load spec config and create LLM client
|
|
136
|
+
const specConfig = (0, config_1.loadSpecConfig)(repoPath);
|
|
137
|
+
const resolvedLLMConfig = llmConfig || specConfig.llm;
|
|
138
|
+
const client = new llm_client_1.LLMClient(resolvedLLMConfig);
|
|
139
|
+
// ------------------------------------------------------------------
|
|
140
|
+
// 2. Path A (GENERATE) — commit message scope resolution
|
|
141
|
+
// ------------------------------------------------------------------
|
|
142
|
+
const pathASpecId = (0, scope_resolver_1.resolveScopeToSpec)(commitInfo.message, meta.specStoragePath, specConfig);
|
|
143
|
+
let pathASpecMetadata = null;
|
|
144
|
+
if (pathASpecId) {
|
|
145
|
+
pathASpecMetadata = (0, spec_extractor_1.extractSpecMetadata)(meta.specStoragePath, pathASpecId, specConfig);
|
|
146
|
+
}
|
|
147
|
+
// ------------------------------------------------------------------
|
|
148
|
+
// 3. LLM logic check
|
|
149
|
+
// ------------------------------------------------------------------
|
|
150
|
+
let logicResult = { isLogic: false, reason: '' };
|
|
151
|
+
try {
|
|
152
|
+
logicResult = await (0, logic_checker_1.isLogicChange)(commitInfo.message, diff, client);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
(0, errors_1.logWarn)('LLM logic check failed, treating as non-logic change', {
|
|
156
|
+
commitHash: resolvedHash.slice(0, 7),
|
|
157
|
+
});
|
|
158
|
+
logicResult = { isLogic: false, reason: 'LLM call failed' };
|
|
159
|
+
}
|
|
160
|
+
// ------------------------------------------------------------------
|
|
161
|
+
// 4. Path B (impact + rewrite) — only when the commit is a logic change
|
|
162
|
+
// ------------------------------------------------------------------
|
|
163
|
+
let pathBSpecIds = [];
|
|
164
|
+
if (logicResult.isLogic) {
|
|
165
|
+
// Extract file paths from diff fragments
|
|
166
|
+
const filePaths = diffFragments.map(f => f.filePath);
|
|
167
|
+
// Locate affected specs
|
|
168
|
+
const affectedSpecIds = (0, impact_locator_1.locateAffectedSpecs)(db, filePaths);
|
|
169
|
+
if (affectedSpecIds.length > 0) {
|
|
170
|
+
// Filter to active specs only
|
|
171
|
+
const placeholders = affectedSpecIds.map(() => '?').join(',');
|
|
172
|
+
const activeRows = db
|
|
173
|
+
.prepare(`SELECT id FROM spec_nodes WHERE status = 'active' AND id IN (${placeholders})`)
|
|
174
|
+
.all(...affectedSpecIds);
|
|
175
|
+
pathBSpecIds = activeRows.map((r) => r.id);
|
|
176
|
+
// Remove Path A spec from Path B list (if present)
|
|
177
|
+
if (pathASpecId) {
|
|
178
|
+
pathBSpecIds = pathBSpecIds.filter((id) => id !== pathASpecId);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
(0, errors_1.logDebug)('Path B: affected active specs', {
|
|
182
|
+
count: pathBSpecIds.length,
|
|
183
|
+
specIds: pathBSpecIds,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
// ------------------------------------------------------------------
|
|
187
|
+
// 5. Decide relevance
|
|
188
|
+
// ------------------------------------------------------------------
|
|
189
|
+
const hasPathA = pathASpecId !== null;
|
|
190
|
+
const hasPathB = pathBSpecIds.length > 0;
|
|
191
|
+
if (!hasPathA && !hasPathB) {
|
|
192
|
+
(0, errors_1.logDebug)('runEvolvePipeline: no relevant spec found, returning early', {
|
|
193
|
+
commitHash: resolvedHash.slice(0, 7),
|
|
194
|
+
});
|
|
195
|
+
return {
|
|
196
|
+
commitHash: resolvedHash,
|
|
197
|
+
generateRelationCreated: false,
|
|
198
|
+
isLogicChange: logicResult.isLogic,
|
|
199
|
+
logicCheckReason: logicResult.reason,
|
|
200
|
+
affectedSpecCount: 0,
|
|
201
|
+
evolvedSpecs: [],
|
|
202
|
+
fragmentsCount: 0,
|
|
203
|
+
relationsCreated: 0,
|
|
204
|
+
persisted: false,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
const pendingDecisions = [];
|
|
208
|
+
for (let idx = 0; idx < pathBSpecIds.length; idx++) {
|
|
209
|
+
const specId = pathBSpecIds[idx];
|
|
210
|
+
const scheduleNextSpecs = pathBSpecIds.slice(idx + 1);
|
|
211
|
+
const { version, filePath } = getSpecPathInfo(db, meta.specStoragePath, specId);
|
|
212
|
+
const decision = await (0, spec_rewriter_1.evaluateSpec)(specId, meta.specStoragePath, filePath, commitInfo.message, diff, scheduleNextSpecs, client);
|
|
213
|
+
pendingDecisions.push({ specId, decision, version, filePath });
|
|
214
|
+
}
|
|
215
|
+
// ------------------------------------------------------------------
|
|
216
|
+
// 7. Persist (atomic via explicit BEGIN/COMMIT/ROLLBACK)
|
|
217
|
+
// All LLM evaluation is complete; only fast DB writes remain.
|
|
218
|
+
// ------------------------------------------------------------------
|
|
219
|
+
const evolveResult = {
|
|
220
|
+
commitHash: resolvedHash,
|
|
221
|
+
generateSpecId: pathASpecId ?? undefined,
|
|
222
|
+
generateRelationCreated: false,
|
|
223
|
+
isLogicChange: logicResult.isLogic,
|
|
224
|
+
logicCheckReason: logicResult.reason,
|
|
225
|
+
affectedSpecCount: pathBSpecIds.length,
|
|
226
|
+
evolvedSpecs: [],
|
|
227
|
+
fragmentsCount: 0,
|
|
228
|
+
relationsCreated: 0,
|
|
229
|
+
persisted: true,
|
|
230
|
+
};
|
|
231
|
+
db.exec('BEGIN');
|
|
232
|
+
try {
|
|
233
|
+
// ---- Insert CommitNode ----
|
|
234
|
+
(0, commit_node_1.insertCommitNode)(db, {
|
|
235
|
+
hash: commitInfo.hash,
|
|
236
|
+
message: commitInfo.message,
|
|
237
|
+
author: commitInfo.author,
|
|
238
|
+
timestamp: commitInfo.timestamp,
|
|
239
|
+
});
|
|
240
|
+
// ---- Path A: Insert SpecNode + GENERATE relation ----
|
|
241
|
+
if (pathASpecId && pathASpecMetadata) {
|
|
242
|
+
(0, spec_node_1.insertSpecNode)(db, {
|
|
243
|
+
id: pathASpecMetadata.specId,
|
|
244
|
+
title: pathASpecMetadata.title,
|
|
245
|
+
subtitles: pathASpecMetadata.subtitles,
|
|
246
|
+
status: 'active',
|
|
247
|
+
version: 1,
|
|
248
|
+
filePath: pathASpecMetadata.filePath,
|
|
249
|
+
timestamp: commitInfo.timestamp,
|
|
250
|
+
});
|
|
251
|
+
(0, relations_1.insertSpecCommitRelation)(db, pathASpecMetadata.specId, commitInfo.hash, 'GENERATE');
|
|
252
|
+
evolveResult.generateRelationCreated = true;
|
|
253
|
+
evolveResult.relationsCreated++;
|
|
254
|
+
}
|
|
255
|
+
else if (pathASpecId) {
|
|
256
|
+
(0, errors_1.logWarn)('Path A: specId resolved but no metadata extracted, skipping insert', {
|
|
257
|
+
specId: pathASpecId,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
// ---- Path B: Apply pre-evaluated decisions ----
|
|
261
|
+
const evolvedSpecs = [];
|
|
262
|
+
for (const pending of pendingDecisions) {
|
|
263
|
+
const { specId, decision, version, filePath } = pending;
|
|
264
|
+
if (decision.action === 'UPDATE') {
|
|
265
|
+
const updateResult = (0, spec_rewriter_1.applyUpdate)(db, meta.specStoragePath, specId, filePath, version, decision, commitInfo.hash);
|
|
266
|
+
evolvedSpecs.push({
|
|
267
|
+
specId,
|
|
268
|
+
action: 'UPDATE',
|
|
269
|
+
newVersion: updateResult.newVersion,
|
|
270
|
+
newSpecId: updateResult.newSpecId,
|
|
271
|
+
});
|
|
272
|
+
evolveResult.relationsCreated += 2; // EVOLVED_FROM + GENERATE
|
|
273
|
+
}
|
|
274
|
+
else if (decision.action === 'DEPRECATE') {
|
|
275
|
+
(0, spec_rewriter_1.applyDeprecate)(db, specId);
|
|
276
|
+
evolvedSpecs.push({
|
|
277
|
+
specId,
|
|
278
|
+
action: 'DEPRECATE',
|
|
279
|
+
});
|
|
280
|
+
// applyDeprecate creates one EVOLVED_FROM relation
|
|
281
|
+
evolveResult.relationsCreated += 1;
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
// UNCHANGED
|
|
285
|
+
evolvedSpecs.push({
|
|
286
|
+
specId,
|
|
287
|
+
action: 'UNCHANGED',
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
evolveResult.evolvedSpecs = evolvedSpecs;
|
|
292
|
+
// ---- Common: Persist pre-parsed fragments and create CONTAINS relations ----
|
|
293
|
+
for (const frag of diffFragments) {
|
|
294
|
+
const inserted = (0, fragment_node_1.insertCodeFragment)(db, {
|
|
295
|
+
id: '',
|
|
296
|
+
changeType: frag.changeType,
|
|
297
|
+
filePath: frag.filePath,
|
|
298
|
+
startLine: frag.startLine,
|
|
299
|
+
endLine: frag.endLine,
|
|
300
|
+
codeDiff: frag.codeDiff,
|
|
301
|
+
});
|
|
302
|
+
evolveResult.fragmentsCount++;
|
|
303
|
+
(0, relations_1.insertCommitFragmentRelation)(db, commitInfo.hash, inserted.id);
|
|
304
|
+
evolveResult.relationsCreated++;
|
|
305
|
+
}
|
|
306
|
+
db.exec('COMMIT');
|
|
307
|
+
}
|
|
308
|
+
catch (e) {
|
|
309
|
+
db.exec('ROLLBACK');
|
|
310
|
+
throw e;
|
|
311
|
+
}
|
|
312
|
+
return evolveResult;
|
|
313
|
+
}
|
|
314
|
+
//# sourceMappingURL=pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../../src/spec/evolve/pipeline.ts"],"names":[],"mappings":"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"}
|