homegraph 1.4.1 → 1.5.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/README.md +48 -11
- package/dist/bin/homegraph.js +295 -72
- package/dist/bin/homegraph.js.map +1 -1
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +32 -11
- package/dist/context/index.js.map +1 -1
- package/dist/db/index.d.ts +143 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +293 -16
- package/dist/db/index.js.map +1 -1
- package/dist/db/queries.d.ts +43 -4
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +138 -14
- package/dist/db/queries.js.map +1 -1
- package/dist/db/sqlite-adapter.d.ts +24 -17
- package/dist/db/sqlite-adapter.d.ts.map +1 -1
- package/dist/db/sqlite-adapter.js +292 -36
- package/dist/db/sqlite-adapter.js.map +1 -1
- package/dist/db/wal-valve.d.ts +15 -2
- package/dist/db/wal-valve.d.ts.map +1 -1
- package/dist/db/wal-valve.js +88 -6
- package/dist/db/wal-valve.js.map +1 -1
- package/dist/extraction/arkts-batch-worker.js +3 -2
- package/dist/extraction/arkts-batch-worker.js.map +1 -1
- package/dist/extraction/default-ignore.d.ts +39 -0
- package/dist/extraction/default-ignore.d.ts.map +1 -0
- package/dist/extraction/default-ignore.js +221 -0
- package/dist/extraction/default-ignore.js.map +1 -0
- package/dist/extraction/index.d.ts +9 -10
- package/dist/extraction/index.d.ts.map +1 -1
- package/dist/extraction/index.js +227 -323
- package/dist/extraction/index.js.map +1 -1
- package/dist/extraction/languages/arkts.d.ts +90 -6
- package/dist/extraction/languages/arkts.d.ts.map +1 -1
- package/dist/extraction/languages/arkts.js +1579 -128
- package/dist/extraction/languages/arkts.js.map +1 -1
- package/dist/extraction/store-worker.d.ts +20 -0
- package/dist/extraction/store-worker.d.ts.map +1 -0
- package/dist/extraction/store-worker.js +102 -0
- package/dist/extraction/store-worker.js.map +1 -0
- package/dist/extraction/store-writer.d.ts +48 -0
- package/dist/extraction/store-writer.d.ts.map +1 -0
- package/dist/extraction/store-writer.js +167 -0
- package/dist/extraction/store-writer.js.map +1 -0
- package/dist/extraction/tree-sitter.d.ts.map +1 -1
- package/dist/extraction/tree-sitter.js +47 -0
- package/dist/extraction/tree-sitter.js.map +1 -1
- package/dist/extraction/wasm-runtime-flags.d.ts +14 -4
- package/dist/extraction/wasm-runtime-flags.d.ts.map +1 -1
- package/dist/extraction/wasm-runtime-flags.js +55 -7
- package/dist/extraction/wasm-runtime-flags.js.map +1 -1
- package/dist/index.d.ts +16 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +135 -97
- package/dist/index.js.map +1 -1
- package/dist/mcp/query-worker.d.ts +2 -2
- package/dist/mcp/query-worker.js +2 -2
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +42 -26
- package/dist/mcp/tools.js.map +1 -1
- package/dist/resolution/callback-synthesizer.d.ts +52 -16
- package/dist/resolution/callback-synthesizer.d.ts.map +1 -1
- package/dist/resolution/callback-synthesizer.js +234 -180
- package/dist/resolution/callback-synthesizer.js.map +1 -1
- package/dist/resolution/cooperative-yield.d.ts +10 -2
- package/dist/resolution/cooperative-yield.d.ts.map +1 -1
- package/dist/resolution/cooperative-yield.js +6 -4
- package/dist/resolution/cooperative-yield.js.map +1 -1
- package/dist/resolution/frameworks/go.d.ts.map +1 -1
- package/dist/resolution/frameworks/go.js +29 -6
- package/dist/resolution/frameworks/go.js.map +1 -1
- package/dist/resolution/import-resolver.d.ts +2 -3
- package/dist/resolution/import-resolver.d.ts.map +1 -1
- package/dist/resolution/import-resolver.js +166 -7
- package/dist/resolution/import-resolver.js.map +1 -1
- package/dist/resolution/index.d.ts +87 -2
- package/dist/resolution/index.d.ts.map +1 -1
- package/dist/resolution/index.js +739 -131
- package/dist/resolution/index.js.map +1 -1
- package/dist/resolution/memory-budget.d.ts +48 -0
- package/dist/resolution/memory-budget.d.ts.map +1 -0
- package/dist/resolution/memory-budget.js +162 -0
- package/dist/resolution/memory-budget.js.map +1 -0
- package/dist/resolution/name-matcher.d.ts +12 -1
- package/dist/resolution/name-matcher.d.ts.map +1 -1
- package/dist/resolution/name-matcher.js +439 -97
- package/dist/resolution/name-matcher.js.map +1 -1
- package/dist/resolution/resolver-pool.d.ts +106 -0
- package/dist/resolution/resolver-pool.d.ts.map +1 -0
- package/dist/resolution/resolver-pool.js +344 -0
- package/dist/resolution/resolver-pool.js.map +1 -0
- package/dist/resolution/resolver-worker.d.ts +17 -0
- package/dist/resolution/resolver-worker.d.ts.map +1 -0
- package/dist/resolution/resolver-worker.js +141 -0
- package/dist/resolution/resolver-worker.js.map +1 -0
- package/dist/resolution/types.d.ts +3 -0
- package/dist/resolution/types.d.ts.map +1 -1
- package/dist/spec/build/diff-parser.d.ts +55 -0
- package/dist/spec/build/diff-parser.d.ts.map +1 -0
- package/dist/spec/build/diff-parser.js +205 -0
- package/dist/spec/build/diff-parser.js.map +1 -0
- package/dist/spec/build/git-scanner.d.ts +93 -0
- package/dist/spec/build/git-scanner.d.ts.map +1 -0
- package/dist/spec/build/git-scanner.js +254 -0
- package/dist/spec/build/git-scanner.js.map +1 -0
- package/dist/spec/build/pipeline.d.ts +54 -0
- package/dist/spec/build/pipeline.d.ts.map +1 -0
- package/dist/spec/build/pipeline.js +170 -0
- package/dist/spec/build/pipeline.js.map +1 -0
- package/dist/spec/build/scan.d.ts +48 -0
- package/dist/spec/build/scan.d.ts.map +1 -0
- package/dist/spec/build/scan.js +89 -0
- package/dist/spec/build/scan.js.map +1 -0
- package/dist/spec/build/scope-resolver.d.ts +50 -0
- package/dist/spec/build/scope-resolver.d.ts.map +1 -0
- package/dist/spec/build/scope-resolver.js +105 -0
- package/dist/spec/build/scope-resolver.js.map +1 -0
- package/dist/spec/build/spec-extractor.d.ts +74 -0
- package/dist/spec/build/spec-extractor.d.ts.map +1 -0
- package/dist/spec/build/spec-extractor.js +344 -0
- package/dist/spec/build/spec-extractor.js.map +1 -0
- package/dist/spec/config.d.ts +35 -1
- package/dist/spec/config.d.ts.map +1 -1
- package/dist/spec/config.js +30 -5
- package/dist/spec/config.js.map +1 -1
- package/dist/spec/db/fts.d.ts.map +1 -1
- package/dist/spec/db/fts.js +19 -50
- package/dist/spec/db/fts.js.map +1 -1
- package/dist/spec/db/index.d.ts +5 -3
- package/dist/spec/db/index.d.ts.map +1 -1
- package/dist/spec/db/index.js +16 -1
- package/dist/spec/db/index.js.map +1 -1
- package/dist/spec/db/persist.d.ts +45 -0
- package/dist/spec/db/persist.d.ts.map +1 -0
- package/dist/spec/db/persist.js +66 -0
- package/dist/spec/db/persist.js.map +1 -0
- package/dist/spec/db/relations.d.ts +80 -1
- package/dist/spec/db/relations.d.ts.map +1 -1
- package/dist/spec/db/relations.js +175 -4
- package/dist/spec/db/relations.js.map +1 -1
- package/dist/spec/db/schema.d.ts +4 -0
- package/dist/spec/db/schema.d.ts.map +1 -1
- package/dist/spec/db/schema.js +4 -0
- package/dist/spec/db/schema.js.map +1 -1
- package/dist/spec/db/schema.sql +5 -1
- package/dist/spec/db/spec-node.d.ts +5 -0
- package/dist/spec/db/spec-node.d.ts.map +1 -1
- package/dist/spec/db/spec-node.js +11 -5
- package/dist/spec/db/spec-node.js.map +1 -1
- package/dist/spec/db/sql-utils.d.ts +11 -0
- package/dist/spec/db/sql-utils.d.ts.map +1 -0
- package/dist/spec/db/sql-utils.js +19 -0
- package/dist/spec/db/sql-utils.js.map +1 -0
- package/dist/spec/evolve/cluster-context.d.ts +30 -0
- package/dist/spec/evolve/cluster-context.d.ts.map +1 -0
- package/dist/spec/evolve/cluster-context.js +78 -0
- package/dist/spec/evolve/cluster-context.js.map +1 -0
- package/dist/spec/evolve/commit-spec-analyzer.d.ts +51 -0
- package/dist/spec/evolve/commit-spec-analyzer.d.ts.map +1 -0
- package/dist/spec/evolve/commit-spec-analyzer.js +88 -0
- package/dist/spec/evolve/commit-spec-analyzer.js.map +1 -0
- package/dist/spec/evolve/commit-spec-persister.d.ts +53 -0
- package/dist/spec/evolve/commit-spec-persister.d.ts.map +1 -0
- package/dist/spec/evolve/commit-spec-persister.js +93 -0
- package/dist/spec/evolve/commit-spec-persister.js.map +1 -0
- package/dist/spec/evolve/impact-locator.d.ts +23 -7
- package/dist/spec/evolve/impact-locator.d.ts.map +1 -1
- package/dist/spec/evolve/impact-locator.js +58 -14
- package/dist/spec/evolve/impact-locator.js.map +1 -1
- package/dist/spec/evolve/pipeline.d.ts +62 -25
- package/dist/spec/evolve/pipeline.d.ts.map +1 -1
- package/dist/spec/evolve/pipeline.js +436 -457
- package/dist/spec/evolve/pipeline.js.map +1 -1
- package/dist/spec/evolve/spec-rewriter.d.ts +13 -13
- package/dist/spec/evolve/spec-rewriter.d.ts.map +1 -1
- package/dist/spec/evolve/spec-rewriter.js +45 -45
- package/dist/spec/evolve/spec-rewriter.js.map +1 -1
- package/dist/spec/git/commits.d.ts +85 -0
- package/dist/spec/git/commits.d.ts.map +1 -0
- package/dist/spec/git/commits.js +218 -0
- package/dist/spec/git/commits.js.map +1 -0
- package/dist/spec/git/exec.d.ts +13 -0
- package/dist/spec/git/exec.d.ts.map +1 -0
- package/dist/spec/git/exec.js +19 -0
- package/dist/spec/git/exec.js.map +1 -0
- package/dist/spec/git/index.d.ts +9 -0
- package/dist/spec/git/index.d.ts.map +1 -0
- package/dist/spec/git/index.js +22 -0
- package/dist/spec/git/index.js.map +1 -0
- package/dist/spec/git-utils.d.ts +8 -0
- package/dist/spec/git-utils.d.ts.map +1 -0
- package/dist/spec/git-utils.js +14 -0
- package/dist/spec/git-utils.js.map +1 -0
- package/dist/spec/graph/index.d.ts +8 -0
- package/dist/spec/graph/index.d.ts.map +1 -0
- package/dist/spec/graph/index.js +17 -0
- package/dist/spec/graph/index.js.map +1 -0
- package/dist/spec/graph/queries.d.ts +6 -35
- package/dist/spec/graph/queries.d.ts.map +1 -1
- package/dist/spec/graph/queries.js +71 -248
- package/dist/spec/graph/queries.js.map +1 -1
- package/dist/spec/llm/agent-client.d.ts +59 -0
- package/dist/spec/llm/agent-client.d.ts.map +1 -0
- package/dist/spec/llm/agent-client.js +213 -0
- package/dist/spec/llm/agent-client.js.map +1 -0
- package/dist/spec/llm/agents/claude-code.d.ts +32 -0
- package/dist/spec/llm/agents/claude-code.d.ts.map +1 -0
- package/dist/spec/llm/agents/claude-code.js +125 -0
- package/dist/spec/llm/agents/claude-code.js.map +1 -0
- package/dist/spec/llm/agents/codex.d.ts +32 -0
- package/dist/spec/llm/agents/codex.d.ts.map +1 -0
- package/dist/spec/llm/agents/codex.js +145 -0
- package/dist/spec/llm/agents/codex.js.map +1 -0
- package/dist/spec/llm/agents/detect-utils.d.ts +28 -0
- package/dist/spec/llm/agents/detect-utils.d.ts.map +1 -0
- package/dist/spec/llm/agents/detect-utils.js +91 -0
- package/dist/spec/llm/agents/detect-utils.js.map +1 -0
- package/dist/spec/llm/agents/deveco-code.d.ts +33 -0
- package/dist/spec/llm/agents/deveco-code.d.ts.map +1 -0
- package/dist/spec/llm/agents/deveco-code.js +165 -0
- package/dist/spec/llm/agents/deveco-code.js.map +1 -0
- package/dist/spec/llm/agents/index.d.ts +31 -0
- package/dist/spec/llm/agents/index.d.ts.map +1 -0
- package/dist/spec/llm/agents/index.js +65 -0
- package/dist/spec/llm/agents/index.js.map +1 -0
- package/dist/spec/llm/agents/types.d.ts +76 -0
- package/dist/spec/llm/agents/types.d.ts.map +1 -0
- package/dist/spec/llm/agents/types.js +15 -0
- package/dist/spec/llm/agents/types.js.map +1 -0
- package/dist/spec/llm/client.d.ts +31 -11
- package/dist/spec/llm/client.d.ts.map +1 -1
- package/dist/spec/llm/client.js +143 -81
- package/dist/spec/llm/client.js.map +1 -1
- package/dist/spec/llm/factory.d.ts +41 -0
- package/dist/spec/llm/factory.d.ts.map +1 -0
- package/dist/spec/llm/factory.js +80 -0
- package/dist/spec/llm/factory.js.map +1 -0
- package/dist/spec/llm/prompts.d.ts +24 -8
- package/dist/spec/llm/prompts.d.ts.map +1 -1
- package/dist/spec/llm/prompts.js +100 -50
- package/dist/spec/llm/prompts.js.map +1 -1
- package/dist/spec/llm/retry.d.ts +53 -0
- package/dist/spec/llm/retry.d.ts.map +1 -0
- package/dist/spec/llm/retry.js +153 -0
- package/dist/spec/llm/retry.js.map +1 -0
- package/dist/spec/mine/clusterer.d.ts +63 -0
- package/dist/spec/mine/clusterer.d.ts.map +1 -0
- package/dist/spec/mine/clusterer.js +904 -0
- package/dist/spec/mine/clusterer.js.map +1 -0
- package/dist/spec/mine/clustering/features.d.ts +38 -0
- package/dist/spec/mine/clustering/features.d.ts.map +1 -0
- package/dist/spec/mine/clustering/features.js +108 -0
- package/dist/spec/mine/clustering/features.js.map +1 -0
- package/dist/spec/mine/clustering/index.d.ts +62 -0
- package/dist/spec/mine/clustering/index.d.ts.map +1 -0
- package/dist/spec/mine/clustering/index.js +259 -0
- package/dist/spec/mine/clustering/index.js.map +1 -0
- package/dist/spec/mine/clustering/leiden.d.ts +61 -0
- package/dist/spec/mine/clustering/leiden.d.ts.map +1 -0
- package/dist/spec/mine/clustering/leiden.js +489 -0
- package/dist/spec/mine/clustering/leiden.js.map +1 -0
- package/dist/spec/mine/clustering/text-similarity.d.ts +22 -0
- package/dist/spec/mine/clustering/text-similarity.d.ts.map +1 -0
- package/dist/spec/mine/clustering/text-similarity.js +98 -0
- package/dist/spec/mine/clustering/text-similarity.js.map +1 -0
- package/dist/spec/mine/generator.d.ts +54 -0
- package/dist/spec/mine/generator.d.ts.map +1 -0
- package/dist/spec/mine/generator.js +267 -0
- package/dist/spec/mine/generator.js.map +1 -0
- package/dist/spec/mine/persist.d.ts +37 -0
- package/dist/spec/mine/persist.d.ts.map +1 -0
- package/dist/spec/mine/persist.js +170 -0
- package/dist/spec/mine/persist.js.map +1 -0
- package/dist/spec/mine/pipeline.d.ts +41 -0
- package/dist/spec/mine/pipeline.d.ts.map +1 -0
- package/dist/spec/mine/pipeline.js +236 -0
- package/dist/spec/mine/pipeline.js.map +1 -0
- package/dist/spec/mine/progress-handler.d.ts +22 -0
- package/dist/spec/mine/progress-handler.d.ts.map +1 -0
- package/dist/spec/mine/progress-handler.js +108 -0
- package/dist/spec/mine/progress-handler.js.map +1 -0
- package/dist/spec/mine/progress.d.ts +23 -0
- package/dist/spec/mine/progress.d.ts.map +1 -0
- package/dist/spec/mine/progress.js +12 -0
- package/dist/spec/mine/progress.js.map +1 -0
- package/dist/spec/mine/scanner.d.ts +59 -0
- package/dist/spec/mine/scanner.d.ts.map +1 -0
- package/dist/spec/mine/scanner.js +383 -0
- package/dist/spec/mine/scanner.js.map +1 -0
- package/dist/spec/types.d.ts +32 -0
- package/dist/spec/types.d.ts.map +1 -1
- package/dist/spec/ui/index.d.ts +9 -0
- package/dist/spec/ui/index.d.ts.map +1 -0
- package/dist/spec/ui/index.js +16 -0
- package/dist/spec/ui/index.js.map +1 -0
- package/dist/spec/ui/progress-handler.d.ts +33 -0
- package/dist/spec/ui/progress-handler.d.ts.map +1 -0
- package/dist/spec/ui/progress-handler.js +132 -0
- package/dist/spec/ui/progress-handler.js.map +1 -0
- package/dist/spec/ui/progress.d.ts +24 -0
- package/dist/spec/ui/progress.d.ts.map +1 -0
- package/dist/spec/ui/progress.js +13 -0
- package/dist/spec/ui/progress.js.map +1 -0
- package/dist/spec/utils/fs.d.ts +45 -0
- package/dist/spec/utils/fs.d.ts.map +1 -0
- package/dist/spec/utils/fs.js +163 -0
- package/dist/spec/utils/fs.js.map +1 -0
- package/dist/spec/utils/index.d.ts +12 -0
- package/dist/spec/utils/index.d.ts.map +1 -0
- package/dist/spec/utils/index.js +26 -0
- package/dist/spec/utils/index.js.map +1 -0
- package/dist/spec/utils/meta.d.ts +32 -0
- package/dist/spec/utils/meta.d.ts.map +1 -0
- package/dist/spec/utils/meta.js +122 -0
- package/dist/spec/utils/meta.js.map +1 -0
- package/dist/spec/utils/truncate.d.ts +86 -0
- package/dist/spec/utils/truncate.d.ts.map +1 -0
- package/dist/spec/utils/truncate.js +172 -0
- package/dist/spec/utils/truncate.js.map +1 -0
- package/dist/spec/utils.d.ts +4 -16
- package/dist/spec/utils.d.ts.map +1 -1
- package/dist/spec/utils.js +6 -58
- package/dist/spec/utils.js.map +1 -1
- package/dist/sync/watcher.d.ts +25 -1
- package/dist/sync/watcher.d.ts.map +1 -1
- package/dist/sync/watcher.js +76 -3
- package/dist/sync/watcher.js.map +1 -1
- package/dist/telemetry/index.js +3 -3
- package/dist/telemetry/index.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -3
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Spec file discovery and metadata extraction.
|
|
4
|
+
*
|
|
5
|
+
* Replaces `commit4spec/reverse_engineer/spec_extractor.py`.
|
|
6
|
+
* Discovers spec files in a storage directory and extracts structured
|
|
7
|
+
* metadata (title, subtitles).
|
|
8
|
+
*
|
|
9
|
+
* @module spec/build/spec-extractor
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.extractTitleFromMarkdown = extractTitleFromMarkdown;
|
|
46
|
+
exports.extractMarkdownHeadings = extractMarkdownHeadings;
|
|
47
|
+
exports.extractSpecMetadata = extractSpecMetadata;
|
|
48
|
+
const fs = __importStar(require("fs"));
|
|
49
|
+
const path = __importStar(require("path"));
|
|
50
|
+
const config_1 = require("../config");
|
|
51
|
+
const utils_1 = require("../utils");
|
|
52
|
+
const errors_1 = require("../../errors");
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// Constants
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
const HEADING_RE = /^(#{1,6})\s+(.*)/;
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// extractTitleFromMarkdown
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
/**
|
|
61
|
+
* Extract a title from markdown content: the first `# ` heading with any
|
|
62
|
+
* trailing `SPEC` suffix stripped. Falls back to `fallback` when no usable
|
|
63
|
+
* heading is found.
|
|
64
|
+
*/
|
|
65
|
+
function extractTitleFromMarkdown(content, fallback) {
|
|
66
|
+
const firstH1Match = content.match(/^#\s+(.*)/m);
|
|
67
|
+
if (firstH1Match && firstH1Match[1]) {
|
|
68
|
+
const title = firstH1Match[1].trim().replace(/\s*SPEC\s*$/i, '');
|
|
69
|
+
if (title)
|
|
70
|
+
return title;
|
|
71
|
+
}
|
|
72
|
+
return fallback;
|
|
73
|
+
}
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// extractMarkdownHeadings
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
/**
|
|
78
|
+
* Parse ATX headings from markdown content and build breadcrumb-path strings
|
|
79
|
+
* with content previews.
|
|
80
|
+
*
|
|
81
|
+
* Algorithm (ported from `spec_extractor.py:50-88`):
|
|
82
|
+
*
|
|
83
|
+
* 1. Find all `#` … `######` headings (ATX-style) and their line positions.
|
|
84
|
+
* 2. Walk through headings, maintaining a breadcrumb stack — pop until the
|
|
85
|
+
* stack is shorter than the current heading's level, then push the new
|
|
86
|
+
* heading text.
|
|
87
|
+
* 3. For each heading, collect the "direct content" lines — non-heading,
|
|
88
|
+
* non-empty lines between this heading and the next heading of equal or
|
|
89
|
+
* higher level (or EOF).
|
|
90
|
+
* 4. Skip headings that have sub-headings but no direct content.
|
|
91
|
+
* 5. Build a display string: `breadcrumb_path - first_direct_content_line`.
|
|
92
|
+
* 6. Strip `SPEC` suffix from level-1 (root) breadcrumb parts.
|
|
93
|
+
* 7. Truncate the preview to `maxContentLen` characters, appending `…`
|
|
94
|
+
* when truncated.
|
|
95
|
+
*
|
|
96
|
+
* @param content - Raw markdown string.
|
|
97
|
+
* @param maxContentLen - Max characters for the content preview (default 200).
|
|
98
|
+
* @returns Array of formatted heading strings.
|
|
99
|
+
*/
|
|
100
|
+
function extractMarkdownHeadings(content, maxContentLen = 200) {
|
|
101
|
+
const lines = content.split('\n');
|
|
102
|
+
const headings = [];
|
|
103
|
+
for (let i = 0; i < lines.length; i++) {
|
|
104
|
+
const match = HEADING_RE.exec(lines[i]);
|
|
105
|
+
if (!match)
|
|
106
|
+
continue;
|
|
107
|
+
const text = match[2].trim();
|
|
108
|
+
if (!text)
|
|
109
|
+
continue;
|
|
110
|
+
headings.push({
|
|
111
|
+
lineIndex: i,
|
|
112
|
+
level: match[1].length,
|
|
113
|
+
text,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
// Second pass: build breadcrumb and collect direct content.
|
|
117
|
+
const breadcrumb = [];
|
|
118
|
+
const result = [];
|
|
119
|
+
for (let hi = 0; hi < headings.length; hi++) {
|
|
120
|
+
const h = headings[hi];
|
|
121
|
+
// Adjust breadcrumb: pop until we're at the right depth.
|
|
122
|
+
while (breadcrumb.length >= h.level) {
|
|
123
|
+
breadcrumb.pop();
|
|
124
|
+
}
|
|
125
|
+
breadcrumb.push(h.text);
|
|
126
|
+
// Determine the end line of this heading's content section.
|
|
127
|
+
// The section ends at the next heading of equal or higher level (or EOF).
|
|
128
|
+
let endLine = lines.length;
|
|
129
|
+
for (let hj = hi + 1; hj < headings.length; hj++) {
|
|
130
|
+
const nextH = headings[hj];
|
|
131
|
+
if (nextH.level <= h.level) {
|
|
132
|
+
endLine = nextH.lineIndex;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Collect direct content: non-heading, non-empty lines within this section.
|
|
137
|
+
const directLines = [];
|
|
138
|
+
let hasSubHeadings = false;
|
|
139
|
+
for (let li = h.lineIndex + 1; li < endLine; li++) {
|
|
140
|
+
const line = lines[li].trim();
|
|
141
|
+
if (!line)
|
|
142
|
+
continue;
|
|
143
|
+
if (HEADING_RE.test(line)) {
|
|
144
|
+
hasSubHeadings = true;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
directLines.push(line);
|
|
148
|
+
}
|
|
149
|
+
// Skip headings that only contain sub-headings (no direct text).
|
|
150
|
+
if (hasSubHeadings && directLines.length === 0) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
// Build the display path.
|
|
154
|
+
let display = breadcrumb.join(' → ');
|
|
155
|
+
// Strip trailing SPEC from level-1 (root) headings.
|
|
156
|
+
if (breadcrumb.length === 1) {
|
|
157
|
+
display = display.replace(/\s*SPEC\s*$/i, '');
|
|
158
|
+
}
|
|
159
|
+
// Append content preview (first direct line, truncated).
|
|
160
|
+
if (directLines.length > 0) {
|
|
161
|
+
let preview = directLines[0];
|
|
162
|
+
if (preview.length > maxContentLen) {
|
|
163
|
+
preview = preview.slice(0, maxContentLen) + '…';
|
|
164
|
+
}
|
|
165
|
+
display += ' - ' + preview;
|
|
166
|
+
}
|
|
167
|
+
result.push(display);
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
// ---------------------------------------------------------------------------
|
|
172
|
+
// _findPrimaryDoc
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
/**
|
|
175
|
+
* Find the primary spec document by trying each candidate name.
|
|
176
|
+
*
|
|
177
|
+
* Replaces the `{spec_dir}` placeholder in each candidate with `specDirName`,
|
|
178
|
+
* then checks whether the resolved file exists in `specDirPath`. Returns the
|
|
179
|
+
* first match as `[resolvedName, absolutePath]`, or `null` when no candidate
|
|
180
|
+
* matches.
|
|
181
|
+
*
|
|
182
|
+
* Ported from `spec_extractor.py:94-114`.
|
|
183
|
+
*/
|
|
184
|
+
function _findPrimaryDoc(specDirPath, specDirName, candidates) {
|
|
185
|
+
for (const candidate of candidates) {
|
|
186
|
+
const resolved = candidate.replace(/\{spec_dir\}/g, specDirName);
|
|
187
|
+
const absPath = path.join(specDirPath, resolved);
|
|
188
|
+
if (fs.existsSync(absPath)) {
|
|
189
|
+
return [resolved, absPath];
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
// ---------------------------------------------------------------------------
|
|
195
|
+
// Glob helper
|
|
196
|
+
// ---------------------------------------------------------------------------
|
|
197
|
+
/**
|
|
198
|
+
* Simple glob-to-regex conversion for supplementary document matching.
|
|
199
|
+
*
|
|
200
|
+
* Only handles `*` (any non-separator characters) and literal text.
|
|
201
|
+
* Does not support `**`, `?`, or character classes — sufficient for
|
|
202
|
+
* patterns like `"*.md"` or `"changelog-*.md"`.
|
|
203
|
+
*/
|
|
204
|
+
function globToRegex(glob) {
|
|
205
|
+
// Escape regex-special characters except *
|
|
206
|
+
let pattern = '';
|
|
207
|
+
for (const ch of glob) {
|
|
208
|
+
if (ch === '*') {
|
|
209
|
+
pattern += '[^/]*';
|
|
210
|
+
}
|
|
211
|
+
else if ('.+^${}()|[]\\'.includes(ch)) {
|
|
212
|
+
pattern += '\\' + ch;
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
pattern += ch;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return new RegExp('^' + pattern + '$');
|
|
219
|
+
}
|
|
220
|
+
// ---------------------------------------------------------------------------
|
|
221
|
+
// _buildMetadata
|
|
222
|
+
// ---------------------------------------------------------------------------
|
|
223
|
+
/**
|
|
224
|
+
* Build `SpecMetadata` from raw spec content and supplementary documents.
|
|
225
|
+
*
|
|
226
|
+
* Ported from `spec_extractor.py:120-171`.
|
|
227
|
+
*
|
|
228
|
+
* 1. Extract a title from the first `# ` heading (stripping a trailing
|
|
229
|
+
* `SPEC` suffix); fallback to `specId`.
|
|
230
|
+
* 2. Collect subtitles via `extractMarkdownHeadings`.
|
|
231
|
+
* 3. Discover supplementary `.md` files in `specDirPath` that match
|
|
232
|
+
* `config.supplementaryGlobs` (excluding the primary doc) and merge
|
|
233
|
+
* their headings into the subtitle list.
|
|
234
|
+
*/
|
|
235
|
+
function _buildMetadata(specId, content, filePath, specDirPath, config) {
|
|
236
|
+
// ---- title ----
|
|
237
|
+
const title = extractTitleFromMarkdown(content, specId);
|
|
238
|
+
// ---- subtitles from primary doc ----
|
|
239
|
+
const subtitles = extractMarkdownHeadings(content);
|
|
240
|
+
// ---- supplementary docs ----
|
|
241
|
+
// Find the primary doc's filename so we can skip it.
|
|
242
|
+
const primaryDocName = path.basename(filePath);
|
|
243
|
+
let dirEntries;
|
|
244
|
+
try {
|
|
245
|
+
dirEntries = fs.readdirSync(specDirPath, { withFileTypes: true });
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
dirEntries = [];
|
|
249
|
+
}
|
|
250
|
+
const globRegexes = config.supplementaryGlobs.map((g) => globToRegex(g));
|
|
251
|
+
for (const entry of dirEntries) {
|
|
252
|
+
if (!entry.isFile())
|
|
253
|
+
continue;
|
|
254
|
+
if (!entry.name.endsWith('.md'))
|
|
255
|
+
continue;
|
|
256
|
+
if (entry.name === primaryDocName)
|
|
257
|
+
continue;
|
|
258
|
+
// Check if the file name matches any supplementary glob.
|
|
259
|
+
const matchesGlob = globRegexes.some((re) => re.test(entry.name));
|
|
260
|
+
if (!matchesGlob)
|
|
261
|
+
continue;
|
|
262
|
+
const suppPath = path.join(specDirPath, entry.name);
|
|
263
|
+
const suppContent = (0, utils_1.readFileContent)(suppPath);
|
|
264
|
+
if (suppContent === null)
|
|
265
|
+
continue;
|
|
266
|
+
const suppHeadings = extractMarkdownHeadings(suppContent);
|
|
267
|
+
for (const heading of suppHeadings) {
|
|
268
|
+
subtitles.push(heading);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
(0, errors_1.logDebug)('Built spec metadata', { specId, title, subtitleCount: subtitles.length });
|
|
272
|
+
return {
|
|
273
|
+
specId,
|
|
274
|
+
title,
|
|
275
|
+
subtitles,
|
|
276
|
+
filePath,
|
|
277
|
+
type: 'directory',
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
// ---------------------------------------------------------------------------
|
|
281
|
+
// extractSpecMetadata (public)
|
|
282
|
+
// ---------------------------------------------------------------------------
|
|
283
|
+
/**
|
|
284
|
+
* Discover and extract metadata for a single spec, given its storage location
|
|
285
|
+
* and directory name.
|
|
286
|
+
*
|
|
287
|
+
* Ported from `spec_extractor.py:177-237`.
|
|
288
|
+
*
|
|
289
|
+
* Two discovery branches are attempted in order:
|
|
290
|
+
*
|
|
291
|
+
* - **Flat-file**: checks `{specStoragePath}/{specDirName}.md`. If it exists,
|
|
292
|
+
* reads it and produces metadata with `type: 'flat-file'`.
|
|
293
|
+
* - **Directory**: checks `{specStoragePath}/{specDirName}/`. If it exists,
|
|
294
|
+
* searches for a primary document using `config.discovery.primaryDocCandidates`,
|
|
295
|
+
* reads it, and produces metadata with `type: 'directory'`.
|
|
296
|
+
*
|
|
297
|
+
* Returns `null` when neither branch yields a readable spec.
|
|
298
|
+
*
|
|
299
|
+
* @param specStoragePath - Root directory where specs are stored.
|
|
300
|
+
* @param specDirName - Name of the spec (e.g. "spec03", "auth-module").
|
|
301
|
+
* @param config - Optional full `SpecConfig`; falls back to defaults
|
|
302
|
+
* when omitted (discovery config resolved at call site).
|
|
303
|
+
*/
|
|
304
|
+
function extractSpecMetadata(specStoragePath, specDirName, config) {
|
|
305
|
+
// Resolve discovery config — use provided config or the built-in defaults.
|
|
306
|
+
const discoveryConfig = config?.discovery ?? config_1.DEFAULT_CONFIG.discovery;
|
|
307
|
+
// Branch A: flat-file
|
|
308
|
+
const flatFilePath = path.join(specStoragePath, `${specDirName}.md`);
|
|
309
|
+
if (fs.existsSync(flatFilePath) && fs.statSync(flatFilePath).isFile()) {
|
|
310
|
+
const content = (0, utils_1.readFileContent)(flatFilePath);
|
|
311
|
+
if (content !== null) {
|
|
312
|
+
(0, errors_1.logDebug)('Discovered flat-file spec', { specDirName, path: flatFilePath });
|
|
313
|
+
return {
|
|
314
|
+
specId: specDirName,
|
|
315
|
+
title: extractTitleFromMarkdown(content, specDirName),
|
|
316
|
+
subtitles: extractMarkdownHeadings(content),
|
|
317
|
+
filePath: flatFilePath,
|
|
318
|
+
type: 'flat-file',
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
// Branch B: directory
|
|
323
|
+
const specDirPath = path.join(specStoragePath, specDirName);
|
|
324
|
+
if (fs.existsSync(specDirPath) && fs.statSync(specDirPath).isDirectory()) {
|
|
325
|
+
const primary = _findPrimaryDoc(specDirPath, specDirName, discoveryConfig.primaryDocCandidates);
|
|
326
|
+
if (primary) {
|
|
327
|
+
const [, primaryAbsPath] = primary;
|
|
328
|
+
const content = (0, utils_1.readFileContent)(primaryAbsPath);
|
|
329
|
+
if (content !== null) {
|
|
330
|
+
(0, errors_1.logDebug)('Discovered directory spec', { specDirName, primaryDoc: primaryAbsPath });
|
|
331
|
+
const meta = _buildMetadata(specDirName, content, primaryAbsPath, specDirPath, discoveryConfig);
|
|
332
|
+
return { ...meta, type: 'directory' };
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
// Directory exists but no primary doc was found or it was unreadable.
|
|
336
|
+
(0, errors_1.logWarn)('Spec directory exists but no primary doc found', {
|
|
337
|
+
specDirName,
|
|
338
|
+
specDirPath,
|
|
339
|
+
candidates: discoveryConfig.primaryDocCandidates,
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
//# sourceMappingURL=spec-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-extractor.js","sourceRoot":"","sources":["../../../src/spec/build/spec-extractor.ts"],"names":[],"mappings":"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"}
|
package/dist/spec/config.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export interface SpecDiscoveryConfig {
|
|
2
2
|
primaryDocCandidates: string[];
|
|
3
3
|
supplementaryGlobs: string[];
|
|
4
|
-
commitInfoCandidates: string[];
|
|
5
4
|
}
|
|
6
5
|
export interface CommitScopeConfig {
|
|
7
6
|
scopeRegex: string;
|
|
@@ -19,12 +18,47 @@ export interface LLMConfig {
|
|
|
19
18
|
baseUrl?: string;
|
|
20
19
|
temperature: number;
|
|
21
20
|
maxTokens: number;
|
|
21
|
+
/** Maximum retries on transient errors. Default 3 (4 total attempts). */
|
|
22
|
+
maxRetries: number;
|
|
23
|
+
/** Base delay for exponential backoff in ms. Default 1000. */
|
|
24
|
+
retryBaseDelayMs: number;
|
|
25
|
+
/** Delay ceiling in ms. Default 30000. */
|
|
26
|
+
retryMaxDelayMs: number;
|
|
22
27
|
}
|
|
23
28
|
export interface SpecConfig {
|
|
24
29
|
discovery: SpecDiscoveryConfig;
|
|
25
30
|
commitScope: CommitScopeConfig;
|
|
26
31
|
llm: LLMConfig | null;
|
|
27
32
|
}
|
|
33
|
+
export interface MineConfig {
|
|
34
|
+
/** Maximum commits to scan (default: 100). */
|
|
35
|
+
limit: number;
|
|
36
|
+
/** Clustering similarity threshold (0-1, default: 0.5). */
|
|
37
|
+
threshold: number;
|
|
38
|
+
/** Maximum number of clusters to produce (default: 10). */
|
|
39
|
+
maxCluster: number;
|
|
40
|
+
/** Output directory for generated spec files (default: '.spec'). */
|
|
41
|
+
outputDir: string;
|
|
42
|
+
/** Optional path to a spec template markdown file. */
|
|
43
|
+
template?: string;
|
|
44
|
+
/** Skip LLM generation — only output clusters (default: false). */
|
|
45
|
+
skipLlm: boolean;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Build a MineConfig from raw option values (typically from CLI parsing).
|
|
49
|
+
*
|
|
50
|
+
* @param options - Raw option values from the CLI action handler.
|
|
51
|
+
* @param llmConfigured - Whether a valid LLM config was loaded. When false,
|
|
52
|
+
* skipLlm is forced to true regardless of the option value.
|
|
53
|
+
*/
|
|
54
|
+
export declare function createMineConfig(options: {
|
|
55
|
+
limit: number;
|
|
56
|
+
threshold: number;
|
|
57
|
+
maxCluster: number;
|
|
58
|
+
outputDir: string;
|
|
59
|
+
template?: string;
|
|
60
|
+
skipLlm: boolean;
|
|
61
|
+
}, llmConfigured: boolean): MineConfig;
|
|
28
62
|
export declare const DEFAULT_CONFIG: SpecConfig;
|
|
29
63
|
/**
|
|
30
64
|
* Load spec config from `${SPEC_DATA_DIR}/configs.json` in the given repo path.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/spec/config.ts"],"names":[],"mappings":"AAoCA,MAAM,WAAW,mBAAmB;IAClC,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,kBAAkB,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/spec/config.ts"],"names":[],"mappings":"AAoCA,MAAM,WAAW,mBAAmB;IAClC,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE;QACT,aAAa,EAAE,MAAM,EAAE,CAAC;QACxB,SAAS,EAAE,OAAO,CAAC;QACnB,aAAa,EAAE,OAAO,CAAC;KACxB,CAAC;CACH;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,QAAQ,GAAG,WAAW,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,gBAAgB,EAAE,MAAM,CAAC;IACzB,0CAA0C;IAC1C,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,mBAAmB,CAAC;IAC/B,WAAW,EAAE,iBAAiB,CAAC;IAC/B,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE;IACP,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB,EACD,aAAa,EAAE,OAAO,GACrB,UAAU,CASZ;AAMD,eAAO,MAAM,cAAc,EAAE,UAsBb,CAAC;AAmCjB;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAkD3D"}
|
package/dist/spec/config.js
CHANGED
|
@@ -34,11 +34,12 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.DEFAULT_CONFIG = void 0;
|
|
37
|
+
exports.createMineConfig = createMineConfig;
|
|
37
38
|
exports.loadSpecConfig = loadSpecConfig;
|
|
38
39
|
/**
|
|
39
40
|
* Spec configuration module — replaces `commit4spec/utils/config.py`.
|
|
40
41
|
*
|
|
41
|
-
* Loads spec
|
|
42
|
+
* Loads spec build/evolve configuration from `${SPEC_DATA_DIR}/configs.json`
|
|
42
43
|
* within a repository. Discovery and commitScope sections fall back to code
|
|
43
44
|
* defaults; the `llm` section must be explicitly configured by the user —
|
|
44
45
|
* there are no hard-coded LLM defaults.
|
|
@@ -66,6 +67,23 @@ const fs = __importStar(require("fs"));
|
|
|
66
67
|
const path = __importStar(require("path"));
|
|
67
68
|
const errors_1 = require("../errors");
|
|
68
69
|
const utils_1 = require("./utils");
|
|
70
|
+
/**
|
|
71
|
+
* Build a MineConfig from raw option values (typically from CLI parsing).
|
|
72
|
+
*
|
|
73
|
+
* @param options - Raw option values from the CLI action handler.
|
|
74
|
+
* @param llmConfigured - Whether a valid LLM config was loaded. When false,
|
|
75
|
+
* skipLlm is forced to true regardless of the option value.
|
|
76
|
+
*/
|
|
77
|
+
function createMineConfig(options, llmConfigured) {
|
|
78
|
+
return {
|
|
79
|
+
limit: options.limit,
|
|
80
|
+
threshold: options.threshold,
|
|
81
|
+
maxCluster: options.maxCluster,
|
|
82
|
+
outputDir: options.outputDir,
|
|
83
|
+
template: options.template,
|
|
84
|
+
skipLlm: options.skipLlm || !llmConfigured,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
69
87
|
// ---------------------------------------------------------------------------
|
|
70
88
|
// Defaults (match commit4spec/utils/config.py exactly)
|
|
71
89
|
// ---------------------------------------------------------------------------
|
|
@@ -80,7 +98,6 @@ exports.DEFAULT_CONFIG = Object.freeze({
|
|
|
80
98
|
'spec-{spec_dir}.md',
|
|
81
99
|
]),
|
|
82
100
|
supplementaryGlobs: Object.freeze(['logic/**/*.md', 'design/**/*.md']),
|
|
83
|
-
commitInfoCandidates: Object.freeze(['commit-info.md']),
|
|
84
101
|
}),
|
|
85
102
|
commitScope: Object.freeze({
|
|
86
103
|
scopeRegex: '^(?:feat|fix|chore|docs|style|refactor|perf|test|build|ci|revert)\\((?:review\\/)?(spec\\d+)\\)',
|
|
@@ -183,7 +200,6 @@ function normalizeDiscovery(val, file) {
|
|
|
183
200
|
return {
|
|
184
201
|
primaryDocCandidates: normalizeStringArray(val.primaryDocCandidates, def.primaryDocCandidates, 'discovery.primaryDocCandidates', file),
|
|
185
202
|
supplementaryGlobs: normalizeStringArray(val.supplementaryGlobs, def.supplementaryGlobs, 'discovery.supplementaryGlobs', file),
|
|
186
|
-
commitInfoCandidates: normalizeStringArray(val.commitInfoCandidates, def.commitInfoCandidates, 'discovery.commitInfoCandidates', file),
|
|
187
203
|
};
|
|
188
204
|
}
|
|
189
205
|
function normalizeCommitScope(val, file) {
|
|
@@ -231,7 +247,7 @@ const LLM_CONFIG_EXAMPLE = [
|
|
|
231
247
|
*
|
|
232
248
|
* Optional fields with defaults:
|
|
233
249
|
* - `temperature`: defaults to 0.2
|
|
234
|
-
* - `maxTokens`: defaults to
|
|
250
|
+
* - `maxTokens`: defaults to 20000
|
|
235
251
|
*
|
|
236
252
|
* Returns a valid LLMConfig, or `null` if the user did not provide an `llm`
|
|
237
253
|
* section at all (no error in that case — callers decide how to handle it).
|
|
@@ -269,7 +285,16 @@ function validateLLM(val, file) {
|
|
|
269
285
|
: 0.2,
|
|
270
286
|
maxTokens: typeof val.maxTokens === 'number' && Number.isInteger(val.maxTokens) && val.maxTokens > 0
|
|
271
287
|
? val.maxTokens
|
|
272
|
-
:
|
|
288
|
+
: 20000,
|
|
289
|
+
maxRetries: typeof val.maxRetries === 'number' && Number.isInteger(val.maxRetries) && val.maxRetries >= 0
|
|
290
|
+
? val.maxRetries
|
|
291
|
+
: 3,
|
|
292
|
+
retryBaseDelayMs: typeof val.retryBaseDelayMs === 'number' && val.retryBaseDelayMs > 0
|
|
293
|
+
? val.retryBaseDelayMs
|
|
294
|
+
: 1000,
|
|
295
|
+
retryMaxDelayMs: typeof val.retryMaxDelayMs === 'number' && val.retryMaxDelayMs > 0
|
|
296
|
+
? val.retryMaxDelayMs
|
|
297
|
+
: 30000,
|
|
273
298
|
};
|
|
274
299
|
}
|
|
275
300
|
// ---------------------------------------------------------------------------
|
package/dist/spec/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/spec/config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/spec/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fts.d.ts","sourceRoot":"","sources":["../../../src/spec/db/fts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"fts.d.ts","sourceRoot":"","sources":["../../../src/spec/db/fts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAW5C;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQpD;AAuLD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CACzB,EAAE,EAAE,cAAc,EAClB,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,MAAW,GACjB,gBAAgB,EAAE,CAsCpB;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,cAAc,EAClB,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,MAAW,GACjB,MAAM,EAAE,CAqBV"}
|
package/dist/spec/db/fts.js
CHANGED
|
@@ -35,6 +35,8 @@ exports.segmentCjk = segmentCjk;
|
|
|
35
35
|
exports.escapeFtsQuery = escapeFtsQuery;
|
|
36
36
|
exports.searchSpecs = searchSpecs;
|
|
37
37
|
exports.searchCodeFragments = searchCodeFragments;
|
|
38
|
+
const spec_node_1 = require("./spec-node");
|
|
39
|
+
const sql_utils_1 = require("./sql-utils");
|
|
38
40
|
// ===========================================================================
|
|
39
41
|
// CJK Segmentation
|
|
40
42
|
// ===========================================================================
|
|
@@ -129,20 +131,13 @@ function searchSpecsFts(db, query, limit, oversample = 3) {
|
|
|
129
131
|
}
|
|
130
132
|
const scored = [];
|
|
131
133
|
for (const row of rows) {
|
|
132
|
-
let subtitles;
|
|
133
|
-
try {
|
|
134
|
-
subtitles = JSON.parse(row.subtitles || '[]');
|
|
135
|
-
}
|
|
136
|
-
catch {
|
|
137
|
-
subtitles = [];
|
|
138
|
-
}
|
|
139
134
|
const boost = scoreTitleMatch(row.title, query);
|
|
140
135
|
scored.push({
|
|
141
136
|
score: boost,
|
|
142
137
|
result: {
|
|
143
138
|
id: row.id,
|
|
144
139
|
title: row.title,
|
|
145
|
-
subtitles,
|
|
140
|
+
subtitles: (0, spec_node_1.parseSubtitlesJson)(row.subtitles),
|
|
146
141
|
_score: boost,
|
|
147
142
|
_method: 'fts5',
|
|
148
143
|
},
|
|
@@ -162,8 +157,7 @@ function searchSpecsFts(db, query, limit, oversample = 3) {
|
|
|
162
157
|
*/
|
|
163
158
|
function searchSpecsLike(db, query, limit, excludeIds) {
|
|
164
159
|
// Escape LIKE metacharacters so '%' and '_' are treated as literals
|
|
165
|
-
const
|
|
166
|
-
const likePat = `%${escaped}%`;
|
|
160
|
+
const likePat = `%${(0, sql_utils_1.escapeLike)(query)}%`;
|
|
167
161
|
const rows = db
|
|
168
162
|
.prepare(`SELECT id, title, subtitles FROM spec_nodes
|
|
169
163
|
WHERE title LIKE ? ESCAPE '\\' OR subtitles LIKE ? ESCAPE '\\'
|
|
@@ -173,13 +167,6 @@ function searchSpecsLike(db, query, limit, excludeIds) {
|
|
|
173
167
|
for (const row of rows) {
|
|
174
168
|
if (excludeIds.has(row.id))
|
|
175
169
|
continue;
|
|
176
|
-
let subtitles;
|
|
177
|
-
try {
|
|
178
|
-
subtitles = JSON.parse(row.subtitles || '[]');
|
|
179
|
-
}
|
|
180
|
-
catch {
|
|
181
|
-
subtitles = [];
|
|
182
|
-
}
|
|
183
170
|
const [score, tier] = likeScore(row.title, query);
|
|
184
171
|
scored.push({
|
|
185
172
|
score,
|
|
@@ -187,7 +174,7 @@ function searchSpecsLike(db, query, limit, excludeIds) {
|
|
|
187
174
|
result: {
|
|
188
175
|
id: row.id,
|
|
189
176
|
title: row.title,
|
|
190
|
-
subtitles,
|
|
177
|
+
subtitles: (0, spec_node_1.parseSubtitlesJson)(row.subtitles),
|
|
191
178
|
_score: score,
|
|
192
179
|
_method: 'like',
|
|
193
180
|
_tier: tier,
|
|
@@ -212,22 +199,13 @@ function discoveryFallback(db, limit) {
|
|
|
212
199
|
const rows = db
|
|
213
200
|
.prepare('SELECT id, title, subtitles FROM spec_nodes ORDER BY timestamp DESC LIMIT ?')
|
|
214
201
|
.all(limit);
|
|
215
|
-
return rows.map((row) => {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
223
|
-
return {
|
|
224
|
-
id: row.id,
|
|
225
|
-
title: row.title,
|
|
226
|
-
subtitles,
|
|
227
|
-
_score: 0.0,
|
|
228
|
-
_method: 'discovery',
|
|
229
|
-
};
|
|
230
|
-
});
|
|
202
|
+
return rows.map((row) => ({
|
|
203
|
+
id: row.id,
|
|
204
|
+
title: row.title,
|
|
205
|
+
subtitles: (0, spec_node_1.parseSubtitlesJson)(row.subtitles),
|
|
206
|
+
_score: 0.0,
|
|
207
|
+
_method: 'discovery',
|
|
208
|
+
}));
|
|
231
209
|
}
|
|
232
210
|
// ===========================================================================
|
|
233
211
|
// Combined Search (public API)
|
|
@@ -251,22 +229,13 @@ function searchSpecs(db, query, limit = 10) {
|
|
|
251
229
|
const rows = db
|
|
252
230
|
.prepare('SELECT id, title, subtitles FROM spec_nodes ORDER BY id LIMIT ?')
|
|
253
231
|
.all(limit);
|
|
254
|
-
return rows.map((row) => {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
}
|
|
262
|
-
return {
|
|
263
|
-
id: row.id,
|
|
264
|
-
title: row.title,
|
|
265
|
-
subtitles,
|
|
266
|
-
_score: 0.0,
|
|
267
|
-
_method: 'all',
|
|
268
|
-
};
|
|
269
|
-
});
|
|
232
|
+
return rows.map((row) => ({
|
|
233
|
+
id: row.id,
|
|
234
|
+
title: row.title,
|
|
235
|
+
subtitles: (0, spec_node_1.parseSubtitlesJson)(row.subtitles),
|
|
236
|
+
_score: 0.0,
|
|
237
|
+
_method: 'all',
|
|
238
|
+
}));
|
|
270
239
|
}
|
|
271
240
|
// Stage 1: FTS5 weighted search
|
|
272
241
|
const ftsResults = searchSpecsFts(db, query, limit);
|