@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,335 @@
|
|
|
1
|
+
// Module: import — load graph from exported JSON (merge or replace mode)
|
|
2
|
+
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { consolidate } from "@/capture/consolidate";
|
|
5
|
+
import type { CandidateFact } from "@/capture/types";
|
|
6
|
+
import type { ExportData } from "@/cli/commands/export";
|
|
7
|
+
import { writeAuditEntry } from "@/graph/audit";
|
|
8
|
+
import type { SiaDb } from "@/graph/db-interface";
|
|
9
|
+
|
|
10
|
+
/** Aggregate counts returned after an import operation. */
|
|
11
|
+
export interface ImportResult {
|
|
12
|
+
entitiesImported: number;
|
|
13
|
+
edgesImported: number;
|
|
14
|
+
communitiesImported: number;
|
|
15
|
+
mode: "merge" | "replace";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Import graph data from an ExportData payload.
|
|
20
|
+
*
|
|
21
|
+
* Two modes:
|
|
22
|
+
* - **merge**: converts entities to CandidateFact[] and runs through the
|
|
23
|
+
* consolidation pipeline; edges are inserted only when both endpoints exist;
|
|
24
|
+
* communities use INSERT OR IGNORE.
|
|
25
|
+
* - **replace**: archives all active entities, then bulk-inserts everything
|
|
26
|
+
* from the export data directly.
|
|
27
|
+
*/
|
|
28
|
+
export async function importGraph(
|
|
29
|
+
db: SiaDb,
|
|
30
|
+
data: ExportData,
|
|
31
|
+
mode: "merge" | "replace",
|
|
32
|
+
): Promise<ImportResult> {
|
|
33
|
+
if (data.version !== 1) {
|
|
34
|
+
throw new Error(`Unsupported export version: ${data.version}. Expected version 1.`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (mode === "merge") {
|
|
38
|
+
return mergeImport(db, data);
|
|
39
|
+
}
|
|
40
|
+
return replaceImport(db, data);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
// Merge mode
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
async function mergeImport(db: SiaDb, data: ExportData): Promise<ImportResult> {
|
|
48
|
+
const result: ImportResult = {
|
|
49
|
+
entitiesImported: 0,
|
|
50
|
+
edgesImported: 0,
|
|
51
|
+
communitiesImported: 0,
|
|
52
|
+
mode: "merge",
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// 1. Convert entities to CandidateFact[] and consolidate
|
|
56
|
+
const candidates: CandidateFact[] = data.entities.map((e) => ({
|
|
57
|
+
type: (e.type as CandidateFact["type"]) ?? "Concept",
|
|
58
|
+
name: (e.name as string) ?? "",
|
|
59
|
+
content: (e.content as string) ?? "",
|
|
60
|
+
summary: (e.summary as string) ?? "",
|
|
61
|
+
tags: parseTags(e.tags),
|
|
62
|
+
file_paths: parseFilePaths(e.file_paths),
|
|
63
|
+
trust_tier: parseTrustTier(e.trust_tier),
|
|
64
|
+
confidence: typeof e.confidence === "number" ? e.confidence : 0.7,
|
|
65
|
+
extraction_method: (e.extraction_method as string) ?? undefined,
|
|
66
|
+
t_valid_from: typeof e.t_valid_from === "number" ? e.t_valid_from : undefined,
|
|
67
|
+
}));
|
|
68
|
+
|
|
69
|
+
const consolidationResult = await consolidate(db, candidates);
|
|
70
|
+
result.entitiesImported = consolidationResult.added + consolidationResult.updated;
|
|
71
|
+
|
|
72
|
+
// 2. Import edges — only if both endpoints exist in the graph
|
|
73
|
+
for (const edge of data.edges) {
|
|
74
|
+
const fromId = edge.from_id as string;
|
|
75
|
+
const toId = edge.to_id as string;
|
|
76
|
+
if (!fromId || !toId) continue;
|
|
77
|
+
|
|
78
|
+
const fromExists = await db.execute("SELECT 1 FROM graph_nodes WHERE id = ?", [fromId]);
|
|
79
|
+
const toExists = await db.execute("SELECT 1 FROM graph_nodes WHERE id = ?", [toId]);
|
|
80
|
+
|
|
81
|
+
if (fromExists.rows.length > 0 && toExists.rows.length > 0) {
|
|
82
|
+
await db.execute(
|
|
83
|
+
`INSERT INTO graph_edges (id, from_id, to_id, type, weight, confidence, trust_tier,
|
|
84
|
+
t_created, t_expired, t_valid_from, t_valid_until,
|
|
85
|
+
source_episode, extraction_method)
|
|
86
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
87
|
+
[
|
|
88
|
+
edge.id as string,
|
|
89
|
+
fromId,
|
|
90
|
+
toId,
|
|
91
|
+
(edge.type as string) ?? "RELATED_TO",
|
|
92
|
+
typeof edge.weight === "number" ? edge.weight : 1.0,
|
|
93
|
+
typeof edge.confidence === "number" ? edge.confidence : 0.7,
|
|
94
|
+
typeof edge.trust_tier === "number" ? edge.trust_tier : 3,
|
|
95
|
+
typeof edge.t_created === "number" ? edge.t_created : Date.now(),
|
|
96
|
+
edge.t_expired ?? null,
|
|
97
|
+
edge.t_valid_from ?? null,
|
|
98
|
+
edge.t_valid_until ?? null,
|
|
99
|
+
edge.source_episode ?? null,
|
|
100
|
+
edge.extraction_method ?? null,
|
|
101
|
+
],
|
|
102
|
+
);
|
|
103
|
+
result.edgesImported++;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 3. Import communities — INSERT OR IGNORE
|
|
108
|
+
for (const community of data.communities) {
|
|
109
|
+
await db.execute(
|
|
110
|
+
`INSERT OR IGNORE INTO communities (id, level, parent_id, summary, member_count, package_path, created_at, updated_at)
|
|
111
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
112
|
+
[
|
|
113
|
+
community.id ?? null,
|
|
114
|
+
community.level ?? 0,
|
|
115
|
+
community.parent_id ?? null,
|
|
116
|
+
community.summary ?? "",
|
|
117
|
+
community.member_count ?? 0,
|
|
118
|
+
community.package_path ?? null,
|
|
119
|
+
community.created_at ?? Date.now(),
|
|
120
|
+
community.updated_at ?? Date.now(),
|
|
121
|
+
],
|
|
122
|
+
);
|
|
123
|
+
result.communitiesImported++;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 4. Audit log
|
|
127
|
+
await writeAuditEntry(db, "ADD", {
|
|
128
|
+
extraction_method: `import:merge:${result.entitiesImported}e/${result.edgesImported}ed/${result.communitiesImported}c`,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
// Replace mode
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
|
|
138
|
+
async function replaceImport(db: SiaDb, data: ExportData): Promise<ImportResult> {
|
|
139
|
+
const result: ImportResult = {
|
|
140
|
+
entitiesImported: 0,
|
|
141
|
+
edgesImported: 0,
|
|
142
|
+
communitiesImported: 0,
|
|
143
|
+
mode: "replace",
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const now = Date.now();
|
|
147
|
+
|
|
148
|
+
await db.transaction(async (tx) => {
|
|
149
|
+
// 1. Archive all currently active entities
|
|
150
|
+
await tx.execute(
|
|
151
|
+
"UPDATE graph_nodes SET archived_at = ? WHERE t_valid_until IS NULL AND archived_at IS NULL",
|
|
152
|
+
[now],
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
// 2. Insert all entities from export data
|
|
156
|
+
for (const e of data.entities) {
|
|
157
|
+
await tx.execute(
|
|
158
|
+
`INSERT INTO graph_nodes (
|
|
159
|
+
id, type, name, content, summary,
|
|
160
|
+
package_path, tags, file_paths,
|
|
161
|
+
trust_tier, confidence, base_confidence,
|
|
162
|
+
importance, base_importance,
|
|
163
|
+
access_count, edge_count,
|
|
164
|
+
last_accessed, created_at,
|
|
165
|
+
t_created, t_expired, t_valid_from, t_valid_until,
|
|
166
|
+
visibility, created_by, workspace_scope,
|
|
167
|
+
hlc_created, hlc_modified, synced_at,
|
|
168
|
+
conflict_group_id,
|
|
169
|
+
source_episode, extraction_method, extraction_model,
|
|
170
|
+
embedding, archived_at
|
|
171
|
+
) VALUES (
|
|
172
|
+
?, ?, ?, ?, ?,
|
|
173
|
+
?, ?, ?,
|
|
174
|
+
?, ?, ?,
|
|
175
|
+
?, ?,
|
|
176
|
+
?, ?,
|
|
177
|
+
?, ?,
|
|
178
|
+
?, ?, ?, ?,
|
|
179
|
+
?, ?, ?,
|
|
180
|
+
?, ?, ?,
|
|
181
|
+
?,
|
|
182
|
+
?, ?, ?,
|
|
183
|
+
?, ?
|
|
184
|
+
)`,
|
|
185
|
+
[
|
|
186
|
+
e.id as string,
|
|
187
|
+
e.type as string,
|
|
188
|
+
e.name as string,
|
|
189
|
+
e.content as string,
|
|
190
|
+
e.summary as string,
|
|
191
|
+
e.package_path ?? null,
|
|
192
|
+
typeof e.tags === "string" ? e.tags : JSON.stringify(e.tags ?? []),
|
|
193
|
+
typeof e.file_paths === "string" ? e.file_paths : JSON.stringify(e.file_paths ?? []),
|
|
194
|
+
typeof e.trust_tier === "number" ? e.trust_tier : 3,
|
|
195
|
+
typeof e.confidence === "number" ? e.confidence : 0.7,
|
|
196
|
+
typeof e.base_confidence === "number" ? e.base_confidence : 0.7,
|
|
197
|
+
typeof e.importance === "number" ? e.importance : 0.5,
|
|
198
|
+
typeof e.base_importance === "number" ? e.base_importance : 0.5,
|
|
199
|
+
typeof e.access_count === "number" ? e.access_count : 0,
|
|
200
|
+
typeof e.edge_count === "number" ? e.edge_count : 0,
|
|
201
|
+
typeof e.last_accessed === "number" ? e.last_accessed : now,
|
|
202
|
+
typeof e.created_at === "number" ? e.created_at : now,
|
|
203
|
+
typeof e.t_created === "number" ? e.t_created : now,
|
|
204
|
+
e.t_expired ?? null,
|
|
205
|
+
e.t_valid_from ?? null,
|
|
206
|
+
e.t_valid_until ?? null,
|
|
207
|
+
(e.visibility as string) ?? "private",
|
|
208
|
+
(e.created_by as string) ?? "local",
|
|
209
|
+
e.workspace_scope ?? null,
|
|
210
|
+
e.hlc_created ?? null,
|
|
211
|
+
e.hlc_modified ?? null,
|
|
212
|
+
e.synced_at ?? null,
|
|
213
|
+
e.conflict_group_id ?? null,
|
|
214
|
+
e.source_episode ?? null,
|
|
215
|
+
e.extraction_method ?? null,
|
|
216
|
+
e.extraction_model ?? null,
|
|
217
|
+
e.embedding ?? null,
|
|
218
|
+
e.archived_at ?? null,
|
|
219
|
+
],
|
|
220
|
+
);
|
|
221
|
+
result.entitiesImported++;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// 3. Insert all edges from export data
|
|
225
|
+
for (const edge of data.edges) {
|
|
226
|
+
await tx.execute(
|
|
227
|
+
`INSERT INTO graph_edges (id, from_id, to_id, type, weight, confidence, trust_tier,
|
|
228
|
+
t_created, t_expired, t_valid_from, t_valid_until,
|
|
229
|
+
source_episode, extraction_method)
|
|
230
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
231
|
+
[
|
|
232
|
+
edge.id as string,
|
|
233
|
+
edge.from_id as string,
|
|
234
|
+
edge.to_id as string,
|
|
235
|
+
(edge.type as string) ?? "RELATED_TO",
|
|
236
|
+
typeof edge.weight === "number" ? edge.weight : 1.0,
|
|
237
|
+
typeof edge.confidence === "number" ? edge.confidence : 0.7,
|
|
238
|
+
typeof edge.trust_tier === "number" ? edge.trust_tier : 3,
|
|
239
|
+
typeof edge.t_created === "number" ? edge.t_created : now,
|
|
240
|
+
edge.t_expired ?? null,
|
|
241
|
+
edge.t_valid_from ?? null,
|
|
242
|
+
edge.t_valid_until ?? null,
|
|
243
|
+
edge.source_episode ?? null,
|
|
244
|
+
edge.extraction_method ?? null,
|
|
245
|
+
],
|
|
246
|
+
);
|
|
247
|
+
result.edgesImported++;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// 4. Insert communities
|
|
251
|
+
for (const community of data.communities) {
|
|
252
|
+
await tx.execute(
|
|
253
|
+
`INSERT INTO communities (id, level, parent_id, summary, member_count, package_path, created_at, updated_at)
|
|
254
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
255
|
+
[
|
|
256
|
+
community.id ?? null,
|
|
257
|
+
community.level ?? 0,
|
|
258
|
+
community.parent_id ?? null,
|
|
259
|
+
community.summary ?? "",
|
|
260
|
+
community.member_count ?? 0,
|
|
261
|
+
community.package_path ?? null,
|
|
262
|
+
community.created_at ?? Date.now(),
|
|
263
|
+
community.updated_at ?? Date.now(),
|
|
264
|
+
],
|
|
265
|
+
);
|
|
266
|
+
result.communitiesImported++;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// 5. Audit log
|
|
270
|
+
await writeAuditEntry(tx, "ADD", {
|
|
271
|
+
extraction_method: `import:replace:${result.entitiesImported}e/${result.edgesImported}ed/${result.communitiesImported}c`,
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
return result;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
// File I/O
|
|
280
|
+
// ---------------------------------------------------------------------------
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Import graph data from a JSON file on disk.
|
|
284
|
+
*
|
|
285
|
+
* Reads the file, parses it as ExportData, and delegates to importGraph.
|
|
286
|
+
*/
|
|
287
|
+
export async function importFromFile(
|
|
288
|
+
db: SiaDb,
|
|
289
|
+
filePath: string,
|
|
290
|
+
mode: "merge" | "replace",
|
|
291
|
+
): Promise<ImportResult> {
|
|
292
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
293
|
+
const data = JSON.parse(raw) as ExportData;
|
|
294
|
+
return importGraph(db, data, mode);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// ---------------------------------------------------------------------------
|
|
298
|
+
// Helpers
|
|
299
|
+
// ---------------------------------------------------------------------------
|
|
300
|
+
|
|
301
|
+
/** Parse tags from an export row — handles both JSON strings and arrays. */
|
|
302
|
+
function parseTags(raw: unknown): string[] {
|
|
303
|
+
if (Array.isArray(raw)) return raw as string[];
|
|
304
|
+
if (typeof raw === "string") {
|
|
305
|
+
try {
|
|
306
|
+
const parsed = JSON.parse(raw);
|
|
307
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
308
|
+
} catch {
|
|
309
|
+
return [];
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return [];
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/** Parse file_paths from an export row — handles both JSON strings and arrays. */
|
|
316
|
+
function parseFilePaths(raw: unknown): string[] {
|
|
317
|
+
if (Array.isArray(raw)) return raw as string[];
|
|
318
|
+
if (typeof raw === "string") {
|
|
319
|
+
try {
|
|
320
|
+
const parsed = JSON.parse(raw);
|
|
321
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
322
|
+
} catch {
|
|
323
|
+
return [];
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return [];
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/** Parse trust_tier ensuring it falls within the 1-4 range. */
|
|
330
|
+
function parseTrustTier(raw: unknown): 1 | 2 | 3 | 4 {
|
|
331
|
+
if (typeof raw === "number" && raw >= 1 && raw <= 4) {
|
|
332
|
+
return raw as 1 | 2 | 3 | 4;
|
|
333
|
+
}
|
|
334
|
+
return 3;
|
|
335
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// Module: install — sia install command implementation
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { basename, join, resolve } from "node:path";
|
|
5
|
+
import { openBridgeDb } from "@/graph/bridge-db";
|
|
6
|
+
import { openMetaDb, registerRepo } from "@/graph/meta-db";
|
|
7
|
+
import { openEpisodicDb, openGraphDb } from "@/graph/semantic-db";
|
|
8
|
+
import { SIA_HOME, writeConfig } from "@/shared/config";
|
|
9
|
+
|
|
10
|
+
/** Result returned by siaInstall on success. */
|
|
11
|
+
export interface SiaInstallResult {
|
|
12
|
+
repoHash: string;
|
|
13
|
+
siaHome: string;
|
|
14
|
+
dbsInitialized: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Walk up from `startDir` looking for a `.git` directory.
|
|
19
|
+
* Returns the directory containing `.git`, or null if none found.
|
|
20
|
+
*/
|
|
21
|
+
function findRepoRoot(startDir: string): string | null {
|
|
22
|
+
let dir = resolve(startDir);
|
|
23
|
+
const root = resolve("/");
|
|
24
|
+
while (dir !== root) {
|
|
25
|
+
if (existsSync(join(dir, ".git"))) {
|
|
26
|
+
return dir;
|
|
27
|
+
}
|
|
28
|
+
const parent = resolve(dir, "..");
|
|
29
|
+
if (parent === dir) break;
|
|
30
|
+
dir = parent;
|
|
31
|
+
}
|
|
32
|
+
// Check root as well
|
|
33
|
+
if (existsSync(join(dir, ".git"))) {
|
|
34
|
+
return dir;
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Install Sia for a repository.
|
|
41
|
+
*
|
|
42
|
+
* Detects the repo root, initializes all databases, registers the repo,
|
|
43
|
+
* writes default config, copies the CLAUDE.md template, and creates the
|
|
44
|
+
* ast-cache directory.
|
|
45
|
+
*/
|
|
46
|
+
export async function siaInstall(opts?: {
|
|
47
|
+
cwd?: string;
|
|
48
|
+
siaHome?: string;
|
|
49
|
+
}): Promise<SiaInstallResult> {
|
|
50
|
+
const cwd = opts?.cwd ?? process.cwd();
|
|
51
|
+
const siaHome = opts?.siaHome ?? SIA_HOME;
|
|
52
|
+
|
|
53
|
+
// (a) Detect repo root
|
|
54
|
+
const repoRoot = findRepoRoot(cwd);
|
|
55
|
+
if (!repoRoot) {
|
|
56
|
+
throw new Error(`No .git directory found from ${cwd}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// (b) Compute repo hash
|
|
60
|
+
const resolvedPath = resolve(repoRoot);
|
|
61
|
+
const repoHash = createHash("sha256").update(resolvedPath).digest("hex");
|
|
62
|
+
|
|
63
|
+
// (c) Create repo directory
|
|
64
|
+
const repoDir = join(siaHome, "repos", repoHash);
|
|
65
|
+
mkdirSync(repoDir, { recursive: true });
|
|
66
|
+
|
|
67
|
+
// (d) Initialize all 4 databases, then close each
|
|
68
|
+
const graphDb = openGraphDb(repoHash, siaHome);
|
|
69
|
+
await graphDb.close();
|
|
70
|
+
|
|
71
|
+
const episodicDb = openEpisodicDb(repoHash, siaHome);
|
|
72
|
+
await episodicDb.close();
|
|
73
|
+
|
|
74
|
+
const metaDb = openMetaDb(siaHome);
|
|
75
|
+
|
|
76
|
+
// (e) Register repo in meta.db
|
|
77
|
+
await registerRepo(metaDb, resolvedPath);
|
|
78
|
+
await metaDb.close();
|
|
79
|
+
|
|
80
|
+
const bridgeDb = openBridgeDb(siaHome);
|
|
81
|
+
await bridgeDb.close();
|
|
82
|
+
|
|
83
|
+
// (f) Write default config if absent
|
|
84
|
+
const configPath = join(siaHome, "config.json");
|
|
85
|
+
if (!existsSync(configPath)) {
|
|
86
|
+
writeConfig({}, siaHome);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// (g) Copy CLAUDE.md template to project root
|
|
90
|
+
writeClaude(repoRoot, resolvedPath);
|
|
91
|
+
|
|
92
|
+
// (h) Create ast-cache directory
|
|
93
|
+
const astCacheDir = join(siaHome, "ast-cache", repoHash);
|
|
94
|
+
mkdirSync(astCacheDir, { recursive: true });
|
|
95
|
+
|
|
96
|
+
// (i) Print success message
|
|
97
|
+
console.log(`Sia installed successfully.`);
|
|
98
|
+
console.log(` Repo hash: ${repoHash}`);
|
|
99
|
+
console.log(` Sia home: ${siaHome}`);
|
|
100
|
+
console.log(` Repo path: ${resolvedPath}`);
|
|
101
|
+
|
|
102
|
+
// (j) Return result
|
|
103
|
+
return { repoHash, siaHome, dbsInitialized: true };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** End-of-generated-block marker used in CLAUDE.md */
|
|
107
|
+
const END_MARKER = "<!-- END GENERATED BLOCK -->";
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Read the CLAUDE.md template, substitute placeholders, and write to project root.
|
|
111
|
+
* - If CLAUDE.md does not exist: write the full file.
|
|
112
|
+
* - If CLAUDE.md exists and contains the END_MARKER: replace everything up to and
|
|
113
|
+
* including the marker, preserving user content after it.
|
|
114
|
+
* - If CLAUDE.md exists but has no END_MARKER: skip (do not overwrite).
|
|
115
|
+
*/
|
|
116
|
+
function writeClaude(repoRoot: string, resolvedPath: string): void {
|
|
117
|
+
const templatePath = resolve(import.meta.dirname, "../../agent/claude-md-template.md");
|
|
118
|
+
if (!existsSync(templatePath)) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const template = readFileSync(templatePath, "utf-8");
|
|
123
|
+
const pkgPath = resolve(import.meta.dirname, "../../../package.json");
|
|
124
|
+
let version = "0.0.0";
|
|
125
|
+
if (existsSync(pkgPath)) {
|
|
126
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
127
|
+
version = pkg.version ?? version;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const repoName = basename(resolvedPath);
|
|
131
|
+
const rendered = template
|
|
132
|
+
.replace(/\{\{SIA_VERSION\}\}/g, version)
|
|
133
|
+
.replace(/\{\{GENERATED_AT\}\}/g, new Date().toISOString())
|
|
134
|
+
.replace(/\{\{WORKSPACE_NAME\}\}/g, repoName);
|
|
135
|
+
|
|
136
|
+
const claudePath = join(repoRoot, "CLAUDE.md");
|
|
137
|
+
|
|
138
|
+
if (!existsSync(claudePath)) {
|
|
139
|
+
// File does not exist — write fresh
|
|
140
|
+
writeFileSync(claudePath, rendered, "utf-8");
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// File exists — check for END_MARKER
|
|
145
|
+
const existing = readFileSync(claudePath, "utf-8");
|
|
146
|
+
const markerIdx = existing.indexOf(END_MARKER);
|
|
147
|
+
|
|
148
|
+
if (markerIdx === -1) {
|
|
149
|
+
// No marker found — skip to avoid overwriting user content
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Replace everything up to and including the marker, keep user content after
|
|
154
|
+
const userContent = existing.slice(markerIdx + END_MARKER.length);
|
|
155
|
+
writeFileSync(claudePath, rendered + userContent, "utf-8");
|
|
156
|
+
}
|