@mrc2204/agent-smart-memo 5.0.1 → 5.1.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.
Files changed (30) hide show
  1. package/dist/core/contracts/adapter-contracts.d.ts +1 -1
  2. package/dist/core/contracts/adapter-contracts.d.ts.map +1 -1
  3. package/dist/core/ingest/contracts.d.ts +44 -0
  4. package/dist/core/ingest/contracts.d.ts.map +1 -0
  5. package/dist/core/ingest/contracts.js +2 -0
  6. package/dist/core/ingest/contracts.js.map +1 -0
  7. package/dist/core/ingest/ids.d.ts +5 -0
  8. package/dist/core/ingest/ids.d.ts.map +1 -0
  9. package/dist/core/ingest/ids.js +17 -0
  10. package/dist/core/ingest/ids.js.map +1 -0
  11. package/dist/core/ingest/ingest-pipeline.d.ts +4 -0
  12. package/dist/core/ingest/ingest-pipeline.d.ts.map +1 -0
  13. package/dist/core/ingest/ingest-pipeline.js +105 -0
  14. package/dist/core/ingest/ingest-pipeline.js.map +1 -0
  15. package/dist/core/ingest/semantic-block-extractor.d.ts +9 -0
  16. package/dist/core/ingest/semantic-block-extractor.d.ts.map +1 -0
  17. package/dist/core/ingest/semantic-block-extractor.js +135 -0
  18. package/dist/core/ingest/semantic-block-extractor.js.map +1 -0
  19. package/dist/core/usecases/default-memory-usecase-port.d.ts +3 -0
  20. package/dist/core/usecases/default-memory-usecase-port.d.ts.map +1 -1
  21. package/dist/core/usecases/default-memory-usecase-port.js +124 -12
  22. package/dist/core/usecases/default-memory-usecase-port.js.map +1 -1
  23. package/dist/db/slot-db.d.ts +8 -1
  24. package/dist/db/slot-db.d.ts.map +1 -1
  25. package/dist/db/slot-db.js +132 -22
  26. package/dist/db/slot-db.js.map +1 -1
  27. package/dist/tools/project-tools.d.ts.map +1 -1
  28. package/dist/tools/project-tools.js +68 -0
  29. package/dist/tools/project-tools.js.map +1 -1
  30. package/package.json +1 -1
@@ -17,7 +17,7 @@ export interface CoreRequestEnvelope<TPayload> {
17
17
  requestId?: string;
18
18
  };
19
19
  }
20
- export type MemoryUseCaseName = "slot.get" | "slot.set" | "slot.list" | "slot.delete" | "project.register" | "project.get" | "project.list" | "project.set_registration_state" | "project.set_tracker_mapping" | "project.register_command" | "project.link_tracker" | "project.trigger_index" | "project.reindex_diff" | "project.index_watch_get" | "project.task_registry_upsert" | "project.task_lineage_context" | "project.hybrid_search" | "project.legacy_backfill" | "project.telegram_onboarding" | "memory.capture" | "memory.search" | "graph.entity.get" | "graph.entity.set" | "graph.rel.add" | "graph.rel.remove" | "graph.search";
20
+ export type MemoryUseCaseName = "slot.get" | "slot.set" | "slot.list" | "slot.delete" | "project.register" | "project.get" | "project.list" | "project.set_registration_state" | "project.set_tracker_mapping" | "project.register_command" | "project.link_tracker" | "project.trigger_index" | "project.reindex_diff" | "project.index_event" | "project.install_hooks" | "project.index_watch_get" | "project.task_registry_upsert" | "project.task_lineage_context" | "project.hybrid_search" | "project.legacy_backfill" | "project.telegram_onboarding" | "memory.capture" | "memory.search" | "graph.entity.get" | "graph.entity.set" | "graph.rel.add" | "graph.rel.remove" | "graph.search";
21
21
  export interface MemoryUseCasePort {
22
22
  run<TReq, TRes>(useCase: MemoryUseCaseName, req: CoreRequestEnvelope<TReq>): Promise<TRes>;
23
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"adapter-contracts.d.ts","sourceRoot":"","sources":["../../../src/core/contracts/adapter-contracts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,mBAAmB,CAAC,QAAQ;IAC3C,OAAO,EAAE,aAAa,CAAC;IACvB,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,OAAO,EAAE,QAAQ,CAAC;IAClB,IAAI,CAAC,EAAE;QACL,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,KAAK,GAAG,MAAM,CAAC;QAClD,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,UAAU,GACV,WAAW,GACX,aAAa,GACb,kBAAkB,GAClB,aAAa,GACb,cAAc,GACd,gCAAgC,GAChC,6BAA6B,GAC7B,0BAA0B,GAC1B,sBAAsB,GACtB,uBAAuB,GACvB,sBAAsB,GACtB,yBAAyB,GACzB,8BAA8B,GAC9B,8BAA8B,GAC9B,uBAAuB,GACvB,yBAAyB,GACzB,6BAA6B,GAC7B,gBAAgB,GAChB,eAAe,GACf,kBAAkB,GAClB,kBAAkB,GAClB,eAAe,GACf,kBAAkB,GAClB,cAAc,CAAC;AAEnB,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,IAAI,EAAE,IAAI,EACZ,OAAO,EAAE,iBAAiB,EAC1B,GAAG,EAAE,mBAAmB,CAAC,IAAI,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB,CAAC,WAAW;IAC/C,eAAe,CAAC,UAAU,EAAE,WAAW,GAAG,aAAa,CAAC;IACxD,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,CAAC;CAC1D;AAED,MAAM,WAAW,qBAAqB,CAAC,WAAW;IAChD,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAAC;CAC9C"}
1
+ {"version":3,"file":"adapter-contracts.d.ts","sourceRoot":"","sources":["../../../src/core/contracts/adapter-contracts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,mBAAmB,CAAC,QAAQ;IAC3C,OAAO,EAAE,aAAa,CAAC;IACvB,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,OAAO,EAAE,QAAQ,CAAC;IAClB,IAAI,CAAC,EAAE;QACL,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,KAAK,GAAG,MAAM,CAAC;QAClD,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,UAAU,GACV,WAAW,GACX,aAAa,GACb,kBAAkB,GAClB,aAAa,GACb,cAAc,GACd,gCAAgC,GAChC,6BAA6B,GAC7B,0BAA0B,GAC1B,sBAAsB,GACtB,uBAAuB,GACvB,sBAAsB,GACtB,qBAAqB,GACrB,uBAAuB,GACvB,yBAAyB,GACzB,8BAA8B,GAC9B,8BAA8B,GAC9B,uBAAuB,GACvB,yBAAyB,GACzB,6BAA6B,GAC7B,gBAAgB,GAChB,eAAe,GACf,kBAAkB,GAClB,kBAAkB,GAClB,eAAe,GACf,kBAAkB,GAClB,cAAc,CAAC;AAEnB,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,IAAI,EAAE,IAAI,EACZ,OAAO,EAAE,iBAAiB,EAC1B,GAAG,EAAE,mBAAmB,CAAC,IAAI,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB,CAAC,WAAW;IAC/C,eAAe,CAAC,UAAU,EAAE,WAAW,GAAG,aAAa,CAAC;IACxD,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,CAAC;CAC1D;AAED,MAAM,WAAW,qBAAqB,CAAC,WAAW;IAChD,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAAC;CAC9C"}
@@ -0,0 +1,44 @@
1
+ export type IngestTriggerType = "bootstrap" | "incremental" | "manual" | "repair";
2
+ export interface IngestPlanInput {
3
+ project_id: string;
4
+ source_rev: string;
5
+ trigger_type: IngestTriggerType;
6
+ index_profile: string;
7
+ include_overrides?: string[];
8
+ max_file_bytes?: number;
9
+ }
10
+ export interface FileCandidateInput {
11
+ relative_path: string;
12
+ content: string;
13
+ bytes?: number;
14
+ }
15
+ export interface FilePlanEntry {
16
+ relative_path: string;
17
+ file_id: string;
18
+ include: boolean;
19
+ reason: "included" | "ignored_path" | "binary_ext" | "oversized";
20
+ checksum: string;
21
+ bytes: number;
22
+ }
23
+ export type SemanticBlockKind = "function" | "class" | "method" | "doc_section" | "doc_paragraph";
24
+ export interface SemanticBlock {
25
+ kind: SemanticBlockKind;
26
+ symbol_name: string;
27
+ semantic_path: string;
28
+ start_line: number;
29
+ end_line: number;
30
+ ordinal: number;
31
+ text: string;
32
+ }
33
+ export interface ChunkArtifact {
34
+ chunk_id: string;
35
+ file_id: string;
36
+ relative_path: string;
37
+ chunk_kind: SemanticBlockKind;
38
+ symbol_id: string | null;
39
+ checksum: string;
40
+ semantic_path: string;
41
+ ordinal: number;
42
+ text: string;
43
+ }
44
+ //# sourceMappingURL=contracts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../../src/core/ingest/contracts.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,aAAa,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAElF,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,iBAAiB,CAAC;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,UAAU,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,CAAC;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,OAAO,GACP,QAAQ,GACR,aAAa,GACb,eAAe,CAAC;AAEpB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,iBAAiB,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=contracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../../src/core/ingest/contracts.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ export declare function buildFileId(projectId: string, relativePath: string): string;
2
+ export declare function buildChunkId(fileId: string, chunkKind: string, semanticPath: string, ordinal: number): string;
3
+ export declare function buildSymbolId(projectId: string, relativePath: string, symbolFqn: string): string;
4
+ export declare function checksumOf(raw: string): string;
5
+ //# sourceMappingURL=ids.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../../../src/core/ingest/ids.ts"],"names":[],"mappings":"AAMA,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,GACd,MAAM,CAER;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEhG;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C"}
@@ -0,0 +1,17 @@
1
+ import { createHash } from "node:crypto";
2
+ function sha1(raw) {
3
+ return createHash("sha1").update(raw).digest("hex");
4
+ }
5
+ export function buildFileId(projectId, relativePath) {
6
+ return sha1(`${projectId}:${relativePath}`);
7
+ }
8
+ export function buildChunkId(fileId, chunkKind, semanticPath, ordinal) {
9
+ return sha1(`${fileId}:${chunkKind}:${semanticPath}:${ordinal}`);
10
+ }
11
+ export function buildSymbolId(projectId, relativePath, symbolFqn) {
12
+ return sha1(`${projectId}:${relativePath}:${symbolFqn}`);
13
+ }
14
+ export function checksumOf(raw) {
15
+ return sha1(raw);
16
+ }
17
+ //# sourceMappingURL=ids.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ids.js","sourceRoot":"","sources":["../../../src/core/ingest/ids.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,SAAS,IAAI,CAAC,GAAW;IACvB,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,SAAiB,EAAE,YAAoB;IACjE,OAAO,IAAI,CAAC,GAAG,SAAS,IAAI,YAAY,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,MAAc,EACd,SAAiB,EACjB,YAAoB,EACpB,OAAe;IAEf,OAAO,IAAI,CAAC,GAAG,MAAM,IAAI,SAAS,IAAI,YAAY,IAAI,OAAO,EAAE,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,SAAiB,EAAE,YAAoB,EAAE,SAAiB;IACtF,OAAO,IAAI,CAAC,GAAG,SAAS,IAAI,YAAY,IAAI,SAAS,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AACnB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { ChunkArtifact, FileCandidateInput, FilePlanEntry, IngestPlanInput, SemanticBlock } from "./contracts.js";
2
+ export declare function planIngestFiles(input: IngestPlanInput, files: FileCandidateInput[]): FilePlanEntry[];
3
+ export declare function buildChunkArtifacts(projectId: string, fileId: string, relativePath: string, blocks: SemanticBlock[]): ChunkArtifact[];
4
+ //# sourceMappingURL=ingest-pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingest-pipeline.d.ts","sourceRoot":"","sources":["../../../src/core/ingest/ingest-pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,aAAa,EACd,MAAM,gBAAgB,CAAC;AAoCxB,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,kBAAkB,EAAE,GAAG,aAAa,EAAE,CA8DpG;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,aAAa,EAAE,GACtB,aAAa,EAAE,CAkBjB"}
@@ -0,0 +1,105 @@
1
+ import { buildChunkId, buildFileId, buildSymbolId, checksumOf } from "./ids.js";
2
+ const DEFAULT_MAX_FILE_BYTES = 256 * 1024;
3
+ const IGNORED_DIRS = [
4
+ "node_modules",
5
+ ".venv",
6
+ "vendor",
7
+ "dist",
8
+ "build",
9
+ "coverage",
10
+ ".next",
11
+ ".git",
12
+ ];
13
+ const BINARY_EXT = [
14
+ "png", "jpg", "jpeg", "gif", "webp", "pdf", "zip", "gz", "tar", "mp4", "mov", "mp3", "wav", "ico", "lockb",
15
+ ];
16
+ function isIgnoredPath(relativePath) {
17
+ const normalized = relativePath.replace(/\\/g, "/");
18
+ return IGNORED_DIRS.some((dir) => normalized.split("/").includes(dir));
19
+ }
20
+ function hasBinaryExt(relativePath) {
21
+ const idx = relativePath.lastIndexOf(".");
22
+ if (idx < 0)
23
+ return false;
24
+ const ext = relativePath.slice(idx + 1).toLowerCase();
25
+ return BINARY_EXT.includes(ext);
26
+ }
27
+ function isIncludeOverride(relativePath, includeOverrides) {
28
+ return includeOverrides.some((prefix) => relativePath.startsWith(prefix));
29
+ }
30
+ export function planIngestFiles(input, files) {
31
+ const includeOverrides = input.include_overrides ?? [];
32
+ const maxFileBytes = input.max_file_bytes ?? DEFAULT_MAX_FILE_BYTES;
33
+ return files.map((file) => {
34
+ const bytes = file.bytes ?? Buffer.byteLength(file.content, "utf8");
35
+ const fileId = buildFileId(input.project_id, file.relative_path);
36
+ const checksum = checksumOf(file.content);
37
+ if (isIncludeOverride(file.relative_path, includeOverrides)) {
38
+ return {
39
+ relative_path: file.relative_path,
40
+ file_id: fileId,
41
+ include: true,
42
+ reason: "included",
43
+ checksum,
44
+ bytes,
45
+ };
46
+ }
47
+ if (isIgnoredPath(file.relative_path)) {
48
+ return {
49
+ relative_path: file.relative_path,
50
+ file_id: fileId,
51
+ include: false,
52
+ reason: "ignored_path",
53
+ checksum,
54
+ bytes,
55
+ };
56
+ }
57
+ if (hasBinaryExt(file.relative_path)) {
58
+ return {
59
+ relative_path: file.relative_path,
60
+ file_id: fileId,
61
+ include: false,
62
+ reason: "binary_ext",
63
+ checksum,
64
+ bytes,
65
+ };
66
+ }
67
+ if (bytes > maxFileBytes) {
68
+ return {
69
+ relative_path: file.relative_path,
70
+ file_id: fileId,
71
+ include: false,
72
+ reason: "oversized",
73
+ checksum,
74
+ bytes,
75
+ };
76
+ }
77
+ return {
78
+ relative_path: file.relative_path,
79
+ file_id: fileId,
80
+ include: true,
81
+ reason: "included",
82
+ checksum,
83
+ bytes,
84
+ };
85
+ });
86
+ }
87
+ export function buildChunkArtifacts(projectId, fileId, relativePath, blocks) {
88
+ return blocks.map((block, ordinal) => {
89
+ const symbolId = ["function", "class", "method"].includes(block.kind)
90
+ ? buildSymbolId(projectId, relativePath, block.semantic_path)
91
+ : null;
92
+ return {
93
+ chunk_id: buildChunkId(fileId, block.kind, block.semantic_path, ordinal),
94
+ file_id: fileId,
95
+ relative_path: relativePath,
96
+ chunk_kind: block.kind,
97
+ symbol_id: symbolId,
98
+ checksum: checksumOf(block.text),
99
+ semantic_path: block.semantic_path,
100
+ ordinal,
101
+ text: block.text,
102
+ };
103
+ });
104
+ }
105
+ //# sourceMappingURL=ingest-pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingest-pipeline.js","sourceRoot":"","sources":["../../../src/core/ingest/ingest-pipeline.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEhF,MAAM,sBAAsB,GAAG,GAAG,GAAG,IAAI,CAAC;AAE1C,MAAM,YAAY,GAAG;IACnB,cAAc;IACd,OAAO;IACP,QAAQ;IACR,MAAM;IACN,OAAO;IACP,UAAU;IACV,OAAO;IACP,MAAM;CACP,CAAC;AAEF,MAAM,UAAU,GAAG;IACjB,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO;CAC3G,CAAC;AAEF,SAAS,aAAa,CAAC,YAAoB;IACzC,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACpD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,YAAY,CAAC,YAAoB;IACxC,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1B,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACtD,OAAO,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,iBAAiB,CAAC,YAAoB,EAAE,gBAA0B;IACzE,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAsB,EAAE,KAA2B;IACjF,MAAM,gBAAgB,GAAG,KAAK,CAAC,iBAAiB,IAAI,EAAE,CAAC;IACvD,MAAM,YAAY,GAAG,KAAK,CAAC,cAAc,IAAI,sBAAsB,CAAC;IAEpE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACpE,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QACjE,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE1C,IAAI,iBAAiB,CAAC,IAAI,CAAC,aAAa,EAAE,gBAAgB,CAAC,EAAE,CAAC;YAC5D,OAAO;gBACL,aAAa,EAAE,IAAI,CAAC,aAAa;gBACjC,OAAO,EAAE,MAAM;gBACf,OAAO,EAAE,IAAI;gBACb,MAAM,EAAE,UAAmB;gBAC3B,QAAQ;gBACR,KAAK;aACN,CAAC;QACJ,CAAC;QAED,IAAI,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;YACtC,OAAO;gBACL,aAAa,EAAE,IAAI,CAAC,aAAa;gBACjC,OAAO,EAAE,MAAM;gBACf,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,cAAuB;gBAC/B,QAAQ;gBACR,KAAK;aACN,CAAC;QACJ,CAAC;QAED,IAAI,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;YACrC,OAAO;gBACL,aAAa,EAAE,IAAI,CAAC,aAAa;gBACjC,OAAO,EAAE,MAAM;gBACf,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,YAAqB;gBAC7B,QAAQ;gBACR,KAAK;aACN,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,GAAG,YAAY,EAAE,CAAC;YACzB,OAAO;gBACL,aAAa,EAAE,IAAI,CAAC,aAAa;gBACjC,OAAO,EAAE,MAAM;gBACf,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,WAAoB;gBAC5B,QAAQ;gBACR,KAAK;aACN,CAAC;QACJ,CAAC;QAED,OAAO;YACL,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,OAAO,EAAE,MAAM;YACf,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,UAAmB;YAC3B,QAAQ;YACR,KAAK;SACN,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,SAAiB,EACjB,MAAc,EACd,YAAoB,EACpB,MAAuB;IAEvB,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACnC,MAAM,QAAQ,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;YACnE,CAAC,CAAC,aAAa,CAAC,SAAS,EAAE,YAAY,EAAE,KAAK,CAAC,aAAa,CAAC;YAC7D,CAAC,CAAC,IAAI,CAAC;QAET,OAAO;YACL,QAAQ,EAAE,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,aAAa,EAAE,OAAO,CAAC;YACxE,OAAO,EAAE,MAAM;YACf,aAAa,EAAE,YAAY;YAC3B,UAAU,EAAE,KAAK,CAAC,IAAI;YACtB,SAAS,EAAE,QAAQ;YACnB,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;YAChC,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,OAAO;YACP,IAAI,EAAE,KAAK,CAAC,IAAI;SACjB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { SemanticBlock } from "./contracts.js";
2
+ interface ExtractInput {
3
+ relativePath: string;
4
+ content: string;
5
+ maxDocChunkChars?: number;
6
+ }
7
+ export declare function extractSemanticBlocks(input: ExtractInput): SemanticBlock[];
8
+ export {};
9
+ //# sourceMappingURL=semantic-block-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-block-extractor.d.ts","sourceRoot":"","sources":["../../../src/core/ingest/semantic-block-extractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,UAAU,YAAY;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AA8ID,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,YAAY,GAAG,aAAa,EAAE,CAS1E"}
@@ -0,0 +1,135 @@
1
+ const DEFAULT_MAX_DOC_CHUNK = 1400;
2
+ function ext(path) {
3
+ const idx = path.lastIndexOf(".");
4
+ return idx >= 0 ? path.slice(idx + 1).toLowerCase() : "";
5
+ }
6
+ function isCodeLike(path) {
7
+ return ["ts", "tsx", "js", "jsx", "mjs", "cjs", "py", "go", "java", "rs"].includes(ext(path));
8
+ }
9
+ function lineOf(content, offset) {
10
+ return content.slice(0, offset).split("\n").length;
11
+ }
12
+ function findBalancedBlock(content, startOffset) {
13
+ const firstBrace = content.indexOf("{", startOffset);
14
+ if (firstBrace < 0) {
15
+ const lineEnd = content.indexOf("\n", startOffset);
16
+ const endOffset = lineEnd >= 0 ? lineEnd : content.length;
17
+ return { text: content.slice(startOffset, endOffset), endOffset };
18
+ }
19
+ let depth = 0;
20
+ for (let i = firstBrace; i < content.length; i++) {
21
+ const ch = content[i];
22
+ if (ch === "{")
23
+ depth += 1;
24
+ else if (ch === "}") {
25
+ depth -= 1;
26
+ if (depth === 0) {
27
+ return { text: content.slice(startOffset, i + 1), endOffset: i + 1 };
28
+ }
29
+ }
30
+ }
31
+ return { text: content.slice(startOffset), endOffset: content.length };
32
+ }
33
+ function extractCodeBlocks(relativePath, content) {
34
+ const blocks = [];
35
+ const classRegex = /^\s*(?:export\s+)?class\s+([A-Za-z_][\w$]*)/gm;
36
+ const functionRegex = /^\s*(?:export\s+)?(?:async\s+)?function\s+([A-Za-z_][\w$]*)\s*\(/gm;
37
+ const methodRegex = /^\s{2,}(?:public\s+|private\s+|protected\s+|static\s+|async\s+)*(?!if\b|for\b|while\b|switch\b|catch\b|return\b|throw\b|else\b)([A-Za-z_][\w$]*)\s*\([^\)]*\)\s*\{/gm;
38
+ const disallowedMethodNames = new Set(["if", "for", "while", "switch", "catch", "return", "throw", "else"]);
39
+ let match;
40
+ while ((match = classRegex.exec(content))) {
41
+ const symbolName = match[1];
42
+ const start = match.index;
43
+ const block = findBalancedBlock(content, start);
44
+ blocks.push({
45
+ kind: "class",
46
+ symbol_name: symbolName,
47
+ semantic_path: `class:${symbolName}`,
48
+ start_line: lineOf(content, start),
49
+ end_line: lineOf(content, block.endOffset),
50
+ ordinal: blocks.length,
51
+ text: block.text,
52
+ });
53
+ }
54
+ while ((match = functionRegex.exec(content))) {
55
+ const symbolName = match[1];
56
+ const start = match.index;
57
+ const block = findBalancedBlock(content, start);
58
+ blocks.push({
59
+ kind: "function",
60
+ symbol_name: symbolName,
61
+ semantic_path: `function:${symbolName}`,
62
+ start_line: lineOf(content, start),
63
+ end_line: lineOf(content, block.endOffset),
64
+ ordinal: blocks.length,
65
+ text: block.text,
66
+ });
67
+ }
68
+ while ((match = methodRegex.exec(content))) {
69
+ const symbolName = match[1];
70
+ if (disallowedMethodNames.has(symbolName))
71
+ continue;
72
+ const start = match.index;
73
+ const block = findBalancedBlock(content, start);
74
+ blocks.push({
75
+ kind: "method",
76
+ symbol_name: symbolName,
77
+ semantic_path: `method:${symbolName}`,
78
+ start_line: lineOf(content, start),
79
+ end_line: lineOf(content, block.endOffset),
80
+ ordinal: blocks.length,
81
+ text: block.text,
82
+ });
83
+ }
84
+ return blocks
85
+ .filter((b, idx, arr) => arr.findIndex((x) => x.semantic_path === b.semantic_path && x.start_line === b.start_line) === idx)
86
+ .sort((a, b) => a.start_line - b.start_line)
87
+ .map((b, i) => ({ ...b, ordinal: i }));
88
+ }
89
+ function extractDocBlocks(content, maxDocChunkChars) {
90
+ const blocks = [];
91
+ const sections = content
92
+ .split(/\n(?=#{1,3}\s+)/g)
93
+ .map((s) => s.trim())
94
+ .filter(Boolean);
95
+ const sourceSections = sections.length > 0 ? sections : [content];
96
+ for (const section of sourceSections) {
97
+ if (section.length <= maxDocChunkChars) {
98
+ blocks.push({
99
+ kind: section.startsWith("#") ? "doc_section" : "doc_paragraph",
100
+ symbol_name: "doc",
101
+ semantic_path: section.startsWith("#") ? "doc:section" : "doc:paragraph",
102
+ start_line: 1,
103
+ end_line: section.split("\n").length,
104
+ ordinal: blocks.length,
105
+ text: section,
106
+ });
107
+ continue;
108
+ }
109
+ let cursor = 0;
110
+ while (cursor < section.length) {
111
+ const slice = section.slice(cursor, cursor + maxDocChunkChars);
112
+ blocks.push({
113
+ kind: "doc_paragraph",
114
+ symbol_name: "doc",
115
+ semantic_path: "doc:paragraph",
116
+ start_line: 1,
117
+ end_line: slice.split("\n").length,
118
+ ordinal: blocks.length,
119
+ text: slice,
120
+ });
121
+ cursor += maxDocChunkChars;
122
+ }
123
+ }
124
+ return blocks.map((b, i) => ({ ...b, ordinal: i }));
125
+ }
126
+ export function extractSemanticBlocks(input) {
127
+ const maxDocChunkChars = Math.max(300, input.maxDocChunkChars ?? DEFAULT_MAX_DOC_CHUNK);
128
+ if (isCodeLike(input.relativePath)) {
129
+ const codeBlocks = extractCodeBlocks(input.relativePath, input.content);
130
+ if (codeBlocks.length > 0)
131
+ return codeBlocks;
132
+ }
133
+ return extractDocBlocks(input.content, maxDocChunkChars);
134
+ }
135
+ //# sourceMappingURL=semantic-block-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-block-extractor.js","sourceRoot":"","sources":["../../../src/core/ingest/semantic-block-extractor.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,7 @@ export declare class DefaultMemoryUseCasePort implements MemoryUseCasePort {
20
20
  private handleProjectTriggerIndex;
21
21
  private scheduleProjectReindexJob;
22
22
  private resolveProjectRef;
23
+ private installProjectGitHooks;
23
24
  private validateJiraTrackerFields;
24
25
  private tryResolveRepoRootFromCwd;
25
26
  private resolveWorkspaceRoot;
@@ -37,6 +38,8 @@ export declare class DefaultMemoryUseCasePort implements MemoryUseCasePort {
37
38
  private tryReadGitRemote;
38
39
  private collectGitTrackedPaths;
39
40
  private handleProjectReindexDiff;
41
+ private handleProjectIndexEvent;
42
+ private handleProjectInstallHooks;
40
43
  private handleProjectIndexWatchGet;
41
44
  private handleProjectTaskRegistryUpsert;
42
45
  private handleProjectTaskLineageContext;
@@ -1 +1 @@
1
- {"version":3,"file":"default-memory-usecase-port.d.ts","sourceRoot":"","sources":["../../../src/core/usecases/default-memory-usecase-port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,mCAAmC,CAAC;AAK3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AA4T1E,qBAAa,wBAAyB,YAAW,iBAAiB;IAE9D,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;gBADhB,MAAM,EAAE,MAAM,EACd,eAAe,CAAC,EAAE,qBAAqB,YAAA;IAGpD,GAAG,CAAC,IAAI,EAAE,IAAI,EAClB,OAAO,EAAE,iBAAiB,EAC1B,GAAG,EAAE,mBAAmB,CAAC,IAAI,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC;IA6DhB,OAAO,CAAC,aAAa;IAqDrB,OAAO,CAAC,aAAa;IAsBrB,OAAO,CAAC,cAAc;IA6BtB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,qBAAqB;IAkB7B,OAAO,CAAC,gBAAgB;IA0BxB,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,iCAAiC;IAkBzC,OAAO,CAAC,8BAA8B;IAuBtC,OAAO,CAAC,4BAA4B;IA8GpC,OAAO,CAAC,wBAAwB;IAyChC,OAAO,CAAC,yBAAyB;IAoCjC,OAAO,CAAC,yBAAyB;IAwCjC,OAAO,CAAC,iBAAiB;IAoBzB,OAAO,CAAC,yBAAyB;IAmBjC,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,oBAAoB;IA8B5B,OAAO,CAAC,0BAA0B;IAgGlC,OAAO,CAAC,sBAAsB;IAa9B,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,6BAA6B;IAuBrC,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,yBAAyB;IAmBjC,OAAO,CAAC,gBAAgB;IAmDxB,OAAO,CAAC,0BAA0B;IAkBlC,OAAO,CAAC,uBAAuB;IAgB/B,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,sBAAsB;IAgE9B,OAAO,CAAC,wBAAwB;IAgBhC,OAAO,CAAC,0BAA0B;IAUlC,OAAO,CAAC,+BAA+B;IAwBvC,OAAO,CAAC,+BAA+B;IAqBvC,OAAO,CAAC,yBAAyB;IAoBjC,OAAO,CAAC,2BAA2B;IAYnC,OAAO,CAAC,+BAA+B;IAmIvC,OAAO,CAAC,oBAAoB;IAa5B,OAAO,CAAC,oBAAoB;IA0B5B,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,oBAAoB;YAuBd,mBAAmB;YAOnB,kBAAkB;IAOhC,OAAO,CAAC,iBAAiB;CAmB1B"}
1
+ {"version":3,"file":"default-memory-usecase-port.d.ts","sourceRoot":"","sources":["../../../src/core/usecases/default-memory-usecase-port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,mCAAmC,CAAC;AAO3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AA4U1E,qBAAa,wBAAyB,YAAW,iBAAiB;IAE9D,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;gBADhB,MAAM,EAAE,MAAM,EACd,eAAe,CAAC,EAAE,qBAAqB,YAAA;IAGpD,GAAG,CAAC,IAAI,EAAE,IAAI,EAClB,OAAO,EAAE,iBAAiB,EAC1B,GAAG,EAAE,mBAAmB,CAAC,IAAI,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC;IAiEhB,OAAO,CAAC,aAAa;IAqDrB,OAAO,CAAC,aAAa;IAsBrB,OAAO,CAAC,cAAc;IA6BtB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,qBAAqB;IAkB7B,OAAO,CAAC,gBAAgB;IA0BxB,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,iCAAiC;IAkBzC,OAAO,CAAC,8BAA8B;IAuBtC,OAAO,CAAC,4BAA4B;IAiHpC,OAAO,CAAC,wBAAwB;IAyChC,OAAO,CAAC,yBAAyB;IAoCjC,OAAO,CAAC,yBAAyB;IA0CjC,OAAO,CAAC,iBAAiB;IAoBzB,OAAO,CAAC,sBAAsB;IA0B9B,OAAO,CAAC,yBAAyB;IAmBjC,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,oBAAoB;IA8B5B,OAAO,CAAC,0BAA0B;IAgGlC,OAAO,CAAC,sBAAsB;IAa9B,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,6BAA6B;IAuBrC,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,yBAAyB;IAmBjC,OAAO,CAAC,gBAAgB;IAmDxB,OAAO,CAAC,0BAA0B;IAkBlC,OAAO,CAAC,uBAAuB;IAgB/B,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,sBAAsB;IA+E9B,OAAO,CAAC,wBAAwB;IAiBhC,OAAO,CAAC,uBAAuB;IAyD/B,OAAO,CAAC,yBAAyB;IAYjC,OAAO,CAAC,0BAA0B;IAUlC,OAAO,CAAC,+BAA+B;IAwBvC,OAAO,CAAC,+BAA+B;IAqBvC,OAAO,CAAC,yBAAyB;IAoBjC,OAAO,CAAC,2BAA2B;IAYnC,OAAO,CAAC,+BAA+B;IAmIvC,OAAO,CAAC,oBAAoB;IAa5B,OAAO,CAAC,oBAAoB;IA0B5B,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,oBAAoB;YAuBd,mBAAmB;YAOnB,kBAAkB;IAOhC,OAAO,CAAC,iBAAiB;CAmB1B"}
@@ -1,6 +1,6 @@
1
1
  import { execSync } from "node:child_process";
2
2
  import { createHash } from "node:crypto";
3
- import { existsSync, mkdirSync, readdirSync, statSync } from "node:fs";
3
+ import { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
4
4
  import { basename, dirname, isAbsolute, resolve } from "node:path";
5
5
  function asRecord(value) {
6
6
  return value && typeof value === "object" && !Array.isArray(value)
@@ -75,6 +75,10 @@ export class DefaultMemoryUseCasePort {
75
75
  return this.handleProjectTriggerIndex(payload, req);
76
76
  case "project.reindex_diff":
77
77
  return this.handleProjectReindexDiff(payload, req);
78
+ case "project.index_event":
79
+ return this.handleProjectIndexEvent(payload, req);
80
+ case "project.install_hooks":
81
+ return this.handleProjectInstallHooks(payload, req);
78
82
  case "project.index_watch_get":
79
83
  return this.handleProjectIndexWatchGet(payload, req);
80
84
  case "project.task_registry_upsert":
@@ -349,6 +353,7 @@ export class DefaultMemoryUseCasePort {
349
353
  note: triggerResult?.note || null,
350
354
  };
351
355
  }
356
+ const autoIndexHook = this.installProjectGitHooks(registered.project.project_id, registered.project.repo_root);
352
357
  return {
353
358
  project_id: registered.project.project_id,
354
359
  project_alias: registered.alias.project_alias,
@@ -356,6 +361,7 @@ export class DefaultMemoryUseCasePort {
356
361
  validation_status: registered.registration.validation_status,
357
362
  completeness_score: Number((registered.registration.completeness_score / 100).toFixed(2)),
358
363
  warnings: [],
364
+ auto_index_hook: autoIndexHook,
359
365
  repo_resolution: {
360
366
  resolution: selection.resolution,
361
367
  clone_policy: selection.clone_policy || "not_applicable",
@@ -460,6 +466,7 @@ export class DefaultMemoryUseCasePort {
460
466
  source_rev: input.sourceRev,
461
467
  trigger_type: input.triggerType,
462
468
  index_profile: input.indexProfile,
469
+ full_snapshot: input.triggerType === "bootstrap",
463
470
  paths,
464
471
  });
465
472
  }
@@ -483,6 +490,31 @@ export class DefaultMemoryUseCasePort {
483
490
  }
484
491
  throw new Error("project reference requires project_id or project_alias");
485
492
  }
493
+ installProjectGitHooks(projectId, repoRoot) {
494
+ if (!repoRoot)
495
+ return { installed: false, hooks: [], note: 'repo_root_missing' };
496
+ const gitDir = resolve(repoRoot, '.git');
497
+ const hooksDir = resolve(gitDir, 'hooks');
498
+ if (!existsSync(gitDir))
499
+ return { installed: false, hooks: [], note: 'git_dir_missing' };
500
+ mkdirSync(hooksDir, { recursive: true });
501
+ const writeHook = (name, eventType) => {
502
+ const hookPath = resolve(hooksDir, name);
503
+ const script = `#!/bin/sh
504
+ PROJECT_ID="${projectId}"
505
+ REPO_ROOT="${repoRoot}"
506
+ SOURCE_REV="$(git rev-parse HEAD 2>/dev/null || echo unknown)"
507
+ CHANGED_FILES="$(git diff-tree --no-commit-id --name-only -r HEAD 2>/dev/null | paste -sd, -)"
508
+ DELETED_FILES="$(git diff-tree --no-commit-id --name-only --diff-filter=D -r HEAD 2>/dev/null | paste -sd, -)"
509
+ asm project-event --project-id "$PROJECT_ID" --repo-root "$REPO_ROOT" --event-type ${eventType} --source-rev "$SOURCE_REV" --changed-files "$CHANGED_FILES" --deleted-files "$DELETED_FILES" >/dev/null 2>&1 || true
510
+ `;
511
+ writeFileSync(hookPath, script, 'utf8');
512
+ chmodSync(hookPath, 0o755);
513
+ return hookPath;
514
+ };
515
+ const hooks = [writeHook('post-commit', 'post_commit'), writeHook('post-merge', 'post_merge')];
516
+ return { installed: true, hooks };
517
+ }
486
518
  validateJiraTrackerFields(trackerSpaceKey, defaultEpicKey) {
487
519
  const space = String(trackerSpaceKey || "").trim();
488
520
  if (!space) {
@@ -800,18 +832,24 @@ export class DefaultMemoryUseCasePort {
800
832
  .split("\n")
801
833
  .map((line) => line.trim())
802
834
  .filter(Boolean);
803
- const supplemental = ["distill-cron.sh", "re-embed-all.sh", "snapshots/last-distill.json"]
804
- .filter((rel) => existsSync(resolve(repoRoot, rel)));
805
- const merged = Array.from(new Set([...paths, ...supplemental]));
806
- return merged
835
+ return paths
807
836
  .filter((p) => !p.startsWith(".git/"))
808
837
  .map((relativePath) => {
809
838
  const ext = relativePath.includes(".") ? relativePath.split(".").pop() || "" : "";
839
+ const abs = resolve(repoRoot, relativePath);
840
+ let content;
841
+ try {
842
+ content = readFileSync(abs, "utf8");
843
+ }
844
+ catch {
845
+ content = undefined;
846
+ }
810
847
  return {
811
848
  relative_path: relativePath,
812
- checksum: `${paths.includes(relativePath) ? "git" : "fs"}:${relativePath}`,
849
+ checksum: `git:${relativePath}`,
813
850
  module: relativePath.split("/")[0] || undefined,
814
851
  language: ext || undefined,
852
+ content,
815
853
  };
816
854
  });
817
855
  }
@@ -838,12 +876,23 @@ export class DefaultMemoryUseCasePort {
838
876
  catch {
839
877
  return [];
840
878
  }
841
- return files.map((relativePath) => ({
842
- relative_path: relativePath,
843
- checksum: `fs:${relativePath}`,
844
- module: relativePath.split("/")[0] || undefined,
845
- language: relativePath.includes(".") ? relativePath.split(".").pop() || undefined : undefined,
846
- }));
879
+ return files.map((relativePath) => {
880
+ const abs = resolve(repoRoot, relativePath);
881
+ let content;
882
+ try {
883
+ content = readFileSync(abs, "utf8");
884
+ }
885
+ catch {
886
+ content = undefined;
887
+ }
888
+ return {
889
+ relative_path: relativePath,
890
+ checksum: `fs:${relativePath}`,
891
+ module: relativePath.split("/")[0] || undefined,
892
+ language: relativePath.includes(".") ? relativePath.split(".").pop() || undefined : undefined,
893
+ content,
894
+ };
895
+ });
847
896
  }
848
897
  }
849
898
  handleProjectReindexDiff(payload, req) {
@@ -856,9 +905,72 @@ export class DefaultMemoryUseCasePort {
856
905
  source_rev: payload.source_rev,
857
906
  trigger_type: payload.trigger_type,
858
907
  index_profile: payload.index_profile,
908
+ full_snapshot: payload.full_snapshot === true,
859
909
  paths: payload.paths || [],
860
910
  });
861
911
  }
912
+ handleProjectIndexEvent(payload, req) {
913
+ const identity = normalizePrivateIdentity(req.context);
914
+ if (!payload.project_id) {
915
+ throw new Error("project.index_event requires payload.project_id");
916
+ }
917
+ const project = this.slotDb.getProjectById(identity.userId, identity.agentId, payload.project_id);
918
+ if (!project || !project.repo_root) {
919
+ throw new Error("project.index_event requires a registered project with repo_root");
920
+ }
921
+ const changedFiles = Array.from(new Set((payload.changed_files || []).map((x) => String(x || "").trim()).filter(Boolean)));
922
+ const deletedFiles = Array.from(new Set((payload.deleted_files || []).map((x) => String(x || "").trim()).filter(Boolean)));
923
+ const paths = changedFiles.map((relativePath) => {
924
+ const abs = resolve(project.repo_root, relativePath);
925
+ let content = null;
926
+ try {
927
+ content = readFileSync(abs, "utf8");
928
+ }
929
+ catch {
930
+ content = null;
931
+ }
932
+ return {
933
+ relative_path: relativePath,
934
+ checksum: `event:${relativePath}:${payload.source_rev || "unknown"}`,
935
+ module: relativePath.split("/")[0] || undefined,
936
+ language: relativePath.includes(".") ? relativePath.split(".").pop() || undefined : undefined,
937
+ content,
938
+ };
939
+ });
940
+ const reindex = this.slotDb.reindexProjectByDiff(identity.userId, identity.agentId, {
941
+ project_id: payload.project_id,
942
+ source_rev: payload.source_rev || null,
943
+ trigger_type: "incremental",
944
+ index_profile: "default",
945
+ full_snapshot: false,
946
+ paths,
947
+ });
948
+ if (deletedFiles.length > 0) {
949
+ const tombstoneAt = new Date().toISOString();
950
+ for (const relativePath of deletedFiles) {
951
+ this.slotDb.markProjectFileDeletedForEvent(identity.userId, identity.agentId, payload.project_id, relativePath, tombstoneAt);
952
+ }
953
+ }
954
+ return {
955
+ project_id: payload.project_id,
956
+ event_type: payload.event_type || "manual",
957
+ source_rev: payload.source_rev || null,
958
+ changed_files: changedFiles,
959
+ deleted_files: deletedFiles,
960
+ reindex,
961
+ };
962
+ }
963
+ handleProjectInstallHooks(payload, req) {
964
+ const identity = normalizePrivateIdentity(req.context);
965
+ if (!payload.project_id) {
966
+ throw new Error("project.install_hooks requires payload.project_id");
967
+ }
968
+ const project = this.slotDb.getProjectById(identity.userId, identity.agentId, payload.project_id);
969
+ if (!project) {
970
+ throw new Error("project.install_hooks requires a registered project");
971
+ }
972
+ return this.installProjectGitHooks(project.project_id, project.repo_root);
973
+ }
862
974
  handleProjectIndexWatchGet(payload, req) {
863
975
  const identity = normalizePrivateIdentity(req.context);
864
976
  if (!payload.project_id) {