@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,16 @@
1
+ import type { CodeQueryKind } from '../../schemas/code.js';
2
+ import type { CliOutput } from '../output.js';
3
+ export declare const codeUsage: string;
4
+ export interface CodeCommandOptions {
5
+ readonly cwd: string;
6
+ readonly json: boolean;
7
+ readonly action: 'status' | 'prepare' | 'query' | null;
8
+ readonly repositoryId: string | null;
9
+ readonly kind: CodeQueryKind | null;
10
+ readonly query: string | null;
11
+ readonly maxResults: number | null;
12
+ readonly maxBytes: number | null;
13
+ readonly apply: boolean;
14
+ readonly rebuild: boolean;
15
+ }
16
+ export declare function runCodeCommand(options: CodeCommandOptions, output: CliOutput): Promise<number>;
@@ -0,0 +1,127 @@
1
+ import { formatDiagnostic } from '../../schemas/diagnostics.js';
2
+ import { CodeIntelligenceService } from '../../code/service.js';
3
+ import { resolveWorkspaceRoot } from '../../workspace/resolve.js';
4
+ export const codeUsage = 'pappra code status --repo <id> [--json]\n' +
5
+ 'pappra code prepare --repo <id> [--apply] [--rebuild] [--json]\n' +
6
+ 'pappra code query --repo <id> --kind explore|symbol|references|impact|text --query <text>\n' +
7
+ ' [--limit <1-100>] [--max-bytes <bytes>] [--json]';
8
+ function printDiagnostics(output, diagnostics) {
9
+ for (const diagnostic of diagnostics) {
10
+ output.stderr(`${formatDiagnostic(diagnostic)}\n`);
11
+ }
12
+ }
13
+ async function serviceRoot(cwd) {
14
+ const resolution = await resolveWorkspaceRoot({ startPath: cwd });
15
+ return resolution.root ?? cwd;
16
+ }
17
+ function statusJson(result) {
18
+ return {
19
+ schema: 'pappra/code-status-result/1',
20
+ ok: result.ok,
21
+ identity: result.identity,
22
+ health: result.health,
23
+ registrationPath: result.registrationPath,
24
+ registrationPresent: result.registrationPresent,
25
+ diagnostics: result.diagnostics,
26
+ };
27
+ }
28
+ export async function runCodeCommand(options, output) {
29
+ if (options.action === null) {
30
+ output.stderr('pappra: code requires status, prepare, or query.\n');
31
+ return 2;
32
+ }
33
+ if (options.repositoryId === null) {
34
+ output.stderr('pappra: code requires --repo <id>.\n');
35
+ return 2;
36
+ }
37
+ const root = await serviceRoot(options.cwd);
38
+ const service = new CodeIntelligenceService(root);
39
+ if (options.action === 'status') {
40
+ const result = await service.status({ repositoryId: options.repositoryId });
41
+ if (options.json) {
42
+ output.stdout(`${JSON.stringify(statusJson(result))}\n`);
43
+ }
44
+ else {
45
+ output.stdout(`Repository: ${options.repositoryId}\n`);
46
+ output.stdout(`Identity: ${result.identity?.checkoutId ?? 'unavailable'}\n`);
47
+ output.stdout(`Index: ${result.health.state}\n`);
48
+ output.stdout(`Registration: ${result.registrationPresent ? 'present' : 'missing'}\n`);
49
+ for (const reason of result.health.reasons)
50
+ output.stdout(`Reason: ${reason}\n`);
51
+ printDiagnostics(output, result.diagnostics);
52
+ }
53
+ return result.ok ? 0 : 1;
54
+ }
55
+ if (options.action === 'prepare') {
56
+ const result = await service.prepare({
57
+ root,
58
+ repositoryId: options.repositoryId,
59
+ apply: options.apply,
60
+ rebuild: options.rebuild,
61
+ });
62
+ if (options.json) {
63
+ output.stdout(`${JSON.stringify(result)}\n`);
64
+ }
65
+ else {
66
+ output.stdout(`Prepare plan: ${result.plan.action}\n`);
67
+ output.stdout(`Mutates index: ${result.plan.mutates ? 'yes' : 'no'}\n`);
68
+ output.stdout(`Index: ${result.health.state}\n`);
69
+ if (result.registrationPath !== null) {
70
+ output.stdout(`Registration: ${result.registrationPath}\n`);
71
+ }
72
+ for (const reason of result.plan.reasons)
73
+ output.stdout(`Reason: ${reason}\n`);
74
+ printDiagnostics(output, result.diagnostics);
75
+ }
76
+ return result.ok || result.status === 'planned' ? 0 : 1;
77
+ }
78
+ if (options.kind === null || options.query === null) {
79
+ output.stderr('pappra: code query requires --kind and --query.\n');
80
+ return 2;
81
+ }
82
+ const result = await service.query({
83
+ root,
84
+ repositoryId: options.repositoryId,
85
+ kind: options.kind,
86
+ query: options.query,
87
+ ...(options.maxResults === null && options.maxBytes === null
88
+ ? {}
89
+ : {
90
+ limits: {
91
+ ...(options.maxResults === null
92
+ ? {}
93
+ : { maxResults: options.maxResults }),
94
+ ...(options.maxBytes === null
95
+ ? {}
96
+ : { maxBytes: options.maxBytes }),
97
+ },
98
+ }),
99
+ });
100
+ if (options.json) {
101
+ output.stdout(`${JSON.stringify({
102
+ schema: 'pappra/code-query-result/1',
103
+ ok: result.ok,
104
+ health: result.health,
105
+ result: result.result,
106
+ diagnostics: result.diagnostics,
107
+ })}\n`);
108
+ }
109
+ else if (result.result !== null) {
110
+ output.stdout(`Query: ${result.result.kind} ${result.result.query}\n`);
111
+ output.stdout(`Coverage: ${result.result.coverage}\n`);
112
+ output.stdout(`Provider: ${result.result.provider}\n`);
113
+ for (const item of result.result.items) {
114
+ output.stdout(`${item.path}:${item.line ?? '?'}:${item.column ?? '?'} ${item.kind} ${item.name ?? ''}\n`);
115
+ if (item.snippet !== '')
116
+ output.stdout(` ${item.snippet}\n`);
117
+ }
118
+ if (result.result.unsupportedReason !== null) {
119
+ output.stdout(`Note: ${result.result.unsupportedReason}\n`);
120
+ }
121
+ printDiagnostics(output, result.diagnostics);
122
+ }
123
+ else {
124
+ printDiagnostics(output, result.diagnostics);
125
+ }
126
+ return result.ok ? 0 : 1;
127
+ }
@@ -0,0 +1,13 @@
1
+ import type { CliOutput } from '../output.js';
2
+ export declare const collaborationUsage: string;
3
+ export interface CollaborationCommandOptions {
4
+ readonly cwd: string;
5
+ readonly action: string | null;
6
+ readonly json: boolean;
7
+ readonly goalFile: string | null;
8
+ readonly preparedFile: string | null;
9
+ readonly capabilitiesFile: string | null;
10
+ readonly controller: string | null;
11
+ readonly domainRoot: string | null;
12
+ }
13
+ export declare function runCollaborationCommand(options: CollaborationCommandOptions, output: CliOutput, input?: NodeJS.ReadableStream): Promise<number>;
@@ -0,0 +1,186 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { FixtureController, PiRpcController, driveRun, inspectPreparedHistory, prepareCollaboration, startPrepared, } from '../../app/collaboration.js';
4
+ export const collaborationUsage = 'pappra collab <prepare|run|query> [options]\n' +
5
+ ' prepare --goal <file> --domain-root <dir> [--json]\n' +
6
+ ' run --prepared <file> --capabilities <card> --controller <fixture|pi-rpc>\n' +
7
+ ' query --prepared <file> [--json]\n' +
8
+ ' run reads pappra/collaboration-command/1 JSONL from stdin and writes\n' +
9
+ ' pappra/collaboration-event/1 JSONL to stdout.';
10
+ function failure(code, message) {
11
+ return { schema: 'pappra/collaboration-result/1', ok: false, code, message };
12
+ }
13
+ function readGoal(file) {
14
+ const stat = fs.lstatSync(file);
15
+ if (!stat.isFile() || stat.size > 1024 * 1024) {
16
+ throw new Error('goal file must be a regular file no larger than 1 MiB');
17
+ }
18
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
19
+ }
20
+ function controllerFor(name) {
21
+ if (name === 'fixture')
22
+ return new FixtureController();
23
+ if (name === 'pi-rpc')
24
+ return new PiRpcController();
25
+ return null;
26
+ }
27
+ const MAX_COMMAND_LINE_BYTES = 256 * 1024;
28
+ const MAX_COMMAND_TOTAL_BYTES = 4 * 1024 * 1024;
29
+ const MAX_QUEUED_COMMANDS = 64;
30
+ function lines(stream) {
31
+ let buffer = '';
32
+ const queue = [];
33
+ let ended = false;
34
+ let error = null;
35
+ let total = 0;
36
+ let notify = null;
37
+ stream.setEncoding('utf8');
38
+ stream.on('data', (chunk) => {
39
+ if (error !== null)
40
+ return;
41
+ total += Buffer.byteLength(chunk);
42
+ if (total > MAX_COMMAND_TOTAL_BYTES) {
43
+ error = new Error('run command input exceeded its aggregate bound');
44
+ ended = true;
45
+ notify?.();
46
+ return;
47
+ }
48
+ buffer += chunk;
49
+ if (Buffer.byteLength(buffer) > MAX_COMMAND_LINE_BYTES) {
50
+ error = new Error('run command line exceeded its bound');
51
+ ended = true;
52
+ notify?.();
53
+ return;
54
+ }
55
+ for (;;) {
56
+ const newline = buffer.indexOf('\n');
57
+ if (newline < 0)
58
+ break;
59
+ queue.push(buffer.slice(0, newline));
60
+ buffer = buffer.slice(newline + 1);
61
+ if (queue.length > MAX_QUEUED_COMMANDS) {
62
+ error = new Error('run command queue exceeded its bound');
63
+ ended = true;
64
+ notify?.();
65
+ return;
66
+ }
67
+ }
68
+ notify?.();
69
+ });
70
+ stream.on('error', (streamError) => {
71
+ error = streamError;
72
+ ended = true;
73
+ notify?.();
74
+ });
75
+ stream.on('end', () => {
76
+ if (buffer.length > 0)
77
+ queue.push(buffer);
78
+ ended = true;
79
+ notify?.();
80
+ });
81
+ return {
82
+ async *[Symbol.asyncIterator]() {
83
+ for (;;) {
84
+ if (error !== null)
85
+ throw error;
86
+ if (queue.length > 0) {
87
+ yield queue.shift();
88
+ continue;
89
+ }
90
+ if (ended)
91
+ return;
92
+ await new Promise((resolve) => {
93
+ notify = resolve;
94
+ });
95
+ notify = null;
96
+ }
97
+ },
98
+ };
99
+ }
100
+ export async function runCollaborationCommand(options, output, input = process.stdin) {
101
+ if (options.action === 'prepare') {
102
+ if (options.goalFile === null) {
103
+ output.stderr('pappra: collab prepare requires --goal <file>\n');
104
+ return 2;
105
+ }
106
+ if (options.domainRoot === null) {
107
+ output.stdout(`${JSON.stringify(failure('domain_root_required', 'collab prepare requires --domain-root so shared-resource conflicts use one explicit domain'))}\n`);
108
+ return 2;
109
+ }
110
+ const domainRoot = options.domainRoot;
111
+ let goal;
112
+ try {
113
+ goal = readGoal(options.goalFile);
114
+ }
115
+ catch (error) {
116
+ output.stdout(`${JSON.stringify(failure('goal_unreadable', error instanceof Error ? error.message : String(error)))}\n`);
117
+ return 2;
118
+ }
119
+ const result = await prepareCollaboration(goal, {
120
+ domainRoot: path.resolve(domainRoot),
121
+ });
122
+ if (!result.ok) {
123
+ output.stdout(`${JSON.stringify(result)}\n`);
124
+ return 1;
125
+ }
126
+ output.stdout(`${JSON.stringify({
127
+ schema: 'pappra/collaboration-prepared/1',
128
+ ok: true,
129
+ status: 'prepared',
130
+ prepared: result.value.prepared,
131
+ })}\n`);
132
+ return 0;
133
+ }
134
+ if (options.action === 'query') {
135
+ if (options.preparedFile === null) {
136
+ output.stderr('pappra: collab query requires --prepared <file>\n');
137
+ return 2;
138
+ }
139
+ const result = inspectPreparedHistory(path.resolve(options.preparedFile));
140
+ output.stdout(`${JSON.stringify(result)}\n`);
141
+ return result.ok ? 0 : 1;
142
+ }
143
+ if (options.action === 'run') {
144
+ if (options.preparedFile === null || options.capabilitiesFile === null) {
145
+ output.stderr('pappra: collab run requires --prepared <file> and --capabilities <card>\n');
146
+ return 2;
147
+ }
148
+ const controller = controllerFor(options.controller);
149
+ if (controller === null) {
150
+ output.stderr('pappra: collab run requires --controller <fixture|pi-rpc>\n');
151
+ return 2;
152
+ }
153
+ const started = await startPrepared(path.resolve(options.preparedFile), {
154
+ capabilitiesFile: path.resolve(options.capabilitiesFile),
155
+ controller,
156
+ controllerId: controller.id,
157
+ });
158
+ if (!started.ok) {
159
+ output.stdout(`${JSON.stringify(started)}\n`);
160
+ return 1;
161
+ }
162
+ const commands = (async function* () {
163
+ for await (const line of lines(input)) {
164
+ const trimmed = line.trim();
165
+ if (!trimmed)
166
+ continue;
167
+ try {
168
+ yield JSON.parse(trimmed);
169
+ }
170
+ catch {
171
+ yield { schema: 'pappra/collaboration-command/1', action: 'invalid' };
172
+ }
173
+ }
174
+ })();
175
+ const result = await driveRun(started.value, commands, (event) => {
176
+ output.stdout(`${JSON.stringify(event)}\n`);
177
+ });
178
+ if (!result.ok) {
179
+ output.stderr(`pappra: ${result.code}: ${result.message}\n`);
180
+ return 1;
181
+ }
182
+ return result.value.ok ? 0 : 1;
183
+ }
184
+ output.stderr('pappra: collab requires prepare, run, or query\n');
185
+ return 2;
186
+ }
@@ -0,0 +1,29 @@
1
+ import type { CliOutput } from '../output.js';
2
+ export declare const checkpointUsage: string;
3
+ export declare const resumeUsage = "pappra resume <taskId> [--session <native-session-id>] [--json]";
4
+ export interface CheckpointCommandOptions {
5
+ readonly cwd: string;
6
+ readonly json: boolean;
7
+ readonly task: string | null;
8
+ readonly objective: string | null;
9
+ readonly acceptance: readonly string[];
10
+ readonly constraints: readonly string[];
11
+ readonly decisions: readonly string[];
12
+ readonly attempted: readonly string[];
13
+ readonly nextActions: readonly string[];
14
+ readonly limitations: readonly string[];
15
+ readonly artifacts: readonly string[];
16
+ readonly collaborationRecordRef: string | null;
17
+ readonly contextCompleteness: 'complete' | 'partial' | null;
18
+ readonly authorSession: string | null;
19
+ readonly nativeHarness: 'pi' | 'codex' | 'claude' | 'unknown' | null;
20
+ readonly nativeSession: string | null;
21
+ }
22
+ export interface ResumeCommandOptions {
23
+ readonly cwd: string;
24
+ readonly json: boolean;
25
+ readonly taskId: string;
26
+ readonly currentSession: string | null;
27
+ }
28
+ export declare function runCheckpointCommand(options: CheckpointCommandOptions, output: CliOutput): Promise<number>;
29
+ export declare function runResumeCommand(options: ResumeCommandOptions, output: CliOutput): Promise<number>;
@@ -0,0 +1,133 @@
1
+ import { formatDiagnostic } from '../../schemas/diagnostics.js';
2
+ import { CheckpointService, } from '../../continuity/index.js';
3
+ import { resolveWorkspaceRoot } from '../../workspace/resolve.js';
4
+ export const checkpointUsage = 'pappra checkpoint --task <id> [options]\n' +
5
+ ' --objective <text> --acceptance <text> [--acceptance <text> ...]\n' +
6
+ ' [--constraint <text> ...] [--decision <text> ...]\n' +
7
+ ' [--attempted <text> ...] [--next-action <text> ...]\n' +
8
+ ' [--limitation <text> ...] [--artifact <path> ...]\n' +
9
+ ' [--collaboration-record <path>] [--context-completeness complete|partial]\n' +
10
+ ' [--author-session <id>] [--native-harness pi|codex|claude|unknown]\n' +
11
+ ' [--native-session <id>] [--json]';
12
+ export const resumeUsage = 'pappra resume <taskId> [--session <native-session-id>] [--json]';
13
+ function printDiagnostics(output, diagnostics) {
14
+ for (const diagnostic of diagnostics) {
15
+ output.stderr(`${formatDiagnostic(diagnostic)}\n`);
16
+ }
17
+ }
18
+ async function serviceRoot(cwd) {
19
+ const resolution = await resolveWorkspaceRoot({ startPath: cwd });
20
+ return resolution.root ?? cwd;
21
+ }
22
+ export async function runCheckpointCommand(options, output) {
23
+ if (options.task === null) {
24
+ output.stderr('pappra: checkpoint requires --task\n');
25
+ return 2;
26
+ }
27
+ const root = await serviceRoot(options.cwd);
28
+ const service = new CheckpointService(root);
29
+ const nativeSession = options.nativeSession ?? options.authorSession;
30
+ const input = {
31
+ taskId: options.task,
32
+ ...(options.objective === null ? {} : { objective: options.objective }),
33
+ ...(options.acceptance.length === 0
34
+ ? {}
35
+ : { acceptance: options.acceptance }),
36
+ constraints: options.constraints,
37
+ decisions: options.decisions,
38
+ attempted: options.attempted,
39
+ nextActions: options.nextActions,
40
+ limitations: options.limitations,
41
+ artifacts: options.artifacts,
42
+ ...(options.collaborationRecordRef === null
43
+ ? {}
44
+ : { collaborationRecordRef: options.collaborationRecordRef }),
45
+ ...(options.contextCompleteness === null
46
+ ? {}
47
+ : { contextCompleteness: options.contextCompleteness }),
48
+ authorSession: options.authorSession,
49
+ ...(nativeSession === null
50
+ ? {}
51
+ : {
52
+ nativeRefs: [
53
+ {
54
+ harness: options.nativeHarness ?? 'pi',
55
+ sessionId: nativeSession,
56
+ turnId: null,
57
+ runId: null,
58
+ },
59
+ ],
60
+ }),
61
+ };
62
+ const result = await service.save(input);
63
+ if (options.json) {
64
+ output.stdout(`${JSON.stringify({
65
+ schema: 'pappra/checkpoint-result/1',
66
+ ok: result.ok,
67
+ status: result.status,
68
+ checkpoint: result.checkpoint,
69
+ checkpointPath: result.checkpointPath,
70
+ latestPath: result.latestPath,
71
+ diagnostics: result.diagnostics,
72
+ residualPaths: result.residualPaths,
73
+ })}\n`);
74
+ }
75
+ else if (result.checkpoint !== null) {
76
+ output.stdout(`checkpoint ${result.checkpoint.revision} saved: ${result.checkpointPath ?? 'unknown'}\n`);
77
+ printDiagnostics(output, result.diagnostics);
78
+ }
79
+ else {
80
+ printDiagnostics(output, result.diagnostics);
81
+ }
82
+ return result.ok ? 0 : 1;
83
+ }
84
+ export async function runResumeCommand(options, output) {
85
+ const root = await serviceRoot(options.cwd);
86
+ const service = new CheckpointService(root);
87
+ const result = await service.resume({
88
+ taskId: options.taskId,
89
+ currentSession: options.currentSession,
90
+ });
91
+ if (options.json) {
92
+ if (result.packet !== null) {
93
+ output.stdout(`${JSON.stringify(result.packet)}\n`);
94
+ }
95
+ else {
96
+ output.stdout(`${JSON.stringify({
97
+ schema: 'pappra/resume-result/1',
98
+ ok: false,
99
+ status: result.status,
100
+ diagnostics: result.diagnostics,
101
+ })}\n`);
102
+ }
103
+ }
104
+ else if (result.packet !== null) {
105
+ const packet = result.packet;
106
+ output.stdout(`Task: ${packet.taskId}\n`);
107
+ output.stdout(`Checkpoint: ${packet.checkpoint.ref}@${packet.checkpoint.revision}\n`);
108
+ output.stdout(`Execution allowed: ${packet.executionAllowed ? 'yes' : 'no'}\n`);
109
+ output.stdout(`Context: ${packet.contextCompleteness}\n`);
110
+ output.stdout(`Code drift: ${packet.codeDrift.status}\n`);
111
+ output.stdout(`Verification: ${packet.verificationStatus}\n`);
112
+ output.stdout(`Objective: ${packet.boundedContext.objective}\n`);
113
+ for (const reason of packet.blockingReasons) {
114
+ output.stdout(`Blocked: ${reason.code}: ${reason.message}\n`);
115
+ }
116
+ for (const action of packet.boundedContext.nextActions) {
117
+ output.stdout(`Next: ${action}\n`);
118
+ }
119
+ for (const observation of packet.executionObservations) {
120
+ output.stdout(`Observation: ${observation.harness}/${observation.sessionId ?? 'unknown'} stored-snapshot live=${observation.liveStatus}\n`);
121
+ }
122
+ printDiagnostics(output, result.diagnostics);
123
+ }
124
+ else {
125
+ printDiagnostics(output, result.diagnostics);
126
+ }
127
+ return result.ok &&
128
+ result.packet !== null &&
129
+ result.packet.executionAllowed &&
130
+ result.packet.verificationStatus === 'current'
131
+ ? 0
132
+ : 1;
133
+ }
@@ -0,0 +1,11 @@
1
+ import type { CliOutput } from '../output.js';
2
+ export declare const docsUsage: string;
3
+ export interface DocsCommandOptions {
4
+ readonly cwd: string;
5
+ readonly action: string | null;
6
+ readonly argument: string | null;
7
+ readonly json: boolean;
8
+ readonly includePrivate: boolean;
9
+ readonly includeArchived: boolean;
10
+ }
11
+ export declare function runDocsCommand(options: DocsCommandOptions, output: CliOutput): Promise<number>;
@@ -0,0 +1,133 @@
1
+ import { resolveWorkspaceRoot } from '../../workspace/resolve.js';
2
+ import { formatDiagnostic } from '../../schemas/diagnostics.js';
3
+ import { docsArchiveReportSchema, docsCheckReportSchema, docsListReportSchema, } from '../../schemas/document.js';
4
+ import { KnowledgeService, } from '../../knowledge/index.js';
5
+ export const docsUsage = 'pappra docs <list|check|archive> [options]\n' +
6
+ ' list [--include-private] [--include-archived] [--json]\n' +
7
+ ' check [--include-private] [--json]\n' +
8
+ ' archive <documentId> [--json]';
9
+ function printDiagnostics(output, diagnostics) {
10
+ for (const diagnostic of diagnostics) {
11
+ output.stderr(`${formatDiagnostic(diagnostic)}\n`);
12
+ }
13
+ }
14
+ function printDocument(output, record) {
15
+ output.stdout(`${record.documentId} ${record.lifecycle}/${record.maturity} ${record.visibility} ${record.kind} ${record.location.kind === 'workspace' ? record.location.path : `${record.location.sourceId}:${record.location.path}`}\n`);
16
+ }
17
+ function listReport(result) {
18
+ return {
19
+ schema: 'pappra/docs-list/1',
20
+ ok: result.ok,
21
+ includePrivate: result.includePrivate,
22
+ includeArchived: result.includeArchived,
23
+ catalogDigest: result.catalogDigest,
24
+ documents: result.records,
25
+ diagnostics: result.diagnostics,
26
+ };
27
+ }
28
+ function checkReport(result) {
29
+ return {
30
+ schema: 'pappra/docs-check/1',
31
+ ...result,
32
+ };
33
+ }
34
+ function invalidArguments(output, json, message) {
35
+ if (json) {
36
+ output.stdout(`${JSON.stringify({ ok: false, code: 'invalid_arguments', message })}\n`);
37
+ }
38
+ else {
39
+ output.stderr(`pappra: ${message}\n`);
40
+ }
41
+ return 2;
42
+ }
43
+ export async function runDocsCommand(options, output) {
44
+ if (options.action === null || options.action === 'help') {
45
+ if (options.json) {
46
+ output.stdout(`${JSON.stringify({
47
+ commands: ['list', 'check', 'archive'],
48
+ usage: docsUsage,
49
+ })}\n`);
50
+ }
51
+ else {
52
+ output.stdout(`${docsUsage}\n`);
53
+ }
54
+ return 0;
55
+ }
56
+ const resolution = await resolveWorkspaceRoot({ startPath: options.cwd });
57
+ const serviceRoot = resolution.root ?? options.cwd;
58
+ if (!['list', 'check', 'archive'].includes(options.action)) {
59
+ return invalidArguments(output, options.json, `unknown docs action: ${options.action}`);
60
+ }
61
+ if (options.action === 'archive' && options.argument === null) {
62
+ return invalidArguments(output, options.json, 'docs archive requires a documentId');
63
+ }
64
+ if (options.action !== 'archive' && options.argument !== null) {
65
+ return invalidArguments(output, options.json, `docs ${options.action} does not accept an argument`);
66
+ }
67
+ if (options.action === 'archive' && options.argument !== null) {
68
+ const service = new KnowledgeService(serviceRoot);
69
+ const result = await service.archive(options.argument);
70
+ if (options.json) {
71
+ const report = docsArchiveReportSchema.safeParse({
72
+ schema: 'pappra/docs-archive/1',
73
+ ok: result.ok,
74
+ status: result.status,
75
+ document: result.record,
76
+ diagnostics: result.diagnostics,
77
+ });
78
+ if (!report.success) {
79
+ return invalidArguments(output, true, `docs archive report is invalid: ${report.error.issues[0]?.message ?? 'unknown issue'}`);
80
+ }
81
+ output.stdout(`${JSON.stringify(report.data)}\n`);
82
+ }
83
+ else if (result.record !== null) {
84
+ printDocument(output, result.record);
85
+ printDiagnostics(output, result.diagnostics);
86
+ }
87
+ else {
88
+ printDiagnostics(output, result.diagnostics);
89
+ }
90
+ return result.ok ? 0 : 1;
91
+ }
92
+ const service = new KnowledgeService(serviceRoot);
93
+ if (options.action === 'list') {
94
+ const result = await service.list({
95
+ includePrivate: options.includePrivate,
96
+ includeArchived: options.includeArchived,
97
+ });
98
+ if (options.json) {
99
+ const report = docsListReportSchema.safeParse(listReport(result));
100
+ if (!report.success) {
101
+ return invalidArguments(output, true, `docs list report is invalid: ${report.error.issues[0]?.message ?? 'unknown issue'}`);
102
+ }
103
+ output.stdout(`${JSON.stringify(report.data)}\n`);
104
+ }
105
+ else {
106
+ for (const record of result.records)
107
+ printDocument(output, record);
108
+ printDiagnostics(output, result.diagnostics);
109
+ }
110
+ return result.ok ? 0 : 1;
111
+ }
112
+ const result = await service.check({
113
+ includePrivate: options.includePrivate,
114
+ });
115
+ if (options.json) {
116
+ const report = docsCheckReportSchema.safeParse(checkReport(result));
117
+ if (!report.success) {
118
+ return invalidArguments(output, true, `docs check report is invalid: ${report.error.issues[0]?.message ?? 'unknown issue'}`);
119
+ }
120
+ output.stdout(`${JSON.stringify(report.data)}\n`);
121
+ }
122
+ else {
123
+ for (const entry of result.entries) {
124
+ output.stdout(`${entry.documentId} ${entry.freshness} ${entry.lifecycle}/${entry.maturity} record=${entry.recordDigest} file=${entry.fileDigest ?? 'missing'}\n`);
125
+ for (const reason of entry.reasons) {
126
+ output.stdout(` ${reason.code}: ${reason.message}\n`);
127
+ }
128
+ }
129
+ output.stdout(`total=${result.summary.total} current=${result.summary.current} needs-review=${result.summary.needsReview} unknown=${result.summary.unknown}\n`);
130
+ printDiagnostics(output, result.diagnostics);
131
+ }
132
+ return result.ok ? 0 : 1;
133
+ }
@@ -0,0 +1,14 @@
1
+ import type { CliOutput } from '../output.js';
2
+ export interface DoctorCommandOptions {
3
+ readonly root: string;
4
+ readonly json: boolean;
5
+ readonly dataDir?: string;
6
+ readonly homeDir?: string;
7
+ readonly pathEnv?: string;
8
+ }
9
+ /**
10
+ * Runs one read-only doctor report. JSON mode writes exactly one JSON document
11
+ * to stdout and never opens prompts or emits progress logs.
12
+ */
13
+ export declare function runDoctorCommand(options: DoctorCommandOptions, output: CliOutput): Promise<number>;
14
+ export declare const doctorUsage: string;