maestro-flow 0.5.34 → 0.5.36
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/.agents/agents/cli-explore-agent.md +71 -68
- package/.agents/agents/workflow-analyzer.md +1 -0
- package/.agents/agents/workflow-collab-planner.md +1 -0
- package/.agents/agents/workflow-debugger.md +1 -0
- package/.agents/agents/workflow-executor.md +1 -0
- package/.agents/agents/workflow-planner.md +2 -0
- package/.agents/skills/domain-add/SKILL.md +71 -0
- package/.agents/skills/maestro/SKILL.md +7 -6
- package/.agents/skills/maestro-amend/SKILL.md +0 -2
- package/.agents/skills/maestro-analyze/SKILL.md +9 -0
- package/.agents/skills/maestro-brainstorm/SKILL.md +10 -1
- package/.agents/skills/maestro-collab/SKILL.md +14 -1
- package/.agents/skills/maestro-help/SKILL.md +1 -1
- package/.agents/skills/maestro-help/index/catalog.json +0 -1
- package/.agents/skills/maestro-help/phases/01-parse-intent.md +1 -1
- package/.agents/skills/maestro-next/SKILL.md +15 -4
- package/.agents/skills/maestro-overlay/SKILL.md +4 -3
- package/.agents/skills/maestro-plan/SKILL.md +15 -4
- package/.agents/skills/maestro-ralph/SKILL.md +135 -31
- package/.agents/skills/maestro-ralph-execute/SKILL.md +51 -10
- package/.agents/skills/maestro-tools-register/SKILL.md +0 -6
- package/.agents/skills/maestro-ui-codify/SKILL.md +0 -2
- package/.agents/skills/manage-kg-extractors/SKILL.md +0 -2
- package/.agents/skills/quality-test/SKILL.md +25 -1
- package/.agents/skills/spec-load/SKILL.md +0 -1
- package/.agents/skills/spec-setup/SKILL.md +0 -1
- package/.agents/skills/team-lifecycle-v4/roles/analyst/role.md +13 -7
- package/.agents/skills/team-quality-assurance/roles/scout/role.md +15 -11
- package/.agents/skills/team-tech-debt/roles/scanner/role.md +1 -1
- package/.agents/skills/team-ultra-analyze/roles/explorer/role.md +23 -16
- package/.agy/agents/cli-explore-agent.md +71 -68
- package/.agy/agents/workflow-analyzer.md +1 -0
- package/.agy/agents/workflow-collab-planner.md +1 -0
- package/.agy/agents/workflow-debugger.md +1 -0
- package/.agy/agents/workflow-executor.md +1 -0
- package/.agy/agents/workflow-planner.md +2 -0
- package/.agy/skills/domain-add/SKILL.md +68 -0
- package/.agy/skills/maestro/SKILL.md +7 -6
- package/.agy/skills/maestro-amend/SKILL.md +0 -2
- package/.agy/skills/maestro-analyze/SKILL.md +9 -0
- package/.agy/skills/maestro-brainstorm/SKILL.md +10 -1
- package/.agy/skills/maestro-collab/SKILL.md +14 -1
- package/.agy/skills/maestro-help/SKILL.md +1 -1
- package/.agy/skills/maestro-help/index/catalog.json +0 -1
- package/.agy/skills/maestro-help/phases/01-parse-intent.md +1 -1
- package/.agy/skills/maestro-next/SKILL.md +15 -4
- package/.agy/skills/maestro-overlay/SKILL.md +4 -3
- package/.agy/skills/maestro-plan/SKILL.md +15 -4
- package/.agy/skills/maestro-ralph/SKILL.md +135 -31
- package/.agy/skills/maestro-ralph-execute/SKILL.md +51 -10
- package/.agy/skills/maestro-tools-register/SKILL.md +0 -6
- package/.agy/skills/maestro-ui-codify/SKILL.md +0 -2
- package/.agy/skills/manage-kg-extractors/SKILL.md +0 -2
- package/.agy/skills/quality-test/SKILL.md +25 -1
- package/.agy/skills/spec-load/SKILL.md +0 -1
- package/.agy/skills/spec-setup/SKILL.md +0 -1
- package/.agy/skills/team-lifecycle-v4/roles/analyst/role.md +13 -7
- package/.agy/skills/team-quality-assurance/roles/scout/role.md +15 -11
- package/.agy/skills/team-tech-debt/roles/scanner/role.md +1 -1
- package/.agy/skills/team-ultra-analyze/roles/explorer/role.md +23 -16
- package/.claude/agents/cli-explore-agent.md +71 -68
- package/.claude/agents/workflow-analyzer.md +1 -0
- package/.claude/agents/workflow-collab-planner.md +1 -0
- package/.claude/agents/workflow-debugger.md +1 -0
- package/.claude/agents/workflow-executor.md +1 -0
- package/.claude/agents/workflow-planner.md +2 -0
- package/.claude/commands/domain-add.md +69 -0
- package/.claude/commands/maestro-amend.md +0 -2
- package/.claude/commands/maestro-analyze.md +9 -0
- package/.claude/commands/maestro-brainstorm.md +10 -1
- package/.claude/commands/maestro-collab.md +14 -1
- package/.claude/commands/maestro-next.md +15 -4
- package/.claude/commands/maestro-overlay.md +4 -3
- package/.claude/commands/maestro-plan.md +15 -4
- package/.claude/commands/maestro-ralph-execute.md +51 -10
- package/.claude/commands/maestro-ralph.md +135 -31
- package/.claude/commands/maestro-tools-register.md +0 -6
- package/.claude/commands/maestro-ui-codify.md +0 -2
- package/.claude/commands/maestro.md +7 -6
- package/.claude/commands/manage-kg-extractors.md +0 -2
- package/.claude/commands/quality-test.md +25 -1
- package/.claude/commands/spec-load.md +0 -1
- package/.claude/commands/spec-setup.md +0 -1
- package/.claude/skills/maestro-help/SKILL.md +1 -1
- package/.claude/skills/maestro-help/index/catalog.json +0 -1
- package/.claude/skills/maestro-help/phases/01-parse-intent.md +1 -1
- package/.claude/skills/team-lifecycle-v4/roles/analyst/role.md +13 -7
- package/.claude/skills/team-quality-assurance/roles/scout/role.md +15 -11
- package/.claude/skills/team-tech-debt/roles/scanner/role.md +1 -1
- package/.claude/skills/team-ultra-analyze/roles/explorer/role.md +23 -16
- package/.codex/skills/domain-add/SKILL.md +79 -0
- package/.codex/skills/domain-discover/SKILL.md +43 -0
- package/.codex/skills/domain-list/SKILL.md +38 -0
- package/.codex/skills/learn-follow/SKILL.md +0 -3
- package/.codex/skills/learn-investigate/SKILL.md +0 -3
- package/.codex/skills/learn-retro/SKILL.md +0 -2
- package/.codex/skills/maestro/SKILL.md +34 -13
- package/.codex/skills/maestro-amend/SKILL.md +0 -2
- package/.codex/skills/maestro-analyze/SKILL.md +36 -6
- package/.codex/skills/maestro-blueprint/SKILL.md +0 -4
- package/.codex/skills/maestro-brainstorm/SKILL.md +46 -6
- package/.codex/skills/maestro-collab/SKILL.md +14 -1
- package/.codex/skills/maestro-companion/SKILL.md +0 -2
- package/.codex/skills/maestro-execute/SKILL.md +25 -3
- package/.codex/skills/maestro-fork/SKILL.md +0 -2
- package/.codex/skills/maestro-grill/SKILL.md +9 -1
- package/.codex/skills/maestro-next/SKILL.md +12 -5
- package/.codex/skills/maestro-plan/SKILL.md +43 -5
- package/.codex/skills/maestro-ralph/SKILL.md +10 -3
- package/.codex/skills/maestro-ralph-execute/SKILL.md +51 -10
- package/.codex/skills/maestro-roadmap/SKILL.md +30 -3
- package/.codex/skills/manage-wiki/SKILL.md +0 -2
- package/.codex/skills/odyssey-debug/SKILL.md +0 -2
- package/.codex/skills/odyssey-improve/SKILL.md +0 -6
- package/.codex/skills/odyssey-review-test-fix/SKILL.md +0 -3
- package/.codex/skills/odyssey-ui/SKILL.md +0 -3
- package/.codex/skills/quality-review/SKILL.md +9 -0
- package/.codex/skills/spec-setup/SKILL.md +0 -2
- package/.codex/skills/team-coordinate/SKILL.md +0 -3
- package/.codex/skills/team-lifecycle-v4/instructions/agent-instruction.md +0 -2
- package/README.md +28 -5
- package/README.zh-CN.md +28 -5
- package/chains/_intent-map.json +36 -0
- package/chains/blueprint-driven.json +49 -0
- package/chains/grill-driven.json +51 -0
- package/dashboard/dist-server/dashboard/src/server/agents/adapter-factory.js +4 -0
- package/dashboard/dist-server/dashboard/src/server/agents/adapter-factory.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/server/agents/api-explore-adapter.d.ts +6 -0
- package/dashboard/dist-server/dashboard/src/server/agents/api-explore-adapter.js +36 -0
- package/dashboard/dist-server/dashboard/src/server/agents/api-explore-adapter.js.map +1 -0
- package/dashboard/dist-server/dashboard/src/server/agents/stream-json-adapter.d.ts +1 -1
- package/dashboard/dist-server/dashboard/src/server/agents/stream-json-adapter.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/server/wiki/embedding.d.ts +82 -0
- package/dashboard/dist-server/dashboard/src/server/wiki/embedding.js +444 -0
- package/dashboard/dist-server/dashboard/src/server/wiki/embedding.js.map +1 -0
- package/dashboard/dist-server/dashboard/src/server/wiki/search.d.ts +47 -1
- package/dashboard/dist-server/dashboard/src/server/wiki/search.js +426 -19
- package/dashboard/dist-server/dashboard/src/server/wiki/search.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/server/wiki/stress.test.js +16 -0
- package/dashboard/dist-server/dashboard/src/server/wiki/stress.test.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/server/wiki/virtual-wiki-adapters.d.ts +11 -0
- package/dashboard/dist-server/dashboard/src/server/wiki/virtual-wiki-adapters.js +492 -1
- package/dashboard/dist-server/dashboard/src/server/wiki/virtual-wiki-adapters.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.d.ts +18 -0
- package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.js +192 -9
- package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.test.js +42 -0
- package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.test.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/shared/constants.js +2 -0
- package/dashboard/dist-server/dashboard/src/shared/constants.js.map +1 -1
- package/dashboard/dist-server/shared/agent-types.d.ts +1 -1
- package/dashboard/dist-server/src/commands/hooks.d.ts +3 -0
- package/dashboard/dist-server/src/commands/hooks.js +60 -9
- package/dashboard/dist-server/src/commands/hooks.js.map +1 -1
- package/dashboard/dist-server/src/graph/kg/extraction/code/code-extractor.js +1 -1
- package/dashboard/dist-server/src/graph/kg/extraction/code/code-extractor.js.map +1 -1
- package/dashboard/dist-server/src/graph/kg/extraction/knowledge/domain-extractor.js +4 -2
- package/dashboard/dist-server/src/graph/kg/extraction/knowledge/domain-extractor.js.map +1 -1
- package/dashboard/dist-server/src/graph/kg/extraction/knowledge-extractor-registry.js +6 -1
- package/dashboard/dist-server/src/graph/kg/extraction/knowledge-extractor-registry.js.map +1 -1
- package/dashboard/dist-server/src/graph/kg/extraction/orchestrator.js +2 -6
- package/dashboard/dist-server/src/graph/kg/extraction/orchestrator.js.map +1 -1
- package/dashboard/dist-server/src/hooks/session-context.js +37 -1
- package/dashboard/dist-server/src/hooks/session-context.js.map +1 -1
- package/dashboard/dist-server/src/search/daemon.d.ts +42 -0
- package/dashboard/dist-server/src/search/daemon.js +180 -0
- package/dashboard/dist-server/src/search/daemon.js.map +1 -0
- package/dashboard/dist-server/src/tools/domain-loader.d.ts +4 -1
- package/dashboard/dist-server/src/tools/domain-loader.js +56 -25
- package/dashboard/dist-server/src/tools/domain-loader.js.map +1 -1
- package/dashboard/dist-server/src/tools/domain-schema.d.ts +1 -1
- package/dashboard/dist-server/src/tools/domain-schema.js +1 -1
- package/dist/shared/agent-types.d.ts +1 -1
- package/dist/shared/agent-types.d.ts.map +1 -1
- package/dist/src/agents/api-explore/agent-loop.d.ts +14 -0
- package/dist/src/agents/api-explore/agent-loop.d.ts.map +1 -0
- package/dist/src/agents/api-explore/agent-loop.js +86 -0
- package/dist/src/agents/api-explore/agent-loop.js.map +1 -0
- package/dist/src/agents/api-explore/config.d.ts +42 -0
- package/dist/src/agents/api-explore/config.d.ts.map +1 -0
- package/dist/src/agents/api-explore/config.js +99 -0
- package/dist/src/agents/api-explore/config.js.map +1 -0
- package/dist/src/agents/api-explore/index.d.ts +2 -0
- package/dist/src/agents/api-explore/index.d.ts.map +1 -0
- package/dist/src/agents/api-explore/index.js +102 -0
- package/dist/src/agents/api-explore/index.js.map +1 -0
- package/dist/src/agents/api-explore/llm.d.ts +28 -0
- package/dist/src/agents/api-explore/llm.d.ts.map +1 -0
- package/dist/src/agents/api-explore/llm.js +48 -0
- package/dist/src/agents/api-explore/llm.js.map +1 -0
- package/dist/src/agents/api-explore/prompt-parser.d.ts +23 -0
- package/dist/src/agents/api-explore/prompt-parser.d.ts.map +1 -0
- package/dist/src/agents/api-explore/prompt-parser.js +73 -0
- package/dist/src/agents/api-explore/prompt-parser.js.map +1 -0
- package/dist/src/agents/api-explore/runner.d.ts +65 -0
- package/dist/src/agents/api-explore/runner.d.ts.map +1 -0
- package/dist/src/agents/api-explore/runner.js +196 -0
- package/dist/src/agents/api-explore/runner.js.map +1 -0
- package/dist/src/agents/api-explore/session.d.ts +23 -0
- package/dist/src/agents/api-explore/session.d.ts.map +1 -0
- package/dist/src/agents/api-explore/session.js +57 -0
- package/dist/src/agents/api-explore/session.js.map +1 -0
- package/dist/src/agents/api-explore/stream-json-emitter.d.ts +10 -0
- package/dist/src/agents/api-explore/stream-json-emitter.d.ts.map +1 -0
- package/dist/src/agents/api-explore/stream-json-emitter.js +19 -0
- package/dist/src/agents/api-explore/stream-json-emitter.js.map +1 -0
- package/dist/src/agents/api-explore/system-prompt.d.ts +2 -0
- package/dist/src/agents/api-explore/system-prompt.d.ts.map +1 -0
- package/dist/src/agents/api-explore/system-prompt.js +31 -0
- package/dist/src/agents/api-explore/system-prompt.js.map +1 -0
- package/dist/src/agents/api-explore/tools.d.ts +11 -0
- package/dist/src/agents/api-explore/tools.d.ts.map +1 -0
- package/dist/src/agents/api-explore/tools.js +168 -0
- package/dist/src/agents/api-explore/tools.js.map +1 -0
- package/dist/src/agents/cli-agent-runner.d.ts.map +1 -1
- package/dist/src/agents/cli-agent-runner.js +3 -0
- package/dist/src/agents/cli-agent-runner.js.map +1 -1
- package/dist/src/cli.js +4 -0
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands/domain.d.ts.map +1 -1
- package/dist/src/commands/domain.js +5 -4
- package/dist/src/commands/domain.js.map +1 -1
- package/dist/src/commands/explore.d.ts +7 -0
- package/dist/src/commands/explore.d.ts.map +1 -0
- package/dist/src/commands/explore.js +201 -0
- package/dist/src/commands/explore.js.map +1 -0
- package/dist/src/commands/hooks.d.ts +3 -0
- package/dist/src/commands/hooks.d.ts.map +1 -1
- package/dist/src/commands/hooks.js +60 -9
- package/dist/src/commands/hooks.js.map +1 -1
- package/dist/src/commands/install.d.ts.map +1 -1
- package/dist/src/commands/install.js +42 -9
- package/dist/src/commands/install.js.map +1 -1
- package/dist/src/commands/search.d.ts +26 -4
- package/dist/src/commands/search.d.ts.map +1 -1
- package/dist/src/commands/search.js +359 -93
- package/dist/src/commands/search.js.map +1 -1
- package/dist/src/commands/update.d.ts.map +1 -1
- package/dist/src/commands/update.js +37 -21
- package/dist/src/commands/update.js.map +1 -1
- package/dist/src/commands/workspace.d.ts.map +1 -1
- package/dist/src/commands/workspace.js +9 -3
- package/dist/src/commands/workspace.js.map +1 -1
- package/dist/src/config/cli-tools-defaults.json +2 -1
- package/dist/src/core/install-executor.d.ts.map +1 -1
- package/dist/src/core/install-executor.js +6 -3
- package/dist/src/core/install-executor.js.map +1 -1
- package/dist/src/graph/kg/extraction/code/code-extractor.js +1 -1
- package/dist/src/graph/kg/extraction/code/code-extractor.js.map +1 -1
- package/dist/src/graph/kg/extraction/knowledge/domain-extractor.d.ts.map +1 -1
- package/dist/src/graph/kg/extraction/knowledge/domain-extractor.js +4 -2
- package/dist/src/graph/kg/extraction/knowledge/domain-extractor.js.map +1 -1
- package/dist/src/graph/kg/extraction/knowledge-extractor-registry.d.ts.map +1 -1
- package/dist/src/graph/kg/extraction/knowledge-extractor-registry.js +6 -1
- package/dist/src/graph/kg/extraction/knowledge-extractor-registry.js.map +1 -1
- package/dist/src/graph/kg/extraction/orchestrator.d.ts.map +1 -1
- package/dist/src/graph/kg/extraction/orchestrator.js +2 -6
- package/dist/src/graph/kg/extraction/orchestrator.js.map +1 -1
- package/dist/src/graph/kg/surface/cli.d.ts.map +1 -1
- package/dist/src/graph/kg/surface/cli.js +5 -2
- package/dist/src/graph/kg/surface/cli.js.map +1 -1
- package/dist/src/hooks/session-context.d.ts.map +1 -1
- package/dist/src/hooks/session-context.js +37 -1
- package/dist/src/hooks/session-context.js.map +1 -1
- package/dist/src/ralph/cmd-next.d.ts.map +1 -1
- package/dist/src/ralph/cmd-next.js +66 -4
- package/dist/src/ralph/cmd-next.js.map +1 -1
- package/dist/src/ralph/status-schema.d.ts +1 -0
- package/dist/src/ralph/status-schema.d.ts.map +1 -1
- package/dist/src/search/daemon.d.ts +43 -0
- package/dist/src/search/daemon.d.ts.map +1 -0
- package/dist/src/search/daemon.js +180 -0
- package/dist/src/search/daemon.js.map +1 -0
- package/dist/src/tools/__tests__/domain-search-debug.js +3 -1
- package/dist/src/tools/__tests__/domain-search-debug.js.map +1 -1
- package/dist/src/tools/domain-loader.d.ts +4 -1
- package/dist/src/tools/domain-loader.d.ts.map +1 -1
- package/dist/src/tools/domain-loader.js +56 -25
- package/dist/src/tools/domain-loader.js.map +1 -1
- package/dist/src/tools/domain-schema.d.ts +1 -1
- package/dist/src/tools/domain-schema.js +1 -1
- package/dist/src/utils/update-notices.js +12 -0
- package/dist/src/utils/update-notices.js.map +1 -1
- package/package.json +5 -1
- package/shared/agent-types.ts +1 -1
- package/templates/search-tools.md +22 -6
- package/workflows/agy-instructions.md +0 -4
- package/workflows/analyze.md +2 -2
- package/workflows/boundary-grill.md +50 -0
- package/workflows/brainstorm.md +6 -5
- package/workflows/claude-instructions.md +29 -2
- package/workflows/codebase-rebuild.md +0 -1
- package/workflows/codex-instructions.md +97 -14
- package/workflows/command-authoring.md +1 -1
- package/workflows/debug.md +0 -4
- package/workflows/domain-add.md +115 -0
- package/workflows/execute.md +7 -0
- package/workflows/explore-usage.md +128 -0
- package/workflows/finish-work.md +2 -6
- package/workflows/fork.md +0 -4
- package/workflows/grill.md +14 -1
- package/workflows/harvest.md +0 -3
- package/workflows/impeccable/audit.md +0 -2
- package/workflows/impeccable/codex.md +0 -4
- package/workflows/init.md +9 -0
- package/workflows/interview-mechanics.md +3 -2
- package/workflows/issue-analyze.md +0 -5
- package/workflows/issue-gaps-analyze.codex.md +0 -6
- package/workflows/knowledge-audit.md +0 -4
- package/workflows/learn.md +0 -6
- package/workflows/maestro.codex.md +0 -4
- package/workflows/maestro.md +31 -18
- package/workflows/merge.md +0 -4
- package/workflows/milestone-complete.md +0 -4
- package/workflows/overlays.md +0 -10
- package/workflows/plan.md +2 -3
- package/workflows/roadmap-common.md +0 -4
- package/workflows/tdd.md +0 -2
- package/workflows/tools-spec.md +1 -7
- package/workflows/ui-codify-extract.md +0 -2
- package/workflows/ui-codify-package.md +0 -2
- package/.agents/skills/maestro-ralph-beta/SKILL.md +0 -882
- package/.agy/skills/maestro-ralph-beta/SKILL.md +0 -878
- package/.claude/commands/maestro-ralph-beta.md +0 -880
- package/.codex/skills/maestro-ralph-beta/SKILL.md +0 -883
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Search Command — Unified knowledge search across
|
|
2
|
+
* Search Command — Unified knowledge search across wiki + code.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Default: mixed results (wiki + code interleaved by normalized score).
|
|
5
|
+
* --code: separate section display (backward compat).
|
|
6
|
+
* --wiki-only: wiki results only (no code search).
|
|
7
|
+
*
|
|
8
|
+
* Scoring: multi-signal normalization inspired by codebase-memory-mcp.
|
|
9
|
+
* Wiki: BM25F score + type boost (spec > knowhow > note)
|
|
10
|
+
* Code: BM25 score + kind boost + name-match bonus
|
|
11
|
+
* Merge: percentile-aware normalization + source weight
|
|
6
12
|
*/
|
|
7
13
|
import type { Command } from 'commander';
|
|
8
14
|
import type { WikiEntry, WikiNodeType } from '#maestro-dashboard/wiki/wiki-types.js';
|
|
@@ -38,6 +44,22 @@ export interface UnifiedSearchOptions {
|
|
|
38
44
|
* Unified knowledge search — BM25F ranking via WikiIndexer, with type/category
|
|
39
45
|
* filtering and per-source deduplication.
|
|
40
46
|
*/
|
|
41
|
-
export
|
|
47
|
+
export interface SearchMeta {
|
|
48
|
+
embeddingUsed: boolean;
|
|
49
|
+
embeddingDocs: number;
|
|
50
|
+
}
|
|
51
|
+
export declare function getLastSearchMeta(): SearchMeta;
|
|
52
|
+
export declare function runUnifiedSearch(q: string, opts: UnifiedSearchOptions & {
|
|
53
|
+
skipEmbedding?: boolean;
|
|
54
|
+
}): Promise<SearchResult[]>;
|
|
42
55
|
export declare function registerSearchCommand(program: Command): void;
|
|
56
|
+
export interface MergedResult {
|
|
57
|
+
source: 'wiki' | 'code';
|
|
58
|
+
kind: string;
|
|
59
|
+
name: string;
|
|
60
|
+
detail: string;
|
|
61
|
+
normalizedScore: number;
|
|
62
|
+
snippet?: string;
|
|
63
|
+
signature?: string;
|
|
64
|
+
}
|
|
43
65
|
//# sourceMappingURL=search.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/commands/search.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/commands/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAOrF,kEAAkE;AAClE,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,2CAA2C;AAC3C,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,2EAA2E;AAC3E,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAoBD;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB;AAGD,wBAAgB,iBAAiB,IAAI,UAAU,CAA4B;AAE3E,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,oBAAoB,GAAG;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CA+DnI;AAgDD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAsO5D;AAkCD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Search Command — Unified knowledge search across
|
|
2
|
+
* Search Command — Unified knowledge search across wiki + code.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Default: mixed results (wiki + code interleaved by normalized score).
|
|
5
|
+
* --code: separate section display (backward compat).
|
|
6
|
+
* --wiki-only: wiki results only (no code search).
|
|
7
|
+
*
|
|
8
|
+
* Scoring: multi-signal normalization inspired by codebase-memory-mcp.
|
|
9
|
+
* Wiki: BM25F score + type boost (spec > knowhow > note)
|
|
10
|
+
* Code: BM25 score + kind boost + name-match bonus
|
|
11
|
+
* Merge: percentile-aware normalization + source weight
|
|
6
12
|
*/
|
|
7
13
|
import { resolve } from 'node:path';
|
|
8
14
|
import { truncate, extractSnippet, highlightTerms } from '../utils/cli-format.js';
|
|
9
15
|
import { WikiIndexer } from '#maestro-dashboard/wiki/wiki-indexer.js';
|
|
10
16
|
import { loadWorkspaceConfig, resolveWorkspaceLinks } from '../config/index.js';
|
|
17
|
+
import { tryDaemonSearch, startDaemon, stopDaemon, readDaemonInfo, isDaemonAlive, getDaemonPath } from '../search/daemon.js';
|
|
11
18
|
// Valid type filter values — matches WikiNodeType.
|
|
12
19
|
const VALID_TYPES = ['project', 'roadmap', 'spec', 'issue', 'knowhow', 'note', 'domain'];
|
|
13
20
|
// ── Lazy offline client ────────────────────────────────────────────────
|
|
@@ -25,15 +32,30 @@ function getIndexer() {
|
|
|
25
32
|
}
|
|
26
33
|
return _indexer;
|
|
27
34
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
* filtering and per-source deduplication.
|
|
31
|
-
*/
|
|
35
|
+
let _lastSearchMeta = { embeddingUsed: false, embeddingDocs: 0 };
|
|
36
|
+
export function getLastSearchMeta() { return _lastSearchMeta; }
|
|
32
37
|
export async function runUnifiedSearch(q, opts) {
|
|
33
38
|
const limit = opts.limit > 0 ? opts.limit : 20;
|
|
34
|
-
const indexer = getIndexer();
|
|
35
39
|
const candidateLimit = Math.max(limit * 3, 60);
|
|
36
|
-
|
|
40
|
+
// Try daemon first (warm ONNX model, no cold-start penalty)
|
|
41
|
+
const workflowRoot = resolve('.workflow');
|
|
42
|
+
const daemonResult = await tryDaemonSearch(workflowRoot, q, candidateLimit, opts.skipEmbedding);
|
|
43
|
+
let scored;
|
|
44
|
+
let embeddingUsed;
|
|
45
|
+
let embeddingDocs;
|
|
46
|
+
if (daemonResult?.ok && daemonResult.results) {
|
|
47
|
+
scored = daemonResult.results;
|
|
48
|
+
embeddingUsed = daemonResult.embeddingUsed ?? false;
|
|
49
|
+
embeddingDocs = daemonResult.embeddingDocs ?? 0;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const indexer = getIndexer();
|
|
53
|
+
const result = await indexer.searchWithMeta(q, candidateLimit, { skipEmbedding: opts.skipEmbedding });
|
|
54
|
+
scored = result.results;
|
|
55
|
+
embeddingUsed = result.embeddingUsed;
|
|
56
|
+
embeddingDocs = result.embeddingDocs;
|
|
57
|
+
}
|
|
58
|
+
_lastSearchMeta = { embeddingUsed, embeddingDocs };
|
|
37
59
|
let filtered = scored;
|
|
38
60
|
if (opts.type) {
|
|
39
61
|
filtered = filtered.filter(r => r.entry.type === opts.type);
|
|
@@ -54,13 +76,14 @@ export async function runUnifiedSearch(q, opts) {
|
|
|
54
76
|
if (deduped.length >= limit)
|
|
55
77
|
break;
|
|
56
78
|
}
|
|
79
|
+
const maxScore = deduped.length > 0 ? deduped[0].score : 1;
|
|
57
80
|
const results = deduped.map(({ entry, score }) => ({
|
|
58
81
|
id: entry.id,
|
|
59
82
|
type: entry.type,
|
|
60
83
|
title: entry.title,
|
|
61
84
|
category: entry.category,
|
|
62
85
|
summary: entry.summary,
|
|
63
|
-
score,
|
|
86
|
+
score: maxScore > 0 ? score / maxScore : score,
|
|
64
87
|
snippet: extractSnippet(entry.body, q),
|
|
65
88
|
source: entry.source,
|
|
66
89
|
workspace: entry.source.workspace,
|
|
@@ -124,142 +147,385 @@ async function runCodeSearch(q, limit) {
|
|
|
124
147
|
export function registerSearchCommand(program) {
|
|
125
148
|
program
|
|
126
149
|
.command('search <query...>')
|
|
127
|
-
.description('Unified knowledge search across
|
|
150
|
+
.description('Unified knowledge search across wiki + code (mixed by default)')
|
|
128
151
|
.option('--type <type>', `Filter by type: ${VALID_TYPES.join(', ')}`)
|
|
129
152
|
.option('--category <cat>', 'Filter by category (e.g. coding, arch, debug, test, review, learning)')
|
|
130
|
-
.option('--code', '
|
|
131
|
-
.option('--all', '
|
|
153
|
+
.option('--code', 'Show wiki and code in separate sections (legacy display)')
|
|
154
|
+
.option('--all', 'Alias for default mixed mode (backward compat)')
|
|
155
|
+
.option('--wiki-only', 'Search wiki only, skip code results')
|
|
132
156
|
.option('--workspace <name>', 'Filter results to a specific linked workspace')
|
|
157
|
+
.option('--no-emb', 'Skip embedding, use BM25 only')
|
|
133
158
|
.option('--limit <n>', 'Max results', '20')
|
|
134
159
|
.option('--json', 'Output as JSON')
|
|
135
160
|
.action(async (queryParts, opts) => {
|
|
136
161
|
const q = queryParts.join(' ');
|
|
137
162
|
const limit = parseInt(opts.limit, 10) || 20;
|
|
138
|
-
const
|
|
163
|
+
const wikiOnly = opts.wikiOnly === true;
|
|
164
|
+
const separateSections = opts.code === true && !opts.all;
|
|
139
165
|
if (opts.type && !VALID_TYPES.includes(opts.type)) {
|
|
140
166
|
console.error(`Error: --type must be one of ${VALID_TYPES.join(', ')} (got "${opts.type}")`);
|
|
141
167
|
process.exit(1);
|
|
142
168
|
}
|
|
143
|
-
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
169
|
+
const skipEmbedding = opts.emb === false;
|
|
170
|
+
const wikiResults = await runUnifiedSearch(q, { type: opts.type, category: opts.category, workspace: opts.workspace, limit, skipEmbedding });
|
|
171
|
+
const codeResults = wikiOnly ? [] : await runCodeSearch(q, limit);
|
|
172
|
+
const meta = getLastSearchMeta();
|
|
173
|
+
const embTag = meta.embeddingUsed ? `+emb(${meta.embeddingDocs})` : 'bm25';
|
|
174
|
+
const isTTY = process.stdout.isTTY === true;
|
|
175
|
+
const qTerms = q.toLowerCase().split(/\s+/).filter(Boolean);
|
|
176
|
+
// --code (without --all): legacy separate-section display
|
|
177
|
+
if (separateSections) {
|
|
148
178
|
if (opts.json) {
|
|
149
|
-
console.log(JSON.stringify({ query: q,
|
|
179
|
+
console.log(JSON.stringify({ query: q, wikiCount: wikiResults.length, codeCount: codeResults.length, wikiResults, codeResults }, null, 2));
|
|
150
180
|
return;
|
|
151
181
|
}
|
|
152
|
-
console.log(`Search: "${q}" (${
|
|
153
|
-
if (
|
|
182
|
+
console.log(`Search: "${q}" (${wikiResults.length} wiki + ${codeResults.length} code, ${embTag})`);
|
|
183
|
+
if (wikiResults.length === 0 && codeResults.length === 0) {
|
|
154
184
|
console.log(' No matches found.');
|
|
155
185
|
return;
|
|
156
186
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
187
|
+
if (wikiResults.length > 0) {
|
|
188
|
+
console.log(' [Wiki Results]');
|
|
189
|
+
for (const r of wikiResults) {
|
|
190
|
+
printWikiResult(r, ' ', isTTY, qTerms);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (codeResults.length > 0) {
|
|
194
|
+
console.log(' [Code Results]');
|
|
195
|
+
for (const r of codeResults) {
|
|
196
|
+
printCodeResult(r, ' ', isTTY, qTerms);
|
|
197
|
+
}
|
|
163
198
|
}
|
|
164
199
|
return;
|
|
165
200
|
}
|
|
201
|
+
// Default / --all / --wiki-only: mixed interleaved results
|
|
202
|
+
const merged = mergeAndNormalize(wikiResults, codeResults, limit, q);
|
|
203
|
+
const wikiCount = merged.filter(r => r.source === 'wiki').length;
|
|
204
|
+
const codeCount = merged.filter(r => r.source === 'code').length;
|
|
166
205
|
if (opts.json) {
|
|
167
|
-
|
|
168
|
-
if (includeCode) {
|
|
169
|
-
output.wikiResults = wikiResults;
|
|
170
|
-
output.codeResults = codeResults;
|
|
171
|
-
output.wikiCount = wikiResults.length;
|
|
172
|
-
output.codeCount = codeResults.length;
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
output.count = wikiResults.length;
|
|
176
|
-
output.results = wikiResults;
|
|
177
|
-
}
|
|
178
|
-
console.log(JSON.stringify(output, null, 2));
|
|
206
|
+
console.log(JSON.stringify({ query: q, wikiCount, codeCount, count: merged.length, results: merged }, null, 2));
|
|
179
207
|
return;
|
|
180
208
|
}
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
209
|
+
const countParts = [];
|
|
210
|
+
if (wikiCount > 0)
|
|
211
|
+
countParts.push(`wiki ${wikiCount}个`);
|
|
212
|
+
if (codeCount > 0)
|
|
213
|
+
countParts.push(`代码 ${codeCount}个`);
|
|
214
|
+
const countSummary = countParts.length > 0
|
|
215
|
+
? `${countParts.join(' + ')} = ${merged.length} results`
|
|
216
|
+
: '0 results';
|
|
217
|
+
console.log(`Search: "${q}" (${countSummary}, ${embTag})`);
|
|
218
|
+
if (qTerms.length > 4) {
|
|
219
|
+
console.log(` Hint: ${qTerms.length} terms — split into 1-3 keyword queries for better precision`);
|
|
188
220
|
}
|
|
189
|
-
if (
|
|
221
|
+
if (merged.length === 0) {
|
|
190
222
|
console.log(' No matches found.');
|
|
191
223
|
return;
|
|
192
224
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const typeTag = `[${r.type}]`;
|
|
199
|
-
const catTag = r.category ? ` ${r.category}` : '';
|
|
200
|
-
const wsTag = r.workspace ? ` [ws:${r.workspace}]` : '';
|
|
201
|
-
const scoreTag = r.score !== null ? ` (${r.score.toFixed(2)})` : '';
|
|
202
|
-
const title = isTTY ? highlightTerms(r.title, qTerms) : r.title;
|
|
203
|
-
console.log(`${indent}${typeTag}${catTag}${wsTag} ${r.id} ${title}${scoreTag}`);
|
|
225
|
+
for (const r of merged) {
|
|
226
|
+
const name = isTTY ? highlightTerms(r.name, qTerms) : r.name;
|
|
227
|
+
const scoreTag = ` (${r.normalizedScore.toFixed(4)})`;
|
|
228
|
+
if (r.source === 'wiki') {
|
|
229
|
+
console.log(` [wiki:${r.kind}] ${name} ${r.detail}${scoreTag}`);
|
|
204
230
|
if (r.snippet) {
|
|
205
231
|
const snippet = isTTY ? highlightTerms(r.snippet, qTerms) : r.snippet;
|
|
206
|
-
console.log(
|
|
232
|
+
console.log(` ${snippet}`);
|
|
207
233
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
const sigTag = r.signature ? ` ${truncate(r.signature, 60)}` : '';
|
|
237
|
+
console.log(` [code:${r.kind}] ${name} ${r.detail}${sigTag}${scoreTag}`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
// ── Search daemon management ───────────────────────────────────────────
|
|
242
|
+
program
|
|
243
|
+
.command('search-daemon')
|
|
244
|
+
.description('Manage the resident search daemon (warm ONNX model)')
|
|
245
|
+
.argument('<action>', 'start | stop | status')
|
|
246
|
+
.action(async (action) => {
|
|
247
|
+
const workflowRoot = resolve('.workflow');
|
|
248
|
+
if (action === 'start' || action === 'start-daemon') {
|
|
249
|
+
const info = readDaemonInfo(workflowRoot);
|
|
250
|
+
if (info && isDaemonAlive(info)) {
|
|
251
|
+
console.log(`Search daemon already running (pid=${info.pid}, port=${info.port})`);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
console.log('Starting search daemon...');
|
|
255
|
+
const projectPath = process.cwd();
|
|
256
|
+
const wsConfig = loadWorkspaceConfig(projectPath);
|
|
257
|
+
const resolved = resolveWorkspaceLinks(projectPath, wsConfig);
|
|
258
|
+
const linkedWorkspaces = resolved
|
|
259
|
+
.filter(lw => lw.valid)
|
|
260
|
+
.map(lw => ({ name: lw.name, workflowRoot: lw.workflowRoot, shareTypes: lw.share }));
|
|
261
|
+
const { port } = await startDaemon(workflowRoot, { workflowRoot, linkedWorkspaces });
|
|
262
|
+
console.log(`Search daemon started (pid=${process.pid}, port=${port})`);
|
|
263
|
+
// Keep process alive
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (action === 'stop') {
|
|
267
|
+
const stopped = stopDaemon(workflowRoot);
|
|
268
|
+
console.log(stopped ? 'Search daemon stopped.' : 'No daemon running.');
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if (action === 'status') {
|
|
272
|
+
const info = readDaemonInfo(workflowRoot);
|
|
273
|
+
if (!info) {
|
|
274
|
+
console.log('Search daemon: not running');
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
const alive = isDaemonAlive(info);
|
|
278
|
+
console.log(`Search daemon: ${alive ? 'running' : 'stale (pid dead)'} pid=${info.pid} port=${info.port} started=${info.startedAt}`);
|
|
279
|
+
if (!alive)
|
|
280
|
+
try {
|
|
281
|
+
const { unlinkSync } = await import('node:fs');
|
|
282
|
+
unlinkSync(getDaemonPath(workflowRoot));
|
|
211
283
|
}
|
|
284
|
+
catch { }
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
console.error(`Unknown action: ${action}. Use: start, stop, status`);
|
|
288
|
+
});
|
|
289
|
+
// Hidden flag for hook-spawned daemon startup
|
|
290
|
+
program
|
|
291
|
+
.command('search-start-daemon', { hidden: true })
|
|
292
|
+
.action(async () => {
|
|
293
|
+
const workflowRoot = resolve('.workflow');
|
|
294
|
+
const projectPath = process.cwd();
|
|
295
|
+
const wsConfig = loadWorkspaceConfig(projectPath);
|
|
296
|
+
const resolved = resolveWorkspaceLinks(projectPath, wsConfig);
|
|
297
|
+
const linkedWorkspaces = resolved
|
|
298
|
+
.filter(lw => lw.valid)
|
|
299
|
+
.map(lw => ({ name: lw.name, workflowRoot: lw.workflowRoot, shareTypes: lw.share }));
|
|
300
|
+
try {
|
|
301
|
+
await startDaemon(workflowRoot, { workflowRoot, linkedWorkspaces });
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
process.exit(0);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
program
|
|
308
|
+
.command('embedding')
|
|
309
|
+
.description('Embedding model status, warmup, and rebuild')
|
|
310
|
+
.argument('[action]', 'status (default), warmup, rebuild', 'status')
|
|
311
|
+
.action(async (action) => {
|
|
312
|
+
const workflowRoot = resolve('.workflow');
|
|
313
|
+
const { isAvailable, getUnavailableReason, loadEmbeddingIndex, embedTexts, getDeviceSummary, detectDevice } = await import('#maestro-dashboard/wiki/embedding.js');
|
|
314
|
+
if (action === 'status') {
|
|
315
|
+
const avail = await isAvailable();
|
|
316
|
+
console.log(`Transformers: ${avail ? 'available' : 'NOT available (' + (getUnavailableReason?.() ?? 'unknown') + ')'}`);
|
|
317
|
+
if (avail) {
|
|
318
|
+
await detectDevice();
|
|
319
|
+
console.log(`Device: ${getDeviceSummary()}`);
|
|
320
|
+
}
|
|
321
|
+
const idx = loadEmbeddingIndex(workflowRoot);
|
|
322
|
+
if (idx) {
|
|
323
|
+
console.log(`Index: ${idx.docIds.length} docs, dim=${idx.dimension}, model=${idx.modelId}`);
|
|
324
|
+
console.log(`Built: ${new Date(idx.builtAt).toISOString()}, device=${idx.deviceUsed}`);
|
|
325
|
+
if (idx.buildTimeMs)
|
|
326
|
+
console.log(`Build time: ${idx.buildTimeMs}ms`);
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
console.log('Index: not built (will build on first search)');
|
|
212
330
|
}
|
|
331
|
+
return;
|
|
213
332
|
}
|
|
214
|
-
if (
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
console.log(` [${r.kind}] ${name} ${r.filePath}${scoreTag}`);
|
|
333
|
+
if (action === 'warmup') {
|
|
334
|
+
const avail = await isAvailable();
|
|
335
|
+
if (!avail) {
|
|
336
|
+
console.error(`Embedding unavailable: ${getUnavailableReason?.() ?? 'unknown'}`);
|
|
337
|
+
process.exit(1);
|
|
220
338
|
}
|
|
339
|
+
console.log('Warming up model...');
|
|
340
|
+
const t0 = Date.now();
|
|
341
|
+
await embedTexts(['warmup']);
|
|
342
|
+
console.log(`Model ready (${getDeviceSummary()}, ${Date.now() - t0}ms)`);
|
|
343
|
+
return;
|
|
221
344
|
}
|
|
345
|
+
if (action === 'rebuild') {
|
|
346
|
+
const avail = await isAvailable();
|
|
347
|
+
if (!avail) {
|
|
348
|
+
console.error(`Embedding unavailable: ${getUnavailableReason?.() ?? 'unknown'}`);
|
|
349
|
+
process.exit(1);
|
|
350
|
+
}
|
|
351
|
+
console.log('Rebuilding embedding index...');
|
|
352
|
+
const { WikiIndexer } = await import('#maestro-dashboard/wiki/wiki-indexer.js');
|
|
353
|
+
const { loadWorkspaceConfig, resolveWorkspaceLinks } = await import('../config/index.js');
|
|
354
|
+
const projectPath = process.cwd();
|
|
355
|
+
const wsConfig = loadWorkspaceConfig(projectPath);
|
|
356
|
+
const resolved = resolveWorkspaceLinks(projectPath, wsConfig);
|
|
357
|
+
const linkedWorkspaces = resolved.filter(lw => lw.valid).map(lw => ({ name: lw.name, workflowRoot: lw.workflowRoot, shareTypes: lw.share }));
|
|
358
|
+
const indexer = new WikiIndexer({ workflowRoot, linkedWorkspaces });
|
|
359
|
+
const t0 = Date.now();
|
|
360
|
+
const { results, embeddingUsed, embeddingDocs } = await indexer.searchWithMeta('warmup', 1);
|
|
361
|
+
if (embeddingUsed) {
|
|
362
|
+
console.log(`Index rebuilt: ${embeddingDocs} docs (${Date.now() - t0}ms)`);
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
console.log(`Rebuild failed — check with: maestro embedding status`);
|
|
366
|
+
}
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
console.error(`Unknown action: ${action}. Use: status, warmup, rebuild`);
|
|
370
|
+
process.exit(1);
|
|
222
371
|
});
|
|
223
372
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
373
|
+
// ── Display helpers ──────────────────────────────────────────────────
|
|
374
|
+
function printWikiResult(r, indent, isTTY, qTerms) {
|
|
375
|
+
const typeTag = `[${r.type}]`;
|
|
376
|
+
const catTag = r.category ? ` ${r.category}` : '';
|
|
377
|
+
const wsTag = r.workspace ? ` [ws:${r.workspace}]` : '';
|
|
378
|
+
const scoreTag = r.score !== null ? ` (${r.score.toFixed(4)})` : '';
|
|
379
|
+
const title = isTTY ? highlightTerms(r.title, qTerms) : r.title;
|
|
380
|
+
console.log(`${indent}${typeTag}${catTag}${wsTag} ${r.id} ${title}${scoreTag}`);
|
|
381
|
+
if (r.snippet) {
|
|
382
|
+
const snippet = isTTY ? highlightTerms(r.snippet, qTerms) : r.snippet;
|
|
383
|
+
console.log(`${indent} ${snippet}`);
|
|
384
|
+
}
|
|
385
|
+
else if (r.summary) {
|
|
386
|
+
const summary = isTTY ? highlightTerms(truncate(r.summary, 80), qTerms) : truncate(r.summary, 80);
|
|
387
|
+
console.log(`${indent} ${summary}`);
|
|
232
388
|
}
|
|
233
|
-
return { min, max };
|
|
234
389
|
}
|
|
235
|
-
function
|
|
236
|
-
const
|
|
237
|
-
const
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
390
|
+
function printCodeResult(r, indent, isTTY, qTerms) {
|
|
391
|
+
const scoreTag = r.score !== null ? ` (${r.score.toFixed(4)})` : '';
|
|
392
|
+
const name = isTTY ? highlightTerms(r.name, qTerms) : r.name;
|
|
393
|
+
const sigTag = r.signature ? ` ${truncate(r.signature, 60)}` : '';
|
|
394
|
+
console.log(`${indent}[${r.kind}] ${name} ${r.filePath}${sigTag}${scoreTag}`);
|
|
395
|
+
}
|
|
396
|
+
const WIKI_TYPE_BOOST = {
|
|
397
|
+
spec: 1.15,
|
|
398
|
+
domain: 1.10,
|
|
399
|
+
knowhow: 1.05,
|
|
400
|
+
project: 0.95,
|
|
401
|
+
roadmap: 0.95,
|
|
402
|
+
issue: 0.85,
|
|
403
|
+
note: 0.80,
|
|
404
|
+
};
|
|
405
|
+
const CODE_KIND_BOOST = {
|
|
406
|
+
class: 1.20,
|
|
407
|
+
interface: 1.15,
|
|
408
|
+
function: 1.10,
|
|
409
|
+
method: 1.10,
|
|
410
|
+
component: 1.08,
|
|
411
|
+
route: 1.12,
|
|
412
|
+
type_alias: 1.05,
|
|
413
|
+
enum: 1.05,
|
|
414
|
+
constant: 1.00,
|
|
415
|
+
variable: 0.90,
|
|
416
|
+
field: 0.85,
|
|
417
|
+
property: 0.80,
|
|
418
|
+
};
|
|
419
|
+
function isCodeIdentifier(query) {
|
|
420
|
+
const trimmed = query.trim();
|
|
421
|
+
if (/^[a-z]+[A-Z]/.test(trimmed))
|
|
422
|
+
return true;
|
|
423
|
+
if (/^[A-Z][a-z]+[A-Z]/.test(trimmed))
|
|
424
|
+
return true;
|
|
425
|
+
if (/^[A-Z]{2,}[a-z]/.test(trimmed))
|
|
426
|
+
return true;
|
|
427
|
+
if (/^[a-z]+_[a-z]+/.test(trimmed))
|
|
428
|
+
return true;
|
|
429
|
+
if (/^[A-Z][a-zA-Z]+$/.test(trimmed) && !trimmed.includes(' '))
|
|
430
|
+
return true;
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
433
|
+
function splitCamelSnake(s) {
|
|
434
|
+
return s
|
|
435
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
436
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
|
|
437
|
+
.split(/[\s_\-.]+/)
|
|
438
|
+
.map(t => t.toLowerCase())
|
|
439
|
+
.filter(t => t.length > 0);
|
|
440
|
+
}
|
|
441
|
+
function codeNameMatchBonus(codeName, query) {
|
|
442
|
+
const nameLower = codeName.toLowerCase();
|
|
443
|
+
const queryLower = query.toLowerCase().trim();
|
|
444
|
+
if (!queryLower)
|
|
445
|
+
return 0;
|
|
446
|
+
if (nameLower === queryLower)
|
|
447
|
+
return 50;
|
|
448
|
+
if (nameLower.startsWith(queryLower))
|
|
449
|
+
return 30;
|
|
450
|
+
if (queryLower.startsWith(nameLower))
|
|
451
|
+
return 20;
|
|
452
|
+
if (nameLower.includes(queryLower) || queryLower.includes(nameLower))
|
|
453
|
+
return 10;
|
|
454
|
+
const queryTokens = splitCamelSnake(query);
|
|
455
|
+
const nameTokens = splitCamelSnake(codeName);
|
|
456
|
+
if (queryTokens.length === 0)
|
|
457
|
+
return 0;
|
|
458
|
+
const matched = queryTokens.filter(qt => nameTokens.some(nt => nt.includes(qt) || qt.includes(nt)));
|
|
459
|
+
if (matched.length === queryTokens.length)
|
|
460
|
+
return 15 + 5 * matched.length;
|
|
461
|
+
if (matched.length > 0)
|
|
462
|
+
return 5 * matched.length;
|
|
463
|
+
return 0;
|
|
464
|
+
}
|
|
465
|
+
function rankNormalize(items) {
|
|
466
|
+
if (items.length === 0)
|
|
467
|
+
return [];
|
|
468
|
+
const n = items.length;
|
|
469
|
+
const sorted = [...items].sort((a, b) => b.score - a.score);
|
|
470
|
+
const result = new Array(n);
|
|
471
|
+
let i = 0;
|
|
472
|
+
while (i < n) {
|
|
473
|
+
let j = i;
|
|
474
|
+
while (j < n - 1 && sorted[j + 1].score === sorted[j].score)
|
|
475
|
+
j++;
|
|
476
|
+
const avgRank = (i + j) / 2;
|
|
477
|
+
const normalizedRank = 1 - avgRank / n;
|
|
478
|
+
for (let k = i; k <= j; k++) {
|
|
479
|
+
result[sorted[k].index] = normalizedRank;
|
|
480
|
+
}
|
|
481
|
+
i = j + 1;
|
|
482
|
+
}
|
|
483
|
+
return result;
|
|
484
|
+
}
|
|
485
|
+
function mergeAndNormalize(wiki, code, limit, query) {
|
|
486
|
+
const q = query ?? '';
|
|
487
|
+
const isIdQuery = isCodeIdentifier(q);
|
|
488
|
+
const hasStrongCodeMatch = code.length > 0 && code.some(r => codeNameMatchBonus(r.name, q) >= 15);
|
|
489
|
+
const WIKI_WEIGHT = isIdQuery ? 0.4 : hasStrongCodeMatch ? 0.5 : 0.6;
|
|
490
|
+
const CODE_WEIGHT = isIdQuery ? 0.6 : hasStrongCodeMatch ? 0.5 : 0.4;
|
|
491
|
+
const codeNames = new Set(code.map(r => r.name.toLowerCase()));
|
|
492
|
+
const wikiScored = wiki.map((r, i) => {
|
|
246
493
|
const raw = r.score ?? 0;
|
|
494
|
+
let typeBoost = WIKI_TYPE_BOOST[r.type] ?? 1.0;
|
|
495
|
+
if (r.id.startsWith('kg-') && codeNames.has(r.title.toLowerCase())) {
|
|
496
|
+
typeBoost *= 0.7;
|
|
497
|
+
}
|
|
498
|
+
return { ...r, finalScore: raw * typeBoost, index: i };
|
|
499
|
+
});
|
|
500
|
+
const codeScored = code.map((r, i) => {
|
|
501
|
+
const raw = r.score ?? 0;
|
|
502
|
+
const kindBoost = CODE_KIND_BOOST[r.kind] ?? 1.0;
|
|
503
|
+
const nameBonus = codeNameMatchBonus(r.name, q);
|
|
504
|
+
return { ...r, finalScore: raw * kindBoost + nameBonus, index: i };
|
|
505
|
+
});
|
|
506
|
+
const wikiRanks = rankNormalize(wikiScored.map(r => ({ index: r.index, score: r.finalScore })));
|
|
507
|
+
const codeRanks = rankNormalize(codeScored.map(r => ({ index: r.index, score: r.finalScore })));
|
|
508
|
+
const merged = [];
|
|
509
|
+
for (let i = 0; i < wikiScored.length; i++) {
|
|
510
|
+
const r = wikiScored[i];
|
|
247
511
|
merged.push({
|
|
248
512
|
source: 'wiki',
|
|
249
513
|
kind: r.type,
|
|
250
514
|
name: r.title,
|
|
251
515
|
detail: r.category ? `${r.category} ${r.id}` : r.id,
|
|
252
|
-
normalizedScore:
|
|
516
|
+
normalizedScore: wikiRanks[i] * WIKI_WEIGHT,
|
|
517
|
+
snippet: r.snippet ?? undefined,
|
|
253
518
|
});
|
|
254
519
|
}
|
|
255
|
-
for (
|
|
256
|
-
const
|
|
520
|
+
for (let i = 0; i < codeScored.length; i++) {
|
|
521
|
+
const r = codeScored[i];
|
|
257
522
|
merged.push({
|
|
258
523
|
source: 'code',
|
|
259
524
|
kind: r.kind,
|
|
260
525
|
name: r.name,
|
|
261
526
|
detail: r.filePath,
|
|
262
|
-
normalizedScore:
|
|
527
|
+
normalizedScore: codeRanks[i] * CODE_WEIGHT,
|
|
528
|
+
signature: r.signature,
|
|
263
529
|
});
|
|
264
530
|
}
|
|
265
531
|
merged.sort((a, b) => b.normalizedScore - a.normalizedScore);
|