@phyzess/pappra 0.1.0-beta.11 → 0.1.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -2
- package/assets/integrations/skills/pappra/references/operations.md +5 -0
- package/dist/app/collab-from.d.ts +35 -0
- package/dist/app/collab-from.js +84 -0
- package/dist/app/host-mcp.d.ts +25 -0
- package/dist/app/host-mcp.js +227 -0
- package/dist/app/host-probe.d.ts +16 -0
- package/dist/app/host-probe.js +125 -0
- package/dist/app/init.d.ts +15 -0
- package/dist/app/init.js +82 -3
- package/dist/app/onboard.d.ts +60 -0
- package/dist/app/onboard.js +259 -0
- package/dist/app/task-pin.d.ts +23 -0
- package/dist/app/task-pin.js +113 -0
- package/dist/cli/commands/docs.js +12 -76
- package/dist/cli/commands/host.d.ts +3 -1
- package/dist/cli/commands/host.js +55 -1
- package/dist/cli/commands/init.d.ts +0 -8
- package/dist/cli/commands/init.js +5 -126
- package/dist/cli/commands/mcp.d.ts +8 -0
- package/dist/cli/commands/mcp.js +13 -0
- package/dist/cli/commands/onboard.d.ts +14 -0
- package/dist/cli/commands/onboard.js +225 -0
- package/dist/cli/commands/task.d.ts +10 -0
- package/dist/cli/commands/task.js +76 -0
- package/dist/cli/run.js +206 -7
- package/dist/hosts/integration/hook.js +4 -1
- package/dist/hosts/integration/pappra-extension-runtime.mjs +50 -8
- package/dist/hosts/integration/pappra-hook.mjs +50 -8
- package/dist/knowledge/scan.d.ts +30 -0
- package/dist/knowledge/scan.js +91 -0
- package/dist/mcp/server.d.ts +11 -0
- package/dist/mcp/server.js +518 -0
- package/dist/schemas/workspace.d.ts +6 -0
- package/dist/schemas/workspace.js +4 -0
- package/package.json +2 -1
- package/skills/pappra/references/operations.md +5 -0
package/dist/cli/run.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { parseArgs } from 'node:util';
|
|
2
2
|
import { getPackageInfo } from '../package-info.js';
|
|
3
3
|
import { initUsage, runInitCommand } from './commands/init.js';
|
|
4
|
+
import { onboardUsage, runOnboardCommand } from './commands/onboard.js';
|
|
5
|
+
import { mcpUsage, runMcpCommand } from './commands/mcp.js';
|
|
6
|
+
import { taskUsage, runTaskCommand } from './commands/task.js';
|
|
4
7
|
import { doctorUsage, runDoctorCommand } from './commands/doctor.js';
|
|
5
8
|
import { docsUsage, runDocsCommand } from './commands/docs.js';
|
|
6
9
|
import { checkpointUsage, resumeUsage, runCheckpointCommand, runResumeCommand, } from './commands/continuity.js';
|
|
@@ -21,6 +24,11 @@ function parseOptions(args) {
|
|
|
21
24
|
yes: { type: 'boolean', short: 'y' },
|
|
22
25
|
'no-runtime': { type: 'boolean' },
|
|
23
26
|
reconfigure: { type: 'boolean' },
|
|
27
|
+
hosts: { type: 'string' },
|
|
28
|
+
'apply-host': { type: 'boolean' },
|
|
29
|
+
'dry-run': { type: 'boolean' },
|
|
30
|
+
'print-handoff': { type: 'boolean' },
|
|
31
|
+
'auto-resume': { type: 'boolean' },
|
|
24
32
|
from: { type: 'string' },
|
|
25
33
|
tarball: { type: 'string' },
|
|
26
34
|
out: { type: 'string' },
|
|
@@ -74,6 +82,25 @@ function parseOptions(args) {
|
|
|
74
82
|
throw new Error('Use either --help or --version, not both.');
|
|
75
83
|
}
|
|
76
84
|
const command = positionals[0] ?? null;
|
|
85
|
+
if (command === 'task') {
|
|
86
|
+
if (positionals.length > 3) {
|
|
87
|
+
throw new Error('task accepts one action and an optional task id.');
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
values,
|
|
91
|
+
command,
|
|
92
|
+
docsAction: null,
|
|
93
|
+
docsArgument: null,
|
|
94
|
+
codeAction: null,
|
|
95
|
+
hostAction: null,
|
|
96
|
+
hostSubAction: null,
|
|
97
|
+
collaborationAction: null,
|
|
98
|
+
resumeTaskId: null,
|
|
99
|
+
runtimeAction: null,
|
|
100
|
+
taskAction: positionals[1] ?? null,
|
|
101
|
+
taskArgument: positionals[2] ?? null,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
77
104
|
if (command === 'docs') {
|
|
78
105
|
if (positionals.length > 3) {
|
|
79
106
|
throw new Error('Unknown command; docs accepts one action and one argument.');
|
|
@@ -85,9 +112,12 @@ function parseOptions(args) {
|
|
|
85
112
|
docsAction: positionals[1] ?? null,
|
|
86
113
|
docsArgument: positionals[2] ?? null,
|
|
87
114
|
hostAction: null,
|
|
115
|
+
hostSubAction: null,
|
|
88
116
|
collaborationAction: null,
|
|
89
117
|
resumeTaskId: null,
|
|
90
118
|
runtimeAction: null,
|
|
119
|
+
taskAction: null,
|
|
120
|
+
taskArgument: null,
|
|
91
121
|
};
|
|
92
122
|
}
|
|
93
123
|
if (command === 'resume') {
|
|
@@ -101,9 +131,12 @@ function parseOptions(args) {
|
|
|
101
131
|
docsArgument: null,
|
|
102
132
|
codeAction: null,
|
|
103
133
|
hostAction: null,
|
|
134
|
+
hostSubAction: null,
|
|
104
135
|
collaborationAction: null,
|
|
105
136
|
resumeTaskId: positionals[1] ?? null,
|
|
106
137
|
runtimeAction: null,
|
|
138
|
+
taskAction: null,
|
|
139
|
+
taskArgument: null,
|
|
107
140
|
};
|
|
108
141
|
}
|
|
109
142
|
if (command === 'code') {
|
|
@@ -117,14 +150,17 @@ function parseOptions(args) {
|
|
|
117
150
|
docsArgument: null,
|
|
118
151
|
codeAction: positionals[1] ?? null,
|
|
119
152
|
hostAction: null,
|
|
153
|
+
hostSubAction: null,
|
|
120
154
|
collaborationAction: null,
|
|
121
155
|
resumeTaskId: null,
|
|
122
156
|
runtimeAction: null,
|
|
157
|
+
taskAction: null,
|
|
158
|
+
taskArgument: null,
|
|
123
159
|
};
|
|
124
160
|
}
|
|
125
161
|
if (command === 'host') {
|
|
126
|
-
if (positionals.length >
|
|
127
|
-
throw new Error('host accepts one action
|
|
162
|
+
if (positionals.length > 3) {
|
|
163
|
+
throw new Error('host accepts one action and an optional mcp sub-action.');
|
|
128
164
|
}
|
|
129
165
|
return {
|
|
130
166
|
values,
|
|
@@ -133,9 +169,12 @@ function parseOptions(args) {
|
|
|
133
169
|
docsArgument: null,
|
|
134
170
|
codeAction: null,
|
|
135
171
|
hostAction: positionals[1] ?? null,
|
|
172
|
+
hostSubAction: positionals[2] ?? null,
|
|
136
173
|
collaborationAction: null,
|
|
137
174
|
resumeTaskId: null,
|
|
138
175
|
runtimeAction: null,
|
|
176
|
+
taskAction: null,
|
|
177
|
+
taskArgument: null,
|
|
139
178
|
};
|
|
140
179
|
}
|
|
141
180
|
if (command === 'runtime') {
|
|
@@ -149,9 +188,12 @@ function parseOptions(args) {
|
|
|
149
188
|
docsArgument: null,
|
|
150
189
|
codeAction: null,
|
|
151
190
|
hostAction: null,
|
|
191
|
+
hostSubAction: null,
|
|
152
192
|
collaborationAction: null,
|
|
153
193
|
resumeTaskId: null,
|
|
154
194
|
runtimeAction: positionals[1] ?? null,
|
|
195
|
+
taskAction: null,
|
|
196
|
+
taskArgument: null,
|
|
155
197
|
};
|
|
156
198
|
}
|
|
157
199
|
if (command === 'collab') {
|
|
@@ -165,9 +207,12 @@ function parseOptions(args) {
|
|
|
165
207
|
docsArgument: null,
|
|
166
208
|
codeAction: null,
|
|
167
209
|
hostAction: null,
|
|
210
|
+
hostSubAction: null,
|
|
168
211
|
collaborationAction: positionals[1] ?? null,
|
|
169
212
|
resumeTaskId: null,
|
|
170
213
|
runtimeAction: null,
|
|
214
|
+
taskAction: null,
|
|
215
|
+
taskArgument: null,
|
|
171
216
|
};
|
|
172
217
|
}
|
|
173
218
|
if (positionals.length > 1) {
|
|
@@ -216,6 +261,10 @@ function hasContinuityOptions(values, includeSession = true) {
|
|
|
216
261
|
(includeSession && values.session !== undefined));
|
|
217
262
|
}
|
|
218
263
|
const globalUsage = 'pappra [--help | --version] [--json]\n' +
|
|
264
|
+
'pappra task <pin|unpin|show> [taskId] [--auto-resume] [--json]\n' +
|
|
265
|
+
'pappra mcp [--root <dir>] [--help]\n' +
|
|
266
|
+
'pappra onboard [--root <dir>] [--config <file>] [--hosts <list>] [--yes]\n' +
|
|
267
|
+
' [--apply-host] [--dry-run] [--print-handoff] [--json]\n' +
|
|
219
268
|
'pappra init [--config <file> | --yes] [--apply] [--json] [--print-choices]\n' +
|
|
220
269
|
' [--install-runtime (--runtime-tarball <file> | --runtime-version <version>)]\n' +
|
|
221
270
|
'pappra doctor [--root <path>] [--json]\n' +
|
|
@@ -236,16 +285,31 @@ export async function runCli(args, output) {
|
|
|
236
285
|
failure(output, jsonRequested, 'invalid_arguments', error);
|
|
237
286
|
return 2;
|
|
238
287
|
}
|
|
239
|
-
const { values, command, docsAction, docsArgument, codeAction, hostAction, collaborationAction, resumeTaskId, runtimeAction, } = parsed;
|
|
288
|
+
const { values, command, docsAction, docsArgument, codeAction, hostAction, collaborationAction, resumeTaskId, runtimeAction, hostSubAction, taskAction, taskArgument, } = parsed;
|
|
240
289
|
const json = values.json === true;
|
|
241
290
|
const applyRequested = values.apply === true;
|
|
242
291
|
if (command !== 'init' &&
|
|
243
|
-
(values
|
|
244
|
-
values['no-interactive'] === true ||
|
|
292
|
+
(values['no-interactive'] === true ||
|
|
245
293
|
values['print-choices'] === true ||
|
|
246
294
|
values['no-runtime'] === true ||
|
|
247
295
|
values.reconfigure === true)) {
|
|
248
|
-
failure(output, json, 'invalid_arguments', '--
|
|
296
|
+
failure(output, json, 'invalid_arguments', '--no-interactive, --print-choices, --no-runtime and --reconfigure are only valid for init.');
|
|
297
|
+
return 2;
|
|
298
|
+
}
|
|
299
|
+
if (command !== 'init' && command !== 'onboard' && values.yes === true) {
|
|
300
|
+
failure(output, json, 'invalid_arguments', '--yes is only valid for init and onboard.');
|
|
301
|
+
return 2;
|
|
302
|
+
}
|
|
303
|
+
if (command !== 'task' && values['auto-resume'] === true) {
|
|
304
|
+
failure(output, json, 'invalid_arguments', '--auto-resume is only valid for task pin.');
|
|
305
|
+
return 2;
|
|
306
|
+
}
|
|
307
|
+
if (command !== 'onboard' &&
|
|
308
|
+
(values.hosts !== undefined ||
|
|
309
|
+
values['apply-host'] === true ||
|
|
310
|
+
values['dry-run'] === true ||
|
|
311
|
+
values['print-handoff'] === true)) {
|
|
312
|
+
failure(output, json, 'invalid_arguments', '--hosts, --apply-host, --dry-run and --print-handoff are only valid for onboard.');
|
|
249
313
|
return 2;
|
|
250
314
|
}
|
|
251
315
|
if (command !== 'host' && values.out !== undefined) {
|
|
@@ -279,6 +343,7 @@ export async function runCli(args, output) {
|
|
|
279
343
|
return 2;
|
|
280
344
|
}
|
|
281
345
|
if (command !== 'runtime' &&
|
|
346
|
+
command !== 'host' &&
|
|
282
347
|
(values.from !== undefined ||
|
|
283
348
|
values.tarball !== undefined ||
|
|
284
349
|
values.bind === true ||
|
|
@@ -398,6 +463,136 @@ export async function runCli(args, output) {
|
|
|
398
463
|
json,
|
|
399
464
|
}, output);
|
|
400
465
|
}
|
|
466
|
+
if (command === 'task') {
|
|
467
|
+
const action = taskAction === 'pin' || taskAction === 'unpin' || taskAction === 'show'
|
|
468
|
+
? taskAction
|
|
469
|
+
: null;
|
|
470
|
+
if (values.config !== undefined ||
|
|
471
|
+
values.apply === true ||
|
|
472
|
+
values.yes === true ||
|
|
473
|
+
values['install-runtime'] === true ||
|
|
474
|
+
values['runtime-tarball'] !== undefined ||
|
|
475
|
+
values['runtime-version'] !== undefined ||
|
|
476
|
+
values.host !== undefined ||
|
|
477
|
+
values.repo !== undefined ||
|
|
478
|
+
values.kind !== undefined ||
|
|
479
|
+
values.query !== undefined ||
|
|
480
|
+
values.root !== undefined ||
|
|
481
|
+
hasContinuityOptions(values)) {
|
|
482
|
+
failure(output, json, 'invalid_arguments', 'task accepts pin|unpin|show, an optional task id, --auto-resume, --help, and --json.');
|
|
483
|
+
return 2;
|
|
484
|
+
}
|
|
485
|
+
if (values.help) {
|
|
486
|
+
if (json) {
|
|
487
|
+
output.stdout(`${JSON.stringify({ ...info, commands: ['task'], usage: taskUsage })}\n`);
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
output.stdout(taskUsage);
|
|
491
|
+
}
|
|
492
|
+
return 0;
|
|
493
|
+
}
|
|
494
|
+
if (values.version) {
|
|
495
|
+
failure(output, json, 'invalid_arguments', '--version cannot be combined with task.');
|
|
496
|
+
return 2;
|
|
497
|
+
}
|
|
498
|
+
return runTaskCommand({
|
|
499
|
+
cwd: process.cwd(),
|
|
500
|
+
action,
|
|
501
|
+
taskId: taskArgument ?? null,
|
|
502
|
+
autoResume: values['auto-resume'] === true,
|
|
503
|
+
json,
|
|
504
|
+
}, output);
|
|
505
|
+
}
|
|
506
|
+
if (command === 'mcp') {
|
|
507
|
+
if (values.config !== undefined ||
|
|
508
|
+
values.apply === true ||
|
|
509
|
+
values.yes === true ||
|
|
510
|
+
values['install-runtime'] === true ||
|
|
511
|
+
values['runtime-tarball'] !== undefined ||
|
|
512
|
+
values['runtime-version'] !== undefined ||
|
|
513
|
+
values['include-private'] === true ||
|
|
514
|
+
values['include-archived'] === true ||
|
|
515
|
+
values['apply-host'] === true ||
|
|
516
|
+
values['dry-run'] === true ||
|
|
517
|
+
values['print-handoff'] === true ||
|
|
518
|
+
values.hosts !== undefined ||
|
|
519
|
+
values.repo !== undefined ||
|
|
520
|
+
values.kind !== undefined ||
|
|
521
|
+
values.query !== undefined ||
|
|
522
|
+
values.limit !== undefined ||
|
|
523
|
+
values['max-bytes'] !== undefined ||
|
|
524
|
+
values.rebuild === true ||
|
|
525
|
+
values.host !== undefined ||
|
|
526
|
+
hasContinuityOptions(values)) {
|
|
527
|
+
failure(output, json, 'invalid_arguments', 'mcp accepts only --root, --help, and --json.');
|
|
528
|
+
return 2;
|
|
529
|
+
}
|
|
530
|
+
if (values.help) {
|
|
531
|
+
if (json) {
|
|
532
|
+
output.stdout(`${JSON.stringify({ ...info, commands: ['mcp'], usage: mcpUsage })}\n`);
|
|
533
|
+
}
|
|
534
|
+
else {
|
|
535
|
+
output.stdout(mcpUsage);
|
|
536
|
+
}
|
|
537
|
+
return 0;
|
|
538
|
+
}
|
|
539
|
+
if (values.version) {
|
|
540
|
+
failure(output, json, 'invalid_arguments', '--version cannot be combined with mcp.');
|
|
541
|
+
return 2;
|
|
542
|
+
}
|
|
543
|
+
return runMcpCommand({ cwd: process.cwd(), root: values.root ?? null, json }, output);
|
|
544
|
+
}
|
|
545
|
+
if (command === 'onboard') {
|
|
546
|
+
if (values.apply === true ||
|
|
547
|
+
values['install-runtime'] === true ||
|
|
548
|
+
values['runtime-tarball'] !== undefined ||
|
|
549
|
+
values['runtime-version'] !== undefined ||
|
|
550
|
+
values['host-root'] !== undefined ||
|
|
551
|
+
values['host-version'] !== undefined ||
|
|
552
|
+
values.mode !== undefined ||
|
|
553
|
+
values.from !== undefined ||
|
|
554
|
+
values.tarball !== undefined ||
|
|
555
|
+
values.bind === true ||
|
|
556
|
+
values.force === true ||
|
|
557
|
+
values.marketplace === true ||
|
|
558
|
+
values.scope !== undefined ||
|
|
559
|
+
values.repo !== undefined ||
|
|
560
|
+
values.kind !== undefined ||
|
|
561
|
+
values.query !== undefined ||
|
|
562
|
+
values.limit !== undefined ||
|
|
563
|
+
values['max-bytes'] !== undefined ||
|
|
564
|
+
values.rebuild === true ||
|
|
565
|
+
values['include-private'] === true ||
|
|
566
|
+
values['include-archived'] === true ||
|
|
567
|
+
hasContinuityOptions(values)) {
|
|
568
|
+
failure(output, json, 'invalid_arguments', 'onboard accepts --root, --config, --hosts, --yes, --apply-host, --dry-run, --print-handoff, --help, and --json.');
|
|
569
|
+
return 2;
|
|
570
|
+
}
|
|
571
|
+
if (values.help) {
|
|
572
|
+
if (json) {
|
|
573
|
+
output.stdout(`${JSON.stringify({ ...info, commands: ['onboard'], usage: onboardUsage })}\n`);
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
output.stdout(onboardUsage);
|
|
577
|
+
}
|
|
578
|
+
return 0;
|
|
579
|
+
}
|
|
580
|
+
if (values.version) {
|
|
581
|
+
failure(output, json, 'invalid_arguments', '--version cannot be combined with onboard.');
|
|
582
|
+
return 2;
|
|
583
|
+
}
|
|
584
|
+
return runOnboardCommand({
|
|
585
|
+
cwd: process.cwd(),
|
|
586
|
+
root: values.root ?? null,
|
|
587
|
+
configPath: values.config ?? null,
|
|
588
|
+
hosts: values.hosts ?? null,
|
|
589
|
+
apply: values.yes === true,
|
|
590
|
+
applyHosts: values['apply-host'] === true,
|
|
591
|
+
dryRun: values['dry-run'] === true,
|
|
592
|
+
printHandoff: values['print-handoff'] === true,
|
|
593
|
+
json,
|
|
594
|
+
}, output);
|
|
595
|
+
}
|
|
401
596
|
if (command === 'init') {
|
|
402
597
|
if (values.root !== undefined ||
|
|
403
598
|
values['include-private'] === true ||
|
|
@@ -654,6 +849,8 @@ export async function runCli(args, output) {
|
|
|
654
849
|
'install',
|
|
655
850
|
'verify',
|
|
656
851
|
'bundle',
|
|
852
|
+
'mcp',
|
|
853
|
+
'probe',
|
|
657
854
|
];
|
|
658
855
|
const action = allowedActions.find((item) => item === hostAction) ?? null;
|
|
659
856
|
const parsedHost = hostNameSchema.safeParse(values.host);
|
|
@@ -673,7 +870,7 @@ export async function runCli(args, output) {
|
|
|
673
870
|
values['max-bytes'] !== undefined ||
|
|
674
871
|
values.rebuild === true ||
|
|
675
872
|
hasContinuityOptions(values) ||
|
|
676
|
-
(values.apply === true && action !== 'install') ||
|
|
873
|
+
(values.apply === true && action !== 'install' && action !== 'mcp') ||
|
|
677
874
|
(values.mode !== undefined && action !== 'install') ||
|
|
678
875
|
(values.marketplace === true && action !== 'bundle') ||
|
|
679
876
|
(values.scope !== undefined &&
|
|
@@ -703,6 +900,8 @@ export async function runCli(args, output) {
|
|
|
703
900
|
hostRoot: values['host-root'] ?? null,
|
|
704
901
|
hostVersion: values['host-version'] ?? null,
|
|
705
902
|
apply: values.apply === true,
|
|
903
|
+
force: values.force === true,
|
|
904
|
+
subAction: hostSubAction ?? null,
|
|
706
905
|
out: values.out ?? null,
|
|
707
906
|
mode: values.mode === 'project-settings' || values.mode === 'plugin'
|
|
708
907
|
? values.mode
|
|
@@ -10,6 +10,7 @@ import { resolveWorkspaceRoot } from '../../workspace/resolve.js';
|
|
|
10
10
|
import { inspectMachineConfig, loadWorkspaceConfig, } from '../../workspace/config.js';
|
|
11
11
|
import { CheckpointService } from '../../continuity/service.js';
|
|
12
12
|
import { ensureStatePathBoundary } from '../../install/ownership.js';
|
|
13
|
+
import { readAutoResume, readTaskPin } from '../../app/task-pin.js';
|
|
13
14
|
import { nativeEventFor } from './support.js';
|
|
14
15
|
const DEFAULT_MAX_INPUT_BYTES = 1024 * 1024;
|
|
15
16
|
const DEFAULT_DEADLINE_MS = 1000;
|
|
@@ -489,7 +490,9 @@ export async function runHostHook(input, options = {}) {
|
|
|
489
490
|
dev: directoryAfter.stats.dev,
|
|
490
491
|
ino: directoryAfter.stats.ino,
|
|
491
492
|
};
|
|
492
|
-
const
|
|
493
|
+
const pinnedTask = await readTaskPin(root);
|
|
494
|
+
const autoResume = pinnedTask !== null && (await readAutoResume(root));
|
|
495
|
+
const context = await boundedAdvisory(root, value.event, value.taskId ?? (autoResume ? pinnedTask.taskId : null), workspaceRead.value.name);
|
|
493
496
|
if (clock() - started > deadline) {
|
|
494
497
|
return result({
|
|
495
498
|
ok: false,
|
|
@@ -6,8 +6,8 @@ var __export = (target, all) => {
|
|
|
6
6
|
|
|
7
7
|
// dist/hosts/integration/hook.js
|
|
8
8
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
9
|
-
import { link as link2, mkdir as
|
|
10
|
-
import { isAbsolute as isAbsolute4, join as
|
|
9
|
+
import { link as link2, mkdir as mkdir4, open as open5, rm as rm2 } from "node:fs/promises";
|
|
10
|
+
import { isAbsolute as isAbsolute4, join as join9, relative as relative3, resolve as resolve6, sep as sep3 } from "node:path";
|
|
11
11
|
|
|
12
12
|
// dist/schemas/diagnostics.js
|
|
13
13
|
function createDiagnostic(input2) {
|
|
@@ -20662,6 +20662,9 @@ var workspaceValidationSchema = external_exports.strictObject({
|
|
|
20662
20662
|
executable: executableSchema,
|
|
20663
20663
|
args: external_exports.array(argumentSchema).max(256)
|
|
20664
20664
|
});
|
|
20665
|
+
var workspaceContinuitySchema = external_exports.strictObject({
|
|
20666
|
+
autoResume: external_exports.boolean()
|
|
20667
|
+
});
|
|
20665
20668
|
var workspaceConfigSchema = external_exports.strictObject({
|
|
20666
20669
|
schema: external_exports.literal(WORKSPACE_SCHEMA),
|
|
20667
20670
|
workspaceId: external_exports.uuid(),
|
|
@@ -20672,7 +20675,8 @@ var workspaceConfigSchema = external_exports.strictObject({
|
|
|
20672
20675
|
code: workspaceCodeSchema,
|
|
20673
20676
|
validation: external_exports.array(workspaceValidationSchema).max(128),
|
|
20674
20677
|
excludes: external_exports.array(portablePathSchema).max(128),
|
|
20675
|
-
extensions: external_exports.record(external_exports.string().min(1).max(128), external_exports.unknown())
|
|
20678
|
+
extensions: external_exports.record(external_exports.string().min(1).max(128), external_exports.unknown()),
|
|
20679
|
+
continuity: workspaceContinuitySchema.optional()
|
|
20676
20680
|
});
|
|
20677
20681
|
function pathDiagnostic(value, source, fieldPointer, label) {
|
|
20678
20682
|
const hint = 'Use a workspace-relative path such as "docs" or "repos/app".';
|
|
@@ -23928,6 +23932,42 @@ async function ensureStatePathBoundary(root, path) {
|
|
|
23928
23932
|
}
|
|
23929
23933
|
}
|
|
23930
23934
|
|
|
23935
|
+
// dist/app/task-pin.js
|
|
23936
|
+
import { mkdir as mkdir3, readFile, rename as rename2, writeFile } from "node:fs/promises";
|
|
23937
|
+
import { dirname as dirname5, join as join8 } from "node:path";
|
|
23938
|
+
var TASK_PIN_SCHEMA = "pappra/task-pin/1";
|
|
23939
|
+
var TASK_ID2 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
23940
|
+
function pinPath(root) {
|
|
23941
|
+
return join8(root, ".pappra", "local", "current-task");
|
|
23942
|
+
}
|
|
23943
|
+
async function readTaskPin(root) {
|
|
23944
|
+
const read = await readTextFileBounded(pinPath(root), 64 * 1024);
|
|
23945
|
+
if (!read.ok)
|
|
23946
|
+
return null;
|
|
23947
|
+
try {
|
|
23948
|
+
const value = JSON.parse(read.value.text);
|
|
23949
|
+
if (typeof value !== "object" || value === null || !("schema" in value) || value.schema !== TASK_PIN_SCHEMA || !("taskId" in value) || typeof value.taskId !== "string" || !TASK_ID2.test(value.taskId)) {
|
|
23950
|
+
return null;
|
|
23951
|
+
}
|
|
23952
|
+
return value;
|
|
23953
|
+
} catch {
|
|
23954
|
+
return null;
|
|
23955
|
+
}
|
|
23956
|
+
}
|
|
23957
|
+
async function readAutoResume(root) {
|
|
23958
|
+
const read = await readFile(join8(root, ".pappra", "workspace.json"), "utf8");
|
|
23959
|
+
try {
|
|
23960
|
+
const raw = JSON.parse(read);
|
|
23961
|
+
if (typeof raw !== "object" || raw === null || !("continuity" in raw)) {
|
|
23962
|
+
return false;
|
|
23963
|
+
}
|
|
23964
|
+
const continuity = raw.continuity;
|
|
23965
|
+
return typeof continuity === "object" && continuity !== null && "autoResume" in continuity && continuity.autoResume === true;
|
|
23966
|
+
} catch {
|
|
23967
|
+
return false;
|
|
23968
|
+
}
|
|
23969
|
+
}
|
|
23970
|
+
|
|
23931
23971
|
// dist/hosts/integration/support.js
|
|
23932
23972
|
var HOST_SUPPORT = {
|
|
23933
23973
|
pi: {
|
|
@@ -24015,7 +24055,7 @@ async function privateSegmentsSafe(root, directory) {
|
|
|
24015
24055
|
}
|
|
24016
24056
|
let current = root;
|
|
24017
24057
|
for (const segment of rel.split(sep3)) {
|
|
24018
|
-
current =
|
|
24058
|
+
current = join9(current, segment);
|
|
24019
24059
|
const observed = await observePath(current);
|
|
24020
24060
|
if (observed.kind === "missing")
|
|
24021
24061
|
return true;
|
|
@@ -24256,7 +24296,7 @@ async function runHostHook(input2, options = {}) {
|
|
|
24256
24296
|
});
|
|
24257
24297
|
}
|
|
24258
24298
|
const eventKey = value.eventId === null ? null : sha256Digest([value.host, value.event, value.sessionId ?? "", value.eventId].join("\0"));
|
|
24259
|
-
const directory =
|
|
24299
|
+
const directory = join9(root, ".pappra", "local", "host-events", value.host);
|
|
24260
24300
|
if (!await privateSegmentsSafe(root, directory)) {
|
|
24261
24301
|
return result2({
|
|
24262
24302
|
ok: false,
|
|
@@ -24301,7 +24341,7 @@ async function runHostHook(input2, options = {}) {
|
|
|
24301
24341
|
]
|
|
24302
24342
|
});
|
|
24303
24343
|
}
|
|
24304
|
-
await
|
|
24344
|
+
await mkdir4(directory, { recursive: true, mode: 448 });
|
|
24305
24345
|
const directoryAfter = await observePath(directory);
|
|
24306
24346
|
const realDirectory = await resolveRealpath(directory);
|
|
24307
24347
|
const privateAfter = await privateSegmentsSafe(root, directory);
|
|
@@ -24326,7 +24366,9 @@ async function runHostHook(input2, options = {}) {
|
|
|
24326
24366
|
dev: directoryAfter.stats.dev,
|
|
24327
24367
|
ino: directoryAfter.stats.ino
|
|
24328
24368
|
};
|
|
24329
|
-
const
|
|
24369
|
+
const pinnedTask = await readTaskPin(root);
|
|
24370
|
+
const autoResume = pinnedTask !== null && await readAutoResume(root);
|
|
24371
|
+
const context = await boundedAdvisory(root, value.event, value.taskId ?? (autoResume ? pinnedTask.taskId : null), workspaceRead.value.name);
|
|
24330
24372
|
if (clock() - started > deadline) {
|
|
24331
24373
|
return result2({
|
|
24332
24374
|
ok: false,
|
|
@@ -24342,7 +24384,7 @@ async function runHostHook(input2, options = {}) {
|
|
|
24342
24384
|
});
|
|
24343
24385
|
}
|
|
24344
24386
|
const fileName = eventKey === null ? `${sha256Digest(`${value.observedAt}\0${randomUUID3()}`).slice(7)}.json` : `${eventKey.slice(7)}.json`;
|
|
24345
|
-
const path =
|
|
24387
|
+
const path = join9(directory, fileName);
|
|
24346
24388
|
const record2 = Buffer.from(`${JSON.stringify({
|
|
24347
24389
|
schema: "pappra/host-event/1",
|
|
24348
24390
|
host: value.host,
|
|
@@ -6,8 +6,8 @@ var __export = (target, all) => {
|
|
|
6
6
|
|
|
7
7
|
// dist/hosts/integration/hook.js
|
|
8
8
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
9
|
-
import { link as link2, mkdir as
|
|
10
|
-
import { isAbsolute as isAbsolute4, join as
|
|
9
|
+
import { link as link2, mkdir as mkdir4, open as open5, rm as rm2 } from "node:fs/promises";
|
|
10
|
+
import { isAbsolute as isAbsolute4, join as join9, relative as relative3, resolve as resolve6, sep as sep3 } from "node:path";
|
|
11
11
|
|
|
12
12
|
// dist/schemas/diagnostics.js
|
|
13
13
|
function createDiagnostic(input2) {
|
|
@@ -20667,6 +20667,9 @@ var workspaceValidationSchema = external_exports.strictObject({
|
|
|
20667
20667
|
executable: executableSchema,
|
|
20668
20668
|
args: external_exports.array(argumentSchema).max(256)
|
|
20669
20669
|
});
|
|
20670
|
+
var workspaceContinuitySchema = external_exports.strictObject({
|
|
20671
|
+
autoResume: external_exports.boolean()
|
|
20672
|
+
});
|
|
20670
20673
|
var workspaceConfigSchema = external_exports.strictObject({
|
|
20671
20674
|
schema: external_exports.literal(WORKSPACE_SCHEMA),
|
|
20672
20675
|
workspaceId: external_exports.uuid(),
|
|
@@ -20677,7 +20680,8 @@ var workspaceConfigSchema = external_exports.strictObject({
|
|
|
20677
20680
|
code: workspaceCodeSchema,
|
|
20678
20681
|
validation: external_exports.array(workspaceValidationSchema).max(128),
|
|
20679
20682
|
excludes: external_exports.array(portablePathSchema).max(128),
|
|
20680
|
-
extensions: external_exports.record(external_exports.string().min(1).max(128), external_exports.unknown())
|
|
20683
|
+
extensions: external_exports.record(external_exports.string().min(1).max(128), external_exports.unknown()),
|
|
20684
|
+
continuity: workspaceContinuitySchema.optional()
|
|
20681
20685
|
});
|
|
20682
20686
|
function pathDiagnostic(value, source, fieldPointer, label) {
|
|
20683
20687
|
const hint = 'Use a workspace-relative path such as "docs" or "repos/app".';
|
|
@@ -23933,6 +23937,42 @@ async function ensureStatePathBoundary(root, path) {
|
|
|
23933
23937
|
}
|
|
23934
23938
|
}
|
|
23935
23939
|
|
|
23940
|
+
// dist/app/task-pin.js
|
|
23941
|
+
import { mkdir as mkdir3, readFile, rename as rename2, writeFile } from "node:fs/promises";
|
|
23942
|
+
import { dirname as dirname5, join as join8 } from "node:path";
|
|
23943
|
+
var TASK_PIN_SCHEMA = "pappra/task-pin/1";
|
|
23944
|
+
var TASK_ID2 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
23945
|
+
function pinPath(root) {
|
|
23946
|
+
return join8(root, ".pappra", "local", "current-task");
|
|
23947
|
+
}
|
|
23948
|
+
async function readTaskPin(root) {
|
|
23949
|
+
const read = await readTextFileBounded(pinPath(root), 64 * 1024);
|
|
23950
|
+
if (!read.ok)
|
|
23951
|
+
return null;
|
|
23952
|
+
try {
|
|
23953
|
+
const value = JSON.parse(read.value.text);
|
|
23954
|
+
if (typeof value !== "object" || value === null || !("schema" in value) || value.schema !== TASK_PIN_SCHEMA || !("taskId" in value) || typeof value.taskId !== "string" || !TASK_ID2.test(value.taskId)) {
|
|
23955
|
+
return null;
|
|
23956
|
+
}
|
|
23957
|
+
return value;
|
|
23958
|
+
} catch {
|
|
23959
|
+
return null;
|
|
23960
|
+
}
|
|
23961
|
+
}
|
|
23962
|
+
async function readAutoResume(root) {
|
|
23963
|
+
const read = await readFile(join8(root, ".pappra", "workspace.json"), "utf8");
|
|
23964
|
+
try {
|
|
23965
|
+
const raw = JSON.parse(read);
|
|
23966
|
+
if (typeof raw !== "object" || raw === null || !("continuity" in raw)) {
|
|
23967
|
+
return false;
|
|
23968
|
+
}
|
|
23969
|
+
const continuity = raw.continuity;
|
|
23970
|
+
return typeof continuity === "object" && continuity !== null && "autoResume" in continuity && continuity.autoResume === true;
|
|
23971
|
+
} catch {
|
|
23972
|
+
return false;
|
|
23973
|
+
}
|
|
23974
|
+
}
|
|
23975
|
+
|
|
23936
23976
|
// dist/hosts/integration/support.js
|
|
23937
23977
|
var HOST_SUPPORT = {
|
|
23938
23978
|
pi: {
|
|
@@ -24038,7 +24078,7 @@ async function privateSegmentsSafe(root, directory) {
|
|
|
24038
24078
|
}
|
|
24039
24079
|
let current = root;
|
|
24040
24080
|
for (const segment of rel.split(sep3)) {
|
|
24041
|
-
current =
|
|
24081
|
+
current = join9(current, segment);
|
|
24042
24082
|
const observed = await observePath(current);
|
|
24043
24083
|
if (observed.kind === "missing")
|
|
24044
24084
|
return true;
|
|
@@ -24337,7 +24377,7 @@ async function runHostHook(input2, options = {}) {
|
|
|
24337
24377
|
});
|
|
24338
24378
|
}
|
|
24339
24379
|
const eventKey = value.eventId === null ? null : sha256Digest([value.host, value.event, value.sessionId ?? "", value.eventId].join("\0"));
|
|
24340
|
-
const directory =
|
|
24380
|
+
const directory = join9(root, ".pappra", "local", "host-events", value.host);
|
|
24341
24381
|
if (!await privateSegmentsSafe(root, directory)) {
|
|
24342
24382
|
return result2({
|
|
24343
24383
|
ok: false,
|
|
@@ -24382,7 +24422,7 @@ async function runHostHook(input2, options = {}) {
|
|
|
24382
24422
|
]
|
|
24383
24423
|
});
|
|
24384
24424
|
}
|
|
24385
|
-
await
|
|
24425
|
+
await mkdir4(directory, { recursive: true, mode: 448 });
|
|
24386
24426
|
const directoryAfter = await observePath(directory);
|
|
24387
24427
|
const realDirectory = await resolveRealpath(directory);
|
|
24388
24428
|
const privateAfter = await privateSegmentsSafe(root, directory);
|
|
@@ -24407,7 +24447,9 @@ async function runHostHook(input2, options = {}) {
|
|
|
24407
24447
|
dev: directoryAfter.stats.dev,
|
|
24408
24448
|
ino: directoryAfter.stats.ino
|
|
24409
24449
|
};
|
|
24410
|
-
const
|
|
24450
|
+
const pinnedTask = await readTaskPin(root);
|
|
24451
|
+
const autoResume = pinnedTask !== null && await readAutoResume(root);
|
|
24452
|
+
const context = await boundedAdvisory(root, value.event, value.taskId ?? (autoResume ? pinnedTask.taskId : null), workspaceRead.value.name);
|
|
24411
24453
|
if (clock() - started > deadline) {
|
|
24412
24454
|
return result2({
|
|
24413
24455
|
ok: false,
|
|
@@ -24423,7 +24465,7 @@ async function runHostHook(input2, options = {}) {
|
|
|
24423
24465
|
});
|
|
24424
24466
|
}
|
|
24425
24467
|
const fileName = eventKey === null ? `${sha256Digest(`${value.observedAt}\0${randomUUID3()}`).slice(7)}.json` : `${eventKey.slice(7)}.json`;
|
|
24426
|
-
const path =
|
|
24468
|
+
const path = join9(directory, fileName);
|
|
24427
24469
|
const record2 = Buffer.from(`${JSON.stringify({
|
|
24428
24470
|
schema: "pappra/host-event/1",
|
|
24429
24471
|
host: value.host,
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Diagnostic } from '../schemas/diagnostics.js';
|
|
2
|
+
import type { DocumentKind } from '../schemas/document.js';
|
|
3
|
+
export interface DocumentScanCandidate {
|
|
4
|
+
readonly path: string;
|
|
5
|
+
readonly kind: DocumentKind;
|
|
6
|
+
readonly visibility: 'private' | 'shareable';
|
|
7
|
+
}
|
|
8
|
+
export interface DocumentScanResult {
|
|
9
|
+
readonly ok: boolean;
|
|
10
|
+
readonly schema: 'pappra/docs-scan/1';
|
|
11
|
+
readonly mode: 'plan' | 'apply';
|
|
12
|
+
readonly workspaceRoot: string;
|
|
13
|
+
readonly candidates: readonly DocumentScanCandidate[];
|
|
14
|
+
readonly registered: readonly unknown[];
|
|
15
|
+
readonly skipped: number;
|
|
16
|
+
readonly nextActions: readonly string[];
|
|
17
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
18
|
+
}
|
|
19
|
+
export type DocumentScanFailure = {
|
|
20
|
+
readonly ok: false;
|
|
21
|
+
readonly message: string;
|
|
22
|
+
} | DocumentScanResult;
|
|
23
|
+
export declare function classifyScannedDocumentKind(path: string): DocumentKind;
|
|
24
|
+
/**
|
|
25
|
+
* Registers documents discovered under the configured knowledge sources.
|
|
26
|
+
* Without apply this is read-only and reports the candidates.
|
|
27
|
+
*/
|
|
28
|
+
export declare function scanDiscoveredDocuments(root: string, options: {
|
|
29
|
+
readonly apply: boolean;
|
|
30
|
+
}): Promise<DocumentScanFailure>;
|