@rkarim08/sia 1.0.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/.claude-plugin/marketplace.json +35 -0
- package/.claude-plugin/plugin.json +27 -0
- package/.mcp.json +13 -0
- package/CLAUDE.md +226 -0
- package/LICENSE +202 -0
- package/PLUGIN_README.md +253 -0
- package/README.md +1013 -0
- package/agents/sia-changelog-writer.md +89 -0
- package/agents/sia-code-reviewer.md +86 -0
- package/agents/sia-conflict-resolver.md +100 -0
- package/agents/sia-convention-enforcer.md +69 -0
- package/agents/sia-debug.md +106 -0
- package/agents/sia-decision-reviewer.md +101 -0
- package/agents/sia-dependency-tracker.md +80 -0
- package/agents/sia-explain.md +126 -0
- package/agents/sia-feature.md +116 -0
- package/agents/sia-knowledge-capture.md +117 -0
- package/agents/sia-lead-architecture-advisor.md +93 -0
- package/agents/sia-lead-team-health.md +107 -0
- package/agents/sia-migration.md +100 -0
- package/agents/sia-onboarding.md +115 -0
- package/agents/sia-orientation.md +99 -0
- package/agents/sia-pm-briefing.md +106 -0
- package/agents/sia-pm-risk-advisor.md +82 -0
- package/agents/sia-qa-analyst.md +116 -0
- package/agents/sia-qa-regression-map.md +94 -0
- package/agents/sia-refactor.md +115 -0
- package/agents/sia-regression.md +112 -0
- package/agents/sia-security-audit.md +125 -0
- package/agents/sia-test-advisor.md +91 -0
- package/hooks/hooks.json +98 -0
- package/migrations/bridge/001_initial.sql +34 -0
- package/migrations/episodic/001_initial.sql +35 -0
- package/migrations/meta/001_initial.sql +68 -0
- package/migrations/semantic/001_initial.sql +292 -0
- package/migrations/semantic/002_ontology.sql +89 -0
- package/migrations/semantic/003_freshness.sql +63 -0
- package/migrations/semantic/004_v5_unified_schema.sql +194 -0
- package/migrations/semantic/005_backfill_event_kinds.sql +8 -0
- package/migrations/semantic/006_tree_sitter.sql +6 -0
- package/migrations/semantic/007_branch_snapshots.sql +22 -0
- package/package.json +110 -0
- package/scripts/branch-switch.sh +13 -0
- package/scripts/build-wasm-grammars.sh +81 -0
- package/scripts/post-compact.sh +8 -0
- package/scripts/post-tool-use.sh +10 -0
- package/scripts/pre-compact.sh +8 -0
- package/scripts/session-end.sh +8 -0
- package/scripts/session-start.sh +8 -0
- package/scripts/start-mcp.ts +45 -0
- package/scripts/stop-hook.sh +8 -0
- package/scripts/user-prompt-submit.sh +8 -0
- package/scripts/viz-server.ts +152 -0
- package/skills/sia-brainstorm/SKILL.md +156 -0
- package/skills/sia-brainstorm/scripts/frame-template.html +214 -0
- package/skills/sia-brainstorm/scripts/helper.js +95 -0
- package/skills/sia-brainstorm/scripts/server.cjs +338 -0
- package/skills/sia-brainstorm/scripts/start-server.sh +153 -0
- package/skills/sia-brainstorm/scripts/stop-server.sh +55 -0
- package/skills/sia-brainstorm/spec-document-reviewer-prompt.md +49 -0
- package/skills/sia-brainstorm/visual-companion.md +286 -0
- package/skills/sia-capture/SKILL.md +64 -0
- package/skills/sia-compare/SKILL.md +33 -0
- package/skills/sia-conflicts/SKILL.md +38 -0
- package/skills/sia-debug-workflow/SKILL.md +120 -0
- package/skills/sia-debug-workflow/root-cause-tracing.md +70 -0
- package/skills/sia-debug-workflow/scripts/find-polluter.sh +64 -0
- package/skills/sia-debug-workflow/temporal-investigation.md +72 -0
- package/skills/sia-digest/SKILL.md +23 -0
- package/skills/sia-dispatch/SKILL.md +69 -0
- package/skills/sia-dispatch/agent-task-template.md +99 -0
- package/skills/sia-doctor/SKILL.md +39 -0
- package/skills/sia-execute/SKILL.md +70 -0
- package/skills/sia-execute-plan/SKILL.md +85 -0
- package/skills/sia-export-import/SKILL.md +49 -0
- package/skills/sia-export-knowledge/SKILL.md +46 -0
- package/skills/sia-finish/SKILL.md +100 -0
- package/skills/sia-finish/pr-summary-template.md +54 -0
- package/skills/sia-freshness/SKILL.md +38 -0
- package/skills/sia-history/SKILL.md +42 -0
- package/skills/sia-impact/SKILL.md +70 -0
- package/skills/sia-index/SKILL.md +54 -0
- package/skills/sia-install/SKILL.md +39 -0
- package/skills/sia-lead-compliance/SKILL.md +16 -0
- package/skills/sia-lead-drift-report/SKILL.md +16 -0
- package/skills/sia-lead-knowledge-map/SKILL.md +16 -0
- package/skills/sia-learn/SKILL.md +58 -0
- package/skills/sia-plan/SKILL.md +68 -0
- package/skills/sia-plan/plan-reviewer-prompt.md +63 -0
- package/skills/sia-playbooks/SKILL.md +29 -0
- package/skills/sia-playbooks/reference-feature.md +100 -0
- package/skills/sia-playbooks/reference-flagging.md +50 -0
- package/skills/sia-playbooks/reference-orientation.md +92 -0
- package/skills/sia-playbooks/reference-regression.md +115 -0
- package/skills/sia-playbooks/reference-review.md +64 -0
- package/skills/sia-playbooks/reference-tools.md +239 -0
- package/skills/sia-pm-decision-log/SKILL.md +28 -0
- package/skills/sia-pm-risk-dashboard/SKILL.md +24 -0
- package/skills/sia-pm-sprint-summary/SKILL.md +27 -0
- package/skills/sia-prune/SKILL.md +45 -0
- package/skills/sia-qa-coverage/SKILL.md +28 -0
- package/skills/sia-qa-flaky/SKILL.md +20 -0
- package/skills/sia-qa-report/SKILL.md +26 -0
- package/skills/sia-reindex/SKILL.md +30 -0
- package/skills/sia-review-respond/SKILL.md +88 -0
- package/skills/sia-review-respond/pushback-patterns.md +90 -0
- package/skills/sia-search/SKILL.md +47 -0
- package/skills/sia-setup/SKILL.md +82 -0
- package/skills/sia-setup/setup-checklist.md +97 -0
- package/skills/sia-stats/SKILL.md +36 -0
- package/skills/sia-status/SKILL.md +44 -0
- package/skills/sia-sync/SKILL.md +46 -0
- package/skills/sia-team/SKILL.md +64 -0
- package/skills/sia-test/SKILL.md +92 -0
- package/skills/sia-test/testing-anti-patterns.md +104 -0
- package/skills/sia-tour/SKILL.md +29 -0
- package/skills/sia-upgrade/SKILL.md +43 -0
- package/skills/sia-verify/SKILL.md +81 -0
- package/skills/sia-visualize/SKILL.md +28 -0
- package/skills/sia-visualize-live/SKILL.md +55 -0
- package/skills/sia-visualize-live/scripts/graph-template.html +389 -0
- package/skills/sia-visualize-live/scripts/start-visualizer.sh +161 -0
- package/skills/sia-visualize-live/scripts/stop-visualizer.sh +55 -0
- package/skills/sia-visualize-live/scripts/visualizer-server.cjs +264 -0
- package/skills/sia-workspace/SKILL.md +57 -0
- package/src/agent/claude-md-template-flagging.md +219 -0
- package/src/agent/claude-md-template.md +213 -0
- package/src/agent/modules/sia-feature.md +100 -0
- package/src/agent/modules/sia-flagging.md +50 -0
- package/src/agent/modules/sia-orientation.md +92 -0
- package/src/agent/modules/sia-regression.md +115 -0
- package/src/agent/modules/sia-review.md +64 -0
- package/src/agent/modules/sia-tools.md +239 -0
- package/src/ast/extractors/c-include.ts +189 -0
- package/src/ast/extractors/csharp-project.ts +260 -0
- package/src/ast/extractors/prisma-schema.ts +44 -0
- package/src/ast/extractors/project-manifest.ts +111 -0
- package/src/ast/extractors/sql-schema.ts +67 -0
- package/src/ast/extractors/tier-a.ts +423 -0
- package/src/ast/extractors/tier-b.ts +289 -0
- package/src/ast/extractors/tier-dispatch.ts +247 -0
- package/src/ast/index-worker.ts +108 -0
- package/src/ast/indexer.ts +484 -0
- package/src/ast/languages.ts +408 -0
- package/src/ast/pagerank-builder.ts +125 -0
- package/src/ast/path-utils.ts +137 -0
- package/src/ast/tree-sitter/backends/native.ts +57 -0
- package/src/ast/tree-sitter/backends/wasm.ts +39 -0
- package/src/ast/tree-sitter/call-walker.ts +44 -0
- package/src/ast/tree-sitter/edit-computer.ts +55 -0
- package/src/ast/tree-sitter/query-runner.ts +46 -0
- package/src/ast/tree-sitter/service.ts +174 -0
- package/src/ast/tree-sitter/tree-cache.ts +39 -0
- package/src/ast/tree-sitter/types.ts +79 -0
- package/src/ast/watcher.ts +322 -0
- package/src/capture/chunker.ts +169 -0
- package/src/capture/consolidate.ts +127 -0
- package/src/capture/edge-inferrer.ts +161 -0
- package/src/capture/embedder.ts +166 -0
- package/src/capture/embedding-cache.ts +73 -0
- package/src/capture/flag-processor.ts +64 -0
- package/src/capture/hook.ts +67 -0
- package/src/capture/pipeline.ts +450 -0
- package/src/capture/prompts/consolidate.ts +25 -0
- package/src/capture/prompts/edge-infer.ts +29 -0
- package/src/capture/prompts/extract-flagged.ts +36 -0
- package/src/capture/prompts/extract.ts +42 -0
- package/src/capture/tokenizer.ts +147 -0
- package/src/capture/track-a-ast.ts +93 -0
- package/src/capture/track-b-llm.ts +149 -0
- package/src/capture/types.ts +64 -0
- package/src/cli/commands/community.ts +137 -0
- package/src/cli/commands/compare.ts +123 -0
- package/src/cli/commands/conflicts.ts +41 -0
- package/src/cli/commands/digest.ts +197 -0
- package/src/cli/commands/disable-flagging.ts +34 -0
- package/src/cli/commands/doctor.ts +240 -0
- package/src/cli/commands/download-model.ts +161 -0
- package/src/cli/commands/enable-flagging.ts +34 -0
- package/src/cli/commands/export-knowledge.ts +208 -0
- package/src/cli/commands/export.ts +85 -0
- package/src/cli/commands/freshness.ts +164 -0
- package/src/cli/commands/graph.ts +51 -0
- package/src/cli/commands/history.ts +139 -0
- package/src/cli/commands/import.ts +335 -0
- package/src/cli/commands/install.ts +156 -0
- package/src/cli/commands/lead-report.ts +241 -0
- package/src/cli/commands/learn.ts +321 -0
- package/src/cli/commands/pm-report.ts +413 -0
- package/src/cli/commands/prune.ts +75 -0
- package/src/cli/commands/qa-report.ts +278 -0
- package/src/cli/commands/reindex.ts +104 -0
- package/src/cli/commands/rollback.ts +70 -0
- package/src/cli/commands/search.ts +103 -0
- package/src/cli/commands/server.ts +91 -0
- package/src/cli/commands/share.ts +33 -0
- package/src/cli/commands/stats.ts +79 -0
- package/src/cli/commands/status.ts +176 -0
- package/src/cli/commands/sync.ts +96 -0
- package/src/cli/commands/team.ts +118 -0
- package/src/cli/commands/tour.ts +157 -0
- package/src/cli/commands/visualize-live.ts +162 -0
- package/src/cli/commands/workspace.ts +117 -0
- package/src/cli/index.ts +424 -0
- package/src/cli/learn-progress.ts +87 -0
- package/src/community/detection-bridge.ts +344 -0
- package/src/community/leiden.ts +462 -0
- package/src/community/raptor.ts +210 -0
- package/src/community/scheduler.ts +74 -0
- package/src/community/summarize.ts +115 -0
- package/src/decay/archiver.ts +73 -0
- package/src/decay/bridge-orphan-cleanup.ts +212 -0
- package/src/decay/consolidation-sweep.ts +112 -0
- package/src/decay/decay.ts +116 -0
- package/src/decay/deep-validator.ts +62 -0
- package/src/decay/episodic-promoter.ts +132 -0
- package/src/decay/maintenance-scheduler.ts +326 -0
- package/src/decay/scheduler.ts +6 -0
- package/src/decay/session-sweeper.ts +79 -0
- package/src/decay/types.ts +17 -0
- package/src/freshness/confidence-decay.ts +122 -0
- package/src/freshness/cuckoo-filter.ts +176 -0
- package/src/freshness/deep-validation.ts +345 -0
- package/src/freshness/dirty-tracker.ts +237 -0
- package/src/freshness/file-watcher-layer.ts +119 -0
- package/src/freshness/firewall.ts +64 -0
- package/src/freshness/git-reconcile-layer.ts +161 -0
- package/src/freshness/inverted-index.ts +158 -0
- package/src/freshness/stale-read-layer.ts +222 -0
- package/src/graph/audit.ts +69 -0
- package/src/graph/bridge-db.ts +141 -0
- package/src/graph/communities.ts +195 -0
- package/src/graph/db-interface.ts +259 -0
- package/src/graph/edges.ts +163 -0
- package/src/graph/entities.ts +327 -0
- package/src/graph/episodic-db.ts +113 -0
- package/src/graph/flags.ts +31 -0
- package/src/graph/meta-db.ts +200 -0
- package/src/graph/semantic-db.ts +101 -0
- package/src/graph/session-resume.ts +56 -0
- package/src/graph/snapshots.ts +342 -0
- package/src/graph/staging.ts +151 -0
- package/src/graph/types.ts +128 -0
- package/src/hooks/adapters/claude-code.ts +21 -0
- package/src/hooks/adapters/cline.ts +43 -0
- package/src/hooks/adapters/cursor.ts +65 -0
- package/src/hooks/adapters/generic.ts +12 -0
- package/src/hooks/agent-detect.ts +34 -0
- package/src/hooks/claude-md-directives.ts +32 -0
- package/src/hooks/event-router.ts +182 -0
- package/src/hooks/extractors/pattern-detector.ts +111 -0
- package/src/hooks/handlers/post-compact.ts +30 -0
- package/src/hooks/handlers/post-tool-use.ts +403 -0
- package/src/hooks/handlers/pre-compact.ts +100 -0
- package/src/hooks/handlers/session-end.ts +47 -0
- package/src/hooks/handlers/session-start.ts +154 -0
- package/src/hooks/handlers/stop.ts +128 -0
- package/src/hooks/handlers/user-prompt-submit.ts +68 -0
- package/src/hooks/plugin-branch-switch.ts +68 -0
- package/src/hooks/plugin-common.ts +47 -0
- package/src/hooks/plugin-post-compact.ts +28 -0
- package/src/hooks/plugin-post-tool-use.ts +38 -0
- package/src/hooks/plugin-pre-compact.ts +37 -0
- package/src/hooks/plugin-session-end.ts +37 -0
- package/src/hooks/plugin-session-start.ts +75 -0
- package/src/hooks/plugin-stop.ts +61 -0
- package/src/hooks/plugin-user-prompt-submit.ts +47 -0
- package/src/hooks/types.ts +43 -0
- package/src/knowledge/discovery.ts +238 -0
- package/src/knowledge/external-refs.ts +98 -0
- package/src/knowledge/freshness.ts +221 -0
- package/src/knowledge/ingest.ts +330 -0
- package/src/knowledge/markdown-export.ts +229 -0
- package/src/knowledge/markdown-import.ts +359 -0
- package/src/knowledge/patterns.ts +74 -0
- package/src/knowledge/templates.ts +307 -0
- package/src/llm/ai-sdk-adapter.ts +46 -0
- package/src/llm/config.ts +88 -0
- package/src/llm/cost-tracker.ts +110 -0
- package/src/llm/prompts/extraction.ts +55 -0
- package/src/llm/prompts/summarization.ts +36 -0
- package/src/llm/prompts/validation.ts +37 -0
- package/src/llm/provider-registry.ts +68 -0
- package/src/llm/reliability.ts +179 -0
- package/src/llm/schemas.ts +52 -0
- package/src/mcp/freshness-annotator.ts +69 -0
- package/src/mcp/server.ts +949 -0
- package/src/mcp/tools/sia-ast-query.ts +225 -0
- package/src/mcp/tools/sia-at-time.ts +151 -0
- package/src/mcp/tools/sia-backlinks.ts +87 -0
- package/src/mcp/tools/sia-batch-execute.ts +169 -0
- package/src/mcp/tools/sia-by-file.ts +89 -0
- package/src/mcp/tools/sia-community.ts +113 -0
- package/src/mcp/tools/sia-doctor.ts +73 -0
- package/src/mcp/tools/sia-execute-file.ts +122 -0
- package/src/mcp/tools/sia-execute.ts +104 -0
- package/src/mcp/tools/sia-expand.ts +158 -0
- package/src/mcp/tools/sia-fetch-and-index.ts +241 -0
- package/src/mcp/tools/sia-flag.ts +65 -0
- package/src/mcp/tools/sia-index.ts +111 -0
- package/src/mcp/tools/sia-note.ts +134 -0
- package/src/mcp/tools/sia-search.ts +105 -0
- package/src/mcp/tools/sia-stats.ts +63 -0
- package/src/mcp/tools/sia-sync-status.ts +44 -0
- package/src/mcp/tools/sia-upgrade.ts +247 -0
- package/src/mcp/truncate.ts +231 -0
- package/src/native/bridge.ts +167 -0
- package/src/native/fallback-ast-diff.ts +144 -0
- package/src/native/fallback-graph.ts +325 -0
- package/src/ontology/constraints.ts +56 -0
- package/src/ontology/errors.ts +8 -0
- package/src/ontology/middleware.ts +266 -0
- package/src/retrieval/bm25-search.ts +151 -0
- package/src/retrieval/context-assembly.ts +76 -0
- package/src/retrieval/graph-traversal.ts +168 -0
- package/src/retrieval/pagerank.ts +40 -0
- package/src/retrieval/query-classifier.ts +106 -0
- package/src/retrieval/reranker.ts +156 -0
- package/src/retrieval/search.ts +236 -0
- package/src/retrieval/throttle.ts +102 -0
- package/src/retrieval/vector-search.ts +203 -0
- package/src/retrieval/workspace-search.ts +130 -0
- package/src/sandbox/context-mode.ts +285 -0
- package/src/sandbox/credential-pass.ts +55 -0
- package/src/sandbox/executor.ts +235 -0
- package/src/security/pattern-detector.ts +127 -0
- package/src/security/rule-of-two.ts +50 -0
- package/src/security/sanitize.ts +46 -0
- package/src/security/semantic-consistency.ts +93 -0
- package/src/security/staging-promoter.ts +154 -0
- package/src/shared/config.ts +302 -0
- package/src/shared/diagnostics.ts +210 -0
- package/src/shared/errors.ts +48 -0
- package/src/shared/git-utils.ts +143 -0
- package/src/shared/llm-client.ts +120 -0
- package/src/shared/logger.ts +99 -0
- package/src/shared/types.ts +79 -0
- package/src/sync/client.ts +43 -0
- package/src/sync/conflict.ts +106 -0
- package/src/sync/dedup.ts +183 -0
- package/src/sync/hlc.ts +117 -0
- package/src/sync/keychain.ts +144 -0
- package/src/sync/pull.ts +232 -0
- package/src/sync/push.ts +131 -0
- package/src/types/chokidar.d.ts +23 -0
- package/src/visualization/graph-renderer.ts +312 -0
- package/src/visualization/subgraph-extract.ts +208 -0
- package/src/visualization/views/community-clusters.ts +246 -0
- package/src/visualization/views/dependency-map.ts +189 -0
- package/src/visualization/views/graph-explorer.ts +364 -0
- package/src/visualization/views/timeline.ts +247 -0
- package/src/workspace/api-contracts.ts +226 -0
- package/src/workspace/cross-repo.ts +61 -0
- package/src/workspace/detector.ts +190 -0
- package/src/workspace/manifest.ts +141 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// src/graph/types.ts — Graph domain interfaces for communities, episodes, and MCP results
|
|
2
|
+
|
|
3
|
+
import type { PackagePath, TrustTier, UnixMs } from "@/shared/types";
|
|
4
|
+
|
|
5
|
+
// ── Community types ───────────────────────────────────────────
|
|
6
|
+
|
|
7
|
+
export interface Community {
|
|
8
|
+
id: string;
|
|
9
|
+
level: 0 | 1 | 2;
|
|
10
|
+
parent_id: string | null;
|
|
11
|
+
summary: string | null;
|
|
12
|
+
summary_hash: string | null;
|
|
13
|
+
member_count: number;
|
|
14
|
+
last_summary_member_count: number;
|
|
15
|
+
package_path: PackagePath;
|
|
16
|
+
created_at: UnixMs;
|
|
17
|
+
updated_at: UnixMs;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface CommunityMember {
|
|
21
|
+
community_id: string;
|
|
22
|
+
entity_id: string;
|
|
23
|
+
level: 0 | 1 | 2;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface InsertCommunityInput {
|
|
27
|
+
level: 0 | 1 | 2;
|
|
28
|
+
parent_id?: string | null;
|
|
29
|
+
package_path?: PackagePath;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface UpdateCommunityInput {
|
|
33
|
+
summary?: string | null;
|
|
34
|
+
summary_hash?: string | null;
|
|
35
|
+
member_count?: number;
|
|
36
|
+
last_summary_member_count?: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface CommunitySummary {
|
|
40
|
+
id: string;
|
|
41
|
+
level: 0 | 1 | 2;
|
|
42
|
+
summary: string;
|
|
43
|
+
member_count: number;
|
|
44
|
+
top_entities: Array<{ name: string; type: string }>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ── Episode types ─────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
export interface Episode {
|
|
50
|
+
id: string;
|
|
51
|
+
session_id: string;
|
|
52
|
+
ts: UnixMs;
|
|
53
|
+
type: "conversation" | "tool_use" | "file_read" | "command";
|
|
54
|
+
role: "user" | "assistant" | "tool" | null;
|
|
55
|
+
content: string;
|
|
56
|
+
tool_name: string | null;
|
|
57
|
+
file_path: string | null;
|
|
58
|
+
trust_tier: TrustTier;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface InsertEpisodeInput {
|
|
62
|
+
session_id: string;
|
|
63
|
+
type: Episode["type"];
|
|
64
|
+
role?: Episode["role"];
|
|
65
|
+
content: string;
|
|
66
|
+
tool_name?: string | null;
|
|
67
|
+
file_path?: string | null;
|
|
68
|
+
trust_tier?: TrustTier;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ── MCP result types ──────────────────────────────────────────
|
|
72
|
+
|
|
73
|
+
export interface SiaSearchResult {
|
|
74
|
+
entity_id: string;
|
|
75
|
+
type: string;
|
|
76
|
+
name: string;
|
|
77
|
+
summary: string;
|
|
78
|
+
content: string;
|
|
79
|
+
tags: string[];
|
|
80
|
+
file_paths: string[];
|
|
81
|
+
trust_tier: TrustTier;
|
|
82
|
+
confidence: number;
|
|
83
|
+
importance: number;
|
|
84
|
+
extraction_method?: string;
|
|
85
|
+
conflict_group_id?: string | null;
|
|
86
|
+
t_valid_from?: UnixMs | null;
|
|
87
|
+
t_valid_until?: UnixMs | null;
|
|
88
|
+
source_repo_id?: string;
|
|
89
|
+
source_repo_name?: string;
|
|
90
|
+
freshness?: "fresh" | "stale" | "rotten";
|
|
91
|
+
freshness_detail?: {
|
|
92
|
+
source_path: string;
|
|
93
|
+
source_mtime: number;
|
|
94
|
+
extraction_time: number;
|
|
95
|
+
divergence_seconds: number;
|
|
96
|
+
confidence: number;
|
|
97
|
+
alpha?: number;
|
|
98
|
+
beta?: number;
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface SiaEdge {
|
|
103
|
+
id: string;
|
|
104
|
+
from_id: string;
|
|
105
|
+
to_id: string;
|
|
106
|
+
type: string;
|
|
107
|
+
weight: number;
|
|
108
|
+
confidence: number;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface SiaExpandResult {
|
|
112
|
+
center: SiaSearchResult;
|
|
113
|
+
neighbors: SiaSearchResult[];
|
|
114
|
+
edges: SiaEdge[];
|
|
115
|
+
edge_count: number;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface SiaTemporalResult {
|
|
119
|
+
entities: SiaSearchResult[];
|
|
120
|
+
invalidated_entities: SiaSearchResult[];
|
|
121
|
+
edges: SiaEdge[];
|
|
122
|
+
invalidated_count: number;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface SiaCommunityResult {
|
|
126
|
+
communities: CommunitySummary[];
|
|
127
|
+
global_unavailable: boolean;
|
|
128
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// src/hooks/adapters/claude-code.ts — Native Claude Code adapter (identity mapping)
|
|
2
|
+
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import type { HookEvent } from "@/hooks/types";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Claude Code adapter — identity mapping, no transformation needed.
|
|
9
|
+
* Claude Code emits events that already match Sia's HookEvent format exactly.
|
|
10
|
+
*/
|
|
11
|
+
export function normalizeClaudeCodeEvent(raw: Record<string, unknown>): HookEvent {
|
|
12
|
+
return raw as unknown as HookEvent;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Detect whether the current project is using Claude Code.
|
|
17
|
+
* Looks for the .claude/ directory created by `claude` CLI initialization.
|
|
18
|
+
*/
|
|
19
|
+
export function detectClaudeCode(cwd: string): boolean {
|
|
20
|
+
return existsSync(join(cwd, ".claude"));
|
|
21
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// src/hooks/adapters/cline.ts — Cline hook adapter
|
|
2
|
+
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import type { HookEvent } from "@/hooks/types";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Tool name mapping from Cline's conventions to Claude Code conventions.
|
|
9
|
+
* Cline uses snake_case tool names; Claude Code uses PascalCase.
|
|
10
|
+
*/
|
|
11
|
+
const CLINE_TOOL_NAME_MAP: Record<string, string> = {
|
|
12
|
+
write_to_file: "Write",
|
|
13
|
+
read_file: "Read",
|
|
14
|
+
list_files: "LS",
|
|
15
|
+
search_files: "Grep",
|
|
16
|
+
execute_command: "Bash",
|
|
17
|
+
browser_action: "WebFetch",
|
|
18
|
+
ask_followup_question: "Ask",
|
|
19
|
+
attempt_completion: "TodoWrite",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Cline hooks are nearly identical to Claude Code — thin mapping.
|
|
24
|
+
* The main difference is Cline uses snake_case tool names vs Claude Code's PascalCase.
|
|
25
|
+
*/
|
|
26
|
+
export function normalizeClineEvent(raw: Record<string, unknown>): HookEvent {
|
|
27
|
+
const normalized = { ...raw } as Record<string, unknown>;
|
|
28
|
+
|
|
29
|
+
// Normalize Cline snake_case tool names to Claude Code PascalCase
|
|
30
|
+
if (typeof raw.tool_name === "string") {
|
|
31
|
+
normalized.tool_name = CLINE_TOOL_NAME_MAP[raw.tool_name] ?? raw.tool_name;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return normalized as unknown as HookEvent;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Detect whether the current project is using Cline.
|
|
39
|
+
* Looks for the .clinerules/ directory used by Cline for custom instructions.
|
|
40
|
+
*/
|
|
41
|
+
export function detectCline(cwd: string): boolean {
|
|
42
|
+
return existsSync(join(cwd, ".clinerules"));
|
|
43
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// src/hooks/adapters/cursor.ts — Cursor hook adapter
|
|
2
|
+
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import type { HookEvent } from "@/hooks/types";
|
|
6
|
+
|
|
7
|
+
/** Cursor's native hook event shape */
|
|
8
|
+
interface CursorHookEvent {
|
|
9
|
+
event: "afterFileEdit" | "afterModelResponse" | "beforeSubmitPrompt";
|
|
10
|
+
filePath?: string;
|
|
11
|
+
content?: string;
|
|
12
|
+
response?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Map Cursor hook events to Sia's HookEvent format.
|
|
17
|
+
*
|
|
18
|
+
* Cursor event → Claude Code HookEvent mapping:
|
|
19
|
+
* afterFileEdit → PostToolUse (tool_name: Write)
|
|
20
|
+
* afterModelResponse → Stop
|
|
21
|
+
* beforeSubmitPrompt → UserPromptSubmit
|
|
22
|
+
*/
|
|
23
|
+
export function normalizeCursorEvent(raw: CursorHookEvent): HookEvent {
|
|
24
|
+
const base: Partial<HookEvent> = {
|
|
25
|
+
session_id: "",
|
|
26
|
+
transcript_path: "",
|
|
27
|
+
cwd: "",
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
switch (raw.event) {
|
|
31
|
+
case "afterFileEdit":
|
|
32
|
+
return {
|
|
33
|
+
...base,
|
|
34
|
+
hook_event_name: "PostToolUse",
|
|
35
|
+
tool_name: "Write",
|
|
36
|
+
tool_input: raw.filePath
|
|
37
|
+
? {
|
|
38
|
+
file_path: raw.filePath,
|
|
39
|
+
content: raw.content ?? "",
|
|
40
|
+
}
|
|
41
|
+
: undefined,
|
|
42
|
+
} as HookEvent;
|
|
43
|
+
|
|
44
|
+
case "afterModelResponse":
|
|
45
|
+
return {
|
|
46
|
+
...base,
|
|
47
|
+
hook_event_name: "Stop",
|
|
48
|
+
reason: "exit",
|
|
49
|
+
} as HookEvent;
|
|
50
|
+
|
|
51
|
+
case "beforeSubmitPrompt":
|
|
52
|
+
return {
|
|
53
|
+
...base,
|
|
54
|
+
hook_event_name: "UserPromptSubmit",
|
|
55
|
+
} as HookEvent;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Detect whether the current project is using Cursor.
|
|
61
|
+
* Looks for the .cursor/ directory created by Cursor IDE.
|
|
62
|
+
*/
|
|
63
|
+
export function detectCursor(cwd: string): boolean {
|
|
64
|
+
return existsSync(join(cwd, ".cursor"));
|
|
65
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// src/hooks/adapters/generic.ts — Fallback adapter for agents without hook systems
|
|
2
|
+
|
|
3
|
+
import type { CaptureMode } from "@/llm/provider-registry";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* For agents without hook systems (Windsurf, Aider, etc.), fall back to api
|
|
7
|
+
* capture mode. In api mode, Sia periodically polls or processes transcripts
|
|
8
|
+
* via direct LLM calls rather than relying on event hooks.
|
|
9
|
+
*/
|
|
10
|
+
export function getGenericCaptureMode(): CaptureMode {
|
|
11
|
+
return "api";
|
|
12
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// src/hooks/agent-detect.ts — Auto-detection of AI coding agents
|
|
2
|
+
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import type { CaptureMode } from "@/llm/provider-registry";
|
|
6
|
+
|
|
7
|
+
/** Known AI coding agents that Sia can integrate with */
|
|
8
|
+
export type DetectedAgent = "claude-code" | "cursor" | "cline" | "generic";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Detect which AI agent is active based on directory markers.
|
|
12
|
+
* Used by `npx sia install` to configure appropriate hooks.
|
|
13
|
+
*
|
|
14
|
+
* Detection order (precedence):
|
|
15
|
+
* 1. .claude/ → claude-code
|
|
16
|
+
* 2. .cursor/ → cursor
|
|
17
|
+
* 3. .clinerules/ → cline
|
|
18
|
+
* 4. (none found) → generic
|
|
19
|
+
*/
|
|
20
|
+
export function detectAgent(cwd: string): DetectedAgent {
|
|
21
|
+
if (existsSync(join(cwd, ".claude"))) return "claude-code";
|
|
22
|
+
if (existsSync(join(cwd, ".cursor"))) return "cursor";
|
|
23
|
+
if (existsSync(join(cwd, ".clinerules"))) return "cline";
|
|
24
|
+
return "generic";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get the recommended capture mode for the detected agent.
|
|
29
|
+
* Agents with hook systems use "hooks" mode; those without use "api" mode.
|
|
30
|
+
*/
|
|
31
|
+
export function getRecommendedCaptureMode(agent: DetectedAgent): CaptureMode {
|
|
32
|
+
if (agent === "generic") return "api";
|
|
33
|
+
return "hooks";
|
|
34
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Module: claude-md-directives — Behavioral directives for proactive knowledge capture
|
|
2
|
+
//
|
|
3
|
+
// This string constant is injected into CLAUDE.md to guide the agent toward
|
|
4
|
+
// capturing decisions, conventions, bugs, and solutions during coding sessions.
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* CLAUDE.md behavioral directives that instruct the agent to proactively
|
|
8
|
+
* capture knowledge into Sia's persistent graph memory.
|
|
9
|
+
*
|
|
10
|
+
* Include this block in the project's CLAUDE.md to enable session-aware
|
|
11
|
+
* knowledge capture.
|
|
12
|
+
*/
|
|
13
|
+
export const KNOWLEDGE_DIRECTIVES = `## Sia Knowledge Management
|
|
14
|
+
|
|
15
|
+
When you make decisions during coding:
|
|
16
|
+
- After choosing between architectural alternatives, call mcp__sia__note with
|
|
17
|
+
kind='Decision', including your reasoning and the alternatives you considered.
|
|
18
|
+
- When you establish or recognize a coding pattern the team should follow,
|
|
19
|
+
call mcp__sia__note with kind='Convention'.
|
|
20
|
+
- When you discover a bug's root cause, call mcp__sia__note with kind='Bug'
|
|
21
|
+
and reference the affected files.
|
|
22
|
+
- When you fix a bug, call mcp__sia__note with kind='Solution' and reference
|
|
23
|
+
the Bug it resolves.
|
|
24
|
+
|
|
25
|
+
Before starting work:
|
|
26
|
+
- Call mcp__sia__search to check for relevant prior knowledge about the files
|
|
27
|
+
and symbols you'll be working with.
|
|
28
|
+
|
|
29
|
+
These calls help build persistent memory that survives across sessions.
|
|
30
|
+
You don't need to capture every small edit — focus on decisions, patterns,
|
|
31
|
+
and discoveries that a future developer (or your future self) would want to know.
|
|
32
|
+
`;
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// src/hooks/event-router.ts — HTTP hook endpoint server
|
|
2
|
+
//
|
|
3
|
+
// Runs alongside the MCP stdio server. Receives hook events from Claude Code
|
|
4
|
+
// as HTTP POST requests and dispatches to the appropriate handler.
|
|
5
|
+
//
|
|
6
|
+
// PostToolUse hooks run async (non-blocking). Stop and PreCompact run sync.
|
|
7
|
+
// SessionStart uses a command hook (not HTTP) — handled separately.
|
|
8
|
+
//
|
|
9
|
+
// Uses node:http for cross-runtime compatibility (Bun + Node/Vitest).
|
|
10
|
+
|
|
11
|
+
import { createServer, type Server } from "node:http";
|
|
12
|
+
import type { HookEvent, HookHandler, HookResponse } from "./types";
|
|
13
|
+
|
|
14
|
+
const DEFAULT_PORT = 4521;
|
|
15
|
+
|
|
16
|
+
/** Registry of hook handlers by event name */
|
|
17
|
+
const handlers: Record<string, HookHandler> = {};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Register a handler for a hook event name.
|
|
21
|
+
* Event names: "post-tool-use", "stop", "pre-compact", "post-compact",
|
|
22
|
+
* "session-start", "session-end", "user-prompt-submit"
|
|
23
|
+
*/
|
|
24
|
+
export function registerHandler(eventName: string, handler: HookHandler): void {
|
|
25
|
+
handlers[eventName] = handler;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Get a registered handler. Returns undefined if not found.
|
|
30
|
+
*/
|
|
31
|
+
export function getHandler(eventName: string): HookHandler | undefined {
|
|
32
|
+
return handlers[eventName];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Clear all registered handlers (for testing).
|
|
37
|
+
*/
|
|
38
|
+
export function clearHandlers(): void {
|
|
39
|
+
for (const key of Object.keys(handlers)) {
|
|
40
|
+
delete handlers[key];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Read the full request body as a string. */
|
|
45
|
+
function readBody(req: import("node:http").IncomingMessage): Promise<string> {
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
const chunks: Buffer[] = [];
|
|
48
|
+
req.on("data", (chunk: Buffer) => chunks.push(chunk));
|
|
49
|
+
req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
|
|
50
|
+
req.on("error", reject);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Send a JSON response. */
|
|
55
|
+
function sendJson(res: import("node:http").ServerResponse, status: number, body: unknown): void {
|
|
56
|
+
const json = JSON.stringify(body);
|
|
57
|
+
res.writeHead(status, {
|
|
58
|
+
"Content-Type": "application/json",
|
|
59
|
+
"Content-Length": Buffer.byteLength(json),
|
|
60
|
+
});
|
|
61
|
+
res.end(json);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Start the HTTP hook event server.
|
|
66
|
+
* Returns a server object that can be stopped.
|
|
67
|
+
*/
|
|
68
|
+
export function startHookServer(port: number = DEFAULT_PORT): {
|
|
69
|
+
port: number;
|
|
70
|
+
stop: () => void;
|
|
71
|
+
} {
|
|
72
|
+
const server: Server = createServer(async (req, res) => {
|
|
73
|
+
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
74
|
+
|
|
75
|
+
// Health check
|
|
76
|
+
if (url.pathname === "/health") {
|
|
77
|
+
sendJson(res, 200, {
|
|
78
|
+
status: "ok",
|
|
79
|
+
handlers: Object.keys(handlers),
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Hook dispatch: /hooks/<event-name>
|
|
85
|
+
const match = url.pathname.match(/^\/hooks\/(.+)$/);
|
|
86
|
+
if (!match) {
|
|
87
|
+
res.writeHead(404);
|
|
88
|
+
res.end("Not found");
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const eventName = match[1];
|
|
93
|
+
const handler = handlers[eventName];
|
|
94
|
+
if (!handler) {
|
|
95
|
+
sendJson(res, 404, {
|
|
96
|
+
status: "error",
|
|
97
|
+
error: `No handler for event: ${eventName}`,
|
|
98
|
+
} satisfies HookResponse);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
const body = await readBody(req);
|
|
104
|
+
const event: HookEvent = JSON.parse(body);
|
|
105
|
+
const response = await handler(event);
|
|
106
|
+
sendJson(res, 200, response);
|
|
107
|
+
} catch (err) {
|
|
108
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
109
|
+
sendJson(res, 500, {
|
|
110
|
+
status: "error",
|
|
111
|
+
error: message,
|
|
112
|
+
} satisfies HookResponse);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
server.listen(port);
|
|
117
|
+
|
|
118
|
+
// Resolve the actual port (important when port=0 for random assignment)
|
|
119
|
+
const addr = server.address();
|
|
120
|
+
const actualPort = typeof addr === "object" && addr !== null ? addr.port : port;
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
port: actualPort,
|
|
124
|
+
stop: () => server.close(),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Get the hook configuration for .claude/settings.json.
|
|
130
|
+
* Used by `npx sia install` to register hooks.
|
|
131
|
+
*/
|
|
132
|
+
export function getHookConfig(port: number = DEFAULT_PORT): Record<string, unknown[]> {
|
|
133
|
+
return {
|
|
134
|
+
PostToolUse: [
|
|
135
|
+
{
|
|
136
|
+
type: "http",
|
|
137
|
+
url: `http://localhost:${port}/hooks/post-tool-use`,
|
|
138
|
+
timeout: 5000,
|
|
139
|
+
async: true,
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
Stop: [
|
|
143
|
+
{
|
|
144
|
+
type: "http",
|
|
145
|
+
url: `http://localhost:${port}/hooks/stop`,
|
|
146
|
+
timeout: 10000,
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
PreCompact: [
|
|
150
|
+
{
|
|
151
|
+
type: "http",
|
|
152
|
+
url: `http://localhost:${port}/hooks/pre-compact`,
|
|
153
|
+
timeout: 5000,
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
PostCompact: [
|
|
157
|
+
{
|
|
158
|
+
type: "http",
|
|
159
|
+
url: `http://localhost:${port}/hooks/post-compact`,
|
|
160
|
+
timeout: 5000,
|
|
161
|
+
async: true,
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
SessionStart: [{ type: "command", command: "npx sia hook session-start" }],
|
|
165
|
+
SessionEnd: [
|
|
166
|
+
{
|
|
167
|
+
type: "http",
|
|
168
|
+
url: `http://localhost:${port}/hooks/session-end`,
|
|
169
|
+
timeout: 5000,
|
|
170
|
+
async: true,
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
UserPromptSubmit: [
|
|
174
|
+
{
|
|
175
|
+
type: "http",
|
|
176
|
+
url: `http://localhost:${port}/hooks/user-prompt-submit`,
|
|
177
|
+
timeout: 5000,
|
|
178
|
+
async: true,
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
};
|
|
182
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// Module: pattern-detector — Deterministic knowledge pattern detection (zero LLM)
|
|
2
|
+
//
|
|
3
|
+
// Scans text for structured knowledge markers: decisions, conventions, bugs,
|
|
4
|
+
// concepts, and solutions. Used by PostToolUse and Stop handlers to extract
|
|
5
|
+
// knowledge without requiring an LLM call.
|
|
6
|
+
|
|
7
|
+
import type { EntityType } from "@/capture/types";
|
|
8
|
+
|
|
9
|
+
/** A knowledge pattern detected in text content. */
|
|
10
|
+
export interface DetectedPattern {
|
|
11
|
+
type: EntityType;
|
|
12
|
+
content: string;
|
|
13
|
+
confidence: number;
|
|
14
|
+
/** The line that matched, for dedup downstream. */
|
|
15
|
+
matchedLine: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Content pattern rules — each rule maps a regex to an entity type
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
interface PatternRule {
|
|
23
|
+
type: EntityType;
|
|
24
|
+
pattern: RegExp;
|
|
25
|
+
confidence: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const CONTENT_RULES: PatternRule[] = [
|
|
29
|
+
// Decision markers
|
|
30
|
+
{ type: "Decision", pattern: /\bwe decided\b/i, confidence: 0.85 },
|
|
31
|
+
{ type: "Decision", pattern: /\bchose\s+\S+\s+over\b/i, confidence: 0.8 },
|
|
32
|
+
{ type: "Decision", pattern: /\bdecision:\s*/i, confidence: 0.9 },
|
|
33
|
+
|
|
34
|
+
// Convention markers
|
|
35
|
+
{ type: "Convention", pattern: /\bconvention:\s*/i, confidence: 0.9 },
|
|
36
|
+
{ type: "Convention", pattern: /\balways use\b/i, confidence: 0.7 },
|
|
37
|
+
{ type: "Convention", pattern: /\bnever use\b/i, confidence: 0.7 },
|
|
38
|
+
|
|
39
|
+
// Bug markers
|
|
40
|
+
{ type: "Bug", pattern: /\bBUG:\s*/i, confidence: 0.9 },
|
|
41
|
+
{ type: "Bug", pattern: /\bFIXME:\s*/i, confidence: 0.85 },
|
|
42
|
+
{ type: "Bug", pattern: /\bHACK:\s*/i, confidence: 0.8 },
|
|
43
|
+
|
|
44
|
+
// Concept markers
|
|
45
|
+
{ type: "Concept", pattern: /\bTODO:\s*/i, confidence: 0.75 },
|
|
46
|
+
{ type: "Concept", pattern: /\bREFACTOR:\s*/i, confidence: 0.75 },
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Commit message pattern rules
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
|
|
53
|
+
const COMMIT_RULES: PatternRule[] = [
|
|
54
|
+
{ type: "Solution", pattern: /^fix(\(.+?\))?:\s*/i, confidence: 0.85 },
|
|
55
|
+
{ type: "Decision", pattern: /^feat(\(.+?\))?:\s*/i, confidence: 0.75 },
|
|
56
|
+
{ type: "Decision", pattern: /^refactor(\(.+?\))?:\s*/i, confidence: 0.7 },
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// Public API
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Scan free-form content for knowledge patterns.
|
|
65
|
+
* Processes line-by-line to attribute each match to the originating line.
|
|
66
|
+
* Returns one DetectedPattern per match (a single line may yield multiple).
|
|
67
|
+
*/
|
|
68
|
+
export function detectKnowledgePatterns(content: string): DetectedPattern[] {
|
|
69
|
+
const results: DetectedPattern[] = [];
|
|
70
|
+
const lines = content.split("\n");
|
|
71
|
+
|
|
72
|
+
for (const line of lines) {
|
|
73
|
+
const trimmed = line.trim();
|
|
74
|
+
if (trimmed.length === 0) continue;
|
|
75
|
+
|
|
76
|
+
for (const rule of CONTENT_RULES) {
|
|
77
|
+
if (rule.pattern.test(trimmed)) {
|
|
78
|
+
results.push({
|
|
79
|
+
type: rule.type,
|
|
80
|
+
content: trimmed,
|
|
81
|
+
confidence: rule.confidence,
|
|
82
|
+
matchedLine: trimmed,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return results;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Scan a conventional commit message for knowledge patterns.
|
|
93
|
+
* Recognizes fix/feat/refactor prefixes.
|
|
94
|
+
*/
|
|
95
|
+
export function detectCommitPatterns(message: string): DetectedPattern[] {
|
|
96
|
+
const results: DetectedPattern[] = [];
|
|
97
|
+
const trimmed = message.trim();
|
|
98
|
+
|
|
99
|
+
for (const rule of COMMIT_RULES) {
|
|
100
|
+
if (rule.pattern.test(trimmed)) {
|
|
101
|
+
results.push({
|
|
102
|
+
type: rule.type,
|
|
103
|
+
content: trimmed,
|
|
104
|
+
confidence: rule.confidence,
|
|
105
|
+
matchedLine: trimmed,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return results;
|
|
111
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Module: post-compact — PostCompact hook handler
|
|
2
|
+
//
|
|
3
|
+
// Fires after Claude Code has compacted the context window. This is a
|
|
4
|
+
// lightweight handler — the compaction has already occurred, so there is
|
|
5
|
+
// nothing to capture at this point. Instead, it logs compaction coverage
|
|
6
|
+
// info for observability.
|
|
7
|
+
//
|
|
8
|
+
// Returns { status: "processed", compact_summary_length: N } where N is
|
|
9
|
+
// the character length of the compaction summary provided by Claude Code.
|
|
10
|
+
|
|
11
|
+
import type { HookEvent, HookResponse } from "@/hooks/types";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Create a PostCompact hook handler.
|
|
15
|
+
*
|
|
16
|
+
* Lightweight — logs compaction coverage info and returns immediately.
|
|
17
|
+
* No database writes are performed; knowledge should have been captured
|
|
18
|
+
* by the PreCompact handler before compaction occurred.
|
|
19
|
+
*/
|
|
20
|
+
export function createPostCompactHandler(): (event: HookEvent) => Promise<HookResponse> {
|
|
21
|
+
return async (event: HookEvent): Promise<HookResponse> => {
|
|
22
|
+
const compactSummary = event.compact_summary ?? "";
|
|
23
|
+
const summaryLength = compactSummary.length;
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
status: "processed",
|
|
27
|
+
compact_summary_length: summaryLength,
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
}
|