@phyzess/pappra 0.0.0-stage → 0.1.0-beta.2

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 (221) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +80 -2
  3. package/THIRD_PARTY_NOTICES.md +16 -0
  4. package/assets/integrations/skills/pappra/SKILL.md +68 -0
  5. package/assets/integrations/skills/pappra/references/hosts.md +30 -0
  6. package/assets/integrations/skills/pappra/references/lifecycle.md +37 -0
  7. package/assets/integrations/skills/pappra/references/operations.md +14 -0
  8. package/assets/manifest.json +4 -0
  9. package/dist/app/collaboration.d.ts +170 -0
  10. package/dist/app/collaboration.js +1650 -0
  11. package/dist/app/doctor.d.ts +9 -0
  12. package/dist/app/doctor.js +1030 -0
  13. package/dist/app/init.d.ts +143 -0
  14. package/dist/app/init.js +1111 -0
  15. package/dist/cli/commands/code.d.ts +16 -0
  16. package/dist/cli/commands/code.js +127 -0
  17. package/dist/cli/commands/collaboration.d.ts +13 -0
  18. package/dist/cli/commands/collaboration.js +186 -0
  19. package/dist/cli/commands/continuity.d.ts +29 -0
  20. package/dist/cli/commands/continuity.js +133 -0
  21. package/dist/cli/commands/docs.d.ts +11 -0
  22. package/dist/cli/commands/docs.js +133 -0
  23. package/dist/cli/commands/doctor.d.ts +14 -0
  24. package/dist/cli/commands/doctor.js +57 -0
  25. package/dist/cli/commands/host.d.ts +13 -0
  26. package/dist/cli/commands/host.js +125 -0
  27. package/dist/cli/commands/init.d.ts +51 -0
  28. package/dist/cli/commands/init.js +668 -0
  29. package/dist/cli/main.d.ts +2 -0
  30. package/dist/cli/main.js +10 -0
  31. package/dist/cli/output.d.ts +4 -0
  32. package/dist/cli/output.js +1 -0
  33. package/dist/cli/run.d.ts +2 -0
  34. package/dist/cli/run.js +597 -0
  35. package/dist/code/budget.d.ts +14 -0
  36. package/dist/code/budget.js +39 -0
  37. package/dist/code/exec.d.ts +23 -0
  38. package/dist/code/exec.js +133 -0
  39. package/dist/code/identity.d.ts +13 -0
  40. package/dist/code/identity.js +214 -0
  41. package/dist/code/index.d.ts +6 -0
  42. package/dist/code/index.js +3 -0
  43. package/dist/code/providers/codegraph.d.ts +59 -0
  44. package/dist/code/providers/codegraph.js +567 -0
  45. package/dist/code/registration.d.ts +9 -0
  46. package/dist/code/registration.js +293 -0
  47. package/dist/code/service.d.ts +53 -0
  48. package/dist/code/service.js +633 -0
  49. package/dist/code/text.d.ts +3 -0
  50. package/dist/code/text.js +202 -0
  51. package/dist/collab/admission.d.ts +450 -0
  52. package/dist/collab/admission.js +797 -0
  53. package/dist/collab/canonical.d.ts +26 -0
  54. package/dist/collab/canonical.js +136 -0
  55. package/dist/collab/contracts.d.ts +73 -0
  56. package/dist/collab/contracts.js +76 -0
  57. package/dist/collab/envelope.d.ts +52 -0
  58. package/dist/collab/envelope.js +241 -0
  59. package/dist/collab/fingerprint.d.ts +7 -0
  60. package/dist/collab/fingerprint.js +58 -0
  61. package/dist/collab/handoff.d.ts +350 -0
  62. package/dist/collab/handoff.js +513 -0
  63. package/dist/collab/index.d.ts +9 -0
  64. package/dist/collab/index.js +8 -0
  65. package/dist/collab/lifecycle.d.ts +449 -0
  66. package/dist/collab/lifecycle.js +534 -0
  67. package/dist/collab/messages.d.ts +148 -0
  68. package/dist/collab/messages.js +583 -0
  69. package/dist/collab/notify.d.ts +47 -0
  70. package/dist/collab/notify.js +140 -0
  71. package/dist/collab/preflight.d.ts +31 -0
  72. package/dist/collab/preflight.js +271 -0
  73. package/dist/collab/resources.d.ts +119 -0
  74. package/dist/collab/resources.js +451 -0
  75. package/dist/collab/store.d.ts +143 -0
  76. package/dist/collab/store.js +606 -0
  77. package/dist/collab/types.d.ts +354 -0
  78. package/dist/collab/types.js +1 -0
  79. package/dist/collab/validation.d.ts +10 -0
  80. package/dist/collab/validation.js +303 -0
  81. package/dist/continuity/context.d.ts +24 -0
  82. package/dist/continuity/context.js +179 -0
  83. package/dist/continuity/index.d.ts +3 -0
  84. package/dist/continuity/index.js +1 -0
  85. package/dist/continuity/paths.d.ts +37 -0
  86. package/dist/continuity/paths.js +258 -0
  87. package/dist/continuity/service.d.ts +59 -0
  88. package/dist/continuity/service.js +1258 -0
  89. package/dist/hosts/claude/native.d.ts +79 -0
  90. package/dist/hosts/claude/native.js +853 -0
  91. package/dist/hosts/codex/native.d.ts +345 -0
  92. package/dist/hosts/codex/native.js +1528 -0
  93. package/dist/hosts/codex/protocol.d.ts +51 -0
  94. package/dist/hosts/codex/protocol.js +42 -0
  95. package/dist/hosts/detect.d.ts +28 -0
  96. package/dist/hosts/detect.js +73 -0
  97. package/dist/hosts/index.d.ts +10 -0
  98. package/dist/hosts/index.js +10 -0
  99. package/dist/hosts/integration/bundle.d.ts +16 -0
  100. package/dist/hosts/integration/bundle.js +81 -0
  101. package/dist/hosts/integration/hook-entry.d.ts +1 -0
  102. package/dist/hosts/integration/hook-entry.js +68 -0
  103. package/dist/hosts/integration/hook.d.ts +32 -0
  104. package/dist/hosts/integration/hook.js +781 -0
  105. package/dist/hosts/integration/pi-extension-runtime.d.ts +18 -0
  106. package/dist/hosts/integration/pi-extension-runtime.js +89 -0
  107. package/dist/hosts/integration/pi-template.d.ts +3 -0
  108. package/dist/hosts/integration/pi-template.js +5 -0
  109. package/dist/hosts/integration/service.d.ts +41 -0
  110. package/dist/hosts/integration/service.js +1381 -0
  111. package/dist/hosts/integration/support.d.ts +36 -0
  112. package/dist/hosts/integration/support.js +41 -0
  113. package/dist/hosts/integration/templates.d.ts +22 -0
  114. package/dist/hosts/integration/templates.js +70 -0
  115. package/dist/hosts/pi/protocol.d.ts +22 -0
  116. package/dist/hosts/pi/protocol.js +28 -0
  117. package/dist/hosts/pi/query-result.d.ts +22 -0
  118. package/dist/hosts/pi/query-result.js +710 -0
  119. package/dist/hosts/pi/rpc.d.ts +937 -0
  120. package/dist/hosts/pi/rpc.js +1621 -0
  121. package/dist/hosts/pilot.d.ts +485 -0
  122. package/dist/hosts/pilot.js +593 -0
  123. package/dist/index.d.ts +5 -0
  124. package/dist/index.js +4 -0
  125. package/dist/infra/fs.d.ts +27 -0
  126. package/dist/infra/fs.js +130 -0
  127. package/dist/infra/git.d.ts +60 -0
  128. package/dist/infra/git.js +358 -0
  129. package/dist/infra/owned-process-group.d.ts +173 -0
  130. package/dist/infra/owned-process-group.js +571 -0
  131. package/dist/install/apply.d.ts +65 -0
  132. package/dist/install/apply.js +663 -0
  133. package/dist/install/index.d.ts +5 -0
  134. package/dist/install/index.js +5 -0
  135. package/dist/install/ownership.d.ts +85 -0
  136. package/dist/install/ownership.js +430 -0
  137. package/dist/install/plan.d.ts +39 -0
  138. package/dist/install/plan.js +97 -0
  139. package/dist/install/rollback.d.ts +18 -0
  140. package/dist/install/rollback.js +544 -0
  141. package/dist/install/runtime.d.ts +76 -0
  142. package/dist/install/runtime.js +1145 -0
  143. package/dist/knowledge/catalog.d.ts +47 -0
  144. package/dist/knowledge/catalog.js +308 -0
  145. package/dist/knowledge/context.d.ts +28 -0
  146. package/dist/knowledge/context.js +61 -0
  147. package/dist/knowledge/index.d.ts +3 -0
  148. package/dist/knowledge/index.js +1 -0
  149. package/dist/knowledge/journal.d.ts +16 -0
  150. package/dist/knowledge/journal.js +109 -0
  151. package/dist/knowledge/lifecycle.d.ts +8 -0
  152. package/dist/knowledge/lifecycle.js +1001 -0
  153. package/dist/knowledge/paths.d.ts +37 -0
  154. package/dist/knowledge/paths.js +236 -0
  155. package/dist/knowledge/refs.d.ts +36 -0
  156. package/dist/knowledge/refs.js +267 -0
  157. package/dist/knowledge/service.d.ts +21 -0
  158. package/dist/knowledge/service.js +393 -0
  159. package/dist/knowledge/types.d.ts +171 -0
  160. package/dist/knowledge/types.js +1 -0
  161. package/dist/knowledge/write.d.ts +8 -0
  162. package/dist/knowledge/write.js +1223 -0
  163. package/dist/package-info.d.ts +6 -0
  164. package/dist/package-info.js +19 -0
  165. package/dist/schemas/code.d.ts +377 -0
  166. package/dist/schemas/code.js +145 -0
  167. package/dist/schemas/collaboration.d.ts +115 -0
  168. package/dist/schemas/collaboration.js +106 -0
  169. package/dist/schemas/continuity.d.ts +315 -0
  170. package/dist/schemas/continuity.js +199 -0
  171. package/dist/schemas/diagnostics.d.ts +28 -0
  172. package/dist/schemas/diagnostics.js +27 -0
  173. package/dist/schemas/doctor.d.ts +157 -0
  174. package/dist/schemas/doctor.js +75 -0
  175. package/dist/schemas/document.d.ts +644 -0
  176. package/dist/schemas/document.js +296 -0
  177. package/dist/schemas/errors.d.ts +177 -0
  178. package/dist/schemas/errors.js +176 -0
  179. package/dist/schemas/evidence.d.ts +24 -0
  180. package/dist/schemas/evidence.js +16 -0
  181. package/dist/schemas/host.d.ts +436 -0
  182. package/dist/schemas/host.js +201 -0
  183. package/dist/schemas/index.d.ts +15 -0
  184. package/dist/schemas/index.js +15 -0
  185. package/dist/schemas/init.d.ts +121 -0
  186. package/dist/schemas/init.js +94 -0
  187. package/dist/schemas/install.d.ts +213 -0
  188. package/dist/schemas/install.js +139 -0
  189. package/dist/schemas/machine.d.ts +43 -0
  190. package/dist/schemas/machine.js +96 -0
  191. package/dist/schemas/outcome.d.ts +23 -0
  192. package/dist/schemas/outcome.js +17 -0
  193. package/dist/schemas/paths.d.ts +19 -0
  194. package/dist/schemas/paths.js +63 -0
  195. package/dist/schemas/workspace.d.ts +120 -0
  196. package/dist/schemas/workspace.js +201 -0
  197. package/dist/workspace/config-file.d.ts +36 -0
  198. package/dist/workspace/config-file.js +237 -0
  199. package/dist/workspace/config.d.ts +28 -0
  200. package/dist/workspace/config.js +79 -0
  201. package/dist/workspace/discover.d.ts +34 -0
  202. package/dist/workspace/discover.js +195 -0
  203. package/dist/workspace/documents.d.ts +21 -0
  204. package/dist/workspace/documents.js +395 -0
  205. package/dist/workspace/ignore.d.ts +10 -0
  206. package/dist/workspace/ignore.js +48 -0
  207. package/dist/workspace/index.d.ts +7 -0
  208. package/dist/workspace/index.js +3 -0
  209. package/dist/workspace/repositories.d.ts +24 -0
  210. package/dist/workspace/repositories.js +411 -0
  211. package/dist/workspace/resolve.d.ts +24 -0
  212. package/dist/workspace/resolve.js +268 -0
  213. package/dist/workspace/types.d.ts +71 -0
  214. package/dist/workspace/types.js +1 -0
  215. package/dist/workspace/validation.d.ts +18 -0
  216. package/dist/workspace/validation.js +197 -0
  217. package/package.json +105 -4
  218. package/skills/pappra/SKILL.md +68 -0
  219. package/skills/pappra/references/hosts.md +30 -0
  220. package/skills/pappra/references/lifecycle.md +37 -0
  221. package/skills/pappra/references/operations.md +14 -0
@@ -0,0 +1,133 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { failed, succeeded } from '../schemas/outcome.js';
3
+ import { diagnosticCodes } from '../schemas/errors.js';
4
+ function errorText(error) {
5
+ return error instanceof Error ? error.message : String(error);
6
+ }
7
+ function killGroup(pid) {
8
+ if (pid === undefined)
9
+ return;
10
+ try {
11
+ process.kill(-pid, 'SIGKILL');
12
+ }
13
+ catch {
14
+ try {
15
+ process.kill(pid, 'SIGKILL');
16
+ }
17
+ catch {
18
+ // The process already exited.
19
+ }
20
+ }
21
+ }
22
+ /**
23
+ * Executes one argv-delimited local command without a shell. Output and time
24
+ * are bounded; a failure never becomes an empty successful result.
25
+ */
26
+ export function runCommand(options) {
27
+ if (options.signal?.aborted === true) {
28
+ return Promise.resolve(failed(diagnosticCodes.code_engine_failed, 'Command was cancelled.', {
29
+ nextAction: 'Retry when cancellation is no longer requested.',
30
+ }));
31
+ }
32
+ const startedAt = performance.now();
33
+ const timeoutMs = options.timeoutMs ?? 10_000;
34
+ const maxOutputBytes = options.maxOutputBytes ?? 2 * 1024 * 1024;
35
+ return new Promise((resolveResult) => {
36
+ let settled = false;
37
+ let timedOut = false;
38
+ let aborted = false;
39
+ let outputExceeded = false;
40
+ let bytes = 0;
41
+ const stdout = [];
42
+ const stderr = [];
43
+ let timer = null;
44
+ let child;
45
+ const settle = (result) => {
46
+ if (settled)
47
+ return;
48
+ settled = true;
49
+ if (timer !== null)
50
+ clearTimeout(timer);
51
+ options.signal?.removeEventListener('abort', abort);
52
+ resolveResult(result);
53
+ };
54
+ const abort = () => {
55
+ aborted = true;
56
+ killGroup(child?.pid);
57
+ };
58
+ try {
59
+ child = spawn(options.command, [...options.args], {
60
+ cwd: options.cwd,
61
+ shell: false,
62
+ detached: process.platform !== 'win32',
63
+ stdio: ['ignore', 'pipe', 'pipe'],
64
+ env: {
65
+ ...process.env,
66
+ NO_COLOR: '1',
67
+ FORCE_COLOR: '0',
68
+ CI: '1',
69
+ },
70
+ });
71
+ }
72
+ catch (error) {
73
+ settle(failed(diagnosticCodes.code_engine_unavailable, `Cannot start ${options.command}: ${errorText(error)}`, {
74
+ nextAction: 'Install the selected code engine or use text fallback.',
75
+ }));
76
+ return;
77
+ }
78
+ timer = setTimeout(() => {
79
+ timedOut = true;
80
+ killGroup(child.pid);
81
+ }, timeoutMs);
82
+ options.signal?.addEventListener('abort', abort, { once: true });
83
+ const collect = (chunks, chunk) => {
84
+ bytes += chunk.byteLength;
85
+ if (bytes > maxOutputBytes) {
86
+ outputExceeded = true;
87
+ killGroup(child.pid);
88
+ return;
89
+ }
90
+ chunks.push(chunk);
91
+ };
92
+ child.stdout?.on('data', (chunk) => collect(stdout, chunk));
93
+ child.stderr?.on('data', (chunk) => collect(stderr, chunk));
94
+ child.on('error', (error) => {
95
+ settle(failed(diagnosticCodes.code_engine_unavailable, `Cannot run ${options.command}: ${errorText(error)}`, {
96
+ nextAction: 'Install the selected code engine or use text fallback.',
97
+ }));
98
+ });
99
+ child.on('close', (exitCode, signal) => {
100
+ const durationMs = Math.round(performance.now() - startedAt);
101
+ if (timedOut) {
102
+ settle(failed(diagnosticCodes.code_engine_failed, `${options.command} timed out after ${timeoutMs}ms.`, {
103
+ retryable: true,
104
+ nextAction: 'Retry with a bounded smaller target.',
105
+ }));
106
+ return;
107
+ }
108
+ if (aborted) {
109
+ settle(failed(diagnosticCodes.code_engine_failed, 'Command was cancelled.', {
110
+ nextAction: 'Retry when cancellation is no longer requested.',
111
+ }));
112
+ return;
113
+ }
114
+ if (outputExceeded) {
115
+ settle(failed(diagnosticCodes.code_output_limit, `${options.command} exceeded the ${maxOutputBytes}-byte output limit.`, { nextAction: 'Narrow the query or selected repository scope.' }));
116
+ return;
117
+ }
118
+ if (exitCode === null) {
119
+ settle(failed(diagnosticCodes.code_engine_failed, `${options.command} ended without an exit code (signal ${signal ?? 'unknown'}).`, { retryable: true, nextAction: 'Inspect the engine and retry.' }));
120
+ return;
121
+ }
122
+ settle(succeeded({
123
+ command: options.command,
124
+ args: [...options.args],
125
+ stdout: Buffer.concat(stdout).toString('utf8'),
126
+ stderr: Buffer.concat(stderr).toString('utf8'),
127
+ exitCode,
128
+ bytes,
129
+ durationMs,
130
+ }));
131
+ });
132
+ });
133
+ }
@@ -0,0 +1,13 @@
1
+ import { type Outcome } from '../schemas/outcome.js';
2
+ import { type CodeIdentity } from '../schemas/code.js';
3
+ export interface ComputeCodeIdentityInput {
4
+ readonly repositoryId: string;
5
+ readonly root: string;
6
+ readonly engineVersion: string;
7
+ readonly configDigest: string;
8
+ readonly configStatus?: 'default' | 'observed' | 'unknown';
9
+ readonly excludedRoots?: readonly string[];
10
+ readonly signal?: AbortSignal;
11
+ }
12
+ export declare function computeCodeIdentity(input: ComputeCodeIdentityInput): Promise<Outcome<CodeIdentity>>;
13
+ export declare function codeIdentityDigest(identity: CodeIdentity): string;
@@ -0,0 +1,214 @@
1
+ import { readlink } from 'node:fs/promises';
2
+ import { join, relative, sep } from 'node:path';
3
+ import { inspectGitRepository } from '../infra/git.js';
4
+ import { runGit } from '../infra/git.js';
5
+ import { observePath, readFileBounded, sha256Digest } from '../infra/fs.js';
6
+ import { diagnosticCodes } from '../schemas/errors.js';
7
+ import { failed, succeeded } from '../schemas/outcome.js';
8
+ import { isPathInside } from '../schemas/paths.js';
9
+ import { codeIdentitySchema, } from '../schemas/code.js';
10
+ const MAX_WORKTREE_BYTES = 16 * 1024 * 1024;
11
+ const MAX_FILE_BYTES = 4 * 1024 * 1024;
12
+ const GIT_TIMEOUT_MS = 10_000;
13
+ const EXCLUDES = [
14
+ ':(exclude).codegraph',
15
+ ':(exclude).pappra/local',
16
+ ':(exclude).pappra/generated',
17
+ ];
18
+ async function observeWorkingTree(root, excludedRoots, signal) {
19
+ const reasons = [];
20
+ let completeness = 'complete';
21
+ const readDiff = async (args) => runGit({
22
+ cwd: root,
23
+ args,
24
+ timeoutMs: GIT_TIMEOUT_MS,
25
+ maxOutputBytes: MAX_WORKTREE_BYTES,
26
+ ...(signal === undefined ? {} : { signal }),
27
+ });
28
+ const trackedExcludes = [...EXCLUDES];
29
+ for (const excluded of excludedRoots) {
30
+ const rel = relative(root, excluded);
31
+ if (rel !== '' && rel !== '..' && !rel.startsWith(`..${sep}`)) {
32
+ trackedExcludes.push(`:(exclude)${rel.split(sep).join('/')}`);
33
+ }
34
+ }
35
+ const cached = await readDiff([
36
+ 'diff',
37
+ '--binary',
38
+ '--cached',
39
+ '--',
40
+ '.',
41
+ ...trackedExcludes,
42
+ ]);
43
+ const unstaged = await readDiff([
44
+ 'diff',
45
+ '--binary',
46
+ '--',
47
+ '.',
48
+ ...trackedExcludes,
49
+ ]);
50
+ const cachedBytes = cached.ok
51
+ ? Buffer.from(cached.value.stdout, 'utf8')
52
+ : Buffer.alloc(0);
53
+ const unstagedBytes = unstaged.ok
54
+ ? Buffer.from(unstaged.value.stdout, 'utf8')
55
+ : Buffer.alloc(0);
56
+ if (!cached.ok) {
57
+ completeness =
58
+ cached.code === diagnosticCodes.gitOutputLimit ? 'partial' : 'unknown';
59
+ reasons.push('tracked_staged_diff_unavailable');
60
+ }
61
+ if (!unstaged.ok) {
62
+ completeness =
63
+ unstaged.code === diagnosticCodes.gitOutputLimit ? 'partial' : 'unknown';
64
+ reasons.push('tracked_unstaged_diff_unavailable');
65
+ }
66
+ const diffBytes = cachedBytes.length + unstagedBytes.length;
67
+ if (diffBytes > MAX_WORKTREE_BYTES) {
68
+ completeness = 'partial';
69
+ reasons.push('tracked_diff_output_limit');
70
+ }
71
+ const untracked = await runGit({
72
+ cwd: root,
73
+ args: [
74
+ 'ls-files',
75
+ '--others',
76
+ '--exclude-standard',
77
+ '-z',
78
+ '--',
79
+ '.',
80
+ ...trackedExcludes,
81
+ ],
82
+ timeoutMs: GIT_TIMEOUT_MS,
83
+ maxOutputBytes: 2 * 1024 * 1024,
84
+ ...(signal === undefined ? {} : { signal }),
85
+ });
86
+ const parts = [
87
+ Buffer.from(`PAPPRA-CODE-WORKTREE/2\nD ${cachedBytes.length} ${unstagedBytes.length}\n`, 'utf8'),
88
+ cachedBytes,
89
+ unstagedBytes,
90
+ ];
91
+ let total = parts.reduce((sum, part) => sum + part.length, 0);
92
+ let fileCount = 0;
93
+ if (!untracked.ok) {
94
+ completeness = 'partial';
95
+ reasons.push('untracked_list_unavailable');
96
+ }
97
+ else {
98
+ const paths = untracked.value.stdout
99
+ .split('\0')
100
+ .filter((path) => path.length > 0);
101
+ for (const path of paths) {
102
+ if (total > MAX_WORKTREE_BYTES) {
103
+ completeness = 'partial';
104
+ reasons.push('working_tree_output_limit');
105
+ break;
106
+ }
107
+ const absolute = join(root, path);
108
+ if (!isPathInside(root, absolute)) {
109
+ completeness = 'partial';
110
+ reasons.push(`untracked_path_unsafe:${path.slice(0, 200)}`);
111
+ continue;
112
+ }
113
+ if (excludedRoots.some((excluded) => isPathInside(excluded, absolute))) {
114
+ continue;
115
+ }
116
+ const observation = await observePath(absolute).catch(() => null);
117
+ if (observation === null) {
118
+ completeness = 'partial';
119
+ reasons.push(`untracked_unreadable:${path.slice(0, 200)}`);
120
+ continue;
121
+ }
122
+ let body;
123
+ let kind;
124
+ if (observation.kind === 'file') {
125
+ const read = await readFileBounded(absolute, MAX_FILE_BYTES);
126
+ if (!read.ok) {
127
+ completeness = 'partial';
128
+ reasons.push(`untracked_file_limit:${path.slice(0, 200)}`);
129
+ continue;
130
+ }
131
+ body = read.value.bytes;
132
+ kind = 'F';
133
+ }
134
+ else if (observation.kind === 'symlink') {
135
+ const target = await readlink(absolute).catch(() => null);
136
+ if (target === null) {
137
+ completeness = 'partial';
138
+ reasons.push(`untracked_symlink_unreadable:${path.slice(0, 200)}`);
139
+ continue;
140
+ }
141
+ body = Buffer.from(target, 'utf8');
142
+ kind = 'L';
143
+ }
144
+ else {
145
+ completeness = 'partial';
146
+ reasons.push(`untracked_not_regular:${path.slice(0, 200)}`);
147
+ continue;
148
+ }
149
+ const pathBytes = Buffer.from(path, 'utf8');
150
+ const header = Buffer.from(`${kind} ${pathBytes.length} ${body.length}\n`, 'utf8');
151
+ if (total + header.length + pathBytes.length + body.length >
152
+ MAX_WORKTREE_BYTES) {
153
+ completeness = 'partial';
154
+ reasons.push('working_tree_output_limit');
155
+ break;
156
+ }
157
+ parts.push(header, pathBytes, body);
158
+ total += header.length + pathBytes.length + body.length;
159
+ fileCount += 1;
160
+ }
161
+ }
162
+ const bytes = Buffer.concat(parts);
163
+ return {
164
+ observation: {
165
+ digest: sha256Digest(bytes),
166
+ completeness,
167
+ fileCount,
168
+ byteCount: bytes.length,
169
+ reasons: [...new Set(reasons)].slice(0, 16),
170
+ },
171
+ bytes,
172
+ };
173
+ }
174
+ export async function computeCodeIdentity(input) {
175
+ const observed = await inspectGitRepository(input.root, {
176
+ timeoutMs: GIT_TIMEOUT_MS,
177
+ ...(input.signal === undefined ? {} : { signal: input.signal }),
178
+ });
179
+ if (!observed.ok)
180
+ return observed;
181
+ const git = observed.value;
182
+ const working = await observeWorkingTree(input.root, input.excludedRoots ?? [], input.signal);
183
+ const checkoutId = sha256Digest(JSON.stringify({
184
+ root: git.root,
185
+ gitDir: git.gitDir,
186
+ commonDir: git.commonDir,
187
+ }));
188
+ const parsed = codeIdentitySchema.safeParse({
189
+ schema: 'pappra/code-identity/1',
190
+ repositoryId: input.repositoryId,
191
+ checkoutId,
192
+ root: git.root,
193
+ gitDir: git.gitDir,
194
+ gitCommonDir: git.commonDir,
195
+ head: git.head,
196
+ branch: git.branch,
197
+ workingTree: working.observation,
198
+ engine: {
199
+ id: 'codegraph',
200
+ version: input.engineVersion,
201
+ configDigest: input.configDigest,
202
+ configStatus: input.configStatus ?? 'observed',
203
+ },
204
+ });
205
+ if (!parsed.success) {
206
+ return failed(diagnosticCodes.code_identity_changed, `Code identity is invalid: ${parsed.error.issues[0]?.message ?? 'unknown issue'}`, {
207
+ nextAction: 'Inspect the selected repository and code engine configuration.',
208
+ });
209
+ }
210
+ return succeeded(parsed.data);
211
+ }
212
+ export function codeIdentityDigest(identity) {
213
+ return sha256Digest(JSON.stringify(identity));
214
+ }
@@ -0,0 +1,6 @@
1
+ export { CodeIntelligenceService, codeIdentityDigest } from './service.js';
2
+ export type { CodePrepareInput, CodeQueryInput, CodeQueryOutput, CodeStatusInput, CodeStatusResult, } from './service.js';
3
+ export { CodeGraphProvider, codeGraphConfigDigest, codeGraphIndexPath, codeGraphVersion, } from './providers/codegraph.js';
4
+ export type { CodeProvider } from './providers/codegraph.js';
5
+ export { codeRegistrationPath, readCodeRegistration, registrationMatches, writeCodeRegistration, } from './registration.js';
6
+ export type { CodeEngine, CodeIdentity, CodeIndexCoverage, CodeIndexHealth, CodeIndexRegistration, CodePrepareAction, CodePreparePlan, CodePrepareResult, CodeQueryItem, CodeQueryKind, CodeQueryLimits, CodeQueryRequest, CodeQueryResult, CodeWorkingTree, } from '../schemas/code.js';
@@ -0,0 +1,3 @@
1
+ export { CodeIntelligenceService, codeIdentityDigest } from './service.js';
2
+ export { CodeGraphProvider, codeGraphConfigDigest, codeGraphIndexPath, codeGraphVersion, } from './providers/codegraph.js';
3
+ export { codeRegistrationPath, readCodeRegistration, registrationMatches, writeCodeRegistration, } from './registration.js';
@@ -0,0 +1,59 @@
1
+ import { z } from 'zod';
2
+ import { type Outcome } from '../../schemas/outcome.js';
3
+ import type { EvidenceRef } from '../../schemas/evidence.js';
4
+ import { type CodeIdentity, type CodeIndexHealth, type CodeQueryRequest, type CodeQueryResult, type CodePrepareAction, type CodePreparePlan } from '../../schemas/code.js';
5
+ declare const engineStatusSchema: z.ZodObject<{
6
+ initialized: z.ZodBoolean;
7
+ version: z.ZodString;
8
+ projectPath: z.ZodOptional<z.ZodString>;
9
+ indexPath: z.ZodOptional<z.ZodString>;
10
+ lastIndexed: z.ZodOptional<z.ZodNullable<z.ZodString>>;
11
+ fileCount: z.ZodOptional<z.ZodNumber>;
12
+ nodeCount: z.ZodOptional<z.ZodNumber>;
13
+ edgeCount: z.ZodOptional<z.ZodNumber>;
14
+ dbSizeBytes: z.ZodOptional<z.ZodNumber>;
15
+ languages: z.ZodOptional<z.ZodArray<z.ZodString>>;
16
+ pendingChanges: z.ZodOptional<z.ZodObject<{
17
+ added: z.ZodNumber;
18
+ modified: z.ZodNumber;
19
+ removed: z.ZodNumber;
20
+ }, z.core.$strip>>;
21
+ worktreeMismatch: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
22
+ index: z.ZodOptional<z.ZodObject<{
23
+ builtWithVersion: z.ZodOptional<z.ZodNullable<z.ZodString>>;
24
+ builtWithExtractionVersion: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
25
+ currentExtractionVersion: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
26
+ reindexRecommended: z.ZodOptional<z.ZodBoolean>;
27
+ state: z.ZodOptional<z.ZodString>;
28
+ pendingRefs: z.ZodOptional<z.ZodNumber>;
29
+ }, z.core.$strip>>;
30
+ }, z.core.$strip>;
31
+ export declare function codeGraphVersion(signal?: AbortSignal): Promise<Outcome<string>>;
32
+ export interface CodeGraphConfigObservation {
33
+ readonly digest: string;
34
+ readonly status: 'default' | 'observed' | 'unknown';
35
+ }
36
+ export declare function observeCodeGraphConfig(root: string): Promise<Outcome<CodeGraphConfigObservation>>;
37
+ export declare function codeGraphConfigDigest(root: string): Promise<string>;
38
+ export interface CodeProvider {
39
+ readonly id: string;
40
+ detect(root: string, signal?: AbortSignal): Promise<Outcome<readonly EvidenceRef[]>>;
41
+ status(identity: CodeIdentity, signal?: AbortSignal): Promise<Outcome<CodeIndexHealth>>;
42
+ prepare(identity: CodeIdentity, plan: CodePreparePlan, signal?: AbortSignal): Promise<Outcome<CodeIndexHealth>>;
43
+ query(request: CodeQueryRequest, signal?: AbortSignal): Promise<Outcome<CodeQueryResult>>;
44
+ }
45
+ export declare function codeGraphPlanCommand(command: string, action: CodePrepareAction, root: string): string[];
46
+ export declare class CodeGraphProvider implements CodeProvider {
47
+ private readonly command;
48
+ readonly id: 'codegraph';
49
+ constructor(command?: string);
50
+ detect(root: string, signal?: AbortSignal): Promise<Outcome<readonly EvidenceRef[]>>;
51
+ status(identity: CodeIdentity, signal?: AbortSignal): Promise<Outcome<CodeIndexHealth>>;
52
+ plan(identity: CodeIdentity, current: CodeIndexHealth, rebuild: boolean): CodePreparePlan;
53
+ prepare(identity: CodeIdentity, plan: CodePreparePlan, signal?: AbortSignal): Promise<Outcome<CodeIndexHealth>>;
54
+ query(request: CodeQueryRequest, signal?: AbortSignal): Promise<Outcome<CodeQueryResult>>;
55
+ }
56
+ export declare function codeGraphIndexPath(root: string): string;
57
+ export declare function codeGraphStatusSchemaForTests(): typeof engineStatusSchema;
58
+ export declare function codeIndexHealthForTests(state: CodeIndexHealth['state'], reasons: readonly string[]): CodeIndexHealth;
59
+ export {};